tyrell-react 1.0.0-TC10

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 (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/dist/components/TyButton.d.ts +50 -0
  4. package/dist/components/TyButton.d.ts.map +1 -0
  5. package/dist/components/TyButton.js +68 -0
  6. package/dist/components/TyButton.js.map +1 -0
  7. package/dist/components/TyCalendar.d.ts +63 -0
  8. package/dist/components/TyCalendar.d.ts.map +1 -0
  9. package/dist/components/TyCalendar.js +122 -0
  10. package/dist/components/TyCalendar.js.map +1 -0
  11. package/dist/components/TyCalendarMonth.d.ts +32 -0
  12. package/dist/components/TyCalendarMonth.d.ts.map +1 -0
  13. package/dist/components/TyCalendarMonth.js +54 -0
  14. package/dist/components/TyCalendarMonth.js.map +1 -0
  15. package/dist/components/TyCalendarNavigation.d.ts +21 -0
  16. package/dist/components/TyCalendarNavigation.d.ts.map +1 -0
  17. package/dist/components/TyCalendarNavigation.js +50 -0
  18. package/dist/components/TyCalendarNavigation.js.map +1 -0
  19. package/dist/components/TyCheckbox.d.ts +39 -0
  20. package/dist/components/TyCheckbox.d.ts.map +1 -0
  21. package/dist/components/TyCheckbox.js +79 -0
  22. package/dist/components/TyCheckbox.js.map +1 -0
  23. package/dist/components/TyCopy.d.ts +21 -0
  24. package/dist/components/TyCopy.d.ts.map +1 -0
  25. package/dist/components/TyCopy.js +42 -0
  26. package/dist/components/TyCopy.js.map +1 -0
  27. package/dist/components/TyDatePicker.d.ts +45 -0
  28. package/dist/components/TyDatePicker.d.ts.map +1 -0
  29. package/dist/components/TyDatePicker.js +114 -0
  30. package/dist/components/TyDatePicker.js.map +1 -0
  31. package/dist/components/TyDropdown.d.ts +51 -0
  32. package/dist/components/TyDropdown.d.ts.map +1 -0
  33. package/dist/components/TyDropdown.js +109 -0
  34. package/dist/components/TyDropdown.js.map +1 -0
  35. package/dist/components/TyIcon.d.ts +17 -0
  36. package/dist/components/TyIcon.d.ts.map +1 -0
  37. package/dist/components/TyIcon.js +41 -0
  38. package/dist/components/TyIcon.js.map +1 -0
  39. package/dist/components/TyInput.d.ts +65 -0
  40. package/dist/components/TyInput.d.ts.map +1 -0
  41. package/dist/components/TyInput.js +105 -0
  42. package/dist/components/TyInput.js.map +1 -0
  43. package/dist/components/TyModal.d.ts +29 -0
  44. package/dist/components/TyModal.d.ts.map +1 -0
  45. package/dist/components/TyModal.js +74 -0
  46. package/dist/components/TyModal.js.map +1 -0
  47. package/dist/components/TyMultiselect.d.ts +51 -0
  48. package/dist/components/TyMultiselect.d.ts.map +1 -0
  49. package/dist/components/TyMultiselect.js +103 -0
  50. package/dist/components/TyMultiselect.js.map +1 -0
  51. package/dist/components/TyOption.d.ts +10 -0
  52. package/dist/components/TyOption.d.ts.map +1 -0
  53. package/dist/components/TyOption.js +25 -0
  54. package/dist/components/TyOption.js.map +1 -0
  55. package/dist/components/TyPopup.d.ts +24 -0
  56. package/dist/components/TyPopup.d.ts.map +1 -0
  57. package/dist/components/TyPopup.js +61 -0
  58. package/dist/components/TyPopup.js.map +1 -0
  59. package/dist/components/TyRadio.d.ts +20 -0
  60. package/dist/components/TyRadio.d.ts.map +1 -0
  61. package/dist/components/TyRadio.js +31 -0
  62. package/dist/components/TyRadio.js.map +1 -0
  63. package/dist/components/TyRadioGroup.d.ts +40 -0
  64. package/dist/components/TyRadioGroup.d.ts.map +1 -0
  65. package/dist/components/TyRadioGroup.js +58 -0
  66. package/dist/components/TyRadioGroup.js.map +1 -0
  67. package/dist/components/TyResizeObserver.d.ts +11 -0
  68. package/dist/components/TyResizeObserver.d.ts.map +1 -0
  69. package/dist/components/TyResizeObserver.js +28 -0
  70. package/dist/components/TyResizeObserver.js.map +1 -0
  71. package/dist/components/TyScrollContainer.d.ts +25 -0
  72. package/dist/components/TyScrollContainer.d.ts.map +1 -0
  73. package/dist/components/TyScrollContainer.js +43 -0
  74. package/dist/components/TyScrollContainer.js.map +1 -0
  75. package/dist/components/TyStep.d.ts +17 -0
  76. package/dist/components/TyStep.d.ts.map +1 -0
  77. package/dist/components/TyStep.js +35 -0
  78. package/dist/components/TyStep.js.map +1 -0
  79. package/dist/components/TySwitch.d.ts +35 -0
  80. package/dist/components/TySwitch.d.ts.map +1 -0
  81. package/dist/components/TySwitch.js +54 -0
  82. package/dist/components/TySwitch.js.map +1 -0
  83. package/dist/components/TyTab.d.ts +13 -0
  84. package/dist/components/TyTab.d.ts.map +1 -0
  85. package/dist/components/TyTab.js +32 -0
  86. package/dist/components/TyTab.js.map +1 -0
  87. package/dist/components/TyTabs.d.ts +23 -0
  88. package/dist/components/TyTabs.d.ts.map +1 -0
  89. package/dist/components/TyTabs.js +48 -0
  90. package/dist/components/TyTabs.js.map +1 -0
  91. package/dist/components/TyTag.d.ts +22 -0
  92. package/dist/components/TyTag.d.ts.map +1 -0
  93. package/dist/components/TyTag.js +45 -0
  94. package/dist/components/TyTag.js.map +1 -0
  95. package/dist/components/TyTextarea.d.ts +37 -0
  96. package/dist/components/TyTextarea.d.ts.map +1 -0
  97. package/dist/components/TyTextarea.js +93 -0
  98. package/dist/components/TyTextarea.js.map +1 -0
  99. package/dist/components/TyTooltip.d.ts +17 -0
  100. package/dist/components/TyTooltip.d.ts.map +1 -0
  101. package/dist/components/TyTooltip.js +40 -0
  102. package/dist/components/TyTooltip.js.map +1 -0
  103. package/dist/components/TyWizard.d.ts +26 -0
  104. package/dist/components/TyWizard.d.ts.map +1 -0
  105. package/dist/components/TyWizard.js +50 -0
  106. package/dist/components/TyWizard.js.map +1 -0
  107. package/dist/components/index.d.ts +105 -0
  108. package/dist/components/index.d.ts.map +1 -0
  109. package/dist/components/index.js +112 -0
  110. package/dist/components/index.js.map +1 -0
  111. package/package.json +46 -0
  112. package/src/components/EventConventionTest.tsx +155 -0
  113. package/src/components/TyButton.tsx +145 -0
  114. package/src/components/TyCalendar.tsx +244 -0
  115. package/src/components/TyCalendarMonth.tsx +108 -0
  116. package/src/components/TyCalendarNavigation.tsx +91 -0
  117. package/src/components/TyCheckbox.tsx +149 -0
  118. package/src/components/TyCopy.tsx +78 -0
  119. package/src/components/TyDatePicker.tsx +216 -0
  120. package/src/components/TyDropdown.tsx +218 -0
  121. package/src/components/TyIcon.tsx +72 -0
  122. package/src/components/TyInput.tsx +207 -0
  123. package/src/components/TyModal.tsx +142 -0
  124. package/src/components/TyMultiselect.tsx +200 -0
  125. package/src/components/TyOption.tsx +42 -0
  126. package/src/components/TyPopup.tsx +111 -0
  127. package/src/components/TyRadio.tsx +56 -0
  128. package/src/components/TyRadioGroup.tsx +121 -0
  129. package/src/components/TyResizeObserver.tsx +54 -0
  130. package/src/components/TyScrollContainer.tsx +87 -0
  131. package/src/components/TyStep.tsx +71 -0
  132. package/src/components/TySwitch.tsx +108 -0
  133. package/src/components/TyTab.tsx +63 -0
  134. package/src/components/TyTabs.tsx +93 -0
  135. package/src/components/TyTag.tsx +79 -0
  136. package/src/components/TyTextarea.tsx +154 -0
  137. package/src/components/TyTooltip.tsx +83 -0
  138. package/src/components/TyWizard.tsx +99 -0
  139. package/src/components/index.ts +251 -0
@@ -0,0 +1,54 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ // Type definitions for Ty ResizeObserver component
4
+ export interface TyResizeObserverProps extends React.HTMLAttributes<HTMLElement> {
5
+ /** Required unique identifier for size registry */
6
+ id: string;
7
+
8
+ /** Debounce in milliseconds (default: 0 = no debounce) */
9
+ debounce?: number;
10
+
11
+ /** Content to observe */
12
+ children?: React.ReactNode;
13
+ }
14
+
15
+ // React wrapper for ty-resize-observer web component
16
+ export const TyResizeObserver = React.forwardRef<HTMLElement, TyResizeObserverProps>(
17
+ ({
18
+ children,
19
+ id,
20
+ debounce,
21
+ ...props
22
+ }, ref) => {
23
+ const elementRef = useRef<HTMLElement>(null);
24
+
25
+ // Combine refs if needed
26
+ useEffect(() => {
27
+ if (ref && elementRef.current) {
28
+ if (typeof ref === 'function') {
29
+ ref(elementRef.current);
30
+ } else {
31
+ ref.current = elementRef.current;
32
+ }
33
+ }
34
+ }, [ref]);
35
+
36
+ // Convert React props to web component attributes
37
+ const webComponentProps: Record<string, any> = {
38
+ ...props,
39
+ ref: elementRef,
40
+ id,
41
+ };
42
+
43
+ // Add number attributes
44
+ if (debounce !== undefined) webComponentProps.debounce = debounce;
45
+
46
+ return React.createElement(
47
+ 'ty-resize-observer',
48
+ webComponentProps,
49
+ children
50
+ );
51
+ }
52
+ );
53
+
54
+ TyResizeObserver.displayName = 'TyResizeObserver';
@@ -0,0 +1,87 @@
1
+ import React, { useEffect, useRef, useImperativeHandle } from 'react';
2
+
3
+ // Type definitions for Ty ScrollContainer component
4
+ export interface TyScrollContainerProps extends React.HTMLAttributes<HTMLElement> {
5
+ /** Maximum height of the scroll container */
6
+ maxHeight?: string;
7
+
8
+ /** Enable/disable scroll shadows (default: true) */
9
+ shadow?: boolean;
10
+
11
+ /** Hide native scrollbar */
12
+ hideScrollbar?: boolean;
13
+
14
+ /** Content to scroll */
15
+ children?: React.ReactNode;
16
+ }
17
+
18
+ // Ref interface for imperative methods
19
+ export interface TyScrollContainerRef {
20
+ /** Force update shadows (useful after dynamic content changes) */
21
+ updateShadows: () => void;
22
+ /** Scroll to top */
23
+ scrollToTop: (smooth?: boolean) => void;
24
+ /** Scroll to bottom */
25
+ scrollToBottom: (smooth?: boolean) => void;
26
+ /** Get the underlying scroll element */
27
+ scrollElement: HTMLElement | null;
28
+ /** Get the native element */
29
+ element: HTMLElement | null;
30
+ }
31
+
32
+ // React wrapper for ty-scroll-container web component
33
+ export const TyScrollContainer = React.forwardRef<TyScrollContainerRef, TyScrollContainerProps>(
34
+ ({
35
+ children,
36
+ maxHeight,
37
+ shadow,
38
+ hideScrollbar,
39
+ ...props
40
+ }, ref) => {
41
+ const elementRef = useRef<HTMLElement>(null);
42
+
43
+ // Expose imperative methods via ref
44
+ useImperativeHandle(ref, () => ({
45
+ updateShadows: () => {
46
+ const el = elementRef.current as any;
47
+ el?.updateShadows?.();
48
+ },
49
+ scrollToTop: (smooth = true) => {
50
+ const el = elementRef.current as any;
51
+ el?.scrollToTop?.(smooth);
52
+ },
53
+ scrollToBottom: (smooth = true) => {
54
+ const el = elementRef.current as any;
55
+ el?.scrollToBottom?.(smooth);
56
+ },
57
+ get scrollElement() {
58
+ const el = elementRef.current as any;
59
+ return el?.scrollElement ?? null;
60
+ },
61
+ get element() {
62
+ return elementRef.current;
63
+ }
64
+ }), []);
65
+
66
+ // Convert React props to web component attributes
67
+ const webComponentProps: Record<string, any> = {
68
+ ...props,
69
+ ref: elementRef,
70
+ };
71
+
72
+ // Add string attributes
73
+ if (maxHeight) webComponentProps['max-height'] = maxHeight;
74
+
75
+ // Add boolean attributes
76
+ if (shadow === false) webComponentProps.shadow = 'false';
77
+ if (hideScrollbar) webComponentProps['hide-scrollbar'] = true;
78
+
79
+ return React.createElement(
80
+ 'ty-scroll-container',
81
+ webComponentProps,
82
+ children
83
+ );
84
+ }
85
+ );
86
+
87
+ TyScrollContainer.displayName = 'TyScrollContainer';
@@ -0,0 +1,71 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ // Type definitions for Ty Step component
4
+ export interface TyStepProps extends React.HTMLAttributes<HTMLElement> {
5
+ /** Required unique identifier for the step */
6
+ id: string;
7
+
8
+ /** Main step title displayed in indicator */
9
+ label?: string;
10
+
11
+ /** Optional subtitle/description */
12
+ description?: string;
13
+
14
+ /** Whether the step is disabled */
15
+ disabled?: boolean;
16
+
17
+ /** User-controlled status override */
18
+ status?: 'completed' | 'active' | 'pending' | 'error';
19
+
20
+ /** Step content */
21
+ children?: React.ReactNode;
22
+ }
23
+
24
+ // React wrapper for ty-step web component
25
+ export const TyStep = React.forwardRef<HTMLElement, TyStepProps>(
26
+ ({
27
+ children,
28
+ id,
29
+ label,
30
+ description,
31
+ disabled,
32
+ status,
33
+ ...props
34
+ }, ref) => {
35
+ const elementRef = useRef<HTMLElement>(null);
36
+
37
+ // Combine refs if needed
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
+ id,
53
+ };
54
+
55
+ // Add string attributes
56
+ if (label) webComponentProps.label = label;
57
+ if (description) webComponentProps.description = description;
58
+ if (status) webComponentProps.status = status;
59
+
60
+ // Add boolean attributes
61
+ if (disabled) webComponentProps.disabled = true;
62
+
63
+ return React.createElement(
64
+ 'ty-step',
65
+ webComponentProps,
66
+ children
67
+ );
68
+ }
69
+ );
70
+
71
+ TyStep.displayName = 'TyStep';
@@ -0,0 +1,108 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ export interface TySwitchProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
4
+ /** Checked (on) state */
5
+ checked?: boolean;
6
+
7
+ /** Form field value when checked */
8
+ value?: string;
9
+
10
+ /** Form field name */
11
+ name?: string;
12
+
13
+ /** Disable the switch */
14
+ disabled?: boolean;
15
+
16
+ /** Required field */
17
+ required?: boolean;
18
+
19
+ /** Switch size */
20
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
21
+
22
+ /** Semantic styling variant */
23
+ flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
24
+
25
+ /**
26
+ * Fires when switch state changes (React convention)
27
+ * Maps to native 'input' event from ty-switch
28
+ */
29
+ onChange?: (event: CustomEvent<TySwitchEventDetail>) => void;
30
+
31
+ /**
32
+ * Fires on blur if value changed (native DOM behavior)
33
+ * Maps to native 'change' event from ty-switch
34
+ */
35
+ onChangeCommit?: (event: CustomEvent<TySwitchEventDetail>) => void;
36
+ }
37
+
38
+ export interface TySwitchEventDetail {
39
+ value: boolean;
40
+ checked: boolean;
41
+ formValue: string | null;
42
+ originalEvent: Event;
43
+ }
44
+
45
+ export const TySwitch = React.forwardRef<HTMLElement, TySwitchProps>(
46
+ ({
47
+ checked,
48
+ value,
49
+ name,
50
+ disabled,
51
+ required,
52
+ size,
53
+ flavor,
54
+ onChange,
55
+ onChangeCommit,
56
+ ...props
57
+ }, ref) => {
58
+ const elementRef = useRef<HTMLElement>(null);
59
+
60
+ useEffect(() => {
61
+ const element = elementRef.current;
62
+ if (!element) return;
63
+
64
+ const handleInput = (event: Event) => {
65
+ if (onChange) onChange(event as CustomEvent<TySwitchEventDetail>);
66
+ };
67
+ const handleChangeCommit = (event: Event) => {
68
+ if (onChangeCommit) onChangeCommit(event as CustomEvent<TySwitchEventDetail>);
69
+ };
70
+
71
+ element.addEventListener('input', handleInput);
72
+ element.addEventListener('change', handleChangeCommit);
73
+
74
+ return () => {
75
+ element.removeEventListener('input', handleInput);
76
+ element.removeEventListener('change', handleChangeCommit);
77
+ };
78
+ }, [onChange, onChangeCommit]);
79
+
80
+ useEffect(() => {
81
+ if (ref && elementRef.current) {
82
+ if (typeof ref === 'function') {
83
+ ref(elementRef.current);
84
+ } else {
85
+ ref.current = elementRef.current;
86
+ }
87
+ }
88
+ }, [ref]);
89
+
90
+ const webComponentProps: Record<string, any> = {
91
+ ...props,
92
+ ref: elementRef,
93
+ };
94
+
95
+ if (checked) webComponentProps.checked = '';
96
+ if (disabled) webComponentProps.disabled = '';
97
+ if (required) webComponentProps.required = '';
98
+
99
+ if (value) webComponentProps.value = value;
100
+ if (name) webComponentProps.name = name;
101
+ if (size) webComponentProps.size = size;
102
+ if (flavor) webComponentProps.flavor = flavor;
103
+
104
+ return React.createElement('ty-switch', webComponentProps);
105
+ }
106
+ );
107
+
108
+ TySwitch.displayName = 'TySwitch';
@@ -0,0 +1,63 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ // Type definitions for Ty Tab component
4
+ export interface TyTabProps extends React.HTMLAttributes<HTMLElement> {
5
+ /** Required unique identifier */
6
+ id: string;
7
+
8
+ /** Simple text label */
9
+ label?: string;
10
+
11
+ /** Whether the tab is disabled */
12
+ disabled?: boolean;
13
+
14
+ /** Tab content */
15
+ children?: React.ReactNode;
16
+ }
17
+
18
+ // React wrapper for ty-tab web component
19
+ export const TyTab = React.forwardRef<HTMLElement, TyTabProps>(
20
+ ({
21
+ children,
22
+ id,
23
+ label,
24
+ disabled,
25
+ ...props
26
+ }, ref) => {
27
+ const elementRef = useRef<HTMLElement>(null);
28
+
29
+ // Combine refs if needed
30
+ useEffect(() => {
31
+ if (ref && elementRef.current) {
32
+ if (typeof ref === 'function') {
33
+ ref(elementRef.current);
34
+ } else {
35
+ ref.current = elementRef.current;
36
+ }
37
+ }
38
+ }, [ref]);
39
+
40
+ // Convert React props to web component attributes
41
+ const webComponentProps: Record<string, any> = {
42
+ ...props,
43
+ ref: elementRef,
44
+ };
45
+
46
+ // Add required attribute
47
+ webComponentProps.id = id;
48
+
49
+ // Add boolean attributes
50
+ if (disabled) webComponentProps.disabled = '';
51
+
52
+ // Add string attributes
53
+ if (label) webComponentProps.label = label;
54
+
55
+ return React.createElement(
56
+ 'ty-tab',
57
+ webComponentProps,
58
+ children
59
+ );
60
+ }
61
+ );
62
+
63
+ TyTab.displayName = 'TyTab';
@@ -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';