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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/dist/components/TyButton.d.ts +52 -0
  4. package/dist/components/TyButton.d.ts.map +1 -0
  5. package/dist/components/TyButton.js +76 -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 +128 -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 +76 -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 +46 -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 +122 -0
  30. package/dist/components/TyDatePicker.js.map +1 -0
  31. package/dist/components/TyDropdown.d.ts +62 -0
  32. package/dist/components/TyDropdown.d.ts.map +1 -0
  33. package/dist/components/TyDropdown.js +124 -0
  34. package/dist/components/TyDropdown.js.map +1 -0
  35. package/dist/components/TyFileUpload.d.ts +31 -0
  36. package/dist/components/TyFileUpload.d.ts.map +1 -0
  37. package/dist/components/TyFileUpload.js +56 -0
  38. package/dist/components/TyFileUpload.js.map +1 -0
  39. package/dist/components/TyIcon.d.ts +17 -0
  40. package/dist/components/TyIcon.d.ts.map +1 -0
  41. package/dist/components/TyIcon.js +42 -0
  42. package/dist/components/TyIcon.js.map +1 -0
  43. package/dist/components/TyInput.d.ts +65 -0
  44. package/dist/components/TyInput.d.ts.map +1 -0
  45. package/dist/components/TyInput.js +134 -0
  46. package/dist/components/TyInput.js.map +1 -0
  47. package/dist/components/TyModal.d.ts +48 -0
  48. package/dist/components/TyModal.d.ts.map +1 -0
  49. package/dist/components/TyModal.js +120 -0
  50. package/dist/components/TyModal.js.map +1 -0
  51. package/dist/components/TyMultiselect.d.ts +57 -0
  52. package/dist/components/TyMultiselect.d.ts.map +1 -0
  53. package/dist/components/TyMultiselect.js +111 -0
  54. package/dist/components/TyMultiselect.js.map +1 -0
  55. package/dist/components/TyOption.d.ts +10 -0
  56. package/dist/components/TyOption.d.ts.map +1 -0
  57. package/dist/components/TyOption.js +29 -0
  58. package/dist/components/TyOption.js.map +1 -0
  59. package/dist/components/TyPopup.d.ts +24 -0
  60. package/dist/components/TyPopup.d.ts.map +1 -0
  61. package/dist/components/TyPopup.js +70 -0
  62. package/dist/components/TyPopup.js.map +1 -0
  63. package/dist/components/TyRadio.d.ts +20 -0
  64. package/dist/components/TyRadio.d.ts.map +1 -0
  65. package/dist/components/TyRadio.js +35 -0
  66. package/dist/components/TyRadio.js.map +1 -0
  67. package/dist/components/TyRadioGroup.d.ts +40 -0
  68. package/dist/components/TyRadioGroup.d.ts.map +1 -0
  69. package/dist/components/TyRadioGroup.js +61 -0
  70. package/dist/components/TyRadioGroup.js.map +1 -0
  71. package/dist/components/TyResizeObserver.d.ts +11 -0
  72. package/dist/components/TyResizeObserver.d.ts.map +1 -0
  73. package/dist/components/TyResizeObserver.js +28 -0
  74. package/dist/components/TyResizeObserver.js.map +1 -0
  75. package/dist/components/TyScrollContainer.d.ts +25 -0
  76. package/dist/components/TyScrollContainer.d.ts.map +1 -0
  77. package/dist/components/TyScrollContainer.js +61 -0
  78. package/dist/components/TyScrollContainer.js.map +1 -0
  79. package/dist/components/TyStep.d.ts +17 -0
  80. package/dist/components/TyStep.d.ts.map +1 -0
  81. package/dist/components/TyStep.js +35 -0
  82. package/dist/components/TyStep.js.map +1 -0
  83. package/dist/components/TySwitch.d.ts +35 -0
  84. package/dist/components/TySwitch.d.ts.map +1 -0
  85. package/dist/components/TySwitch.js +59 -0
  86. package/dist/components/TySwitch.js.map +1 -0
  87. package/dist/components/TyTab.d.ts +13 -0
  88. package/dist/components/TyTab.d.ts.map +1 -0
  89. package/dist/components/TyTab.js +34 -0
  90. package/dist/components/TyTab.js.map +1 -0
  91. package/dist/components/TyTabs.d.ts +23 -0
  92. package/dist/components/TyTabs.d.ts.map +1 -0
  93. package/dist/components/TyTabs.js +48 -0
  94. package/dist/components/TyTabs.js.map +1 -0
  95. package/dist/components/TyTag.d.ts +22 -0
  96. package/dist/components/TyTag.d.ts.map +1 -0
  97. package/dist/components/TyTag.js +51 -0
  98. package/dist/components/TyTag.js.map +1 -0
  99. package/dist/components/TyTextarea.d.ts +37 -0
  100. package/dist/components/TyTextarea.d.ts.map +1 -0
  101. package/dist/components/TyTextarea.js +116 -0
  102. package/dist/components/TyTextarea.js.map +1 -0
  103. package/dist/components/TyTooltip.d.ts +17 -0
  104. package/dist/components/TyTooltip.d.ts.map +1 -0
  105. package/dist/components/TyTooltip.js +41 -0
  106. package/dist/components/TyTooltip.js.map +1 -0
  107. package/dist/components/TyWizard.d.ts +26 -0
  108. package/dist/components/TyWizard.d.ts.map +1 -0
  109. package/dist/components/TyWizard.js +50 -0
  110. package/dist/components/TyWizard.js.map +1 -0
  111. package/dist/components/index.d.ts +112 -0
  112. package/dist/components/index.d.ts.map +1 -0
  113. package/dist/components/index.js +127 -0
  114. package/dist/components/index.js.map +1 -0
  115. package/dist/utils/react-version.d.ts +2 -0
  116. package/dist/utils/react-version.d.ts.map +1 -0
  117. package/dist/utils/react-version.js +8 -0
  118. package/dist/utils/react-version.js.map +1 -0
  119. package/dist/utils/use-boolean-prop.d.ts +36 -0
  120. package/dist/utils/use-boolean-prop.d.ts.map +1 -0
  121. package/dist/utils/use-boolean-prop.js +62 -0
  122. package/dist/utils/use-boolean-prop.js.map +1 -0
  123. package/dist/version.d.ts +3 -0
  124. package/dist/version.d.ts.map +1 -0
  125. package/dist/version.js +6 -0
  126. package/dist/version.js.map +1 -0
  127. package/package.json +47 -0
  128. package/src/components/EventConventionTest.tsx +155 -0
  129. package/src/components/TyButton.tsx +157 -0
  130. package/src/components/TyCalendar.tsx +247 -0
  131. package/src/components/TyCalendarMonth.tsx +108 -0
  132. package/src/components/TyCalendarNavigation.tsx +91 -0
  133. package/src/components/TyCheckbox.tsx +147 -0
  134. package/src/components/TyCopy.tsx +83 -0
  135. package/src/components/TyDatePicker.tsx +215 -0
  136. package/src/components/TyDropdown.tsx +240 -0
  137. package/src/components/TyFileUpload.tsx +108 -0
  138. package/src/components/TyIcon.tsx +71 -0
  139. package/src/components/TyInput.tsx +239 -0
  140. package/src/components/TyModal.tsx +195 -0
  141. package/src/components/TyMultiselect.tsx +208 -0
  142. package/src/components/TyOption.tsx +47 -0
  143. package/src/components/TyPopup.tsx +116 -0
  144. package/src/components/TyRadio.tsx +61 -0
  145. package/src/components/TyRadioGroup.tsx +125 -0
  146. package/src/components/TyResizeObserver.tsx +54 -0
  147. package/src/components/TyScrollContainer.tsx +102 -0
  148. package/src/components/TyStep.tsx +71 -0
  149. package/src/components/TySwitch.tsx +114 -0
  150. package/src/components/TyTab.tsx +65 -0
  151. package/src/components/TyTabs.tsx +93 -0
  152. package/src/components/TyTag.tsx +86 -0
  153. package/src/components/TyTextarea.tsx +181 -0
  154. package/src/components/TyTooltip.tsx +83 -0
  155. package/src/components/TyWizard.tsx +99 -0
  156. package/src/components/index.ts +279 -0
  157. package/src/utils/react-version.ts +8 -0
  158. package/src/utils/use-boolean-prop.ts +62 -0
  159. package/src/version.ts +6 -0
@@ -0,0 +1,127 @@
1
+ // ===================================================================
2
+ // VERSION
3
+ // ===================================================================
4
+ import { VERSION } from '../version';
5
+ /** Current version of tyrell-react (auto-synced with package.json on build). */
6
+ export { VERSION };
7
+ // One-time load banner so consumers can confirm which version of
8
+ // tyrell-react their page is actually running. Mirrors the banner in
9
+ // tyrell-components. Filter DevTools with "tyrell-react" if noisy.
10
+ if (typeof window !== 'undefined') {
11
+ window.tyReactVersion = VERSION;
12
+ console.log(`%c[tyrell-react]%c v${VERSION}`, 'color:#a78bfa;font-weight:600', 'color:inherit;font-weight:400');
13
+ }
14
+ // ===================================================================
15
+ // TYRELL REACT WRAPPER EXPORTS
16
+ // ===================================================================
17
+ // This file provides two export styles for maximum developer flexibility:
18
+ // 1. Ty-prefixed exports (TyButton, TyInput) - explicit and backward compatible
19
+ // 2. Short name exports (Button, Input) - clean and familiar to React developers
20
+ //
21
+ // Choose the style that fits your team's preferences!
22
+ // ===================================================================
23
+ // TY-PREFIXED EXPORTS (Explicit Style - Backward Compatible)
24
+ // ===================================================================
25
+ export { TyButton } from './TyButton';
26
+ export { TyTag } from './TyTag';
27
+ export { TyInput } from './TyInput';
28
+ export { TyTextarea } from './TyTextarea';
29
+ export { TyDropdown } from './TyDropdown';
30
+ export { TyOption } from './TyOption';
31
+ export { TyIcon } from './TyIcon';
32
+ export { TyModal } from './TyModal';
33
+ export { TyTooltip } from './TyTooltip';
34
+ export { TyMultiselect } from './TyMultiselect';
35
+ export { TyCalendar } from './TyCalendar';
36
+ export { TyDatePicker } from './TyDatePicker';
37
+ export { TyPopup } from './TyPopup';
38
+ export { TyCheckbox } from './TyCheckbox';
39
+ export { TySwitch } from './TySwitch';
40
+ export { TyRadio } from './TyRadio';
41
+ export { TyRadioGroup } from './TyRadioGroup';
42
+ export { TyCopy } from './TyCopy';
43
+ export { TyFileUpload } from './TyFileUpload';
44
+ export { TyTabs } from './TyTabs';
45
+ export { TyTab } from './TyTab';
46
+ export { TyCalendarMonth } from './TyCalendarMonth';
47
+ export { TyCalendarNavigation } from './TyCalendarNavigation';
48
+ export { TyWizard } from './TyWizard';
49
+ export { TyStep } from './TyStep';
50
+ export { TyResizeObserver } from './TyResizeObserver';
51
+ export { TyScrollContainer } from './TyScrollContainer';
52
+ // ===================================================================
53
+ // SHORT NAME EXPORTS (Clean Style - Developer Choice)
54
+ // ===================================================================
55
+ export { TyButton as Button } from './TyButton';
56
+ export { TyTag as Tag } from './TyTag';
57
+ export { TyInput as Input } from './TyInput';
58
+ export { TyTextarea as Textarea } from './TyTextarea';
59
+ export { TyDropdown as Dropdown } from './TyDropdown';
60
+ export { TyOption as Option } from './TyOption';
61
+ export { TyIcon as Icon } from './TyIcon';
62
+ export { TyModal as Modal } from './TyModal';
63
+ export { TyTooltip as Tooltip } from './TyTooltip';
64
+ export { TyMultiselect as Multiselect } from './TyMultiselect';
65
+ export { TyCalendar as Calendar } from './TyCalendar';
66
+ export { TyDatePicker as DatePicker } from './TyDatePicker';
67
+ export { TyPopup as Popup } from './TyPopup';
68
+ export { TyCheckbox as Checkbox } from './TyCheckbox';
69
+ export { TySwitch as Switch } from './TySwitch';
70
+ export { TyRadio as Radio } from './TyRadio';
71
+ export { TyRadioGroup as RadioGroup } from './TyRadioGroup';
72
+ export { TyCopy as Copy } from './TyCopy';
73
+ export { TyFileUpload as FileUpload } from './TyFileUpload';
74
+ export { TyTabs as Tabs } from './TyTabs';
75
+ export { TyTab as Tab } from './TyTab';
76
+ export { TyCalendarMonth as CalendarMonth } from './TyCalendarMonth';
77
+ export { TyCalendarNavigation as CalendarNavigation } from './TyCalendarNavigation';
78
+ export { TyWizard as Wizard } from './TyWizard';
79
+ export { TyStep as Step } from './TyStep';
80
+ export { TyResizeObserver as ResizeObserver } from './TyResizeObserver';
81
+ export { TyScrollContainer as ScrollContainer } from './TyScrollContainer';
82
+ // ===================================================================
83
+ // USAGE EXAMPLES
84
+ // ===================================================================
85
+ /*
86
+
87
+ // STYLE 1: Ty-prefixed (Explicit and backward compatible)
88
+ import { TyButton, TyInput, TyModal } from 'tyrell-react';
89
+ import type { TyButtonProps, TyInputProps } from 'tyrell-react';
90
+
91
+ function MyComponent() {
92
+ return (
93
+ <TyModal>
94
+ <TyInput placeholder="Enter text..." />
95
+ <TyButton>Submit</TyButton>
96
+ </TyModal>
97
+ );
98
+ }
99
+
100
+ // STYLE 2: Short names (Clean and familiar)
101
+ import { Button, Input, Modal } from 'tyrell-react';
102
+ import type { ButtonProps, InputProps } from 'tyrell-react';
103
+
104
+ function MyComponent() {
105
+ return (
106
+ <Modal>
107
+ <Input placeholder="Enter text..." />
108
+ <Button>Submit</Button>
109
+ </Modal>
110
+ );
111
+ }
112
+
113
+ // STYLE 3: Mixed (Team preferences)
114
+ import { TyModal, Input, Button } from 'tyrell-react';
115
+ import type { TyModalProps, InputProps } from 'tyrell-react';
116
+
117
+ function MyComponent() {
118
+ return (
119
+ <TyModal>
120
+ <Input placeholder="Enter text..." />
121
+ <Button>Submit</Button>
122
+ </TyModal>
123
+ );
124
+ }
125
+
126
+ */
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const needsPropertyBridge: boolean;
2
+ //# sourceMappingURL=react-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-version.d.ts","sourceRoot":"","sources":["../../src/utils/react-version.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,mBAAmB,SAAmC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ // React 19 natively bridges props to custom-element properties (including
3
+ // empty strings, `false` booleans, functions, and objects). On React 18 we
4
+ // must imperatively assign these properties via useEffect. Wrappers gate
5
+ // their bridging effects on this flag so the workaround is dead code on
6
+ // React 19+ and removable when React 18 support is eventually dropped.
7
+ export const needsPropertyBridge = parseInt(React.version, 10) < 19;
8
+ //# sourceMappingURL=react-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-version.js","sourceRoot":"","sources":["../../src/utils/react-version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,0EAA0E;AAC1E,2EAA2E;AAC3E,yEAAyE;AACzE,wEAAwE;AACxE,uEAAuE;AACvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Coerce a value to a boolean using the same rules as the core property
4
+ * manager (packages/core/src/utils/property-manager.ts:142-152). This matters
5
+ * because consumers sometimes pass the string "false" through untyped call
6
+ * sites (JSON config, query params, server-rendered props) — and the JS
7
+ * `Boolean("false")` is surprisingly `true`.
8
+ *
9
+ * undefined | null | false | "false" | "0" → false
10
+ * "" → true (HTML boolean-attribute convention)
11
+ * any other truthy → true
12
+ */
13
+ export declare function coerceBool(value: unknown): boolean;
14
+ /**
15
+ * Imperatively keep a boolean property on the underlying custom element in
16
+ * sync with its React prop.
17
+ *
18
+ * Why this exists: React 18 sets boolean attributes as empty strings on the
19
+ * first render to a custom element but does not reliably *remove* them when
20
+ * the prop flips back to `false`. Without this bridge, `<TyModal open>` →
21
+ * `<TyModal open={false}>` leaves the `open` attribute on the element and
22
+ * the modal stays open. Same class of bug affects `disabled`, `required`,
23
+ * `clearable`, `loading`, `readonly`, `protected`, etc.
24
+ *
25
+ * React 19+ bridges this natively — the effect short-circuits via
26
+ * `needsPropertyBridge`, so this is dead code on modern React.
27
+ *
28
+ * Pass the *camelCase JS property name* on the element (e.g. `externalSearch`
29
+ * for the `external-search` attribute). The core base class handles the
30
+ * attribute-side sync once the property changes.
31
+ *
32
+ * Returns the coerced boolean so the caller can also drive its conditional
33
+ * JSX attribute emission with a value that correctly handles "false".
34
+ */
35
+ export declare function useBooleanProperty(ref: RefObject<HTMLElement | null>, propName: string, value: unknown): boolean;
36
+ //# sourceMappingURL=use-boolean-prop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-boolean-prop.d.ts","sourceRoot":"","sources":["../../src/utils/use-boolean-prop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7C;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASlD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,GACb,OAAO,CAWT"}
@@ -0,0 +1,62 @@
1
+ import { useEffect } from 'react';
2
+ import { needsPropertyBridge } from './react-version';
3
+ /**
4
+ * Coerce a value to a boolean using the same rules as the core property
5
+ * manager (packages/core/src/utils/property-manager.ts:142-152). This matters
6
+ * because consumers sometimes pass the string "false" through untyped call
7
+ * sites (JSON config, query params, server-rendered props) — and the JS
8
+ * `Boolean("false")` is surprisingly `true`.
9
+ *
10
+ * undefined | null | false | "false" | "0" → false
11
+ * "" → true (HTML boolean-attribute convention)
12
+ * any other truthy → true
13
+ */
14
+ export function coerceBool(value) {
15
+ if (value === undefined || value === null || value === false)
16
+ return false;
17
+ if (typeof value === 'string') {
18
+ if (value === '')
19
+ return true;
20
+ const norm = value.toLowerCase().trim();
21
+ if (norm === 'false' || norm === '0')
22
+ return false;
23
+ return true;
24
+ }
25
+ return Boolean(value);
26
+ }
27
+ /**
28
+ * Imperatively keep a boolean property on the underlying custom element in
29
+ * sync with its React prop.
30
+ *
31
+ * Why this exists: React 18 sets boolean attributes as empty strings on the
32
+ * first render to a custom element but does not reliably *remove* them when
33
+ * the prop flips back to `false`. Without this bridge, `<TyModal open>` →
34
+ * `<TyModal open={false}>` leaves the `open` attribute on the element and
35
+ * the modal stays open. Same class of bug affects `disabled`, `required`,
36
+ * `clearable`, `loading`, `readonly`, `protected`, etc.
37
+ *
38
+ * React 19+ bridges this natively — the effect short-circuits via
39
+ * `needsPropertyBridge`, so this is dead code on modern React.
40
+ *
41
+ * Pass the *camelCase JS property name* on the element (e.g. `externalSearch`
42
+ * for the `external-search` attribute). The core base class handles the
43
+ * attribute-side sync once the property changes.
44
+ *
45
+ * Returns the coerced boolean so the caller can also drive its conditional
46
+ * JSX attribute emission with a value that correctly handles "false".
47
+ */
48
+ export function useBooleanProperty(ref, propName, value) {
49
+ const coerced = coerceBool(value);
50
+ useEffect(() => {
51
+ if (!needsPropertyBridge)
52
+ return;
53
+ const el = ref.current;
54
+ if (!el)
55
+ return;
56
+ if (Boolean(el[propName]) !== coerced) {
57
+ el[propName] = coerced;
58
+ }
59
+ }, [coerced, propName, ref]);
60
+ return coerced;
61
+ }
62
+ //# sourceMappingURL=use-boolean-prop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-boolean-prop.js","sourceRoot":"","sources":["../../src/utils/use-boolean-prop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAkC,EAClC,QAAgB,EAChB,KAAc;IAEd,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,mBAAmB;YAAE,OAAO;QACjC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAc,CAAC;QAC9B,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,IAAI,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;YACtC,EAAE,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Current version of tyrell-react. Synced with package.json on build. */
2
+ export declare const VERSION = "1.0.0-RC10";
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAIA,0EAA0E;AAC1E,eAAO,MAAM,OAAO,eAAe,CAAA"}
@@ -0,0 +1,6 @@
1
+ // AUTO-GENERATED FILE - DO NOT EDIT
2
+ // Generated from package.json by scripts/generate-version.js
3
+ // Run 'npm run generate:version' to regenerate.
4
+ /** Current version of tyrell-react. Synced with package.json on build. */
5
+ export const VERSION = '1.0.0-RC10';
6
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,6DAA6D;AAC7D,gDAAgD;AAEhD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,OAAO,GAAG,YAAY,CAAA"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "tyrell-react",
3
+ "version": "1.0.0-RC10",
4
+ "description": "React wrappers for Tyrell Components",
5
+ "type": "module",
6
+ "main": "./dist/components/index.js",
7
+ "types": "./dist/components/index.d.ts",
8
+ "files": [
9
+ "dist/**/*",
10
+ "src/**/*",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "generate:version": "node scripts/generate-version.js",
16
+ "build": "npm run generate:version && tsc",
17
+ "clean": "rm -rf dist",
18
+ "prepublishOnly": "npm run clean && npm run build"
19
+ },
20
+ "peerDependencies": {
21
+ "react": ">=18.0.0",
22
+ "react-dom": ">=18.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/react": "^18.2.66",
26
+ "@types/react-dom": "^18.2.22",
27
+ "typescript": "^5.7.0"
28
+ },
29
+ "keywords": [
30
+ "react",
31
+ "web-components",
32
+ "typescript",
33
+ "ui-components",
34
+ "tyrell",
35
+ "wrapper",
36
+ "clojurescript",
37
+ "reagent",
38
+ "uix"
39
+ ],
40
+ "author": "Gersak <dev@gersak.io>",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/gersak/tyrell.git",
45
+ "directory": "packages/react"
46
+ }
47
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Test Example: React Event Convention
3
+ *
4
+ * This file demonstrates the new event handling convention
5
+ * for tyrell-react components.
6
+ *
7
+ * To test:
8
+ * 1. Create a new React project or use existing
9
+ * 2. npm install tyrell-react
10
+ * 3. Add this component to your app
11
+ * 4. Observe console logs and state updates
12
+ */
13
+
14
+ import React, { useState } from 'react';
15
+ import { TyInput } from './TyInput';
16
+ import { TyTextarea } from './TyTextarea';
17
+ import { TyCheckbox } from './TyCheckbox';
18
+ import type { TyInputEventDetail } from './TyInput';
19
+ import type { TyTextareaEventDetail } from './TyTextarea';
20
+ import type { TyCheckboxEventDetail } from './TyCheckbox';
21
+
22
+ export function EventConventionTest() {
23
+ const [inputValue, setInputValue] = useState('');
24
+ const [textareaValue, setTextareaValue] = useState('');
25
+ const [checked, setChecked] = useState(false);
26
+ const [logs, setLogs] = useState<string[]>([]);
27
+
28
+ const addLog = (message: string) => {
29
+ setLogs(prev => [...prev, `${new Date().toLocaleTimeString()}: ${message}`]);
30
+ };
31
+
32
+ return (
33
+ <div className="p-8 space-y-6 max-w-2xl">
34
+ <h1 className="text-2xl font-bold">React Event Convention Test</h1>
35
+
36
+ {/* Input Test */}
37
+ <div className="space-y-2">
38
+ <h2 className="text-lg font-semibold">TyInput Test</h2>
39
+ <TyInput
40
+ label="Email"
41
+ placeholder="Type to test onChange..."
42
+ value={inputValue}
43
+ onChange={(e: CustomEvent<TyInputEventDetail>) => {
44
+ setInputValue(e.detail.value);
45
+ addLog(`onChange: "${e.detail.value}" (fires on keystroke)`);
46
+ }}
47
+ onChangeCommit={(e: CustomEvent<TyInputEventDetail>) => {
48
+ addLog(`onChangeCommit: "${e.detail.value}" (fires on blur)`);
49
+ }}
50
+ onFocus={() => addLog('onFocus')}
51
+ onBlur={() => addLog('onBlur')}
52
+ />
53
+ <p className="text-sm text-gray-600">
54
+ Current value: <strong>{inputValue}</strong>
55
+ </p>
56
+ </div>
57
+
58
+ {/* Textarea Test */}
59
+ <div className="space-y-2">
60
+ <h2 className="text-lg font-semibold">TyTextarea Test</h2>
61
+ <TyTextarea
62
+ label="Comments"
63
+ placeholder="Type to test onChange..."
64
+ value={textareaValue}
65
+ rows={3}
66
+ onChange={(e: CustomEvent<TyTextareaEventDetail>) => {
67
+ setTextareaValue(e.detail.value);
68
+ addLog(`Textarea onChange: "${e.detail.value}"`);
69
+ }}
70
+ onChangeCommit={(e: CustomEvent<TyTextareaEventDetail>) => {
71
+ addLog(`Textarea onChangeCommit: "${e.detail.value}"`);
72
+ }}
73
+ />
74
+ <p className="text-sm text-gray-600">
75
+ Current value: <strong>{textareaValue}</strong>
76
+ </p>
77
+ </div>
78
+
79
+ {/* Checkbox Test */}
80
+ <div className="space-y-2">
81
+ <h2 className="text-lg font-semibold">TyCheckbox Test</h2>
82
+ <TyCheckbox
83
+ checked={checked}
84
+ onChange={(e: CustomEvent<TyCheckboxEventDetail>) => {
85
+ setChecked(e.detail.checked);
86
+ addLog(`Checkbox onChange: ${e.detail.checked} (fires immediately)`);
87
+ }}
88
+ onChangeCommit={(e: CustomEvent<TyCheckboxEventDetail>) => {
89
+ addLog(`Checkbox onChangeCommit: ${e.detail.checked} (fires on blur)`);
90
+ }}
91
+ >
92
+ Subscribe to newsletter
93
+ </TyCheckbox>
94
+ <p className="text-sm text-gray-600">
95
+ Current state: <strong>{checked ? 'Checked' : 'Unchecked'}</strong>
96
+ </p>
97
+ </div>
98
+
99
+ {/* Event Log */}
100
+ <div className="space-y-2">
101
+ <h2 className="text-lg font-semibold">Event Log</h2>
102
+ <div className="bg-gray-100 p-4 rounded max-h-64 overflow-y-auto font-mono text-xs">
103
+ {logs.length === 0 ? (
104
+ <p className="text-gray-500">No events yet. Start typing or checking boxes!</p>
105
+ ) : (
106
+ logs.map((log, i) => (
107
+ <div key={i} className="text-gray-800">
108
+ {log}
109
+ </div>
110
+ ))
111
+ )}
112
+ </div>
113
+ <button
114
+ onClick={() => setLogs([])}
115
+ className="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300"
116
+ >
117
+ Clear Log
118
+ </button>
119
+ </div>
120
+
121
+ {/* Expected Behavior */}
122
+ <div className="bg-blue-50 p-4 rounded">
123
+ <h3 className="font-semibold mb-2">Expected Behavior:</h3>
124
+ <ul className="list-disc list-inside space-y-1 text-sm">
125
+ <li>
126
+ <strong>onChange</strong> - Fires on every keystroke/state change (React convention)
127
+ </li>
128
+ <li>
129
+ <strong>onChangeCommit</strong> - Fires on blur if value changed (optional)
130
+ </li>
131
+ <li>
132
+ <strong>onFocus</strong> - Fires when element gains focus
133
+ </li>
134
+ <li>
135
+ <strong>onBlur</strong> - Fires when element loses focus
136
+ </li>
137
+ </ul>
138
+ </div>
139
+
140
+ {/* Verification */}
141
+ <div className="bg-green-50 p-4 rounded">
142
+ <h3 className="font-semibold mb-2">Verification Checklist:</h3>
143
+ <ul className="list-disc list-inside space-y-1 text-sm">
144
+ <li>✅ onChange fires on EVERY keystroke (not just on blur)</li>
145
+ <li>✅ State updates in real-time as you type</li>
146
+ <li>✅ onChangeCommit fires ONLY on blur (if value changed)</li>
147
+ <li>✅ Event order: onChange → onBlur → onChangeCommit</li>
148
+ <li>✅ Checkbox onChange fires immediately on click</li>
149
+ </ul>
150
+ </div>
151
+ </div>
152
+ );
153
+ }
154
+
155
+ export default EventConventionTest;
@@ -0,0 +1,157 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { useBooleanProperty } from '../utils/use-boolean-prop';
3
+
4
+ type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
6
+ type ButtonAppearance = 'solid' | 'outlined' | 'ghost';
7
+
8
+ export interface TyButtonCSSProperties extends React.CSSProperties {
9
+ '--ty-button-bg'?: string;
10
+ '--ty-button-bg-hover'?: string;
11
+ '--ty-button-color'?: string;
12
+ '--ty-button-border'?: string;
13
+ }
14
+
15
+ export interface TyButtonProps extends Omit<React.HTMLAttributes<HTMLElement>, 'style'> {
16
+ style?: TyButtonCSSProperties;
17
+ /**
18
+ * Semantic styling variant. Built-in flavors get themed styles; append `+`
19
+ * for a stronger shade or `-` for a softer one (e.g. `"primary+"`,
20
+ * `"danger-"`). Any other string is passed through as-is — theme it via
21
+ * `--ty-button-*` CSS variables.
22
+ */
23
+ flavor?: ShadedFlavor | (string & {});
24
+
25
+ /**
26
+ * Visual appearance:
27
+ * - `"solid"` (default) — saturated brand fill with paired text color
28
+ * - `"outlined"` — transparent background, text === border
29
+ * - `"ghost"` — text only with hover background
30
+ */
31
+ appearance?: ButtonAppearance;
32
+
33
+ /** Button size */
34
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
35
+
36
+ /** Button type for form submission */
37
+ type?: 'button' | 'submit' | 'reset';
38
+
39
+ /** Disable the button */
40
+ disabled?: boolean;
41
+
42
+ /** Loading state — shows a centered spinner, blocks click, preserves width */
43
+ loading?: boolean;
44
+
45
+ /** Pill-shaped button (rounded ends) */
46
+ pill?: boolean;
47
+
48
+ /** Action (icon-only square) */
49
+ action?: boolean;
50
+
51
+ /** Accessible label for screen readers */
52
+ label?: string;
53
+
54
+ /** Form field name for form submission */
55
+ name?: string;
56
+
57
+ /** Form field value for form submission */
58
+ value?: string;
59
+
60
+ /** Full-width button */
61
+ wide?: boolean;
62
+
63
+ /** Button content */
64
+ children?: React.ReactNode;
65
+ }
66
+
67
+ export const TyButton = React.forwardRef<HTMLElement, TyButtonProps>(
68
+ ({
69
+ children,
70
+ type,
71
+ appearance,
72
+ disabled,
73
+ loading,
74
+ pill,
75
+ action,
76
+ wide,
77
+ label,
78
+ name,
79
+ value,
80
+ onClick,
81
+ ...props
82
+ }, ref) => {
83
+ const elementRef = useRef<HTMLElement>(null);
84
+
85
+ // Imperatively attach the click listener so onClick reliably fires for the
86
+ // CustomEvent('click') that <ty-button> re-dispatches on its host (the
87
+ // inner <button> calls stopPropagation, so React's delegated onClick can
88
+ // miss it). Also handles type=submit by dispatching a synthetic submit.
89
+ useEffect(() => {
90
+ const element = elementRef.current;
91
+ if (!element) return;
92
+
93
+ const handler = (event: Event) => {
94
+ if (type === 'submit') {
95
+ const form = element.closest('form');
96
+ if (form) {
97
+ event.preventDefault();
98
+ event.stopPropagation();
99
+ form.dispatchEvent(new Event('submit', {
100
+ bubbles: true,
101
+ cancelable: true,
102
+ }));
103
+ }
104
+ }
105
+ if (onClick) {
106
+ onClick(event as unknown as React.MouseEvent<HTMLElement>);
107
+ }
108
+ };
109
+
110
+ element.addEventListener('click', handler);
111
+ return () => {
112
+ element.removeEventListener('click', handler);
113
+ };
114
+ }, [type, onClick]);
115
+
116
+ useEffect(() => {
117
+ if (ref && elementRef.current) {
118
+ if (typeof ref === 'function') {
119
+ ref(elementRef.current);
120
+ } else {
121
+ ref.current = elementRef.current;
122
+ }
123
+ }
124
+ }, [ref]);
125
+
126
+ const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
127
+ const isLoading = useBooleanProperty(elementRef, 'loading', loading);
128
+ const isPill = useBooleanProperty(elementRef, 'pill', pill);
129
+ const isAction = useBooleanProperty(elementRef, 'action', action);
130
+ const isWide = useBooleanProperty(elementRef, 'wide', wide);
131
+
132
+ const webComponentProps: Record<string, any> = {
133
+ ...props,
134
+ ref: elementRef,
135
+ };
136
+
137
+ if (isDisabled) webComponentProps.disabled = '';
138
+ if (isLoading) webComponentProps.loading = '';
139
+ if (isPill) webComponentProps.pill = '';
140
+ if (isAction) webComponentProps.action = '';
141
+ if (isWide) webComponentProps.wide = '';
142
+
143
+ if (appearance) webComponentProps.appearance = appearance;
144
+ if (type) webComponentProps.type = type;
145
+ if (label) webComponentProps.label = label;
146
+ if (name) webComponentProps.name = name;
147
+ if (value) webComponentProps.value = value;
148
+
149
+ return React.createElement(
150
+ 'ty-button',
151
+ webComponentProps,
152
+ children
153
+ );
154
+ }
155
+ );
156
+
157
+ TyButton.displayName = 'TyButton';