@expokit/cli 0.0.0-stage → 0.3.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 (312) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -2
  3. package/bin/expo-kit.js +1266 -0
  4. package/bin/lib.mjs +343 -0
  5. package/bin/mcp.mjs +345 -0
  6. package/package.json +49 -4
  7. package/registry/_docs/accordion.json +115 -0
  8. package/registry/_docs/action-sheet.json +138 -0
  9. package/registry/_docs/alert.json +155 -0
  10. package/registry/_docs/avatar.json +227 -0
  11. package/registry/_docs/badge.json +148 -0
  12. package/registry/_docs/bottom-nav.json +143 -0
  13. package/registry/_docs/bottom-sheet.json +186 -0
  14. package/registry/_docs/bullet.json +27 -0
  15. package/registry/_docs/button-3d.json +138 -0
  16. package/registry/_docs/button.json +131 -0
  17. package/registry/_docs/calendar.json +198 -0
  18. package/registry/_docs/card-stack.json +124 -0
  19. package/registry/_docs/card.json +131 -0
  20. package/registry/_docs/carousel.json +122 -0
  21. package/registry/_docs/chat.json +184 -0
  22. package/registry/_docs/checkbox.json +109 -0
  23. package/registry/_docs/checkout.json +105 -0
  24. package/registry/_docs/chip-group.json +132 -0
  25. package/registry/_docs/color-swatch.json +82 -0
  26. package/registry/_docs/confetti.json +102 -0
  27. package/registry/_docs/coupon.json +192 -0
  28. package/registry/_docs/cube-pager.json +100 -0
  29. package/registry/_docs/dashboard.json +123 -0
  30. package/registry/_docs/date-picker.json +269 -0
  31. package/registry/_docs/dialog.json +186 -0
  32. package/registry/_docs/drawer.json +199 -0
  33. package/registry/_docs/fab.json +144 -0
  34. package/registry/_docs/flip-card.json +127 -0
  35. package/registry/_docs/floating-input.json +211 -0
  36. package/registry/_docs/gift-card.json +124 -0
  37. package/registry/_docs/glass-button.json +142 -0
  38. package/registry/_docs/glass-nav-bar.json +102 -0
  39. package/registry/_docs/glass-search-bar.json +114 -0
  40. package/registry/_docs/glass-segmented.json +94 -0
  41. package/registry/_docs/glass-sheet.json +136 -0
  42. package/registry/_docs/glass-tab-bar.json +100 -0
  43. package/registry/_docs/glass.json +94 -0
  44. package/registry/_docs/inbox.json +75 -0
  45. package/registry/_docs/isometric-bar.json +75 -0
  46. package/registry/_docs/kit.json +14 -0
  47. package/registry/_docs/kpi-card.json +14 -0
  48. package/registry/_docs/like-button.json +92 -0
  49. package/registry/_docs/liquidglass-tab.json +30 -0
  50. package/registry/_docs/list-item.json +216 -0
  51. package/registry/_docs/loyalty-card.json +124 -0
  52. package/registry/_docs/morph-button.json +128 -0
  53. package/registry/_docs/number-ticker.json +112 -0
  54. package/registry/_docs/offers.json +81 -0
  55. package/registry/_docs/onboarding.json +69 -0
  56. package/registry/_docs/otp-input.json +158 -0
  57. package/registry/_docs/pagination-dots.json +108 -0
  58. package/registry/_docs/parallax-layers.json +104 -0
  59. package/registry/_docs/parallax-scroll.json +210 -0
  60. package/registry/_docs/password-input.json +112 -0
  61. package/registry/_docs/payment-card.json +169 -0
  62. package/registry/_docs/pixel-bar.json +69 -0
  63. package/registry/_docs/polar-area.json +81 -0
  64. package/registry/_docs/profile.json +87 -0
  65. package/registry/_docs/progress-steps.json +116 -0
  66. package/registry/_docs/progress.json +152 -0
  67. package/registry/_docs/radio-group.json +112 -0
  68. package/registry/_docs/rating.json +114 -0
  69. package/registry/_docs/ring-carousel.json +122 -0
  70. package/registry/_docs/scratch-card.json +110 -0
  71. package/registry/_docs/search-bar.json +160 -0
  72. package/registry/_docs/search-results.json +123 -0
  73. package/registry/_docs/segmented-control.json +123 -0
  74. package/registry/_docs/select.json +277 -0
  75. package/registry/_docs/settings.json +75 -0
  76. package/registry/_docs/shimmer-button.json +98 -0
  77. package/registry/_docs/sign-in.json +201 -0
  78. package/registry/_docs/skeleton.json +162 -0
  79. package/registry/_docs/slide-to-confirm.json +108 -0
  80. package/registry/_docs/slider.json +177 -0
  81. package/registry/_docs/spin-wheel.json +138 -0
  82. package/registry/_docs/spinner.json +121 -0
  83. package/registry/_docs/stateful-button.json +184 -0
  84. package/registry/_docs/stepper.json +184 -0
  85. package/registry/_docs/swipe-deck.json +118 -0
  86. package/registry/_docs/swipeable-row.json +95 -0
  87. package/registry/_docs/switch.json +124 -0
  88. package/registry/_docs/tabs.json +129 -0
  89. package/registry/_docs/tag-input.json +148 -0
  90. package/registry/_docs/text-animation.json +141 -0
  91. package/registry/_docs/textarea.json +191 -0
  92. package/registry/_docs/ticket-card.json +194 -0
  93. package/registry/_docs/ticket-shape.json +14 -0
  94. package/registry/_docs/tilt-card.json +157 -0
  95. package/registry/_docs/time-picker.json +269 -0
  96. package/registry/_docs/timeline-chart.json +33 -0
  97. package/registry/_docs/timeline.json +172 -0
  98. package/registry/_docs/toast.json +185 -0
  99. package/registry/_docs/treemap.json +33 -0
  100. package/registry/_docs/waterfall.json +39 -0
  101. package/registry/_docs/wheel-list.json +122 -0
  102. package/registry/accordion/files/src/components/ui/accordion.tsx +233 -0
  103. package/registry/accordion/files/src/lib/kit.tsx +219 -0
  104. package/registry/accordion.json +17 -0
  105. package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +580 -0
  106. package/registry/action-sheet/files/src/lib/kit.tsx +219 -0
  107. package/registry/action-sheet.json +18 -0
  108. package/registry/alert/files/src/components/ui/alert.tsx +654 -0
  109. package/registry/alert/files/src/components/ui/button.tsx +274 -0
  110. package/registry/alert/files/src/lib/kit.tsx +219 -0
  111. package/registry/alert.json +20 -0
  112. package/registry/avatar/files/src/components/ui/avatar.tsx +790 -0
  113. package/registry/avatar/files/src/lib/kit.tsx +219 -0
  114. package/registry/avatar.json +18 -0
  115. package/registry/badge/files/src/components/ui/badge.tsx +626 -0
  116. package/registry/badge/files/src/lib/kit.tsx +219 -0
  117. package/registry/badge.json +17 -0
  118. package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +1050 -0
  119. package/registry/bottom-nav/files/src/lib/kit.tsx +219 -0
  120. package/registry/bottom-nav.json +18 -0
  121. package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +585 -0
  122. package/registry/bottom-sheet/files/src/lib/kit.tsx +219 -0
  123. package/registry/bottom-sheet.json +17 -0
  124. package/registry/bullet.json +14 -0
  125. package/registry/button/files/src/components/ui/button.tsx +274 -0
  126. package/registry/button/files/src/lib/kit.tsx +219 -0
  127. package/registry/button-3d/files/src/components/ui/button-3d.tsx +212 -0
  128. package/registry/button-3d/files/src/lib/kit.tsx +219 -0
  129. package/registry/button-3d.json +18 -0
  130. package/registry/button.json +18 -0
  131. package/registry/calendar/files/src/components/ui/calendar.tsx +822 -0
  132. package/registry/calendar/files/src/lib/kit.tsx +219 -0
  133. package/registry/calendar.json +17 -0
  134. package/registry/card/files/src/components/ui/card.tsx +300 -0
  135. package/registry/card/files/src/lib/kit.tsx +219 -0
  136. package/registry/card-stack.json +15 -0
  137. package/registry/card.json +17 -0
  138. package/registry/carousel.json +15 -0
  139. package/registry/chat.json +18 -0
  140. package/registry/checkbox/files/src/components/ui/checkbox.tsx +150 -0
  141. package/registry/checkbox/files/src/lib/kit.tsx +219 -0
  142. package/registry/checkbox.json +17 -0
  143. package/registry/checkout.json +26 -0
  144. package/registry/chip-group/files/src/components/ui/chip-group.tsx +269 -0
  145. package/registry/chip-group/files/src/lib/kit.tsx +219 -0
  146. package/registry/chip-group.json +17 -0
  147. package/registry/color-swatch.json +17 -0
  148. package/registry/confetti/files/src/components/ui/confetti.tsx +222 -0
  149. package/registry/confetti/files/src/lib/kit.tsx +219 -0
  150. package/registry/confetti.json +15 -0
  151. package/registry/coupon/files/src/components/ui/coupon.tsx +698 -0
  152. package/registry/coupon/files/src/components/ui/flip-card.tsx +205 -0
  153. package/registry/coupon/files/src/components/ui/tilt-card.tsx +635 -0
  154. package/registry/coupon/files/src/lib/kit.tsx +219 -0
  155. package/registry/coupon/files/src/lib/ticket-shape.tsx +543 -0
  156. package/registry/coupon.json +23 -0
  157. package/registry/cube-pager.json +15 -0
  158. package/registry/dashboard.json +32 -0
  159. package/registry/date-picker/files/src/components/ui/calendar.tsx +822 -0
  160. package/registry/date-picker/files/src/components/ui/date-picker.tsx +796 -0
  161. package/registry/date-picker/files/src/lib/kit.tsx +219 -0
  162. package/registry/date-picker.json +19 -0
  163. package/registry/dialog/files/src/components/ui/dialog.tsx +759 -0
  164. package/registry/dialog/files/src/lib/kit.tsx +219 -0
  165. package/registry/dialog.json +18 -0
  166. package/registry/drawer/files/src/components/ui/drawer.tsx +1135 -0
  167. package/registry/drawer/files/src/lib/kit.tsx +219 -0
  168. package/registry/drawer.json +18 -0
  169. package/registry/fab.json +18 -0
  170. package/registry/flip-card/files/src/components/ui/flip-card.tsx +205 -0
  171. package/registry/flip-card/files/src/lib/kit.tsx +219 -0
  172. package/registry/flip-card.json +15 -0
  173. package/registry/floating-input/files/src/components/ui/floating-input.tsx +528 -0
  174. package/registry/floating-input/files/src/lib/kit.tsx +219 -0
  175. package/registry/floating-input.json +17 -0
  176. package/registry/gift-card.json +21 -0
  177. package/registry/glass-button.json +22 -0
  178. package/registry/glass-nav-bar.json +21 -0
  179. package/registry/glass-search-bar.json +21 -0
  180. package/registry/glass-segmented.json +22 -0
  181. package/registry/glass-sheet.json +22 -0
  182. package/registry/glass-tab-bar.json +22 -0
  183. package/registry/glass.json +19 -0
  184. package/registry/inbox.json +30 -0
  185. package/registry/isometric-bar.json +14 -0
  186. package/registry/kit/files/src/lib/kit.tsx +219 -0
  187. package/registry/kit.json +11 -0
  188. package/registry/kpi-card/files/src/components/charts/kpi-card.tsx +45 -0
  189. package/registry/kpi-card.json +14 -0
  190. package/registry/like-button.json +18 -0
  191. package/registry/liquidglass-tab/files/src/app/(tabs)/_layout.tsx +97 -0
  192. package/registry/liquidglass-tab/files/src/app/(tabs)/alerts.tsx +5 -0
  193. package/registry/liquidglass-tab/files/src/app/(tabs)/explore.tsx +5 -0
  194. package/registry/liquidglass-tab/files/src/app/(tabs)/index.tsx +5 -0
  195. package/registry/liquidglass-tab/files/src/app/(tabs)/profile.tsx +5 -0
  196. package/registry/liquidglass-tab/files/src/app/_layout.tsx +33 -0
  197. package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +259 -0
  198. package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +122 -0
  199. package/registry/liquidglass-tab/files/src/lib/tab-bar.ts +61 -0
  200. package/registry/liquidglass-tab/files/src/lib/tab-icons.ts +130 -0
  201. package/registry/liquidglass-tab/files/src/lib/tabs.ts +108 -0
  202. package/registry/liquidglass-tab.json +23 -0
  203. package/registry/list-item/files/src/components/ui/list-item.tsx +508 -0
  204. package/registry/list-item/files/src/lib/kit.tsx +219 -0
  205. package/registry/list-item.json +17 -0
  206. package/registry/loyalty-card.json +23 -0
  207. package/registry/morph-button.json +18 -0
  208. package/registry/number-ticker.json +15 -0
  209. package/registry/offers.json +24 -0
  210. package/registry/onboarding.json +17 -0
  211. package/registry/otp-input/files/src/components/ui/otp-input.tsx +380 -0
  212. package/registry/otp-input/files/src/lib/kit.tsx +219 -0
  213. package/registry/otp-input.json +17 -0
  214. package/registry/pagination-dots/files/src/components/ui/pagination-dots.tsx +262 -0
  215. package/registry/pagination-dots/files/src/lib/kit.tsx +219 -0
  216. package/registry/pagination-dots.json +15 -0
  217. package/registry/parallax-layers.json +15 -0
  218. package/registry/parallax-scroll.json +17 -0
  219. package/registry/password-input/files/src/components/ui/floating-input.tsx +528 -0
  220. package/registry/password-input/files/src/components/ui/password-input.tsx +271 -0
  221. package/registry/password-input/files/src/lib/kit.tsx +219 -0
  222. package/registry/password-input.json +19 -0
  223. package/registry/payment-card/files/src/components/ui/flip-card.tsx +205 -0
  224. package/registry/payment-card/files/src/components/ui/payment-card.tsx +385 -0
  225. package/registry/payment-card/files/src/components/ui/tilt-card.tsx +635 -0
  226. package/registry/payment-card/files/src/lib/kit.tsx +219 -0
  227. package/registry/payment-card.json +21 -0
  228. package/registry/pixel-bar.json +14 -0
  229. package/registry/polar-area.json +14 -0
  230. package/registry/profile.json +17 -0
  231. package/registry/progress/files/src/components/ui/progress.tsx +883 -0
  232. package/registry/progress/files/src/lib/kit.tsx +219 -0
  233. package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +559 -0
  234. package/registry/progress-steps/files/src/lib/kit.tsx +219 -0
  235. package/registry/progress-steps.json +18 -0
  236. package/registry/progress.json +17 -0
  237. package/registry/radio-group/files/src/components/ui/radio-group.tsx +327 -0
  238. package/registry/radio-group/files/src/lib/kit.tsx +219 -0
  239. package/registry/radio-group.json +18 -0
  240. package/registry/rating.json +18 -0
  241. package/registry/ring-carousel.json +15 -0
  242. package/registry/scratch-card.json +18 -0
  243. package/registry/search-bar/files/src/components/ui/search-bar.tsx +530 -0
  244. package/registry/search-bar/files/src/lib/kit.tsx +219 -0
  245. package/registry/search-bar.json +17 -0
  246. package/registry/search-results.json +30 -0
  247. package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +341 -0
  248. package/registry/segmented-control/files/src/lib/kit.tsx +219 -0
  249. package/registry/segmented-control.json +18 -0
  250. package/registry/select/files/src/components/ui/select.tsx +1398 -0
  251. package/registry/select/files/src/lib/kit.tsx +219 -0
  252. package/registry/select.json +17 -0
  253. package/registry/settings.json +26 -0
  254. package/registry/shimmer-button.json +17 -0
  255. package/registry/sign-in.json +26 -0
  256. package/registry/skeleton/files/src/components/ui/skeleton.tsx +799 -0
  257. package/registry/skeleton/files/src/lib/kit.tsx +219 -0
  258. package/registry/skeleton.json +17 -0
  259. package/registry/slide-to-confirm.json +18 -0
  260. package/registry/slider/files/src/components/ui/slider.tsx +716 -0
  261. package/registry/slider/files/src/lib/kit.tsx +219 -0
  262. package/registry/slider.json +17 -0
  263. package/registry/spin-wheel.json +18 -0
  264. package/registry/spinner/files/src/components/ui/spinner.tsx +748 -0
  265. package/registry/spinner/files/src/lib/kit.tsx +219 -0
  266. package/registry/spinner.json +17 -0
  267. package/registry/stateful-button/files/src/components/ui/stateful-button.tsx +532 -0
  268. package/registry/stateful-button/files/src/lib/kit.tsx +219 -0
  269. package/registry/stateful-button.json +18 -0
  270. package/registry/stepper/files/src/components/ui/stepper.tsx +646 -0
  271. package/registry/stepper/files/src/lib/kit.tsx +219 -0
  272. package/registry/stepper.json +17 -0
  273. package/registry/swipe-deck.json +15 -0
  274. package/registry/swipeable-row.json +15 -0
  275. package/registry/switch/files/src/components/ui/switch.tsx +344 -0
  276. package/registry/switch/files/src/lib/kit.tsx +219 -0
  277. package/registry/switch.json +18 -0
  278. package/registry/tabs/files/src/components/ui/tabs.tsx +539 -0
  279. package/registry/tabs/files/src/lib/kit.tsx +219 -0
  280. package/registry/tabs.json +17 -0
  281. package/registry/tag-input/files/src/components/ui/tag-input.tsx +720 -0
  282. package/registry/tag-input/files/src/lib/kit.tsx +219 -0
  283. package/registry/tag-input.json +17 -0
  284. package/registry/text-animation/files/src/components/ui/text-animation.tsx +650 -0
  285. package/registry/text-animation/files/src/lib/kit.tsx +219 -0
  286. package/registry/text-animation.json +15 -0
  287. package/registry/textarea/files/src/components/ui/textarea.tsx +553 -0
  288. package/registry/textarea/files/src/lib/kit.tsx +219 -0
  289. package/registry/textarea.json +17 -0
  290. package/registry/ticket-card.json +24 -0
  291. package/registry/ticket-shape/files/src/lib/kit.tsx +219 -0
  292. package/registry/ticket-shape/files/src/lib/ticket-shape.tsx +543 -0
  293. package/registry/ticket-shape.json +17 -0
  294. package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +635 -0
  295. package/registry/tilt-card/files/src/lib/kit.tsx +219 -0
  296. package/registry/tilt-card.json +17 -0
  297. package/registry/time-picker/files/src/components/ui/time-picker.tsx +1159 -0
  298. package/registry/time-picker/files/src/lib/kit.tsx +219 -0
  299. package/registry/time-picker.json +17 -0
  300. package/registry/timeline/files/src/components/ui/avatar.tsx +790 -0
  301. package/registry/timeline/files/src/components/ui/timeline.tsx +1059 -0
  302. package/registry/timeline/files/src/lib/kit.tsx +219 -0
  303. package/registry/timeline-chart.json +14 -0
  304. package/registry/timeline.json +20 -0
  305. package/registry/toast/files/src/components/ui/button.tsx +274 -0
  306. package/registry/toast/files/src/components/ui/toast.tsx +1284 -0
  307. package/registry/toast/files/src/lib/kit.tsx +219 -0
  308. package/registry/toast.json +20 -0
  309. package/registry/treemap.json +14 -0
  310. package/registry/waterfall.json +14 -0
  311. package/registry/wheel-list.json +17 -0
  312. package/schema/components.schema.json +13 -0
@@ -0,0 +1,61 @@
1
+ import { useCallback, useRef } from 'react';
2
+ import {
3
+ Animated,
4
+ Platform,
5
+ type NativeScrollEvent,
6
+ type NativeSyntheticEvent,
7
+ } from 'react-native';
8
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
9
+ import { isLiquidGlassAvailable } from 'expo-glass-effect';
10
+
11
+ import { TAB_BAR } from '@/lib/tabs';
12
+
13
+ /**
14
+ * Which tab bar this device gets:
15
+ * - iOS 26+ (built with Xcode 26) → system NativeTabs with real Liquid Glass.
16
+ * - iOS 18 and older, Android, web → <GlassTabBar />, a floating blur pill that
17
+ * mimics Liquid Glass and collapses on scroll the same way.
18
+ * Set TAB_BAR.legacy = 'native' to use plain system tabs on older OS versions instead.
19
+ */
20
+ export const USE_NATIVE_TABS =
21
+ Platform.OS !== 'web' &&
22
+ ((Platform.OS === 'ios' && isLiquidGlassAvailable()) || TAB_BAR.legacy === 'native');
23
+
24
+ export const GLASS_BAR_HEIGHT = 64;
25
+
26
+ /** 0 = expanded, 1 = collapsed into a circle. Shared by every tab screen. */
27
+ export const tabBarCollapse = new Animated.Value(0);
28
+ let collapsed = false;
29
+
30
+ export function setTabBarCollapsed(next: boolean) {
31
+ if (next === collapsed) return;
32
+ collapsed = next;
33
+ Animated.spring(tabBarCollapse, {
34
+ toValue: next ? 1 : 0,
35
+ useNativeDriver: false,
36
+ damping: 20,
37
+ stiffness: 220,
38
+ mass: 0.9,
39
+ }).start();
40
+ }
41
+
42
+ /** Pass to your ScrollView's onScroll — drives the collapse on the glass fallback bar. */
43
+ export function useTabBarScroll() {
44
+ const last = useRef(0);
45
+ return useCallback((e: NativeSyntheticEvent<NativeScrollEvent>) => {
46
+ if (USE_NATIVE_TABS || TAB_BAR.minimizeBehavior === 'never') return;
47
+ const y = e.nativeEvent.contentOffset.y;
48
+ const dy = y - last.current;
49
+ last.current = y;
50
+ const down = TAB_BAR.minimizeBehavior === 'onScrollUp' ? dy < 0 : dy > 0;
51
+ if (y < 24) setTabBarCollapsed(false);
52
+ else if (Math.abs(dy) > 6) setTabBarCollapsed(down);
53
+ }, []);
54
+ }
55
+
56
+ /** Bottom padding a scrolling screen needs so its last row clears the floating bar. */
57
+ export function useTabBarInset() {
58
+ const insets = useSafeAreaInsets();
59
+ if (USE_NATIVE_TABS) return 24;
60
+ return GLASS_BAR_HEIGHT + Math.max(insets.bottom, 12) + 24;
61
+ }
@@ -0,0 +1,130 @@
1
+ import AntDesign from '@expo/vector-icons/AntDesign';
2
+ import Entypo from '@expo/vector-icons/Entypo';
3
+ import Feather from '@expo/vector-icons/Feather';
4
+ import FontAwesome from '@expo/vector-icons/FontAwesome';
5
+ import FontAwesome5 from '@expo/vector-icons/FontAwesome5';
6
+ import Ionicons from '@expo/vector-icons/Ionicons';
7
+ import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
8
+ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
9
+ import Octicons from '@expo/vector-icons/Octicons';
10
+ import {
11
+ createIconSet,
12
+ createIconSetFromIcoMoon,
13
+ } from '@expo/vector-icons';
14
+ import type { ColorValue, ImageSourcePropType } from 'react-native';
15
+
16
+ /**
17
+ * Native UITabBar can only show icon fonts or PNG/WebP — not SVG React components.
18
+ *
19
+ * Preset sets (no import needed): Ionicons, Feather, FontAwesome, …
20
+ * Custom font: iconFont() / icoMoon()
21
+ * Custom module: library + icon on TabItem
22
+ * PNG: src on TabItem
23
+ */
24
+
25
+ export type IconSetName =
26
+ | 'Ionicons'
27
+ | 'Feather'
28
+ | 'FontAwesome'
29
+ | 'FontAwesome5'
30
+ | 'MaterialCommunityIcons'
31
+ | 'MaterialIcons'
32
+ | 'AntDesign'
33
+ | 'Entypo'
34
+ | 'Octicons';
35
+
36
+ export const ICON_SETS: Record<IconSetName, unknown> = {
37
+ Ionicons,
38
+ Feather,
39
+ FontAwesome,
40
+ FontAwesome5,
41
+ MaterialCommunityIcons,
42
+ MaterialIcons,
43
+ AntDesign,
44
+ Entypo,
45
+ Octicons,
46
+ };
47
+
48
+ export interface TabIconPreset {
49
+ set: IconSetName;
50
+ name: string;
51
+ selected?: string;
52
+ }
53
+
54
+ export type VectorIconFamily = {
55
+ getImageSource: (
56
+ name: string,
57
+ size: number,
58
+ color: ColorValue
59
+ ) => Promise<ImageSourcePropType | null>;
60
+ };
61
+
62
+ export function asFamily(mod: unknown): VectorIconFamily {
63
+ if (mod == null) {
64
+ throw new Error('[expo-kit] Missing icon library. Set `icon.set` or `library` on the tab.');
65
+ }
66
+
67
+ const pack = mod as {
68
+ getImageSource?: VectorIconFamily['getImageSource'];
69
+ getImageSourceSync?: (
70
+ name: string,
71
+ size: number,
72
+ color: ColorValue
73
+ ) => ImageSourcePropType | null;
74
+ };
75
+
76
+ if (typeof pack.getImageSource === 'function') {
77
+ return { getImageSource: pack.getImageSource.bind(pack) };
78
+ }
79
+
80
+ if (typeof pack.getImageSourceSync === 'function') {
81
+ return {
82
+ getImageSource: async (name, size, color) =>
83
+ pack.getImageSourceSync!(name, size, color),
84
+ };
85
+ }
86
+
87
+ throw new Error(
88
+ '[expo-kit] This icon package has no getImageSource (SVG kits like Hugeicons, Tabler, Lucide).\n' +
89
+ 'Use icon.set preset, src PNG, iconFont(), or icoMoon().'
90
+ );
91
+ }
92
+
93
+ export function resolveIconLibrary(tab: {
94
+ icon?: TabIconPreset;
95
+ library?: unknown;
96
+ }): unknown | undefined {
97
+ if (tab.library) return tab.library;
98
+ if (tab.icon?.set) return ICON_SETS[tab.icon.set];
99
+ return undefined;
100
+ }
101
+
102
+ export function resolveIconNames(tab: {
103
+ icon?: TabIconPreset;
104
+ iconName?: string;
105
+ iconSelected?: string;
106
+ }): { name?: string; selected?: string } {
107
+ if (tab.icon?.name) {
108
+ return { name: tab.icon.name, selected: tab.icon.selected };
109
+ }
110
+ if (tab.iconName) {
111
+ return { name: tab.iconName, selected: tab.iconSelected };
112
+ }
113
+ return {};
114
+ }
115
+
116
+ export function iconFont(
117
+ glyphMap: Record<string, number | string>,
118
+ fontFamily: string,
119
+ fontAsset: number | string
120
+ ): VectorIconFamily {
121
+ return asFamily(createIconSet(glyphMap, fontFamily, fontAsset));
122
+ }
123
+
124
+ export function icoMoon(
125
+ selectionJson: unknown,
126
+ fontFamily: string,
127
+ fontAsset: number | string
128
+ ): VectorIconFamily {
129
+ return asFamily(createIconSetFromIcoMoon(selectionJson, fontFamily, fontAsset));
130
+ }
@@ -0,0 +1,108 @@
1
+ import type { ImageSourcePropType } from 'react-native';
2
+
3
+ import type { TabIconPreset } from '@/lib/tab-icons';
4
+
5
+ export {
6
+ asFamily,
7
+ ICON_SETS,
8
+ iconFont,
9
+ icoMoon,
10
+ resolveIconLibrary,
11
+ resolveIconNames,
12
+ } from '@/lib/tab-icons';
13
+ export type { IconSetName, TabIconPreset } from '@/lib/tab-icons';
14
+
15
+ /**
16
+ * Edit this file only — tabs, labels, icons, colors, and screen copy.
17
+ * Each tab needs a route file: src/app/(tabs)/{name}.tsx (use TabScreenFromConfig).
18
+ *
19
+ * Icons (pick one per tab):
20
+ * icon: { set: 'Ionicons', name: 'home-outline', selected: 'home' }
21
+ * library + iconName (any package with getImageSource)
22
+ * src: require('../assets/icon.png')
23
+ */
24
+
25
+ export interface TabItem {
26
+ /** Route name — file under (tabs)/ must match (e.g. index, explore) */
27
+ name: string;
28
+ title: string;
29
+ description?: string;
30
+ accent?: string;
31
+ hidden?: boolean;
32
+ hiddenLabel?: boolean;
33
+ badge?: string;
34
+ sf?: string | { default: string; selected: string };
35
+ /** Preset — no import needed */
36
+ icon?: TabIconPreset;
37
+ /** Advanced — any icon-font module or iconFont() / icoMoon() */
38
+ library?: unknown;
39
+ iconName?: string;
40
+ iconSelected?: string;
41
+ src?:
42
+ | ImageSourcePropType
43
+ | { default: ImageSourcePropType; selected: ImageSourcePropType };
44
+ }
45
+
46
+ export const TAB_BAR = {
47
+ /** 'automatic' | 'never' | 'onScrollDown' | 'onScrollUp' — the glass fallback supports all but 'automatic' (treated as onScrollDown). */
48
+ minimizeBehavior: 'onScrollDown' as 'automatic' | 'never' | 'onScrollDown' | 'onScrollUp',
49
+ /**
50
+ * What to show where Liquid Glass is unavailable (iOS 18 and older, Android, web):
51
+ * 'glass' → floating blur pill that looks and collapses like Liquid Glass (default)
52
+ * 'native' → plain system tab bar (UITabBar / Material bottom navigation)
53
+ */
54
+ legacy: 'glass' as 'glass' | 'native',
55
+ /** 'auto' | 'selected' | 'labeled' | 'unlabeled' */
56
+ labelVisibilityMode: 'labeled' as 'auto' | 'selected' | 'labeled' | 'unlabeled',
57
+ /** null = transparent — only the floating glass pill shows (no solid bar fill). */
58
+ backgroundColor: null as null,
59
+ colors: {
60
+ tint: { light: '#007AFF', dark: '#0A84FF' },
61
+ inactive: { light: 'rgba(60,60,67,0.6)', dark: 'rgba(235,235,245,0.6)' },
62
+ },
63
+ labelStyle: {
64
+ fontSize: 10,
65
+ fontWeight: '400' as const,
66
+ selectedFontWeight: '500' as const,
67
+ },
68
+ };
69
+
70
+ export const TABS: TabItem[] = [
71
+ {
72
+ name: 'index',
73
+ title: 'Home',
74
+ description:
75
+ 'Scroll down — the glass tab bar collapses into a circle. Scroll up to expand all tabs again.',
76
+ accent: '#6366f1',
77
+ sf: { default: 'house', selected: 'house.fill' },
78
+ icon: { set: 'Ionicons', name: 'home-outline', selected: 'home' },
79
+ },
80
+ {
81
+ name: 'explore',
82
+ title: 'Explore',
83
+ description: 'Same collapse on this tab — only Explore stays as a glass circle when scrolling.',
84
+ accent: '#8b5cf6',
85
+ sf: { default: 'square.grid.2x2', selected: 'square.grid.2x2.fill' },
86
+ icon: { set: 'MaterialCommunityIcons', name: 'view-grid-outline', selected: 'view-grid' },
87
+ },
88
+ {
89
+ name: 'alerts',
90
+ title: 'Alerts',
91
+ description: 'Every tab minimizes the same way. The active tab remains in the corner.',
92
+ accent: '#0ea5e9',
93
+ sf: { default: 'bell', selected: 'bell.fill' },
94
+ icon: { set: 'Feather', name: 'bell' },
95
+ },
96
+ {
97
+ name: 'profile',
98
+ title: 'You',
99
+ description: 'Change everything in src/lib/tabs.ts — icons, labels, colors, and screen text.',
100
+ accent: '#10b981',
101
+ sf: { default: 'person.circle', selected: 'person.circle.fill' },
102
+ icon: { set: 'FontAwesome', name: 'user-circle-o', selected: 'user-circle' },
103
+ },
104
+ ];
105
+
106
+ export function getTab(name: string) {
107
+ return TABS.find((tab) => tab.name === name);
108
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "liquidglass-tab",
3
+ "type": "template",
4
+ "title": "Native bottom tabs (Liquid Glass)",
5
+ "description": "Real Liquid Glass NativeTabs on iOS 26+, and a floating blur glass tab bar with the same scroll-collapse on iOS 18 and older, Android and web.",
6
+ "tier": "free",
7
+ "dependencies": [
8
+ "expo-router",
9
+ "expo-glass-effect",
10
+ "expo-blur",
11
+ "expo-haptics",
12
+ "expo-splash-screen",
13
+ "@expo/vector-icons",
14
+ "react-native-gesture-handler",
15
+ "react-native-safe-area-context",
16
+ "react-native-screens",
17
+ "react-native-reanimated",
18
+ "react-native-worklets"
19
+ ],
20
+ "registryDependencies": [],
21
+ "sharedFiles": [],
22
+ "filesDir": "liquidglass-tab/files"
23
+ }