paseo-form-render 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +113 -2
- package/client/container.tsx +286 -0
- package/client/host-markdown.tsx +24 -0
- package/client/markdown.tsx +470 -0
- package/client/project-file-modal.tsx +687 -0
- package/client/react-native-dataset.d.ts +10 -0
- package/client/renderer.tsx +1053 -0
- package/client/rpc-bridge.tsx +27 -0
- package/client/settings-screen.tsx +168 -0
- package/index.client.tsx +102 -0
- package/index.server.ts +38 -0
- package/package.json +50 -4
- package/paseo-plugin.json +8 -0
- package/server/auto-fix.ts +199 -0
- package/server/demo.ts +20 -0
- package/server/file-picker.ts +253 -0
- package/server/settings.ts +26 -0
- package/shared/demo.ts +96 -0
- package/shared/form-errors.ts +390 -0
- package/shared/form-fix.ts +77 -0
- package/shared/form-helpers.ts +214 -0
- package/shared/parser.ts +119 -0
- package/shared/pickers.ts +50 -0
- package/shared/prompt.ts +96 -0
- package/shared/schema.ts +330 -0
- package/shared/settings.ts +18 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import type { PluginHostProps } from "@getpaseo/plugin/client";
|
|
2
|
+
import React, { useMemo, type ReactNode } from "react";
|
|
3
|
+
import { Platform, StyleSheet, Text, View } from "react-native";
|
|
4
|
+
|
|
5
|
+
interface MarkdownBlock {
|
|
6
|
+
type: "heading" | "paragraph" | "list-item" | "code" | "table";
|
|
7
|
+
text?: string;
|
|
8
|
+
level?: number;
|
|
9
|
+
bullet?: string;
|
|
10
|
+
code?: string;
|
|
11
|
+
lang?: string;
|
|
12
|
+
headers?: string[];
|
|
13
|
+
rows?: string[][];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isTableSeparatorLine(line: string): boolean {
|
|
17
|
+
const trimmed = line.trim();
|
|
18
|
+
if (!trimmed.includes("|") || !trimmed.includes("-")) return false;
|
|
19
|
+
const cells = parseTableRow(trimmed);
|
|
20
|
+
if (cells.length === 0) return false;
|
|
21
|
+
return cells.every((c) => /^:?-{1,}:?$/.test(c.trim()));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseTableRow(line: string): string[] {
|
|
25
|
+
let trimmed = line.trim();
|
|
26
|
+
if (trimmed.startsWith("|")) trimmed = trimmed.slice(1);
|
|
27
|
+
if (trimmed.endsWith("|")) trimmed = trimmed.slice(0, -1);
|
|
28
|
+
return trimmed.split("|").map((cell) => cell.trim());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseBlocks(src: string): MarkdownBlock[] {
|
|
32
|
+
const lines = src.replace(/\r\n/g, "\n").split("\n");
|
|
33
|
+
const blocks: MarkdownBlock[] = [];
|
|
34
|
+
let inCode = false;
|
|
35
|
+
let codeLines: string[] = [];
|
|
36
|
+
let codeLang = "";
|
|
37
|
+
let paragraph: string[] = [];
|
|
38
|
+
|
|
39
|
+
const flushParagraph = () => {
|
|
40
|
+
if (paragraph.length > 0) {
|
|
41
|
+
blocks.push({ type: "paragraph", text: paragraph.join("\n") });
|
|
42
|
+
paragraph = [];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < lines.length; i++) {
|
|
47
|
+
const line = lines[i];
|
|
48
|
+
if (line.trim().startsWith("```")) {
|
|
49
|
+
if (inCode) {
|
|
50
|
+
blocks.push({ type: "code", code: codeLines.join("\n"), lang: codeLang });
|
|
51
|
+
codeLines = [];
|
|
52
|
+
inCode = false;
|
|
53
|
+
} else {
|
|
54
|
+
flushParagraph();
|
|
55
|
+
inCode = true;
|
|
56
|
+
codeLang = line.trim().slice(3).trim();
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (inCode) {
|
|
61
|
+
codeLines.push(line);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!line.trim()) {
|
|
65
|
+
flushParagraph();
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (
|
|
69
|
+
line.includes("|") &&
|
|
70
|
+
i + 1 < lines.length &&
|
|
71
|
+
isTableSeparatorLine(lines[i + 1])
|
|
72
|
+
) {
|
|
73
|
+
flushParagraph();
|
|
74
|
+
const headers = parseTableRow(line);
|
|
75
|
+
const rows: string[][] = [];
|
|
76
|
+
i += 2;
|
|
77
|
+
while (i < lines.length && lines[i].trim().includes("|")) {
|
|
78
|
+
rows.push(parseTableRow(lines[i]));
|
|
79
|
+
i++;
|
|
80
|
+
}
|
|
81
|
+
i--;
|
|
82
|
+
blocks.push({ type: "table", headers, rows });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const hMatch = line.match(/^(#{1,6})\s+(.*)$/);
|
|
86
|
+
if (hMatch) {
|
|
87
|
+
flushParagraph();
|
|
88
|
+
blocks.push({ type: "heading", level: hMatch[1].length, text: hMatch[2] });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const listMatch = line.match(/^(\*|-|\d+\.)\s+(.*)$/);
|
|
92
|
+
if (listMatch) {
|
|
93
|
+
flushParagraph();
|
|
94
|
+
blocks.push({ type: "list-item", bullet: listMatch[1], text: listMatch[2] });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
paragraph.push(line);
|
|
98
|
+
}
|
|
99
|
+
flushParagraph();
|
|
100
|
+
if (inCode && codeLines.length > 0) {
|
|
101
|
+
blocks.push({ type: "code", code: codeLines.join("\n"), lang: codeLang });
|
|
102
|
+
}
|
|
103
|
+
return blocks;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const WEB_TEXT_SELECTABLE = Platform.OS === "web" ? { userSelect: "text" as const } : {};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Typography that mirrors Paseo's own markdown scale: body text uses `fontSize.content` (15) with a
|
|
110
|
+
* 1.4 line height, inline/code blocks use `fontSize.code` (12) and headings are scaled from the same
|
|
111
|
+
* base (h1 28, h2 24, h3 21, h4 19, h5/h6 17 with a 1.3 line height).
|
|
112
|
+
*
|
|
113
|
+
* This matters because a message that contains a pfr-form block is rendered by this plugin instead
|
|
114
|
+
* of the host's markdown renderer. With smaller values the surrounding text of such a reply looked
|
|
115
|
+
* shrunk compared to the same text in a plain assistant message.
|
|
116
|
+
*/
|
|
117
|
+
const CONTENT_FONT_SIZE = 15;
|
|
118
|
+
const CONTENT_LINE_HEIGHT = 21;
|
|
119
|
+
const CODE_FONT_SIZE = 12;
|
|
120
|
+
const CODE_LINE_HEIGHT = 22;
|
|
121
|
+
const HEADING_FONT_SIZES = [28, 24, 21, 19, 17, 17];
|
|
122
|
+
const HEADING_LINE_HEIGHTS = [36, 31, 27, 25, 22, 22];
|
|
123
|
+
/** Host spacing scale (spacing[2] = 8, spacing[3] = 12, spacing[4] = 16, spacing[6] = 24). */
|
|
124
|
+
const SPACE_1 = 4;
|
|
125
|
+
const SPACE_2 = 8;
|
|
126
|
+
const SPACE_3 = 12;
|
|
127
|
+
const SPACE_4 = 16;
|
|
128
|
+
const SPACE_6 = 24;
|
|
129
|
+
|
|
130
|
+
function parseInline(text: string, color: string, codeBg: string): ReactNode[] {
|
|
131
|
+
const regex = /(`[^`]+`|\*\*[^*]+\*\*|\*[^*]+\*|\[[^\]]+\]\([^)]+\))/g;
|
|
132
|
+
const parts: ReactNode[] = [];
|
|
133
|
+
let lastIndex = 0;
|
|
134
|
+
let match: RegExpExecArray | null;
|
|
135
|
+
|
|
136
|
+
while ((match = regex.exec(text)) !== null) {
|
|
137
|
+
if (match.index > lastIndex) {
|
|
138
|
+
parts.push(text.slice(lastIndex, match.index));
|
|
139
|
+
}
|
|
140
|
+
const token = match[0];
|
|
141
|
+
if (token.startsWith("`") && token.endsWith("`")) {
|
|
142
|
+
parts.push(
|
|
143
|
+
<Text
|
|
144
|
+
key={match.index}
|
|
145
|
+
selectable
|
|
146
|
+
dataSet={{ paseoMarkdownTag: "code" }}
|
|
147
|
+
style={{
|
|
148
|
+
color,
|
|
149
|
+
fontFamily: Platform.select({ ios: "Menlo", default: "monospace" }),
|
|
150
|
+
fontSize: CODE_FONT_SIZE,
|
|
151
|
+
lineHeight: CODE_LINE_HEIGHT,
|
|
152
|
+
backgroundColor: codeBg,
|
|
153
|
+
paddingHorizontal: SPACE_1,
|
|
154
|
+
paddingVertical: 2,
|
|
155
|
+
borderRadius: 4,
|
|
156
|
+
...WEB_TEXT_SELECTABLE,
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
{token.slice(1, -1)}
|
|
160
|
+
</Text>,
|
|
161
|
+
);
|
|
162
|
+
} else if (token.startsWith("**") && token.endsWith("**")) {
|
|
163
|
+
parts.push(
|
|
164
|
+
<Text
|
|
165
|
+
key={match.index}
|
|
166
|
+
selectable
|
|
167
|
+
dataSet={{ paseoMarkdownTag: "strong" }}
|
|
168
|
+
style={{
|
|
169
|
+
fontWeight: "bold",
|
|
170
|
+
color,
|
|
171
|
+
...WEB_TEXT_SELECTABLE,
|
|
172
|
+
}}
|
|
173
|
+
>
|
|
174
|
+
{token.slice(2, -2)}
|
|
175
|
+
</Text>,
|
|
176
|
+
);
|
|
177
|
+
} else if (token.startsWith("*") && token.endsWith("*")) {
|
|
178
|
+
parts.push(
|
|
179
|
+
<Text
|
|
180
|
+
key={match.index}
|
|
181
|
+
selectable
|
|
182
|
+
dataSet={{ paseoMarkdownTag: "em" }}
|
|
183
|
+
style={{
|
|
184
|
+
fontStyle: "italic",
|
|
185
|
+
color,
|
|
186
|
+
...WEB_TEXT_SELECTABLE,
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
{token.slice(1, -1)}
|
|
190
|
+
</Text>,
|
|
191
|
+
);
|
|
192
|
+
} else if (token.startsWith("[") && token.includes("](")) {
|
|
193
|
+
const closeBracket = token.indexOf("]");
|
|
194
|
+
const linkText = token.slice(1, closeBracket);
|
|
195
|
+
parts.push(
|
|
196
|
+
<Text
|
|
197
|
+
key={match.index}
|
|
198
|
+
selectable
|
|
199
|
+
dataSet={{ paseoMarkdownTag: "a" }}
|
|
200
|
+
style={{
|
|
201
|
+
color,
|
|
202
|
+
textDecorationLine: "underline",
|
|
203
|
+
...WEB_TEXT_SELECTABLE,
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
{linkText}
|
|
207
|
+
</Text>,
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
lastIndex = regex.lastIndex;
|
|
211
|
+
}
|
|
212
|
+
if (lastIndex < text.length) {
|
|
213
|
+
parts.push(text.slice(lastIndex));
|
|
214
|
+
}
|
|
215
|
+
return parts;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function MarkdownText({
|
|
219
|
+
text,
|
|
220
|
+
theme,
|
|
221
|
+
}: Pick<PluginHostProps, "theme"> & { text: string }) {
|
|
222
|
+
const blocks = useMemo(() => {
|
|
223
|
+
try {
|
|
224
|
+
return parseBlocks(text);
|
|
225
|
+
} catch {
|
|
226
|
+
return [{ type: "paragraph" as const, text }];
|
|
227
|
+
}
|
|
228
|
+
}, [text]);
|
|
229
|
+
const color = theme.colors.foreground;
|
|
230
|
+
const codeBg = theme.colors.surface2;
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<View style={styles.container}>
|
|
234
|
+
{blocks.map((block, index) => {
|
|
235
|
+
if (block.type === "heading") {
|
|
236
|
+
const level = Math.min(Math.max(block.level || 1, 1), 6);
|
|
237
|
+
const fontSize = HEADING_FONT_SIZES[level - 1];
|
|
238
|
+
const lineHeight = HEADING_LINE_HEIGHTS[level - 1];
|
|
239
|
+
return (
|
|
240
|
+
<Text
|
|
241
|
+
key={index}
|
|
242
|
+
selectable
|
|
243
|
+
dataSet={{ paseoMarkdownTag: `h${level}` }}
|
|
244
|
+
style={{
|
|
245
|
+
color,
|
|
246
|
+
fontSize,
|
|
247
|
+
lineHeight,
|
|
248
|
+
fontWeight: level <= 2 ? "bold" : "600",
|
|
249
|
+
marginTop: level === 1 ? SPACE_6 : level <= 4 ? SPACE_4 : SPACE_3,
|
|
250
|
+
marginBottom: level === 1 ? SPACE_3 : level <= 4 ? SPACE_2 : SPACE_1,
|
|
251
|
+
...(level === 1
|
|
252
|
+
? {
|
|
253
|
+
borderBottomWidth: 1,
|
|
254
|
+
borderBottomColor: theme.colors.border,
|
|
255
|
+
paddingBottom: SPACE_2,
|
|
256
|
+
}
|
|
257
|
+
: null),
|
|
258
|
+
...(level === 6 ? { textTransform: "uppercase" as const, letterSpacing: 0.5 } : null),
|
|
259
|
+
...WEB_TEXT_SELECTABLE,
|
|
260
|
+
}}
|
|
261
|
+
>
|
|
262
|
+
{parseInline(block.text ?? "", color, codeBg)}
|
|
263
|
+
</Text>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
if (block.type === "paragraph") {
|
|
267
|
+
return (
|
|
268
|
+
<Text
|
|
269
|
+
key={index}
|
|
270
|
+
selectable
|
|
271
|
+
dataSet={{ paseoMarkdownTag: "p" }}
|
|
272
|
+
style={{
|
|
273
|
+
color,
|
|
274
|
+
lineHeight: CONTENT_LINE_HEIGHT,
|
|
275
|
+
fontSize: CONTENT_FONT_SIZE,
|
|
276
|
+
marginBottom: SPACE_3,
|
|
277
|
+
...WEB_TEXT_SELECTABLE,
|
|
278
|
+
}}
|
|
279
|
+
>
|
|
280
|
+
{parseInline(block.text ?? "", color, codeBg)}
|
|
281
|
+
</Text>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
if (block.type === "list-item") {
|
|
285
|
+
return (
|
|
286
|
+
<View
|
|
287
|
+
key={index}
|
|
288
|
+
dataSet={{ paseoMarkdownTag: "li" }}
|
|
289
|
+
style={styles.listRow}
|
|
290
|
+
>
|
|
291
|
+
<Text
|
|
292
|
+
selectable
|
|
293
|
+
dataSet={{ paseoMarkdownIgnore: "true", paseoMarkdownListMarker: "true" }}
|
|
294
|
+
style={{
|
|
295
|
+
color: theme.colors.foregroundMuted,
|
|
296
|
+
lineHeight: CONTENT_LINE_HEIGHT,
|
|
297
|
+
fontSize: CONTENT_FONT_SIZE,
|
|
298
|
+
width: 18,
|
|
299
|
+
}}
|
|
300
|
+
>
|
|
301
|
+
{block.bullet?.endsWith(".") ? block.bullet : "•"}
|
|
302
|
+
</Text>
|
|
303
|
+
<Text
|
|
304
|
+
selectable
|
|
305
|
+
style={{
|
|
306
|
+
color,
|
|
307
|
+
lineHeight: CONTENT_LINE_HEIGHT,
|
|
308
|
+
fontSize: CONTENT_FONT_SIZE,
|
|
309
|
+
flex: 1,
|
|
310
|
+
...WEB_TEXT_SELECTABLE,
|
|
311
|
+
}}
|
|
312
|
+
>
|
|
313
|
+
{parseInline(block.text ?? "", color, codeBg)}
|
|
314
|
+
</Text>
|
|
315
|
+
</View>
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
if (block.type === "table") {
|
|
319
|
+
const headers = block.headers ?? [];
|
|
320
|
+
const rows = block.rows ?? [];
|
|
321
|
+
return (
|
|
322
|
+
<View
|
|
323
|
+
key={index}
|
|
324
|
+
dataSet={{ paseoMarkdownTag: "table" }}
|
|
325
|
+
style={[
|
|
326
|
+
styles.tableContainer,
|
|
327
|
+
{ borderColor: theme.colors.border },
|
|
328
|
+
]}
|
|
329
|
+
>
|
|
330
|
+
<View
|
|
331
|
+
dataSet={{ paseoMarkdownTag: "thead" }}
|
|
332
|
+
style={[
|
|
333
|
+
styles.tableHeaderRow,
|
|
334
|
+
{
|
|
335
|
+
backgroundColor: theme.colors.surface2,
|
|
336
|
+
borderBottomColor: theme.colors.border,
|
|
337
|
+
},
|
|
338
|
+
]}
|
|
339
|
+
>
|
|
340
|
+
{headers.map((header, colIdx) => (
|
|
341
|
+
<View
|
|
342
|
+
key={colIdx}
|
|
343
|
+
dataSet={{ paseoMarkdownTag: "th" }}
|
|
344
|
+
style={styles.tableCell}
|
|
345
|
+
>
|
|
346
|
+
<Text
|
|
347
|
+
selectable
|
|
348
|
+
style={{
|
|
349
|
+
color,
|
|
350
|
+
fontSize: CONTENT_FONT_SIZE,
|
|
351
|
+
lineHeight: CONTENT_LINE_HEIGHT,
|
|
352
|
+
fontWeight: "600",
|
|
353
|
+
...WEB_TEXT_SELECTABLE,
|
|
354
|
+
}}
|
|
355
|
+
>
|
|
356
|
+
{parseInline(header, color, codeBg)}
|
|
357
|
+
</Text>
|
|
358
|
+
</View>
|
|
359
|
+
))}
|
|
360
|
+
</View>
|
|
361
|
+
{rows.map((row, rowIdx) => (
|
|
362
|
+
<View
|
|
363
|
+
key={rowIdx}
|
|
364
|
+
dataSet={{ paseoMarkdownTag: "tr" }}
|
|
365
|
+
style={[
|
|
366
|
+
styles.tableRow,
|
|
367
|
+
rowIdx < rows.length - 1
|
|
368
|
+
? {
|
|
369
|
+
borderBottomWidth: 1,
|
|
370
|
+
borderBottomColor: theme.colors.border,
|
|
371
|
+
}
|
|
372
|
+
: null,
|
|
373
|
+
]}
|
|
374
|
+
>
|
|
375
|
+
{headers.map((_, colIdx) => (
|
|
376
|
+
<View
|
|
377
|
+
key={colIdx}
|
|
378
|
+
dataSet={{ paseoMarkdownTag: "td" }}
|
|
379
|
+
style={styles.tableCell}
|
|
380
|
+
>
|
|
381
|
+
<Text
|
|
382
|
+
selectable
|
|
383
|
+
style={{
|
|
384
|
+
color,
|
|
385
|
+
fontSize: CONTENT_FONT_SIZE,
|
|
386
|
+
lineHeight: CONTENT_LINE_HEIGHT,
|
|
387
|
+
...WEB_TEXT_SELECTABLE,
|
|
388
|
+
}}
|
|
389
|
+
>
|
|
390
|
+
{parseInline(row[colIdx] ?? "", color, codeBg)}
|
|
391
|
+
</Text>
|
|
392
|
+
</View>
|
|
393
|
+
))}
|
|
394
|
+
</View>
|
|
395
|
+
))}
|
|
396
|
+
</View>
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
if (block.type === "code") {
|
|
400
|
+
return (
|
|
401
|
+
<View
|
|
402
|
+
key={index}
|
|
403
|
+
dataSet={{
|
|
404
|
+
paseoMarkdownTag: "pre",
|
|
405
|
+
paseoMarkdownLanguage: block.lang || undefined,
|
|
406
|
+
}}
|
|
407
|
+
style={[
|
|
408
|
+
styles.codeBlock,
|
|
409
|
+
{ backgroundColor: codeBg },
|
|
410
|
+
]}
|
|
411
|
+
>
|
|
412
|
+
<Text
|
|
413
|
+
selectable
|
|
414
|
+
dataSet={{ paseoMarkdownTag: "code" }}
|
|
415
|
+
style={{
|
|
416
|
+
color,
|
|
417
|
+
fontFamily: Platform.select({ ios: "Menlo", default: "monospace" }),
|
|
418
|
+
fontSize: CODE_FONT_SIZE,
|
|
419
|
+
lineHeight: CODE_LINE_HEIGHT,
|
|
420
|
+
...WEB_TEXT_SELECTABLE,
|
|
421
|
+
}}
|
|
422
|
+
>
|
|
423
|
+
{block.code?.trimEnd() ?? ""}
|
|
424
|
+
</Text>
|
|
425
|
+
</View>
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
429
|
+
})}
|
|
430
|
+
</View>
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const styles = StyleSheet.create({
|
|
435
|
+
container: {
|
|
436
|
+
marginVertical: 2,
|
|
437
|
+
...(Platform.OS === "web" ? { userSelect: "text" as const } : {}),
|
|
438
|
+
},
|
|
439
|
+
listRow: {
|
|
440
|
+
flexDirection: "row",
|
|
441
|
+
gap: 6,
|
|
442
|
+
marginVertical: 2,
|
|
443
|
+
},
|
|
444
|
+
tableContainer: {
|
|
445
|
+
borderWidth: 1,
|
|
446
|
+
borderRadius: 6,
|
|
447
|
+
overflow: "hidden",
|
|
448
|
+
marginVertical: SPACE_2,
|
|
449
|
+
},
|
|
450
|
+
tableHeaderRow: {
|
|
451
|
+
flexDirection: "row",
|
|
452
|
+
borderBottomWidth: 1,
|
|
453
|
+
paddingVertical: SPACE_2,
|
|
454
|
+
paddingHorizontal: SPACE_2,
|
|
455
|
+
},
|
|
456
|
+
tableRow: {
|
|
457
|
+
flexDirection: "row",
|
|
458
|
+
paddingVertical: SPACE_2,
|
|
459
|
+
paddingHorizontal: SPACE_2,
|
|
460
|
+
},
|
|
461
|
+
tableCell: {
|
|
462
|
+
flex: 1,
|
|
463
|
+
paddingRight: SPACE_2,
|
|
464
|
+
},
|
|
465
|
+
codeBlock: {
|
|
466
|
+
borderRadius: 6,
|
|
467
|
+
padding: SPACE_3,
|
|
468
|
+
marginVertical: SPACE_2,
|
|
469
|
+
},
|
|
470
|
+
});
|