@expokit/cli 0.0.0-stage → 0.2.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 (302) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -2
  3. package/bin/expo-kit.js +1204 -0
  4. package/bin/lib.mjs +343 -0
  5. package/bin/mcp.mjs +338 -0
  6. package/package.json +44 -4
  7. package/registry/_docs/accordion.json +99 -0
  8. package/registry/_docs/action-sheet.json +110 -0
  9. package/registry/_docs/alert.json +127 -0
  10. package/registry/_docs/avatar.json +203 -0
  11. package/registry/_docs/badge.json +117 -0
  12. package/registry/_docs/bottom-nav.json +119 -0
  13. package/registry/_docs/bottom-sheet.json +158 -0
  14. package/registry/_docs/bullet.json +24 -0
  15. package/registry/_docs/button-3d.json +122 -0
  16. package/registry/_docs/button.json +115 -0
  17. package/registry/_docs/calendar.json +182 -0
  18. package/registry/_docs/card-stack.json +108 -0
  19. package/registry/_docs/card.json +111 -0
  20. package/registry/_docs/carousel.json +102 -0
  21. package/registry/_docs/checkbox.json +93 -0
  22. package/registry/_docs/checkout.json +102 -0
  23. package/registry/_docs/chip-group.json +116 -0
  24. package/registry/_docs/color-swatch.json +66 -0
  25. package/registry/_docs/confetti.json +82 -0
  26. package/registry/_docs/coupon.json +176 -0
  27. package/registry/_docs/cube-pager.json +84 -0
  28. package/registry/_docs/dashboard.json +120 -0
  29. package/registry/_docs/date-picker.json +249 -0
  30. package/registry/_docs/dialog.json +162 -0
  31. package/registry/_docs/drawer.json +171 -0
  32. package/registry/_docs/fab.json +120 -0
  33. package/registry/_docs/flip-card.json +111 -0
  34. package/registry/_docs/floating-input.json +191 -0
  35. package/registry/_docs/gift-card.json +108 -0
  36. package/registry/_docs/glass-button.json +118 -0
  37. package/registry/_docs/glass-nav-bar.json +78 -0
  38. package/registry/_docs/glass-search-bar.json +90 -0
  39. package/registry/_docs/glass-segmented.json +66 -0
  40. package/registry/_docs/glass-sheet.json +108 -0
  41. package/registry/_docs/glass-tab-bar.json +76 -0
  42. package/registry/_docs/glass.json +78 -0
  43. package/registry/_docs/inbox.json +72 -0
  44. package/registry/_docs/isometric-bar.json +72 -0
  45. package/registry/_docs/kit.json +11 -0
  46. package/registry/_docs/kpi-card.json +11 -0
  47. package/registry/_docs/like-button.json +72 -0
  48. package/registry/_docs/liquidglass-tab.json +27 -0
  49. package/registry/_docs/list-item.json +200 -0
  50. package/registry/_docs/loyalty-card.json +108 -0
  51. package/registry/_docs/morph-button.json +108 -0
  52. package/registry/_docs/number-ticker.json +96 -0
  53. package/registry/_docs/offers.json +78 -0
  54. package/registry/_docs/onboarding.json +66 -0
  55. package/registry/_docs/otp-input.json +134 -0
  56. package/registry/_docs/pagination-dots.json +88 -0
  57. package/registry/_docs/parallax-layers.json +84 -0
  58. package/registry/_docs/parallax-scroll.json +186 -0
  59. package/registry/_docs/password-input.json +92 -0
  60. package/registry/_docs/payment-card.json +153 -0
  61. package/registry/_docs/pixel-bar.json +66 -0
  62. package/registry/_docs/polar-area.json +78 -0
  63. package/registry/_docs/profile.json +84 -0
  64. package/registry/_docs/progress-steps.json +92 -0
  65. package/registry/_docs/progress.json +132 -0
  66. package/registry/_docs/radio-group.json +92 -0
  67. package/registry/_docs/rating.json +90 -0
  68. package/registry/_docs/ring-carousel.json +102 -0
  69. package/registry/_docs/scratch-card.json +90 -0
  70. package/registry/_docs/search-bar.json +140 -0
  71. package/registry/_docs/search-results.json +120 -0
  72. package/registry/_docs/segmented-control.json +103 -0
  73. package/registry/_docs/select.json +252 -0
  74. package/registry/_docs/settings.json +72 -0
  75. package/registry/_docs/shimmer-button.json +78 -0
  76. package/registry/_docs/sign-in.json +198 -0
  77. package/registry/_docs/skeleton.json +142 -0
  78. package/registry/_docs/slide-to-confirm.json +84 -0
  79. package/registry/_docs/slider.json +157 -0
  80. package/registry/_docs/spin-wheel.json +114 -0
  81. package/registry/_docs/spinner.json +91 -0
  82. package/registry/_docs/stepper.json +168 -0
  83. package/registry/_docs/swipe-deck.json +102 -0
  84. package/registry/_docs/swipeable-row.json +72 -0
  85. package/registry/_docs/switch.json +104 -0
  86. package/registry/_docs/tabs.json +105 -0
  87. package/registry/_docs/tag-input.json +128 -0
  88. package/registry/_docs/textarea.json +175 -0
  89. package/registry/_docs/ticket-card.json +174 -0
  90. package/registry/_docs/ticket-shape.json +11 -0
  91. package/registry/_docs/tilt-card.json +141 -0
  92. package/registry/_docs/time-picker.json +253 -0
  93. package/registry/_docs/timeline-chart.json +30 -0
  94. package/registry/_docs/timeline.json +156 -0
  95. package/registry/_docs/toast.json +161 -0
  96. package/registry/_docs/treemap.json +30 -0
  97. package/registry/_docs/waterfall.json +36 -0
  98. package/registry/_docs/wheel-list.json +102 -0
  99. package/registry/accordion/files/src/components/ui/accordion.tsx +233 -0
  100. package/registry/accordion/files/src/lib/kit.tsx +219 -0
  101. package/registry/accordion.json +17 -0
  102. package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +580 -0
  103. package/registry/action-sheet/files/src/lib/kit.tsx +219 -0
  104. package/registry/action-sheet.json +18 -0
  105. package/registry/alert/files/src/components/ui/alert.tsx +654 -0
  106. package/registry/alert/files/src/components/ui/button.tsx +274 -0
  107. package/registry/alert/files/src/lib/kit.tsx +219 -0
  108. package/registry/alert.json +20 -0
  109. package/registry/avatar/files/src/components/ui/avatar.tsx +790 -0
  110. package/registry/avatar/files/src/lib/kit.tsx +219 -0
  111. package/registry/avatar.json +18 -0
  112. package/registry/badge/files/src/components/ui/badge.tsx +316 -0
  113. package/registry/badge/files/src/lib/kit.tsx +219 -0
  114. package/registry/badge.json +17 -0
  115. package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +1050 -0
  116. package/registry/bottom-nav/files/src/lib/kit.tsx +219 -0
  117. package/registry/bottom-nav.json +18 -0
  118. package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +585 -0
  119. package/registry/bottom-sheet/files/src/lib/kit.tsx +219 -0
  120. package/registry/bottom-sheet.json +17 -0
  121. package/registry/bullet.json +14 -0
  122. package/registry/button/files/src/components/ui/button.tsx +274 -0
  123. package/registry/button/files/src/lib/kit.tsx +219 -0
  124. package/registry/button-3d/files/src/components/ui/button-3d.tsx +212 -0
  125. package/registry/button-3d/files/src/lib/kit.tsx +219 -0
  126. package/registry/button-3d.json +18 -0
  127. package/registry/button.json +18 -0
  128. package/registry/calendar/files/src/components/ui/calendar.tsx +822 -0
  129. package/registry/calendar/files/src/lib/kit.tsx +219 -0
  130. package/registry/calendar.json +17 -0
  131. package/registry/card/files/src/components/ui/card.tsx +300 -0
  132. package/registry/card/files/src/lib/kit.tsx +219 -0
  133. package/registry/card-stack.json +15 -0
  134. package/registry/card.json +17 -0
  135. package/registry/carousel.json +15 -0
  136. package/registry/checkbox/files/src/components/ui/checkbox.tsx +150 -0
  137. package/registry/checkbox/files/src/lib/kit.tsx +219 -0
  138. package/registry/checkbox.json +17 -0
  139. package/registry/checkout.json +26 -0
  140. package/registry/chip-group/files/src/components/ui/chip-group.tsx +269 -0
  141. package/registry/chip-group/files/src/lib/kit.tsx +219 -0
  142. package/registry/chip-group.json +17 -0
  143. package/registry/color-swatch.json +17 -0
  144. package/registry/confetti/files/src/components/ui/confetti.tsx +222 -0
  145. package/registry/confetti/files/src/lib/kit.tsx +219 -0
  146. package/registry/confetti.json +15 -0
  147. package/registry/coupon/files/src/components/ui/coupon.tsx +698 -0
  148. package/registry/coupon/files/src/components/ui/flip-card.tsx +205 -0
  149. package/registry/coupon/files/src/components/ui/tilt-card.tsx +635 -0
  150. package/registry/coupon/files/src/lib/kit.tsx +219 -0
  151. package/registry/coupon/files/src/lib/ticket-shape.tsx +543 -0
  152. package/registry/coupon.json +23 -0
  153. package/registry/cube-pager.json +15 -0
  154. package/registry/dashboard.json +32 -0
  155. package/registry/date-picker/files/src/components/ui/calendar.tsx +822 -0
  156. package/registry/date-picker/files/src/components/ui/date-picker.tsx +796 -0
  157. package/registry/date-picker/files/src/lib/kit.tsx +219 -0
  158. package/registry/date-picker.json +19 -0
  159. package/registry/dialog/files/src/components/ui/dialog.tsx +759 -0
  160. package/registry/dialog/files/src/lib/kit.tsx +219 -0
  161. package/registry/dialog.json +18 -0
  162. package/registry/drawer/files/src/components/ui/drawer.tsx +1135 -0
  163. package/registry/drawer/files/src/lib/kit.tsx +219 -0
  164. package/registry/drawer.json +18 -0
  165. package/registry/fab.json +18 -0
  166. package/registry/flip-card/files/src/components/ui/flip-card.tsx +205 -0
  167. package/registry/flip-card/files/src/lib/kit.tsx +219 -0
  168. package/registry/flip-card.json +15 -0
  169. package/registry/floating-input/files/src/components/ui/floating-input.tsx +528 -0
  170. package/registry/floating-input/files/src/lib/kit.tsx +219 -0
  171. package/registry/floating-input.json +17 -0
  172. package/registry/gift-card.json +21 -0
  173. package/registry/glass-button.json +22 -0
  174. package/registry/glass-nav-bar.json +21 -0
  175. package/registry/glass-search-bar.json +21 -0
  176. package/registry/glass-segmented.json +22 -0
  177. package/registry/glass-sheet.json +22 -0
  178. package/registry/glass-tab-bar.json +22 -0
  179. package/registry/glass.json +19 -0
  180. package/registry/inbox.json +30 -0
  181. package/registry/isometric-bar.json +14 -0
  182. package/registry/kit/files/src/lib/kit.tsx +219 -0
  183. package/registry/kit.json +11 -0
  184. package/registry/kpi-card/files/src/components/charts/kpi-card.tsx +45 -0
  185. package/registry/kpi-card.json +14 -0
  186. package/registry/like-button.json +18 -0
  187. package/registry/liquidglass-tab/files/src/app/(tabs)/_layout.tsx +97 -0
  188. package/registry/liquidglass-tab/files/src/app/(tabs)/alerts.tsx +5 -0
  189. package/registry/liquidglass-tab/files/src/app/(tabs)/explore.tsx +5 -0
  190. package/registry/liquidglass-tab/files/src/app/(tabs)/index.tsx +5 -0
  191. package/registry/liquidglass-tab/files/src/app/(tabs)/profile.tsx +5 -0
  192. package/registry/liquidglass-tab/files/src/app/_layout.tsx +33 -0
  193. package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +259 -0
  194. package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +122 -0
  195. package/registry/liquidglass-tab/files/src/lib/tab-bar.ts +61 -0
  196. package/registry/liquidglass-tab/files/src/lib/tab-icons.ts +130 -0
  197. package/registry/liquidglass-tab/files/src/lib/tabs.ts +108 -0
  198. package/registry/liquidglass-tab.json +23 -0
  199. package/registry/list-item/files/src/components/ui/list-item.tsx +508 -0
  200. package/registry/list-item/files/src/lib/kit.tsx +219 -0
  201. package/registry/list-item.json +17 -0
  202. package/registry/loyalty-card.json +23 -0
  203. package/registry/morph-button.json +18 -0
  204. package/registry/number-ticker.json +15 -0
  205. package/registry/offers.json +24 -0
  206. package/registry/onboarding.json +17 -0
  207. package/registry/otp-input/files/src/components/ui/otp-input.tsx +380 -0
  208. package/registry/otp-input/files/src/lib/kit.tsx +219 -0
  209. package/registry/otp-input.json +17 -0
  210. package/registry/pagination-dots/files/src/components/ui/pagination-dots.tsx +262 -0
  211. package/registry/pagination-dots/files/src/lib/kit.tsx +219 -0
  212. package/registry/pagination-dots.json +15 -0
  213. package/registry/parallax-layers.json +15 -0
  214. package/registry/parallax-scroll.json +17 -0
  215. package/registry/password-input/files/src/components/ui/floating-input.tsx +528 -0
  216. package/registry/password-input/files/src/components/ui/password-input.tsx +271 -0
  217. package/registry/password-input/files/src/lib/kit.tsx +219 -0
  218. package/registry/password-input.json +19 -0
  219. package/registry/payment-card/files/src/components/ui/flip-card.tsx +205 -0
  220. package/registry/payment-card/files/src/components/ui/payment-card.tsx +385 -0
  221. package/registry/payment-card/files/src/components/ui/tilt-card.tsx +635 -0
  222. package/registry/payment-card/files/src/lib/kit.tsx +219 -0
  223. package/registry/payment-card.json +21 -0
  224. package/registry/pixel-bar.json +14 -0
  225. package/registry/polar-area.json +14 -0
  226. package/registry/profile.json +17 -0
  227. package/registry/progress/files/src/components/ui/progress.tsx +883 -0
  228. package/registry/progress/files/src/lib/kit.tsx +219 -0
  229. package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +559 -0
  230. package/registry/progress-steps/files/src/lib/kit.tsx +219 -0
  231. package/registry/progress-steps.json +18 -0
  232. package/registry/progress.json +17 -0
  233. package/registry/radio-group/files/src/components/ui/radio-group.tsx +327 -0
  234. package/registry/radio-group/files/src/lib/kit.tsx +219 -0
  235. package/registry/radio-group.json +18 -0
  236. package/registry/rating.json +18 -0
  237. package/registry/ring-carousel.json +15 -0
  238. package/registry/scratch-card.json +18 -0
  239. package/registry/search-bar/files/src/components/ui/search-bar.tsx +530 -0
  240. package/registry/search-bar/files/src/lib/kit.tsx +219 -0
  241. package/registry/search-bar.json +17 -0
  242. package/registry/search-results.json +30 -0
  243. package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +341 -0
  244. package/registry/segmented-control/files/src/lib/kit.tsx +219 -0
  245. package/registry/segmented-control.json +18 -0
  246. package/registry/select/files/src/components/ui/select.tsx +1398 -0
  247. package/registry/select/files/src/lib/kit.tsx +219 -0
  248. package/registry/select.json +17 -0
  249. package/registry/settings.json +26 -0
  250. package/registry/shimmer-button.json +17 -0
  251. package/registry/sign-in.json +26 -0
  252. package/registry/skeleton/files/src/components/ui/skeleton.tsx +799 -0
  253. package/registry/skeleton/files/src/lib/kit.tsx +219 -0
  254. package/registry/skeleton.json +17 -0
  255. package/registry/slide-to-confirm.json +18 -0
  256. package/registry/slider/files/src/components/ui/slider.tsx +716 -0
  257. package/registry/slider/files/src/lib/kit.tsx +219 -0
  258. package/registry/slider.json +17 -0
  259. package/registry/spin-wheel.json +18 -0
  260. package/registry/spinner/files/src/components/ui/spinner.tsx +335 -0
  261. package/registry/spinner/files/src/lib/kit.tsx +219 -0
  262. package/registry/spinner.json +17 -0
  263. package/registry/stepper/files/src/components/ui/stepper.tsx +646 -0
  264. package/registry/stepper/files/src/lib/kit.tsx +219 -0
  265. package/registry/stepper.json +17 -0
  266. package/registry/swipe-deck.json +15 -0
  267. package/registry/swipeable-row.json +15 -0
  268. package/registry/switch/files/src/components/ui/switch.tsx +344 -0
  269. package/registry/switch/files/src/lib/kit.tsx +219 -0
  270. package/registry/switch.json +18 -0
  271. package/registry/tabs/files/src/components/ui/tabs.tsx +539 -0
  272. package/registry/tabs/files/src/lib/kit.tsx +219 -0
  273. package/registry/tabs.json +17 -0
  274. package/registry/tag-input/files/src/components/ui/tag-input.tsx +720 -0
  275. package/registry/tag-input/files/src/lib/kit.tsx +219 -0
  276. package/registry/tag-input.json +17 -0
  277. package/registry/textarea/files/src/components/ui/textarea.tsx +553 -0
  278. package/registry/textarea/files/src/lib/kit.tsx +219 -0
  279. package/registry/textarea.json +17 -0
  280. package/registry/ticket-card.json +24 -0
  281. package/registry/ticket-shape/files/src/lib/kit.tsx +219 -0
  282. package/registry/ticket-shape/files/src/lib/ticket-shape.tsx +543 -0
  283. package/registry/ticket-shape.json +17 -0
  284. package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +635 -0
  285. package/registry/tilt-card/files/src/lib/kit.tsx +219 -0
  286. package/registry/tilt-card.json +17 -0
  287. package/registry/time-picker/files/src/components/ui/time-picker.tsx +1159 -0
  288. package/registry/time-picker/files/src/lib/kit.tsx +219 -0
  289. package/registry/time-picker.json +17 -0
  290. package/registry/timeline/files/src/components/ui/avatar.tsx +790 -0
  291. package/registry/timeline/files/src/components/ui/timeline.tsx +1059 -0
  292. package/registry/timeline/files/src/lib/kit.tsx +219 -0
  293. package/registry/timeline-chart.json +14 -0
  294. package/registry/timeline.json +20 -0
  295. package/registry/toast/files/src/components/ui/button.tsx +274 -0
  296. package/registry/toast/files/src/components/ui/toast.tsx +1284 -0
  297. package/registry/toast/files/src/lib/kit.tsx +219 -0
  298. package/registry/toast.json +20 -0
  299. package/registry/treemap.json +14 -0
  300. package/registry/waterfall.json +14 -0
  301. package/registry/wheel-list.json +17 -0
  302. package/schema/components.schema.json +13 -0
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "button-3d",
3
+ "category": "3D",
4
+ "aliases": [],
5
+ "exportName": "Button3D",
6
+ "files": [
7
+ "src/components/ui/button-3d.tsx"
8
+ ],
9
+ "props": [
10
+ [
11
+ "children",
12
+ "ReactNode",
13
+ "—",
14
+ "Label, a single glyph (circle buttons) or custom content."
15
+ ],
16
+ [
17
+ "onPress",
18
+ "() => void",
19
+ "—",
20
+ "Fires on tap."
21
+ ],
22
+ [
23
+ "appearance",
24
+ "\"auto\" | \"light\" | \"dark\" | \"glass\"",
25
+ "\"auto\"",
26
+ "Keycap material; auto is light on dark screens and dark on light ones. Glass is for buttons on photos."
27
+ ],
28
+ [
29
+ "color",
30
+ "string",
31
+ "—",
32
+ "A custom face colour instead of a material, e.g. your brand colour."
33
+ ],
34
+ [
35
+ "size",
36
+ "\"sm\" | \"md\" | \"lg\"",
37
+ "\"md\"",
38
+ "Height and text size (36 / 46 / 56)."
39
+ ],
40
+ [
41
+ "shape",
42
+ "\"rounded\" | \"pill\" | \"circle\"",
43
+ "\"rounded\"",
44
+ "Keycap, pill or round icon button."
45
+ ],
46
+ [
47
+ "depth",
48
+ "number",
49
+ "4 / 5 / 6 by size",
50
+ "Edge height in points."
51
+ ],
52
+ [
53
+ "icon",
54
+ "ReactNode",
55
+ "—",
56
+ "Shown before the label."
57
+ ],
58
+ [
59
+ "block",
60
+ "boolean",
61
+ "false",
62
+ "Stretch to the parent's width."
63
+ ],
64
+ [
65
+ "loading",
66
+ "boolean",
67
+ "false",
68
+ "Show a spinner and ignore taps."
69
+ ],
70
+ [
71
+ "disabled",
72
+ "boolean",
73
+ "false",
74
+ "Dim the button and ignore taps."
75
+ ],
76
+ [
77
+ "haptics",
78
+ "boolean",
79
+ "true",
80
+ "Light haptic tap on press (iOS / Android)."
81
+ ],
82
+ [
83
+ "accessibilityLabel",
84
+ "string",
85
+ "—",
86
+ "Label for screen readers (needed for icon-only buttons)."
87
+ ],
88
+ [
89
+ "style",
90
+ "StyleProp<ViewStyle>",
91
+ "—",
92
+ "Style for the root (width, margins)."
93
+ ]
94
+ ],
95
+ "examples": [
96
+ {
97
+ "name": "OnPhoto",
98
+ "title": "On Photo",
99
+ "code": "import React, { useState } from 'react';\nimport { Image, Text, View } from 'react-native';\nimport { Button3D } from '@/components/ui/button-3d';\nimport { useKit } from '@/lib/kit';\n\n/** Any photo works (`require()` or a URL). `blur` gives soft, abstract art. */\nconst photo = (id: number, w: number, h: number, blur = false) => ({ uri: `https://picsum.photos/id/${id}/${w}/${h}${blur ? '?blur=10' : ''}` });\n\n/** A screen title, as it sits above the content in your app. */\nfunction Header({ title, sub, right }: { title: string; sub?: string; right?: React.ReactNode }) {\n const { colors } = useKit();\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.foreground, fontSize: 22, fontWeight: '700', letterSpacing: -0.4 }}>{title}</Text>\n {sub ? <Text style={{ color: colors.mutedForeground, fontSize: 13, marginTop: 2 }}>{sub}</Text> : null}\n </View>\n {right}\n </View>\n );\n}\n\nexport default function OnPhoto() {\n const { colors } = useKit();\n return (\n <View style={{ gap: 18 }}>\n <Header\n title=\"Good morning, Maya\"\n sub=\"Your trip starts in 3 days\"\n right={\n <View style={{ width: 40, height: 40, borderRadius: 20, backgroundColor: colors.muted, alignItems: 'center', justifyContent: 'center' }}>\n <Text style={{ color: colors.foreground, fontSize: 14, fontWeight: '700' }}>MP</Text>\n </View>\n }\n />\n <View style={{ height: 440, borderRadius: 28, overflow: 'hidden', backgroundColor: '#1a2a22' }}>\n <Image alt=\"\" source={photo(1039, 700, 880)} style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }} />\n <View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.28)' }} />\n <View style={{ flex: 1, justifyContent: 'flex-end', padding: 22, gap: 16 }}>\n <View>\n <Text style={{ color: 'rgba(255,255,255,0.85)', fontSize: 12, fontWeight: '700', letterSpacing: 1.2 }}>OREGON · 3 DAYS</Text>\n <Text style={{ color: '#fff', fontSize: 30, fontWeight: '800', letterSpacing: -0.8 }}>Multnomah Falls</Text>\n <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: 13, marginTop: 2 }}>Waterfalls, old-growth forest and a lodge by the river</Text>\n </View>\n <View style={{ flexDirection: 'row', gap: 10, alignItems: 'center' }}>\n <Button3D appearance=\"glass\" size=\"lg\" shape=\"pill\" style={{ flex: 1 }} block>\n Start the trip\n </Button3D>\n <Button3D appearance=\"glass\" size=\"lg\" shape=\"circle\" accessibilityLabel=\"Save\">\n ♡\n </Button3D>\n <Button3D appearance=\"glass\" size=\"lg\" shape=\"circle\" accessibilityLabel=\"Share\">\n ↗\n </Button3D>\n </View>\n </View>\n </View>\n </View>\n );\n}\n"
100
+ },
101
+ {
102
+ "name": "Keypad",
103
+ "title": "Keypad",
104
+ "code": "import React, { useState } from 'react';\nimport { Image, Text, View } from 'react-native';\nimport { Button3D } from '@/components/ui/button-3d';\nimport { useKit } from '@/lib/kit';\n\nexport default function Keypad() {\n const { colors } = useKit();\n const [pin, setPin] = useState('');\n const keys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '⌫'];\n return (\n <View style={{ gap: 26, alignItems: 'center' }}>\n <View style={{ alignItems: 'center', gap: 4 }}>\n <Text style={{ color: colors.foreground, fontSize: 22, fontWeight: '700', letterSpacing: -0.4 }}>Enter passcode</Text>\n <Text style={{ color: colors.mutedForeground, fontSize: 13 }}>to unlock Northwind</Text>\n </View>\n <View style={{ flexDirection: 'row', gap: 14 }}>\n {[0, 1, 2, 3].map((i) => (\n <View key={i} style={{ width: 12, height: 12, borderRadius: 6, backgroundColor: i < pin.length ? colors.foreground : colors.border }} />\n ))}\n </View>\n <View style={{ width: 252, flexDirection: 'row', flexWrap: 'wrap', gap: 12, justifyContent: 'center' }}>\n {keys.map((k, i) =>\n k ? (\n <Button3D\n key={k}\n appearance=\"light\"\n size=\"lg\"\n style={{ width: 76 }}\n accessibilityLabel={k === '⌫' ? 'Delete' : k}\n onPress={() => setPin((p) => (k === '⌫' ? p.slice(0, -1) : (p + k).slice(0, 4)))}\n >\n {k}\n </Button3D>\n ) : (\n <View key={`gap-${i}`} style={{ width: 76 }} />\n )\n )}\n </View>\n <Text style={{ color: colors.mutedForeground, fontSize: 13, fontWeight: '500' }}>Forgot passcode?</Text>\n </View>\n );\n}\n"
105
+ },
106
+ {
107
+ "name": "Checkout",
108
+ "title": "Checkout",
109
+ "code": "import React, { useState } from 'react';\nimport { Image, Text, View } from 'react-native';\nimport { Button3D } from '@/components/ui/button-3d';\nimport { useKit } from '@/lib/kit';\n\n/** Any photo works (`require()` or a URL). `blur` gives soft, abstract art. */\nconst photo = (id: number, w: number, h: number, blur = false) => ({ uri: `https://picsum.photos/id/${id}/${w}/${h}${blur ? '?blur=10' : ''}` });\n\n/** A screen title, as it sits above the content in your app. */\nfunction Header({ title, sub, right }: { title: string; sub?: string; right?: React.ReactNode }) {\n const { colors } = useKit();\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.foreground, fontSize: 22, fontWeight: '700', letterSpacing: -0.4 }}>{title}</Text>\n {sub ? <Text style={{ color: colors.mutedForeground, fontSize: 13, marginTop: 2 }}>{sub}</Text> : null}\n </View>\n {right}\n </View>\n );\n}\n\nexport default function Checkout() {\n const { colors } = useKit();\n const [busy, setBusy] = useState(false);\n const items = [\n { img: 766, name: 'House blend beans', detail: '250 g · ×2', price: '₹880' },\n { img: 1060, name: 'Pour-over filters', detail: 'Pack of 100', price: '₹120' },\n ];\n const line = (label: string, value: string, strong = false) => (\n <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>\n <Text style={{ color: strong ? colors.foreground : colors.mutedForeground, fontSize: strong ? 16 : 14, fontWeight: strong ? '700' : '400' }}>{label}</Text>\n <Text style={{ color: colors.foreground, fontSize: strong ? 16 : 14, fontWeight: strong ? '700' : '500' }}>{value}</Text>\n </View>\n );\n return (\n <View style={{ gap: 18 }}>\n <Header title=\"Checkout\" sub=\"2 items · arrives tomorrow\" />\n <View style={{ gap: 12 }}>\n {items.map((it) => (\n <View key={it.name} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <Image alt=\"\" source={photo(it.img, 120, 120)} style={{ width: 52, height: 52, borderRadius: 12, backgroundColor: colors.muted }} />\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.foreground, fontSize: 15, fontWeight: '600' }}>{it.name}</Text>\n <Text style={{ color: colors.mutedForeground, fontSize: 12 }}>{it.detail}</Text>\n </View>\n <Text style={{ color: colors.foreground, fontSize: 14, fontWeight: '600' }}>{it.price}</Text>\n </View>\n ))}\n </View>\n <View style={{ gap: 8, paddingTop: 14, borderTopWidth: 1, borderTopColor: colors.border }}>\n {line('Subtotal', '₹1,000')}\n {line('Express delivery', '₹240')}\n {line('Total', '₹1,240', true)}\n </View>\n <View style={{ gap: 12 }}>\n <Button3D\n block\n size=\"lg\"\n loading={busy}\n onPress={() => {\n setBusy(true);\n setTimeout(() => setBusy(false), 1500);\n }}\n >\n Pay ₹1,240\n </Button3D>\n <Button3D block size=\"md\" color={colors.muted}>\n Add a promo code\n </Button3D>\n </View>\n </View>\n );\n}\n"
110
+ },
111
+ {
112
+ "name": "Keycaps",
113
+ "title": "Keycaps",
114
+ "code": "import React, { useState } from 'react';\nimport { Image, Text, View } from 'react-native';\nimport { Button3D } from '@/components/ui/button-3d';\nimport { useKit } from '@/lib/kit';\n\n/** A screen title, as it sits above the content in your app. */\nfunction Header({ title, sub, right }: { title: string; sub?: string; right?: React.ReactNode }) {\n const { colors } = useKit();\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.foreground, fontSize: 22, fontWeight: '700', letterSpacing: -0.4 }}>{title}</Text>\n {sub ? <Text style={{ color: colors.mutedForeground, fontSize: 13, marginTop: 2 }}>{sub}</Text> : null}\n </View>\n {right}\n </View>\n );\n}\n\nexport default function Keycaps() {\n const row = (keys: [string, number?][], appearance: 'light' | 'dark') => (\n <View style={{ flexDirection: 'row', gap: 8, justifyContent: 'center' }}>\n {keys.map(([k, w]) => (\n <Button3D key={k} appearance={appearance} size=\"lg\" style={{ width: w ?? 56 }} accessibilityLabel={k}>\n {k}\n </Button3D>\n ))}\n </View>\n );\n return (\n <View style={{ gap: 22 }}>\n <Header title=\"Keycaps\" sub=\"Press and hold a key to feel it sink\" />\n <View style={{ gap: 12 }}>\n {row([['esc', 64], ['Q'], ['W'], ['E'], ['R']], 'light')}\n {row([['⌘', 64], ['A'], ['S'], ['D'], ['F']], 'dark')}\n {row([['space', 196], ['↵', 92]], 'light')}\n </View>\n </View>\n );\n}\n"
115
+ },
116
+ {
117
+ "name": "Materials",
118
+ "title": "Materials",
119
+ "code": "import React, { useState } from 'react';\nimport { Image, Text, View } from 'react-native';\nimport { Button3D } from '@/components/ui/button-3d';\nimport { useKit } from '@/lib/kit';\n\n/** Any photo works (`require()` or a URL). `blur` gives soft, abstract art. */\nconst photo = (id: number, w: number, h: number, blur = false) => ({ uri: `https://picsum.photos/id/${id}/${w}/${h}${blur ? '?blur=10' : ''}` });\n\n/** A screen title, as it sits above the content in your app. */\nfunction Header({ title, sub, right }: { title: string; sub?: string; right?: React.ReactNode }) {\n const { colors } = useKit();\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.foreground, fontSize: 22, fontWeight: '700', letterSpacing: -0.4 }}>{title}</Text>\n {sub ? <Text style={{ color: colors.mutedForeground, fontSize: 13, marginTop: 2 }}>{sub}</Text> : null}\n </View>\n {right}\n </View>\n );\n}\n\nexport default function Materials() {\n return (\n <View style={{ gap: 18 }}>\n <Header title=\"Materials\" sub=\"Light, dark, frosted glass — or any colour\" />\n <View style={{ flexDirection: 'row', gap: 10, justifyContent: 'center' }}>\n <Button3D appearance=\"light\">Light</Button3D>\n <Button3D appearance=\"dark\">Dark</Button3D>\n <Button3D color=\"#ff5a5f\">Custom</Button3D>\n </View>\n <View style={{ borderRadius: 22, overflow: 'hidden', padding: 18, alignItems: 'center', backgroundColor: '#3a2b55' }}>\n <Image alt=\"\" source={photo(888, 300, 160, true)} style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }} />\n <View style={{ flexDirection: 'row', gap: 10 }}>\n <Button3D appearance=\"glass\">Glass</Button3D>\n <Button3D appearance=\"glass\" shape=\"pill\">\n On any photo\n </Button3D>\n </View>\n </View>\n </View>\n );\n}\n"
120
+ }
121
+ ]
122
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "button",
3
+ "category": "Buttons",
4
+ "aliases": [],
5
+ "exportName": "Button",
6
+ "files": [
7
+ "src/components/ui/button.tsx"
8
+ ],
9
+ "props": [
10
+ [
11
+ "variant",
12
+ "\"primary\" | \"accent\" | \"secondary\" | \"outline\" | \"ghost\" | \"soft\" | \"destructive\" | \"link\" | \"gradient\" | \"glow\" | \"elevated\"",
13
+ "\"primary\"",
14
+ "Solid primary / accent / secondary / danger fill, bordered outline, transparent ghost, tinted soft, underlined link, two-tone gradient, accent with a coloured glow, or a raised elevated surface."
15
+ ],
16
+ [
17
+ "size",
18
+ "\"sm\" | \"md\" | \"lg\" | \"icon\"",
19
+ "\"md\"",
20
+ "36 / 46 / 54pt, or a round icon button."
21
+ ],
22
+ [
23
+ "loading",
24
+ "boolean",
25
+ "false",
26
+ "Spinner + blocks presses."
27
+ ],
28
+ [
29
+ "left / right",
30
+ "ReactNode",
31
+ "—",
32
+ "Icons beside the label."
33
+ ],
34
+ [
35
+ "block",
36
+ "boolean",
37
+ "false",
38
+ "Stretches to the parent's width (alignSelf: stretch)."
39
+ ],
40
+ [
41
+ "pill",
42
+ "boolean",
43
+ "false",
44
+ "Fully rounded."
45
+ ],
46
+ [
47
+ "color",
48
+ "string",
49
+ "theme accent",
50
+ "Any colour; recolours every tinted variant and picks readable text automatically."
51
+ ],
52
+ [
53
+ "gradientTo",
54
+ "string",
55
+ "color shifted 38° on the hue wheel",
56
+ "Second stop for variant=\"gradient\"."
57
+ ],
58
+ [
59
+ "haptics",
60
+ "boolean",
61
+ "false",
62
+ "Light tap on press."
63
+ ],
64
+ [
65
+ "textStyle",
66
+ "StyleProp<TextStyle>",
67
+ "—",
68
+ "Style for the label text (merged over size and variant typography)."
69
+ ],
70
+ [
71
+ "style",
72
+ "StyleProp<ViewStyle>",
73
+ "—",
74
+ "Style for the outer animated wrapper (margins, alignment); the pressable surface keeps its own."
75
+ ],
76
+ [
77
+ "…PressableProps",
78
+ "",
79
+ "",
80
+ "onPress, disabled, …"
81
+ ]
82
+ ],
83
+ "examples": [
84
+ {
85
+ "name": "Variants",
86
+ "title": "Variants",
87
+ "code": "import { Pressable, Text, View } from 'react-native';\nimport { Button } from '@/components/ui/button';\n\nexport default function Variants() {\n return (\n <View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10 }}>\n <Button>Primary</Button>\n <Button variant=\"accent\">Accent</Button>\n <Button variant=\"secondary\">Secondary</Button>\n <Button variant=\"outline\">Outline</Button>\n <Button variant=\"soft\">Soft</Button>\n <Button variant=\"ghost\">Ghost</Button>\n <Button variant=\"elevated\">Elevated</Button>\n <Button variant=\"destructive\">Delete</Button>\n <Button variant=\"link\">Link</Button>\n </View>\n );\n}\n"
88
+ },
89
+ {
90
+ "name": "GradientAndGlow",
91
+ "title": "Gradient And Glow",
92
+ "code": "import { Pressable, Text, View } from 'react-native';\nimport { Button } from '@/components/ui/button';\nimport { readableOn, useKit } from '@/lib/kit';\n\nexport default function GradientAndGlow() {\n const { colors } = useKit();\n return (\n <View style={{ gap: 12 }}>\n <Button\n variant=\"gradient\"\n size=\"lg\"\n block\n pill\n right={<Text style={{ color: readableOn(colors.accent), fontSize: 18 }}>→</Text>}\n >\n Get started\n </Button>\n <View style={{ flexDirection: 'row', gap: 10 }}>\n <Button variant=\"glow\" pill style={{ flex: 1 }}>\n Go live\n </Button>\n <Button variant=\"gradient\" pill style={{ flex: 1 }}>\n Boost\n </Button>\n </View>\n </View>\n );\n}\n"
93
+ },
94
+ {
95
+ "name": "DynamicColor",
96
+ "title": "Dynamic Color",
97
+ "code": "import React, { useState } from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { Button } from '@/components/ui/button';\nimport { readableOn, useKit } from '@/lib/kit';\n\nconst PALETTE = ['#6366f1', '#10b981', '#f59e0b', '#ef4444', '#0ea5e9', '#ec4899'];\n\nexport default function DynamicColor() {\n const { colors, radius } = useKit();\n const [color, setColor] = useState(PALETTE[0]);\n return (\n <View style={{ gap: 14 }}>\n <View style={{ flexDirection: 'row', gap: 10 }}>\n {PALETTE.map((c) => (\n <Pressable\n key={c}\n onPress={() => setColor(c)}\n accessibilityRole=\"button\"\n accessibilityLabel={`Use ${c}`}\n style={{\n width: 28,\n height: 28,\n borderRadius: radius.full,\n backgroundColor: c,\n borderWidth: 3,\n borderColor: c === color ? colors.foreground : 'transparent',\n }}\n />\n ))}\n </View>\n <View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10 }}>\n <Button variant=\"accent\" color={color}>Accent</Button>\n <Button variant=\"gradient\" color={color}>Gradient</Button>\n <Button variant=\"glow\" color={color}>Glow</Button>\n <Button variant=\"soft\" color={color}>Soft</Button>\n <Button variant=\"outline\" color={color}>Outline</Button>\n <Button variant=\"elevated\" color={color}>Elevated</Button>\n </View>\n </View>\n );\n}\n"
98
+ },
99
+ {
100
+ "name": "Sizes",
101
+ "title": "Sizes",
102
+ "code": "import { Pressable, Text, View } from 'react-native';\nimport { Button } from '@/components/ui/button';\n\nexport default function Sizes() {\n return (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>\n <Button size=\"sm\">Small</Button>\n <Button size=\"md\">Medium</Button>\n <Button size=\"lg\">Large</Button>\n <Button size=\"icon\" variant=\"outline\">\n <Text style={{ fontSize: 18 }}>♥</Text>\n </Button>\n </View>\n );\n}\n"
103
+ },
104
+ {
105
+ "name": "Loading",
106
+ "title": "Loading",
107
+ "code": "import React, { useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\nexport default function Loading() {\n const [busy, setBusy] = useState(false);\n return (\n <Button\n variant=\"accent\"\n pill\n block\n size=\"lg\"\n loading={busy}\n onPress={() => {\n setBusy(true);\n setTimeout(() => setBusy(false), 1600);\n }}\n >\n {busy ? 'Saving' : 'Save changes'}\n </Button>\n );\n}\n"
108
+ },
109
+ {
110
+ "name": "Colors",
111
+ "title": "Colors",
112
+ "code": "import { Pressable, Text, View } from 'react-native';\nimport { Button } from '@/components/ui/button';\n\nexport default function Colors() {\n return (\n <View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 10 }}>\n <Button variant=\"soft\" color=\"#10b981\">Approve</Button>\n <Button variant=\"soft\" color=\"#f59e0b\">Pending</Button>\n <Button variant=\"soft\" color=\"#ef4444\">Reject</Button>\n <Button variant=\"accent\" color=\"#ec4899\" pill>Follow</Button>\n </View>\n );\n}\n"
113
+ }
114
+ ]
115
+ }
@@ -0,0 +1,182 @@
1
+ {
2
+ "name": "calendar",
3
+ "category": "Inputs",
4
+ "aliases": [],
5
+ "exportName": "Calendar",
6
+ "files": [
7
+ "src/components/ui/calendar.tsx"
8
+ ],
9
+ "props": [
10
+ [
11
+ "mode",
12
+ "'single' | 'range' | 'multiple'",
13
+ "'single'",
14
+ "Selection model; decides the value type."
15
+ ],
16
+ [
17
+ "value",
18
+ "Date | { start, end } | Date[] | null",
19
+ "—",
20
+ "Controlled selection (Date for single, DateRange for range, Date[] for multiple)."
21
+ ],
22
+ [
23
+ "defaultValue",
24
+ "same as value",
25
+ "null",
26
+ "Initial selection when uncontrolled."
27
+ ],
28
+ [
29
+ "onChange",
30
+ "(value) => void",
31
+ "—",
32
+ "Fires on every tap. Range fires { start, end: null } first, then both ends."
33
+ ],
34
+ [
35
+ "month",
36
+ "Date",
37
+ "—",
38
+ "Controlled visible month (any date inside it)."
39
+ ],
40
+ [
41
+ "defaultMonth",
42
+ "Date",
43
+ "selection or today",
44
+ "Month shown first when uncontrolled."
45
+ ],
46
+ [
47
+ "onMonthChange",
48
+ "(month: Date) => void",
49
+ "—",
50
+ "Called with the first day of the month navigated to."
51
+ ],
52
+ [
53
+ "weekStartsOn",
54
+ "0 | 1",
55
+ "0",
56
+ "0 = Sunday, 1 = Monday."
57
+ ],
58
+ [
59
+ "locale",
60
+ "string",
61
+ "device",
62
+ "BCP 47 locale for month and weekday names."
63
+ ],
64
+ [
65
+ "minDate",
66
+ "Date",
67
+ "—",
68
+ "Earliest selectable day; also limits navigation."
69
+ ],
70
+ [
71
+ "maxDate",
72
+ "Date",
73
+ "—",
74
+ "Latest selectable day; also limits navigation."
75
+ ],
76
+ [
77
+ "isDateDisabled",
78
+ "(date: Date) => boolean",
79
+ "—",
80
+ "Disable individual days (booked, holidays, weekends)."
81
+ ],
82
+ [
83
+ "markedDates",
84
+ "Record<string, string | string[]>",
85
+ "—",
86
+ "Up to three coloured dots under each day, keyed by toDateKey(date) (YYYY-MM-DD)."
87
+ ],
88
+ [
89
+ "highlightedDates",
90
+ "Record<string, string>",
91
+ "—",
92
+ "Fills whole days with a colour (birthdays, shifts, people), keyed by toDateKey(date). Text switches to a readable colour on top."
93
+ ],
94
+ [
95
+ "variant",
96
+ "'tiles' | 'minimal'",
97
+ "'tiles'",
98
+ "tiles puts every day of the month on a soft tile; minimal shows bare numbers with a hover / press circle."
99
+ ],
100
+ [
101
+ "weekdayFormat",
102
+ "'narrow' | 'short'",
103
+ "'narrow'",
104
+ "Weekday header as single letters (M T W) or short names (Mon Tue Wed), via Intl."
105
+ ],
106
+ [
107
+ "showTodayButton",
108
+ "boolean",
109
+ "true",
110
+ "Shows a Today pill in the header whenever another month is on screen; tapping it jumps back."
111
+ ],
112
+ [
113
+ "showOutsideDays",
114
+ "boolean",
115
+ "false",
116
+ "Show faded days of the neighbouring months (tapping one navigates there)."
117
+ ],
118
+ [
119
+ "showToday",
120
+ "boolean",
121
+ "true",
122
+ "Ring and tint today."
123
+ ],
124
+ [
125
+ "fixedWeeks",
126
+ "boolean",
127
+ "false",
128
+ "Always render six week rows so the height never changes."
129
+ ],
130
+ [
131
+ "monthPicker",
132
+ "boolean",
133
+ "true",
134
+ "Tap the title for a month grid, tap again for a year grid."
135
+ ],
136
+ [
137
+ "max",
138
+ "number",
139
+ "—",
140
+ "Most dates selectable in multiple mode."
141
+ ],
142
+ [
143
+ "accent",
144
+ "string",
145
+ "theme accent",
146
+ "Selection, band and today colour."
147
+ ],
148
+ [
149
+ "style",
150
+ "StyleProp<ViewStyle>",
151
+ "—",
152
+ "Root container style."
153
+ ]
154
+ ],
155
+ "examples": [
156
+ {
157
+ "name": "Single",
158
+ "title": "Single",
159
+ "code": "import React, { useMemo, useState } from 'react';\nimport { StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Calendar, addDays, startOfDay, toDateKey, type DateRange } from '@/components/ui/calendar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst today = startOfDay(new Date());\n\nconst day = (d: Date | null) => (d ? d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' }) : '—');\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, ...rest }: ViewProps) {\n const { colors, radius } = useKit();\n return <View style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]} {...rest} />;\n}\n\n/** Text in the kit's ink: `tone=\"muted\"` for secondary copy. */\nfunction Ink({ tone, style, ...rest }: TextProps & { tone?: 'muted' }) {\n const { colors } = useKit();\n return <Text style={[{ color: tone === 'muted' ? colors.mutedForeground : colors.foreground }, style]} {...rest} />;\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n title: { fontSize: 15, fontWeight: '400' },\n summary: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },\n row: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n col: { flex: 1, gap: 2 },\n muted: { fontSize: 13 },\n strong: { fontSize: 15, fontWeight: '400' },\n pill: { paddingHorizontal: 10, paddingVertical: 6 },\n pillText: { fontSize: 13, fontWeight: '400' },\n legend: { flexDirection: 'row', flexWrap: 'wrap', columnGap: 14, rowGap: 6, justifyContent: 'center' },\n legendItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },\n dot: { width: 8, height: 8, borderRadius: 4 },\n});\n\nexport default function Single() {\n const [date, setDate] = useState<Date>(addDays(today, 3));\n return (\n <Card>\n <Ink style={s.title}>Delivery day</Ink>\n <Calendar value={date} onChange={setDate} minDate={today} />\n <View style={s.summary}>\n <Ink tone=\"muted\" style={s.muted}>Arriving</Ink>\n <Ink style={s.strong}>{day(date)}</Ink>\n </View>\n </Card>\n );\n}\n"
160
+ },
161
+ {
162
+ "name": "Range",
163
+ "title": "Range",
164
+ "code": "import React, { useMemo, useState } from 'react';\nimport { StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Calendar, addDays, startOfDay, toDateKey, type DateRange } from '@/components/ui/calendar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst today = startOfDay(new Date());\n\nconst day = (d: Date | null) => (d ? d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' }) : '—');\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, ...rest }: ViewProps) {\n const { colors, radius } = useKit();\n return <View style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]} {...rest} />;\n}\n\n/** Text in the kit's ink: `tone=\"muted\"` for secondary copy. */\nfunction Ink({ tone, style, ...rest }: TextProps & { tone?: 'muted' }) {\n const { colors } = useKit();\n return <Text style={[{ color: tone === 'muted' ? colors.mutedForeground : colors.foreground }, style]} {...rest} />;\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n title: { fontSize: 15, fontWeight: '400' },\n summary: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },\n row: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n col: { flex: 1, gap: 2 },\n muted: { fontSize: 13 },\n strong: { fontSize: 15, fontWeight: '400' },\n pill: { paddingHorizontal: 10, paddingVertical: 6 },\n pillText: { fontSize: 13, fontWeight: '400' },\n legend: { flexDirection: 'row', flexWrap: 'wrap', columnGap: 14, rowGap: 6, justifyContent: 'center' },\n legendItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },\n dot: { width: 8, height: 8, borderRadius: 4 },\n});\n\nexport default function Range() {\n const [stay, setStay] = useState<DateRange>({ start: addDays(today, 4), end: addDays(today, 8) });\n const { colors, radius } = useKit();\n const nights = stay.start && stay.end ? Math.round((stay.end.getTime() - stay.start.getTime()) / 86400000) : 0;\n return (\n <Card>\n <Ink style={s.title}>Your stay · Lisbon</Ink>\n <Calendar mode=\"range\" value={stay} onChange={setStay} minDate={today} />\n <View style={s.row}>\n <View style={s.col}>\n <Ink tone=\"muted\" style={s.muted}>Check-in</Ink>\n <Ink style={s.strong}>{day(stay.start)}</Ink>\n </View>\n <View style={s.col}>\n <Ink tone=\"muted\" style={s.muted}>Check-out</Ink>\n <Ink style={s.strong}>{stay.end ? day(stay.end) : 'Select a date'}</Ink>\n </View>\n <View style={[s.pill, { opacity: nights ? 1 : 0.4, backgroundColor: alpha(colors.accent, 0.14), borderRadius: radius.capsule(30) }]}>\n <Text style={[s.pillText, { color: colors.accent }]}>{nights ? `${nights} night${nights > 1 ? 's' : ''}` : '0 nights'}</Text>\n </View>\n </View>\n </Card>\n );\n}\n"
165
+ },
166
+ {
167
+ "name": "Marked",
168
+ "title": "Marked",
169
+ "code": "import React, { useMemo, useState } from 'react';\nimport { StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Calendar, addDays, startOfDay, toDateKey, type DateRange } from '@/components/ui/calendar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst today = startOfDay(new Date());\n\nconst day = (d: Date | null) => (d ? d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' }) : '—');\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, ...rest }: ViewProps) {\n const { colors, radius } = useKit();\n return <View style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]} {...rest} />;\n}\n\n/** Text in the kit's ink: `tone=\"muted\"` for secondary copy. */\nfunction Ink({ tone, style, ...rest }: TextProps & { tone?: 'muted' }) {\n const { colors } = useKit();\n return <Text style={[{ color: tone === 'muted' ? colors.mutedForeground : colors.foreground }, style]} {...rest} />;\n}\n\nconst MEETING = '#38bdf8';\n\nconst BIRTHDAY = '#f472b6';\n\nconst TRIP = '#f59e0b';\n\nconst DONE = '#22c55e';\n\nconst DUE = '#ef4444';\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n title: { fontSize: 15, fontWeight: '400' },\n summary: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },\n row: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n col: { flex: 1, gap: 2 },\n muted: { fontSize: 13 },\n strong: { fontSize: 15, fontWeight: '400' },\n pill: { paddingHorizontal: 10, paddingVertical: 6 },\n pillText: { fontSize: 13, fontWeight: '400' },\n legend: { flexDirection: 'row', flexWrap: 'wrap', columnGap: 14, rowGap: 6, justifyContent: 'center' },\n legendItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },\n dot: { width: 8, height: 8, borderRadius: 4 },\n});\n\nexport default function Marked() {\n const [date, setDate] = useState<Date>(today);\n const { highlights, marks } = useMemo(() => {\n const y = today.getFullYear();\n const m = today.getMonth();\n const k = (d: number) => toDateKey(new Date(y, m, d));\n return {\n // Whole-day fills: who / what owns the day.\n highlights: { [k(2)]: MEETING, [k(14)]: BIRTHDAY, [k(18)]: TRIP, [k(21)]: MEETING, [k(31)]: BIRTHDAY },\n // Dots underneath: smaller things on that day.\n marks: { [k(3)]: DONE, [k(8)]: DUE, [k(12)]: DONE, [k(17)]: DONE, [k(22)]: [DONE, DUE], [k(26)]: DUE },\n };\n }, []);\n return (\n <Card>\n <Ink style={s.title}>Schedule</Ink>\n <Calendar value={date} onChange={setDate} highlightedDates={highlights} markedDates={marks} weekStartsOn={1} />\n <View style={s.legend}>\n {[\n ['Meeting', MEETING],\n ['Birthday', BIRTHDAY],\n ['Trip', TRIP],\n ['Done', DONE],\n ['Due', DUE],\n ].map(([label, color]) => (\n <View key={label} style={s.legendItem}>\n <View style={[s.dot, { backgroundColor: color }]} />\n <Ink tone=\"muted\" style={s.muted}>{label}</Ink>\n </View>\n ))}\n </View>\n </Card>\n );\n}\n"
170
+ },
171
+ {
172
+ "name": "Booking",
173
+ "title": "Booking",
174
+ "code": "import React, { useMemo, useState } from 'react';\nimport { StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Calendar, addDays, startOfDay, toDateKey, type DateRange } from '@/components/ui/calendar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst today = startOfDay(new Date());\n\nconst day = (d: Date | null) => (d ? d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' }) : '—');\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, ...rest }: ViewProps) {\n const { colors, radius } = useKit();\n return <View style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]} {...rest} />;\n}\n\n/** Text in the kit's ink: `tone=\"muted\"` for secondary copy. */\nfunction Ink({ tone, style, ...rest }: TextProps & { tone?: 'muted' }) {\n const { colors } = useKit();\n return <Text style={[{ color: tone === 'muted' ? colors.mutedForeground : colors.foreground }, style]} {...rest} />;\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n title: { fontSize: 15, fontWeight: '400' },\n summary: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },\n row: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n col: { flex: 1, gap: 2 },\n muted: { fontSize: 13 },\n strong: { fontSize: 15, fontWeight: '400' },\n pill: { paddingHorizontal: 10, paddingVertical: 6 },\n pillText: { fontSize: 13, fontWeight: '400' },\n legend: { flexDirection: 'row', flexWrap: 'wrap', columnGap: 14, rowGap: 6, justifyContent: 'center' },\n legendItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },\n dot: { width: 8, height: 8, borderRadius: 4 },\n});\n\nexport default function Booking() {\n const booked = useMemo(() => new Set([2, 5, 6, 11, 19].map((n) => toDateKey(addDays(today, n)))), []);\n const [date, setDate] = useState<Date | null>(null);\n return (\n <Card>\n <Ink style={s.title}>Book a consultation</Ink>\n <Calendar\n value={date}\n onChange={setDate}\n minDate={today}\n maxDate={addDays(today, 45)}\n isDateDisabled={(d) => d.getDay() === 0 || booked.has(toDateKey(d))}\n showOutsideDays\n fixedWeeks\n />\n <Ink tone=\"muted\" style={s.muted}>\n {date ? `Next: choose a time on ${day(date)}` : 'Faded days are fully booked or closed on Sundays.'}\n </Ink>\n </Card>\n );\n}\n"
175
+ },
176
+ {
177
+ "name": "WeekStartsMonday",
178
+ "title": "Week Starts Monday",
179
+ "code": "import React, { useMemo, useState } from 'react';\nimport { StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Calendar, addDays, startOfDay, toDateKey, type DateRange } from '@/components/ui/calendar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst today = startOfDay(new Date());\n\nconst day = (d: Date | null) => (d ? d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' }) : '—');\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, ...rest }: ViewProps) {\n const { colors, radius } = useKit();\n return <View style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]} {...rest} />;\n}\n\n/** Text in the kit's ink: `tone=\"muted\"` for secondary copy. */\nfunction Ink({ tone, style, ...rest }: TextProps & { tone?: 'muted' }) {\n const { colors } = useKit();\n return <Text style={[{ color: tone === 'muted' ? colors.mutedForeground : colors.foreground }, style]} {...rest} />;\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n title: { fontSize: 15, fontWeight: '400' },\n summary: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },\n row: { flexDirection: 'row', alignItems: 'center', gap: 12 },\n col: { flex: 1, gap: 2 },\n muted: { fontSize: 13 },\n strong: { fontSize: 15, fontWeight: '400' },\n pill: { paddingHorizontal: 10, paddingVertical: 6 },\n pillText: { fontSize: 13, fontWeight: '400' },\n legend: { flexDirection: 'row', flexWrap: 'wrap', columnGap: 14, rowGap: 6, justifyContent: 'center' },\n legendItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },\n dot: { width: 8, height: 8, borderRadius: 4 },\n});\n\nexport default function WeekStartsMonday() {\n const [days, setDays] = useState<Date[]>([addDays(today, 1), addDays(today, 3)]);\n return (\n <Card>\n <Ink style={s.title}>Training days · pick up to 3</Ink>\n <Calendar mode=\"multiple\" value={days} onChange={setDays} max={3} weekStartsOn={1} locale=\"en-GB\" showOutsideDays />\n <Ink tone=\"muted\" style={s.muted}>{days.length ? days.map((d) => day(d)).join(' · ') : 'No sessions planned'}</Ink>\n </Card>\n );\n}\n"
180
+ }
181
+ ]
182
+ }
@@ -0,0 +1,108 @@
1
+ {
2
+ "name": "card-stack",
3
+ "category": "3D",
4
+ "aliases": [],
5
+ "exportName": "CardStack",
6
+ "files": [
7
+ "src/components/ui/card-stack.tsx"
8
+ ],
9
+ "props": [
10
+ [
11
+ "data",
12
+ "T[]",
13
+ "—",
14
+ "Items, one card each."
15
+ ],
16
+ [
17
+ "renderItem",
18
+ "({ item, index, front }) => ReactNode",
19
+ "—",
20
+ "Render a card. `front` is true for the card in front."
21
+ ],
22
+ [
23
+ "keyExtractor",
24
+ "(item: T, index: number) => string",
25
+ "index",
26
+ "React key for each card."
27
+ ],
28
+ [
29
+ "cardHeight",
30
+ "number",
31
+ "190",
32
+ "Card height."
33
+ ],
34
+ [
35
+ "peek",
36
+ "number",
37
+ "14",
38
+ "How much of each card shows behind the front one when closed."
39
+ ],
40
+ [
41
+ "spread",
42
+ "number",
43
+ "64",
44
+ "Space between cards when open."
45
+ ],
46
+ [
47
+ "depth",
48
+ "number",
49
+ "3",
50
+ "Cards visible behind the front one when closed."
51
+ ],
52
+ [
53
+ "selected",
54
+ "number",
55
+ "—",
56
+ "Controlled front card (index into data)."
57
+ ],
58
+ [
59
+ "onPressFront",
60
+ "(index) => void",
61
+ "—",
62
+ "Tap on the front card while closed (pay with it); the cards behind still open the stack."
63
+ ],
64
+ [
65
+ "getAccessibilityLabel",
66
+ "(item, index) => string",
67
+ "\"Card 2 of 4\"",
68
+ "Screen-reader label for each card."
69
+ ],
70
+ [
71
+ "defaultSelected",
72
+ "number",
73
+ "0",
74
+ "Uncontrolled initial front card."
75
+ ],
76
+ [
77
+ "onSelect",
78
+ "(index: number) => void",
79
+ "—",
80
+ "Fires when a card is picked."
81
+ ],
82
+ [
83
+ "open",
84
+ "boolean",
85
+ "—",
86
+ "Controlled open state."
87
+ ],
88
+ [
89
+ "onOpenChange",
90
+ "(open: boolean) => void",
91
+ "—",
92
+ "Fires when the stack opens or closes."
93
+ ],
94
+ [
95
+ "radius",
96
+ "number",
97
+ "18",
98
+ "Corner radius of each card."
99
+ ],
100
+ [
101
+ "style",
102
+ "StyleProp<ViewStyle>",
103
+ "—",
104
+ "Style for the root view."
105
+ ]
106
+ ],
107
+ "examples": []
108
+ }