@vvedantb/native-ui 0.17.2 → 0.18.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 (220) hide show
  1. package/dist/AlertDialog.jsx +123 -0
  2. package/dist/AmbientBackground.jsx +73 -0
  3. package/dist/ArtifactList.jsx +59 -0
  4. package/dist/Avatar.jsx +285 -0
  5. package/dist/Badge.jsx +154 -0
  6. package/dist/BottomSheetContainer.jsx +208 -0
  7. package/dist/BulkActionBar.jsx +717 -0
  8. package/dist/Button.jsx +344 -0
  9. package/dist/CaptureButton.jsx +104 -0
  10. package/dist/Card.jsx +371 -0
  11. package/dist/Checkbox.jsx +177 -0
  12. package/dist/Chip.jsx +79 -0
  13. package/dist/ColorSwatches.jsx +159 -0
  14. package/dist/ConfirmDialog.jsx +157 -0
  15. package/dist/DateTimeField.jsx +204 -0
  16. package/dist/Dialog.jsx +614 -0
  17. package/dist/DividedList.jsx +120 -0
  18. package/dist/DropdownMenu.jsx +849 -0
  19. package/dist/EmptyState.jsx +434 -0
  20. package/dist/ExpoWebRoot.jsx +134 -0
  21. package/dist/FloatingFAB.jsx +95 -0
  22. package/dist/FloatingSurface.jsx +226 -0
  23. package/dist/FloatingTabBar.jsx +403 -0
  24. package/dist/HeaderIconButton.jsx +53 -0
  25. package/dist/IconButton.jsx +157 -0
  26. package/dist/Input.jsx +96 -0
  27. package/dist/Label.jsx +96 -0
  28. package/dist/LabeledSwitchRow.jsx +170 -0
  29. package/dist/LiquidGlass.jsx +2 -0
  30. package/dist/ListRow.jsx +281 -0
  31. package/dist/LoadingState.jsx +205 -0
  32. package/dist/PageIndicator.jsx +128 -0
  33. package/dist/PageTitle.jsx +205 -0
  34. package/dist/Pager.jsx +105 -0
  35. package/dist/PasswordInput.jsx +120 -0
  36. package/dist/PillTabs.jsx +300 -0
  37. package/dist/PinnedBotTile.jsx +212 -0
  38. package/dist/Progress.jsx +147 -0
  39. package/dist/SafeAreaContainer.jsx +38 -0
  40. package/dist/ScreenContainer.jsx +117 -0
  41. package/dist/SearchInput.jsx +150 -0
  42. package/dist/SectionLabel.jsx +128 -0
  43. package/dist/Select.jsx +223 -0
  44. package/dist/Separator.jsx +95 -0
  45. package/dist/Sheet.jsx +343 -0
  46. package/dist/SheetRow.jsx +198 -0
  47. package/dist/Skeleton.jsx +311 -0
  48. package/dist/Spinner.jsx +195 -0
  49. package/dist/StackPageHeader.jsx +160 -0
  50. package/dist/StatGrid.jsx +74 -0
  51. package/dist/StatusDot.jsx +129 -0
  52. package/dist/SurfaceRow.jsx +143 -0
  53. package/dist/SwipeableRow.jsx +50 -0
  54. package/dist/Switch.jsx +130 -0
  55. package/dist/Tabs.jsx +385 -0
  56. package/dist/Textarea.jsx +103 -0
  57. package/dist/ThemeToggle.jsx +78 -0
  58. package/dist/Toast.jsx +396 -0
  59. package/dist/ai/activity-step-detail.jsx +179 -0
  60. package/dist/ai/activity-step-label.js +816 -0
  61. package/dist/ai/activity-step-types.js +14 -0
  62. package/dist/ai/activity-step.jsx +98 -0
  63. package/dist/ai/activity-tasks-utils.js +172 -0
  64. package/dist/ai/activity-timeline.js +47 -0
  65. package/dist/ai/attachments.jsx +258 -0
  66. package/dist/ai/card-button.jsx +188 -0
  67. package/dist/ai/chain-of-thought.jsx +459 -0
  68. package/dist/ai/chat-jump-rail.jsx +57 -0
  69. package/dist/ai/chat-text.js +44 -0
  70. package/dist/ai/chat-thread.jsx +135 -0
  71. package/dist/ai/choice-question.jsx +925 -0
  72. package/dist/ai/code-block.jsx +574 -0
  73. package/dist/ai/collapsible.jsx +275 -0
  74. package/dist/ai/conversation.jsx +723 -0
  75. package/dist/ai/file-chip.jsx +198 -0
  76. package/dist/ai/icon-button.jsx +179 -0
  77. package/dist/ai/index.js +37 -0
  78. package/dist/ai/message-action-sheet.jsx +408 -0
  79. package/dist/ai/message-quote.jsx +241 -0
  80. package/dist/ai/message.jsx +739 -0
  81. package/dist/ai/prompt-input-menu.jsx +365 -0
  82. package/dist/ai/prompt-input.jsx +626 -0
  83. package/dist/ai/reasoning.jsx +446 -0
  84. package/dist/ai/reply-quote-chip.jsx +278 -0
  85. package/dist/ai/response-text.jsx +130 -0
  86. package/dist/ai/shimmer.jsx +149 -0
  87. package/dist/ai/sources.jsx +260 -0
  88. package/dist/ai/subagent-cards.jsx +645 -0
  89. package/dist/ai/suggestion.jsx +186 -0
  90. package/dist/ai/tool-approval-card.jsx +359 -0
  91. package/dist/ai/trace.jsx +728 -0
  92. package/dist/ai/unified-diff.jsx +280 -0
  93. package/dist/ai/use-streaming-disclosure.js +70 -0
  94. package/dist/auth/AuthProviders.jsx +27 -0
  95. package/dist/auth/AuthScreen.jsx +292 -0
  96. package/dist/auth/GoogleSignInButton.jsx +188 -0
  97. package/dist/auth/SecondFactorScreen.jsx +133 -0
  98. package/dist/auth/SignInScreen.jsx +482 -0
  99. package/dist/auth/authErrors.js +131 -0
  100. package/dist/auth/index.js +11 -0
  101. package/dist/auth/totp.js +378 -0
  102. package/dist/blur.js +36 -0
  103. package/dist/brand/AppIcons.jsx +118 -0
  104. package/dist/brand/AppMark.jsx +128 -0
  105. package/dist/brand/AppWordmark.jsx +138 -0
  106. package/dist/brand/GoogleMark.jsx +71 -0
  107. package/dist/brand/ProviderIcon.jsx +192 -0
  108. package/dist/brand/familyApps.js +33 -0
  109. package/dist/brand/index.js +11 -0
  110. package/dist/brand/svg.js +252 -0
  111. package/dist/brand/vProAppBenefits.js +19 -0
  112. package/dist/cn.js +5 -0
  113. package/dist/colors.js +15 -0
  114. package/dist/configureTheme.js +72 -0
  115. package/dist/controlStyles.js +520 -0
  116. package/dist/definiteSize.js +12 -0
  117. package/dist/dialogLayout.js +18 -0
  118. package/dist/entries/ai.js +4 -0
  119. package/dist/entries/ambient.js +3 -0
  120. package/dist/entries/auth.js +5 -0
  121. package/dist/entries/bottom-sheet.js +2 -0
  122. package/dist/entries/brand.js +2 -0
  123. package/dist/entries/button.js +2 -0
  124. package/dist/entries/date-time.js +3 -0
  125. package/dist/entries/expo-router.js +4 -0
  126. package/dist/entries/expo-web-root.js +3 -0
  127. package/dist/entries/floating.js +7 -0
  128. package/dist/entries/gesture-handler.js +4 -0
  129. package/dist/entries/keyboard-controller.js +4 -0
  130. package/dist/entries/layout.js +16 -0
  131. package/dist/entries/markdown.js +4 -0
  132. package/dist/entries/marketing.js +3 -0
  133. package/dist/entries/page-title.js +7 -0
  134. package/dist/entries/password-input.js +3 -0
  135. package/dist/entries/primitives.js +57 -0
  136. package/dist/entries/search-input.js +3 -0
  137. package/dist/entries/tab-bar.js +4 -0
  138. package/dist/entries/theme.js +7 -0
  139. package/dist/entries/toast.js +5 -0
  140. package/dist/entries/video.js +3 -0
  141. package/dist/entries/webview.js +4 -0
  142. package/dist/examples/AiChatGallery.jsx +509 -0
  143. package/dist/examples/ParityGallery.jsx +1307 -0
  144. package/dist/floating.js +62 -0
  145. package/dist/glassBlur.jsx +145 -0
  146. package/dist/gradient.js +17 -0
  147. package/dist/haptics.js +44 -0
  148. package/dist/highlight.js +382 -0
  149. package/dist/index.js +85 -0
  150. package/dist/initials.js +4 -0
  151. package/dist/loadingGrid.js +81 -0
  152. package/dist/markdown/Markdown.jsx +515 -0
  153. package/dist/markdown/MarkdownTable.jsx +443 -0
  154. package/dist/markdown/tableText.js +68 -0
  155. package/dist/marketing/PricingModal.jsx +608 -0
  156. package/dist/marketing/UpgradeToProCard.jsx +164 -0
  157. package/dist/marketing/pricing.js +34 -0
  158. package/dist/media/ImageGallery.jsx +580 -0
  159. package/dist/media/MediaCard.jsx +162 -0
  160. package/dist/media/imageGrid.js +54 -0
  161. package/dist/motion.js +33 -0
  162. package/dist/pagerSwipe.js +104 -0
  163. package/dist/palette.js +104 -0
  164. package/dist/primitives/button.jsx +127 -0
  165. package/dist/primitives/card.jsx +249 -0
  166. package/dist/primitives/icon.jsx +37 -0
  167. package/dist/primitives/input.jsx +56 -0
  168. package/dist/primitives/keyboard-controller.jsx +207 -0
  169. package/dist/primitives/keyboard-parts.jsx +75 -0
  170. package/dist/primitives/native-only-animated-view.jsx +68 -0
  171. package/dist/primitives/overlay.jsx +391 -0
  172. package/dist/primitives/pager-gesture.jsx +131 -0
  173. package/dist/primitives/select-host.jsx +103 -0
  174. package/dist/primitives/select.jsx +555 -0
  175. package/dist/primitives/sheet-drag.jsx +420 -0
  176. package/dist/primitives/sheet-gesture.jsx +219 -0
  177. package/dist/primitives/swipe-row-gesture.jsx +341 -0
  178. package/dist/primitives/switch.jsx +105 -0
  179. package/dist/primitives/text.jsx +145 -0
  180. package/dist/primitives/toast-drag-gesture.jsx +94 -0
  181. package/dist/primitives/use-controllable-state.js +40 -0
  182. package/dist/primitives/web-click-guard.js +69 -0
  183. package/dist/push.js +166 -0
  184. package/dist/relativeTime.js +70 -0
  185. package/dist/router/RouterStackPageHeader.jsx +53 -0
  186. package/dist/selectA11y.js +32 -0
  187. package/dist/settings/MoreFromProjectV.jsx +168 -0
  188. package/dist/settings/SettingsEmptyState.jsx +102 -0
  189. package/dist/settings/SettingsField.jsx +49 -0
  190. package/dist/settings/SettingsSection.jsx +101 -0
  191. package/dist/settings/SettingsStack.jsx +17 -0
  192. package/dist/settings/SettingsToggleRow.jsx +163 -0
  193. package/dist/settings/projectVMobileApps.js +126 -0
  194. package/dist/settings/relaxedSizeStyle.js +11 -0
  195. package/dist/sheetDrag.js +76 -0
  196. package/dist/svgA11y.js +46 -0
  197. package/dist/swipeRow.js +161 -0
  198. package/dist/tabBarRoutes.js +41 -0
  199. package/dist/tabIndicator.js +139 -0
  200. package/dist/tailwind-preset.cjs +255 -0
  201. package/dist/tailwind-preset.d.cts +55 -0
  202. package/dist/theme.jsx +62 -0
  203. package/dist/toastChrome.js +110 -0
  204. package/dist/toastDrag.js +51 -0
  205. package/dist/toastStore.js +54 -0
  206. package/dist/tokens.js +70 -0
  207. package/dist/typography.js +40 -0
  208. package/dist/useReduceMotion.js +32 -0
  209. package/dist/useReduceTransparency.js +27 -0
  210. package/dist/useScheme.js +15 -0
  211. package/dist/video/InlineVideo.jsx +115 -0
  212. package/dist/webview/HtmlView.jsx +169 -0
  213. package/dist/webview/HtmlView.web.jsx +63 -0
  214. package/dist/webview/htmlView.js +43 -0
  215. package/package.json +70 -33
  216. package/src/DropdownMenu.tsx +28 -16
  217. package/src/FloatingTabBar.tsx +78 -41
  218. package/src/ai/conversation.tsx +12 -8
  219. package/src/glassBlur.tsx +47 -22
  220. package/src/primitives/swipe-row-gesture.tsx +11 -2
@@ -0,0 +1,443 @@
1
+ import { c as _c } from "react/compiler-runtime";
2
+ import { useState } from "react";
3
+ import { Modal, ScrollView, Text, View } from "react-native";
4
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
5
+ import { IconCopy, IconMaximize, IconX } from "@tabler/icons-react-native";
6
+ import { ChatIconButton } from "../ai/icon-button";
7
+ import { withAlpha } from "../palette";
8
+ import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle } from "../Sheet";
9
+ import { SheetRow } from "../SheetRow";
10
+ import { tokens } from "../tokens";
11
+ import { useReduceMotion } from "../useReduceMotion";
12
+ import { useScheme } from "../useScheme";
13
+ import { markdownTableColumnWidths, markdownTableText } from "./tableText";
14
+
15
+ /**
16
+ * Web `.markdown table` and its Streamdown wrapper: text at 0.93em with
17
+ * line-height 1.5, cells `0.45rem 0.75rem`, header cells semibold, rows split
18
+ * by the border at 70% (the header's in the full border), the table 0.65rem
19
+ * inside the code-block panel (padding `0.25rem 0.3rem 0.4rem`), below the
20
+ * row of table actions (`flex justify-end gap-1`, 24 buttons, then `gap-2`).
21
+ */
22
+ export const MARKDOWN_TABLE = {
23
+ fontScale: 0.93,
24
+ lineHeight: 1.5,
25
+ cellPaddingX: 12,
26
+ cellPaddingY: 7,
27
+ panelPadding: {
28
+ top: 4,
29
+ x: 5,
30
+ bottom: 6
31
+ },
32
+ tableMargin: 10,
33
+ /** The web action row: 24 buttons in a 27 row. */
34
+ actionsHeight: 27,
35
+ /**
36
+ * The web buttons sit 4 apart; here 16, so each slops to 44 without
37
+ * taking its neighbour's taps.
38
+ */
39
+ actionsGap: 16
40
+ };
41
+
42
+ /**
43
+ * The full-screen table sizes each column to its text, as the web table does
44
+ * (`markdownTableColumnWidths`). 8.5 a character fits the 12 mono of inline
45
+ * code with its chip padding, so a code cell does not wrap; body text is narrower.
46
+ */
47
+ const FULL_SCREEN_COLUMN = {
48
+ charWidth: 8.5,
49
+ min: 72,
50
+ max: 320
51
+ };
52
+
53
+ /** The web Copy table menu, in its order. */
54
+ const COPY_FORMATS = [{
55
+ format: "markdown",
56
+ title: "Markdown"
57
+ }, {
58
+ format: "csv",
59
+ title: "CSV"
60
+ }, {
61
+ format: "tsv",
62
+ title: "TSV"
63
+ }];
64
+ /**
65
+ * The cells as rows. `widths` gives every column its own width (the
66
+ * full-screen view, which scrolls sideways); without it the columns share the
67
+ * width equally and the cells wrap, so they line up in a chat column.
68
+ */
69
+ function TableRows(t0) {
70
+ const $ = _c(17);
71
+ const {
72
+ header,
73
+ rows,
74
+ color,
75
+ widths
76
+ } = t0;
77
+ const scheme = useScheme();
78
+ const {
79
+ cellPaddingX,
80
+ cellPaddingY
81
+ } = MARKDOWN_TABLE;
82
+ let t1;
83
+ if ($[0] !== scheme) {
84
+ t1 = index => index === 1 ? tokens.color.border[scheme] : withAlpha(tokens.color.border[scheme], 0.7);
85
+ $[0] = scheme;
86
+ $[1] = t1;
87
+ } else {
88
+ t1 = $[1];
89
+ }
90
+ const rule = t1;
91
+ let t2;
92
+ if ($[2] !== color || $[3] !== rule || $[4] !== widths) {
93
+ t2 = (cells, index_0) => <View key={index_0} style={{
94
+ flexDirection: "row",
95
+ borderTopWidth: index_0 > 0 ? 1 : 0,
96
+ borderTopColor: rule(index_0)
97
+ }}>{cells.map((cell, cellIndex) => <View key={cellIndex} style={[{
98
+ paddingHorizontal: cellPaddingX,
99
+ paddingVertical: cellPaddingY
100
+ }, widths ? {
101
+ width: widths[cellIndex]
102
+ } : {
103
+ flex: 1
104
+ }]}><Text style={{
105
+ color
106
+ }}>{cell}</Text></View>)}</View>;
107
+ $[2] = color;
108
+ $[3] = rule;
109
+ $[4] = widths;
110
+ $[5] = t2;
111
+ } else {
112
+ t2 = $[5];
113
+ }
114
+ const row = t2;
115
+ let t3;
116
+ if ($[6] !== header || $[7] !== row) {
117
+ t3 = row(header, 0);
118
+ $[6] = header;
119
+ $[7] = row;
120
+ $[8] = t3;
121
+ } else {
122
+ t3 = $[8];
123
+ }
124
+ let t4;
125
+ if ($[9] !== row || $[10] !== rows) {
126
+ let t5;
127
+ if ($[12] !== row) {
128
+ t5 = (cells_0, index_1) => row(cells_0, index_1 + 1);
129
+ $[12] = row;
130
+ $[13] = t5;
131
+ } else {
132
+ t5 = $[13];
133
+ }
134
+ t4 = rows.map(t5);
135
+ $[9] = row;
136
+ $[10] = rows;
137
+ $[11] = t4;
138
+ } else {
139
+ t4 = $[11];
140
+ }
141
+ let t5;
142
+ if ($[14] !== t3 || $[15] !== t4) {
143
+ t5 = <>{t3}{t4}</>;
144
+ $[14] = t3;
145
+ $[15] = t4;
146
+ $[16] = t5;
147
+ } else {
148
+ t5 = $[16];
149
+ }
150
+ return t5;
151
+ }
152
+
153
+ /**
154
+ * A markdown table on the web's panel, with the web table actions a phone
155
+ * can use: Copy table (a sheet of Markdown, CSV and TSV, as the web menu)
156
+ * and View fullscreen (the table at its own column widths, scrolling
157
+ * sideways, for a table too wide for the chat). The web's Download table is
158
+ * left out: a phone saves a file through a share sheet, which native-ui does
159
+ * not bundle, and the copy formats carry the same text.
160
+ */
161
+ export function MarkdownTable(t0) {
162
+ const $ = _c(65);
163
+ const {
164
+ header,
165
+ rows,
166
+ data,
167
+ color,
168
+ onCopy
169
+ } = t0;
170
+ const scheme = useScheme();
171
+ const insets = useSafeAreaInsets();
172
+ const reduceMotion = useReduceMotion();
173
+ const [copyOpen, setCopyOpen] = useState(false);
174
+ const [fullScreen, setFullScreen] = useState(false);
175
+ const {
176
+ panelPadding,
177
+ tableMargin,
178
+ actionsHeight,
179
+ actionsGap
180
+ } = MARKDOWN_TABLE;
181
+ const muted = tokens.color.muted[scheme];
182
+ const t1 = tokens.color.surfaceSecondary[scheme];
183
+ let t2;
184
+ if ($[0] !== t1) {
185
+ t2 = {
186
+ borderRadius: tokens.radius.lg,
187
+ backgroundColor: t1,
188
+ paddingTop: panelPadding.top,
189
+ paddingHorizontal: panelPadding.x,
190
+ paddingBottom: panelPadding.bottom
191
+ };
192
+ $[0] = t1;
193
+ $[1] = t2;
194
+ } else {
195
+ t2 = $[1];
196
+ }
197
+ const panel = t2;
198
+ let t3;
199
+ if ($[2] !== data || $[3] !== onCopy) {
200
+ t3 = async format => {
201
+ setCopyOpen(false);
202
+ await onCopy?.(markdownTableText(data, format));
203
+ };
204
+ $[2] = data;
205
+ $[3] = onCopy;
206
+ $[4] = t3;
207
+ } else {
208
+ t3 = $[4];
209
+ }
210
+ const copy = t3;
211
+ let t4;
212
+ if ($[5] !== muted || $[6] !== onCopy) {
213
+ t4 = onCopy ? <ChatIconButton icon={IconCopy} label="Copy table" size="xs" iconColor={muted} onPress={() => setCopyOpen(true)} /> : null;
214
+ $[5] = muted;
215
+ $[6] = onCopy;
216
+ $[7] = t4;
217
+ } else {
218
+ t4 = $[7];
219
+ }
220
+ const copyButton = t4;
221
+ let t5;
222
+ if ($[8] !== data) {
223
+ t5 = markdownTableColumnWidths(data, {
224
+ ...FULL_SCREEN_COLUMN,
225
+ padding: MARKDOWN_TABLE.cellPaddingX * 2
226
+ });
227
+ $[8] = data;
228
+ $[9] = t5;
229
+ } else {
230
+ t5 = $[9];
231
+ }
232
+ const widths = t5;
233
+ let t6;
234
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
235
+ t6 = {
236
+ height: actionsHeight,
237
+ gap: actionsGap
238
+ };
239
+ $[10] = t6;
240
+ } else {
241
+ t6 = $[10];
242
+ }
243
+ let t7;
244
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
245
+ t7 = () => setFullScreen(true);
246
+ $[11] = t7;
247
+ } else {
248
+ t7 = $[11];
249
+ }
250
+ let t8;
251
+ if ($[12] !== muted) {
252
+ t8 = <ChatIconButton icon={IconMaximize} label="View fullscreen" size="xs" iconColor={muted} onPress={t7} />;
253
+ $[12] = muted;
254
+ $[13] = t8;
255
+ } else {
256
+ t8 = $[13];
257
+ }
258
+ let t9;
259
+ if ($[14] !== copyButton || $[15] !== t8) {
260
+ t9 = <View className="flex-row items-center justify-end" style={t6}>{copyButton}{t8}</View>;
261
+ $[14] = copyButton;
262
+ $[15] = t8;
263
+ $[16] = t9;
264
+ } else {
265
+ t9 = $[16];
266
+ }
267
+ let t10;
268
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
269
+ t10 = {
270
+ marginTop: tableMargin,
271
+ marginBottom: tableMargin
272
+ };
273
+ $[17] = t10;
274
+ } else {
275
+ t10 = $[17];
276
+ }
277
+ let t11;
278
+ if ($[18] !== color || $[19] !== header || $[20] !== rows) {
279
+ t11 = <View style={t10}><TableRows header={header} rows={rows} color={color} /></View>;
280
+ $[18] = color;
281
+ $[19] = header;
282
+ $[20] = rows;
283
+ $[21] = t11;
284
+ } else {
285
+ t11 = $[21];
286
+ }
287
+ let t12;
288
+ if ($[22] !== copy || $[23] !== copyOpen || $[24] !== onCopy) {
289
+ t12 = onCopy ? <Sheet open={copyOpen} onOpenChange={setCopyOpen}><SheetContent className="gap-3 px-3"><SheetHeader className="px-2"><SheetTitle>Copy table</SheetTitle></SheetHeader><SheetBody contentContainerClassName="gap-3">{COPY_FORMATS.map(t13 => {
290
+ const {
291
+ format: format_0,
292
+ title
293
+ } = t13;
294
+ return <SheetRow key={format_0} title={title} onPress={() => void copy(format_0)} />;
295
+ })}</SheetBody></SheetContent></Sheet> : null;
296
+ $[22] = copy;
297
+ $[23] = copyOpen;
298
+ $[24] = onCopy;
299
+ $[25] = t12;
300
+ } else {
301
+ t12 = $[25];
302
+ }
303
+ const t13 = reduceMotion ? "none" : "fade";
304
+ let t14;
305
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
306
+ t14 = () => setFullScreen(false);
307
+ $[26] = t14;
308
+ } else {
309
+ t14 = $[26];
310
+ }
311
+ const t15 = tokens.color.background[scheme];
312
+ let t16;
313
+ if ($[27] !== insets.bottom || $[28] !== insets.left || $[29] !== insets.right || $[30] !== insets.top || $[31] !== t15) {
314
+ t16 = {
315
+ backgroundColor: t15,
316
+ paddingTop: insets.top,
317
+ paddingBottom: insets.bottom,
318
+ paddingLeft: insets.left,
319
+ paddingRight: insets.right
320
+ };
321
+ $[27] = insets.bottom;
322
+ $[28] = insets.left;
323
+ $[29] = insets.right;
324
+ $[30] = insets.top;
325
+ $[31] = t15;
326
+ $[32] = t16;
327
+ } else {
328
+ t16 = $[32];
329
+ }
330
+ let t17;
331
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
332
+ t17 = {
333
+ gap: actionsGap
334
+ };
335
+ $[33] = t17;
336
+ } else {
337
+ t17 = $[33];
338
+ }
339
+ let t18;
340
+ if ($[34] === Symbol.for("react.memo_cache_sentinel")) {
341
+ t18 = () => setFullScreen(false);
342
+ $[34] = t18;
343
+ } else {
344
+ t18 = $[34];
345
+ }
346
+ let t19;
347
+ if ($[35] !== muted) {
348
+ t19 = <ChatIconButton icon={IconX} label="Exit fullscreen" iconColor={muted} onPress={t18} />;
349
+ $[35] = muted;
350
+ $[36] = t19;
351
+ } else {
352
+ t19 = $[36];
353
+ }
354
+ let t20;
355
+ if ($[37] !== copyButton || $[38] !== t19) {
356
+ t20 = <View className="flex-row items-center justify-end px-2 py-1.5" style={t17}>{copyButton}{t19}</View>;
357
+ $[37] = copyButton;
358
+ $[38] = t19;
359
+ $[39] = t20;
360
+ } else {
361
+ t20 = $[39];
362
+ }
363
+ let t21;
364
+ if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
365
+ t21 = {
366
+ padding: 16
367
+ };
368
+ $[40] = t21;
369
+ } else {
370
+ t21 = $[40];
371
+ }
372
+ let t22;
373
+ if ($[41] === Symbol.for("react.memo_cache_sentinel")) {
374
+ t22 = {
375
+ flexGrow: 1
376
+ };
377
+ $[41] = t22;
378
+ } else {
379
+ t22 = $[41];
380
+ }
381
+ let t23;
382
+ if ($[42] === Symbol.for("react.memo_cache_sentinel")) {
383
+ t23 = {
384
+ marginVertical: tableMargin
385
+ };
386
+ $[42] = t23;
387
+ } else {
388
+ t23 = $[42];
389
+ }
390
+ let t24;
391
+ if ($[43] !== color || $[44] !== header || $[45] !== rows || $[46] !== widths) {
392
+ t24 = <View style={t23}><TableRows header={header} rows={rows} color={color} widths={widths} /></View>;
393
+ $[43] = color;
394
+ $[44] = header;
395
+ $[45] = rows;
396
+ $[46] = widths;
397
+ $[47] = t24;
398
+ } else {
399
+ t24 = $[47];
400
+ }
401
+ let t25;
402
+ if ($[48] !== panel || $[49] !== t24) {
403
+ t25 = <ScrollView contentContainerStyle={t21}><ScrollView horizontal={true} contentContainerStyle={t22}><View style={panel}>{t24}</View></ScrollView></ScrollView>;
404
+ $[48] = panel;
405
+ $[49] = t24;
406
+ $[50] = t25;
407
+ } else {
408
+ t25 = $[50];
409
+ }
410
+ let t26;
411
+ if ($[51] !== t16 || $[52] !== t20 || $[53] !== t25) {
412
+ t26 = <View className="flex-1" accessibilityViewIsModal={true} style={t16}>{t20}{t25}</View>;
413
+ $[51] = t16;
414
+ $[52] = t20;
415
+ $[53] = t25;
416
+ $[54] = t26;
417
+ } else {
418
+ t26 = $[54];
419
+ }
420
+ let t27;
421
+ if ($[55] !== fullScreen || $[56] !== t13 || $[57] !== t26) {
422
+ t27 = <Modal visible={fullScreen} animationType={t13} statusBarTranslucent={true} onRequestClose={t14}>{t26}</Modal>;
423
+ $[55] = fullScreen;
424
+ $[56] = t13;
425
+ $[57] = t26;
426
+ $[58] = t27;
427
+ } else {
428
+ t27 = $[58];
429
+ }
430
+ let t28;
431
+ if ($[59] !== panel || $[60] !== t11 || $[61] !== t12 || $[62] !== t27 || $[63] !== t9) {
432
+ t28 = <View style={panel}>{t9}{t11}{t12}{t27}</View>;
433
+ $[59] = panel;
434
+ $[60] = t11;
435
+ $[61] = t12;
436
+ $[62] = t27;
437
+ $[63] = t9;
438
+ $[64] = t28;
439
+ } else {
440
+ t28 = $[64];
441
+ }
442
+ return t28;
443
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * A markdown table as text, for the table's copy actions: the formats and
3
+ * escaping of the web table controls (Streamdown's Copy table: Markdown, CSV
4
+ * and TSV), from each cell's plain text.
5
+ */
6
+
7
+ /** CSV: a cell with a comma, quote or line break is quoted, its quotes doubled. Lines join with `\n`. */
8
+ function toCsv({
9
+ headers,
10
+ rows
11
+ }) {
12
+ const cell = text => /[",\n\r]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
13
+ return [...(headers.length > 0 ? [headers] : []), ...rows].map(row => row.map(cell).join(",")).join("\n");
14
+ }
15
+
16
+ /** TSV: tabs and line breaks in a cell are written as `\t`, `\n` and `\r`. */
17
+ function toTsv({
18
+ headers,
19
+ rows
20
+ }) {
21
+ const cell = text => text.replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r");
22
+ return [...(headers.length > 0 ? [headers] : []), ...rows].map(row => row.map(cell).join("\t")).join("\n");
23
+ }
24
+ const MARKDOWN_ESCAPES = {
25
+ "\\": "\\\\",
26
+ "|": "\\|",
27
+ "\n": "<br>",
28
+ "&": "&amp;",
29
+ "<": "&lt;",
30
+ ">": "&gt;"
31
+ };
32
+
33
+ /** GitHub markdown: pipes and backslashes escaped, line breaks as `<br>`, short rows padded to the header. */
34
+ function toMarkdown({
35
+ headers,
36
+ rows
37
+ }) {
38
+ if (headers.length === 0) return "";
39
+ const cell = text => text.replace(/[\\|\n&<>]/g, char => MARKDOWN_ESCAPES[char] ?? char);
40
+ const line = cells => `| ${cells.join(" | ")} |`;
41
+ return [line(headers.map(cell)), line(headers.map(() => "---")), ...rows.map(row => line(row.length < headers.length ? headers.map((_, index) => cell(row[index] ?? "")) : row.map(cell)))].join("\n");
42
+ }
43
+
44
+ /** The table in one of the copy formats. */
45
+ export function markdownTableText(data, format) {
46
+ if (format === "csv") return toCsv(data);
47
+ if (format === "tsv") return toTsv(data);
48
+ return toMarkdown(data);
49
+ }
50
+
51
+ /**
52
+ * Column widths for the full-screen table, where columns size to their text
53
+ * as the web table does: React Native has no table layout, so the longest
54
+ * line in each column, at `charWidth` a character plus the cell padding,
55
+ * clamped to `[min, max]`.
56
+ */
57
+ export function markdownTableColumnWidths(data, {
58
+ charWidth,
59
+ padding,
60
+ min,
61
+ max
62
+ }) {
63
+ return data.headers.map((header, column) => {
64
+ const cells = [header, ...data.rows.map(row => row[column] ?? "")];
65
+ const longest = Math.max(...cells.flatMap(text => text.split("\n").map(line => line.length)));
66
+ return Math.min(max, Math.max(min, Math.ceil(longest * charWidth + padding)));
67
+ });
68
+ }