react-native-mantine 0.6.0 → 0.8.0

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 (225) hide show
  1. package/README.md +38 -6
  2. package/lib/commonjs/components/Anchor/index.js +6 -1
  3. package/lib/commonjs/components/Anchor/index.js.map +1 -1
  4. package/lib/commonjs/components/Badge/index.js +12 -13
  5. package/lib/commonjs/components/Badge/index.js.map +1 -1
  6. package/lib/commonjs/components/Blockquote/index.js +8 -12
  7. package/lib/commonjs/components/Blockquote/index.js.map +1 -1
  8. package/lib/commonjs/components/Button/index.js +5 -6
  9. package/lib/commonjs/components/Button/index.js.map +1 -1
  10. package/lib/commonjs/components/Chip/index.js +8 -9
  11. package/lib/commonjs/components/Chip/index.js.map +1 -1
  12. package/lib/commonjs/components/Code/index.js +13 -8
  13. package/lib/commonjs/components/Code/index.js.map +1 -1
  14. package/lib/commonjs/components/Group/index.js.map +1 -1
  15. package/lib/commonjs/components/Kbd/index.js +7 -8
  16. package/lib/commonjs/components/Kbd/index.js.map +1 -1
  17. package/lib/commonjs/components/List/index.js +6 -5
  18. package/lib/commonjs/components/List/index.js.map +1 -1
  19. package/lib/commonjs/components/Mark/index.js +4 -0
  20. package/lib/commonjs/components/Mark/index.js.map +1 -1
  21. package/lib/commonjs/components/Menu/index.js +12 -15
  22. package/lib/commonjs/components/Menu/index.js.map +1 -1
  23. package/lib/commonjs/components/NavLink/index.js +7 -11
  24. package/lib/commonjs/components/NavLink/index.js.map +1 -1
  25. package/lib/commonjs/components/Notification/index.js +5 -15
  26. package/lib/commonjs/components/Notification/index.js.map +1 -1
  27. package/lib/commonjs/components/Radio/index.js +62 -6
  28. package/lib/commonjs/components/Radio/index.js.map +1 -1
  29. package/lib/commonjs/components/Table/Table.example.js +131 -0
  30. package/lib/commonjs/components/Table/Table.example.js.map +1 -0
  31. package/lib/commonjs/components/Table/index.js +69 -15
  32. package/lib/commonjs/components/Table/index.js.map +1 -1
  33. package/lib/commonjs/components/Title/index.js +4 -0
  34. package/lib/commonjs/components/Title/index.js.map +1 -1
  35. package/lib/commonjs/hooks/index.js +28 -0
  36. package/lib/commonjs/hooks/index.js.map +1 -0
  37. package/lib/commonjs/hooks/use-form/index.js +40 -0
  38. package/lib/commonjs/hooks/use-form/index.js.map +1 -0
  39. package/lib/commonjs/hooks/use-form/types.js +2 -0
  40. package/lib/commonjs/hooks/use-form/types.js.map +1 -0
  41. package/lib/commonjs/hooks/use-form/useForm.js +418 -0
  42. package/lib/commonjs/hooks/use-form/useForm.js.map +1 -0
  43. package/lib/commonjs/hooks/use-form/validators.js +135 -0
  44. package/lib/commonjs/hooks/use-form/validators.js.map +1 -0
  45. package/lib/commonjs/index.js +11 -0
  46. package/lib/commonjs/index.js.map +1 -1
  47. package/lib/commonjs/theme/utils/index.js +26 -0
  48. package/lib/commonjs/theme/utils/index.js.map +1 -0
  49. package/lib/commonjs/theme/utils/withTextWrapper.js +49 -0
  50. package/lib/commonjs/theme/utils/withTextWrapper.js.map +1 -0
  51. package/lib/module/components/Anchor/index.js +6 -1
  52. package/lib/module/components/Anchor/index.js.map +1 -1
  53. package/lib/module/components/Badge/index.js +5 -6
  54. package/lib/module/components/Badge/index.js.map +1 -1
  55. package/lib/module/components/Blockquote/index.js +6 -10
  56. package/lib/module/components/Blockquote/index.js.map +1 -1
  57. package/lib/module/components/Button/index.js +5 -6
  58. package/lib/module/components/Button/index.js.map +1 -1
  59. package/lib/module/components/Chip/index.js +5 -6
  60. package/lib/module/components/Chip/index.js.map +1 -1
  61. package/lib/module/components/Code/index.js +13 -8
  62. package/lib/module/components/Code/index.js.map +1 -1
  63. package/lib/module/components/Group/index.js.map +1 -1
  64. package/lib/module/components/Kbd/index.js +5 -6
  65. package/lib/module/components/Kbd/index.js.map +1 -1
  66. package/lib/module/components/List/index.js +6 -5
  67. package/lib/module/components/List/index.js.map +1 -1
  68. package/lib/module/components/Mark/index.js +4 -0
  69. package/lib/module/components/Mark/index.js.map +1 -1
  70. package/lib/module/components/Menu/index.js +7 -10
  71. package/lib/module/components/Menu/index.js.map +1 -1
  72. package/lib/module/components/NavLink/index.js +5 -9
  73. package/lib/module/components/NavLink/index.js.map +1 -1
  74. package/lib/module/components/Notification/index.js +5 -15
  75. package/lib/module/components/Notification/index.js.map +1 -1
  76. package/lib/module/components/Radio/index.js +64 -8
  77. package/lib/module/components/Radio/index.js.map +1 -1
  78. package/lib/module/components/Table/Table.example.js +128 -0
  79. package/lib/module/components/Table/Table.example.js.map +1 -0
  80. package/lib/module/components/Table/index.js +70 -16
  81. package/lib/module/components/Table/index.js.map +1 -1
  82. package/lib/module/components/Title/index.js +4 -0
  83. package/lib/module/components/Title/index.js.map +1 -1
  84. package/lib/module/hooks/index.js +5 -0
  85. package/lib/module/hooks/index.js.map +1 -0
  86. package/lib/module/hooks/use-form/index.js +6 -0
  87. package/lib/module/hooks/use-form/index.js.map +1 -0
  88. package/lib/module/hooks/use-form/types.js +2 -0
  89. package/lib/module/hooks/use-form/types.js.map +1 -0
  90. package/lib/module/hooks/use-form/useForm.js +414 -0
  91. package/lib/module/hooks/use-form/useForm.js.map +1 -0
  92. package/lib/module/hooks/use-form/validators.js +122 -0
  93. package/lib/module/hooks/use-form/validators.js.map +1 -0
  94. package/lib/module/index.js +1 -0
  95. package/lib/module/index.js.map +1 -1
  96. package/lib/module/theme/utils/index.js +5 -0
  97. package/lib/module/theme/utils/index.js.map +1 -0
  98. package/lib/module/theme/utils/withTextWrapper.js +45 -0
  99. package/lib/module/theme/utils/withTextWrapper.js.map +1 -0
  100. package/lib/typescript/commonjs/src/components/Anchor/index.d.ts +2 -1
  101. package/lib/typescript/commonjs/src/components/Anchor/index.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/src/components/Badge/index.d.ts +2 -1
  103. package/lib/typescript/commonjs/src/components/Badge/index.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/src/components/Blockquote/index.d.ts +2 -1
  105. package/lib/typescript/commonjs/src/components/Blockquote/index.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/src/components/Button/index.d.ts +2 -2
  107. package/lib/typescript/commonjs/src/components/Button/index.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/src/components/Chip/index.d.ts +2 -1
  109. package/lib/typescript/commonjs/src/components/Chip/index.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/src/components/Code/index.d.ts +2 -1
  111. package/lib/typescript/commonjs/src/components/Code/index.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/src/components/Group/index.d.ts +1 -0
  113. package/lib/typescript/commonjs/src/components/Group/index.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/src/components/Kbd/index.d.ts +2 -1
  115. package/lib/typescript/commonjs/src/components/Kbd/index.d.ts.map +1 -1
  116. package/lib/typescript/commonjs/src/components/List/index.d.ts +2 -1
  117. package/lib/typescript/commonjs/src/components/List/index.d.ts.map +1 -1
  118. package/lib/typescript/commonjs/src/components/Mark/index.d.ts +2 -1
  119. package/lib/typescript/commonjs/src/components/Mark/index.d.ts.map +1 -1
  120. package/lib/typescript/commonjs/src/components/Menu/index.d.ts +3 -2
  121. package/lib/typescript/commonjs/src/components/Menu/index.d.ts.map +1 -1
  122. package/lib/typescript/commonjs/src/components/NavLink/index.d.ts +2 -1
  123. package/lib/typescript/commonjs/src/components/NavLink/index.d.ts.map +1 -1
  124. package/lib/typescript/commonjs/src/components/Notification/index.d.ts +2 -1
  125. package/lib/typescript/commonjs/src/components/Notification/index.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/src/components/Radio/index.d.ts +22 -1
  127. package/lib/typescript/commonjs/src/components/Radio/index.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/src/components/Table/Table.example.d.ts +3 -0
  129. package/lib/typescript/commonjs/src/components/Table/Table.example.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/src/components/Table/index.d.ts +7 -2
  131. package/lib/typescript/commonjs/src/components/Table/index.d.ts.map +1 -1
  132. package/lib/typescript/commonjs/src/components/Title/index.d.ts +2 -1
  133. package/lib/typescript/commonjs/src/components/Title/index.d.ts.map +1 -1
  134. package/lib/typescript/commonjs/src/hooks/index.d.ts +3 -0
  135. package/lib/typescript/commonjs/src/hooks/index.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/src/hooks/use-form/index.d.ts +4 -0
  137. package/lib/typescript/commonjs/src/hooks/use-form/index.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/src/hooks/use-form/types.d.ts +119 -0
  139. package/lib/typescript/commonjs/src/hooks/use-form/types.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/src/hooks/use-form/useForm.d.ts +30 -0
  141. package/lib/typescript/commonjs/src/hooks/use-form/useForm.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/src/hooks/use-form/validators.d.ts +41 -0
  143. package/lib/typescript/commonjs/src/hooks/use-form/validators.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/src/index.d.ts +1 -0
  145. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  146. package/lib/typescript/commonjs/src/theme/utils/index.d.ts +3 -0
  147. package/lib/typescript/commonjs/src/theme/utils/index.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/src/theme/utils/withTextWrapper.d.ts +41 -0
  149. package/lib/typescript/commonjs/src/theme/utils/withTextWrapper.d.ts.map +1 -0
  150. package/lib/typescript/module/src/components/Anchor/index.d.ts +2 -1
  151. package/lib/typescript/module/src/components/Anchor/index.d.ts.map +1 -1
  152. package/lib/typescript/module/src/components/Badge/index.d.ts +2 -1
  153. package/lib/typescript/module/src/components/Badge/index.d.ts.map +1 -1
  154. package/lib/typescript/module/src/components/Blockquote/index.d.ts +2 -1
  155. package/lib/typescript/module/src/components/Blockquote/index.d.ts.map +1 -1
  156. package/lib/typescript/module/src/components/Button/index.d.ts +2 -2
  157. package/lib/typescript/module/src/components/Button/index.d.ts.map +1 -1
  158. package/lib/typescript/module/src/components/Chip/index.d.ts +2 -1
  159. package/lib/typescript/module/src/components/Chip/index.d.ts.map +1 -1
  160. package/lib/typescript/module/src/components/Code/index.d.ts +2 -1
  161. package/lib/typescript/module/src/components/Code/index.d.ts.map +1 -1
  162. package/lib/typescript/module/src/components/Group/index.d.ts +1 -0
  163. package/lib/typescript/module/src/components/Group/index.d.ts.map +1 -1
  164. package/lib/typescript/module/src/components/Kbd/index.d.ts +2 -1
  165. package/lib/typescript/module/src/components/Kbd/index.d.ts.map +1 -1
  166. package/lib/typescript/module/src/components/List/index.d.ts +2 -1
  167. package/lib/typescript/module/src/components/List/index.d.ts.map +1 -1
  168. package/lib/typescript/module/src/components/Mark/index.d.ts +2 -1
  169. package/lib/typescript/module/src/components/Mark/index.d.ts.map +1 -1
  170. package/lib/typescript/module/src/components/Menu/index.d.ts +3 -2
  171. package/lib/typescript/module/src/components/Menu/index.d.ts.map +1 -1
  172. package/lib/typescript/module/src/components/NavLink/index.d.ts +2 -1
  173. package/lib/typescript/module/src/components/NavLink/index.d.ts.map +1 -1
  174. package/lib/typescript/module/src/components/Notification/index.d.ts +2 -1
  175. package/lib/typescript/module/src/components/Notification/index.d.ts.map +1 -1
  176. package/lib/typescript/module/src/components/Radio/index.d.ts +22 -1
  177. package/lib/typescript/module/src/components/Radio/index.d.ts.map +1 -1
  178. package/lib/typescript/module/src/components/Table/Table.example.d.ts +3 -0
  179. package/lib/typescript/module/src/components/Table/Table.example.d.ts.map +1 -0
  180. package/lib/typescript/module/src/components/Table/index.d.ts +7 -2
  181. package/lib/typescript/module/src/components/Table/index.d.ts.map +1 -1
  182. package/lib/typescript/module/src/components/Title/index.d.ts +2 -1
  183. package/lib/typescript/module/src/components/Title/index.d.ts.map +1 -1
  184. package/lib/typescript/module/src/hooks/index.d.ts +3 -0
  185. package/lib/typescript/module/src/hooks/index.d.ts.map +1 -0
  186. package/lib/typescript/module/src/hooks/use-form/index.d.ts +4 -0
  187. package/lib/typescript/module/src/hooks/use-form/index.d.ts.map +1 -0
  188. package/lib/typescript/module/src/hooks/use-form/types.d.ts +119 -0
  189. package/lib/typescript/module/src/hooks/use-form/types.d.ts.map +1 -0
  190. package/lib/typescript/module/src/hooks/use-form/useForm.d.ts +30 -0
  191. package/lib/typescript/module/src/hooks/use-form/useForm.d.ts.map +1 -0
  192. package/lib/typescript/module/src/hooks/use-form/validators.d.ts +41 -0
  193. package/lib/typescript/module/src/hooks/use-form/validators.d.ts.map +1 -0
  194. package/lib/typescript/module/src/index.d.ts +1 -0
  195. package/lib/typescript/module/src/index.d.ts.map +1 -1
  196. package/lib/typescript/module/src/theme/utils/index.d.ts +3 -0
  197. package/lib/typescript/module/src/theme/utils/index.d.ts.map +1 -0
  198. package/lib/typescript/module/src/theme/utils/withTextWrapper.d.ts +41 -0
  199. package/lib/typescript/module/src/theme/utils/withTextWrapper.d.ts.map +1 -0
  200. package/package.json +1 -1
  201. package/src/components/Anchor/index.tsx +8 -2
  202. package/src/components/Badge/index.tsx +5 -3
  203. package/src/components/Blockquote/index.tsx +6 -5
  204. package/src/components/Button/index.tsx +5 -6
  205. package/src/components/Chip/index.tsx +5 -3
  206. package/src/components/Code/index.tsx +19 -14
  207. package/src/components/Group/index.tsx +1 -0
  208. package/src/components/Kbd/index.tsx +5 -4
  209. package/src/components/List/index.tsx +7 -8
  210. package/src/components/Mark/index.tsx +7 -2
  211. package/src/components/Menu/index.tsx +8 -7
  212. package/src/components/NavLink/index.tsx +6 -4
  213. package/src/components/Notification/index.tsx +6 -15
  214. package/src/components/Radio/index.tsx +99 -8
  215. package/src/components/Table/Table.example.tsx +85 -0
  216. package/src/components/Table/index.tsx +93 -11
  217. package/src/components/Title/index.tsx +7 -2
  218. package/src/hooks/index.ts +2 -0
  219. package/src/hooks/use-form/index.ts +3 -0
  220. package/src/hooks/use-form/types.ts +169 -0
  221. package/src/hooks/use-form/useForm.ts +436 -0
  222. package/src/hooks/use-form/validators.ts +143 -0
  223. package/src/index.tsx +1 -0
  224. package/src/theme/utils/index.ts +2 -0
  225. package/src/theme/utils/withTextWrapper.tsx +58 -0
@@ -6,8 +6,9 @@ import type { DefaultProps, MantineColor, MantineNumberSize } from '../../theme/
6
6
  import { useComponentDefaultProps } from '../../theme/theme-provider';
7
7
  import { createStyles } from '../../theme';
8
8
  import { rem } from '../../theme/utils/rem';
9
+ import { withTextWrapper, type WithTextWrapperProps } from '../../theme/utils/withTextWrapper';
9
10
 
10
- export interface NotificationProps extends DefaultProps {
11
+ export interface NotificationProps extends DefaultProps, WithTextWrapperProps {
11
12
  /** Notification title */
12
13
  title?: React.ReactNode;
13
14
 
@@ -128,6 +129,7 @@ const defaultProps: Partial<NotificationProps> = {
128
129
  withCloseButton: true,
129
130
  withBorder: true,
130
131
  loading: false,
132
+ withTextWrapper: true,
131
133
  };
132
134
 
133
135
  export const Notification = forwardRef<any, NotificationProps>((props, ref) => {
@@ -142,6 +144,7 @@ export const Notification = forwardRef<any, NotificationProps>((props, ref) => {
142
144
  loading,
143
145
  withBorder,
144
146
  style,
147
+ withTextWrapper: shouldWrapInText,
145
148
  ...others
146
149
  } = useComponentDefaultProps('Notification', defaultProps, props);
147
150
 
@@ -155,20 +158,8 @@ export const Notification = forwardRef<any, NotificationProps>((props, ref) => {
155
158
  {icon && <BoxView style={styles.icon}>{icon}</BoxView>}
156
159
 
157
160
  <BoxView style={styles.body}>
158
- {title && (
159
- typeof title === 'string' || typeof title === 'number' ? (
160
- <Text style={styles.title}>{title}</Text>
161
- ) : (
162
- <BoxView style={{ marginBottom: styles.title.marginBottom }}>{title}</BoxView>
163
- )
164
- )}
165
- {message && (
166
- typeof message === 'string' || typeof message === 'number' ? (
167
- <Text style={styles.message}>{message}</Text>
168
- ) : (
169
- <BoxView>{message}</BoxView>
170
- )
171
- )}
161
+ {title && withTextWrapper(title, shouldWrapInText, styles.title)}
162
+ {message && withTextWrapper(message, shouldWrapInText, styles.message)}
172
163
  </BoxView>
173
164
 
174
165
  {withCloseButton && onClose && (
@@ -1,5 +1,5 @@
1
- import React, { forwardRef, useEffect, useRef } from 'react';
2
- import { Pressable, Animated } from 'react-native';
1
+ import React, { forwardRef, useEffect, useRef, createContext, useContext } from 'react';
2
+ import { Pressable, Animated, View } from 'react-native';
3
3
  import { BoxView } from '../BoxView';
4
4
  import { Text } from '../Text';
5
5
  import type { DefaultProps, MantineColor, MantineSize } from '../../theme/types';
@@ -36,6 +36,44 @@ export interface RadioProps extends DefaultProps {
36
36
  wrapperStyle?: any;
37
37
  }
38
38
 
39
+ export interface RadioGroupProps {
40
+ /** Current selected value */
41
+ value?: string;
42
+
43
+ /** Called when value changes */
44
+ onChange?: (value: string) => void;
45
+
46
+ /** Radio group children */
47
+ children: React.ReactNode;
48
+
49
+ /** Radio group name for accessibility */
50
+ name?: string;
51
+
52
+ /** Radio size for all children */
53
+ size?: MantineSize;
54
+
55
+ /** Radio color for all children */
56
+ color?: MantineColor;
57
+
58
+ /** Wrapper style */
59
+ style?: any;
60
+
61
+ /** Spacing between radio buttons */
62
+ spacing?: number;
63
+ }
64
+
65
+ interface RadioGroupContextValue {
66
+ value?: string;
67
+ onChange?: (value: string) => void;
68
+ size?: MantineSize;
69
+ color?: MantineColor;
70
+ name?: string;
71
+ }
72
+
73
+ const RadioGroupContext = createContext<RadioGroupContextValue | undefined>(undefined);
74
+
75
+ const useRadioGroupContext = () => useContext(RadioGroupContext);
76
+
39
77
  const sizes = {
40
78
  xs: rem(14),
41
79
  sm: rem(18),
@@ -103,20 +141,28 @@ const defaultProps: Partial<RadioProps> = {
103
141
  disabled: false,
104
142
  };
105
143
 
106
- export const Radio = forwardRef<any, RadioProps>((props, ref) => {
144
+ const RadioComponent = forwardRef<any, RadioProps>((props, ref) => {
145
+ const groupContext = useRadioGroupContext();
146
+
107
147
  const {
108
148
  label,
109
- size,
110
- color,
149
+ size: propSize,
150
+ color: propColor,
111
151
  value,
112
- checked,
113
- onChange,
152
+ checked: propChecked,
153
+ onChange: propOnChange,
114
154
  disabled,
115
155
  style,
116
156
  wrapperStyle,
117
157
  ...others
118
158
  } = useComponentDefaultProps('Radio', defaultProps, props);
119
159
 
160
+ // Use group context if available, otherwise use props
161
+ const size = propSize || groupContext?.size || defaultProps.size;
162
+ const color = propColor || groupContext?.color || defaultProps.color;
163
+ const checked = groupContext ? groupContext.value === value : propChecked;
164
+ const onChange = groupContext?.onChange || propOnChange;
165
+
120
166
  const { styles, sx } = useStyles({ size, color, disabled }, { name: 'Radio' }) as any;
121
167
 
122
168
  const scaleAnim = useRef(new Animated.Value(checked ? 1 : 0)).current;
@@ -158,6 +204,7 @@ export const Radio = forwardRef<any, RadioProps>((props, ref) => {
158
204
  style={sx(styles.root, wrapperStyle)}
159
205
  accessibilityRole="radio"
160
206
  accessibilityState={{ checked }}
207
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
161
208
  {...others}
162
209
  >
163
210
  {radioContent}
@@ -166,4 +213,48 @@ export const Radio = forwardRef<any, RadioProps>((props, ref) => {
166
213
  );
167
214
  });
168
215
 
169
- Radio.displayName = 'Radio';
216
+ RadioComponent.displayName = 'Radio';
217
+
218
+ const RadioGroup = forwardRef<View, RadioGroupProps>((props, ref) => {
219
+ const {
220
+ value,
221
+ onChange,
222
+ children,
223
+ name,
224
+ size,
225
+ color,
226
+ style,
227
+ spacing = 12,
228
+ } = props;
229
+
230
+ const contextValue: RadioGroupContextValue = {
231
+ value,
232
+ onChange,
233
+ size,
234
+ color,
235
+ name,
236
+ };
237
+
238
+ return (
239
+ <RadioGroupContext.Provider value={contextValue}>
240
+ <View ref={ref} style={style}>
241
+ {React.Children.map(children, (child, index) => {
242
+ if (!React.isValidElement(child)) {
243
+ return child;
244
+ }
245
+ return (
246
+ <View key={index} style={{ marginBottom: index < React.Children.count(children) - 1 ? spacing : 0 }}>
247
+ {child}
248
+ </View>
249
+ );
250
+ })}
251
+ </View>
252
+ </RadioGroupContext.Provider>
253
+ );
254
+ });
255
+
256
+ RadioGroup.displayName = 'RadioGroup';
257
+
258
+ export const Radio = Object.assign(RadioComponent, {
259
+ Group: RadioGroup,
260
+ });
@@ -0,0 +1,85 @@
1
+ import { View } from 'react-native';
2
+ import { Table } from './index';
3
+
4
+ /**
5
+ * Example demonstrating the fixed Table component with proper column alignment.
6
+ *
7
+ * The fix addresses the following issues:
8
+ * 1. Removed flex: 1 from cells which caused equal spacing regardless of content
9
+ * 2. Implemented automatic column width calculation using onLayout callbacks
10
+ * 3. Each column now uses the maximum width of all cells in that column
11
+ * 4. Columns align properly across all rows (thead, tbody, tfoot)
12
+ */
13
+
14
+ const elements = [
15
+ { position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
16
+ { position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
17
+ { position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
18
+ { position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
19
+ { position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
20
+ ];
21
+
22
+ export function TableExample() {
23
+ return (
24
+ <View style={{ padding: 40 }}>
25
+ <Table
26
+ verticalSpacing="md"
27
+ horizontalSpacing="md"
28
+ fontSize="sm"
29
+ striped
30
+ withBorder
31
+ withColumnBorders
32
+ >
33
+ <Table.Thead>
34
+ <Table.Tr>
35
+ <Table.Th>Element position</Table.Th>
36
+ <Table.Th>Element name</Table.Th>
37
+ <Table.Th>Symbol</Table.Th>
38
+ <Table.Th>Atomic mass</Table.Th>
39
+ </Table.Tr>
40
+ </Table.Thead>
41
+ <Table.Tbody>
42
+ {elements.map((element) => (
43
+ <Table.Tr key={element.name}>
44
+ <Table.Td>{element.position}</Table.Td>
45
+ <Table.Td>{element.name}</Table.Td>
46
+ <Table.Td>{element.symbol}</Table.Td>
47
+ <Table.Td>{element.mass}</Table.Td>
48
+ </Table.Tr>
49
+ ))}
50
+ </Table.Tbody>
51
+ </Table>
52
+ </View>
53
+ );
54
+ }
55
+
56
+ export function TableWithVariableContent() {
57
+ return (
58
+ <View style={{ padding: 40 }}>
59
+ <Table withBorder withColumnBorders>
60
+ <Table.Thead>
61
+ <Table.Tr>
62
+ <Table.Th>Short</Table.Th>
63
+ <Table.Th>Medium length header</Table.Th>
64
+ <Table.Th>Very long header text that spans multiple words</Table.Th>
65
+ <Table.Th>ID</Table.Th>
66
+ </Table.Tr>
67
+ </Table.Thead>
68
+ <Table.Tbody>
69
+ <Table.Tr>
70
+ <Table.Td>A</Table.Td>
71
+ <Table.Td>Medium content here</Table.Td>
72
+ <Table.Td>Short</Table.Td>
73
+ <Table.Td>1</Table.Td>
74
+ </Table.Tr>
75
+ <Table.Tr>
76
+ <Table.Td>B</Table.Td>
77
+ <Table.Td>Short</Table.Td>
78
+ <Table.Td>This is a very long content that should make the column wider</Table.Td>
79
+ <Table.Td>2</Table.Td>
80
+ </Table.Tr>
81
+ </Table.Tbody>
82
+ </Table>
83
+ </View>
84
+ );
85
+ }
@@ -1,11 +1,13 @@
1
- import React, { forwardRef, createContext, useContext } from 'react';
1
+ import React, { forwardRef, createContext, useContext, useState, useCallback } from 'react';
2
2
  import { ScrollView } from 'react-native';
3
+ import type { LayoutChangeEvent } from 'react-native';
3
4
  import { BoxView } from '../BoxView';
4
5
  import { Text } from '../Text';
5
6
  import type { DefaultProps, SpacingValue } from '../../theme/types';
6
7
  import { useComponentDefaultProps } from '../../theme/theme-provider';
7
8
  import { createStyles } from '../../theme';
8
9
  import { rem } from '../../theme/utils/rem';
10
+ import { withTextWrapper, type WithTextWrapperProps } from '../../theme/utils/withTextWrapper';
9
11
 
10
12
  interface TableContextValue {
11
13
  striped: boolean;
@@ -15,6 +17,8 @@ interface TableContextValue {
15
17
  fontSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
16
18
  verticalSpacing: SpacingValue;
17
19
  horizontalSpacing: SpacingValue;
20
+ columnWidths: number[];
21
+ onCellLayout: (columnIndex: number, width: number) => void;
18
22
  }
19
23
 
20
24
  const TableContext = createContext<TableContextValue | null>(null);
@@ -94,20 +98,26 @@ export interface TableTrProps extends DefaultProps {
94
98
  __index?: number;
95
99
  }
96
100
 
97
- export interface TableThProps extends DefaultProps {
101
+ export interface TableThProps extends DefaultProps, WithTextWrapperProps {
98
102
  /** Th children */
99
103
  children?: React.ReactNode;
100
104
 
101
105
  /** Additional styles */
102
106
  style?: any;
107
+
108
+ /** Internal column index */
109
+ __columnIndex?: number;
103
110
  }
104
111
 
105
- export interface TableTdProps extends DefaultProps {
112
+ export interface TableTdProps extends DefaultProps, WithTextWrapperProps {
106
113
  /** Td children */
107
114
  children?: React.ReactNode;
108
115
 
109
116
  /** Additional styles */
110
117
  style?: any;
118
+
119
+ /** Internal column index */
120
+ __columnIndex?: number;
111
121
  }
112
122
 
113
123
  const fontSizes = {
@@ -130,7 +140,7 @@ const useTableStyles = createStyles(
130
140
  }
131
141
  ) => ({
132
142
  wrapper: {
133
- flex: 1,
143
+ // No flex: 1 here to avoid constraining the table
134
144
  },
135
145
  root: {
136
146
  width: '100%',
@@ -179,6 +189,7 @@ const useTableRowStyles = createStyles(
179
189
  }
180
190
  ) => ({
181
191
  tr: {
192
+ flexDirection: 'row',
182
193
  borderBottomWidth: 1,
183
194
  borderBottomColor:
184
195
  theme.colorScheme === 'dark'
@@ -204,12 +215,14 @@ const useTableCellStyles = createStyles(
204
215
  horizontalSpacing,
205
216
  withColumnBorders,
206
217
  isHeader,
218
+ width,
207
219
  }: {
208
220
  fontSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
209
221
  verticalSpacing: SpacingValue;
210
222
  horizontalSpacing: SpacingValue;
211
223
  withColumnBorders: boolean;
212
224
  isHeader: boolean;
225
+ width?: number;
213
226
  }
214
227
  ) => {
215
228
  const getVerticalPadding = () => {
@@ -224,6 +237,9 @@ const useTableCellStyles = createStyles(
224
237
 
225
238
  return {
226
239
  cell: {
240
+ // Remove flex: 1 to prevent equal spacing
241
+ // Use explicit width when available for column alignment
242
+ ...(width && { width }),
227
243
  paddingVertical: getVerticalPadding() as any,
228
244
  paddingHorizontal: getHorizontalPadding() as any,
229
245
  fontSize: fontSizes[fontSize],
@@ -276,6 +292,20 @@ const Table = forwardRef<any, TableProps>((props, ref) => {
276
292
  { name: 'Table' }
277
293
  ) as any;
278
294
 
295
+ // Track column widths to ensure alignment across rows
296
+ const [columnWidths, setColumnWidths] = useState<number[]>([]);
297
+
298
+ const onCellLayout = useCallback((columnIndex: number, width: number) => {
299
+ setColumnWidths((prevWidths) => {
300
+ const newWidths = [...prevWidths];
301
+ // Store the maximum width for each column to ensure all cells in that column have the same width
302
+ if (!newWidths[columnIndex] || width > newWidths[columnIndex]) {
303
+ newWidths[columnIndex] = width;
304
+ }
305
+ return newWidths;
306
+ });
307
+ }, []);
308
+
279
309
  return (
280
310
  <TableContext.Provider
281
311
  value={{
@@ -286,6 +316,8 @@ const Table = forwardRef<any, TableProps>((props, ref) => {
286
316
  fontSize: fontSize!,
287
317
  verticalSpacing: verticalSpacing!,
288
318
  horizontalSpacing: horizontalSpacing!,
319
+ columnWidths,
320
+ onCellLayout,
289
321
  }}
290
322
  >
291
323
  <ScrollView
@@ -357,17 +389,32 @@ const Tr = forwardRef<any, TableTrProps>((props, ref) => {
357
389
  { name: 'Tr' }
358
390
  ) as any;
359
391
 
392
+ // Add column indices to children (Th and Td components)
393
+ const childrenArray = React.Children.toArray(children);
394
+ const childrenWithColumnIndex = childrenArray.map((child, index) => {
395
+ if (!React.isValidElement(child)) return child;
396
+ return React.cloneElement<TableThProps | TableTdProps>(
397
+ child as React.ReactElement<TableThProps | TableTdProps>,
398
+ {
399
+ __columnIndex: index,
400
+ }
401
+ );
402
+ });
403
+
360
404
  return (
361
405
  <BoxView ref={ref} style={sx(styles.tr, style)} {...others}>
362
- {children}
406
+ {childrenWithColumnIndex}
363
407
  </BoxView>
364
408
  );
365
409
  });
366
410
 
367
411
  const Th = forwardRef<any, TableThProps>((props, ref) => {
368
- const { children, style, ...others } = props;
412
+ const { children, style, withTextWrapper: shouldWrapInText = true, __columnIndex, ...others } = props;
369
413
  const context = useTableContext();
370
414
 
415
+ const columnIndex = __columnIndex ?? 0;
416
+ const columnWidth = context?.columnWidths?.[columnIndex];
417
+
371
418
  const { styles, sx } = useTableCellStyles(
372
419
  {
373
420
  fontSize: context?.fontSize ?? 'sm',
@@ -375,21 +422,40 @@ const Th = forwardRef<any, TableThProps>((props, ref) => {
375
422
  horizontalSpacing: context?.horizontalSpacing ?? 'xs',
376
423
  withColumnBorders: context?.withColumnBorders ?? false,
377
424
  isHeader: true,
425
+ width: columnWidth,
378
426
  },
379
427
  { name: 'Th' }
380
428
  ) as any;
381
429
 
430
+ const handleLayout = useCallback(
431
+ (event: LayoutChangeEvent) => {
432
+ const { width } = event.nativeEvent.layout;
433
+ if (context?.onCellLayout && width > 0) {
434
+ context.onCellLayout(columnIndex, width);
435
+ }
436
+ },
437
+ [context, columnIndex]
438
+ );
439
+
382
440
  return (
383
- <BoxView ref={ref} style={sx(styles.cell, style)} {...others}>
384
- <Text style={styles.cell}>{children}</Text>)
441
+ <BoxView
442
+ ref={ref}
443
+ style={sx(styles.cell, style)}
444
+ onLayout={handleLayout}
445
+ {...others}
446
+ >
447
+ {withTextWrapper(children, shouldWrapInText, styles.cell)}
385
448
  </BoxView>
386
449
  );
387
450
  });
388
451
 
389
452
  const Td = forwardRef<any, TableTdProps>((props, ref) => {
390
- const { children, style, ...others } = props;
453
+ const { children, style, withTextWrapper: shouldWrapInText = true, __columnIndex, ...others } = props;
391
454
  const context = useTableContext();
392
455
 
456
+ const columnIndex = __columnIndex ?? 0;
457
+ const columnWidth = context?.columnWidths?.[columnIndex];
458
+
393
459
  const { styles, sx } = useTableCellStyles(
394
460
  {
395
461
  fontSize: context?.fontSize ?? 'sm',
@@ -397,13 +463,29 @@ const Td = forwardRef<any, TableTdProps>((props, ref) => {
397
463
  horizontalSpacing: context?.horizontalSpacing ?? 'xs',
398
464
  withColumnBorders: context?.withColumnBorders ?? false,
399
465
  isHeader: false,
466
+ width: columnWidth,
400
467
  },
401
468
  { name: 'Td' }
402
469
  ) as any;
403
470
 
471
+ const handleLayout = useCallback(
472
+ (event: LayoutChangeEvent) => {
473
+ const { width } = event.nativeEvent.layout;
474
+ if (context?.onCellLayout && width > 0) {
475
+ context.onCellLayout(columnIndex, width);
476
+ }
477
+ },
478
+ [context, columnIndex]
479
+ );
480
+
404
481
  return (
405
- <BoxView ref={ref} style={sx(styles.cell, style)} {...others}>
406
- <Text style={styles.cell}>{children}</Text>
482
+ <BoxView
483
+ ref={ref}
484
+ style={sx(styles.cell, style)}
485
+ onLayout={handleLayout}
486
+ {...others}
487
+ >
488
+ {withTextWrapper(children, shouldWrapInText, styles.cell)}
407
489
  </BoxView>
408
490
  );
409
491
  });
@@ -2,8 +2,9 @@ import React, { forwardRef } from 'react';
2
2
  import { Text } from '../Text';
3
3
  import type { TextProps } from '../Text';
4
4
  import { useTheme } from '../../theme/theme-provider';
5
+ import type { WithTextWrapperProps } from '../../theme/utils/withTextWrapper';
5
6
 
6
- export interface TitleProps extends Omit<TextProps, 'size'> {
7
+ export interface TitleProps extends Omit<TextProps, 'size'>, WithTextWrapperProps {
7
8
  /** Heading order (h1-h6) */
8
9
  order?: 1 | 2 | 3 | 4 | 5 | 6;
9
10
 
@@ -16,7 +17,7 @@ export interface TitleProps extends Omit<TextProps, 'size'> {
16
17
  * Maps order prop to h1-h6 heading styles from theme
17
18
  */
18
19
  export const Title = forwardRef<any, TitleProps>((props, ref) => {
19
- const { order = 1, children, style, ...others} = props;
20
+ const { order = 1, children, style, withTextWrapper: shouldWrapInText = true, ...others} = props;
20
21
  const theme = useTheme();
21
22
 
22
23
  // Get heading styles from theme
@@ -29,6 +30,10 @@ export const Title = forwardRef<any, TitleProps>((props, ref) => {
29
30
  theme.headings.fontWeight ??
30
31
  700;
31
32
 
33
+ if (!shouldWrapInText) {
34
+ return children;
35
+ }
36
+
32
37
  return (
33
38
  <Text
34
39
  ref={ref}
@@ -0,0 +1,2 @@
1
+ export * from './useCachedResources';
2
+ export * from './use-form';
@@ -0,0 +1,3 @@
1
+ export { useForm } from './useForm';
2
+ export * from './types';
3
+ export * from './validators';