@expokit/cli 0.3.0 → 0.4.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 (165) hide show
  1. package/README.md +8 -4
  2. package/bin/expo-kit.js +137 -24
  3. package/bin/lib.mjs +110 -1
  4. package/bin/mcp.mjs +40 -18
  5. package/package.json +2 -2
  6. package/registry/_docs/assistant-app.json +47 -0
  7. package/registry/_docs/avatar.json +1 -1
  8. package/registry/_docs/badge.json +1 -1
  9. package/registry/_docs/bottom-nav.json +6 -6
  10. package/registry/_docs/button-3d.json +2 -2
  11. package/registry/_docs/calendar.json +5 -5
  12. package/registry/_docs/checkout.json +7 -1
  13. package/registry/_docs/confetti.json +3 -3
  14. package/registry/_docs/date-picker.json +4 -4
  15. package/registry/_docs/donut-shop.json +88 -0
  16. package/registry/_docs/drawer.json +4 -4
  17. package/registry/_docs/fintech-app.json +49 -0
  18. package/registry/_docs/floating-input.json +5 -5
  19. package/registry/_docs/food-app.json +47 -0
  20. package/registry/_docs/glass.json +1 -1
  21. package/registry/_docs/grain.json +80 -0
  22. package/registry/_docs/morphing-button-group.json +96 -0
  23. package/registry/_docs/orb-reveal.json +132 -0
  24. package/registry/_docs/otp-input.json +4 -4
  25. package/registry/_docs/password-input.json +3 -3
  26. package/registry/_docs/qr-code-button.json +122 -0
  27. package/registry/_docs/search-bar.json +3 -3
  28. package/registry/_docs/select.json +7 -7
  29. package/registry/_docs/settings.json +6 -0
  30. package/registry/_docs/skeleton.json +2 -2
  31. package/registry/_docs/slider.json +6 -6
  32. package/registry/_docs/spinner.json +1 -1
  33. package/registry/_docs/stepper.json +7 -7
  34. package/registry/_docs/textarea.json +2 -2
  35. package/registry/_docs/ticket-shape.json +1 -1
  36. package/registry/_docs/tilt-card.json +4 -4
  37. package/registry/_docs/time-picker.json +6 -6
  38. package/registry/_docs/timeline.json +2 -2
  39. package/registry/_docs/toast.json +8 -8
  40. package/registry/accordion/files/src/components/ui/accordion.tsx +5 -4
  41. package/registry/accordion/files/src/lib/kit.tsx +8 -5
  42. package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +9 -8
  43. package/registry/action-sheet/files/src/lib/kit.tsx +8 -5
  44. package/registry/alert/files/src/components/ui/alert.tsx +7 -4
  45. package/registry/alert/files/src/components/ui/button.tsx +4 -3
  46. package/registry/alert/files/src/lib/kit.tsx +8 -5
  47. package/registry/assistant-app.json +49 -0
  48. package/registry/avatar/files/src/components/ui/avatar.tsx +7 -4
  49. package/registry/avatar/files/src/lib/kit.tsx +8 -5
  50. package/registry/badge/files/src/components/ui/badge.tsx +21 -7
  51. package/registry/badge/files/src/lib/kit.tsx +8 -5
  52. package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +14 -7
  53. package/registry/bottom-nav/files/src/lib/kit.tsx +8 -5
  54. package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +7 -6
  55. package/registry/bottom-sheet/files/src/lib/kit.tsx +8 -5
  56. package/registry/button/files/src/components/ui/button.tsx +4 -3
  57. package/registry/button/files/src/lib/kit.tsx +8 -5
  58. package/registry/button-3d/files/src/components/ui/button-3d.tsx +3 -2
  59. package/registry/button-3d/files/src/lib/kit.tsx +8 -5
  60. package/registry/calendar/files/src/components/ui/calendar.tsx +9 -5
  61. package/registry/calendar/files/src/lib/kit.tsx +8 -5
  62. package/registry/card/files/src/components/ui/card.tsx +8 -6
  63. package/registry/card/files/src/lib/kit.tsx +8 -5
  64. package/registry/checkbox/files/src/components/ui/checkbox.tsx +6 -5
  65. package/registry/checkbox/files/src/lib/kit.tsx +8 -5
  66. package/registry/chip-group/files/src/components/ui/chip-group.tsx +4 -2
  67. package/registry/chip-group/files/src/lib/kit.tsx +8 -5
  68. package/registry/confetti/files/src/lib/kit.tsx +8 -5
  69. package/registry/coupon/files/src/components/ui/coupon.tsx +23 -20
  70. package/registry/coupon/files/src/components/ui/flip-card.tsx +1 -1
  71. package/registry/coupon/files/src/components/ui/tilt-card.tsx +2 -2
  72. package/registry/coupon/files/src/lib/kit.tsx +8 -5
  73. package/registry/date-picker/files/src/components/ui/calendar.tsx +9 -5
  74. package/registry/date-picker/files/src/components/ui/date-picker.tsx +2 -2
  75. package/registry/date-picker/files/src/lib/kit.tsx +8 -5
  76. package/registry/dialog/files/src/components/ui/dialog.tsx +12 -6
  77. package/registry/dialog/files/src/lib/kit.tsx +8 -5
  78. package/registry/donut-shop.json +18 -0
  79. package/registry/drawer/files/src/components/ui/drawer.tsx +25 -19
  80. package/registry/drawer/files/src/lib/kit.tsx +8 -5
  81. package/registry/fintech-app.json +57 -0
  82. package/registry/flip-card/files/src/components/ui/flip-card.tsx +1 -1
  83. package/registry/flip-card/files/src/lib/kit.tsx +8 -5
  84. package/registry/floating-input/files/src/components/ui/floating-input.tsx +16 -6
  85. package/registry/floating-input/files/src/lib/kit.tsx +8 -5
  86. package/registry/food-app.json +55 -0
  87. package/registry/grain/files/src/components/ui/grain.tsx +113 -0
  88. package/registry/{tag-input → grain}/files/src/lib/kit.tsx +8 -5
  89. package/registry/grain.json +17 -0
  90. package/registry/kit/files/src/lib/kit.tsx +8 -5
  91. package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +1 -1
  92. package/registry/liquidglass-tab/files/src/lib/tab-bar.ts +1 -1
  93. package/registry/list-item/files/src/components/ui/list-item.tsx +20 -16
  94. package/registry/list-item/files/src/lib/kit.tsx +8 -5
  95. package/registry/morphing-button-group.json +18 -0
  96. package/registry/orb-reveal.json +20 -0
  97. package/registry/otp-input/files/src/components/ui/otp-input.tsx +8 -6
  98. package/registry/otp-input/files/src/lib/kit.tsx +8 -5
  99. package/registry/password-input/files/src/components/ui/floating-input.tsx +16 -6
  100. package/registry/password-input/files/src/components/ui/password-input.tsx +2 -2
  101. package/registry/password-input/files/src/lib/kit.tsx +8 -5
  102. package/registry/payment-card/files/src/components/ui/flip-card.tsx +1 -1
  103. package/registry/payment-card/files/src/components/ui/payment-card.tsx +27 -14
  104. package/registry/payment-card/files/src/components/ui/tilt-card.tsx +2 -2
  105. package/registry/payment-card/files/src/lib/kit.tsx +8 -5
  106. package/registry/progress/files/src/components/ui/progress.tsx +8 -5
  107. package/registry/progress/files/src/lib/kit.tsx +8 -5
  108. package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +15 -11
  109. package/registry/progress-steps/files/src/lib/kit.tsx +8 -5
  110. package/registry/qr-code-button.json +18 -0
  111. package/registry/radio-group/files/src/components/ui/radio-group.tsx +10 -9
  112. package/registry/radio-group/files/src/lib/kit.tsx +8 -5
  113. package/registry/search-bar/files/src/components/ui/search-bar.tsx +13 -11
  114. package/registry/search-bar/files/src/lib/kit.tsx +8 -5
  115. package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +4 -2
  116. package/registry/segmented-control/files/src/lib/kit.tsx +8 -5
  117. package/registry/select/files/src/components/ui/select.tsx +3 -3
  118. package/registry/select/files/src/lib/kit.tsx +8 -5
  119. package/registry/skeleton/files/src/components/ui/skeleton.tsx +4 -4
  120. package/registry/skeleton/files/src/lib/kit.tsx +8 -5
  121. package/registry/slider/files/src/components/ui/slider.tsx +5 -4
  122. package/registry/slider/files/src/lib/kit.tsx +8 -5
  123. package/registry/spinner/files/src/components/ui/spinner.tsx +17 -12
  124. package/registry/spinner/files/src/lib/kit.tsx +8 -5
  125. package/registry/stateful-button/files/src/lib/kit.tsx +8 -5
  126. package/registry/stepper/files/src/components/ui/stepper.tsx +8 -4
  127. package/registry/stepper/files/src/lib/kit.tsx +8 -5
  128. package/registry/switch/files/src/components/ui/switch.tsx +4 -3
  129. package/registry/switch/files/src/lib/kit.tsx +8 -5
  130. package/registry/tabs/files/src/components/ui/tabs.tsx +10 -8
  131. package/registry/tabs/files/src/lib/kit.tsx +8 -5
  132. package/registry/text-animation/files/src/components/ui/text-animation.tsx +4 -4
  133. package/registry/text-animation/files/src/lib/kit.tsx +8 -5
  134. package/registry/textarea/files/src/components/ui/textarea.tsx +11 -9
  135. package/registry/textarea/files/src/lib/kit.tsx +8 -5
  136. package/registry/ticket-shape/files/src/lib/kit.tsx +8 -5
  137. package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +2 -2
  138. package/registry/tilt-card/files/src/lib/kit.tsx +8 -5
  139. package/registry/time-picker/files/src/components/ui/time-picker.tsx +2 -2
  140. package/registry/time-picker/files/src/lib/kit.tsx +8 -5
  141. package/registry/timeline/files/src/components/ui/avatar.tsx +7 -4
  142. package/registry/timeline/files/src/components/ui/timeline.tsx +12 -10
  143. package/registry/timeline/files/src/lib/kit.tsx +8 -5
  144. package/registry/toast/files/src/components/ui/button.tsx +4 -3
  145. package/registry/toast/files/src/components/ui/toast.tsx +13 -11
  146. package/registry/toast/files/src/lib/kit.tsx +8 -5
  147. package/schema/components.schema.json +1 -1
  148. package/registry/_docs/color-swatch.json +0 -82
  149. package/registry/_docs/kpi-card.json +0 -14
  150. package/registry/_docs/like-button.json +0 -92
  151. package/registry/_docs/morph-button.json +0 -128
  152. package/registry/_docs/pagination-dots.json +0 -108
  153. package/registry/_docs/shimmer-button.json +0 -98
  154. package/registry/_docs/tag-input.json +0 -148
  155. package/registry/color-swatch.json +0 -17
  156. package/registry/kpi-card/files/src/components/charts/kpi-card.tsx +0 -45
  157. package/registry/kpi-card.json +0 -14
  158. package/registry/like-button.json +0 -18
  159. package/registry/morph-button.json +0 -18
  160. package/registry/pagination-dots/files/src/components/ui/pagination-dots.tsx +0 -262
  161. package/registry/pagination-dots/files/src/lib/kit.tsx +0 -219
  162. package/registry/pagination-dots.json +0 -15
  163. package/registry/shimmer-button.json +0 -17
  164. package/registry/tag-input/files/src/components/ui/tag-input.tsx +0 -720
  165. package/registry/tag-input.json +0 -17
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "qr-code-button",
3
+ "category": "Buttons",
4
+ "aliases": [],
5
+ "exportName": "QrCodeButton",
6
+ "files": [
7
+ "src/components/ui/qr-code-button.tsx"
8
+ ],
9
+ "summary": "A pill that morphs into a card with a real, scannable QR code.",
10
+ "props": [
11
+ [
12
+ "value",
13
+ "string",
14
+ "—",
15
+ "What the code encodes: a URL, a payment link, a ticket id."
16
+ ],
17
+ [
18
+ "label",
19
+ "string",
20
+ "'Show QR Code'",
21
+ "Text on the pill."
22
+ ],
23
+ [
24
+ "copyLabel",
25
+ "string",
26
+ "'Copy'",
27
+ "Copy button text."
28
+ ],
29
+ [
30
+ "copiedLabel",
31
+ "string",
32
+ "'Copied'",
33
+ "Shown after Copy is pressed."
34
+ ],
35
+ [
36
+ "onCopy",
37
+ "(value: string) => void",
38
+ "—",
39
+ "Wire your clipboard here (expo-clipboard)."
40
+ ],
41
+ [
42
+ "open",
43
+ "boolean",
44
+ "—",
45
+ "Controlled state."
46
+ ],
47
+ [
48
+ "defaultOpen",
49
+ "boolean",
50
+ "false",
51
+ "Uncontrolled initial state."
52
+ ],
53
+ [
54
+ "onOpenChange",
55
+ "(open: boolean) => void",
56
+ "—",
57
+ "Opened or closed."
58
+ ],
59
+ [
60
+ "size",
61
+ "\"sm\" | \"md\" | \"lg\"",
62
+ "\"md\"",
63
+ "Pill height 36 / 44 / 52."
64
+ ],
65
+ [
66
+ "codeSize",
67
+ "number",
68
+ "168",
69
+ "Side of the code in points; the card wraps it."
70
+ ],
71
+ [
72
+ "color",
73
+ "string",
74
+ "white (dark) / primary (light)",
75
+ "Pill colour. The card stays white so the code scans."
76
+ ],
77
+ [
78
+ "accessibilityLabel",
79
+ "string",
80
+ "label",
81
+ "Screen reader label for the pill."
82
+ ],
83
+ [
84
+ "style",
85
+ "StyleProp<ViewStyle>",
86
+ "—",
87
+ "Root style."
88
+ ]
89
+ ],
90
+ "behavior": [
91
+ [
92
+ "Motion",
93
+ "Press swells the pill; it glides into the card while its label fades out and the code fades and scales in. Close glides it back."
94
+ ],
95
+ [
96
+ "Layout",
97
+ "Reserves the open card's size up front, so nothing around it moves and every control stays inside its own bounds (taps work on Android)."
98
+ ],
99
+ [
100
+ "Code",
101
+ "Encoded in the component: UTF-8 bytes, error correction M, smallest version that fits, mask chosen by the spec's penalty rules. Always dark on white so it scans in dark mode too."
102
+ ],
103
+ [
104
+ "Copy",
105
+ "Calls onCopy with the value and flips to a tick and \"Copied\" for 1.5 s."
106
+ ],
107
+ [
108
+ "Haptics",
109
+ "A light impact on open, a success tap on Copy, a tick on close."
110
+ ],
111
+ [
112
+ "Reduced motion",
113
+ "Opens and closes with a short fade."
114
+ ],
115
+ [
116
+ "Screen readers",
117
+ "A button with an expanded state; the code reads as \"QR code for …\"."
118
+ ]
119
+ ],
120
+ "usage": null,
121
+ "examples": []
122
+ }
@@ -134,17 +134,17 @@
134
134
  {
135
135
  "name": "WithSuggestions",
136
136
  "title": "With Suggestions",
137
- "code": "import React, { useEffect, useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\n\nconst SUGGESTIONS: SearchSuggestion[] = [\n { key: 'r1', label: 'Noise cancelling headphones', icon: 'recent' },\n { key: 'r2', label: 'Running shoes', icon: 'recent' },\n { key: 't1', label: 'Mechanical keyboard', icon: 'trending', hint: 'Trending' },\n { key: 't2', label: 'Standing desk', icon: 'trending', hint: '2.1k searches' },\n { key: 's1', label: 'Wireless charger', hint: 'Electronics' },\n { key: 's2', label: 'Coffee grinder', hint: 'Kitchen' },\n];\n\nexport default function WithSuggestions() {\n const { colors } = useKit();\n const [query, setQuery] = useState('');\n const [picked, setPicked] = useState<string | null>(null);\n return (\n // Reserve room for the open list, so the bar stays put when suggestions drop down below it.\n <View style={{ gap: 10, minHeight: 400 }}>\n <SearchBar\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search products\"\n suggestions={SUGGESTIONS}\n maxSuggestions={5}\n onSelectSuggestion={(item) => setPicked(item.label)}\n />\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{picked ? `Showing results for “${picked}”` : 'Tap the field to see recent and trending searches'}</Text>\n </View>\n );\n}\n"
137
+ "code": "import React, { useEffect, useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\nconst SUGGESTIONS: SearchSuggestion[] = [\n { key: 'r1', label: 'Noise cancelling headphones', icon: 'recent' },\n { key: 'r2', label: 'Running shoes', icon: 'recent' },\n { key: 't1', label: 'Mechanical keyboard', icon: 'trending', hint: 'Trending' },\n { key: 't2', label: 'Standing desk', icon: 'trending', hint: '2.1k searches' },\n { key: 's1', label: 'Wireless charger', hint: 'Electronics' },\n { key: 's2', label: 'Coffee grinder', hint: 'Kitchen' },\n];\n\nexport default function WithSuggestions({ screen }: DemoProps) {\n const { colors } = useKit();\n const [query, setQuery] = useState('');\n const [picked, setPicked] = useState<string | null>(null);\n return (\n // Reserve room for the open list, so the bar stays put when suggestions drop down below it.\n <View style={[{ gap: 10 }, screen ? { flex: 1 } : { minHeight: 400 }]}>\n <SearchBar\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search products\"\n suggestions={SUGGESTIONS}\n maxSuggestions={5}\n onSelectSuggestion={(item) => setPicked(item.label)}\n />\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{picked ? `Showing results for “${picked}”` : 'Tap the field to see recent and trending searches'}</Text>\n </View>\n );\n}\n"
138
138
  },
139
139
  {
140
140
  "name": "LiveResults",
141
141
  "title": "Live Results",
142
- "code": "import React, { useEffect, useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { padding: 16, gap: 12, borderRadius: radius.xl, borderWidth: StyleSheet.hairlineWidth, borderColor: colors.border, backgroundColor: colors.card },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst CONTACTS = [\n { name: 'Aarav Mehta', role: 'Design lead' },\n { name: 'Priya Nair', role: 'Product manager' },\n { name: 'Rohan Kapoor', role: 'iOS engineer' },\n { name: 'Sara Ali', role: 'Marketing' },\n { name: 'Vikram Rao', role: 'Backend engineer' },\n];\n\nexport default function LiveResults() {\n const { colors } = useKit();\n const [query, setQuery] = useState('');\n const [loading, setLoading] = useState(false);\n useEffect(() => {\n if (!query) return setLoading(false);\n setLoading(true);\n const id = setTimeout(() => setLoading(false), 600);\n return () => clearTimeout(id);\n }, [query]);\n const q = query.trim().toLowerCase();\n const results = CONTACTS.filter((c) => c.name.toLowerCase().includes(q) || c.role.toLowerCase().includes(q));\n return (\n <Card>\n <SearchBar variant=\"filled\" value={query} onChangeText={setQuery} loading={loading} placeholder=\"Search people\" />\n {loading ? (\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Searching your team…</Text>\n ) : results.length ? (\n results.slice(0, 4).map((c) => (\n <View key={c.name} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ width: 34, height: 34, borderRadius: 17, backgroundColor: alpha(colors.accent, 0.16), alignItems: 'center', justifyContent: 'center' }}>\n <Text style={{ fontSize: 13, fontWeight: '400', color: colors.accent }}>{c.name.split(' ').map((p) => p[0]).join('')}</Text>\n </View>\n <View>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>{c.name}</Text>\n <Text style={{ fontSize: 12.5, color: colors.mutedForeground }}>{c.role}</Text>\n </View>\n </View>\n ))\n ) : (\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>No one matches “{query}”</Text>\n )}\n </Card>\n );\n}\n"
142
+ "code": "import React, { useEffect, useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n { padding: 16, gap: 12 },\n screen\n ? { flex: 1, backgroundColor: colors.background }\n : { borderRadius: radius.xl, borderWidth: StyleSheet.hairlineWidth, borderColor: colors.border, backgroundColor: colors.card },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst CONTACTS = [\n { name: 'Aarav Mehta', role: 'Design lead' },\n { name: 'Priya Nair', role: 'Product manager' },\n { name: 'Rohan Kapoor', role: 'iOS engineer' },\n { name: 'Sara Ali', role: 'Marketing' },\n { name: 'Vikram Rao', role: 'Backend engineer' },\n];\n\nexport default function LiveResults({ screen }: DemoProps) {\n const { colors } = useKit();\n const [query, setQuery] = useState('');\n const [loading, setLoading] = useState(false);\n useEffect(() => {\n if (!query) return setLoading(false);\n setLoading(true);\n const id = setTimeout(() => setLoading(false), 600);\n return () => clearTimeout(id);\n }, [query]);\n const q = query.trim().toLowerCase();\n const results = CONTACTS.filter((c) => c.name.toLowerCase().includes(q) || c.role.toLowerCase().includes(q));\n return (\n <Card screen={screen}>\n <SearchBar variant=\"filled\" value={query} onChangeText={setQuery} loading={loading} placeholder=\"Search people\" />\n {loading ? (\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Searching your team…</Text>\n ) : results.length ? (\n results.slice(0, 4).map((c) => (\n <View key={c.name} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ width: 34, height: 34, borderRadius: 17, backgroundColor: alpha(colors.accent, 0.16), alignItems: 'center', justifyContent: 'center' }}>\n <Text style={{ fontSize: 13, fontWeight: '400', color: colors.accent }}>{c.name.split(' ').map((p) => p[0]).join('')}</Text>\n </View>\n <View>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>{c.name}</Text>\n <Text style={{ fontSize: 12.5, color: colors.mutedForeground }}>{c.role}</Text>\n </View>\n </View>\n ))\n ) : (\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>No one matches “{query}”</Text>\n )}\n </Card>\n );\n}\n"
143
143
  },
144
144
  {
145
145
  "name": "Minimal",
146
146
  "title": "Minimal",
147
- "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { padding: 16, gap: 12, borderRadius: radius.xl, borderWidth: StyleSheet.hairlineWidth, borderColor: colors.border, backgroundColor: colors.card },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Minimal() {\n const { colors } = useKit();\n return (\n <Card style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <Text style={{ fontSize: 22, fontWeight: '400', letterSpacing: -0.4, color: colors.foreground }}>Inbox</Text>\n <SearchBar variant=\"minimal\" align=\"right\" placeholder=\"Search mail\" style={{ flex: 1 }} />\n </Card>\n );\n}\n"
147
+ "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { SearchBar, type SearchSuggestion } from '@/components/ui/search-bar';\nimport { alpha, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n { padding: 16, gap: 12 },\n screen\n ? { flex: 1, backgroundColor: colors.background }\n : { borderRadius: radius.xl, borderWidth: StyleSheet.hairlineWidth, borderColor: colors.border, backgroundColor: colors.card },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Minimal({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <Text style={{ fontSize: 22, fontWeight: '400', letterSpacing: -0.4, color: colors.foreground }}>Inbox</Text>\n <SearchBar variant=\"minimal\" align=\"right\" placeholder=\"Search mail\" style={{ flex: 1 }} />\n </Card>\n );\n}\n"
148
148
  },
149
149
  {
150
150
  "name": "WithFilter",
@@ -241,37 +241,37 @@
241
241
  {
242
242
  "name": "Validation",
243
243
  "title": "Validation",
244
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Validation() {\n const { colors, radius } = useKit();\n const [size, setSize] = useState<string | null>(null);\n const [touched, setTouched] = useState(false);\n const missing = touched && !size;\n return (\n <Card>\n <Heading title=\"Merino crew sweater\" sub=\"₹3,499 · Oatmeal\" />\n <Select\n label=\"Size\"\n floatingLabel={false}\n placeholder=\"Choose a size\"\n size=\"sm\"\n value={size}\n surface={colors.card}\n onValueChange={(v) => {\n setSize(v);\n setTouched(true);\n }}\n options={[\n { label: 'XS', value: 'XS', disabled: true, description: 'Sold out' },\n { label: 'S', value: 'S', description: 'Chest 34–36\"' },\n { label: 'M', value: 'M', description: 'Chest 38–40\"' },\n { label: 'L', value: 'L', description: 'Chest 42–44\"' },\n { label: 'XL', value: 'XL', description: 'Chest 46–48\"' },\n ]}\n error={missing ? 'Pick a size to add this to your bag' : undefined}\n helper={missing ? undefined : 'Runs true to size · free exchanges'}\n />\n <Pressable\n onPress={() => setTouched(true)}\n accessibilityRole=\"button\"\n style={({ pressed }) => [s.button, { backgroundColor: colors.primary, borderRadius: radius.md, opacity: pressed ? 0.88 : 1 }]}\n >\n <Text style={[s.buttonText, { color: colors.primaryForeground }]}>Add to bag</Text>\n </Pressable>\n </Card>\n );\n}\n"
244
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Validation({ screen }: DemoProps) {\n const { colors, radius } = useKit();\n const [size, setSize] = useState<string | null>(null);\n const [touched, setTouched] = useState(false);\n const missing = touched && !size;\n return (\n <Card screen={screen}>\n <Heading title=\"Merino crew sweater\" sub=\"₹3,499 · Oatmeal\" />\n <Select\n label=\"Size\"\n floatingLabel={false}\n placeholder=\"Choose a size\"\n size=\"sm\"\n value={size}\n surface={colors.card}\n onValueChange={(v) => {\n setSize(v);\n setTouched(true);\n }}\n options={[\n { label: 'XS', value: 'XS', disabled: true, description: 'Sold out' },\n { label: 'S', value: 'S', description: 'Chest 34–36\"' },\n { label: 'M', value: 'M', description: 'Chest 38–40\"' },\n { label: 'L', value: 'L', description: 'Chest 42–44\"' },\n { label: 'XL', value: 'XL', description: 'Chest 46–48\"' },\n ]}\n error={missing ? 'Pick a size to add this to your bag' : undefined}\n helper={missing ? undefined : 'Runs true to size · free exchanges'}\n />\n <Pressable\n onPress={() => setTouched(true)}\n accessibilityRole=\"button\"\n style={({ pressed }) => [s.button, { backgroundColor: colors.primary, borderRadius: radius.md, opacity: pressed ? 0.88 : 1 }]}\n >\n <Text style={[s.buttonText, { color: colors.primaryForeground }]}>Add to bag</Text>\n </Pressable>\n </Card>\n );\n}\n"
245
245
  },
246
246
  {
247
247
  "name": "Plan",
248
248
  "title": "Plan",
249
- "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport Svg, { Circle, Path } from 'react-native-svg';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\n/** Small icon tile for option rows. */\nfunction Glyph({ d, tone }: { d: string; tone?: 'accent' | 'success' | 'warning' }) {\n const { colors, radius } = useKit();\n const c = tone ? colors[tone] : colors.mutedForeground;\n return (\n <View style={[s.glyph, { borderRadius: radius.scale(8), backgroundColor: tone ? alpha(c, 0.14) : colors.muted }]}>\n <Svg width={15} height={15} viewBox=\"0 0 24 24\">\n <Path d={d} stroke={c} strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </Svg>\n </View>\n );\n}\n\nconst ICON = {\n leaf: 'M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.5 19 2c1 2 2 4.2 2 8 0 5.5-4.8 10-10 10ZM2 21c0-3 1.9-5.4 5.2-6',\n bolt: 'M13 2 3 14h9l-1 8 10-12h-9l1-8Z',\n users: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8',\n building: 'M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18ZM6 12H4a2 2 0 0 0-2 2v8h4M18 9h2a2 2 0 0 1 2 2v11h-4M10 6h4M10 10h4M10 14h4M10 18h4',\n};\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Plan() {\n const { colors } = useKit();\n return (\n <Card>\n <Heading title=\"Workspace plan\" sub=\"Billed monthly · change anytime\" />\n <Select\n label=\"Plan\"\n floatingLabel={false}\n placeholder=\"Select a plan\"\n size=\"sm\"\n defaultValue=\"pro\"\n surface={colors.card}\n helper=\"You can switch plans later from billing.\"\n options={[\n { label: 'Hobby', value: 'hobby', description: 'Free · 1 project', icon: <Glyph d={ICON.leaf} tone=\"success\" /> },\n { label: 'Pro', value: 'pro', description: '₹499 / seat · unlimited projects', icon: <Glyph d={ICON.bolt} tone=\"accent\" /> },\n { label: 'Team', value: 'team', description: '₹1,499 / seat · SSO and audit log', icon: <Glyph d={ICON.users} tone=\"warning\" /> },\n { label: 'Enterprise', value: 'enterprise', description: 'Talk to sales', icon: <Glyph d={ICON.building} />, disabled: true },\n ]}\n />\n </Card>\n );\n}\n"
249
+ "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport Svg, { Circle, Path } from 'react-native-svg';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\n/** Small icon tile for option rows. */\nfunction Glyph({ d, tone }: { d: string; tone?: 'accent' | 'success' | 'warning' }) {\n const { colors, radius } = useKit();\n const c = tone ? colors[tone] : colors.mutedForeground;\n return (\n <View style={[s.glyph, { borderRadius: radius.scale(8), backgroundColor: tone ? alpha(c, 0.14) : colors.muted }]}>\n <Svg width={15} height={15} viewBox=\"0 0 24 24\">\n <Path d={d} stroke={c} strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" fill=\"none\" />\n </Svg>\n </View>\n );\n}\n\nconst ICON = {\n leaf: 'M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.5 19 2c1 2 2 4.2 2 8 0 5.5-4.8 10-10 10ZM2 21c0-3 1.9-5.4 5.2-6',\n bolt: 'M13 2 3 14h9l-1 8 10-12h-9l1-8Z',\n users: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8',\n building: 'M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18ZM6 12H4a2 2 0 0 0-2 2v8h4M18 9h2a2 2 0 0 1 2 2v11h-4M10 6h4M10 10h4M10 14h4M10 18h4',\n};\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Plan({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Heading title=\"Workspace plan\" sub=\"Billed monthly · change anytime\" />\n <Select\n label=\"Plan\"\n floatingLabel={false}\n placeholder=\"Select a plan\"\n size=\"sm\"\n defaultValue=\"pro\"\n surface={colors.card}\n helper=\"You can switch plans later from billing.\"\n options={[\n { label: 'Hobby', value: 'hobby', description: 'Free · 1 project', icon: <Glyph d={ICON.leaf} tone=\"success\" /> },\n { label: 'Pro', value: 'pro', description: '₹499 / seat · unlimited projects', icon: <Glyph d={ICON.bolt} tone=\"accent\" /> },\n { label: 'Team', value: 'team', description: '₹1,499 / seat · SSO and audit log', icon: <Glyph d={ICON.users} tone=\"warning\" /> },\n { label: 'Enterprise', value: 'enterprise', description: 'Talk to sales', icon: <Glyph d={ICON.building} />, disabled: true },\n ]}\n />\n </Card>\n );\n}\n"
250
250
  },
251
251
  {
252
252
  "name": "Country",
253
253
  "title": "Country",
254
- "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Country() {\n const { colors } = useKit();\n return (\n <Card>\n <Heading title=\"Shipping address\" sub=\"Where should we send this order?\" />\n <Select\n searchable\n label=\"Country\"\n floatingLabel={false}\n placeholder=\"Select country\"\n searchPlaceholder=\"Search countries\"\n size=\"sm\"\n defaultValue=\"DE\"\n surface={colors.card}\n options={[\n { label: 'United States', value: 'US', icon: flag('🇺🇸'), group: 'Americas' },\n { label: 'Canada', value: 'CA', icon: flag('🇨🇦'), group: 'Americas' },\n { label: 'Brazil', value: 'BR', icon: flag('🇧🇷'), group: 'Americas' },\n { label: 'United Kingdom', value: 'GB', icon: flag('🇬🇧'), group: 'Europe' },\n { label: 'Germany', value: 'DE', icon: flag('🇩🇪'), group: 'Europe' },\n { label: 'France', value: 'FR', icon: flag('🇫🇷'), group: 'Europe' },\n { label: 'India', value: 'IN', icon: flag('🇮🇳'), group: 'Asia Pacific' },\n { label: 'Japan', value: 'JP', icon: flag('🇯🇵'), group: 'Asia Pacific' },\n { label: 'Australia', value: 'AU', icon: flag('🇦🇺'), group: 'Asia Pacific' },\n ]}\n />\n </Card>\n );\n}\n"
254
+ "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Country({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Heading title=\"Shipping address\" sub=\"Where should we send this order?\" />\n <Select\n searchable\n label=\"Country\"\n floatingLabel={false}\n placeholder=\"Select country\"\n searchPlaceholder=\"Search countries\"\n size=\"sm\"\n defaultValue=\"DE\"\n surface={colors.card}\n options={[\n { label: 'United States', value: 'US', icon: flag('🇺🇸'), group: 'Americas' },\n { label: 'Canada', value: 'CA', icon: flag('🇨🇦'), group: 'Americas' },\n { label: 'Brazil', value: 'BR', icon: flag('🇧🇷'), group: 'Americas' },\n { label: 'United Kingdom', value: 'GB', icon: flag('🇬🇧'), group: 'Europe' },\n { label: 'Germany', value: 'DE', icon: flag('🇩🇪'), group: 'Europe' },\n { label: 'France', value: 'FR', icon: flag('🇫🇷'), group: 'Europe' },\n { label: 'India', value: 'IN', icon: flag('🇮🇳'), group: 'Asia Pacific' },\n { label: 'Japan', value: 'JP', icon: flag('🇯🇵'), group: 'Asia Pacific' },\n { label: 'Australia', value: 'AU', icon: flag('🇦🇺'), group: 'Asia Pacific' },\n ]}\n />\n </Card>\n );\n}\n"
255
255
  },
256
256
  {
257
257
  "name": "Assignees",
258
258
  "title": "Assignees",
259
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Assignees() {\n const { colors } = useKit();\n const [people, setPeople] = useState(['maya', 'leo']);\n return (\n <Card>\n <Heading title=\"Fix checkout crash on Android 14\" sub=\"ENG-2142 · In progress\" />\n <Select\n multiple\n searchable\n label=\"Assignees\"\n floatingLabel={false}\n placeholder=\"Add teammates\"\n searchPlaceholder=\"Search teammates\"\n size=\"sm\"\n values={people}\n onValuesChange={setPeople}\n surface={colors.card}\n options={[\n { label: 'Maya Chen', value: 'maya', description: 'Design', icon: avatar('MC', '#f472b6') },\n { label: 'Leo Martins', value: 'leo', description: 'iOS', icon: avatar('LM', '#60a5fa') },\n { label: 'Ana Ruiz', value: 'ana', description: 'Android', icon: avatar('AR', '#34d399') },\n { label: 'Sam Okafor', value: 'sam', description: 'Backend', icon: avatar('SO', '#fbbf24') },\n { label: 'Priya Nair', value: 'priya', description: 'QA', icon: avatar('PN', '#a78bfa') },\n ]}\n />\n </Card>\n );\n}\n"
259
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Assignees({ screen }: DemoProps) {\n const { colors } = useKit();\n const [people, setPeople] = useState(['maya', 'leo']);\n return (\n <Card screen={screen}>\n <Heading title=\"Fix checkout crash on Android 14\" sub=\"ENG-2142 · In progress\" />\n <Select\n multiple\n searchable\n label=\"Assignees\"\n floatingLabel={false}\n placeholder=\"Add teammates\"\n searchPlaceholder=\"Search teammates\"\n size=\"sm\"\n values={people}\n onValuesChange={setPeople}\n surface={colors.card}\n options={[\n { label: 'Maya Chen', value: 'maya', description: 'Design', icon: avatar('MC', '#f472b6') },\n { label: 'Leo Martins', value: 'leo', description: 'iOS', icon: avatar('LM', '#60a5fa') },\n { label: 'Ana Ruiz', value: 'ana', description: 'Android', icon: avatar('AR', '#34d399') },\n { label: 'Sam Okafor', value: 'sam', description: 'Backend', icon: avatar('SO', '#fbbf24') },\n { label: 'Priya Nair', value: 'priya', description: 'QA', icon: avatar('PN', '#a78bfa') },\n ]}\n />\n </Card>\n );\n}\n"
260
260
  },
261
261
  {
262
262
  "name": "Sheet",
263
263
  "title": "Sheet",
264
- "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Sheet() {\n const { colors } = useKit();\n return (\n <Card>\n <Heading title=\"Notifications\" sub=\"Opens as a sheet instead of a dropdown\" />\n <Select\n presentation=\"sheet\"\n label=\"Email digest\"\n floatingLabel={false}\n placeholder=\"How often?\"\n title=\"How often?\"\n size=\"sm\"\n defaultValue=\"weekly\"\n surface={colors.card}\n options={[\n { label: 'Daily', value: 'daily', description: 'Every morning at 8:00' },\n { label: 'Weekly', value: 'weekly', description: 'Mondays at 8:00' },\n { label: 'Monthly', value: 'monthly', description: 'First of the month' },\n { label: 'Never', value: 'never', description: 'Only security alerts' },\n ]}\n />\n </Card>\n );\n}\n"
264
+ "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Sheet({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Heading title=\"Notifications\" sub=\"Opens as a sheet instead of a dropdown\" />\n <Select\n presentation=\"sheet\"\n label=\"Email digest\"\n floatingLabel={false}\n placeholder=\"How often?\"\n title=\"How often?\"\n size=\"sm\"\n defaultValue=\"weekly\"\n surface={colors.card}\n options={[\n { label: 'Daily', value: 'daily', description: 'Every morning at 8:00' },\n { label: 'Weekly', value: 'weekly', description: 'Mondays at 8:00' },\n { label: 'Monthly', value: 'monthly', description: 'First of the month' },\n { label: 'Never', value: 'never', description: 'Only security alerts' },\n ]}\n />\n </Card>\n );\n}\n"
265
265
  },
266
266
  {
267
267
  "name": "Sizes",
268
268
  "title": "Sizes",
269
- "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Sizes() {\n const { colors } = useKit();\n const opts = ['Daily', 'Weekly', 'Monthly'];\n return (\n <Card style={{ gap: 16 }}>\n <Select size=\"sm\" label=\"Small\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select size=\"md\" label=\"Medium\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select size=\"lg\" label=\"Large\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select disabled label=\"Disabled\" floatingLabel={false} placeholder=\"Unavailable\" defaultValue=\"Daily\" options={opts} surface={colors.card} />\n </Card>\n );\n}\n"
269
+ "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Sizes({ screen }: DemoProps) {\n const { colors } = useKit();\n const opts = ['Daily', 'Weekly', 'Monthly'];\n return (\n <Card screen={screen} style={{ gap: 16 }}>\n <Select size=\"sm\" label=\"Small\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select size=\"md\" label=\"Medium\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select size=\"lg\" label=\"Large\" floatingLabel={false} placeholder=\"Pick one\" defaultValue=\"Weekly\" options={opts} surface={colors.card} />\n <Select disabled label=\"Disabled\" floatingLabel={false} placeholder=\"Unavailable\" defaultValue=\"Daily\" options={opts} surface={colors.card} />\n </Card>\n );\n}\n"
270
270
  },
271
271
  {
272
272
  "name": "Colors",
273
273
  "title": "Colors",
274
- "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport Svg, { Circle, Path } from 'react-native-svg';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\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 (\n <View\n style={[\n {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nfunction Dot({ color }: { color: string }) {\n return (\n <Svg width={14} height={14} viewBox=\"0 0 14 14\">\n <Circle cx={7} cy={7} r={5} fill={color} />\n </Svg>\n );\n}\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Colors() {\n const { colors } = useKit();\n return (\n <Card>\n <Heading title=\"Project labels\" sub=\"Accent colour drives focus, checks and chips\" />\n <Select\n multiple\n label=\"Labels\"\n floatingLabel={false}\n placeholder=\"Add labels\"\n size=\"sm\"\n accent={colors.success}\n defaultValues={['frontend', 'perf']}\n surface={colors.card}\n options={[\n { label: 'Frontend', value: 'frontend' },\n { label: 'Performance', value: 'perf' },\n { label: 'Accessibility', value: 'a11y' },\n { label: 'Docs', value: 'docs' },\n ]}\n />\n <Select\n label=\"Priority\"\n floatingLabel={false}\n placeholder=\"Set priority\"\n size=\"sm\"\n accent={colors.warning}\n defaultValue=\"p1\"\n surface={colors.card}\n options={[\n { label: 'Urgent', value: 'p0', icon: <Dot color={colors.danger} /> },\n { label: 'High', value: 'p1', icon: <Dot color={colors.warning} /> },\n { label: 'Medium', value: 'p2', icon: <Dot color={colors.accent} /> },\n { label: 'Low', value: 'p3', icon: <Dot color={colors.mutedForeground} /> },\n ]}\n />\n </Card>\n );\n}\n"
274
+ "code": "import { Pressable, StyleSheet, Text, View, type TextProps, type ViewProps } from 'react-native';\nimport Svg, { Circle, Path } from 'react-native-svg';\nimport { Select } from '@/components/ui/select';\nimport { alpha, readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 18, gap: 14 }\n : {\n backgroundColor: colors.card,\n borderColor: colors.border,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: radius.xl,\n padding: 18,\n gap: 14,\n },\n style,\n ]}\n {...rest}\n />\n );\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\nfunction Heading({ title, sub }: { title: string; sub?: string }) {\n return (\n <View style={s.heading}>\n <Ink style={s.title}>{title}</Ink>\n {sub ? (\n <Ink tone=\"muted\" style={s.sub}>\n {sub}\n </Ink>\n ) : null}\n </View>\n );\n}\n\nconst flag = (f: string) => <Text style={s.flag}>{f}</Text>;\n\nconst avatar = (initials: string, color: string) => (\n <View style={[s.avatar, { backgroundColor: color }]}>\n <Text style={[s.initials, { color: readableOn(color) }]}>{initials}</Text>\n </View>\n);\n\nfunction Dot({ color }: { color: string }) {\n return (\n <Svg width={14} height={14} viewBox=\"0 0 14 14\">\n <Circle cx={7} cy={7} r={5} fill={color} />\n </Svg>\n );\n}\n\nconst s = StyleSheet.create({\n heading: { gap: 3, marginBottom: 2 },\n title: { fontSize: 16, fontWeight: '400', letterSpacing: -0.2 },\n sub: { fontSize: 13, lineHeight: 18 },\n glyph: { width: 28, height: 28, alignItems: 'center', justifyContent: 'center' },\n flag: { fontSize: 18 },\n avatar: { width: 26, height: 26, borderRadius: 13, alignItems: 'center', justifyContent: 'center' },\n initials: { fontSize: 10.5, fontWeight: '400' },\n button: { height: 44, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n buttonText: { fontSize: 15, fontWeight: '400' },\n});\n\nexport default function Colors({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Heading title=\"Project labels\" sub=\"Accent colour drives focus, checks and chips\" />\n <Select\n multiple\n label=\"Labels\"\n floatingLabel={false}\n placeholder=\"Add labels\"\n size=\"sm\"\n accent={colors.success}\n defaultValues={['frontend', 'perf']}\n surface={colors.card}\n options={[\n { label: 'Frontend', value: 'frontend' },\n { label: 'Performance', value: 'perf' },\n { label: 'Accessibility', value: 'a11y' },\n { label: 'Docs', value: 'docs' },\n ]}\n />\n <Select\n label=\"Priority\"\n floatingLabel={false}\n placeholder=\"Set priority\"\n size=\"sm\"\n accent={colors.warning}\n defaultValue=\"p1\"\n surface={colors.card}\n options={[\n { label: 'Urgent', value: 'p0', icon: <Dot color={colors.danger} /> },\n { label: 'High', value: 'p1', icon: <Dot color={colors.warning} /> },\n { label: 'Medium', value: 'p2', icon: <Dot color={colors.accent} /> },\n { label: 'Low', value: 'p3', icon: <Dot color={colors.mutedForeground} /> },\n ]}\n />\n </Card>\n );\n}\n"
275
275
  }
276
276
  ]
277
277
  }
@@ -44,6 +44,12 @@
44
44
  "—",
45
45
  "Pressed Sign out."
46
46
  ],
47
+ [
48
+ "onBack",
49
+ "() => void",
50
+ "—",
51
+ "Shows a back button above the title, e.g. when Settings is pushed from a profile tab."
52
+ ],
47
53
  [
48
54
  "storageUsed",
49
55
  "string",
@@ -2,7 +2,7 @@
2
2
  "name": "skeleton",
3
3
  "category": "Feedback",
4
4
  "aliases": [],
5
- "exportName": "SkeletonGroup",
5
+ "exportName": "Skeleton",
6
6
  "files": [
7
7
  "src/components/ui/skeleton.tsx"
8
8
  ],
@@ -156,7 +156,7 @@
156
156
  {
157
157
  "name": "Nav",
158
158
  "title": "Nav",
159
- "code": "import { Skeleton } from '@/components/ui/skeleton';\n\nexport default function Nav() {\n return <Skeleton.Nav rows={6} tabCount={5} style={{ minHeight: 600 }} />;\n}\n"
159
+ "code": "import { Skeleton } from '@/components/ui/skeleton';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\nexport default function Nav({ screen }: DemoProps) {\n return <Skeleton.Nav rows={6} tabCount={5} style={screen ? undefined : { minHeight: 600 }} />;\n}\n"
160
160
  }
161
161
  ]
162
162
  }
@@ -146,32 +146,32 @@
146
146
  {
147
147
  "name": "ControlCenter",
148
148
  "title": "Control Center",
149
- "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function ControlCenter() {\n const [brightness, setBrightness] = useState(72);\n return (\n <Card>\n <Header title=\"Display & sound\" />\n <Slider\n variant=\"bar\"\n size=\"lg\"\n step={0}\n value={brightness}\n onValueChange={setBrightness}\n icon=\"sun-high\"\n showValue=\"always\"\n formatValue={(v) => `${Math.round(v)}%`}\n accessibilityLabel=\"Brightness\"\n />\n <Slider variant=\"bar\" size=\"lg\" defaultValue={40} icon=\"volume-high\" accessibilityLabel=\"Volume\" />\n </Card>\n );\n}\n"
149
+ "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function ControlCenter({ screen }: DemoProps) {\n const [brightness, setBrightness] = useState(72);\n return (\n <Card screen={screen}>\n <Header title=\"Display & sound\" />\n <Slider\n variant=\"bar\"\n size=\"lg\"\n step={0}\n value={brightness}\n onValueChange={setBrightness}\n icon=\"sun-high\"\n showValue=\"always\"\n formatValue={(v) => `${Math.round(v)}%`}\n accessibilityLabel=\"Brightness\"\n />\n <Slider variant=\"bar\" size=\"lg\" defaultValue={40} icon=\"volume-high\" accessibilityLabel=\"Volume\" />\n </Card>\n );\n}\n"
150
150
  },
151
151
  {
152
152
  "name": "Default",
153
153
  "title": "Default",
154
- "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Default() {\n const [volume, setVolume] = useState(64);\n return (\n <Card>\n <Header title=\"Media volume\" value={`${volume}%`} />\n <Slider\n value={volume}\n onValueChange={setVolume}\n leftIcon=\"volume-low\"\n rightIcon=\"volume-high\"\n formatValue={(v) => `${v}%`}\n accessibilityLabel=\"Media volume\"\n />\n </Card>\n );\n}\n"
154
+ "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Default({ screen }: DemoProps) {\n const [volume, setVolume] = useState(64);\n return (\n <Card screen={screen}>\n <Header title=\"Media volume\" value={`${volume}%`} />\n <Slider\n value={volume}\n onValueChange={setVolume}\n leftIcon=\"volume-low\"\n rightIcon=\"volume-high\"\n formatValue={(v) => `${v}%`}\n accessibilityLabel=\"Media volume\"\n />\n </Card>\n );\n}\n"
155
155
  },
156
156
  {
157
157
  "name": "PriceRange",
158
158
  "title": "Price Range",
159
- "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst PRICE_MAX = 2000;\n\nconst rupees = (v: number) => `₹${String(v).replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}`;\n\nconst PRICES = [2, 4, 7, 11, 16, 22, 30, 34, 38, 33, 29, 26, 21, 18, 14, 12, 9, 7, 5, 4, 3, 2, 2, 1];\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function PriceRange() {\n const { colors } = useKit();\n const [price, setPrice] = useState<[number, number]>([400, 1400]);\n const per = PRICE_MAX / PRICES.length;\n const results = PRICES.reduce((n, c, i) => (i * per + per / 2 >= price[0] && i * per + per / 2 <= price[1] ? n + c : n), 0);\n return (\n <Card>\n <Header title=\"Price\" value={`${rupees(price[0])} – ${rupees(price[1])}${price[1] === PRICE_MAX ? '+' : ''}`} />\n <Slider\n range\n min={0}\n max={PRICE_MAX}\n step={50}\n value={price}\n onValueChange={setPrice}\n histogram={PRICES}\n histogramHeight={40}\n showMinMax\n maxLabel={`${rupees(PRICE_MAX)}+`}\n formatValue={rupees}\n accessibilityLabel=\"Price\"\n />\n <Text style={[s.note, { color: colors.mutedForeground }]}>{results * 3} stays match</Text>\n </Card>\n );\n}\n"
159
+ "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst PRICE_MAX = 2000;\n\nconst rupees = (v: number) => `₹${String(v).replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}`;\n\nconst PRICES = [2, 4, 7, 11, 16, 22, 30, 34, 38, 33, 29, 26, 21, 18, 14, 12, 9, 7, 5, 4, 3, 2, 2, 1];\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function PriceRange({ screen }: DemoProps) {\n const { colors } = useKit();\n const [price, setPrice] = useState<[number, number]>([400, 1400]);\n const per = PRICE_MAX / PRICES.length;\n const results = PRICES.reduce((n, c, i) => (i * per + per / 2 >= price[0] && i * per + per / 2 <= price[1] ? n + c : n), 0);\n return (\n <Card screen={screen}>\n <Header title=\"Price\" value={`${rupees(price[0])} – ${rupees(price[1])}${price[1] === PRICE_MAX ? '+' : ''}`} />\n <Slider\n range\n min={0}\n max={PRICE_MAX}\n step={50}\n value={price}\n onValueChange={setPrice}\n histogram={PRICES}\n histogramHeight={40}\n showMinMax\n maxLabel={`${rupees(PRICE_MAX)}+`}\n formatValue={rupees}\n accessibilityLabel=\"Price\"\n />\n <Text style={[s.note, { color: colors.mutedForeground }]}>{results * 3} stays match</Text>\n </Card>\n );\n}\n"
160
160
  },
161
161
  {
162
162
  "name": "FontSize",
163
163
  "title": "Font Size",
164
- "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function FontSize() {\n const { colors } = useKit();\n const [size, setSize] = useState(17);\n const glyph = (px: number) => <Text style={{ color: colors.mutedForeground, fontSize: px, fontWeight: '400' }}>A</Text>;\n return (\n <Card>\n <Header title=\"Text size\" value={`${size} pt`} />\n <Text style={{ color: colors.foreground, fontSize: size, lineHeight: size * 1.35 }}>\n Your reading view will look like this.\n </Text>\n <Slider\n variant=\"stepped\"\n min={13}\n max={23}\n step={2}\n value={size}\n onValueChange={setSize}\n leftIcon={glyph(13)}\n rightIcon={glyph(21)}\n showValue=\"never\"\n accessibilityLabel=\"Text size\"\n />\n </Card>\n );\n}\n"
164
+ "code": "import React, { useState } from 'react';\nimport { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function FontSize({ screen }: DemoProps) {\n const { colors } = useKit();\n const [size, setSize] = useState(17);\n const glyph = (px: number) => <Text style={{ color: colors.mutedForeground, fontSize: px, fontWeight: '400' }}>A</Text>;\n return (\n <Card screen={screen}>\n <Header title=\"Text size\" value={`${size} pt`} />\n <Text style={{ color: colors.foreground, fontSize: size, lineHeight: size * 1.35 }}>\n Your reading view will look like this.\n </Text>\n <Slider\n variant=\"stepped\"\n min={13}\n max={23}\n step={2}\n value={size}\n onValueChange={setSize}\n leftIcon={glyph(13)}\n rightIcon={glyph(21)}\n showValue=\"never\"\n accessibilityLabel=\"Text size\"\n />\n </Card>\n );\n}\n"
165
165
  },
166
166
  {
167
167
  "name": "Sizes",
168
168
  "title": "Sizes",
169
- "code": "import { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Sizes() {\n const { colors } = useKit();\n const label = (t: string) => <Text style={[s.label, { color: colors.mutedForeground }]}>{t}</Text>;\n return (\n <Card>\n {label('Small')}\n <Slider size=\"sm\" defaultValue={25} accessibilityLabel=\"Small\" />\n {label('Medium')}\n <Slider size=\"md\" defaultValue={50} accessibilityLabel=\"Medium\" />\n {label('Large')}\n <Slider size=\"lg\" defaultValue={75} accessibilityLabel=\"Large\" />\n {label('Disabled')}\n <Slider defaultValue={40} disabled accessibilityLabel=\"Disabled\" />\n </Card>\n );\n}\n"
169
+ "code": "import { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Sizes({ screen }: DemoProps) {\n const { colors } = useKit();\n const label = (t: string) => <Text style={[s.label, { color: colors.mutedForeground }]}>{t}</Text>;\n return (\n <Card screen={screen}>\n {label('Small')}\n <Slider size=\"sm\" defaultValue={25} accessibilityLabel=\"Small\" />\n {label('Medium')}\n <Slider size=\"md\" defaultValue={50} accessibilityLabel=\"Medium\" />\n {label('Large')}\n <Slider size=\"lg\" defaultValue={75} accessibilityLabel=\"Large\" />\n {label('Disabled')}\n <Slider defaultValue={40} disabled accessibilityLabel=\"Disabled\" />\n </Card>\n );\n}\n"
170
170
  },
171
171
  {
172
172
  "name": "Colors",
173
173
  "title": "Colors",
174
- "code": "import { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[s.card, { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl }, style]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Colors() {\n const { colors } = useKit();\n return (\n <Card>\n <Header title=\"Daily goals\" />\n <Slider defaultValue={80} accent={colors.success} showValue=\"always\" formatValue={(v) => `${v}% steps`} accessibilityLabel=\"Steps\" />\n <Slider variant=\"bar\" size=\"sm\" defaultValue={55} accent={colors.warning} accessibilityLabel=\"Calories\" />\n <Slider variant=\"stepped\" min={0} max={10} step={1} defaultValue={3} accent={colors.danger} accessibilityLabel=\"Screen time hours\" />\n </Card>\n );\n}\n"
174
+ "code": "import { StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Slider } from '@/components/ui/slider';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ screen, style, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n s.card,\n screen\n ? { flex: 1, backgroundColor: colors.background, borderWidth: 0 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderRadius: radius.xl },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nfunction Header({ title, value }: { title: string; value?: string }) {\n const { colors } = useKit();\n return (\n <View style={s.head}>\n <Text style={[s.title, { color: colors.foreground }]}>{title}</Text>\n {value ? <Text style={[s.value, { color: colors.mutedForeground }]}>{value}</Text> : null}\n </View>\n );\n}\n\nconst s = StyleSheet.create({\n card: { padding: 16, borderWidth: StyleSheet.hairlineWidth, gap: 12 },\n head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' },\n title: { fontSize: 15, fontWeight: '400' },\n value: { fontSize: 15, fontWeight: '400', fontVariant: ['tabular-nums'] },\n label: { fontSize: 12, fontWeight: '400', letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: -8 },\n note: { fontSize: 13 },\n});\n\nexport default function Colors({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Header title=\"Daily goals\" />\n <Slider defaultValue={80} accent={colors.success} showValue=\"always\" formatValue={(v) => `${v}% steps`} accessibilityLabel=\"Steps\" />\n <Slider variant=\"bar\" size=\"sm\" defaultValue={55} accent={colors.warning} accessibilityLabel=\"Calories\" />\n <Slider variant=\"stepped\" min={0} max={10} step={1} defaultValue={3} accent={colors.danger} accessibilityLabel=\"Screen time hours\" />\n </Card>\n );\n}\n"
175
175
  }
176
176
  ]
177
177
  }
@@ -100,7 +100,7 @@
100
100
  {
101
101
  "name": "LoadingCard",
102
102
  "title": "Loading Card",
103
- "code": "import { Pressable, Text, View } from 'react-native';\nimport { Spinner, type SpinnerVariant } from '@/components/ui/spinner';\nimport { readableOn, useKit } from '@/lib/kit';\n\nexport default function LoadingCard() {\n const { colors, radius } = useKit();\n return (\n <View\n style={{\n alignSelf: 'stretch',\n alignItems: 'center',\n gap: 6,\n paddingVertical: 32,\n paddingHorizontal: 20,\n borderRadius: radius.lg,\n backgroundColor: colors.card,\n borderWidth: 1,\n borderColor: colors.border,\n }}\n >\n <Spinner size=\"xl\" track label=\"Preparing your itinerary\" labelPosition=\"bottom\" />\n <Text style={{ fontSize: 13, color: colors.mutedForeground, textAlign: 'center' }}>\n Checking 3 flights and 2 hotels\n </Text>\n </View>\n );\n}\n"
103
+ "code": "import { Pressable, Text, View } from 'react-native';\nimport { Spinner, type SpinnerVariant } from '@/components/ui/spinner';\nimport { readableOn, useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\nexport default function LoadingCard({ screen }: DemoProps) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n { alignSelf: 'stretch', alignItems: 'center', gap: 6, paddingVertical: 32, paddingHorizontal: 20 },\n screen\n ? { flex: 1, justifyContent: 'center', backgroundColor: colors.background }\n : { borderRadius: radius.lg, backgroundColor: colors.card, borderWidth: 1, borderColor: colors.border },\n ]}\n >\n <Spinner size=\"xl\" track label=\"Preparing your itinerary\" labelPosition=\"bottom\" />\n <Text style={{ fontSize: 13, color: colors.mutedForeground, textAlign: 'center' }}>\n Checking 3 flights and 2 hotels\n </Text>\n </View>\n );\n}\n"
104
104
  },
105
105
  {
106
106
  "name": "InlineStatus",
@@ -148,37 +148,37 @@
148
148
  {
149
149
  "name": "Cart",
150
150
  "title": "Cart",
151
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst eyebrow = { fontSize: 12, fontWeight: '400', letterSpacing: 0.6, textTransform: 'uppercase' } as const;\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nconst MENU = [\n { key: 'bowl', emoji: '🥗', name: 'Harvest bowl', note: 'Kale, squash, tahini', price: 349 },\n { key: 'ramen', emoji: '🍜', name: 'Miso ramen', note: 'Spicy · extra egg', price: 420 },\n { key: 'mochi', emoji: '🍡', name: 'Mochi trio', note: 'Matcha, yuzu, sesame', price: 180 },\n];\n\nexport default function Cart() {\n const { colors, radius } = useKit();\n const [qty, setQty] = useState<Record<string, number>>({ bowl: 1, ramen: 2, mochi: 0 });\n const total = MENU.reduce((sum, it) => sum + it.price * (qty[it.key] ?? 0), 0);\n return (\n <Card>\n <Text style={[eyebrow, { color: colors.mutedForeground }]}>Your order</Text>\n {MENU.map((it) => (\n <View key={it.key} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ width: 44, height: 44, borderRadius: radius.scale(12), backgroundColor: colors.muted, alignItems: 'center', justifyContent: 'center' }}>\n <Text style={{ fontSize: 22 }}>{it.emoji}</Text>\n </View>\n <View style={{ flex: 1 }}>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>{it.name}</Text>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{money(it.price)} · {it.note}</Text>\n </View>\n <Stepper\n variant=\"cart\"\n size=\"sm\"\n value={qty[it.key]}\n onValueChange={(n) => setQty((q) => ({ ...q, [it.key]: n }))}\n max={9}\n accessibilityLabel={`${it.name} quantity`}\n />\n </View>\n ))}\n <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: colors.border }} />\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' }}>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>Subtotal</Text>\n <Text style={{ fontSize: 18, fontWeight: '400', color: colors.foreground, fontVariant: ['tabular-nums'] }}>{money(total)}</Text>\n </View>\n </Card>\n );\n}\n"
151
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst eyebrow = { fontSize: 12, fontWeight: '400', letterSpacing: 0.6, textTransform: 'uppercase' } as const;\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nconst MENU = [\n { key: 'bowl', emoji: '🥗', name: 'Harvest bowl', note: 'Kale, squash, tahini', price: 349 },\n { key: 'ramen', emoji: '🍜', name: 'Miso ramen', note: 'Spicy · extra egg', price: 420 },\n { key: 'mochi', emoji: '🍡', name: 'Mochi trio', note: 'Matcha, yuzu, sesame', price: 180 },\n];\n\nexport default function Cart({ screen }: DemoProps) {\n const { colors, radius } = useKit();\n const [qty, setQty] = useState<Record<string, number>>({ bowl: 1, ramen: 2, mochi: 0 });\n const total = MENU.reduce((sum, it) => sum + it.price * (qty[it.key] ?? 0), 0);\n return (\n <Card screen={screen}>\n <Text style={[eyebrow, { color: colors.mutedForeground }]}>Your order</Text>\n {MENU.map((it) => (\n <View key={it.key} style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <View style={{ width: 44, height: 44, borderRadius: radius.scale(12), backgroundColor: colors.muted, alignItems: 'center', justifyContent: 'center' }}>\n <Text style={{ fontSize: 22 }}>{it.emoji}</Text>\n </View>\n <View style={{ flex: 1 }}>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>{it.name}</Text>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>{money(it.price)} · {it.note}</Text>\n </View>\n <Stepper\n variant=\"cart\"\n size=\"sm\"\n value={qty[it.key]}\n onValueChange={(n) => setQty((q) => ({ ...q, [it.key]: n }))}\n max={9}\n accessibilityLabel={`${it.name} quantity`}\n />\n </View>\n ))}\n <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: colors.border }} />\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'baseline' }}>\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.foreground }}>Subtotal</Text>\n <Text style={{ fontSize: 18, fontWeight: '400', color: colors.foreground, fontVariant: ['tabular-nums'] }}>{money(total)}</Text>\n </View>\n </Card>\n );\n}\n"
152
152
  },
153
153
  {
154
154
  "name": "Guests",
155
155
  "title": "Guests",
156
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Guests() {\n const { colors } = useKit();\n const [adults, setAdults] = useState(2);\n const [children, setChildren] = useState(0);\n const [infants, setInfants] = useState(0);\n const cap = 6;\n const rule = <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: colors.border }} />;\n return (\n <Card style={{ gap: 14 }}>\n <Stepper label=\"Adults\" description=\"Ages 13 or above\" value={adults} onValueChange={setAdults} min={1} max={cap - children} />\n {rule}\n <Stepper label=\"Children\" description=\"Ages 2–12\" value={children} onValueChange={setChildren} max={cap - adults} />\n {rule}\n <Stepper label=\"Infants\" description=\"Under 2\" value={infants} onValueChange={setInfants} max={5} />\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>\n This place has a maximum of {cap} guests, not including infants.\n </Text>\n </Card>\n );\n}\n"
156
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Guests({ screen }: DemoProps) {\n const { colors } = useKit();\n const [adults, setAdults] = useState(2);\n const [children, setChildren] = useState(0);\n const [infants, setInfants] = useState(0);\n const cap = 6;\n const rule = <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: colors.border }} />;\n return (\n <Card screen={screen} style={{ gap: 14 }}>\n <Stepper label=\"Adults\" description=\"Ages 13 or above\" value={adults} onValueChange={setAdults} min={1} max={cap - children} />\n {rule}\n <Stepper label=\"Children\" description=\"Ages 2–12\" value={children} onValueChange={setChildren} max={cap - adults} />\n {rule}\n <Stepper label=\"Infants\" description=\"Under 2\" value={infants} onValueChange={setInfants} max={5} />\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>\n This place has a maximum of {cap} guests, not including infants.\n </Text>\n </Card>\n );\n}\n"
157
157
  },
158
158
  {
159
159
  "name": "AddToBag",
160
160
  "title": "Add To Bag",
161
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nexport default function AddToBag() {\n const { colors, radius } = useKit();\n const [qty, setQty] = useState(1);\n const price = 1899;\n return (\n <Card>\n <View style={{ gap: 2 }}>\n <Text style={{ fontSize: 17, fontWeight: '400', color: colors.foreground }}>Linen overshirt</Text>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Sand · Size M · Free returns</Text>\n </View>\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <Stepper variant=\"filled\" size=\"lg\" value={qty} onValueChange={setQty} min={1} max={10} accessibilityLabel=\"Quantity\" />\n <Pressable\n accessibilityRole=\"button\"\n style={({ pressed }) => ({\n flex: 1,\n height: 44,\n borderRadius: radius.capsule(44),\n backgroundColor: colors.primary,\n alignItems: 'center',\n justifyContent: 'center',\n opacity: pressed ? 0.85 : 1,\n })}\n >\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.primaryForeground, fontVariant: ['tabular-nums'] }}>\n Add to bag · {money(price * qty)}\n </Text>\n </Pressable>\n </View>\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>Only 10 left — hold + to add faster.</Text>\n </Card>\n );\n}\n"
161
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nexport default function AddToBag({ screen }: DemoProps) {\n const { colors, radius } = useKit();\n const [qty, setQty] = useState(1);\n const price = 1899;\n return (\n <Card screen={screen}>\n <View style={{ gap: 2 }}>\n <Text style={{ fontSize: 17, fontWeight: '400', color: colors.foreground }}>Linen overshirt</Text>\n <Text style={{ fontSize: 13, color: colors.mutedForeground }}>Sand · Size M · Free returns</Text>\n </View>\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>\n <Stepper variant=\"filled\" size=\"lg\" value={qty} onValueChange={setQty} min={1} max={10} accessibilityLabel=\"Quantity\" />\n <Pressable\n accessibilityRole=\"button\"\n style={({ pressed }) => ({\n flex: 1,\n height: 44,\n borderRadius: radius.capsule(44),\n backgroundColor: colors.primary,\n alignItems: 'center',\n justifyContent: 'center',\n opacity: pressed ? 0.85 : 1,\n })}\n >\n <Text style={{ fontSize: 15, fontWeight: '400', color: colors.primaryForeground, fontVariant: ['tabular-nums'] }}>\n Add to bag · {money(price * qty)}\n </Text>\n </Pressable>\n </View>\n <Text style={{ fontSize: 12, color: colors.mutedForeground }}>Only 10 left — hold + to add faster.</Text>\n </Card>\n );\n}\n"
162
162
  },
163
163
  {
164
164
  "name": "Menu",
165
165
  "title": "Menu",
166
- "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst eyebrow = { fontSize: 12, fontWeight: '400', letterSpacing: 0.6, textTransform: 'uppercase' } as const;\n\nexport default function Menu() {\n const { colors } = useKit();\n return (\n <Card>\n <Text style={[eyebrow, { color: colors.mutedForeground }]}>Popular</Text>\n <Stepper variant=\"cart\" addLabel=\"Add\" label=\"Pistachio croissant\" description=\"₹220 · Baked this morning\" accessibilityLabel=\"Pistachio croissant\" />\n <Stepper variant=\"cart\" addLabel=\"Add\" label=\"Iced oat latte\" description=\"₹280 · 16 oz\" defaultValue={1} accessibilityLabel=\"Iced oat latte\" />\n </Card>\n );\n}\n"
166
+ "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst eyebrow = { fontSize: 12, fontWeight: '400', letterSpacing: 0.6, textTransform: 'uppercase' } as const;\n\nexport default function Menu({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen}>\n <Text style={[eyebrow, { color: colors.mutedForeground }]}>Popular</Text>\n <Stepper variant=\"cart\" addLabel=\"Add\" label=\"Pistachio croissant\" description=\"₹220 · Baked this morning\" accessibilityLabel=\"Pistachio croissant\" />\n <Stepper variant=\"cart\" addLabel=\"Add\" label=\"Iced oat latte\" description=\"₹280 · 16 oz\" defaultValue={1} accessibilityLabel=\"Iced oat latte\" />\n </Card>\n );\n}\n"
167
167
  },
168
168
  {
169
169
  "name": "Formatted",
170
170
  "title": "Formatted",
171
- "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nexport default function Formatted() {\n return (\n <Card style={{ gap: 16 }}>\n <Stepper variant=\"filled\" size=\"sm\" label=\"Nights\" description=\"Check-in Fri, Oct 24\" defaultValue={3} min={1} max={28} suffix={(n) => (n === 1 ? 'night' : 'nights')} />\n <Stepper variant=\"filled\" size=\"sm\" label=\"Driver tip\" description=\"100% goes to your driver\" defaultValue={50} step={10} min={0} max={500} format={money} />\n <Stepper variant=\"filled\" size=\"sm\" label=\"Search radius\" defaultValue={2.5} step={0.5} min={0.5} max={10} suffix=\"km\" />\n <Stepper variant=\"compact\" label=\"Seats\" description=\"₹499 per seat / month\" defaultValue={5} min={1} max={50} />\n </Card>\n );\n}\n"
171
+ "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nconst money = (n: number) => {\n const [int, frac] = n.toFixed(2).split('.');\n return `₹${int.replace(/(\\d)(?=(\\d\\d)+\\d$)/g, '$1,')}${frac === '00' ? '' : `.${frac}`}`;\n};\n\nexport default function Formatted({ screen }: DemoProps) {\n return (\n <Card screen={screen} style={{ gap: 16 }}>\n <Stepper variant=\"filled\" size=\"sm\" label=\"Nights\" description=\"Check-in Fri, Oct 24\" defaultValue={3} min={1} max={28} suffix={(n) => (n === 1 ? 'night' : 'nights')} />\n <Stepper variant=\"filled\" size=\"sm\" label=\"Driver tip\" description=\"100% goes to your driver\" defaultValue={50} step={10} min={0} max={500} format={money} />\n <Stepper variant=\"filled\" size=\"sm\" label=\"Search radius\" defaultValue={2.5} step={0.5} min={0.5} max={10} suffix=\"km\" />\n <Stepper variant=\"compact\" label=\"Seats\" description=\"₹499 per seat / month\" defaultValue={5} min={1} max={50} />\n </Card>\n );\n}\n"
172
172
  },
173
173
  {
174
174
  "name": "Sizes",
175
175
  "title": "Sizes",
176
- "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Sizes() {\n const { colors } = useKit();\n const row = (name: string, el: React.ReactNode) => (\n <View key={name} style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 48 }}>\n <Text style={{ fontSize: 13, fontWeight: '400', color: colors.mutedForeground }}>{name}</Text>\n {el}\n </View>\n );\n return (\n <Card style={{ gap: 4 }}>\n {row('Small', <Stepper size=\"sm\" defaultValue={2} max={20} accessibilityLabel=\"Small stepper\" />)}\n {row('Medium', <Stepper size=\"md\" defaultValue={2} max={20} accessibilityLabel=\"Medium stepper\" />)}\n {row('Large', <Stepper size=\"lg\" defaultValue={2} max={20} accessibilityLabel=\"Large stepper\" />)}\n {row('Compact', <Stepper variant=\"compact\" defaultValue={2} max={20} accessibilityLabel=\"Compact stepper\" />)}\n </Card>\n );\n}\n"
176
+ "code": "import React, { useState } from 'react';\nimport { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Sizes({ screen }: DemoProps) {\n const { colors } = useKit();\n const row = (name: string, el: React.ReactNode) => (\n <View key={name} style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', minHeight: 48 }}>\n <Text style={{ fontSize: 13, fontWeight: '400', color: colors.mutedForeground }}>{name}</Text>\n {el}\n </View>\n );\n return (\n <Card screen={screen} style={{ gap: 4 }}>\n {row('Small', <Stepper size=\"sm\" defaultValue={2} max={20} accessibilityLabel=\"Small stepper\" />)}\n {row('Medium', <Stepper size=\"md\" defaultValue={2} max={20} accessibilityLabel=\"Medium stepper\" />)}\n {row('Large', <Stepper size=\"lg\" defaultValue={2} max={20} accessibilityLabel=\"Large stepper\" />)}\n {row('Compact', <Stepper variant=\"compact\" defaultValue={2} max={20} accessibilityLabel=\"Compact stepper\" />)}\n </Card>\n );\n}\n"
177
177
  },
178
178
  {
179
179
  "name": "Colors",
180
180
  "title": "Colors",
181
- "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\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 (\n <View\n style={[\n { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Colors() {\n const { colors } = useKit();\n return (\n <Card style={{ gap: 16 }}>\n <Stepper variant=\"filled\" accent={colors.success} label=\"Water\" description=\"Glasses today\" defaultValue={6} max={12} />\n <Stepper variant=\"compact\" accent={colors.warning} label=\"Espresso shots\" defaultValue={2} max={4} />\n <Stepper variant=\"cart\" accent={colors.danger} addLabel=\"Add\" label=\"Hot sauce\" description=\"₹30 each\" />\n </Card>\n );\n}\n"
181
+ "code": "import { Pressable, StyleSheet, Text, View, type ViewProps } from 'react-native';\nimport { Stepper } from '@/components/ui/stepper';\nimport { useKit } from '@/lib/kit';\n\n/** From the Expo Go viewer: `screen` = this IS the phone screen, so no mock frame; `bottomInset` = home indicator. */\ntype DemoProps = { screen?: boolean; bottomInset?: number };\n\n/** Demo card that follows the kit theme, so the docs radius / accent picker reshapes it too. */\nfunction Card({ style, screen, ...rest }: ViewProps & { screen?: boolean }) {\n const { colors, radius } = useKit();\n return (\n <View\n style={[\n screen\n ? { flex: 1, backgroundColor: colors.background, padding: 16, gap: 12 }\n : { backgroundColor: colors.card, borderColor: colors.border, borderWidth: StyleSheet.hairlineWidth, borderRadius: radius.xl, padding: 16, gap: 12 },\n style,\n ]}\n {...rest}\n />\n );\n}\n\nexport default function Colors({ screen }: DemoProps) {\n const { colors } = useKit();\n return (\n <Card screen={screen} style={{ gap: 16 }}>\n <Stepper variant=\"filled\" accent={colors.success} label=\"Water\" description=\"Glasses today\" defaultValue={6} max={12} />\n <Stepper variant=\"compact\" accent={colors.warning} label=\"Espresso shots\" defaultValue={2} max={4} />\n <Stepper variant=\"cart\" accent={colors.danger} addLabel=\"Add\" label=\"Hot sauce\" description=\"₹30 each\" />\n </Card>\n );\n}\n"
182
182
  }
183
183
  ]
184
184
  }