@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,225 @@
1
+ import React, { forwardRef, isValidElement, useState } from 'react';
2
+ import { Pressable, Text, View } from 'react-native';
3
+ import {
4
+ breadcrumbContainerStyles,
5
+ breadcrumbItemStyles,
6
+ breadcrumbSeparatorStyles,
7
+ breadcrumbEllipsisStyles,
8
+ breadcrumbMenuButtonStyles
9
+ } from './Breadcrumb.styles';
10
+ import type { BreadcrumbProps, BreadcrumbItem as BreadcrumbItemType } from './types';
11
+ import Icon from '../Icon';
12
+ import type { IconName } from '../Icon/icon-types';
13
+ import Menu from '../Menu/Menu.native';
14
+ import type { MenuItem } from '../Menu/types';
15
+
16
+ interface BreadcrumbItemProps {
17
+ item: BreadcrumbItemType;
18
+ isLast: boolean;
19
+ size: BreadcrumbProps['size'];
20
+ intent: BreadcrumbProps['intent'];
21
+ itemStyle?: BreadcrumbProps['itemStyle'];
22
+ }
23
+
24
+ const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, intent, itemStyle }) => {
25
+ // Apply variants for this item only
26
+ breadcrumbItemStyles.useVariants({
27
+ size,
28
+ intent,
29
+ disabled: item.disabled || false,
30
+ isLast,
31
+ clickable: !!item.onPress && !item.disabled,
32
+ });
33
+
34
+ const iconStyle = breadcrumbItemStyles.icon;
35
+
36
+ const renderIcon = () => {
37
+ if (!item.icon) return null;
38
+
39
+ if (typeof item.icon === 'string') {
40
+ const iconSize = iconStyle.width || 16;
41
+ return (
42
+ <Icon
43
+ name={item.icon as IconName}
44
+ size={iconSize}
45
+ style={iconStyle}
46
+ />
47
+ );
48
+ } else if (isValidElement(item.icon)) {
49
+ return item.icon;
50
+ }
51
+
52
+ return null;
53
+ };
54
+
55
+ const content = (
56
+ <View style={[breadcrumbItemStyles.item, itemStyle]}>
57
+ {item.icon && <View style={iconStyle}>{renderIcon()}</View>}
58
+ <Text style={breadcrumbItemStyles.itemText}>{item.label}</Text>
59
+ </View>
60
+ );
61
+
62
+ if (item.onPress && !item.disabled) {
63
+ return (
64
+ <Pressable
65
+ onPress={item.onPress}
66
+ disabled={item.disabled}
67
+ accessibilityRole="link"
68
+ accessibilityState={{
69
+ disabled: item.disabled,
70
+ }}
71
+ >
72
+ {content}
73
+ </Pressable>
74
+ );
75
+ }
76
+
77
+ return <View>{content}</View>;
78
+ };
79
+
80
+ interface BreadcrumbSeparatorProps {
81
+ separator: React.ReactNode;
82
+ size: BreadcrumbProps['size'];
83
+ separatorStyle?: BreadcrumbProps['separatorStyle'];
84
+ }
85
+
86
+ const BreadcrumbSeparator: React.FC<BreadcrumbSeparatorProps> = ({ separator, size, separatorStyle }) => {
87
+ breadcrumbSeparatorStyles.useVariants({ size });
88
+ const sepStyle = breadcrumbSeparatorStyles.separator;
89
+
90
+ if (typeof separator === 'string') {
91
+ return <Text style={[sepStyle, separatorStyle]}>{separator}</Text>;
92
+ }
93
+ return <View style={[sepStyle, separatorStyle]}>{separator}</View>;
94
+ };
95
+
96
+ interface BreadcrumbEllipsisProps {
97
+ size: BreadcrumbProps['size'];
98
+ intent: BreadcrumbProps['intent'];
99
+ }
100
+
101
+ const BreadcrumbEllipsis: React.FC<BreadcrumbEllipsisProps> = ({ size, intent }) => {
102
+ breadcrumbEllipsisStyles.useVariants({ size });
103
+ const iconStyle = breadcrumbEllipsisStyles.icon({ intent });
104
+
105
+ return (
106
+ <View style={breadcrumbEllipsisStyles.ellipsis}>
107
+ <Icon name="dots-horizontal" style={iconStyle} />
108
+ </View>
109
+ );
110
+ };
111
+
112
+ const Breadcrumb = forwardRef<View, BreadcrumbProps>(({
113
+ items,
114
+ separator = '/',
115
+ maxItems,
116
+ intent = 'primary',
117
+ size = 'md',
118
+ style,
119
+ itemStyle,
120
+ separatorStyle,
121
+ testID,
122
+ responsive = false,
123
+ minVisibleItems = 3,
124
+ }, ref) => {
125
+ const [menuOpen, setMenuOpen] = useState(false);
126
+
127
+ // Apply variants for menu button
128
+ breadcrumbMenuButtonStyles.useVariants({ size });
129
+ const menuIconStyle = breadcrumbMenuButtonStyles.icon({ intent });
130
+
131
+ // Handle responsive collapsing
132
+ let displayItems = items;
133
+ let collapsedItems: BreadcrumbItemType[] = [];
134
+ let showMenu = false;
135
+ let showEllipsis = false;
136
+
137
+ if (responsive && items.length > minVisibleItems) {
138
+ // Responsive mode: show first item + menu + last (minVisibleItems - 2) items
139
+ showMenu = true;
140
+ const lastItemCount = Math.max(1, minVisibleItems - 2);
141
+ displayItems = [
142
+ items[0],
143
+ ...items.slice(-lastItemCount),
144
+ ];
145
+ collapsedItems = items.slice(1, -(lastItemCount));
146
+ } else if (maxItems && items.length > maxItems) {
147
+ // Legacy truncation mode
148
+ showEllipsis = true;
149
+ const firstItems = items.slice(0, 1);
150
+ const lastItems = items.slice(-(maxItems - 1));
151
+ displayItems = [...firstItems, ...lastItems];
152
+ }
153
+
154
+ // Convert collapsed breadcrumb items to menu items
155
+ const menuItems: MenuItem[] = collapsedItems.map((item, index) => ({
156
+ id: `collapsed-${index}`,
157
+ label: item.label,
158
+ onClick: item.onPress,
159
+ disabled: item.disabled,
160
+ icon: typeof item.icon === 'string' ? (item.icon as IconName) : undefined,
161
+ }));
162
+
163
+ return (
164
+ <View
165
+ ref={ref}
166
+ style={[breadcrumbContainerStyles.container, style]}
167
+ testID={testID}
168
+ accessibilityLabel="Breadcrumb"
169
+ >
170
+ {displayItems.map((item, index) => {
171
+ const isLast = index === displayItems.length - 1;
172
+ const shouldShowEllipsis = showEllipsis && index === 1;
173
+ const shouldShowMenu = showMenu && index === 1;
174
+
175
+ return (
176
+ <React.Fragment key={index}>
177
+ {shouldShowEllipsis && (
178
+ <>
179
+ <BreadcrumbEllipsis size={size} intent={intent} />
180
+ <BreadcrumbSeparator separator={separator} size={size} separatorStyle={separatorStyle} />
181
+ </>
182
+ )}
183
+
184
+ {shouldShowMenu && (
185
+ <>
186
+ <Menu
187
+ items={menuItems}
188
+ open={menuOpen}
189
+ onOpenChange={setMenuOpen}
190
+ placement="bottom-start"
191
+ size={size}
192
+ >
193
+ <Pressable
194
+ style={breadcrumbMenuButtonStyles.button}
195
+ accessibilityRole="button"
196
+ accessibilityLabel="Show more breadcrumb items"
197
+ >
198
+ <Icon name="dots-horizontal" style={menuIconStyle} />
199
+ </Pressable>
200
+ </Menu>
201
+ <BreadcrumbSeparator separator={separator} size={size} separatorStyle={separatorStyle} />
202
+ </>
203
+ )}
204
+
205
+ <BreadcrumbItem
206
+ item={item}
207
+ isLast={isLast}
208
+ size={size}
209
+ intent={intent}
210
+ itemStyle={itemStyle}
211
+ />
212
+
213
+ {!isLast && (
214
+ <BreadcrumbSeparator separator={separator} size={size} separatorStyle={separatorStyle} />
215
+ )}
216
+ </React.Fragment>
217
+ );
218
+ })}
219
+ </View>
220
+ );
221
+ });
222
+
223
+ Breadcrumb.displayName = 'Breadcrumb';
224
+
225
+ export default Breadcrumb;
@@ -0,0 +1,234 @@
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 BreadcrumbSize = Size;
6
+ type BreadcrumbIntent = 'primary' | 'neutral';
7
+
8
+ type BreadcrumbVariants = {
9
+ size: BreadcrumbSize;
10
+ intent: BreadcrumbIntent;
11
+ disabled: boolean;
12
+ isLast: boolean;
13
+ clickable: boolean;
14
+ }
15
+
16
+ export type ExpandedBreadcrumbStyles = StylesheetStyles<keyof BreadcrumbVariants>;
17
+
18
+ export type BreadcrumbStylesheet = {
19
+ container: ExpandedBreadcrumbStyles;
20
+ item: ExpandedBreadcrumbStyles;
21
+ itemText: ExpandedBreadcrumbStyles;
22
+ icon: ExpandedBreadcrumbStyles;
23
+ separator: ExpandedBreadcrumbStyles;
24
+ ellipsis: ExpandedBreadcrumbStyles;
25
+ ellipsisIcon: ExpandedBreadcrumbStyles;
26
+ menuButton: ExpandedBreadcrumbStyles;
27
+ menuButtonIcon: ExpandedBreadcrumbStyles;
28
+ }
29
+
30
+ /**
31
+ * Create size variants for item text
32
+ */
33
+ function createItemTextSizeVariants(theme: Theme) {
34
+ return buildSizeVariants(theme, 'breadcrumb', (size) => ({
35
+ fontSize: size.fontSize,
36
+ lineHeight: size.lineHeight,
37
+ }));
38
+ }
39
+
40
+ /**
41
+ * Create compound variants for item text
42
+ */
43
+ function createItemTextCompoundVariants(theme: Theme): CompoundVariants<keyof BreadcrumbVariants> {
44
+ return [
45
+ {
46
+ clickable: true,
47
+ intent: 'primary',
48
+ isLast: false,
49
+ disabled: false,
50
+ styles: { color: theme.intents.primary.primary },
51
+ },
52
+ {
53
+ clickable: true,
54
+ intent: 'neutral',
55
+ isLast: false,
56
+ disabled: false,
57
+ styles: { color: theme.colors.text.secondary },
58
+ },
59
+ {
60
+ clickable: false,
61
+ isLast: false,
62
+ disabled: false,
63
+ styles: { color: theme.colors.text.secondary },
64
+ },
65
+ ];
66
+ }
67
+
68
+ /**
69
+ * Create size variants for icons
70
+ */
71
+ function createIconSizeVariants(theme: Theme) {
72
+ return buildSizeVariants(theme, 'breadcrumb', (size) => ({
73
+ width: size.iconSize,
74
+ height: size.iconSize,
75
+ }));
76
+ }
77
+
78
+ /**
79
+ * Get icon color based on intent
80
+ */
81
+ function getIconColor(theme: Theme, intent: BreadcrumbIntent) {
82
+ if (intent === 'primary') {
83
+ return theme.intents.primary.primary;
84
+ }
85
+ return theme.colors.text.secondary;
86
+ }
87
+
88
+ const createItemTextStyles = (theme: Theme) => {
89
+ return {
90
+ variants: {
91
+ size: createItemTextSizeVariants(theme),
92
+ intent: { primary: {}, neutral: {} },
93
+ disabled: {
94
+ true: {
95
+ opacity: 0.5,
96
+ color: theme.colors.text.secondary,
97
+ },
98
+ false: {},
99
+ },
100
+ isLast: {
101
+ true: { color: theme.colors.text.primary },
102
+ false: {},
103
+ },
104
+ clickable: { true: {}, false: {} },
105
+ },
106
+ compoundVariants: createItemTextCompoundVariants(theme),
107
+ } as const;
108
+ }
109
+
110
+ const createIconStyles = (theme: Theme) => {
111
+ return {
112
+ variants: {
113
+ size: createIconSizeVariants(theme),
114
+ },
115
+ } as const;
116
+ }
117
+
118
+ const createSeparatorStyles = (theme: Theme) => {
119
+ return {
120
+ color: theme.colors.text.tertiary,
121
+ variants: {
122
+ size: createItemTextSizeVariants(theme),
123
+ },
124
+ } as const;
125
+ }
126
+
127
+ const createEllipsisIconStyles = (theme: Theme) => {
128
+ return ({ intent }: Partial<BreadcrumbVariants>) => {
129
+ return {
130
+ color: getIconColor(theme, intent),
131
+ variants: {
132
+ size: createIconSizeVariants(theme),
133
+ },
134
+ } as const;
135
+ }
136
+ }
137
+
138
+ const createMenuButtonIconStyles = (theme: Theme) => {
139
+ return ({ intent }: Partial<BreadcrumbVariants>) => {
140
+ return {
141
+ color: getIconColor(theme, intent),
142
+ variants: {
143
+ size: createIconSizeVariants(theme),
144
+ },
145
+ } as const;
146
+ }
147
+ }
148
+
149
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
150
+ // @ts-ignore - TS language server needs restart to pick up theme structure changes
151
+ export const breadcrumbStyles = StyleSheet.create((theme: Theme) => {
152
+ return {
153
+ container: {
154
+ display: 'flex',
155
+ flexDirection: 'row',
156
+ alignItems: 'center',
157
+ flexWrap: 'wrap',
158
+ gap: 8,
159
+ },
160
+ item: {
161
+ display: 'flex',
162
+ flexDirection: 'row',
163
+ alignItems: 'center',
164
+ gap: 4,
165
+ },
166
+ itemText: createItemTextStyles(theme),
167
+ icon: createIconStyles(theme),
168
+ separator: createSeparatorStyles(theme),
169
+ ellipsis: {
170
+ display: 'flex',
171
+ alignItems: 'center',
172
+ justifyContent: 'center',
173
+ },
174
+ ellipsisIcon: createEllipsisIconStyles(theme),
175
+ menuButton: {
176
+ paddingVertical: 4,
177
+ paddingHorizontal: 8,
178
+ },
179
+ menuButtonIcon: createMenuButtonIconStyles(theme),
180
+ };
181
+ });
182
+
183
+ // Export individual style sheets for backwards compatibility
184
+ export const breadcrumbContainerStyles = StyleSheet.create((theme: Theme) => {
185
+ return {
186
+ container: {
187
+ display: 'flex',
188
+ flexDirection: 'row',
189
+ alignItems: 'center',
190
+ flexWrap: 'wrap',
191
+ gap: 8,
192
+ },
193
+ };
194
+ });
195
+
196
+ export const breadcrumbItemStyles = StyleSheet.create((theme: Theme) => {
197
+ return {
198
+ item: {
199
+ display: 'flex',
200
+ flexDirection: 'row',
201
+ alignItems: 'center',
202
+ gap: 4,
203
+ },
204
+ itemText: createItemTextStyles(theme),
205
+ icon: createIconStyles(theme),
206
+ } as const;
207
+ });
208
+
209
+ export const breadcrumbSeparatorStyles = StyleSheet.create((theme: Theme) => {
210
+ return {
211
+ separator: createSeparatorStyles(theme),
212
+ } as const;
213
+ });
214
+
215
+ export const breadcrumbEllipsisStyles = StyleSheet.create((theme: Theme) => {
216
+ return {
217
+ ellipsis: {
218
+ display: 'flex',
219
+ alignItems: 'center',
220
+ justifyContent: 'center',
221
+ },
222
+ icon: createEllipsisIconStyles(theme),
223
+ } as const;
224
+ });
225
+
226
+ export const breadcrumbMenuButtonStyles = StyleSheet.create((theme: Theme) => {
227
+ return {
228
+ button: {
229
+ paddingVertical: 4,
230
+ paddingHorizontal: 8,
231
+ },
232
+ icon: createMenuButtonIconStyles(theme),
233
+ } as const;
234
+ });