@agimon-ai/po-native-components 0.0.0-alpha.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 (122) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +71 -0
  3. package/dist/components/Badge.d.mts +17 -0
  4. package/dist/components/Badge.d.mts.map +1 -0
  5. package/dist/components/Badge.mjs +106 -0
  6. package/dist/components/Badge.mjs.map +1 -0
  7. package/dist/components/Button.d.mts +20 -0
  8. package/dist/components/Button.d.mts.map +1 -0
  9. package/dist/components/Button.mjs +278 -0
  10. package/dist/components/Button.mjs.map +1 -0
  11. package/dist/components/CodeBlock.d.mts +10 -0
  12. package/dist/components/CodeBlock.d.mts.map +1 -0
  13. package/dist/components/CodeBlock.mjs +88 -0
  14. package/dist/components/CodeBlock.mjs.map +1 -0
  15. package/dist/components/Dialog.d.mts +52 -0
  16. package/dist/components/Dialog.d.mts.map +1 -0
  17. package/dist/components/Dialog.mjs +257 -0
  18. package/dist/components/Dialog.mjs.map +1 -0
  19. package/dist/components/Dot.d.mts +17 -0
  20. package/dist/components/Dot.d.mts.map +1 -0
  21. package/dist/components/Dot.mjs +94 -0
  22. package/dist/components/Dot.mjs.map +1 -0
  23. package/dist/components/DropdownMenu.d.mts +63 -0
  24. package/dist/components/DropdownMenu.d.mts.map +1 -0
  25. package/dist/components/DropdownMenu.mjs +256 -0
  26. package/dist/components/DropdownMenu.mjs.map +1 -0
  27. package/dist/components/EmptyState.d.mts +14 -0
  28. package/dist/components/EmptyState.d.mts.map +1 -0
  29. package/dist/components/EmptyState.mjs +64 -0
  30. package/dist/components/EmptyState.mjs.map +1 -0
  31. package/dist/components/Input.d.mts +19 -0
  32. package/dist/components/Input.d.mts.map +1 -0
  33. package/dist/components/Input.mjs +123 -0
  34. package/dist/components/Input.mjs.map +1 -0
  35. package/dist/components/Label.d.mts +13 -0
  36. package/dist/components/Label.d.mts.map +1 -0
  37. package/dist/components/Label.mjs +36 -0
  38. package/dist/components/Label.mjs.map +1 -0
  39. package/dist/components/List.d.mts +48 -0
  40. package/dist/components/List.d.mts.map +1 -0
  41. package/dist/components/List.mjs +156 -0
  42. package/dist/components/List.mjs.map +1 -0
  43. package/dist/components/Markdown.d.mts +15 -0
  44. package/dist/components/Markdown.d.mts.map +1 -0
  45. package/dist/components/Markdown.mjs +219 -0
  46. package/dist/components/Markdown.mjs.map +1 -0
  47. package/dist/components/MessageItem.d.mts +87 -0
  48. package/dist/components/MessageItem.d.mts.map +1 -0
  49. package/dist/components/MessageItem.mjs +361 -0
  50. package/dist/components/MessageItem.mjs.map +1 -0
  51. package/dist/components/Panel.d.mts +15 -0
  52. package/dist/components/Panel.d.mts.map +1 -0
  53. package/dist/components/Panel.mjs +77 -0
  54. package/dist/components/Panel.mjs.map +1 -0
  55. package/dist/components/PoNativeProvider.d.mts +15 -0
  56. package/dist/components/PoNativeProvider.d.mts.map +1 -0
  57. package/dist/components/PoNativeProvider.mjs +22 -0
  58. package/dist/components/PoNativeProvider.mjs.map +1 -0
  59. package/dist/components/SectionLabel.d.mts +6 -0
  60. package/dist/components/SectionLabel.d.mts.map +1 -0
  61. package/dist/components/SectionLabel.mjs +40 -0
  62. package/dist/components/SectionLabel.mjs.map +1 -0
  63. package/dist/components/SegmentedControl.d.mts +26 -0
  64. package/dist/components/SegmentedControl.d.mts.map +1 -0
  65. package/dist/components/SegmentedControl.mjs +56 -0
  66. package/dist/components/SegmentedControl.mjs.map +1 -0
  67. package/dist/components/Sheet.d.mts +39 -0
  68. package/dist/components/Sheet.d.mts.map +1 -0
  69. package/dist/components/Sheet.mjs +166 -0
  70. package/dist/components/Sheet.mjs.map +1 -0
  71. package/dist/components/SheetFrame.mjs +84 -0
  72. package/dist/components/SheetFrame.mjs.map +1 -0
  73. package/dist/components/Spinner.d.mts +19 -0
  74. package/dist/components/Spinner.d.mts.map +1 -0
  75. package/dist/components/Spinner.mjs +34 -0
  76. package/dist/components/Spinner.mjs.map +1 -0
  77. package/dist/components/StatusBadge.d.mts +23 -0
  78. package/dist/components/StatusBadge.d.mts.map +1 -0
  79. package/dist/components/StatusBadge.mjs +116 -0
  80. package/dist/components/StatusBadge.mjs.map +1 -0
  81. package/dist/components/Tabs.d.mts +44 -0
  82. package/dist/components/Tabs.d.mts.map +1 -0
  83. package/dist/components/Tabs.mjs +197 -0
  84. package/dist/components/Tabs.mjs.map +1 -0
  85. package/dist/components/Textarea.d.mts +10 -0
  86. package/dist/components/Textarea.d.mts.map +1 -0
  87. package/dist/components/Textarea.mjs +29 -0
  88. package/dist/components/Textarea.mjs.map +1 -0
  89. package/dist/icons/IconColorContext.d.mts +10 -0
  90. package/dist/icons/IconColorContext.d.mts.map +1 -0
  91. package/dist/icons/IconColorContext.mjs +13 -0
  92. package/dist/icons/IconColorContext.mjs.map +1 -0
  93. package/dist/icons/iconGlyphs.d.mts +120 -0
  94. package/dist/icons/iconGlyphs.d.mts.map +1 -0
  95. package/dist/icons/iconGlyphs.mjs +121 -0
  96. package/dist/icons/iconGlyphs.mjs.map +1 -0
  97. package/dist/icons/icons.d.mts +122 -0
  98. package/dist/icons/icons.d.mts.map +1 -0
  99. package/dist/icons/icons.mjs +79 -0
  100. package/dist/icons/icons.mjs.map +1 -0
  101. package/dist/index.d.mts +27 -0
  102. package/dist/index.mjs +27 -0
  103. package/dist/lib/fonts.d.mts +13 -0
  104. package/dist/lib/fonts.d.mts.map +1 -0
  105. package/dist/lib/fonts.mjs +22 -0
  106. package/dist/lib/fonts.mjs.map +1 -0
  107. package/dist/lib/haptics.d.mts +7 -0
  108. package/dist/lib/haptics.d.mts.map +1 -0
  109. package/dist/lib/haptics.mjs +25 -0
  110. package/dist/lib/haptics.mjs.map +1 -0
  111. package/dist/lib/insideSheet.mjs +16 -0
  112. package/dist/lib/insideSheet.mjs.map +1 -0
  113. package/dist/lib/markdown.mjs +271 -0
  114. package/dist/lib/markdown.mjs.map +1 -0
  115. package/dist/lib/tone.mjs +50 -0
  116. package/dist/lib/tone.mjs.map +1 -0
  117. package/dist/lib/useControllable.mjs +22 -0
  118. package/dist/lib/useControllable.mjs.map +1 -0
  119. package/dist/lib/wrapText.mjs +20 -0
  120. package/dist/lib/wrapText.mjs.map +1 -0
  121. package/llms.txt +8 -0
  122. package/package.json +104 -0
@@ -0,0 +1,156 @@
1
+ import { fontOf } from "../lib/fonts.mjs";
2
+ import { ChevronRightIcon } from "../icons/icons.mjs";
3
+ import { View } from "react-native-unistyles/components/native/View";
4
+ import { StyleSheet } from "react-native-unistyles";
5
+ import { Platform } from "react-native";
6
+ import { Text } from "react-native-unistyles/components/native/Text";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { Pressable } from "react-native-unistyles/components/native/Pressable";
9
+ import { FlashList } from "@shopify/flash-list";
10
+
11
+ //#region src/components/List.tsx
12
+ const MIN_ROW_HEIGHT = 44;
13
+ const DISABLED_OPACITY = .4;
14
+ /** How close to the bottom a reader must be for a new row to keep the list pinned, as a fraction of the visible height. */
15
+ const PIN_THRESHOLD = .1;
16
+ function Separator() {
17
+ return /* @__PURE__ */ jsx(View, { style: styles.separator });
18
+ }
19
+ function List({ data, renderItem, keyExtractor, startAtBottom = false, separators = true, empty, header, footer, onEndReached, accessibilityLabel, style, contentPadding }) {
20
+ return /* @__PURE__ */ jsx(View, {
21
+ style: [styles.frame, style],
22
+ accessibilityLabel,
23
+ children: /* @__PURE__ */ jsx(FlashList, {
24
+ data,
25
+ renderItem: ({ item, index }) => renderItem(item, index),
26
+ keyExtractor,
27
+ ItemSeparatorComponent: separators ? Separator : null,
28
+ ListEmptyComponent: empty === void 0 ? null : /* @__PURE__ */ jsx(Fragment, { children: empty }),
29
+ ListHeaderComponent: header === void 0 ? null : /* @__PURE__ */ jsx(Fragment, { children: header }),
30
+ ListFooterComponent: footer === void 0 ? null : /* @__PURE__ */ jsx(Fragment, { children: footer }),
31
+ onEndReached,
32
+ contentInsetAdjustmentBehavior: "automatic",
33
+ contentContainerStyle: contentPadding === void 0 ? void 0 : { padding: contentPadding },
34
+ maintainVisibleContentPosition: startAtBottom ? {
35
+ startRenderingFromBottom: true,
36
+ autoscrollToBottomThreshold: PIN_THRESHOLD
37
+ } : void 0
38
+ })
39
+ });
40
+ }
41
+ /** One list row: 44pt tall, optional leading and trailing slots, pressable when it navigates. */
42
+ function ListRow({ title, description, leading, trailing, selected = false, disabled = false, onPress, disclosure, accessibilityLabel, style }) {
43
+ const chevron = disclosure ?? (onPress !== void 0 && Platform.OS === "ios");
44
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
45
+ leading,
46
+ /* @__PURE__ */ jsxs(View, {
47
+ style: styles.text,
48
+ children: [typeof title === "string" ? /* @__PURE__ */ jsx(Text, {
49
+ numberOfLines: 1,
50
+ style: [styles.title, selected && styles.titleSelected],
51
+ children: title
52
+ }) : title, typeof description === "string" ? /* @__PURE__ */ jsx(Text, {
53
+ numberOfLines: 2,
54
+ style: styles.description,
55
+ children: description
56
+ }) : description]
57
+ }),
58
+ trailing,
59
+ chevron ? /* @__PURE__ */ jsx(ChevronRightIcon, {
60
+ size: 14,
61
+ color: "faint"
62
+ }) : null
63
+ ] });
64
+ if (onPress === void 0) return /* @__PURE__ */ jsx(View, {
65
+ accessibilityLabel,
66
+ accessibilityState: {
67
+ selected,
68
+ disabled
69
+ },
70
+ style: [
71
+ styles.row,
72
+ selected && styles.selected,
73
+ disabled && styles.disabled,
74
+ style
75
+ ],
76
+ children: content
77
+ });
78
+ return /* @__PURE__ */ jsx(Pressable, {
79
+ accessibilityRole: "button",
80
+ accessibilityLabel,
81
+ accessibilityState: {
82
+ selected,
83
+ disabled
84
+ },
85
+ disabled,
86
+ onPress,
87
+ style: ({ pressed }) => [
88
+ styles.row,
89
+ selected && styles.selected,
90
+ pressed && styles.pressed,
91
+ disabled && styles.disabled,
92
+ style
93
+ ],
94
+ children: content
95
+ });
96
+ }
97
+ const styles = StyleSheet.create((theme) => ({
98
+ frame: {
99
+ flex: 1,
100
+ minHeight: 0
101
+ },
102
+ separator: {
103
+ height: StyleSheet.hairlineWidth,
104
+ marginLeft: theme.spacing(4),
105
+ backgroundColor: theme.colors["border-soft"],
106
+ uni__dependencies: [0]
107
+ },
108
+ row: {
109
+ flexDirection: "row",
110
+ alignItems: "center",
111
+ gap: theme.spacing(3),
112
+ minHeight: MIN_ROW_HEIGHT,
113
+ paddingHorizontal: theme.spacing(4),
114
+ paddingVertical: theme.spacing(2),
115
+ uni__dependencies: [0]
116
+ },
117
+ selected: {
118
+ backgroundColor: theme.colors["tint-green"],
119
+ uni__dependencies: [0]
120
+ },
121
+ pressed: {
122
+ backgroundColor: theme.colors.panel,
123
+ uni__dependencies: [0]
124
+ },
125
+ disabled: { opacity: DISABLED_OPACITY },
126
+ text: {
127
+ flex: 1,
128
+ minWidth: 0,
129
+ gap: theme.spacing(.5),
130
+ uni__dependencies: [0]
131
+ },
132
+ title: {
133
+ color: theme.colors.hi,
134
+ fontFamily: fontOf(theme.fontFamily.sans),
135
+ fontSize: theme.fontSize.base,
136
+ lineHeight: theme.lineHeight.base,
137
+ fontWeight: theme.fontWeight.medium,
138
+ uni__dependencies: [0]
139
+ },
140
+ titleSelected: {
141
+ color: theme.colors.green,
142
+ fontWeight: theme.fontWeight.semibold,
143
+ uni__dependencies: [0]
144
+ },
145
+ description: {
146
+ color: theme.colors.faint,
147
+ fontFamily: fontOf(theme.fontFamily.sans),
148
+ fontSize: theme.fontSize.sm,
149
+ lineHeight: theme.lineHeight.sm,
150
+ uni__dependencies: [0]
151
+ }
152
+ }));
153
+
154
+ //#endregion
155
+ export { List, ListRow };
156
+ //# sourceMappingURL=List.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"List.mjs","names":["FlashList","ReactElement","ReactNode","Platform","StyleProp","ViewStyle","StyleSheet","ChevronRightIcon","fontOf","MIN_ROW_HEIGHT","DISABLED_OPACITY","PIN_THRESHOLD","ListProps","data","T","renderItem","item","index","keyExtractor","startAtBottom","separators","empty","header","footer","onEndReached","accessibilityLabel","style","contentPadding","Separator","styles","separator","List","frame","undefined","padding","startRenderingFromBottom","autoscrollToBottomThreshold","ListRowProps","title","description","leading","trailing","selected","disabled","onPress","disclosure","ListRow","chevron","OS","content","text","titleSelected","row","pressed","create","theme","flex","minHeight","height","hairlineWidth","marginLeft","spacing","backgroundColor","colors","uni__dependencies","flexDirection","alignItems","gap","paddingHorizontal","paddingVertical","panel","opacity","minWidth","color","hi","fontFamily","sans","fontSize","base","lineHeight","fontWeight","medium","green","semibold","faint","sm"],"sources":["../../src/components/List.tsx"],"sourcesContent":["import { FlashList } from '@shopify/flash-list';\nimport type { ReactElement, ReactNode } from 'react';\nimport { Platform, Pressable, type StyleProp, Text, View, type ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { ChevronRightIcon } from '../icons/icons';\nimport { fontOf } from '../lib/fonts';\n\n/*\n * A virtualised list on FlashList: sessions, devices, a transcript. Rows\n * recycle, separators are hairlines, and a chat list can start at the bottom\n * and stay pinned there as rows arrive. The public props are this package's\n * own, so FlashList's types never reach a caller.\n */\n\nconst MIN_ROW_HEIGHT = 44;\nconst DISABLED_OPACITY = 0.4;\n/** How close to the bottom a reader must be for a new row to keep the list pinned, as a fraction of the visible height. */\nconst PIN_THRESHOLD = 0.1;\n\nexport interface ListProps<T> {\n data: readonly T[];\n renderItem: (item: T, index: number) => ReactElement | null;\n /** A stable key per row; FlashList recycles views by it. */\n keyExtractor: (item: T, index: number) => string;\n /**\n * A chat list: render from the bottom and keep the newest row in view as\n * rows arrive, while the reader is near the bottom.\n */\n startAtBottom?: boolean;\n /** Hairline separators between rows. On by default. */\n separators?: boolean;\n /** Shown when `data` is empty. */\n empty?: ReactNode;\n header?: ReactNode;\n footer?: ReactNode;\n onEndReached?: () => void;\n accessibilityLabel?: string;\n /** The list's frame; give it a height or a flex parent, since a virtualised list needs bounds. */\n style?: StyleProp<ViewStyle>;\n /** Padding around the rows. */\n contentPadding?: number;\n}\n\nfunction Separator() {\n return <View style={styles.separator} />;\n}\n\nexport function List<T>({\n data,\n renderItem,\n keyExtractor,\n startAtBottom = false,\n separators = true,\n empty,\n header,\n footer,\n onEndReached,\n accessibilityLabel,\n style,\n contentPadding,\n}: ListProps<T>) {\n return (\n <View style={[styles.frame, style]} accessibilityLabel={accessibilityLabel}>\n <FlashList\n data={data}\n renderItem={({ item, index }) => renderItem(item, index)}\n keyExtractor={keyExtractor}\n ItemSeparatorComponent={separators ? Separator : null}\n ListEmptyComponent={empty === undefined ? null : <>{empty}</>}\n ListHeaderComponent={header === undefined ? null : <>{header}</>}\n ListFooterComponent={footer === undefined ? null : <>{footer}</>}\n onEndReached={onEndReached}\n // Lets UIKit inset the rows under a translucent or large-title header instead of drawing beneath it.\n contentInsetAdjustmentBehavior=\"automatic\"\n contentContainerStyle={contentPadding === undefined ? undefined : { padding: contentPadding }}\n maintainVisibleContentPosition={\n startAtBottom ? { startRenderingFromBottom: true, autoscrollToBottomThreshold: PIN_THRESHOLD } : undefined\n }\n />\n </View>\n );\n}\n\nexport interface ListRowProps {\n title: ReactNode;\n /** A second, quieter line under the title. */\n description?: ReactNode;\n /** Before the text: a Dot, an icon. */\n leading?: ReactNode;\n /** After the text: a Badge, a ghost button, a count. */\n trailing?: ReactNode;\n /** Selected rows sit on a green tint. */\n selected?: boolean;\n disabled?: boolean;\n onPress?: () => void;\n /** The iOS disclosure chevron. Defaults to on for a pressable row on iOS, where rows that navigate wear one. */\n disclosure?: boolean;\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\n/** One list row: 44pt tall, optional leading and trailing slots, pressable when it navigates. */\nexport function ListRow({\n title,\n description,\n leading,\n trailing,\n selected = false,\n disabled = false,\n onPress,\n disclosure,\n accessibilityLabel,\n style,\n}: ListRowProps) {\n const chevron = disclosure ?? (onPress !== undefined && Platform.OS === 'ios');\n const content = (\n <>\n {leading}\n <View style={styles.text}>\n {typeof title === 'string' ? (\n <Text numberOfLines={1} style={[styles.title, selected && styles.titleSelected]}>\n {title}\n </Text>\n ) : (\n title\n )}\n {typeof description === 'string' ? (\n <Text numberOfLines={2} style={styles.description}>\n {description}\n </Text>\n ) : (\n description\n )}\n </View>\n {trailing}\n {chevron ? <ChevronRightIcon size={14} color=\"faint\" /> : null}\n </>\n );\n if (onPress === undefined) {\n return (\n <View\n accessibilityLabel={accessibilityLabel}\n accessibilityState={{ selected, disabled }}\n style={[styles.row, selected && styles.selected, disabled && styles.disabled, style]}\n >\n {content}\n </View>\n );\n }\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n accessibilityState={{ selected, disabled }}\n disabled={disabled}\n onPress={onPress}\n style={({ pressed }) => [\n styles.row,\n selected && styles.selected,\n pressed && styles.pressed,\n disabled && styles.disabled,\n style,\n ]}\n >\n {content}\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n frame: { flex: 1, minHeight: 0 },\n separator: {\n height: StyleSheet.hairlineWidth,\n marginLeft: theme.spacing(4),\n backgroundColor: theme.colors['border-soft'],\n },\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.spacing(3),\n minHeight: MIN_ROW_HEIGHT,\n paddingHorizontal: theme.spacing(4),\n paddingVertical: theme.spacing(2),\n },\n selected: { backgroundColor: theme.colors['tint-green'] },\n pressed: { backgroundColor: theme.colors.panel },\n disabled: { opacity: DISABLED_OPACITY },\n text: { flex: 1, minWidth: 0, gap: theme.spacing(0.5) },\n title: {\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n fontWeight: theme.fontWeight.medium,\n },\n titleSelected: { color: theme.colors.green, fontWeight: theme.fontWeight.semibold },\n description: {\n color: theme.colors.faint,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n}));\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ //#region src/components/Markdown.d.ts
2
+ /**
3
+ * What a piece of inline code or a relative link opens, when the host knows.
4
+ * Returning undefined leaves it as plain code or an ordinary link. The same
5
+ * contract as the web Markdown's handler.
6
+ */
7
+ export type FileLinkHandler = (text: string, explicit?: boolean) => (() => void) | undefined;
8
+ export interface MarkdownProps {
9
+ text: string;
10
+ onFileLink?: FileLinkHandler;
11
+ }
12
+ /** Markdown in Po's shared presentation, parsed by the package's own small parser. */
13
+ export declare function Markdown({ text, onFileLink }: MarkdownProps): import("react").JSX.Element;
14
+ //#endregion
15
+ //# sourceMappingURL=Markdown.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.d.mts","names":[],"sources":["../../src/components/Markdown.tsx"],"mappings":";;;;;;YAqBY,mBAAmB,cAAc;iBAgH5B;EACf;EACA,aAAa;;;wBAIC,WAAW,MAAM,cAAc,gCAAa,IAAA"}
@@ -0,0 +1,219 @@
1
+ import { fontOf } from "../lib/fonts.mjs";
2
+ import { CodeBlock } from "./CodeBlock.mjs";
3
+ import { parseMarkdown } from "../lib/markdown.mjs";
4
+ import { View } from "react-native-unistyles/components/native/View";
5
+ import { StyleSheet } from "react-native-unistyles";
6
+ import { Linking } from "react-native";
7
+ import { Text } from "react-native-unistyles/components/native/Text";
8
+ import { createContext, useContext, useMemo } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+
11
+ //#region src/components/Markdown.tsx
12
+ /** Passed by context so the inline renderers stay module functions. */
13
+ const FileLinkContext = createContext(void 0);
14
+ const URL_OR_ANCHOR = /^(?:[a-z][a-z\d+.-]*:|\/\/|#|\?)/i;
15
+ function decoded(href) {
16
+ try {
17
+ return decodeURIComponent(href);
18
+ } catch {
19
+ return;
20
+ }
21
+ }
22
+ function InlineCode({ text }) {
23
+ const onFileLink = useContext(FileLinkContext);
24
+ const open = text.includes("\n") ? void 0 : onFileLink?.(text);
25
+ if (open !== void 0) return /* @__PURE__ */ jsx(Text, {
26
+ accessibilityRole: "link",
27
+ accessibilityHint: `open ${text}`,
28
+ onPress: open,
29
+ style: [styles.code, styles.fileLink],
30
+ children: text
31
+ });
32
+ return /* @__PURE__ */ jsx(Text, {
33
+ style: styles.code,
34
+ children: text
35
+ });
36
+ }
37
+ function InlineLink({ href, children }) {
38
+ const onFileLink = useContext(FileLinkContext);
39
+ const path = decoded(href);
40
+ const isFile = path !== void 0 && path !== "" && !URL_OR_ANCHOR.test(path);
41
+ const open = isFile ? onFileLink?.(path, true) : void 0;
42
+ return /* @__PURE__ */ jsx(Text, {
43
+ accessibilityRole: "link",
44
+ onPress: () => {
45
+ if (open !== void 0) open();
46
+ else if (!isFile) Linking.openURL(href).catch(() => void 0);
47
+ },
48
+ style: styles.link,
49
+ children
50
+ });
51
+ }
52
+ function renderInline(nodes) {
53
+ return nodes.map((node, index) => {
54
+ switch (node.type) {
55
+ case "text": return node.text;
56
+ case "code": return /* @__PURE__ */ jsx(InlineCode, { text: node.text }, index);
57
+ case "strong": return /* @__PURE__ */ jsx(Text, {
58
+ style: styles.strong,
59
+ children: renderInline(node.children)
60
+ }, index);
61
+ case "em": return /* @__PURE__ */ jsx(Text, {
62
+ style: styles.em,
63
+ children: renderInline(node.children)
64
+ }, index);
65
+ case "link": return /* @__PURE__ */ jsx(InlineLink, {
66
+ href: node.href,
67
+ children: renderInline(node.children)
68
+ }, index);
69
+ }
70
+ });
71
+ }
72
+ function Block({ block, first }) {
73
+ switch (block.type) {
74
+ case "heading": return /* @__PURE__ */ jsx(Text, {
75
+ accessibilityRole: "header",
76
+ style: [
77
+ styles.prose,
78
+ styles.heading(block.level),
79
+ first && styles.firstHeading
80
+ ],
81
+ children: renderInline(block.children)
82
+ });
83
+ case "paragraph": return /* @__PURE__ */ jsx(Text, {
84
+ style: styles.prose,
85
+ children: renderInline(block.children)
86
+ });
87
+ case "list": return /* @__PURE__ */ jsx(View, {
88
+ accessibilityRole: "list",
89
+ style: styles.list,
90
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxs(View, {
91
+ style: styles.item,
92
+ children: [/* @__PURE__ */ jsx(Text, {
93
+ style: [styles.prose, styles.marker],
94
+ children: block.ordered ? `${block.start + index}.` : "•"
95
+ }), /* @__PURE__ */ jsx(Text, {
96
+ style: [styles.prose, styles.itemText],
97
+ children: renderInline(item)
98
+ })]
99
+ }, index))
100
+ });
101
+ case "code": return /* @__PURE__ */ jsx(CodeBlock, {
102
+ text: block.text,
103
+ language: block.language
104
+ });
105
+ case "rule": return /* @__PURE__ */ jsx(View, {
106
+ accessible: false,
107
+ style: styles.rule
108
+ });
109
+ }
110
+ }
111
+ /** Markdown in Po's shared presentation, parsed by the package's own small parser. */
112
+ function Markdown({ text, onFileLink }) {
113
+ const blocks = useMemo(() => parseMarkdown(text), [text]);
114
+ return /* @__PURE__ */ jsx(FileLinkContext.Provider, {
115
+ value: onFileLink,
116
+ children: /* @__PURE__ */ jsx(View, {
117
+ style: styles.root,
118
+ children: blocks.map((block, index) => /* @__PURE__ */ jsx(Block, {
119
+ block,
120
+ first: index === 0
121
+ }, index))
122
+ })
123
+ });
124
+ }
125
+ /**
126
+ * Headings step up from the prose and never shrink below it; h4 to h6 keep
127
+ * the prose size and lean on weight, fading from `hi` to `dim`.
128
+ */
129
+ const HEADING_STEP = {
130
+ 1: "2xl",
131
+ 2: "xl",
132
+ 3: "lg",
133
+ 4: "base",
134
+ 5: "base",
135
+ 6: "base"
136
+ };
137
+ const HEADING_SPACE = {
138
+ 1: 2,
139
+ 2: 2,
140
+ 3: 1,
141
+ 4: 0,
142
+ 5: 0,
143
+ 6: 0
144
+ };
145
+ const HEADING_INK = {
146
+ 1: "hi",
147
+ 2: "hi",
148
+ 3: "hi",
149
+ 4: "hi",
150
+ 5: "text",
151
+ 6: "dim"
152
+ };
153
+ const styles = StyleSheet.create((theme) => ({
154
+ root: {
155
+ minWidth: 0,
156
+ gap: theme.spacing(2),
157
+ uni__dependencies: [0]
158
+ },
159
+ prose: {
160
+ color: theme.colors.text,
161
+ fontFamily: fontOf(theme.fontFamily.sans),
162
+ fontSize: theme.fontSize.base,
163
+ lineHeight: theme.lineHeight.base,
164
+ uni__dependencies: [0]
165
+ },
166
+ heading: (level) => ({
167
+ marginTop: theme.spacing(HEADING_SPACE[level]),
168
+ fontSize: theme.fontSize[HEADING_STEP[level]],
169
+ lineHeight: theme.lineHeight[HEADING_STEP[level]],
170
+ letterSpacing: theme.letterSpacing[HEADING_STEP[level]],
171
+ fontWeight: theme.fontWeight.semibold,
172
+ color: theme.colors[HEADING_INK[level]],
173
+ uni__dependencies: [0]
174
+ }),
175
+ firstHeading: { marginTop: 0 },
176
+ strong: {
177
+ fontWeight: theme.fontWeight.semibold,
178
+ color: theme.colors.hi,
179
+ uni__dependencies: [0]
180
+ },
181
+ em: { fontStyle: "italic" },
182
+ code: {
183
+ backgroundColor: theme.colors.deep,
184
+ color: theme.colors.green,
185
+ fontFamily: fontOf(theme.fontFamily.mono),
186
+ uni__dependencies: [0]
187
+ },
188
+ fileLink: { textDecorationLine: "underline" },
189
+ link: {
190
+ color: theme.colors.blue,
191
+ textDecorationLine: "underline",
192
+ uni__dependencies: [0]
193
+ },
194
+ list: {
195
+ gap: theme.spacing(.5),
196
+ uni__dependencies: [0]
197
+ },
198
+ item: {
199
+ flexDirection: "row",
200
+ gap: theme.spacing(2),
201
+ paddingLeft: theme.spacing(1),
202
+ uni__dependencies: [0]
203
+ },
204
+ marker: {
205
+ minWidth: theme.spacing(3),
206
+ color: theme.colors.dim,
207
+ uni__dependencies: [0]
208
+ },
209
+ itemText: { flexShrink: 1 },
210
+ rule: {
211
+ height: 1,
212
+ backgroundColor: theme.colors["border-soft"],
213
+ uni__dependencies: [0]
214
+ }
215
+ }));
216
+
217
+ //#endregion
218
+ export { Markdown };
219
+ //# sourceMappingURL=Markdown.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Markdown.mjs","names":["createContext","ReactNode","useContext","useMemo","Linking","StyleSheet","fontOf","MarkdownBlock","MarkdownHeadingLevel","MarkdownInline","parseMarkdown","CodeBlock","FileLinkHandler","text","explicit","FileLinkContext","undefined","URL_OR_ANCHOR","decoded","href","decodeURIComponent","InlineCode","onFileLink","open","includes","styles","code","fileLink","InlineLink","children","path","isFile","test","openURL","catch","link","renderInline","nodes","map","node","index","type","strong","em","Block","block","first","prose","heading","level","firstHeading","list","items","item","marker","ordered","start","itemText","language","rule","MarkdownProps","Markdown","blocks","root","HEADING_STEP","const","HEADING_SPACE","HEADING_INK","create","theme","minWidth","gap","spacing","uni__dependencies","color","colors","fontFamily","sans","fontSize","base","lineHeight","marginTop","letterSpacing","fontWeight","semibold","hi","fontStyle","backgroundColor","deep","green","mono","textDecorationLine","blue","flexDirection","paddingLeft","dim","flexShrink","height"],"sources":["../../src/components/Markdown.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext, useMemo } from 'react';\nimport { Linking, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\nimport { type MarkdownBlock, type MarkdownHeadingLevel, type MarkdownInline, parseMarkdown } from '../lib/markdown';\nimport { CodeBlock } from './CodeBlock';\n\n/*\n * Markdown in the web component's element styles, from the package's own\n * parser: headings, paragraphs, lists, code spans and fences, bold, italic\n * and links. Web links open with Linking; a file path goes to the host.\n *\n * ponytail: no tables, images or blockquotes yet; their source shows as text.\n */\n\n/**\n * What a piece of inline code or a relative link opens, when the host knows.\n * Returning undefined leaves it as plain code or an ordinary link. The same\n * contract as the web Markdown's handler.\n */\nexport type FileLinkHandler = (text: string, explicit?: boolean) => (() => void) | undefined;\n\n/** Passed by context so the inline renderers stay module functions. */\nconst FileLinkContext = createContext<FileLinkHandler | undefined>(undefined);\n\nconst URL_OR_ANCHOR = /^(?:[a-z][a-z\\d+.-]*:|\\/\\/|#|\\?)/i;\n\nfunction decoded(href: string): string | undefined {\n try {\n return decodeURIComponent(href);\n } catch {\n return undefined;\n }\n}\n\nfunction InlineCode({ text }: { text: string }) {\n const onFileLink = useContext(FileLinkContext);\n const open = text.includes('\\n') ? undefined : onFileLink?.(text);\n if (open !== undefined) {\n return (\n <Text\n accessibilityRole=\"link\"\n accessibilityHint={`open ${text}`}\n onPress={open}\n style={[styles.code, styles.fileLink]}\n >\n {text}\n </Text>\n );\n }\n return <Text style={styles.code}>{text}</Text>;\n}\n\nfunction InlineLink({ href, children }: { href: string; children: ReactNode }) {\n const onFileLink = useContext(FileLinkContext);\n const path = decoded(href);\n const isFile = path !== undefined && path !== '' && !URL_OR_ANCHOR.test(path);\n const open = isFile ? onFileLink?.(path, true) : undefined;\n return (\n <Text\n accessibilityRole=\"link\"\n onPress={() => {\n if (open !== undefined) open();\n else if (!isFile) Linking.openURL(href).catch(() => undefined);\n }}\n style={styles.link}\n >\n {children}\n </Text>\n );\n}\n\nfunction renderInline(nodes: readonly MarkdownInline[]): ReactNode[] {\n return nodes.map((node, index) => {\n switch (node.type) {\n case 'text':\n return node.text;\n case 'code':\n return <InlineCode key={index} text={node.text} />;\n case 'strong':\n return (\n <Text key={index} style={styles.strong}>\n {renderInline(node.children)}\n </Text>\n );\n case 'em':\n return (\n <Text key={index} style={styles.em}>\n {renderInline(node.children)}\n </Text>\n );\n case 'link':\n return (\n <InlineLink key={index} href={node.href}>\n {renderInline(node.children)}\n </InlineLink>\n );\n }\n });\n}\n\nfunction Block({ block, first }: { block: MarkdownBlock; first: boolean }) {\n switch (block.type) {\n case 'heading':\n return (\n <Text\n accessibilityRole=\"header\"\n style={[styles.prose, styles.heading(block.level), first && styles.firstHeading]}\n >\n {renderInline(block.children)}\n </Text>\n );\n case 'paragraph':\n return <Text style={styles.prose}>{renderInline(block.children)}</Text>;\n case 'list':\n return (\n <View accessibilityRole=\"list\" style={styles.list}>\n {block.items.map((item, index) => (\n <View key={index} style={styles.item}>\n <Text style={[styles.prose, styles.marker]}>{block.ordered ? `${block.start + index}.` : '\\u2022'}</Text>\n <Text style={[styles.prose, styles.itemText]}>{renderInline(item)}</Text>\n </View>\n ))}\n </View>\n );\n case 'code':\n return <CodeBlock text={block.text} language={block.language} />;\n case 'rule':\n return <View accessible={false} style={styles.rule} />;\n }\n}\n\nexport interface MarkdownProps {\n text: string;\n onFileLink?: FileLinkHandler;\n}\n\n/** Markdown in Po's shared presentation, parsed by the package's own small parser. */\nexport function Markdown({ text, onFileLink }: MarkdownProps) {\n const blocks = useMemo(() => parseMarkdown(text), [text]);\n return (\n <FileLinkContext.Provider value={onFileLink}>\n <View style={styles.root}>\n {blocks.map((block, index) => (\n <Block key={index} block={block} first={index === 0} />\n ))}\n </View>\n </FileLinkContext.Provider>\n );\n}\n\n/**\n * Headings step up from the prose and never shrink below it; h4 to h6 keep\n * the prose size and lean on weight, fading from `hi` to `dim`.\n */\nconst HEADING_STEP = { 1: '2xl', 2: 'xl', 3: 'lg', 4: 'base', 5: 'base', 6: 'base' } as const;\nconst HEADING_SPACE = { 1: 2, 2: 2, 3: 1, 4: 0, 5: 0, 6: 0 } as const;\nconst HEADING_INK = { 1: 'hi', 2: 'hi', 3: 'hi', 4: 'hi', 5: 'text', 6: 'dim' } as const;\n\nconst styles = StyleSheet.create((theme) => ({\n root: { minWidth: 0, gap: theme.spacing(2) },\n prose: {\n color: theme.colors.text,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n heading: (level: MarkdownHeadingLevel) => ({\n marginTop: theme.spacing(HEADING_SPACE[level]),\n fontSize: theme.fontSize[HEADING_STEP[level]],\n lineHeight: theme.lineHeight[HEADING_STEP[level]],\n letterSpacing: theme.letterSpacing[HEADING_STEP[level]],\n fontWeight: theme.fontWeight.semibold,\n color: theme.colors[HEADING_INK[level]],\n }),\n firstHeading: { marginTop: 0 },\n strong: { fontWeight: theme.fontWeight.semibold, color: theme.colors.hi },\n em: { fontStyle: 'italic' },\n code: {\n backgroundColor: theme.colors.deep,\n color: theme.colors.green,\n fontFamily: fontOf(theme.fontFamily.mono),\n },\n fileLink: { textDecorationLine: 'underline' },\n link: { color: theme.colors.blue, textDecorationLine: 'underline' },\n list: { gap: theme.spacing(0.5) },\n item: { flexDirection: 'row', gap: theme.spacing(2), paddingLeft: theme.spacing(1) },\n marker: { minWidth: theme.spacing(3), color: theme.colors.dim },\n itemText: { flexShrink: 1 },\n rule: { height: 1, backgroundColor: theme.colors['border-soft'] },\n}));\n"],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { StatusTone } from "./StatusBadge.mjs";
2
+ import { StyleProp, TextProps, ViewProps, ViewStyle } from "react-native";
3
+ import { ReactNode } from "react";
4
+ //#region src/components/MessageItem.d.ts
5
+ export interface MessageItemState {
6
+ tone: StatusTone;
7
+ /** Whether the header offers the toggle; an item that hides nothing offers none. */
8
+ expandable: boolean;
9
+ expanded: boolean;
10
+ toggle: () => void;
11
+ }
12
+ /** The enclosing item's state, for a part that lives deeper than the item's render prop. */
13
+ export declare function useMessageItem(): MessageItemState;
14
+ /** The tone a tool call's item wears: running while the tool runs, then its outcome. */
15
+ export declare function toolTone(state: {
16
+ running: boolean;
17
+ isError: boolean;
18
+ }): StatusTone;
19
+ /** The badge text a tone reads as when the header is not told otherwise; empty hides the badge. */
20
+ export declare const STATUS_LABEL: Readonly<Record<StatusTone, string>>;
21
+ /** The glyph a tone reads as in a status line. */
22
+ export declare const STATUS_GLYPH: Readonly<Record<StatusTone, string>>;
23
+ export interface MessageItemProps extends Omit<ViewProps, 'children' | 'style'> {
24
+ tone?: StatusTone;
25
+ /** Whether the header offers the expand toggle. A toggle that reveals nothing reads as broken, so the card decides. */
26
+ expandable?: boolean;
27
+ defaultExpanded?: boolean;
28
+ /** Controlled mode; pair with onExpandedChange. Omit it and the item keeps its own state. */
29
+ expanded?: boolean;
30
+ onExpandedChange?: (expanded: boolean) => void;
31
+ /** Plain content, or a function of the item's state for a card that picks its lines by `expanded`. */
32
+ children?: ReactNode | ((state: MessageItemState) => ReactNode);
33
+ style?: StyleProp<ViewStyle>;
34
+ }
35
+ export declare function MessageItem({ tone, expandable, defaultExpanded, expanded, onExpandedChange, children, style, ...props }: MessageItemProps): import("react").JSX.Element;
36
+ export interface MessageItemGroupProps extends Omit<ViewProps, 'children' | 'style'> {
37
+ tone?: StatusTone;
38
+ /** The bold label at the left of the group header: the tool the run belongs to. */
39
+ title: ReactNode;
40
+ /** The line beside it, such as how many calls the group holds. */
41
+ summary?: ReactNode;
42
+ /** The badge text; defaults to the tone's label, null hides the badge. */
43
+ badge?: ReactNode | null;
44
+ children?: ReactNode;
45
+ style?: StyleProp<ViewStyle>;
46
+ }
47
+ /**
48
+ * One frame around a run of items that belong together. Each item inside
49
+ * becomes a row: same header, same expand, no card of its own, and its tone
50
+ * an edge down its left side.
51
+ */
52
+ export declare function MessageItemGroup({ tone, title, summary, badge, children, style, ...props }: MessageItemGroupProps): import("react").JSX.Element;
53
+ export interface MessageItemHeaderProps extends Omit<ViewProps, 'children' | 'style'> {
54
+ /** The bold label at the left: the tool name. */
55
+ title: ReactNode;
56
+ /** The badge text; defaults to the tone's label, null hides the badge. */
57
+ badge?: ReactNode | null;
58
+ /** The summary beside the title; it gets the remaining width. */
59
+ children?: ReactNode;
60
+ style?: StyleProp<ViewStyle>;
61
+ }
62
+ /**
63
+ * The title row: label, summary, the tone's badge and, when the item is
64
+ * expandable, a chevron; the whole row is the toggle. A row inside a group
65
+ * drops its title and speaks up only when something failed or is running.
66
+ */
67
+ export declare function MessageItemHeader({ title, badge, children, style, ...props }: MessageItemHeaderProps): import("react").JSX.Element;
68
+ export interface MessageItemPartProps extends Omit<ViewProps, 'children' | 'style'> {
69
+ children?: ReactNode;
70
+ style?: StyleProp<ViewStyle>;
71
+ }
72
+ /** The body under the header, on the card's own surface. */
73
+ export declare function MessageItemBody({ children, style, ...props }: MessageItemPartProps): import("react").JSX.Element;
74
+ export interface MessageItemStatusProps extends Omit<TextProps, 'children'> {
75
+ tone?: StatusTone;
76
+ /** Replaces the tone's glyph. */
77
+ glyph?: string;
78
+ /** Renders as a button that expands the item: the "N more line(s)" hint. */
79
+ expands?: boolean;
80
+ children?: ReactNode;
81
+ /** Applied to the row; with `expands`, to the button. */
82
+ containerStyle?: StyleProp<ViewStyle>;
83
+ }
84
+ /** The one-line status under a body: `running`, `failed`, `done`, or the hint that more is hidden. */
85
+ export declare function MessageItemStatus({ tone, glyph, expands, children, containerStyle, style, ...props }: MessageItemStatusProps): import("react").JSX.Element;
86
+ //#endregion
87
+ //# sourceMappingURL=MessageItem.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageItem.d.mts","names":[],"sources":["../../src/components/MessageItem.tsx"],"mappings":";;;;iBA0BiB;EACf,MAAM;;EAEN;EACA;EACA;;;wBAWc,kBAAkB;;wBAQlB,SAAS;EAAS;EAAkB;IAAqB;;qBAK5D,cAAc,SAAS,OAAO;;qBAU9B,cAAc,SAAS,OAAO;iBAmB1B,yBAAyB,KAAK;EAC7C,OAAO;;EAEP;EACA;;EAEA;EACA,oBAAoB;;EAEpB,WAAW,cAAc,OAAO,qBAAqB;EACrD,QAAQ,UAAU;;wBAGJ,cACd,MACA,YACA,iBACA,UACA,kBACA,UACA,UACG,SACF,mCAAgB,IAAA;iBA8DF,8BAA8B,KAAK;EAClD,OAAO;;EAEP,OAAO;;EAEP,UAAU;;EAEV,QAAQ;EACR,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAQJ,mBACd,MACA,OACA,SACA,OACA,UACA,UACG,SACF,wCAAqB,IAAA;iBAuBP,+BAA+B,KAAK;;EAEnD,OAAO;;EAEP,QAAQ;;EAER,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAWJ,oBAAoB,OAAO,OAAO,UAAU,UAAU,SAAS,yCAAsB,IAAA;iBAiCpF,6BAA6B,KAAK;EACjD,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,kBAAkB,UAAU,UAAU,SAAS,uCAAoB,IAAA;iBAQlE,+BAA+B,KAAK;EACnD,OAAO;;EAEP;;EAEA;EACA,WAAW;;EAEX,iBAAiB,UAAU;;;wBAIb,oBACd,MACA,OACA,SACA,UACA,gBACA,UACG,SACF,yCAAsB,IAAA"}