tyrell-react 1.0.0-TC10 → 1.0.0-TC12

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 (59) hide show
  1. package/dist/components/TyButton.d.ts +2 -0
  2. package/dist/components/TyButton.d.ts.map +1 -1
  3. package/dist/components/TyButton.js +3 -1
  4. package/dist/components/TyButton.js.map +1 -1
  5. package/dist/components/TyCalendar.d.ts.map +1 -1
  6. package/dist/components/TyCalendar.js +6 -1
  7. package/dist/components/TyCalendar.js.map +1 -1
  8. package/dist/components/TyCheckbox.d.ts.map +1 -1
  9. package/dist/components/TyCheckbox.js +4 -0
  10. package/dist/components/TyCheckbox.js.map +1 -1
  11. package/dist/components/TyDatePicker.d.ts.map +1 -1
  12. package/dist/components/TyDatePicker.js +6 -1
  13. package/dist/components/TyDatePicker.js.map +1 -1
  14. package/dist/components/TyDropdown.d.ts +16 -5
  15. package/dist/components/TyDropdown.d.ts.map +1 -1
  16. package/dist/components/TyDropdown.js +11 -8
  17. package/dist/components/TyDropdown.js.map +1 -1
  18. package/dist/components/TyFileUpload.d.ts +31 -0
  19. package/dist/components/TyFileUpload.d.ts.map +1 -0
  20. package/dist/components/TyFileUpload.js +52 -0
  21. package/dist/components/TyFileUpload.js.map +1 -0
  22. package/dist/components/TyInput.d.ts.map +1 -1
  23. package/dist/components/TyInput.js +23 -1
  24. package/dist/components/TyInput.js.map +1 -1
  25. package/dist/components/TyMultiselect.d.ts +6 -0
  26. package/dist/components/TyMultiselect.d.ts.map +1 -1
  27. package/dist/components/TyMultiselect.js +7 -1
  28. package/dist/components/TyMultiselect.js.map +1 -1
  29. package/dist/components/TyRadio.d.ts.map +1 -1
  30. package/dist/components/TyRadio.js +15 -0
  31. package/dist/components/TyRadio.js.map +1 -1
  32. package/dist/components/TySwitch.d.ts.map +1 -1
  33. package/dist/components/TySwitch.js +15 -0
  34. package/dist/components/TySwitch.js.map +1 -1
  35. package/dist/components/TyTextarea.d.ts.map +1 -1
  36. package/dist/components/TyTextarea.js +20 -0
  37. package/dist/components/TyTextarea.js.map +1 -1
  38. package/dist/components/index.d.ts +4 -0
  39. package/dist/components/index.d.ts.map +1 -1
  40. package/dist/components/index.js +2 -0
  41. package/dist/components/index.js.map +1 -1
  42. package/dist/utils/react-version.d.ts +2 -0
  43. package/dist/utils/react-version.d.ts.map +1 -0
  44. package/dist/utils/react-version.js +8 -0
  45. package/dist/utils/react-version.js.map +1 -0
  46. package/package.json +1 -1
  47. package/src/components/TyButton.tsx +6 -1
  48. package/src/components/TyCalendar.tsx +5 -1
  49. package/src/components/TyCheckbox.tsx +3 -0
  50. package/src/components/TyDatePicker.tsx +5 -1
  51. package/src/components/TyDropdown.tsx +35 -19
  52. package/src/components/TyFileUpload.tsx +103 -0
  53. package/src/components/TyInput.tsx +26 -1
  54. package/src/components/TyMultiselect.tsx +13 -1
  55. package/src/components/TyRadio.tsx +14 -0
  56. package/src/components/TySwitch.tsx +14 -0
  57. package/src/components/TyTextarea.tsx +23 -0
  58. package/src/components/index.ts +7 -0
  59. package/src/utils/react-version.ts +8 -0
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { needsPropertyBridge } from '../utils/react-version';
2
3
 
3
4
  export interface TySwitchProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
4
5
  /** Checked (on) state */
@@ -87,6 +88,19 @@ export const TySwitch = React.forwardRef<HTMLElement, TySwitchProps>(
87
88
  }
88
89
  }, [ref]);
89
90
 
91
+ // Imperatively sync `checked` to the underlying property. React 18 sets
92
+ // boolean attributes as empty strings on first render but doesn't reliably
93
+ // remove them when the prop flips back to false on a custom element.
94
+ // React 19+ handles boolean prop-to-property bridging natively.
95
+ useEffect(() => {
96
+ if (!needsPropertyBridge) return;
97
+ const element = elementRef.current as any;
98
+ if (!element) return;
99
+ if (Boolean(element.checked) !== Boolean(checked)) {
100
+ element.checked = Boolean(checked);
101
+ }
102
+ }, [checked]);
103
+
90
104
  const webComponentProps: Record<string, any> = {
91
105
  ...props,
92
106
  ref: elementRef,
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useRef, useCallback } from 'react';
2
+ import { needsPropertyBridge } from '../utils/react-version';
2
3
 
3
4
  // Event detail structure for ty-textarea events
4
5
  export interface TyTextareaEventDetail {
@@ -45,11 +46,30 @@ export interface TyTextareaProps extends Omit<React.HTMLAttributes<HTMLElement>,
45
46
  onBlur?: (event: FocusEvent) => void;
46
47
  }
47
48
 
49
+ // One-time warning flag.
50
+ let _warnedOnInputProp = false;
51
+
48
52
  // React wrapper for ty-textarea web component
49
53
  export const TyTextarea = React.forwardRef<HTMLElement, TyTextareaProps>(
50
54
  ({ onChange, onChangeCommit, onFocus, onBlur, disabled, required, minHeight, maxHeight, ...props }, ref) => {
51
55
  const elementRef = useRef<HTMLElement>(null);
52
56
 
57
+ // Same `onInput` → `onChange` redirect as TyInput. React's synthetic-event
58
+ // system strips event.detail; users hitting e.detail.value will crash.
59
+ const onInputProp = (props as any).onInput as ((e: any) => void) | undefined;
60
+ if (onInputProp && !onChange) {
61
+ if (!_warnedOnInputProp) {
62
+ _warnedOnInputProp = true;
63
+ console.warn(
64
+ '[tyrell-react] <TyTextarea> received `onInput`. ' +
65
+ 'React strips event.detail; use `onChange` instead — it receives the raw CustomEvent. ' +
66
+ 'Forwarding for now, but please rename the prop.'
67
+ );
68
+ }
69
+ onChange = onInputProp;
70
+ }
71
+ delete (props as any).onInput;
72
+
53
73
  // Map onChange to input event (React convention)
54
74
  const handleInput = useCallback((event: CustomEvent<TyTextareaEventDetail>) => {
55
75
  if (onChange) {
@@ -128,7 +148,10 @@ export const TyTextarea = React.forwardRef<HTMLElement, TyTextareaProps>(
128
148
  }, [ref]);
129
149
 
130
150
  // Imperatively sync `value` to the underlying element's property.
151
+ // React 18 workaround: prop-to-property bridging is unreliable for empty
152
+ // strings on custom elements. React 19+ handles this natively.
131
153
  useEffect(() => {
154
+ if (!needsPropertyBridge) return;
132
155
  const element = elementRef.current as any;
133
156
  if (!element) return;
134
157
  const next = (props as any).value ?? '';
@@ -65,6 +65,9 @@ export type { TyRadioGroupProps, TyRadioGroupEventDetail } from './TyRadioGroup'
65
65
  export { TyCopy } from './TyCopy';
66
66
  export type { TyCopyProps } from './TyCopy';
67
67
 
68
+ export { TyFileUpload } from './TyFileUpload';
69
+ export type { TyFileUploadProps, TyFileUploadEventDetail } from './TyFileUpload';
70
+
68
71
  export { TyTabs } from './TyTabs';
69
72
  export type { TyTabsProps, TabChangeDetail } from './TyTabs';
70
73
 
@@ -112,6 +115,7 @@ export { TySwitch as Switch } from './TySwitch';
112
115
  export { TyRadio as Radio } from './TyRadio';
113
116
  export { TyRadioGroup as RadioGroup } from './TyRadioGroup';
114
117
  export { TyCopy as Copy } from './TyCopy';
118
+ export { TyFileUpload as FileUpload } from './TyFileUpload';
115
119
  export { TyTabs as Tabs } from './TyTabs';
116
120
  export { TyTab as Tab } from './TyTab';
117
121
  export { TyCalendarMonth as CalendarMonth } from './TyCalendarMonth';
@@ -179,6 +183,9 @@ export type { TyRadioGroupProps as RadioGroupProps, TyRadioGroupEventDetail as R
179
183
  // Copy types
180
184
  export type { TyCopyProps as CopyProps } from './TyCopy';
181
185
 
186
+ // FileUpload types
187
+ export type { TyFileUploadProps as FileUploadProps, TyFileUploadEventDetail as FileUploadEventDetail } from './TyFileUpload';
188
+
182
189
  // Tabs types
183
190
  export type { TyTabsProps as TabsProps } from './TyTabs';
184
191
 
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+
3
+ // React 19 natively bridges props to custom-element properties (including
4
+ // empty strings, `false` booleans, functions, and objects). On React 18 we
5
+ // must imperatively assign these properties via useEffect. Wrappers gate
6
+ // their bridging effects on this flag so the workaround is dead code on
7
+ // React 19+ and removable when React 18 support is eventually dropped.
8
+ export const needsPropertyBridge = parseInt(React.version, 10) < 19;