@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,191 @@
1
+ {
2
+ "name": "textarea",
3
+ "category": "Inputs",
4
+ "aliases": [],
5
+ "exportName": "Textarea",
6
+ "files": [
7
+ "src/components/ui/textarea.tsx"
8
+ ],
9
+ "summary": "A multiline field that glides taller line by line, with a ring-style counter.",
10
+ "props": [
11
+ [
12
+ "label",
13
+ "string",
14
+ "—",
15
+ "Rests on the first line, floats onto the border on focus."
16
+ ],
17
+ [
18
+ "floatingLabel",
19
+ "boolean",
20
+ "true",
21
+ "Set to false to put the label above the field as static text (no notch); placeholder shows inside."
22
+ ],
23
+ [
24
+ "variant",
25
+ "\"outlined\" | \"filled\"",
26
+ "\"outlined\"",
27
+ "Field style."
28
+ ],
29
+ [
30
+ "size",
31
+ "\"sm\" | \"md\" | \"lg\"",
32
+ "\"md\"",
33
+ "14 / 16 / 18px text; line height and padding scale too."
34
+ ],
35
+ [
36
+ "minRows / maxRows",
37
+ "number",
38
+ "3 / 8",
39
+ "Grows smoothly between these, then scrolls."
40
+ ],
41
+ [
42
+ "maxLength",
43
+ "number",
44
+ "—",
45
+ "Character limit; enables the counter."
46
+ ],
47
+ [
48
+ "enforceMaxLength",
49
+ "boolean",
50
+ "true",
51
+ "false makes the limit soft: typing past it turns the counter red and negative."
52
+ ],
53
+ [
54
+ "showCount",
55
+ "boolean",
56
+ "true when maxLength",
57
+ "Counter that becomes a ring in the last 20%."
58
+ ],
59
+ [
60
+ "toolbar",
61
+ "ReactNode",
62
+ "—",
63
+ "Row inside the bottom edge — attach, emoji, send."
64
+ ],
65
+ [
66
+ "error",
67
+ "string",
68
+ "—",
69
+ "Red state, icon + message that slides in, one shake."
70
+ ],
71
+ [
72
+ "success",
73
+ "boolean | string",
74
+ "—",
75
+ "Green border + animated check; a string is shown as the message."
76
+ ],
77
+ [
78
+ "helper",
79
+ "string",
80
+ "—",
81
+ "Hint under the field."
82
+ ],
83
+ [
84
+ "accent",
85
+ "string",
86
+ "theme accent",
87
+ "Focus border and halo colour."
88
+ ],
89
+ [
90
+ "surface",
91
+ "string",
92
+ "theme background",
93
+ "Colour behind the field (paints the label notch)."
94
+ ],
95
+ [
96
+ "style",
97
+ "StyleProp<ViewStyle>",
98
+ "—",
99
+ "Style for the outer wrapper around the field and footer (the one that shakes)."
100
+ ],
101
+ [
102
+ "fieldStyle",
103
+ "StyleProp<ViewStyle>",
104
+ "—",
105
+ "The bordered box: background, border width / colour, radius, height, padding. Wins over the computed style; a borderColor replaces the resting border only (focus, error and success colours still show). height is ignored: the box grows with minRows / maxRows."
106
+ ],
107
+ [
108
+ "inputStyle",
109
+ "StyleProp<TextStyle>",
110
+ "—",
111
+ "The typed text — fontSize, lineHeight, fontWeight, color, fontFamily. Row height follows lineHeight (or scales with fontSize)."
112
+ ],
113
+ [
114
+ "labelStyle",
115
+ "StyleProp<TextStyle>",
116
+ "—",
117
+ "Label in both modes (floating and above). color is the resting colour — focus (accent), error and success still take over; fontSize sets the resting size, it floats at the same ratio and the notch follows its width."
118
+ ],
119
+ [
120
+ "messageStyle",
121
+ "StyleProp<TextStyle>",
122
+ "—",
123
+ "Helper / error / success text. color applies to the helper; error and success keep their tone colour."
124
+ ],
125
+ [
126
+ "counterStyle",
127
+ "StyleProp<TextStyle>",
128
+ "—",
129
+ "Counter text (42/280 and the characters-left number); warning / danger still win near the limit."
130
+ ],
131
+ [
132
+ "placeholderTextColor",
133
+ "string",
134
+ "theme mutedForeground",
135
+ "Placeholder colour."
136
+ ],
137
+ [
138
+ "…TextInputProps",
139
+ "",
140
+ "",
141
+ "value, defaultValue, onChangeText, placeholder, …"
142
+ ]
143
+ ],
144
+ "behavior": [
145
+ [
146
+ "Motion",
147
+ "The box grows smoothly between minRows and maxRows as you type; the label floats up on focus and a halo glows around the field."
148
+ ],
149
+ [
150
+ "Screen readers",
151
+ "The input is labelled by label or placeholder; the counter reads like '42 of 200 characters left' and error / success messages land in a polite live region."
152
+ ],
153
+ [
154
+ "Web",
155
+ "The browser focus outline is removed; the field draws its own focus halo."
156
+ ]
157
+ ],
158
+ "usage": "import { useState } from 'react';\nimport { Textarea } from '@/components/ui/textarea';\n\nconst [review, setReview] = useState('');\n<Textarea label=\"Your review\" value={review} onChangeText={setReview} maxLength={200} />",
159
+ "examples": [
160
+ {
161
+ "name": "Composer",
162
+ "title": "Composer",
163
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useKit } from '@/lib/kit';\n\nfunction ToolButton({ glyph, label }: { glyph: string; label: string }) {\n const { colors } = useKit();\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n hitSlop={6}\n style={{ width: 32, height: 32, borderRadius: 16, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.muted }}\n >\n <Text style={{ fontSize: 17, fontWeight: '400', color: colors.mutedForeground }}>{glyph}</Text>\n </Pressable>\n );\n}\n\nexport default function Composer() {\n const { colors, radius } = useKit();\n const [draft, setDraft] = useState('');\n const [sent, setSent] = useState<string[]>(['Are we still on for the design review at 3?']);\n const canSend = draft.trim().length > 0;\n const send = () => {\n if (!canSend) return;\n setSent((s) => [...s.slice(-1), draft.trim()]);\n setDraft('');\n };\n return (\n <View style={{ gap: 10 }}>\n {sent.map((m, i) => (\n <View\n key={i}\n style={{ alignSelf: 'flex-end', maxWidth: '80%', backgroundColor: colors.accent, borderRadius: radius.scale(18), paddingHorizontal: 14, paddingVertical: 9 }}\n >\n <Text style={{ color: colors.accentForeground, fontSize: 15 }}>{m}</Text>\n </View>\n ))}\n <Textarea\n placeholder=\"Message Alex…\"\n value={draft}\n onChangeText={setDraft}\n minRows={1}\n maxRows={5}\n toolbar={\n <>\n <ToolButton glyph=\"+\" label=\"Attach a file\" />\n <ToolButton glyph=\"@\" label=\"Mention someone\" />\n <View style={{ flex: 1 }} />\n <Pressable\n onPress={send}\n disabled={!canSend}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Send message\"\n hitSlop={6}\n style={{\n height: 32,\n paddingHorizontal: 14,\n borderRadius: radius.capsule(32),\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: colors.accent,\n opacity: canSend ? 1 : 0.4,\n }}\n >\n <Text style={{ color: colors.accentForeground, fontSize: 14, fontWeight: '400' }}>Send ↑</Text>\n </Pressable>\n </>\n }\n />\n </View>\n );\n}\n"
164
+ },
165
+ {
166
+ "name": "Review",
167
+ "title": "Review",
168
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useKit } from '@/lib/kit';\n\nfunction Card({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={{\n padding: 16,\n gap: 12,\n borderRadius: radius.xl,\n borderWidth: StyleSheet.hairlineWidth,\n borderColor: colors.border,\n backgroundColor: colors.card,\n }}\n >\n <View style={{ gap: 2, marginBottom: 2 }}>\n <Text style={{ fontSize: 16, fontWeight: '400', color: colors.foreground }}>{title}</Text>\n {subtitle ? <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{subtitle}</Text> : null}\n </View>\n {children}\n </View>\n );\n}\n\nexport default function Review() {\n const [review, setReview] = useState('Great coffee, but');\n const length = review.trim().length;\n return (\n <Card title=\"Rate Blue Bottle, Hayes Valley\" subtitle=\"Reviews are public and show your first name.\">\n <Textarea\n label=\"Your review\"\n value={review}\n onChangeText={setReview}\n maxLength={200}\n enforceMaxLength={false}\n minRows={3}\n error={length > 0 && length < 20 ? 'Tell us a little more — at least 20 characters' : length > 200 ? 'Keep it under 200 characters' : undefined}\n success={length >= 20 && length <= 200 ? 'Thanks — that will really help others' : undefined}\n />\n </Card>\n );\n}\n"
169
+ },
170
+ {
171
+ "name": "Feedback",
172
+ "title": "Feedback",
173
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Textarea } from '@/components/ui/textarea';\nimport { useKit } from '@/lib/kit';\n\nfunction Card({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={{\n padding: 16,\n gap: 12,\n borderRadius: radius.xl,\n borderWidth: StyleSheet.hairlineWidth,\n borderColor: colors.border,\n backgroundColor: colors.card,\n }}\n >\n <View style={{ gap: 2, marginBottom: 2 }}>\n <Text style={{ fontSize: 16, fontWeight: '400', color: colors.foreground }}>{title}</Text>\n {subtitle ? <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{subtitle}</Text> : null}\n </View>\n {children}\n </View>\n );\n}\n\nexport default function Feedback() {\n return (\n <Card title=\"Send feedback\" subtitle=\"Goes straight to the product team.\">\n <Textarea\n variant=\"filled\"\n label=\"What could be better?\"\n defaultValue=\"Dark mode on the invoices page is a little too low-contrast for me.\"\n helper=\"Screenshots help — attach them in the next step.\"\n minRows={3}\n maxRows={6}\n />\n </Card>\n );\n}\n"
174
+ },
175
+ {
176
+ "name": "CharacterLimit",
177
+ "title": "Character Limit",
178
+ "code": "import { Textarea } from '@/components/ui/textarea';\n\nexport default function CharacterLimit() {\n return (\n <Textarea\n label=\"What's happening?\"\n maxLength={140}\n defaultValue=\"Shipping the new ExpoKit inputs today — focus halos, animated checks and fields that glide taller as you type.\"\n minRows={3}\n />\n );\n}\n"
179
+ },
180
+ {
181
+ "name": "States",
182
+ "title": "States",
183
+ "code": "import { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Textarea } from '@/components/ui/textarea';\n\nexport default function States() {\n return (\n <View style={{ gap: 16 }}>\n <Textarea label=\"Delivery instructions\" minRows={2} defaultValue=\"Leave it with the concierge, code 4417.\" success=\"Saved for next time\" />\n <Textarea label=\"Notes for the courier\" minRows={2} editable={false} defaultValue=\"Locked while the order is out for delivery.\" />\n </View>\n );\n}\n"
184
+ },
185
+ {
186
+ "name": "Sizes",
187
+ "title": "Sizes",
188
+ "code": "import { Pressable, StyleSheet, Text, View } from 'react-native';\nimport { Textarea } from '@/components/ui/textarea';\n\nexport default function Sizes() {\n return (\n <View style={{ gap: 14 }}>\n <Textarea size=\"sm\" label=\"Small · 14px\" minRows={1} defaultValue=\"Compact comment box\" />\n <Textarea size=\"md\" label=\"Medium · 16px\" minRows={1} defaultValue=\"The default for forms\" />\n <Textarea size=\"lg\" label=\"Large · 18px\" minRows={1} defaultValue=\"Journaling and long-form\" />\n </View>\n );\n}\n"
189
+ }
190
+ ]
191
+ }
@@ -0,0 +1,194 @@
1
+ {
2
+ "name": "ticket-card",
3
+ "category": "3D",
4
+ "aliases": [],
5
+ "exportName": "TicketCard",
6
+ "files": [
7
+ "src/components/ui/ticket-card.tsx"
8
+ ],
9
+ "summary": "A boarding pass or event ticket with real notches and a stub you can tear off.",
10
+ "props": [
11
+ [
12
+ "brand / logo",
13
+ "string / ReactNode",
14
+ "—",
15
+ "Operator, venue or brand (and its logo), top-left."
16
+ ],
17
+ [
18
+ "badge",
19
+ "string",
20
+ "—",
21
+ "Chip top-right (\"VIP\", \"Business\") — on holographic foil when holo."
22
+ ],
23
+ [
24
+ "eyebrow",
25
+ "string",
26
+ "—",
27
+ "Small line above the title or route (\"Boarding pass · TP 1043\")."
28
+ ],
29
+ [
30
+ "title / subtitle",
31
+ "string",
32
+ "—",
33
+ "Event name and details (omit for a route pass)."
34
+ ],
35
+ [
36
+ "from / to",
37
+ "{ code: string; detail?: string }",
38
+ "—",
39
+ "Route endpoints; a dashed flight path runs between them."
40
+ ],
41
+ [
42
+ "duration",
43
+ "string",
44
+ "—",
45
+ "Under the flight path (\"7h 25m\")."
46
+ ],
47
+ [
48
+ "transport",
49
+ "\"flight\" | \"train\" | \"bus\" | \"boat\"",
50
+ "\"flight\"",
51
+ "Icon riding the flight path."
52
+ ],
53
+ [
54
+ "fields",
55
+ "{ label: string; value: string; span?: number }[]",
56
+ "[]",
57
+ "Details grid that wraps onto more rows; span widens a field."
58
+ ],
59
+ [
60
+ "columns",
61
+ "number",
62
+ "up to 4",
63
+ "Columns in the details grid."
64
+ ],
65
+ [
66
+ "code",
67
+ "string",
68
+ "—",
69
+ "Printed in the stub and shown big on the back. Omit for a ticket without a stub."
70
+ ],
71
+ [
72
+ "codeType",
73
+ "\"qr\" | \"barcode\"",
74
+ "\"qr\"",
75
+ "Look-alike code style — use renderCode for a scannable one."
76
+ ],
77
+ [
78
+ "renderCode",
79
+ "(code: string, size: number) => ReactNode",
80
+ "—",
81
+ "Draw a real code (e.g. react-native-qrcode-svg)."
82
+ ],
83
+ [
84
+ "notes",
85
+ "string | string[]",
86
+ "—",
87
+ "Lines on the back: terms, baggage, gate notes."
88
+ ],
89
+ [
90
+ "image",
91
+ "ImageSourcePropType",
92
+ "—",
93
+ "Header photo (vertical) or full-bleed art (horizontal)."
94
+ ],
95
+ [
96
+ "layout",
97
+ "\"vertical\" | \"horizontal\"",
98
+ "\"vertical\"",
99
+ "Pass with the stub below, or admit-one ticket with the stub on the right."
100
+ ],
101
+ [
102
+ "theme",
103
+ "\"midnight\" | \"paper\" | \"aurora\" | \"sunset\" | \"neon\" | \"royal\" | \"mint\" | TicketTheme",
104
+ "\"midnight\"",
105
+ "Preset, or { fill, stub?, ink, soft?, accent, pattern? } — fill can be a gradient."
106
+ ],
107
+ [
108
+ "tone",
109
+ "\"dark\" | \"light\"",
110
+ "—",
111
+ "Shorthand for theme: midnight / paper."
112
+ ],
113
+ [
114
+ "accent",
115
+ "string",
116
+ "theme accent",
117
+ "Route line, badge and stamp colour."
118
+ ],
119
+ [
120
+ "holo",
121
+ "boolean",
122
+ "false",
123
+ "Rainbow foil glare and a holographic badge."
124
+ ],
125
+ [
126
+ "stamp / stampColor",
127
+ "string / string",
128
+ "— / accent",
129
+ "Rubber stamp across the ticket (\"CHECKED IN\"); thumps in when set."
130
+ ],
131
+ [
132
+ "onTear",
133
+ "() => void",
134
+ "—",
135
+ "Enables swiping the stub off along the tear line; called once it's gone."
136
+ ],
137
+ [
138
+ "torn",
139
+ "boolean",
140
+ "—",
141
+ "Controlled torn state (the stub is gone, the torn edge stays)."
142
+ ],
143
+ [
144
+ "flipped / defaultFlipped / onFlip",
145
+ "boolean / boolean / (flipped) => void",
146
+ "— / false / —",
147
+ "Controlled or uncontrolled side (tap to flip)."
148
+ ],
149
+ [
150
+ "tilt",
151
+ "boolean",
152
+ "true",
153
+ "Tilt toward the finger; false for long lists."
154
+ ],
155
+ [
156
+ "radius",
157
+ "number",
158
+ "22",
159
+ "Corner radius."
160
+ ],
161
+ [
162
+ "labels",
163
+ "{ scan?, admit?, tear?, back? }",
164
+ "English",
165
+ "Every built-in string, for translation."
166
+ ],
167
+ [
168
+ "style",
169
+ "StyleProp<ViewStyle>",
170
+ "—",
171
+ "Style for the root (width, margins)."
172
+ ]
173
+ ],
174
+ "behavior": [
175
+ [
176
+ "Touch",
177
+ "The card tilts toward your finger (tilt={false} turns it off). Tap to flip it to the big code and notes; with onTear set, swipe the stub sideways to tear it off."
178
+ ],
179
+ [
180
+ "Motion",
181
+ "A holo badge shimmers as the card leans, a stamp thumps down when set, and a torn stub falls away along the tear line."
182
+ ],
183
+ [
184
+ "Haptics",
185
+ "A success notification when the stub tears off."
186
+ ],
187
+ [
188
+ "Screen readers",
189
+ "One element whose label joins the brand, title or route, every field and the stamp; it is a button when there is a back to flip to."
190
+ ]
191
+ ],
192
+ "usage": null,
193
+ "examples": []
194
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "ticket-shape",
3
+ "category": null,
4
+ "aliases": [],
5
+ "exportName": "TicketStamp",
6
+ "files": [
7
+ "src/lib/ticket-shape.tsx"
8
+ ],
9
+ "summary": null,
10
+ "props": [],
11
+ "behavior": [],
12
+ "usage": null,
13
+ "examples": []
14
+ }
@@ -0,0 +1,157 @@
1
+ {
2
+ "name": "tilt-card",
3
+ "category": "3D",
4
+ "aliases": [],
5
+ "exportName": "TiltCard",
6
+ "files": [
7
+ "src/components/ui/tilt-card.tsx"
8
+ ],
9
+ "summary": "A card that leans toward your finger in 3D while a glare slides across it.",
10
+ "props": [
11
+ [
12
+ "children",
13
+ "ReactNode",
14
+ "—",
15
+ "Content (sets the card's size). Wrap parts in <TiltLayer depth> to float them."
16
+ ],
17
+ [
18
+ "image",
19
+ "ImageSourcePropType",
20
+ "—",
21
+ "Photo that fills the card behind the content."
22
+ ],
23
+ [
24
+ "shade",
25
+ "number",
26
+ "0.6",
27
+ "Darkens the bottom of the photo so white text stays readable (0–1)."
28
+ ],
29
+ [
30
+ "maxTilt",
31
+ "number",
32
+ "12",
33
+ "Tilt in degrees at the card's edge."
34
+ ],
35
+ [
36
+ "pressScale",
37
+ "number",
38
+ "1.03",
39
+ "Scale while touched."
40
+ ],
41
+ [
42
+ "glare",
43
+ "\"soft\" | \"sharp\" | \"holo\" | \"none\"",
44
+ "\"soft\"",
45
+ "Light reflection that follows your finger. \"holo\" adds a rainbow foil sheen that shifts as the card leans."
46
+ ],
47
+ [
48
+ "glareClip",
49
+ "{ x, y, width, height }[]",
50
+ "whole card",
51
+ "Where the reflection may fall (card points) — for cards with cut-outs, so light never shows over a hole."
52
+ ],
53
+ [
54
+ "perspective",
55
+ "number",
56
+ "800",
57
+ "Depth of the effect — smaller is more dramatic."
58
+ ],
59
+ [
60
+ "idle",
61
+ "boolean",
62
+ "false",
63
+ "Slowly sway while untouched."
64
+ ],
65
+ [
66
+ "radius",
67
+ "number",
68
+ "20",
69
+ "Corner radius."
70
+ ],
71
+ [
72
+ "shadow",
73
+ "boolean",
74
+ "true",
75
+ "Soft shadow under the card that shifts as it tilts."
76
+ ],
77
+ [
78
+ "disabled",
79
+ "boolean",
80
+ "false",
81
+ "Turn touch tilting off."
82
+ ],
83
+ [
84
+ "onPress",
85
+ "() => void",
86
+ "—",
87
+ "Fires on a tap (not after a drag)."
88
+ ],
89
+ [
90
+ "accessibilityLabel",
91
+ "string",
92
+ "—",
93
+ "Label for screen readers."
94
+ ],
95
+ [
96
+ "style",
97
+ "StyleProp<ViewStyle>",
98
+ "—",
99
+ "Style for the card (width, margins)."
100
+ ],
101
+ [
102
+ "TiltLayer.depth",
103
+ "number",
104
+ "0.5",
105
+ "How far a layer floats above the card (negative sinks below)."
106
+ ],
107
+ [
108
+ "TiltFoil",
109
+ "{ children?, radius?, base?, style? }",
110
+ "—",
111
+ "A holographic foil patch (seal, sticker, strip) whose rainbow shifts as the card leans."
112
+ ],
113
+ [
114
+ "useTilt()",
115
+ "() => { tx, ty, press, width, height } | null",
116
+ "—",
117
+ "The card's live tilt values (native-driver friendly) for your own effects."
118
+ ]
119
+ ],
120
+ "behavior": [
121
+ [
122
+ "Touch",
123
+ "Press and drag to tilt up to maxTilt degrees; the card scales by pressScale and springs flat on release. onPress fires on a tap, not after a drag."
124
+ ],
125
+ [
126
+ "Motion",
127
+ "The shadow slides away from the light and the glare (soft, sharp or holo) glides across. TiltLayer children float at their own depth, and idle makes it sway gently at rest."
128
+ ],
129
+ [
130
+ "Screen readers",
131
+ "Exposed as one element when it has onPress or accessibilityLabel; with onPress it is a button with an 'activate' action."
132
+ ]
133
+ ],
134
+ "usage": "import { TiltCard, TiltLayer } from '@/components/ui/tilt-card';\n\n<TiltCard image={{ uri: photoUrl }} idle accessibilityLabel=\"Manarola, Cinque Terre\" style={{ width: 270, height: 360 }}>\n <TiltLayer depth={1}>\n <PlaceCaption place={place} />\n </TiltLayer>\n</TiltCard>",
135
+ "examples": [
136
+ {
137
+ "name": "TravelCard",
138
+ "title": "Travel Card",
139
+ "code": "import React, { useState } from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport { TiltCard, TiltLayer } from '@/components/ui/tilt-card';\nimport { alpha, 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 card 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\nconst glass = {\n paddingHorizontal: 10,\n paddingVertical: 5,\n borderRadius: 999,\n backgroundColor: 'rgba(255,255,255,0.18)',\n borderWidth: 1,\n borderColor: 'rgba(255,255,255,0.32)',\n} as const;\n\nexport default function TravelCard() {\n const { colors } = useKit();\n const [tab, setTab] = useState('Coast');\n return (\n <View style={{ gap: 18 }}>\n <Header title=\"Explore\" sub=\"Stays our guests loved this month\" />\n <View style={{ flexDirection: 'row', gap: 8 }}>\n {['Coast', 'Mountains', 'Cities', 'Lakes'].map((t) => {\n const on = t === tab;\n return (\n <Pressable\n key={t}\n onPress={() => setTab(t)}\n accessibilityRole=\"tab\"\n accessibilityState={{ selected: on }}\n style={{ paddingHorizontal: 14, paddingVertical: 8, borderRadius: 999, backgroundColor: on ? colors.foreground : colors.muted }}\n >\n <Text style={{ color: on ? colors.background : colors.foreground, fontSize: 13, fontWeight: '600' }}>{t}</Text>\n </Pressable>\n );\n })}\n </View>\n <TiltCard idle image={photo(397, 540, 720)} radius={26} accessibilityLabel=\"Manarola, Cinque Terre\" style={{ width: 270, alignSelf: 'center' }}>\n <View style={{ height: 360 }} />\n <TiltLayer depth={1.2}>\n <View style={[glass, { position: 'absolute', top: 16, right: 16 }]}>\n <Text style={{ color: '#fff', fontSize: 12, fontWeight: '700' }}>★ 4.9</Text>\n </View>\n </TiltLayer>\n <TiltLayer depth={0.8}>\n <View style={{ position: 'absolute', left: 20, right: 20, bottom: 20, gap: 2 }}>\n <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: 12, fontWeight: '600', letterSpacing: 1 }}>CINQUE TERRE · ITALY</Text>\n <Text style={{ color: '#fff', fontSize: 30, fontWeight: '800', letterSpacing: -0.8 }}>Manarola</Text>\n <Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: 13 }}>3 nights · from €140</Text>\n </View>\n </TiltLayer>\n </TiltCard>\n </View>\n );\n}\n"
140
+ },
141
+ {
142
+ "name": "NowPlaying",
143
+ "title": "Now Playing",
144
+ "code": "import React, { useState } from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport { TiltCard, TiltLayer } from '@/components/ui/tilt-card';\nimport { alpha, 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\nexport default function NowPlaying() {\n const { colors } = useKit();\n const [playing, setPlaying] = useState(true);\n return (\n <View style={{ alignItems: 'center', gap: 18 }}>\n <View style={{ alignSelf: 'stretch', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>\n <Text style={{ color: colors.foreground, fontSize: 20 }}>⌄</Text>\n <View style={{ alignItems: 'center' }}>\n <Text style={{ color: colors.mutedForeground, fontSize: 11, fontWeight: '700', letterSpacing: 1 }}>PLAYING FROM</Text>\n <Text style={{ color: colors.foreground, fontSize: 13, fontWeight: '600' }}>Late night drive</Text>\n </View>\n <Text style={{ color: colors.foreground, fontSize: 20 }}>⋯</Text>\n </View>\n <TiltCard idle image={photo(888, 300, 300, true)} shade={0.35} radius={20} accessibilityLabel=\"Midnight Bloom by Lumen\" style={{ width: 250 }}>\n <View style={{ height: 250 }} />\n <TiltLayer depth={1}>\n <View style={{ position: 'absolute', left: 18, bottom: 16 }}>\n <Text style={{ color: '#fff', fontSize: 30, fontWeight: '900', letterSpacing: -1, lineHeight: 30 }}>MIDNIGHT</Text>\n <Text style={{ color: '#fff', fontSize: 30, fontWeight: '300', letterSpacing: -1, lineHeight: 32 }}>bloom</Text>\n </View>\n </TiltLayer>\n </TiltCard>\n <View style={{ alignSelf: 'stretch', gap: 10 }}>\n <View>\n <Text style={{ color: colors.foreground, fontSize: 18, fontWeight: '700' }}>Midnight Bloom</Text>\n <Text style={{ color: colors.mutedForeground, fontSize: 14 }}>Lumen</Text>\n </View>\n <View style={{ height: 4, borderRadius: 2, backgroundColor: alpha(colors.mutedForeground, 0.25) }}>\n <View style={{ width: '42%', height: 4, borderRadius: 2, backgroundColor: colors.foreground }} />\n </View>\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: -4 }}>\n <Text style={{ color: colors.mutedForeground, fontSize: 11, fontVariant: ['tabular-nums'] }}>1:42</Text>\n <Text style={{ color: colors.mutedForeground, fontSize: 11, fontVariant: ['tabular-nums'] }}>−2:21</Text>\n </View>\n <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center', gap: 34 }}>\n <Text style={{ color: colors.foreground, fontSize: 22 }}>⏮</Text>\n <Pressable\n onPress={() => setPlaying((p) => !p)}\n accessibilityRole=\"button\"\n accessibilityLabel={playing ? 'Pause' : 'Play'}\n style={{ width: 58, height: 58, borderRadius: 29, backgroundColor: colors.foreground, alignItems: 'center', justifyContent: 'center' }}\n >\n <Text style={{ color: colors.background, fontSize: 20 }}>{playing ? '❚❚' : '▶'}</Text>\n </Pressable>\n <Text style={{ color: colors.foreground, fontSize: 22 }}>⏭</Text>\n </View>\n </View>\n </View>\n );\n}\n"
145
+ },
146
+ {
147
+ "name": "Product",
148
+ "title": "Product",
149
+ "code": "import React, { useState } from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport { TiltCard, TiltLayer } from '@/components/ui/tilt-card';\nimport { alpha, 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 card 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 Product() {\n const { colors } = useKit();\n return (\n <View style={{ gap: 18 }}>\n <Header\n title=\"New in\"\n sub=\"Film cameras, serviced and tested\"\n right={\n <View style={{ paddingHorizontal: 12, paddingVertical: 7, borderRadius: 999, backgroundColor: colors.muted }}>\n <Text style={{ color: colors.foreground, fontSize: 13, fontWeight: '600' }}>Bag · 2</Text>\n </View>\n }\n />\n <TiltCard maxTilt={14} radius={26} accessibilityLabel=\"Leica M6 film camera\" style={{ width: 280, alignSelf: 'center' }}>\n <View style={{ height: 360, backgroundColor: '#efece6' }} />\n <TiltLayer depth={1.4}>\n <View style={{ position: 'absolute', top: 26, left: 22, right: 22, height: 190, borderRadius: 18, overflow: 'hidden' }}>\n <Image alt=\"\" source={photo(250, 560, 380)} style={{ flex: 1 }} />\n </View>\n </TiltLayer>\n <TiltLayer depth={0.4}>\n <View style={{ position: 'absolute', left: 24, right: 24, bottom: 22, gap: 12 }}>\n <View>\n <Text style={{ color: '#8a8378', fontSize: 11, fontWeight: '700', letterSpacing: 1.2 }}>FILM CAMERA</Text>\n <Text style={{ color: '#1b1915', fontSize: 22, fontWeight: '800', letterSpacing: -0.4 }}>Rangefinder 35</Text>\n </View>\n <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>\n <Text style={{ color: '#1b1915', fontSize: 20, fontWeight: '700' }}>$1,290</Text>\n <View style={{ paddingHorizontal: 16, paddingVertical: 10, borderRadius: 999, backgroundColor: '#1b1915' }}>\n <Text style={{ color: '#fff', fontSize: 13, fontWeight: '700' }}>Add to bag</Text>\n </View>\n </View>\n </View>\n </TiltLayer>\n </TiltCard>\n <Text style={{ color: colors.mutedForeground, fontSize: 13, textAlign: 'center' }}>Free shipping · 2-year warranty</Text>\n </View>\n );\n}\n"
150
+ },
151
+ {
152
+ "name": "FeedCard",
153
+ "title": "Feed Card",
154
+ "code": "import React, { useState } from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport { TiltCard, TiltLayer } from '@/components/ui/tilt-card';\nimport { alpha, 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 card 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 FeedCard() {\n const { colors } = useKit();\n return (\n <View style={{ gap: 16 }}>\n <Header title=\"For you\" sub=\"Picked from places you saved\" />\n <TiltCard maxTilt={5} pressScale={1.015} glare=\"soft\" radius={20} onPress={() => {}} accessibilityLabel=\"Read: A fairytale weekend in Bavaria\" style={{ alignSelf: 'stretch' }}>\n <View style={{ backgroundColor: colors.card }}>\n <Image alt=\"\" source={photo(1040, 720, 360)} style={{ height: 170 }} />\n <View style={{ padding: 16, gap: 4 }}>\n <Text style={{ color: colors.mutedForeground, fontSize: 11, fontWeight: '700', letterSpacing: 1 }}>TRAVEL · 6 MIN READ</Text>\n <Text style={{ color: colors.foreground, fontSize: 18, fontWeight: '700', letterSpacing: -0.3 }}>A fairytale weekend in Bavaria</Text>\n <Text style={{ color: colors.mutedForeground, fontSize: 13, lineHeight: 19 }}>Castles, lakes and the best pretzels we had all year.</Text>\n </View>\n </View>\n </TiltCard>\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12, padding: 10, borderRadius: 16, backgroundColor: colors.card }}>\n <Image alt=\"\" source={photo(419, 160, 160)} style={{ width: 56, height: 56, borderRadius: 12, backgroundColor: colors.muted }} />\n <View style={{ flex: 1 }}>\n <Text style={{ color: colors.mutedForeground, fontSize: 11, fontWeight: '700', letterSpacing: 1 }}>UP NEXT · 4 MIN READ</Text>\n <Text style={{ color: colors.foreground, fontSize: 15, fontWeight: '600' }}>Lisbon by tram, end to end</Text>\n </View>\n </View>\n </View>\n );\n}\n"
155
+ }
156
+ ]
157
+ }