@idealyst/components 1.0.82 → 1.0.84

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 (316) hide show
  1. package/CLAUDE.md +199 -232
  2. package/README.md +5 -5
  3. package/package.json +25 -7
  4. package/plugin/README.md +272 -0
  5. package/plugin/test-cases.jsx +112 -0
  6. package/plugin/web-legacy.js +320 -0
  7. package/plugin/web.js +422 -124
  8. package/src/Accordion/Accordion.native.tsx +182 -0
  9. package/src/Accordion/Accordion.styles.tsx +260 -0
  10. package/src/Accordion/Accordion.web.tsx +147 -0
  11. package/src/Accordion/index.native.tsx +3 -0
  12. package/src/Accordion/index.ts +3 -0
  13. package/src/Accordion/index.web.tsx +3 -0
  14. package/src/Accordion/types.ts +23 -0
  15. package/src/ActivityIndicator/ActivityIndicator.native.tsx +17 -12
  16. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +83 -109
  17. package/src/ActivityIndicator/ActivityIndicator.web.tsx +23 -17
  18. package/src/ActivityIndicator/index.ts +5 -2
  19. package/src/ActivityIndicator/index.web.ts +5 -2
  20. package/src/ActivityIndicator/types.ts +15 -10
  21. package/src/Alert/Alert.native.tsx +113 -0
  22. package/src/Alert/Alert.styles.tsx +304 -0
  23. package/src/Alert/Alert.web.tsx +123 -0
  24. package/src/Alert/index.native.ts +5 -0
  25. package/src/Alert/index.ts +5 -0
  26. package/src/Alert/index.web.ts +5 -0
  27. package/src/Alert/types.ts +21 -0
  28. package/src/Avatar/Avatar.native.tsx +8 -6
  29. package/src/Avatar/Avatar.styles.tsx +64 -58
  30. package/src/Avatar/Avatar.web.tsx +13 -8
  31. package/src/Avatar/index.ts +5 -2
  32. package/src/Avatar/index.web.ts +5 -2
  33. package/src/Avatar/types.ts +19 -13
  34. package/src/Badge/Badge.native.tsx +59 -14
  35. package/src/Badge/Badge.styles.tsx +125 -139
  36. package/src/Badge/Badge.web.tsx +72 -16
  37. package/src/Badge/index.ts +5 -2
  38. package/src/Badge/index.web.ts +5 -2
  39. package/src/Badge/types.ts +23 -11
  40. package/src/Breadcrumb/Breadcrumb.native.tsx +225 -0
  41. package/src/Breadcrumb/Breadcrumb.styles.tsx +234 -0
  42. package/src/Breadcrumb/Breadcrumb.web.tsx +268 -0
  43. package/src/Breadcrumb/index.native.ts +5 -0
  44. package/src/Breadcrumb/index.ts +5 -0
  45. package/src/Breadcrumb/index.web.ts +5 -0
  46. package/src/Breadcrumb/types.ts +56 -0
  47. package/src/Button/Button.native.tsx +75 -24
  48. package/src/Button/Button.styles.tsx +248 -205
  49. package/src/Button/Button.web.tsx +82 -25
  50. package/src/Button/index.ts +5 -5
  51. package/src/Button/index.web.ts +5 -3
  52. package/src/Button/types.ts +32 -15
  53. package/src/Card/Card.native.tsx +14 -11
  54. package/src/Card/Card.styles.tsx +146 -220
  55. package/src/Card/Card.web.tsx +20 -21
  56. package/src/Card/index.ts +5 -5
  57. package/src/Card/index.web.ts +5 -3
  58. package/src/Card/types.ts +24 -17
  59. package/src/Checkbox/Checkbox.native.tsx +24 -34
  60. package/src/Checkbox/Checkbox.styles.tsx +223 -275
  61. package/src/Checkbox/Checkbox.web.tsx +30 -37
  62. package/src/Checkbox/index.ts +5 -5
  63. package/src/Checkbox/index.web.ts +5 -3
  64. package/src/Checkbox/types.ts +26 -20
  65. package/src/Chip/Chip.native.tsx +126 -0
  66. package/src/Chip/Chip.styles.tsx +138 -0
  67. package/src/Chip/Chip.web.tsx +154 -0
  68. package/src/Chip/index.native.ts +5 -0
  69. package/src/Chip/index.ts +5 -0
  70. package/src/Chip/index.web.ts +5 -0
  71. package/src/Chip/types.ts +51 -0
  72. package/src/Dialog/Dialog.native.tsx +65 -12
  73. package/src/Dialog/Dialog.styles.tsx +154 -136
  74. package/src/Dialog/Dialog.web.tsx +16 -11
  75. package/src/Dialog/index.ts +5 -2
  76. package/src/Dialog/index.web.ts +5 -2
  77. package/src/Dialog/types.ts +22 -16
  78. package/src/Divider/Divider.native.tsx +19 -14
  79. package/src/Divider/Divider.styles.tsx +273 -595
  80. package/src/Divider/Divider.web.tsx +19 -12
  81. package/src/Divider/index.ts +5 -5
  82. package/src/Divider/index.web.ts +5 -3
  83. package/src/Divider/types.ts +28 -19
  84. package/src/Icon/Icon.native.tsx +17 -24
  85. package/src/Icon/Icon.styles.tsx +64 -48
  86. package/src/Icon/Icon.web.tsx +14 -11
  87. package/src/Icon/IconSvg/IconSvg.native.tsx +42 -0
  88. package/src/Icon/IconSvg/IconSvg.web.tsx +40 -0
  89. package/src/Icon/IconSvg/index.native.ts +1 -0
  90. package/src/Icon/IconSvg/index.ts +1 -0
  91. package/src/Icon/icon-resolver.native.ts +27 -0
  92. package/src/Icon/icon-resolver.ts +70 -0
  93. package/src/Icon/index.ts +5 -5
  94. package/src/Icon/index.web.ts +5 -3
  95. package/src/Icon/types.ts +17 -11
  96. package/src/Image/Image.native.tsx +86 -0
  97. package/src/Image/Image.styles.tsx +57 -0
  98. package/src/Image/Image.web.tsx +92 -0
  99. package/src/Image/index.native.ts +5 -0
  100. package/src/Image/index.ts +5 -0
  101. package/src/Image/types.ts +21 -0
  102. package/src/Input/Input.native.tsx +103 -26
  103. package/src/Input/Input.styles.tsx +240 -177
  104. package/src/Input/Input.web.tsx +141 -38
  105. package/src/Input/index.ts +5 -5
  106. package/src/Input/index.web.ts +5 -3
  107. package/src/Input/types.ts +43 -20
  108. package/src/List/List.native.tsx +56 -0
  109. package/src/List/List.styles.tsx +257 -0
  110. package/src/List/List.web.tsx +43 -0
  111. package/src/List/ListContext.tsx +16 -0
  112. package/src/List/ListItem.native.tsx +111 -0
  113. package/src/List/ListItem.web.tsx +110 -0
  114. package/src/List/ListSection.native.tsx +31 -0
  115. package/src/List/ListSection.web.tsx +33 -0
  116. package/src/List/index.native.tsx +5 -0
  117. package/src/List/index.ts +5 -0
  118. package/src/List/index.web.tsx +5 -0
  119. package/src/List/types.ts +42 -0
  120. package/src/Menu/Menu.native.tsx +150 -0
  121. package/src/Menu/Menu.styles.tsx +185 -0
  122. package/src/Menu/Menu.web.tsx +99 -0
  123. package/src/Menu/MenuItem.native.tsx +66 -0
  124. package/src/Menu/MenuItem.styles.tsx +119 -0
  125. package/src/Menu/MenuItem.web.tsx +67 -0
  126. package/src/Menu/index.native.ts +3 -0
  127. package/src/Menu/index.ts +3 -0
  128. package/src/Menu/index.web.ts +3 -0
  129. package/src/Menu/types.ts +30 -0
  130. package/src/Popover/Popover.native.tsx +102 -32
  131. package/src/Popover/Popover.styles.tsx +100 -67
  132. package/src/Popover/Popover.web.tsx +36 -260
  133. package/src/Popover/index.ts +5 -2
  134. package/src/Popover/index.web.ts +5 -2
  135. package/src/Popover/types.ts +14 -13
  136. package/src/Pressable/Pressable.native.tsx +7 -6
  137. package/src/Pressable/Pressable.web.tsx +8 -6
  138. package/src/Pressable/index.ts +5 -2
  139. package/src/Pressable/index.web.ts +5 -2
  140. package/src/Pressable/types.ts +11 -10
  141. package/src/Progress/Progress.native.tsx +179 -0
  142. package/src/Progress/Progress.styles.tsx +164 -0
  143. package/src/Progress/Progress.web.tsx +144 -0
  144. package/src/Progress/index.native.ts +1 -0
  145. package/src/Progress/index.ts +5 -0
  146. package/src/Progress/index.web.ts +5 -0
  147. package/src/Progress/types.ts +21 -0
  148. package/src/RadioButton/RadioButton.native.tsx +88 -0
  149. package/src/RadioButton/RadioButton.styles.tsx +163 -0
  150. package/src/RadioButton/RadioButton.web.tsx +85 -0
  151. package/src/RadioButton/RadioGroup.native.tsx +43 -0
  152. package/src/RadioButton/RadioGroup.web.tsx +49 -0
  153. package/src/RadioButton/index.native.ts +2 -0
  154. package/src/RadioButton/index.ts +2 -0
  155. package/src/RadioButton/index.web.ts +2 -0
  156. package/src/RadioButton/types.ts +29 -0
  157. package/src/SVGImage/SVGImage.native.tsx +9 -7
  158. package/src/SVGImage/SVGImage.styles.tsx +63 -55
  159. package/src/SVGImage/SVGImage.web.tsx +16 -13
  160. package/src/SVGImage/index.ts +5 -5
  161. package/src/SVGImage/index.web.ts +5 -2
  162. package/src/SVGImage/types.ts +7 -3
  163. package/src/Screen/Screen.native.tsx +43 -17
  164. package/src/Screen/Screen.styles.tsx +58 -54
  165. package/src/Screen/Screen.web.tsx +11 -5
  166. package/src/Screen/index.ts +5 -2
  167. package/src/Screen/index.web.ts +5 -2
  168. package/src/Screen/types.ts +23 -9
  169. package/src/Select/Select.native.tsx +347 -0
  170. package/src/Select/Select.styles.tsx +335 -0
  171. package/src/Select/Select.web.tsx +276 -0
  172. package/src/Select/index.native.ts +2 -0
  173. package/src/Select/index.ts +5 -0
  174. package/src/Select/index.web.ts +5 -0
  175. package/src/Select/types.ts +124 -0
  176. package/src/Skeleton/Skeleton.native.tsx +139 -0
  177. package/src/Skeleton/Skeleton.styles.tsx +59 -0
  178. package/src/Skeleton/Skeleton.web.tsx +112 -0
  179. package/src/Skeleton/index.native.ts +4 -0
  180. package/src/Skeleton/index.ts +5 -0
  181. package/src/Skeleton/index.web.ts +5 -0
  182. package/src/Skeleton/types.ts +75 -0
  183. package/src/Slider/Slider.native.tsx +248 -0
  184. package/src/Slider/Slider.styles.tsx +241 -0
  185. package/src/Slider/Slider.web.tsx +226 -0
  186. package/src/Slider/index.native.ts +3 -0
  187. package/src/Slider/index.ts +5 -0
  188. package/src/Slider/index.web.ts +5 -0
  189. package/src/Slider/types.ts +31 -0
  190. package/src/Switch/Switch.native.tsx +131 -0
  191. package/src/Switch/Switch.styles.tsx +169 -0
  192. package/src/Switch/Switch.web.tsx +121 -0
  193. package/src/Switch/index.native.ts +3 -0
  194. package/src/Switch/index.ts +5 -0
  195. package/src/Switch/index.web.ts +5 -0
  196. package/src/Switch/types.ts +21 -0
  197. package/src/TabBar/TabBar.native.tsx +142 -0
  198. package/src/TabBar/TabBar.styles.tsx +399 -0
  199. package/src/TabBar/TabBar.web.tsx +205 -0
  200. package/src/TabBar/index.native.tsx +3 -0
  201. package/src/TabBar/index.ts +3 -0
  202. package/src/TabBar/index.web.tsx +3 -0
  203. package/src/TabBar/types.ts +26 -0
  204. package/src/Table/Table.native.tsx +122 -0
  205. package/src/Table/Table.styles.tsx +283 -0
  206. package/src/Table/Table.web.tsx +112 -0
  207. package/src/Table/index.native.tsx +3 -0
  208. package/src/Table/index.ts +3 -0
  209. package/src/Table/index.web.tsx +3 -0
  210. package/src/Table/types.ts +28 -0
  211. package/src/Text/Text.native.tsx +12 -11
  212. package/src/Text/Text.styles.tsx +76 -64
  213. package/src/Text/Text.web.tsx +14 -9
  214. package/src/Text/index.ts +5 -5
  215. package/src/Text/index.web.ts +5 -3
  216. package/src/Text/types.ts +20 -13
  217. package/src/TextArea/TextArea.native.tsx +134 -0
  218. package/src/TextArea/TextArea.styles.tsx +175 -0
  219. package/src/TextArea/TextArea.web.tsx +156 -0
  220. package/src/TextArea/index.native.ts +3 -0
  221. package/src/TextArea/index.ts +3 -0
  222. package/src/TextArea/index.web.ts +3 -0
  223. package/src/TextArea/types.ts +30 -0
  224. package/src/Tooltip/Tooltip.native.tsx +165 -0
  225. package/src/Tooltip/Tooltip.styles.tsx +73 -0
  226. package/src/Tooltip/Tooltip.web.tsx +87 -0
  227. package/src/Tooltip/index.native.ts +3 -0
  228. package/src/Tooltip/index.ts +3 -0
  229. package/src/Tooltip/types.ts +18 -0
  230. package/src/Video/Video.native.tsx +105 -0
  231. package/src/Video/Video.styles.tsx +39 -0
  232. package/src/Video/Video.web.tsx +115 -0
  233. package/src/Video/index.native.ts +5 -0
  234. package/src/Video/index.ts +5 -0
  235. package/src/Video/types.ts +29 -0
  236. package/src/View/View.native.tsx +9 -14
  237. package/src/View/View.styles.tsx +101 -93
  238. package/src/View/View.web.tsx +16 -17
  239. package/src/View/index.ts +5 -5
  240. package/src/View/index.web.ts +5 -3
  241. package/src/View/types.ts +29 -21
  242. package/src/examples/AccordionExamples.tsx +126 -0
  243. package/src/examples/AlertExamples.tsx +280 -0
  244. package/src/examples/AvatarExamples.tsx +23 -23
  245. package/src/examples/BadgeExamples.tsx +109 -41
  246. package/src/examples/BreadcrumbExamples.tsx +312 -0
  247. package/src/examples/ButtonExamples.tsx +160 -33
  248. package/src/examples/CardExamples.tsx +40 -40
  249. package/src/examples/CheckboxExamples.tsx +12 -12
  250. package/src/examples/ChipExamples.tsx +197 -0
  251. package/src/examples/DialogExamples.tsx +22 -22
  252. package/src/examples/DividerExamples.tsx +49 -49
  253. package/src/examples/IconExamples.tsx +270 -54
  254. package/src/examples/ImageExamples.tsx +174 -0
  255. package/src/examples/InputExamples.tsx +75 -17
  256. package/src/examples/ListExamples.tsx +288 -0
  257. package/src/examples/MenuExamples.tsx +144 -0
  258. package/src/examples/PopoverExamples.tsx +69 -73
  259. package/src/examples/ProgressExamples.tsx +137 -0
  260. package/src/examples/RadioButtonExamples.tsx +161 -0
  261. package/src/examples/SVGImageExamples.tsx +19 -17
  262. package/src/examples/ScreenExamples.tsx +31 -31
  263. package/src/examples/SelectExamples.tsx +423 -0
  264. package/src/examples/SkeletonExamples.tsx +206 -0
  265. package/src/examples/SliderExamples.tsx +200 -0
  266. package/src/examples/SwitchExamples.tsx +182 -0
  267. package/src/examples/TabBarExamples.tsx +143 -0
  268. package/src/examples/TableExamples.tsx +280 -0
  269. package/src/examples/TextAreaExamples.tsx +173 -0
  270. package/src/examples/TextExamples.tsx +28 -32
  271. package/src/examples/ThemeExtensionExamples.tsx +10 -10
  272. package/src/examples/TooltipExamples.tsx +126 -0
  273. package/src/examples/VideoExamples.tsx +144 -0
  274. package/src/examples/ViewExamples.tsx +64 -56
  275. package/src/examples/index.ts +18 -3
  276. package/src/hooks/useMergeRefs.ts +16 -0
  277. package/src/hooks/useSmartPosition.native.ts +169 -0
  278. package/src/index.native.ts +80 -9
  279. package/src/index.ts +75 -1
  280. package/src/internal/BoundedModalContent.native.tsx +58 -0
  281. package/src/internal/PositionedPortal.tsx +254 -0
  282. package/src/internal/SafeAreaDebugOverlay.native.tsx +173 -0
  283. package/src/unistyles.d.ts +6 -0
  284. package/src/utils/buildSizeVariants.ts +16 -0
  285. package/src/utils/deepMerge.ts +43 -0
  286. package/src/utils/positionUtils.native.ts +280 -0
  287. package/src/utils/styleHelpers.ts +48 -0
  288. package/LLM-ACCESS-GUIDE.md +0 -143
  289. package/src/ActivityIndicator/README.md +0 -132
  290. package/src/Avatar/README.md +0 -139
  291. package/src/Badge/README.md +0 -170
  292. package/src/Button/Button.types.ts +0 -12
  293. package/src/Button/README.md +0 -262
  294. package/src/Card/README.md +0 -258
  295. package/src/Checkbox/README.md +0 -102
  296. package/src/Dialog/README.md +0 -210
  297. package/src/Divider/README.md +0 -108
  298. package/src/Icon/README.md +0 -81
  299. package/src/Input/README.md +0 -100
  300. package/src/SVGImage/README.md +0 -209
  301. package/src/Screen/README.md +0 -86
  302. package/src/Text/README.md +0 -94
  303. package/src/View/README.md +0 -107
  304. package/src/examples/AllExamples.tsx +0 -84
  305. package/src/examples/README.md +0 -136
  306. package/src/examples/ValidationExamples.tsx +0 -95
  307. package/src/examples/extendedTheme.ts +0 -329
  308. package/src/theme/breakpoints.ts +0 -8
  309. package/src/theme/colorResolver.ts +0 -218
  310. package/src/theme/colors.ts +0 -315
  311. package/src/theme/defaultThemes.ts +0 -326
  312. package/src/theme/index.ts +0 -188
  313. package/src/theme/themeBuilder.ts +0 -602
  314. package/src/theme/unistyles.d.ts +0 -6
  315. package/src/theme/variantHelpers.ts +0 -584
  316. package/src/theme/variants.ts +0 -56
@@ -0,0 +1,122 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { View, ScrollView, Text, TouchableOpacity } from 'react-native';
3
+ import { tableStyles } from './Table.styles';
4
+ import type { TableProps, TableColumn } from './types';
5
+
6
+ function TableInner<T = any>({
7
+ columns,
8
+ data,
9
+ type = 'standard',
10
+ size = 'md',
11
+ stickyHeader = false,
12
+ onRowPress,
13
+ style,
14
+ testID,
15
+ }: TableProps<T>, ref: React.Ref<ScrollView>) {
16
+ // Apply variants
17
+ tableStyles.useVariants({
18
+ type,
19
+ size,
20
+ });
21
+
22
+ // Helper to get cell value
23
+ const getCellValue = (column: TableColumn<T>, row: T, rowIndex: number) => {
24
+ if (column.render) {
25
+ const value = column.dataIndex ? (row as any)[column.dataIndex] : row;
26
+ return column.render(value, row, rowIndex);
27
+ }
28
+ const value = column.dataIndex ? (row as any)[column.dataIndex] : '';
29
+ return <Text style={tableStyles.cell}>{String(value)}</Text>;
30
+ };
31
+
32
+ const isClickable = !!onRowPress;
33
+
34
+ return (
35
+ <ScrollView
36
+ ref={ref}
37
+ horizontal
38
+ style={[tableStyles.container, style]}
39
+ testID={testID}
40
+ >
41
+ <View style={tableStyles.table}>
42
+ {/* Header */}
43
+ <View style={tableStyles.thead}>
44
+ <View style={{ flexDirection: 'row' }}>
45
+ {columns.map((column) => {
46
+ tableStyles.useVariants({
47
+ size,
48
+ align: column.align || 'left',
49
+ type,
50
+ });
51
+
52
+ return (
53
+ <View
54
+ key={column.key}
55
+ style={[
56
+ tableStyles.headerCell,
57
+ { width: column.width, flex: column.width ? undefined : 1 },
58
+ ]}
59
+ >
60
+ <Text style={tableStyles.headerCell}>
61
+ {column.title}
62
+ </Text>
63
+ </View>
64
+ );
65
+ })}
66
+ </View>
67
+ </View>
68
+
69
+ {/* Body */}
70
+ <View style={tableStyles.tbody}>
71
+ {data.map((row, rowIndex) => {
72
+ tableStyles.useVariants({
73
+ type,
74
+ clickable: isClickable,
75
+ });
76
+
77
+ const RowComponent = isClickable ? TouchableOpacity : View;
78
+
79
+ return (
80
+ <RowComponent
81
+ key={rowIndex}
82
+ style={tableStyles.row}
83
+ onPress={isClickable ? () => onRowPress?.(row, rowIndex) : undefined}
84
+ testID={`${testID}-row-${rowIndex}`}
85
+ >
86
+ <View style={{ flexDirection: 'row' }}>
87
+ {columns.map((column) => {
88
+ tableStyles.useVariants({
89
+ size,
90
+ align: column.align || 'left',
91
+ type,
92
+ });
93
+
94
+ return (
95
+ <View
96
+ key={column.key}
97
+ style={[
98
+ tableStyles.cell,
99
+ { width: column.width, flex: column.width ? undefined : 1 },
100
+ ]}
101
+ >
102
+ {getCellValue(column, row, rowIndex)}
103
+ </View>
104
+ );
105
+ })}
106
+ </View>
107
+ </RowComponent>
108
+ );
109
+ })}
110
+ </View>
111
+ </View>
112
+ </ScrollView>
113
+ );
114
+ }
115
+
116
+ const Table = forwardRef(TableInner) as <T = any>(
117
+ props: TableProps<T> & { ref?: React.Ref<ScrollView> }
118
+ ) => React.ReactElement;
119
+
120
+ (Table as any).displayName = 'Table';
121
+
122
+ export default Table;
@@ -0,0 +1,283 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { Theme, StylesheetStyles, CompoundVariants, Size } from '@idealyst/theme';
3
+ import { buildSizeVariants } from '../utils/buildSizeVariants';
4
+
5
+ type TableType = 'default' | 'bordered' | 'striped';
6
+
7
+ type TableRowVariants = {
8
+ type: TableType;
9
+ clickable: boolean;
10
+ }
11
+ /**
12
+ * Create type variants for container
13
+ */
14
+ function createContainerTypeVariants(theme: Theme) {
15
+ return {
16
+ standard: {
17
+ borderWidth: 1,
18
+ borderStyle: 'solid',
19
+ borderColor: theme.colors.border.primary,
20
+ borderRadius: 8,
21
+ overflow: 'hidden',
22
+ _web: {
23
+ border: `1px solid ${theme.colors.border.primary}`,
24
+ },
25
+ },
26
+ bordered: {
27
+ borderWidth: 1,
28
+ borderStyle: 'solid',
29
+ borderColor: theme.colors.border.primary,
30
+ borderRadius: 8,
31
+ overflow: 'hidden',
32
+ _web: {
33
+ border: `1px solid ${theme.colors.border.primary}`,
34
+ },
35
+ },
36
+ striped: {
37
+ borderWidth: 1,
38
+ borderStyle: 'solid',
39
+ borderColor: theme.colors.border.primary,
40
+ borderRadius: 8,
41
+ overflow: 'hidden',
42
+ _web: {
43
+ border: `1px solid ${theme.colors.border.primary}`,
44
+ },
45
+ },
46
+ } as const;
47
+ }
48
+
49
+ /**
50
+ * Create type variants for row
51
+ */
52
+ function createRowTypeVariants(theme: Theme) {
53
+ return {
54
+ standard: {},
55
+ bordered: {
56
+ borderBottomWidth: 1,
57
+ borderBottomStyle: 'solid',
58
+ borderBottomColor: theme.colors.border.primary,
59
+ _web: {
60
+ borderBottom: `1px solid ${theme.colors.border.primary}`,
61
+ },
62
+ },
63
+ striped: {
64
+ borderBottomWidth: 1,
65
+ borderBottomStyle: 'solid',
66
+ borderBottomColor: theme.colors.border.primary,
67
+ _web: {
68
+ borderBottom: `1px solid ${theme.colors.border.primary}`,
69
+ ':nth-child(even)': {
70
+ backgroundColor: theme.colors.surface.secondary,
71
+ },
72
+ },
73
+ },
74
+ } as const;
75
+ }
76
+
77
+ /**
78
+ * Create compound variants for row
79
+ */
80
+ function createRowCompoundVariants(theme: Theme): CompoundVariants<keyof TableRowVariants> {
81
+ return [
82
+ {
83
+ type: 'striped',
84
+ clickable: true,
85
+ styles: {
86
+ _web: {
87
+ _hover: {
88
+ backgroundColor: theme.colors.surface.tertiary,
89
+ },
90
+ },
91
+ },
92
+ },
93
+ ] as const;
94
+ }
95
+
96
+ /**
97
+ * Create size variants for header cell
98
+ */
99
+ function createHeaderCellSizeVariants(theme: Theme) {
100
+ return buildSizeVariants(theme, 'table', (size) => ({
101
+ padding: size.padding,
102
+ fontSize: size.fontSize,
103
+ lineHeight: size.lineHeight,
104
+ }));
105
+ }
106
+
107
+ /**
108
+ * Create type variants for header cell
109
+ */
110
+ function createHeaderCellTypeVariants(theme: Theme) {
111
+ return {
112
+ standard: {},
113
+ bordered: {
114
+ borderRightWidth: 1,
115
+ borderRightStyle: 'solid',
116
+ borderRightColor: theme.colors.border.primary,
117
+ _web: {
118
+ borderRight: `1px solid ${theme.colors.border.primary}`,
119
+ ':last-child': {
120
+ borderRight: 'none',
121
+ },
122
+ },
123
+ },
124
+ striped: {},
125
+ } as const;
126
+ }
127
+
128
+ /**
129
+ * Create size variants for cell
130
+ */
131
+ function createCellSizeVariants(theme: Theme) {
132
+ return buildSizeVariants(theme, 'table', (size) => ({
133
+ padding: size.padding,
134
+ fontSize: size.fontSize,
135
+ lineHeight: size.lineHeight,
136
+ }));
137
+ }
138
+
139
+ /**
140
+ * Create type variants for cell
141
+ */
142
+ function createCellTypeVariants(theme: Theme) {
143
+ return {
144
+ standard: {},
145
+ bordered: {
146
+ borderRightWidth: 1,
147
+ borderRightStyle: 'solid',
148
+ borderRightColor: theme.colors.border.primary,
149
+ _web: {
150
+ borderRight: `1px solid ${theme.colors.border.primary}`,
151
+ ':last-child': {
152
+ borderRight: 'none',
153
+ },
154
+ },
155
+ },
156
+ striped: {},
157
+ } as const;
158
+ }
159
+
160
+ const createContainerStyles = (theme: Theme) => {
161
+ return {
162
+ width: '100%',
163
+ _web: {
164
+ overflow: 'auto',
165
+ },
166
+ variants: {
167
+ type: createContainerTypeVariants(theme),
168
+ },
169
+ } as const;
170
+ }
171
+
172
+ const createTableStyles = (theme: Theme) => {
173
+ return {
174
+ width: '100%',
175
+ _web: {
176
+ borderCollapse: 'collapse',
177
+ },
178
+ } as const;
179
+ }
180
+
181
+ const createTheadStyles = (theme: Theme) => {
182
+ return {
183
+ backgroundColor: theme.colors.surface.secondary,
184
+ variants: {
185
+ sticky: {
186
+ true: {
187
+ _web: {
188
+ position: 'sticky',
189
+ top: 0,
190
+ zIndex: 10,
191
+ }
192
+ },
193
+ false: {},
194
+ },
195
+ },
196
+ } as const;
197
+ }
198
+
199
+ const createRowStyles = (theme: Theme) => {
200
+ return {
201
+ variants: {
202
+ type: createRowTypeVariants(theme),
203
+ clickable: {
204
+ true: {
205
+ _web: {
206
+ cursor: 'pointer',
207
+ _hover: {
208
+ backgroundColor: theme.colors.surface.secondary,
209
+ },
210
+ },
211
+ },
212
+ false: {},
213
+ },
214
+ },
215
+ compoundVariants: createRowCompoundVariants(theme),
216
+ _web: {
217
+ transition: 'background-color 0.2s ease',
218
+ },
219
+ } as const;
220
+ }
221
+
222
+ const createHeaderCellStyles = (theme: Theme) => {
223
+ return {
224
+ textAlign: 'left',
225
+ fontWeight: '600',
226
+ color: theme.colors.text.primary,
227
+ borderBottomWidth: 2,
228
+ borderBottomStyle: 'solid',
229
+ borderBottomColor: theme.colors.border.primary,
230
+ _web: {
231
+ borderBottom: `2px solid ${theme.colors.border.primary}`,
232
+ },
233
+ variants: {
234
+ size: createHeaderCellSizeVariants(theme),
235
+ align: {
236
+ left: {
237
+ textAlign: 'left',
238
+ },
239
+ center: {
240
+ textAlign: 'center',
241
+ },
242
+ right: {
243
+ textAlign: 'right',
244
+ },
245
+ },
246
+ type: createHeaderCellTypeVariants(theme),
247
+ },
248
+ } as const;
249
+ }
250
+
251
+ const createCellStyles = (theme: Theme) => {
252
+ return {
253
+ textAlign: 'left',
254
+ color: theme.colors.text.primary,
255
+ variants: {
256
+ size: createCellSizeVariants(theme),
257
+ align: {
258
+ left: {
259
+ textAlign: 'left',
260
+ },
261
+ center: {
262
+ textAlign: 'center',
263
+ },
264
+ right: {
265
+ textAlign: 'right',
266
+ },
267
+ },
268
+ type: createCellTypeVariants(theme),
269
+ },
270
+ } as const;
271
+ }
272
+
273
+ export const tableStyles = StyleSheet.create((theme: Theme) => {
274
+ return {
275
+ container: createContainerStyles(theme),
276
+ table: createTableStyles(theme),
277
+ thead: createTheadStyles(theme),
278
+ tbody: {},
279
+ row: createRowStyles(theme),
280
+ headerCell: createHeaderCellStyles(theme),
281
+ cell: createCellStyles(theme),
282
+ } as const;
283
+ });
@@ -0,0 +1,112 @@
1
+ import React from 'react';
2
+ import { getWebProps } from 'react-native-unistyles/web';
3
+ import { tableStyles } from './Table.styles';
4
+ import type { TableProps, TableColumn } from './types';
5
+
6
+ function Table<T = any>({
7
+ columns,
8
+ data,
9
+ type = 'standard',
10
+ size = 'md',
11
+ stickyHeader = false,
12
+ onRowPress,
13
+ style,
14
+ testID,
15
+ }: TableProps<T>) {
16
+ // Apply variants
17
+ tableStyles.useVariants({
18
+ type,
19
+ size,
20
+ });
21
+
22
+ const containerProps = getWebProps([tableStyles.container, style as any]);
23
+ const tableProps = getWebProps([tableStyles.table]);
24
+
25
+ // Helper to get cell value
26
+ const getCellValue = (column: TableColumn<T>, row: T, rowIndex: number) => {
27
+ if (column.render) {
28
+ const value = column.dataIndex ? (row as any)[column.dataIndex] : row;
29
+ return column.render(value, row, rowIndex);
30
+ }
31
+ return column.dataIndex ? (row as any)[column.dataIndex] : '';
32
+ };
33
+
34
+ const isClickable = !!onRowPress;
35
+
36
+ return (
37
+ <div {...containerProps} data-testid={testID}>
38
+ <table {...tableProps}>
39
+ <thead {...getWebProps([tableStyles.thead])}>
40
+ <tr>
41
+ {columns.map((column) => {
42
+ tableStyles.useVariants({
43
+ size,
44
+ align: column.align || 'left',
45
+ type,
46
+ });
47
+
48
+ const headerCellProps = getWebProps([tableStyles.headerCell]);
49
+
50
+ return (
51
+ <th
52
+ key={column.key}
53
+ {...headerCellProps}
54
+ style={{
55
+ width: column.width,
56
+ }}
57
+ >
58
+ {column.title}
59
+ </th>
60
+ );
61
+ })}
62
+ </tr>
63
+ </thead>
64
+ <tbody {...getWebProps([tableStyles.tbody])}>
65
+ {data.map((row, rowIndex) => {
66
+ tableStyles.useVariants({
67
+ size,
68
+ align: 'left',
69
+ type,
70
+ clickable: isClickable,
71
+ });
72
+
73
+ const rowProps = getWebProps([tableStyles.row]);
74
+
75
+ return (
76
+ <tr
77
+ key={rowIndex}
78
+ {...rowProps}
79
+ onClick={() => onRowPress?.(row, rowIndex)}
80
+ data-testid={`${testID}-row-${rowIndex}`}
81
+ >
82
+ {columns.map((column) => {
83
+ tableStyles.useVariants({
84
+ size,
85
+ align: column.align || 'left',
86
+ type,
87
+ });
88
+
89
+ const cellProps = getWebProps([tableStyles.cell]);
90
+
91
+ return (
92
+ <td
93
+ key={column.key}
94
+ {...cellProps}
95
+ style={{
96
+ width: column.width,
97
+ }}
98
+ >
99
+ {getCellValue(column, row, rowIndex)}
100
+ </td>
101
+ );
102
+ })}
103
+ </tr>
104
+ );
105
+ })}
106
+ </tbody>
107
+ </table>
108
+ </div>
109
+ );
110
+ }
111
+
112
+ export default Table;
@@ -0,0 +1,3 @@
1
+ export { default } from './Table.native';
2
+ export { default as Table } from './Table.native';
3
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export { default } from './Table.web';
2
+ export { default as Table } from './Table.web';
3
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export { default } from './Table.web';
2
+ export { default as Table } from './Table.web';
3
+ export * from './types';
@@ -0,0 +1,28 @@
1
+ import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
2
+ import type { ReactNode } from 'react';
3
+ import { Size } from '@idealyst/theme';
4
+
5
+ // Component-specific type aliases for future extensibility
6
+ export type TableSizeVariant = Size;
7
+ export type TableType = 'standard' | 'bordered' | 'striped';
8
+ export type TableAlignVariant = 'left' | 'center' | 'right';
9
+
10
+ export interface TableColumn<T = any> {
11
+ key: string;
12
+ title: string;
13
+ dataIndex?: string;
14
+ render?: (value: any, row: T, index: number) => ReactNode;
15
+ width?: number | string;
16
+ align?: TableAlignVariant;
17
+ }
18
+
19
+ export interface TableProps<T = any> {
20
+ columns: TableColumn<T>[];
21
+ data: T[];
22
+ type?: TableType;
23
+ size?: TableSizeVariant;
24
+ stickyHeader?: boolean;
25
+ onRowPress?: (row: T, index: number) => void;
26
+ style?: StyleProp<ViewStyle>;
27
+ testID?: string;
28
+ }
@@ -1,36 +1,37 @@
1
- import React from 'react';
2
- import { StyleSheet } from 'react-native-unistyles';
1
+ import React, { forwardRef } from 'react';
3
2
  import { Text as RNText } from 'react-native';
4
3
  import { TextProps } from './types';
5
- import textStyles from './Text.styles';
4
+ import { textStyles } from './Text.styles';
6
5
 
7
- const Text: React.FC<TextProps> = ({
6
+ const Text = forwardRef<RNText, TextProps>(({
8
7
  children,
9
- size = 'medium',
8
+ size = 'md',
10
9
  weight = 'normal',
11
10
  color,
12
11
  align = 'left',
13
12
  style,
14
13
  testID,
15
- }) => {
14
+ }, ref) => {
16
15
  textStyles.useVariants({
17
16
  size,
18
17
  weight,
19
18
  align,
20
- color: color
21
19
  });
22
20
 
23
21
  return (
24
- <RNText
22
+ <RNText
23
+ ref={ref}
25
24
  style={[
26
- textStyles.text,
25
+ textStyles.text({ color }),
27
26
  style,
28
- ]}
27
+ ]}
29
28
  testID={testID}
30
29
  >
31
30
  {children}
32
31
  </RNText>
33
32
  );
34
- };
33
+ });
34
+
35
+ Text.displayName = 'Text';
35
36
 
36
37
  export default Text;