@agimon-ai/po-native-components 0.0.0-alpha.41 → 0.0.0-alpha.43

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.
@@ -0,0 +1,54 @@
1
+ import { StyleProp, ViewStyle } from "react-native";
2
+ import { ReactNode } from "react";
3
+ //#region src/components/AnnotationSurface.d.ts
4
+ /** One note pinned to the content, with an optional stroke, in fractions (0 to 1) of the surface's width and height. */
5
+ export interface AnnotationMark {
6
+ id: string;
7
+ x: number;
8
+ y: number;
9
+ /** The short text drawn on the pin, such as "1". */
10
+ label: string;
11
+ /** What a screen reader announces for the pin, such as the note text. */
12
+ description?: string;
13
+ /** Optional normalized freehand stroke. At most 128 finite points are rendered. */
14
+ points?: readonly {
15
+ x: number;
16
+ y: number;
17
+ }[];
18
+ }
19
+ export interface AnnotationSurfaceProps {
20
+ /** The content being marked up: an image, a page, a block of text. */
21
+ children: ReactNode;
22
+ marks: readonly AnnotationMark[];
23
+ selectedId?: string;
24
+ /** A tap places a note there. Without onPlace or onDraw the surface is read-only. */
25
+ onPlace?: (point: {
26
+ x: number;
27
+ y: number;
28
+ }) => void;
29
+ /** Enables drawing instead of tap placement. Receives 2 to 128 finite [0,1] points only on a completed stroke. */
30
+ onDraw?: (points: {
31
+ x: number;
32
+ y: number;
33
+ }[]) => void;
34
+ onSelectMark?: (id: string) => void;
35
+ /** What the content is, such as "hero.png". */
36
+ accessibilityLabel: string;
37
+ /** Image surfaces can pinch and move with two fingers on both native platforms. */
38
+ zoomable?: boolean;
39
+ /** Source-to-viewport transform, useful when capturing the visible image. */
40
+ onViewportChange?: (viewport: {
41
+ zoom: number;
42
+ originX: number;
43
+ originY: number;
44
+ }) => void;
45
+ style?: StyleProp<ViewStyle>;
46
+ }
47
+ /**
48
+ * Tap to pin a note on whatever it wraps. Each pin is its own 44pt button, so a
49
+ * screen reader can reach every note; activating the surface itself places a
50
+ * note at its centre when the tap carries no position.
51
+ */
52
+ export declare function AnnotationSurface({ children, marks, selectedId, onPlace, onDraw, onSelectMark, accessibilityLabel, zoomable, onViewportChange, style }: AnnotationSurfaceProps): import("react").JSX.Element;
53
+ //#endregion
54
+ //# sourceMappingURL=AnnotationSurface.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnnotationSurface.d.mts","names":[],"sources":["../../src/components/AnnotationSurface.tsx"],"mappings":";;;;iBAQiB;EACf;EACA;EACA;;EAEA;;EAEA;;EAEA;IAAoB;IAAW;;;iBAGhB;;EAEf,UAAU;EACV,gBAAgB;EAChB;;EAEA,WAAW;IAAS;IAAW;;;EAE/B,UAAU;IAAU;IAAW;;EAC/B,gBAAgB;;EAEhB;;EAEA;;EAEA,oBAAoB;IAAY;IAAc;IAAiB;;EAC/D,QAAQ,UAAU;;;;;;;wBAwCJ,oBACd,UACA,OACA,YACA,SACA,QACA,cACA,oBACA,UACA,kBACA,SACC,yCAAsB,IAAA"}
@@ -0,0 +1,344 @@
1
+ import { fontOf } from "../lib/fonts.mjs";
2
+ import { selectionTick } from "../lib/haptics.mjs";
3
+ import { View } from "react-native-unistyles/components/native/View";
4
+ import { Text } from "react-native-unistyles/components/native/Text";
5
+ import { StyleSheet } from "react-native-unistyles";
6
+ import { useEffect, useRef, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { Pressable } from "react-native-unistyles/components/native/Pressable";
9
+
10
+ //#region src/components/AnnotationSurface.tsx
11
+ const clamp = (value) => Math.min(1, Math.max(0, value));
12
+ const MAX_POINTS = 128;
13
+ function Stroke({ points, width, height }) {
14
+ const bounded = points.slice(0, MAX_POINTS);
15
+ return bounded.map((point, index) => {
16
+ const previous = bounded[index - 1];
17
+ if (!previous || ![
18
+ point.x,
19
+ point.y,
20
+ previous.x,
21
+ previous.y
22
+ ].every(Number.isFinite)) return null;
23
+ const x = clamp(previous.x) * width;
24
+ const y = clamp(previous.y) * height;
25
+ const dx = clamp(point.x) * width - x;
26
+ const dy = clamp(point.y) * height - y;
27
+ const length = Math.hypot(dx, dy);
28
+ return /* @__PURE__ */ jsx(View, { style: [styles.segment, {
29
+ left: x + dx / 2 - length / 2,
30
+ top: y + dy / 2 - 1.5,
31
+ width: length,
32
+ transform: [{ rotate: `${Math.atan2(dy, dx)}rad` }]
33
+ }] }, index);
34
+ });
35
+ }
36
+ /**
37
+ * Tap to pin a note on whatever it wraps. Each pin is its own 44pt button, so a
38
+ * screen reader can reach every note; activating the surface itself places a
39
+ * note at its centre when the tap carries no position.
40
+ */
41
+ function AnnotationSurface({ children, marks, selectedId, onPlace, onDraw, onSelectMark, accessibilityLabel, zoomable = false, onViewportChange, style }) {
42
+ const [size, setSize] = useState({
43
+ width: 0,
44
+ height: 0
45
+ });
46
+ const [viewport, setViewport] = useState({
47
+ scale: 1,
48
+ x: 0,
49
+ y: 0
50
+ });
51
+ const transform = useRef(viewport);
52
+ const pinch = useRef(null);
53
+ const suppressTap = useRef(false);
54
+ const resetViewport = () => {
55
+ pinch.current = null;
56
+ transform.current = {
57
+ scale: 1,
58
+ x: 0,
59
+ y: 0
60
+ };
61
+ setViewport(transform.current);
62
+ };
63
+ useEffect(() => {
64
+ resetViewport();
65
+ }, [zoomable]);
66
+ useEffect(() => {
67
+ onViewportChange?.({
68
+ zoom: viewport.scale,
69
+ originX: size.width * (1 - viewport.scale) / 2 + viewport.x,
70
+ originY: size.height * (1 - viewport.scale) / 2 + viewport.y
71
+ });
72
+ }, [
73
+ viewport,
74
+ size,
75
+ onViewportChange
76
+ ]);
77
+ const sourcePoint = (x, y) => {
78
+ const current = transform.current;
79
+ return {
80
+ x: clamp((x - size.width / 2 - current.x) / current.scale / size.width + .5),
81
+ y: clamp((y - size.height / 2 - current.y) / current.scale / size.height + .5)
82
+ };
83
+ };
84
+ const moveViewport = (event) => {
85
+ const [first, second] = event.nativeEvent.touches;
86
+ if (!zoomable || !first || !second || size.width <= 0 || size.height <= 0) {
87
+ pinch.current = null;
88
+ return;
89
+ }
90
+ const x = (first.pageX + second.pageX) / 2;
91
+ const y = (first.pageY + second.pageY) / 2;
92
+ const distance = Math.hypot(first.pageX - second.pageX, first.pageY - second.pageY);
93
+ if (![
94
+ x,
95
+ y,
96
+ distance
97
+ ].every(Number.isFinite) || distance <= 0) {
98
+ pinch.current = null;
99
+ return;
100
+ }
101
+ if (!pinch.current) {
102
+ pinch.current = {
103
+ x,
104
+ y,
105
+ distance,
106
+ scale: transform.current.scale,
107
+ offsetX: transform.current.x,
108
+ offsetY: transform.current.y
109
+ };
110
+ return;
111
+ }
112
+ const start = pinch.current;
113
+ const scale = Math.max(1, Math.min(4, start.scale * distance / start.distance));
114
+ const maxX = size.width * (scale - 1) / 2;
115
+ const maxY = size.height * (scale - 1) / 2;
116
+ transform.current = {
117
+ scale,
118
+ x: Math.max(-maxX, Math.min(maxX, start.offsetX + x - start.x)),
119
+ y: Math.max(-maxY, Math.min(maxY, start.offsetY + y - start.y))
120
+ };
121
+ setViewport(transform.current);
122
+ };
123
+ const [live, setLive] = useState([]);
124
+ const stroke = useRef(null);
125
+ const owner = useRef(onDraw);
126
+ const cancel = () => {
127
+ stroke.current = null;
128
+ setLive([]);
129
+ };
130
+ useEffect(() => {
131
+ stroke.current = null;
132
+ setLive([]);
133
+ return () => {
134
+ stroke.current = null;
135
+ };
136
+ }, [onDraw]);
137
+ const append = (event) => {
138
+ if (!stroke.current || !onDraw || owner.current !== onDraw) return cancel();
139
+ const { locationX, locationY, touches } = event.nativeEvent;
140
+ if (touches.length > 1 || ![
141
+ locationX,
142
+ locationY,
143
+ size.width,
144
+ size.height
145
+ ].every(Number.isFinite) || size.width <= 0 || size.height <= 0) return cancel();
146
+ const point = sourcePoint(locationX, locationY);
147
+ const last = stroke.current[stroke.current.length - 1];
148
+ if (last?.x === point.x && last.y === point.y) return;
149
+ if (stroke.current.length < MAX_POINTS) stroke.current.push(point);
150
+ else stroke.current[127] = point;
151
+ setLive([...stroke.current]);
152
+ };
153
+ const place = (event) => {
154
+ if (!onPlace || onDraw || suppressTap.current) return;
155
+ const { locationX, locationY } = event.nativeEvent;
156
+ const known = size.width > 0 && size.height > 0 && Number.isFinite(locationX) && Number.isFinite(locationY);
157
+ selectionTick();
158
+ onPlace(known ? sourcePoint(locationX, locationY) : {
159
+ x: .5,
160
+ y: .5
161
+ });
162
+ };
163
+ return /* @__PURE__ */ jsxs(View, {
164
+ style: [
165
+ styles.frame,
166
+ zoomable && { overflow: "hidden" },
167
+ style
168
+ ],
169
+ onStartShouldSetResponderCapture: (event) => zoomable && event.nativeEvent.touches.length > 1,
170
+ onMoveShouldSetResponderCapture: (event) => zoomable && event.nativeEvent.touches.length > 1,
171
+ onResponderGrant: zoomable ? (event) => {
172
+ cancel();
173
+ suppressTap.current = true;
174
+ moveViewport(event);
175
+ } : void 0,
176
+ onResponderMove: zoomable ? moveViewport : void 0,
177
+ onResponderRelease: zoomable ? () => {
178
+ pinch.current = null;
179
+ } : void 0,
180
+ onResponderTerminationRequest: () => true,
181
+ onResponderTerminate: zoomable ? () => {
182
+ pinch.current = null;
183
+ cancel();
184
+ } : void 0,
185
+ onLayout: (event) => {
186
+ cancel();
187
+ resetViewport();
188
+ setSize({
189
+ width: event.nativeEvent.layout.width,
190
+ height: event.nativeEvent.layout.height
191
+ });
192
+ },
193
+ children: [
194
+ /* @__PURE__ */ jsx(Pressable, {
195
+ accessibilityRole: onPlace && !onDraw ? "button" : "image",
196
+ accessibilityLabel,
197
+ accessibilityHint: onPlace && !onDraw ? "Double tap to add a note here. Use the Note on whole image action to mark the whole image." : void 0,
198
+ accessibilityActions: onPlace ? [{
199
+ name: "noteWholeImage",
200
+ label: "Note on whole image"
201
+ }] : void 0,
202
+ onAccessibilityAction: (event) => {
203
+ if (event.nativeEvent.actionName === "noteWholeImage") onPlace?.({
204
+ x: .5,
205
+ y: .5
206
+ });
207
+ },
208
+ disabled: !onPlace || !!onDraw,
209
+ onPressIn: () => {
210
+ if (!pinch.current) suppressTap.current = false;
211
+ },
212
+ onPress: place,
213
+ children: /* @__PURE__ */ jsxs(View, {
214
+ pointerEvents: zoomable ? "none" : "auto",
215
+ style: zoomable ? { transform: [
216
+ { translateX: viewport.x },
217
+ { translateY: viewport.y },
218
+ { scale: viewport.scale }
219
+ ] } : void 0,
220
+ children: [children, /* @__PURE__ */ jsxs(View, {
221
+ pointerEvents: "none",
222
+ accessible: false,
223
+ style: styles.overlay,
224
+ children: [marks.map((mark) => mark.points && /* @__PURE__ */ jsx(Stroke, {
225
+ points: mark.points,
226
+ width: size.width,
227
+ height: size.height
228
+ }, mark.id)), onDraw && /* @__PURE__ */ jsx(Stroke, {
229
+ points: live,
230
+ width: size.width,
231
+ height: size.height
232
+ })]
233
+ })]
234
+ })
235
+ }),
236
+ onDraw && /* @__PURE__ */ jsx(View, {
237
+ accessible: false,
238
+ style: styles.overlay,
239
+ onStartShouldSetResponder: () => true,
240
+ onResponderGrant: (event) => {
241
+ owner.current = onDraw;
242
+ stroke.current = [];
243
+ append(event);
244
+ },
245
+ onResponderStart: (event) => {
246
+ if (event.nativeEvent.touches.length > 1) cancel();
247
+ },
248
+ onResponderMove: append,
249
+ onResponderRelease: (event) => {
250
+ append(event);
251
+ const points = stroke.current;
252
+ cancel();
253
+ if (points && points.length >= 2 && points.some((point) => point.x !== points[0].x || point.y !== points[0].y)) onDraw(points);
254
+ },
255
+ onResponderTerminationRequest: () => true,
256
+ onResponderTerminate: cancel
257
+ }),
258
+ marks.map((mark) => {
259
+ const selected = mark.id === selectedId;
260
+ return /* @__PURE__ */ jsx(Pressable, {
261
+ accessibilityRole: "button",
262
+ accessibilityLabel: `Note ${mark.label}${mark.description ? `: ${mark.description}` : ""}`,
263
+ accessibilityState: { selected },
264
+ onPress: () => onSelectMark?.(mark.id),
265
+ style: [styles.hit, zoomable ? {
266
+ left: size.width / 2 + (clamp(mark.x) - .5) * size.width * viewport.scale + viewport.x,
267
+ top: size.height / 2 + (clamp(mark.y) - .5) * size.height * viewport.scale + viewport.y
268
+ } : {
269
+ left: `${clamp(mark.x) * 100}%`,
270
+ top: `${clamp(mark.y) * 100}%`
271
+ }],
272
+ children: /* @__PURE__ */ jsx(View, {
273
+ style: [styles.pin, selected && styles.pinSelected],
274
+ children: /* @__PURE__ */ jsx(Text, {
275
+ style: [styles.label, selected && styles.labelSelected],
276
+ children: mark.label
277
+ })
278
+ })
279
+ }, mark.id);
280
+ })
281
+ ]
282
+ });
283
+ }
284
+ const HIT = 44;
285
+ const PIN = 28;
286
+ const styles = StyleSheet.create((theme) => ({
287
+ frame: {
288
+ position: "relative",
289
+ alignSelf: "stretch"
290
+ },
291
+ overlay: {
292
+ position: "absolute",
293
+ top: 0,
294
+ right: 0,
295
+ bottom: 0,
296
+ left: 0
297
+ },
298
+ segment: {
299
+ position: "absolute",
300
+ height: 3,
301
+ borderRadius: 1.5,
302
+ backgroundColor: theme.colors.magenta,
303
+ uni__dependencies: [0]
304
+ },
305
+ hit: {
306
+ position: "absolute",
307
+ width: HIT,
308
+ height: HIT,
309
+ marginLeft: -22,
310
+ marginTop: -22,
311
+ alignItems: "center",
312
+ justifyContent: "center"
313
+ },
314
+ pin: {
315
+ width: PIN,
316
+ height: PIN,
317
+ borderRadius: PIN / 2,
318
+ alignItems: "center",
319
+ justifyContent: "center",
320
+ borderWidth: 2,
321
+ borderColor: theme.colors.magenta,
322
+ backgroundColor: theme.colors.bg,
323
+ uni__dependencies: [0]
324
+ },
325
+ pinSelected: {
326
+ backgroundColor: theme.colors.magenta,
327
+ uni__dependencies: [0]
328
+ },
329
+ label: {
330
+ color: theme.colors.magenta,
331
+ fontFamily: fontOf(theme.fontFamily.sans),
332
+ fontSize: theme.fontSize.sm,
333
+ fontWeight: theme.fontWeight.semibold,
334
+ uni__dependencies: [0]
335
+ },
336
+ labelSelected: {
337
+ color: theme.colors.bg,
338
+ uni__dependencies: [0]
339
+ }
340
+ }));
341
+
342
+ //#endregion
343
+ export { AnnotationSurface };
344
+ //# sourceMappingURL=AnnotationSurface.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnnotationSurface.mjs","names":["ReactNode","useEffect","useRef","useState","GestureResponderEvent","StyleProp","ViewStyle","StyleSheet","fontOf","selectionTick","AnnotationMark","id","x","y","label","description","points","AnnotationSurfaceProps","children","marks","selectedId","onPlace","point","onDraw","onSelectMark","accessibilityLabel","zoomable","onViewportChange","viewport","zoom","originX","originY","style","clamp","value","Math","min","max","MAX_POINTS","Point","Stroke","width","height","bounded","slice","map","index","previous","every","Number","isFinite","dx","dy","length","hypot","styles","segment","left","top","transform","rotate","atan2","AnnotationSurface","size","setSize","setViewport","scale","pinch","distance","offsetX","offsetY","suppressTap","resetViewport","current","sourcePoint","moveViewport","event","first","second","nativeEvent","touches","pageX","pageY","start","maxX","maxY","live","setLive","stroke","owner","cancel","append","locationX","locationY","last","push","place","known","frame","overflow","undefined","layout","name","actionName","translateX","translateY","overlay","mark","some","selected","hit","pin","pinSelected","labelSelected","HIT","PIN","create","theme","position","alignSelf","right","bottom","borderRadius","backgroundColor","colors","magenta","uni__dependencies","marginLeft","marginTop","alignItems","justifyContent","borderWidth","borderColor","bg","color","fontFamily","sans","fontSize","sm","fontWeight","semibold"],"sources":["../../src/components/AnnotationSurface.tsx"],"sourcesContent":["import { type ReactNode, useEffect, useRef, useState } from 'react';\nimport { type GestureResponderEvent, Pressable, type StyleProp, Text, View, type ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\nimport { selectionTick } from '../lib/haptics';\n\n/** One note pinned to the content, with an optional stroke, in fractions (0 to 1) of the surface's width and height. */\nexport interface AnnotationMark {\n id: string;\n x: number;\n y: number;\n /** The short text drawn on the pin, such as \"1\". */\n label: string;\n /** What a screen reader announces for the pin, such as the note text. */\n description?: string;\n /** Optional normalized freehand stroke. At most 128 finite points are rendered. */\n points?: readonly { x: number; y: number }[];\n}\n\nexport interface AnnotationSurfaceProps {\n /** The content being marked up: an image, a page, a block of text. */\n children: ReactNode;\n marks: readonly AnnotationMark[];\n selectedId?: string;\n /** A tap places a note there. Without onPlace or onDraw the surface is read-only. */\n onPlace?: (point: { x: number; y: number }) => void;\n /** Enables drawing instead of tap placement. Receives 2 to 128 finite [0,1] points only on a completed stroke. */\n onDraw?: (points: { x: number; y: number }[]) => void;\n onSelectMark?: (id: string) => void;\n /** What the content is, such as \"hero.png\". */\n accessibilityLabel: string;\n /** Image surfaces can pinch and move with two fingers on both native platforms. */\n zoomable?: boolean;\n /** Source-to-viewport transform, useful when capturing the visible image. */\n onViewportChange?: (viewport: { zoom: number; originX: number; originY: number }) => void;\n style?: StyleProp<ViewStyle>;\n}\n\nconst clamp = (value: number) => Math.min(1, Math.max(0, value));\nconst MAX_POINTS = 128;\ntype Point = { x: number; y: number };\n\nfunction Stroke({ points, width, height }: { points: readonly Point[]; width: number; height: number }) {\n // Slice before processing so even externally supplied strokes have bounded work.\n const bounded = points.slice(0, MAX_POINTS);\n return bounded.map((point, index) => {\n const previous = bounded[index - 1];\n if (!previous || ![point.x, point.y, previous.x, previous.y].every(Number.isFinite)) return null;\n const x = clamp(previous.x) * width;\n const y = clamp(previous.y) * height;\n const dx = clamp(point.x) * width - x;\n const dy = clamp(point.y) * height - y;\n const length = Math.hypot(dx, dy);\n return (\n <View\n key={index}\n style={[\n styles.segment,\n {\n left: x + dx / 2 - length / 2,\n top: y + dy / 2 - 1.5,\n width: length,\n transform: [{ rotate: `${Math.atan2(dy, dx)}rad` }],\n },\n ]}\n />\n );\n });\n}\n\n/**\n * Tap to pin a note on whatever it wraps. Each pin is its own 44pt button, so a\n * screen reader can reach every note; activating the surface itself places a\n * note at its centre when the tap carries no position.\n */\nexport function AnnotationSurface({\n children,\n marks,\n selectedId,\n onPlace,\n onDraw,\n onSelectMark,\n accessibilityLabel,\n zoomable = false,\n onViewportChange,\n style,\n}: AnnotationSurfaceProps) {\n const [size, setSize] = useState({ width: 0, height: 0 });\n const [viewport, setViewport] = useState({ scale: 1, x: 0, y: 0 });\n const transform = useRef(viewport);\n const pinch = useRef<{\n distance: number;\n x: number;\n y: number;\n scale: number;\n offsetX: number;\n offsetY: number;\n } | null>(null);\n const suppressTap = useRef(false);\n const resetViewport = () => {\n pinch.current = null;\n transform.current = { scale: 1, x: 0, y: 0 };\n setViewport(transform.current);\n };\n useEffect(() => {\n resetViewport();\n }, [zoomable]);\n useEffect(() => {\n onViewportChange?.({\n zoom: viewport.scale,\n originX: (size.width * (1 - viewport.scale)) / 2 + viewport.x,\n originY: (size.height * (1 - viewport.scale)) / 2 + viewport.y,\n });\n }, [viewport, size, onViewportChange]);\n const sourcePoint = (x: number, y: number) => {\n const current = transform.current;\n return {\n x: clamp((x - size.width / 2 - current.x) / current.scale / size.width + 0.5),\n y: clamp((y - size.height / 2 - current.y) / current.scale / size.height + 0.5),\n };\n };\n const moveViewport = (event: GestureResponderEvent) => {\n const [first, second] = event.nativeEvent.touches;\n if (!zoomable || !first || !second || size.width <= 0 || size.height <= 0) {\n pinch.current = null;\n return;\n }\n const x = (first.pageX + second.pageX) / 2;\n const y = (first.pageY + second.pageY) / 2;\n const distance = Math.hypot(first.pageX - second.pageX, first.pageY - second.pageY);\n if (![x, y, distance].every(Number.isFinite) || distance <= 0) {\n pinch.current = null;\n return;\n }\n if (!pinch.current) {\n pinch.current = {\n x,\n y,\n distance,\n scale: transform.current.scale,\n offsetX: transform.current.x,\n offsetY: transform.current.y,\n };\n return;\n }\n const start = pinch.current;\n const scale = Math.max(1, Math.min(4, (start.scale * distance) / start.distance));\n const maxX = (size.width * (scale - 1)) / 2;\n const maxY = (size.height * (scale - 1)) / 2;\n transform.current = {\n scale,\n x: Math.max(-maxX, Math.min(maxX, start.offsetX + x - start.x)),\n y: Math.max(-maxY, Math.min(maxY, start.offsetY + y - start.y)),\n };\n setViewport(transform.current);\n };\n const [live, setLive] = useState<readonly Point[]>([]);\n const stroke = useRef<Point[] | null>(null);\n const owner = useRef(onDraw);\n const cancel = () => {\n stroke.current = null;\n setLive([]);\n };\n useEffect(() => {\n stroke.current = null;\n setLive([]);\n return () => {\n stroke.current = null;\n };\n }, [onDraw]);\n const append = (event: GestureResponderEvent) => {\n if (!stroke.current || !onDraw || owner.current !== onDraw) return cancel();\n const { locationX, locationY, touches } = event.nativeEvent;\n if (\n touches.length > 1 ||\n ![locationX, locationY, size.width, size.height].every(Number.isFinite) ||\n size.width <= 0 ||\n size.height <= 0\n )\n return cancel();\n const point = sourcePoint(locationX, locationY);\n const last = stroke.current[stroke.current.length - 1];\n if (last?.x === point.x && last.y === point.y) return;\n // Keep the start and a bounded prefix; update the last point once full.\n if (stroke.current.length < MAX_POINTS) stroke.current.push(point);\n else stroke.current[MAX_POINTS - 1] = point;\n setLive([...stroke.current]);\n };\n const place = (event: GestureResponderEvent) => {\n if (!onPlace || onDraw || suppressTap.current) return;\n const { locationX, locationY } = event.nativeEvent;\n const known = size.width > 0 && size.height > 0 && Number.isFinite(locationX) && Number.isFinite(locationY);\n selectionTick();\n onPlace(known ? sourcePoint(locationX, locationY) : { x: 0.5, y: 0.5 });\n };\n return (\n <View\n style={[styles.frame, zoomable && { overflow: 'hidden' }, style]}\n onStartShouldSetResponderCapture={(event) => zoomable && event.nativeEvent.touches.length > 1}\n onMoveShouldSetResponderCapture={(event) => zoomable && event.nativeEvent.touches.length > 1}\n onResponderGrant={\n zoomable\n ? (event) => {\n cancel();\n suppressTap.current = true;\n moveViewport(event);\n }\n : undefined\n }\n onResponderMove={zoomable ? moveViewport : undefined}\n onResponderRelease={\n zoomable\n ? () => {\n pinch.current = null;\n }\n : undefined\n }\n onResponderTerminationRequest={() => true}\n onResponderTerminate={\n zoomable\n ? () => {\n pinch.current = null;\n cancel();\n }\n : undefined\n }\n onLayout={(event) => {\n cancel();\n resetViewport();\n setSize({ width: event.nativeEvent.layout.width, height: event.nativeEvent.layout.height });\n }}\n >\n <Pressable\n accessibilityRole={onPlace && !onDraw ? 'button' : 'image'}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={\n onPlace && !onDraw\n ? 'Double tap to add a note here. Use the Note on whole image action to mark the whole image.'\n : undefined\n }\n accessibilityActions={onPlace ? [{ name: 'noteWholeImage', label: 'Note on whole image' }] : undefined}\n onAccessibilityAction={(event) => {\n if (event.nativeEvent.actionName === 'noteWholeImage') onPlace?.({ x: 0.5, y: 0.5 });\n }}\n disabled={!onPlace || !!onDraw}\n onPressIn={() => {\n if (!pinch.current) suppressTap.current = false;\n }}\n onPress={place}\n >\n <View\n pointerEvents={zoomable ? 'none' : 'auto'}\n style={\n zoomable\n ? { transform: [{ translateX: viewport.x }, { translateY: viewport.y }, { scale: viewport.scale }] }\n : undefined\n }\n >\n {children}\n <View pointerEvents=\"none\" accessible={false} style={styles.overlay}>\n {marks.map(\n (mark) =>\n mark.points && <Stroke key={mark.id} points={mark.points} width={size.width} height={size.height} />,\n )}\n {onDraw && <Stroke points={live} width={size.width} height={size.height} />}\n </View>\n </View>\n </Pressable>\n {onDraw && (\n <View\n accessible={false}\n style={styles.overlay}\n onStartShouldSetResponder={() => true}\n onResponderGrant={(event) => {\n owner.current = onDraw;\n stroke.current = [];\n append(event);\n }}\n onResponderStart={(event) => {\n if (event.nativeEvent.touches.length > 1) cancel();\n }}\n onResponderMove={append}\n onResponderRelease={(event) => {\n append(event);\n const points = stroke.current;\n cancel();\n if (\n points &&\n points.length >= 2 &&\n points.some((point) => point.x !== points[0].x || point.y !== points[0].y)\n ) {\n onDraw(points);\n }\n }}\n onResponderTerminationRequest={() => true}\n onResponderTerminate={cancel}\n />\n )}\n {marks.map((mark) => {\n const selected = mark.id === selectedId;\n return (\n <Pressable\n key={mark.id}\n accessibilityRole=\"button\"\n accessibilityLabel={`Note ${mark.label}${mark.description ? `: ${mark.description}` : ''}`}\n accessibilityState={{ selected }}\n onPress={() => onSelectMark?.(mark.id)}\n style={[\n styles.hit,\n zoomable\n ? {\n left: size.width / 2 + (clamp(mark.x) - 0.5) * size.width * viewport.scale + viewport.x,\n top: size.height / 2 + (clamp(mark.y) - 0.5) * size.height * viewport.scale + viewport.y,\n }\n : { left: `${clamp(mark.x) * 100}%`, top: `${clamp(mark.y) * 100}%` },\n ]}\n >\n <View style={[styles.pin, selected && styles.pinSelected]}>\n <Text style={[styles.label, selected && styles.labelSelected]}>{mark.label}</Text>\n </View>\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nconst HIT = 44;\nconst PIN = 28;\n\nconst styles = StyleSheet.create((theme) => ({\n frame: { position: 'relative', alignSelf: 'stretch' },\n overlay: { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 },\n segment: { position: 'absolute', height: 3, borderRadius: 1.5, backgroundColor: theme.colors.magenta },\n hit: {\n position: 'absolute',\n width: HIT,\n height: HIT,\n marginLeft: -HIT / 2,\n marginTop: -HIT / 2,\n alignItems: 'center',\n justifyContent: 'center',\n },\n pin: {\n width: PIN,\n height: PIN,\n borderRadius: PIN / 2,\n alignItems: 'center',\n justifyContent: 'center',\n borderWidth: 2,\n borderColor: theme.colors.magenta,\n backgroundColor: theme.colors.bg,\n },\n pinSelected: { backgroundColor: theme.colors.magenta },\n label: {\n color: theme.colors.magenta,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n fontWeight: theme.fontWeight.semibold,\n },\n labelSelected: { color: theme.colors.bg },\n}));\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
+ import { impactLight } from "../lib/haptics.mjs";
2
3
  import { wrapText } from "../lib/wrapText.mjs";
3
4
  import { IconColorContext } from "../icons/IconColorContext.mjs";
4
- import { impactLight } from "../lib/haptics.mjs";
5
5
  import { Spinner } from "./Spinner.mjs";
6
6
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
7
7
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
@@ -1,6 +1,6 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
- import { wrapText } from "../lib/wrapText.mjs";
3
2
  import { selectionTick } from "../lib/haptics.mjs";
3
+ import { wrapText } from "../lib/wrapText.mjs";
4
4
  import { Button } from "./Button.mjs";
5
5
  import { CheckIcon } from "../icons/icons.mjs";
6
6
  import { useControllable } from "../lib/useControllable.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"List.d.mts","names":[],"sources":["../../src/components/List.tsx"],"mappings":";;;iBAoBiB,UAAU;EACzB,eAAe;EACf,aAAa,MAAM,GAAG,kBAAkB;;EAExC,eAAe,MAAM,GAAG;;;;;EAKxB;;EAEA;;EAEA,QAAQ;EACR,SAAS;EACT,SAAS;EACT;EACA;;EAEA,QAAQ,UAAU;;EAElB;;wBAOc,KAAK,KACnB,MACA,YACA,cACA,eACA,YACA,OACA,QACA,QACA,cACA,oBACA,OACA,kBACC,UAAU,qBAAE,IAAA;iBA2BE;EACf,OAAO;;EAEP,cAAc;;EAEd,UAAU;;EAEV,WAAW;;EAEX;EACA;EACA;;EAEA;EACA;EACA,QAAQ,UAAU;;;wBAIJ,UACd,OACA,aACA,SACA,UACA,UACA,UACA,SACA,YACA,oBACA,SACC,+BAAY,IAAA"}
1
+ {"version":3,"file":"List.d.mts","names":[],"sources":["../../src/components/List.tsx"],"mappings":";;;iBAoBiB,UAAU;EACzB,eAAe;EACf,aAAa,MAAM,GAAG,kBAAkB;;EAExC,eAAe,MAAM,GAAG;;;;;EAKxB;;EAEA;;EAEA,QAAQ;EACR,SAAS;EACT,SAAS;EACT;EACA;;EAEA,QAAQ,UAAU;;EAElB;;wBAOc,KAAK,KACnB,MACA,YACA,cACA,eACA,YACA,OACA,QACA,QACA,cACA,oBACA,OACA,kBACC,UAAU,qBAAE,IAAA;iBA6BE;EACf,OAAO;;EAEP,cAAc;;EAEd,UAAU;;EAEV,WAAW;;EAEX;EACA;EACA;;EAEA;EACA;EACA,QAAQ,UAAU;;;wBAIJ,UACd,OACA,aACA,SACA,UACA,UACA,UACA,SACA,YACA,oBACA,SACC,+BAAY,IAAA"}
@@ -32,7 +32,7 @@ function List({ data, renderItem, keyExtractor, startAtBottom = false, separator
32
32
  ListFooterComponent: footer === void 0 ? null : /* @__PURE__ */ jsx(Fragment, { children: footer }),
33
33
  onEndReached,
34
34
  keyboardDismissMode: Platform.OS === "ios" ? "interactive" : "on-drag",
35
- keyboardShouldPersistTaps: "handled",
35
+ keyboardShouldPersistTaps: startAtBottom ? "never" : "handled",
36
36
  contentInsetAdjustmentBehavior: "automatic",
37
37
  contentContainerStyle: contentPadding === void 0 ? void 0 : { padding: contentPadding },
38
38
  maintainVisibleContentPosition: startAtBottom ? {
@@ -1 +1 @@
1
- {"version":3,"file":"List.mjs","names":["FlashList","ReactElement","ReactNode","useCallback","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","renderRow","frame","undefined","OS","padding","startRenderingFromBottom","autoscrollToBottomThreshold","ListRowProps","title","description","leading","trailing","selected","disabled","onPress","disclosure","ListRow","chevron","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, type ReactNode, useCallback } 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 const renderRow = useCallback(({ item, index }: { item: T; index: number }) => renderItem(item, index), [renderItem]);\n return (\n <View style={[styles.frame, style]} accessibilityLabel={accessibilityLabel}>\n <FlashList\n data={data}\n renderItem={renderRow}\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 // Dragging the rows pulls the keyboard down with the finger, as in Messages; a tap on a row still lands.\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n keyboardShouldPersistTaps=\"handled\"\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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"}
1
+ {"version":3,"file":"List.mjs","names":["FlashList","ReactElement","ReactNode","useCallback","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","renderRow","frame","undefined","OS","padding","startRenderingFromBottom","autoscrollToBottomThreshold","ListRowProps","title","description","leading","trailing","selected","disabled","onPress","disclosure","ListRow","chevron","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, type ReactNode, useCallback } 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 const renderRow = useCallback(({ item, index }: { item: T; index: number }) => renderItem(item, index), [renderItem]);\n return (\n <View style={[styles.frame, style]} accessibilityLabel={accessibilityLabel}>\n <FlashList\n data={data}\n renderItem={renderRow}\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 // Dragging the rows pulls the keyboard down with the finger, as in Messages.\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n // A chat's rows are mostly pressable (long-press bubbles, tool groups), so any tap there hides the keyboard\n // first, as in Messages; other lists let a tap on a row land.\n keyboardShouldPersistTaps={startAtBottom ? 'never' : 'handled'}\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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"}
@@ -1,6 +1,6 @@
1
1
  import { InsideSheetContext } from "../lib/insideSheet.mjs";
2
2
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
3
- import { BackHandler } from "react-native";
3
+ import { BackHandler, Keyboard } from "react-native";
4
4
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
5
5
  import { useCallback, useContext, useEffect, useRef } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -26,6 +26,7 @@ function SheetFrame({ open, onClose, children, scrollable = true }) {
26
26
  openRef.current = open;
27
27
  if (open) {
28
28
  presented.current = true;
29
+ Keyboard.dismiss();
29
30
  sheet.current?.present();
30
31
  } else if (presented.current) {
31
32
  presented.current = false;
@@ -1 +1 @@
1
- {"version":3,"file":"SheetFrame.mjs","names":["withAlpha","BottomSheetBackdrop","BottomSheetBackdropProps","BottomSheetModal","BottomSheetScrollView","ReactNode","useCallback","useContext","useEffect","useRef","BackHandler","SafeAreaInsetsContext","StyleSheet","useUnistyles","InsideSheetContext","BACKDROP_ALPHA_PERCENT","SheetFrameProps","open","onClose","children","scrollable","SheetFrame","theme","insets","sheet","openRef","presented","current","present","dismiss","undefined","subscription","addEventListener","remove","backdropColor","colors","deep","renderBackdrop","props","style","backgroundColor","top","rail","borderRadius","lg","border","styles","content","paddingBottom","bottom","create","flexGrow"],"sources":["../../src/components/SheetFrame.tsx"],"sourcesContent":["import { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport {\n BottomSheetBackdrop,\n type BottomSheetBackdropProps,\n BottomSheetModal,\n BottomSheetScrollView,\n} from '@gorhom/bottom-sheet';\nimport { type ReactNode, useCallback, useContext, useEffect, useRef } from 'react';\nimport { BackHandler } from 'react-native';\nimport { SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { InsideSheetContext } from '../lib/insideSheet';\n\n/** `bg-po-deep/70`, the overlay every web sheet and dialog draws. */\nconst BACKDROP_ALPHA_PERCENT = 70;\n\nexport interface SheetFrameProps {\n open: boolean;\n /** The sheet asked to close: a drag down, a backdrop tap or Android back. */\n onClose: () => void;\n children?: ReactNode;\n /** False when the content supplies its own Gorhom virtualized scroll owner. */\n scrollable?: boolean;\n}\n\n/**\n * The bottom sheet both Sheet and DropdownMenu sit in: a drag handle, sized\n * to its content, closed by dragging down, tapping the backdrop or Android\n * back, clear of the safe area and lifted by the keyboard. Private: the public\n * parts keep bottom-sheet types out of the package API.\n */\nexport function SheetFrame({ open, onClose, children, scrollable = true }: SheetFrameProps) {\n const { theme } = useUnistyles();\n const insets = useContext(SafeAreaInsetsContext);\n const sheet = useRef<BottomSheetModal>(null);\n const openRef = useRef(open);\n const presented = useRef(false);\n\n useEffect(() => {\n openRef.current = open;\n if (open) {\n presented.current = true;\n sheet.current?.present();\n } else if (presented.current) {\n // Only a presented sheet is dismissed. Dismissing one that never opened leaves bottom-sheet's\n // modal stuck in its dismissing status, and the next present() then never draws.\n presented.current = false;\n sheet.current?.dismiss();\n }\n }, [open]);\n\n useEffect(() => {\n if (!open) return undefined;\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n onClose();\n return true;\n });\n return () => subscription.remove();\n }, [open, onClose]);\n\n const backdropColor = withAlpha(theme.colors.deep, BACKDROP_ALPHA_PERCENT);\n const renderBackdrop = useCallback(\n (props: BottomSheetBackdropProps) => (\n <BottomSheetBackdrop\n {...props}\n appearsOnIndex={0}\n disappearsOnIndex={-1}\n opacity={1}\n pressBehavior=\"close\"\n style={[props.style, { backgroundColor: backdropColor }]}\n />\n ),\n [backdropColor],\n );\n\n return (\n <BottomSheetModal\n ref={sheet}\n stackBehavior=\"push\"\n enablePanDownToClose\n topInset={insets?.top ?? 0}\n keyboardBehavior=\"interactive\"\n keyboardBlurBehavior=\"restore\"\n android_keyboardInputMode=\"adjustResize\"\n backdropComponent={renderBackdrop}\n backgroundStyle={{ backgroundColor: theme.colors.rail, borderRadius: theme.borderRadius.lg }}\n handleIndicatorStyle={{ backgroundColor: theme.colors.border }}\n // A sheet the caller closed is already shut; only a close the sheet started is reported.\n onDismiss={() => {\n // Already shut, so the close the parent answers with must not dismiss it a second time.\n presented.current = false;\n if (openRef.current) onClose();\n }}\n >\n {scrollable ? (\n <BottomSheetScrollView\n keyboardShouldPersistTaps=\"handled\"\n contentContainerStyle={[styles.content, { paddingBottom: insets?.bottom ?? 0 }]}\n >\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </BottomSheetScrollView>\n ) : (\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n )}\n </BottomSheetModal>\n );\n}\n\nconst styles = StyleSheet.create({ content: { flexGrow: 1 } });\n"],"mappings":";;;;;;;;;;;AAeA,MAAMe,yBAAyB;;;;;;;AAiB/B,SAAgBM,WAAW,EAAEJ,MAAMC,SAASC,UAAUC,aAAa,QAAyB;CAC1F,MAAM,EAAEE,UAAUT,aAAa;CAC/B,MAAMU,SAAShB,WAAWI,qBAAqB;CAC/C,MAAMa,QAAQf,OAAyB,IAAI;CAC3C,MAAMgB,UAAUhB,OAAOQ,IAAI;CAC3B,MAAMS,YAAYjB,OAAO,KAAK;CAE9BD,gBAAgB;EACdiB,QAAQE,UAAUV;EAClB,IAAIA,MAAM;GACRS,UAAUC,UAAU;GACpBH,MAAMG,SAASC,QAAQ;EACzB,OAAO,IAAIF,UAAUC,SAAS;GAG5BD,UAAUC,UAAU;GACpBH,MAAMG,SAASE,QAAQ;EACzB;CACF,GAAG,CAACZ,IAAI,CAAC;CAETT,gBAAgB;EACd,IAAI,CAACS,MAAM,OAAOa;EAClB,MAAMC,eAAerB,YAAYsB,iBAAiB,2BAA2B;GAC3Ed,QAAQ;GACR,OAAO;EACT,CAAC;EACD,aAAaa,aAAaE,OAAO;CACnC,GAAG,CAAChB,MAAMC,OAAO,CAAC;CAElB,MAAMgB,gBAAgBlC,UAAUsB,MAAMa,OAAOC,MAAMrB,sBAAsB;CACzE,MAAMsB,iBAAiB/B,aACpBgC,UACC,oBAAC,qBAAD;EACE,GAAIA;EACJ,gBAAgB;EAChB,mBAAmB;EACnB,SAAS;EACT,eAAc;EACd,OAAO,CAACA,MAAMC,OAAO,EAAEC,iBAAiBN,cAAc,CAAC;CAAE,IAG7D,CAACA,aAAa,CAChB;CAEA,OACE,oBAAC,kBAAD;EACE,KAAKV;EACL,eAAc;EACd;EACA,UAAUD,QAAQkB,OAAO;EACzB,kBAAiB;EACjB,sBAAqB;EACrB,2BAA0B;EAC1B,mBAAmBJ;EACnB,iBAAiB;GAAEG,iBAAiBlB,MAAMa,OAAOO;GAAMC,cAAcrB,MAAMqB,aAAaC;EAAG;EAC3F,sBAAsB,EAAEJ,iBAAiBlB,MAAMa,OAAOU,OAAO;EAE7D,iBAAiB;GAEfnB,UAAUC,UAAU;GACpB,IAAIF,QAAQE,SAAST,QAAQ;EAC/B;YAECE,aACC,oBAAC,uBAAD;GACE,2BAA0B;GAC1B,uBAAuB,CAAC0B,OAAOC,SAAS,EAAEC,eAAezB,QAAQ0B,UAAU,EAAE,CAAC;aAE9E,oBAAC,mBAAmB,UAApB;IAA6B;IAAO9B;GAAsC;EACrD,KAEvB,oBAAC,mBAAmB,UAApB;GAA6B;GAAOA;EAAsC;CAE5D;AAEtB;AAEA,MAAM2B,SAASlC,WAAWsC,OAAO,EAAEH,SAAS,EAAEI,UAAU,EAAE,EAAE,CAAC"}
1
+ {"version":3,"file":"SheetFrame.mjs","names":["withAlpha","BottomSheetBackdrop","BottomSheetBackdropProps","BottomSheetModal","BottomSheetScrollView","ReactNode","useCallback","useContext","useEffect","useRef","BackHandler","Keyboard","SafeAreaInsetsContext","StyleSheet","useUnistyles","InsideSheetContext","BACKDROP_ALPHA_PERCENT","SheetFrameProps","open","onClose","children","scrollable","SheetFrame","theme","insets","sheet","openRef","presented","current","dismiss","present","undefined","subscription","addEventListener","remove","backdropColor","colors","deep","renderBackdrop","props","style","backgroundColor","top","rail","borderRadius","lg","border","styles","content","paddingBottom","bottom","create","flexGrow"],"sources":["../../src/components/SheetFrame.tsx"],"sourcesContent":["import { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport {\n BottomSheetBackdrop,\n type BottomSheetBackdropProps,\n BottomSheetModal,\n BottomSheetScrollView,\n} from '@gorhom/bottom-sheet';\nimport { type ReactNode, useCallback, useContext, useEffect, useRef } from 'react';\nimport { BackHandler, Keyboard } from 'react-native';\nimport { SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { InsideSheetContext } from '../lib/insideSheet';\n\n/** `bg-po-deep/70`, the overlay every web sheet and dialog draws. */\nconst BACKDROP_ALPHA_PERCENT = 70;\n\nexport interface SheetFrameProps {\n open: boolean;\n /** The sheet asked to close: a drag down, a backdrop tap or Android back. */\n onClose: () => void;\n children?: ReactNode;\n /** False when the content supplies its own Gorhom virtualized scroll owner. */\n scrollable?: boolean;\n}\n\n/**\n * The bottom sheet both Sheet and DropdownMenu sit in: a drag handle, sized\n * to its content, closed by dragging down, tapping the backdrop or Android\n * back, clear of the safe area and lifted by the keyboard. Private: the public\n * parts keep bottom-sheet types out of the package API.\n */\nexport function SheetFrame({ open, onClose, children, scrollable = true }: SheetFrameProps) {\n const { theme } = useUnistyles();\n const insets = useContext(SafeAreaInsetsContext);\n const sheet = useRef<BottomSheetModal>(null);\n const openRef = useRef(open);\n const presented = useRef(false);\n\n useEffect(() => {\n openRef.current = open;\n if (open) {\n presented.current = true;\n // The keyboard of the field behind would cover the sheet; a field inside it focuses after this.\n Keyboard.dismiss();\n sheet.current?.present();\n } else if (presented.current) {\n // Only a presented sheet is dismissed. Dismissing one that never opened leaves bottom-sheet's\n // modal stuck in its dismissing status, and the next present() then never draws.\n presented.current = false;\n sheet.current?.dismiss();\n }\n }, [open]);\n\n useEffect(() => {\n if (!open) return undefined;\n const subscription = BackHandler.addEventListener('hardwareBackPress', () => {\n onClose();\n return true;\n });\n return () => subscription.remove();\n }, [open, onClose]);\n\n const backdropColor = withAlpha(theme.colors.deep, BACKDROP_ALPHA_PERCENT);\n const renderBackdrop = useCallback(\n (props: BottomSheetBackdropProps) => (\n <BottomSheetBackdrop\n {...props}\n appearsOnIndex={0}\n disappearsOnIndex={-1}\n opacity={1}\n pressBehavior=\"close\"\n style={[props.style, { backgroundColor: backdropColor }]}\n />\n ),\n [backdropColor],\n );\n\n return (\n <BottomSheetModal\n ref={sheet}\n stackBehavior=\"push\"\n enablePanDownToClose\n topInset={insets?.top ?? 0}\n keyboardBehavior=\"interactive\"\n keyboardBlurBehavior=\"restore\"\n android_keyboardInputMode=\"adjustResize\"\n backdropComponent={renderBackdrop}\n backgroundStyle={{ backgroundColor: theme.colors.rail, borderRadius: theme.borderRadius.lg }}\n handleIndicatorStyle={{ backgroundColor: theme.colors.border }}\n // A sheet the caller closed is already shut; only a close the sheet started is reported.\n onDismiss={() => {\n // Already shut, so the close the parent answers with must not dismiss it a second time.\n presented.current = false;\n if (openRef.current) onClose();\n }}\n >\n {scrollable ? (\n <BottomSheetScrollView\n keyboardShouldPersistTaps=\"handled\"\n contentContainerStyle={[styles.content, { paddingBottom: insets?.bottom ?? 0 }]}\n >\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </BottomSheetScrollView>\n ) : (\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n )}\n </BottomSheetModal>\n );\n}\n\nconst styles = StyleSheet.create({ content: { flexGrow: 1 } });\n"],"mappings":";;;;;;;;;;;AAeA,MAAMgB,yBAAyB;;;;;;;AAiB/B,SAAgBM,WAAW,EAAEJ,MAAMC,SAASC,UAAUC,aAAa,QAAyB;CAC1F,MAAM,EAAEE,UAAUT,aAAa;CAC/B,MAAMU,SAASjB,WAAWK,qBAAqB;CAC/C,MAAMa,QAAQhB,OAAyB,IAAI;CAC3C,MAAMiB,UAAUjB,OAAOS,IAAI;CAC3B,MAAMS,YAAYlB,OAAO,KAAK;CAE9BD,gBAAgB;EACdkB,QAAQE,UAAUV;EAClB,IAAIA,MAAM;GACRS,UAAUC,UAAU;GAEpBjB,SAASkB,QAAQ;GACjBJ,MAAMG,SAASE,QAAQ;EACzB,OAAO,IAAIH,UAAUC,SAAS;GAG5BD,UAAUC,UAAU;GACpBH,MAAMG,SAASC,QAAQ;EACzB;CACF,GAAG,CAACX,IAAI,CAAC;CAETV,gBAAgB;EACd,IAAI,CAACU,MAAM,OAAOa;EAClB,MAAMC,eAAetB,YAAYuB,iBAAiB,2BAA2B;GAC3Ed,QAAQ;GACR,OAAO;EACT,CAAC;EACD,aAAaa,aAAaE,OAAO;CACnC,GAAG,CAAChB,MAAMC,OAAO,CAAC;CAElB,MAAMgB,gBAAgBnC,UAAUuB,MAAMa,OAAOC,MAAMrB,sBAAsB;CACzE,MAAMsB,iBAAiBhC,aACpBiC,UACC,oBAAC,qBAAD;EACE,GAAIA;EACJ,gBAAgB;EAChB,mBAAmB;EACnB,SAAS;EACT,eAAc;EACd,OAAO,CAACA,MAAMC,OAAO,EAAEC,iBAAiBN,cAAc,CAAC;CAAE,IAG7D,CAACA,aAAa,CAChB;CAEA,OACE,oBAAC,kBAAD;EACE,KAAKV;EACL,eAAc;EACd;EACA,UAAUD,QAAQkB,OAAO;EACzB,kBAAiB;EACjB,sBAAqB;EACrB,2BAA0B;EAC1B,mBAAmBJ;EACnB,iBAAiB;GAAEG,iBAAiBlB,MAAMa,OAAOO;GAAMC,cAAcrB,MAAMqB,aAAaC;EAAG;EAC3F,sBAAsB,EAAEJ,iBAAiBlB,MAAMa,OAAOU,OAAO;EAE7D,iBAAiB;GAEfnB,UAAUC,UAAU;GACpB,IAAIF,QAAQE,SAAST,QAAQ;EAC/B;YAECE,aACC,oBAAC,uBAAD;GACE,2BAA0B;GAC1B,uBAAuB,CAAC0B,OAAOC,SAAS,EAAEC,eAAezB,QAAQ0B,UAAU,EAAE,CAAC;aAE9E,oBAAC,mBAAmB,UAApB;IAA6B;IAAO9B;GAAsC;EACrD,KAEvB,oBAAC,mBAAmB,UAApB;GAA6B;GAAOA;EAAsC;CAE5D;AAEtB;AAEA,MAAM2B,SAASlC,WAAWsC,OAAO,EAAEH,SAAS,EAAEI,UAAU,EAAE,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
- import { wrapText } from "../lib/wrapText.mjs";
3
2
  import { selectionTick } from "../lib/haptics.mjs";
3
+ import { wrapText } from "../lib/wrapText.mjs";
4
4
  import { useControllable } from "../lib/useControllable.mjs";
5
5
  import { View } from "react-native-unistyles/components/native/View";
6
6
  import { Text } from "react-native-unistyles/components/native/Text";
@@ -86,6 +86,10 @@ export declare const ICON_GLYPHS: {
86
86
  readonly sf: "folder";
87
87
  readonly material: "folder";
88
88
  };
89
+ readonly Globe: {
90
+ readonly sf: "globe";
91
+ readonly material: "public";
92
+ };
89
93
  readonly Branch: {
90
94
  readonly sf: "arrow.triangle.branch";
91
95
  readonly material: "call-split";
@@ -1 +1 @@
1
- {"version":3,"file":"iconGlyphs.d.mts","names":[],"sources":["../../src/icons/iconGlyphs.ts"],"mappings":";;;;;;;qBAMa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAyCD,wBAAwB"}
1
+ {"version":3,"file":"iconGlyphs.d.mts","names":[],"sources":["../../src/icons/iconGlyphs.ts"],"mappings":";;;;;;;qBAMa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA0CD,wBAAwB"}
@@ -86,6 +86,10 @@ const ICON_GLYPHS = {
86
86
  sf: "folder",
87
87
  material: "folder"
88
88
  },
89
+ Globe: {
90
+ sf: "globe",
91
+ material: "public"
92
+ },
89
93
  Branch: {
90
94
  sf: "arrow.triangle.branch",
91
95
  material: "call-split"
@@ -1 +1 @@
1
- {"version":3,"file":"iconGlyphs.mjs","names":[],"sources":["../../src/icons/iconGlyphs.ts"],"sourcesContent":["/**\n * The curated native icon set: the same names the web library re-exports from\n * lucide, each drawn with the platform's own family. iOS gets an SF Symbol,\n * Android and web get a Material Icons glyph. Kept free of React Native so a\n * unit test can check every glyph against the installed glyph map.\n */\nexport const ICON_GLYPHS = {\n Check: { sf: 'checkmark', material: 'check' },\n ChevronDown: { sf: 'chevron.down', material: 'expand-more' },\n ChevronRight: { sf: 'chevron.right', material: 'chevron-right' },\n ChevronUp: { sf: 'chevron.up', material: 'expand-less' },\n Alert: { sf: 'exclamationmark.circle', material: 'error-outline' },\n Copy: { sf: 'doc.on.doc', material: 'content-copy' },\n Message: { sf: 'message', material: 'chat-bubble-outline' },\n // Each platform's own overflow mark: a horizontal ellipsis on iOS, vertical dots on Android.\n Kebab: { sf: 'ellipsis', material: 'more-vert' },\n Edit: { sf: 'pencil', material: 'edit' },\n Gear: { sf: 'gearshape', material: 'settings' },\n Send: { sf: 'paperplane', material: 'send' },\n Task: { sf: 'checkmark.square', material: 'check-box' },\n Trash: { sf: 'trash', material: 'delete-outline' },\n Wrench: { sf: 'wrench.and.screwdriver', material: 'build' },\n Close: { sf: 'xmark', material: 'close' },\n File: { sf: 'doc', material: 'insert-drive-file' },\n Search: { sf: 'magnifyingglass', material: 'search' },\n Image: { sf: 'photo', material: 'image' },\n Sliders: { sf: 'slider.horizontal.3', material: 'tune' },\n Folder: { sf: 'folder', material: 'folder' },\n Branch: { sf: 'arrow.triangle.branch', material: 'call-split' },\n // ponytail: SF Symbols has no fork distinct from a branch, so iOS draws Fork as Branch. Swap in a custom symbol if the two must differ there.\n Fork: { sf: 'arrow.triangle.branch', material: 'fork-right' },\n Home: { sf: 'house', material: 'home' },\n Activity: { sf: 'waveform.path.ecg', material: 'monitor-heart' },\n ArrowRight: { sf: 'arrow.right', material: 'arrow-forward' },\n Plus: { sf: 'plus', material: 'add' },\n Users: { sf: 'person.2', material: 'group' },\n PlayCircle: { sf: 'play.circle', material: 'play-circle-outline' },\n Workflow: { sf: 'flowchart', material: 'account-tree' },\n Palette: { sf: 'paintpalette', material: 'palette' },\n Lightbulb: { sf: 'lightbulb', material: 'lightbulb-outline' },\n Sparkles: { sf: 'sparkles', material: 'auto-awesome' },\n Lock: { sf: 'lock', material: 'lock-outline' },\n Download: { sf: 'square.and.arrow.down', material: 'file-download' },\n Mic: { sf: 'mic', material: 'mic' },\n Stop: { sf: 'stop.fill', material: 'stop' },\n} as const;\n\nexport type IconName = keyof typeof ICON_GLYPHS;\n"],"mappings":";;;;;;;AAMA,MAAa,cAAc;CACzB,OAAO;EAAE,IAAI;EAAa,UAAU;CAAQ;CAC5C,aAAa;EAAE,IAAI;EAAgB,UAAU;CAAc;CAC3D,cAAc;EAAE,IAAI;EAAiB,UAAU;CAAgB;CAC/D,WAAW;EAAE,IAAI;EAAc,UAAU;CAAc;CACvD,OAAO;EAAE,IAAI;EAA0B,UAAU;CAAgB;CACjE,MAAM;EAAE,IAAI;EAAc,UAAU;CAAe;CACnD,SAAS;EAAE,IAAI;EAAW,UAAU;CAAsB;CAE1D,OAAO;EAAE,IAAI;EAAY,UAAU;CAAY;CAC/C,MAAM;EAAE,IAAI;EAAU,UAAU;CAAO;CACvC,MAAM;EAAE,IAAI;EAAa,UAAU;CAAW;CAC9C,MAAM;EAAE,IAAI;EAAc,UAAU;CAAO;CAC3C,MAAM;EAAE,IAAI;EAAoB,UAAU;CAAY;CACtD,OAAO;EAAE,IAAI;EAAS,UAAU;CAAiB;CACjD,QAAQ;EAAE,IAAI;EAA0B,UAAU;CAAQ;CAC1D,OAAO;EAAE,IAAI;EAAS,UAAU;CAAQ;CACxC,MAAM;EAAE,IAAI;EAAO,UAAU;CAAoB;CACjD,QAAQ;EAAE,IAAI;EAAmB,UAAU;CAAS;CACpD,OAAO;EAAE,IAAI;EAAS,UAAU;CAAQ;CACxC,SAAS;EAAE,IAAI;EAAuB,UAAU;CAAO;CACvD,QAAQ;EAAE,IAAI;EAAU,UAAU;CAAS;CAC3C,QAAQ;EAAE,IAAI;EAAyB,UAAU;CAAa;CAE9D,MAAM;EAAE,IAAI;EAAyB,UAAU;CAAa;CAC5D,MAAM;EAAE,IAAI;EAAS,UAAU;CAAO;CACtC,UAAU;EAAE,IAAI;EAAqB,UAAU;CAAgB;CAC/D,YAAY;EAAE,IAAI;EAAe,UAAU;CAAgB;CAC3D,MAAM;EAAE,IAAI;EAAQ,UAAU;CAAM;CACpC,OAAO;EAAE,IAAI;EAAY,UAAU;CAAQ;CAC3C,YAAY;EAAE,IAAI;EAAe,UAAU;CAAsB;CACjE,UAAU;EAAE,IAAI;EAAa,UAAU;CAAe;CACtD,SAAS;EAAE,IAAI;EAAgB,UAAU;CAAU;CACnD,WAAW;EAAE,IAAI;EAAa,UAAU;CAAoB;CAC5D,UAAU;EAAE,IAAI;EAAY,UAAU;CAAe;CACrD,MAAM;EAAE,IAAI;EAAQ,UAAU;CAAe;CAC7C,UAAU;EAAE,IAAI;EAAyB,UAAU;CAAgB;CACnE,KAAK;EAAE,IAAI;EAAO,UAAU;CAAM;CAClC,MAAM;EAAE,IAAI;EAAa,UAAU;CAAO;AAC5C"}
1
+ {"version":3,"file":"iconGlyphs.mjs","names":[],"sources":["../../src/icons/iconGlyphs.ts"],"sourcesContent":["/**\n * The curated native icon set: the same names the web library re-exports from\n * lucide, each drawn with the platform's own family. iOS gets an SF Symbol,\n * Android and web get a Material Icons glyph. Kept free of React Native so a\n * unit test can check every glyph against the installed glyph map.\n */\nexport const ICON_GLYPHS = {\n Check: { sf: 'checkmark', material: 'check' },\n ChevronDown: { sf: 'chevron.down', material: 'expand-more' },\n ChevronRight: { sf: 'chevron.right', material: 'chevron-right' },\n ChevronUp: { sf: 'chevron.up', material: 'expand-less' },\n Alert: { sf: 'exclamationmark.circle', material: 'error-outline' },\n Copy: { sf: 'doc.on.doc', material: 'content-copy' },\n Message: { sf: 'message', material: 'chat-bubble-outline' },\n // Each platform's own overflow mark: a horizontal ellipsis on iOS, vertical dots on Android.\n Kebab: { sf: 'ellipsis', material: 'more-vert' },\n Edit: { sf: 'pencil', material: 'edit' },\n Gear: { sf: 'gearshape', material: 'settings' },\n Send: { sf: 'paperplane', material: 'send' },\n Task: { sf: 'checkmark.square', material: 'check-box' },\n Trash: { sf: 'trash', material: 'delete-outline' },\n Wrench: { sf: 'wrench.and.screwdriver', material: 'build' },\n Close: { sf: 'xmark', material: 'close' },\n File: { sf: 'doc', material: 'insert-drive-file' },\n Search: { sf: 'magnifyingglass', material: 'search' },\n Image: { sf: 'photo', material: 'image' },\n Sliders: { sf: 'slider.horizontal.3', material: 'tune' },\n Folder: { sf: 'folder', material: 'folder' },\n Globe: { sf: 'globe', material: 'public' },\n Branch: { sf: 'arrow.triangle.branch', material: 'call-split' },\n // ponytail: SF Symbols has no fork distinct from a branch, so iOS draws Fork as Branch. Swap in a custom symbol if the two must differ there.\n Fork: { sf: 'arrow.triangle.branch', material: 'fork-right' },\n Home: { sf: 'house', material: 'home' },\n Activity: { sf: 'waveform.path.ecg', material: 'monitor-heart' },\n ArrowRight: { sf: 'arrow.right', material: 'arrow-forward' },\n Plus: { sf: 'plus', material: 'add' },\n Users: { sf: 'person.2', material: 'group' },\n PlayCircle: { sf: 'play.circle', material: 'play-circle-outline' },\n Workflow: { sf: 'flowchart', material: 'account-tree' },\n Palette: { sf: 'paintpalette', material: 'palette' },\n Lightbulb: { sf: 'lightbulb', material: 'lightbulb-outline' },\n Sparkles: { sf: 'sparkles', material: 'auto-awesome' },\n Lock: { sf: 'lock', material: 'lock-outline' },\n Download: { sf: 'square.and.arrow.down', material: 'file-download' },\n Mic: { sf: 'mic', material: 'mic' },\n Stop: { sf: 'stop.fill', material: 'stop' },\n} as const;\n\nexport type IconName = keyof typeof ICON_GLYPHS;\n"],"mappings":";;;;;;;AAMA,MAAa,cAAc;CACzB,OAAO;EAAE,IAAI;EAAa,UAAU;CAAQ;CAC5C,aAAa;EAAE,IAAI;EAAgB,UAAU;CAAc;CAC3D,cAAc;EAAE,IAAI;EAAiB,UAAU;CAAgB;CAC/D,WAAW;EAAE,IAAI;EAAc,UAAU;CAAc;CACvD,OAAO;EAAE,IAAI;EAA0B,UAAU;CAAgB;CACjE,MAAM;EAAE,IAAI;EAAc,UAAU;CAAe;CACnD,SAAS;EAAE,IAAI;EAAW,UAAU;CAAsB;CAE1D,OAAO;EAAE,IAAI;EAAY,UAAU;CAAY;CAC/C,MAAM;EAAE,IAAI;EAAU,UAAU;CAAO;CACvC,MAAM;EAAE,IAAI;EAAa,UAAU;CAAW;CAC9C,MAAM;EAAE,IAAI;EAAc,UAAU;CAAO;CAC3C,MAAM;EAAE,IAAI;EAAoB,UAAU;CAAY;CACtD,OAAO;EAAE,IAAI;EAAS,UAAU;CAAiB;CACjD,QAAQ;EAAE,IAAI;EAA0B,UAAU;CAAQ;CAC1D,OAAO;EAAE,IAAI;EAAS,UAAU;CAAQ;CACxC,MAAM;EAAE,IAAI;EAAO,UAAU;CAAoB;CACjD,QAAQ;EAAE,IAAI;EAAmB,UAAU;CAAS;CACpD,OAAO;EAAE,IAAI;EAAS,UAAU;CAAQ;CACxC,SAAS;EAAE,IAAI;EAAuB,UAAU;CAAO;CACvD,QAAQ;EAAE,IAAI;EAAU,UAAU;CAAS;CAC3C,OAAO;EAAE,IAAI;EAAS,UAAU;CAAS;CACzC,QAAQ;EAAE,IAAI;EAAyB,UAAU;CAAa;CAE9D,MAAM;EAAE,IAAI;EAAyB,UAAU;CAAa;CAC5D,MAAM;EAAE,IAAI;EAAS,UAAU;CAAO;CACtC,UAAU;EAAE,IAAI;EAAqB,UAAU;CAAgB;CAC/D,YAAY;EAAE,IAAI;EAAe,UAAU;CAAgB;CAC3D,MAAM;EAAE,IAAI;EAAQ,UAAU;CAAM;CACpC,OAAO;EAAE,IAAI;EAAY,UAAU;CAAQ;CAC3C,YAAY;EAAE,IAAI;EAAe,UAAU;CAAsB;CACjE,UAAU;EAAE,IAAI;EAAa,UAAU;CAAe;CACtD,SAAS;EAAE,IAAI;EAAgB,UAAU;CAAU;CACnD,WAAW;EAAE,IAAI;EAAa,UAAU;CAAoB;CAC5D,UAAU;EAAE,IAAI;EAAY,UAAU;CAAe;CACrD,MAAM;EAAE,IAAI;EAAQ,UAAU;CAAe;CAC7C,UAAU;EAAE,IAAI;EAAyB,UAAU;CAAgB;CACnE,KAAK;EAAE,IAAI;EAAO,UAAU;CAAM;CAClC,MAAM;EAAE,IAAI;EAAa,UAAU;CAAO;AAC5C"}
@@ -74,6 +74,10 @@ export declare const FolderIcon: {
74
74
  ({ size, color, accessibilityLabel, style }: IconProps): import("react").JSX.Element;
75
75
  displayName: string;
76
76
  };
77
+ export declare const GlobeIcon: {
78
+ ({ size, color, accessibilityLabel, style }: IconProps): import("react").JSX.Element;
79
+ displayName: string;
80
+ };
77
81
  export declare const BranchIcon: {
78
82
  ({ size, color, accessibilityLabel, style }: IconProps): import("react").JSX.Element;
79
83
  displayName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.mts","names":[],"sources":["../../src/icons/icons.tsx"],"mappings":";;;iBAaiB;;EAEf;;EAEA,QAAQ;;EAER;EACA,QAAQ,UAAU;;qBAkCP;KA7B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8BvE;KA9B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+BvE;KA/B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgCvE;KAhC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiCvE;KAjC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAkCvE;KAlC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAmCvE;KAnC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAoCvE;KApC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAqCvE;KArC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAsCvE;KAtC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAuCvE;KAvC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAwCvE;KAxC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAyCvE;KAzC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA0CvE;KA1C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA2CvE;KA3C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA4CvE;KA5C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA6CvE;KA7C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8CvE;KA9C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+CvE;KA/C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgDvE;KAhD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiDvE;KAjD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAkDvE;KAlD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAmDvE;KAnD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAoDvE;KApD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAqDvE;KArD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAsDvE;KAtD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAuDvE;KAvD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAwDvE;KAxD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAyDvE;KAzD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA2DvE;KA3D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA4DvE;KA5D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA6DvE;KA7D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8DvE;KA9D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+DvE;KA/D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgEvE;KAhE8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiEvE;KAjE8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA"}
1
+ {"version":3,"file":"icons.d.mts","names":[],"sources":["../../src/icons/icons.tsx"],"mappings":";;;iBAaiB;;EAEf;;EAEA,QAAQ;;EAER;EACA,QAAQ,UAAU;;qBAkCP;KA7B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8BvE;KA9B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+BvE;KA/B8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgCvE;KAhC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiCvE;KAjC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAkCvE;KAlC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAmCvE;KAnC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAoCvE;KApC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAqCvE;KArC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAsCvE;KAtC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAuCvE;KAvC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAwCvE;KAxC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAyCvE;KAzC8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA0CvE;KA1C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA2CvE;KA3C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA4CvE;KA5C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA6CvE;KA7C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8CvE;KA9C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+CvE;KA/C8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgDvE;KAhD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiDvE;KAjD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAkDvE;KAlD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAmDvE;KAnD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAoDvE;KApD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAqDvE;KArD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAsDvE;KAtD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAuDvE;KAvD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAwDvE;KAxD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAyDvE;KAzD8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA0DvE;KA1D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA4DvE;KA5D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA6DvE;KA7D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA8DvE;KA9D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBA+DvE;KA/D8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAgEvE;KAhE8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAiEvE;KAjE8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA;;;qBAkEvE;KAlE8D,MAAA,OAAA,oBAAA,SAAA,4BAAS,IAAA"}
@@ -62,6 +62,7 @@ const TrashIcon = createIcon("Trash");
62
62
  const WrenchIcon = createIcon("Wrench");
63
63
  const CloseIcon = createIcon("Close");
64
64
  const FolderIcon = createIcon("Folder");
65
+ const GlobeIcon = createIcon("Globe");
65
66
  const BranchIcon = createIcon("Branch");
66
67
  const ForkIcon = createIcon("Fork");
67
68
  const HomeIcon = createIcon("Home");
@@ -84,5 +85,5 @@ const MicIcon = createIcon("Mic");
84
85
  const StopIcon = createIcon("Stop");
85
86
 
86
87
  //#endregion
87
- export { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, HomeIcon, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon };
88
+ export { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HomeIcon, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon };
88
89
  //# sourceMappingURL=icons.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.mjs","names":["NativeColorToken","MaterialIcons","SymbolView","useContext","Platform","StyleProp","ViewStyle","useUnistyles","IconColorContext","ICON_GLYPHS","IconName","DEFAULT_SIZE","DEFAULT_COLOR","IconProps","size","color","accessibilityLabel","style","createIcon","name","glyph","Icon","theme","inherited","tint","colors","a11y","undefined","accessible","importantForAccessibility","accessibilityElementsHidden","const","accessibilityRole","OS","sf","width","height","material","displayName","CheckIcon","ChevronDownIcon","ChevronRightIcon","ChevronUpIcon","AlertIcon","CopyIcon","MessageIcon","KebabIcon","EditIcon","GearIcon","SendIcon","TaskIcon","TrashIcon","WrenchIcon","CloseIcon","FolderIcon","BranchIcon","ForkIcon","HomeIcon","ActivityIcon","ArrowRightIcon","PlusIcon","UsersIcon","PlayCircleIcon","WorkflowIcon","PaletteIcon","LightbulbIcon","SparklesIcon","LockIcon","FileIcon","SearchIcon","ImageIcon","SlidersIcon","DownloadIcon","MicIcon","StopIcon"],"sources":["../../src/icons/icons.tsx"],"sourcesContent":["import type { NativeColorToken } from '@agimon-ai/po-web-components/nativeTheme';\nimport MaterialIcons from '@expo/vector-icons/MaterialIcons';\nimport { SymbolView } from 'expo-symbols';\nimport { useContext } from 'react';\nimport { Platform, type StyleProp, type ViewStyle } from 'react-native';\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport { IconColorContext } from './IconColorContext';\nimport { ICON_GLYPHS, type IconName } from './iconGlyphs';\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_COLOR: NativeColorToken = 'dim';\n\nexport interface IconProps {\n /** Edge length in points. */\n size?: number;\n /** A theme token; defaults to the enclosing Button's label colour, else `dim`. */\n color?: NativeColorToken;\n /** Given one, the icon is announced as an image; without one it is hidden from screen readers. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nfunction createIcon(name: IconName) {\n const glyph = ICON_GLYPHS[name];\n function Icon({ size = DEFAULT_SIZE, color, accessibilityLabel, style }: IconProps) {\n const { theme } = useUnistyles();\n const inherited = useContext(IconColorContext);\n const tint = theme.colors[color ?? inherited ?? DEFAULT_COLOR];\n const a11y =\n accessibilityLabel === undefined\n ? ({\n accessible: false,\n importantForAccessibility: 'no-hide-descendants',\n accessibilityElementsHidden: true,\n } as const)\n : ({ accessible: true, accessibilityRole: 'image', accessibilityLabel } as const);\n if (Platform.OS === 'ios') {\n return (\n <SymbolView\n name={glyph.sf}\n size={size}\n tintColor={tint}\n style={[{ width: size, height: size }, style]}\n {...a11y}\n />\n );\n }\n return <MaterialIcons name={glyph.material} size={size} color={tint} style={style} {...a11y} />;\n }\n Icon.displayName = `${name}Icon`;\n return Icon;\n}\n\nexport const CheckIcon = createIcon('Check');\nexport const ChevronDownIcon = createIcon('ChevronDown');\nexport const ChevronRightIcon = createIcon('ChevronRight');\nexport const ChevronUpIcon = createIcon('ChevronUp');\nexport const AlertIcon = createIcon('Alert');\nexport const CopyIcon = createIcon('Copy');\nexport const MessageIcon = createIcon('Message');\nexport const KebabIcon = createIcon('Kebab');\nexport const EditIcon = createIcon('Edit');\nexport const GearIcon = createIcon('Gear');\nexport const SendIcon = createIcon('Send');\nexport const TaskIcon = createIcon('Task');\nexport const TrashIcon = createIcon('Trash');\nexport const WrenchIcon = createIcon('Wrench');\nexport const CloseIcon = createIcon('Close');\nexport const FolderIcon = createIcon('Folder');\nexport const BranchIcon = createIcon('Branch');\nexport const ForkIcon = createIcon('Fork');\nexport const HomeIcon = createIcon('Home');\nexport const ActivityIcon = createIcon('Activity');\nexport const ArrowRightIcon = createIcon('ArrowRight');\nexport const PlusIcon = createIcon('Plus');\nexport const UsersIcon = createIcon('Users');\nexport const PlayCircleIcon = createIcon('PlayCircle');\nexport const WorkflowIcon = createIcon('Workflow');\nexport const PaletteIcon = createIcon('Palette');\nexport const LightbulbIcon = createIcon('Lightbulb');\nexport const SparklesIcon = createIcon('Sparkles');\nexport const LockIcon = createIcon('Lock');\n\nexport const FileIcon = createIcon('File');\nexport const SearchIcon = createIcon('Search');\nexport const ImageIcon = createIcon('Image');\nexport const SlidersIcon = createIcon('Sliders');\nexport const DownloadIcon = createIcon('Download');\nexport const MicIcon = createIcon('Mic');\nexport const StopIcon = createIcon('Stop');\n"],"mappings":";;;;;;;;;;AAUA,MAAMW,eAAe;AACrB,MAAMC,gBAAkC;AAYxC,SAASM,WAAWC,MAAgB;CAClC,MAAMC,QAAQX,YAAYU;CAC1B,SAASE,KAAK,EAAEP,OAAOH,cAAcI,OAAOC,oBAAoBC,SAAoB;EAClF,MAAM,EAAEK,UAAUf,aAAa;EAC/B,MAAMgB,YAAYpB,WAAWK,gBAAgB;EAC7C,MAAMgB,OAAOF,MAAMG,OAAOV,SAASQ,aAAaX;EAChD,MAAMc,OACJV,uBAAuBW,SAClB;GACCC,YAAY;GACZC,2BAA2B;GAC3BC,6BAA6B;EAC/B,IACC;GAAEF,YAAY;GAAMI,mBAAmB;GAAShB;EAAmB;EAC1E,IAAIZ,SAAS6B,OAAO,OAClB,OACE,oBAAC,YAAD;GACE,MAAMb,MAAMc;GACNpB;GACN,WAAWU;GACX,OAAO,CAAC;IAAEW,OAAOrB;IAAMsB,QAAQtB;GAAK,GAAGG,KAAK;GAC5C,GAAIS;EAAK;EAIf,OAAO,oBAAC,eAAD;GAAe,MAAMN,MAAMiB;GAAgBvB;GAAM,OAAOU;GAAaP;GAAO,GAAIS;EAAK;CAC9F;CACAL,KAAKiB,cAAc,GAAGnB,KAAI;CAC1B,OAAOE;AACT;AAEA,MAAakB,YAAYrB,WAAW,OAAO;AAC3C,MAAasB,kBAAkBtB,WAAW,aAAa;AACvD,MAAauB,mBAAmBvB,WAAW,cAAc;AACzD,MAAawB,gBAAgBxB,WAAW,WAAW;AACnD,MAAayB,YAAYzB,WAAW,OAAO;AAC3C,MAAa0B,WAAW1B,WAAW,MAAM;AACzC,MAAa2B,cAAc3B,WAAW,SAAS;AAC/C,MAAa4B,YAAY5B,WAAW,OAAO;AAC3C,MAAa6B,WAAW7B,WAAW,MAAM;AACzC,MAAa8B,WAAW9B,WAAW,MAAM;AACzC,MAAa+B,WAAW/B,WAAW,MAAM;AACzC,MAAagC,WAAWhC,WAAW,MAAM;AACzC,MAAaiC,YAAYjC,WAAW,OAAO;AAC3C,MAAakC,aAAalC,WAAW,QAAQ;AAC7C,MAAamC,YAAYnC,WAAW,OAAO;AAC3C,MAAaoC,aAAapC,WAAW,QAAQ;AAC7C,MAAaqC,aAAarC,WAAW,QAAQ;AAC7C,MAAasC,WAAWtC,WAAW,MAAM;AACzC,MAAauC,WAAWvC,WAAW,MAAM;AACzC,MAAawC,eAAexC,WAAW,UAAU;AACjD,MAAayC,iBAAiBzC,WAAW,YAAY;AACrD,MAAa0C,WAAW1C,WAAW,MAAM;AACzC,MAAa2C,YAAY3C,WAAW,OAAO;AAC3C,MAAa4C,iBAAiB5C,WAAW,YAAY;AACrD,MAAa6C,eAAe7C,WAAW,UAAU;AACjD,MAAa8C,cAAc9C,WAAW,SAAS;AAC/C,MAAa+C,gBAAgB/C,WAAW,WAAW;AACnD,MAAagD,eAAehD,WAAW,UAAU;AACjD,MAAaiD,WAAWjD,WAAW,MAAM;AAEzC,MAAakD,WAAWlD,WAAW,MAAM;AACzC,MAAamD,aAAanD,WAAW,QAAQ;AAC7C,MAAaoD,YAAYpD,WAAW,OAAO;AAC3C,MAAaqD,cAAcrD,WAAW,SAAS;AAC/C,MAAasD,eAAetD,WAAW,UAAU;AACjD,MAAauD,UAAUvD,WAAW,KAAK;AACvC,MAAawD,WAAWxD,WAAW,MAAM"}
1
+ {"version":3,"file":"icons.mjs","names":["NativeColorToken","MaterialIcons","SymbolView","useContext","Platform","StyleProp","ViewStyle","useUnistyles","IconColorContext","ICON_GLYPHS","IconName","DEFAULT_SIZE","DEFAULT_COLOR","IconProps","size","color","accessibilityLabel","style","createIcon","name","glyph","Icon","theme","inherited","tint","colors","a11y","undefined","accessible","importantForAccessibility","accessibilityElementsHidden","const","accessibilityRole","OS","sf","width","height","material","displayName","CheckIcon","ChevronDownIcon","ChevronRightIcon","ChevronUpIcon","AlertIcon","CopyIcon","MessageIcon","KebabIcon","EditIcon","GearIcon","SendIcon","TaskIcon","TrashIcon","WrenchIcon","CloseIcon","FolderIcon","GlobeIcon","BranchIcon","ForkIcon","HomeIcon","ActivityIcon","ArrowRightIcon","PlusIcon","UsersIcon","PlayCircleIcon","WorkflowIcon","PaletteIcon","LightbulbIcon","SparklesIcon","LockIcon","FileIcon","SearchIcon","ImageIcon","SlidersIcon","DownloadIcon","MicIcon","StopIcon"],"sources":["../../src/icons/icons.tsx"],"sourcesContent":["import type { NativeColorToken } from '@agimon-ai/po-web-components/nativeTheme';\nimport MaterialIcons from '@expo/vector-icons/MaterialIcons';\nimport { SymbolView } from 'expo-symbols';\nimport { useContext } from 'react';\nimport { Platform, type StyleProp, type ViewStyle } from 'react-native';\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport { IconColorContext } from './IconColorContext';\nimport { ICON_GLYPHS, type IconName } from './iconGlyphs';\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_COLOR: NativeColorToken = 'dim';\n\nexport interface IconProps {\n /** Edge length in points. */\n size?: number;\n /** A theme token; defaults to the enclosing Button's label colour, else `dim`. */\n color?: NativeColorToken;\n /** Given one, the icon is announced as an image; without one it is hidden from screen readers. */\n accessibilityLabel?: string;\n style?: StyleProp<ViewStyle>;\n}\n\nfunction createIcon(name: IconName) {\n const glyph = ICON_GLYPHS[name];\n function Icon({ size = DEFAULT_SIZE, color, accessibilityLabel, style }: IconProps) {\n const { theme } = useUnistyles();\n const inherited = useContext(IconColorContext);\n const tint = theme.colors[color ?? inherited ?? DEFAULT_COLOR];\n const a11y =\n accessibilityLabel === undefined\n ? ({\n accessible: false,\n importantForAccessibility: 'no-hide-descendants',\n accessibilityElementsHidden: true,\n } as const)\n : ({ accessible: true, accessibilityRole: 'image', accessibilityLabel } as const);\n if (Platform.OS === 'ios') {\n return (\n <SymbolView\n name={glyph.sf}\n size={size}\n tintColor={tint}\n style={[{ width: size, height: size }, style]}\n {...a11y}\n />\n );\n }\n return <MaterialIcons name={glyph.material} size={size} color={tint} style={style} {...a11y} />;\n }\n Icon.displayName = `${name}Icon`;\n return Icon;\n}\n\nexport const CheckIcon = createIcon('Check');\nexport const ChevronDownIcon = createIcon('ChevronDown');\nexport const ChevronRightIcon = createIcon('ChevronRight');\nexport const ChevronUpIcon = createIcon('ChevronUp');\nexport const AlertIcon = createIcon('Alert');\nexport const CopyIcon = createIcon('Copy');\nexport const MessageIcon = createIcon('Message');\nexport const KebabIcon = createIcon('Kebab');\nexport const EditIcon = createIcon('Edit');\nexport const GearIcon = createIcon('Gear');\nexport const SendIcon = createIcon('Send');\nexport const TaskIcon = createIcon('Task');\nexport const TrashIcon = createIcon('Trash');\nexport const WrenchIcon = createIcon('Wrench');\nexport const CloseIcon = createIcon('Close');\nexport const FolderIcon = createIcon('Folder');\nexport const GlobeIcon = createIcon('Globe');\nexport const BranchIcon = createIcon('Branch');\nexport const ForkIcon = createIcon('Fork');\nexport const HomeIcon = createIcon('Home');\nexport const ActivityIcon = createIcon('Activity');\nexport const ArrowRightIcon = createIcon('ArrowRight');\nexport const PlusIcon = createIcon('Plus');\nexport const UsersIcon = createIcon('Users');\nexport const PlayCircleIcon = createIcon('PlayCircle');\nexport const WorkflowIcon = createIcon('Workflow');\nexport const PaletteIcon = createIcon('Palette');\nexport const LightbulbIcon = createIcon('Lightbulb');\nexport const SparklesIcon = createIcon('Sparkles');\nexport const LockIcon = createIcon('Lock');\n\nexport const FileIcon = createIcon('File');\nexport const SearchIcon = createIcon('Search');\nexport const ImageIcon = createIcon('Image');\nexport const SlidersIcon = createIcon('Sliders');\nexport const DownloadIcon = createIcon('Download');\nexport const MicIcon = createIcon('Mic');\nexport const StopIcon = createIcon('Stop');\n"],"mappings":";;;;;;;;;;AAUA,MAAMW,eAAe;AACrB,MAAMC,gBAAkC;AAYxC,SAASM,WAAWC,MAAgB;CAClC,MAAMC,QAAQX,YAAYU;CAC1B,SAASE,KAAK,EAAEP,OAAOH,cAAcI,OAAOC,oBAAoBC,SAAoB;EAClF,MAAM,EAAEK,UAAUf,aAAa;EAC/B,MAAMgB,YAAYpB,WAAWK,gBAAgB;EAC7C,MAAMgB,OAAOF,MAAMG,OAAOV,SAASQ,aAAaX;EAChD,MAAMc,OACJV,uBAAuBW,SAClB;GACCC,YAAY;GACZC,2BAA2B;GAC3BC,6BAA6B;EAC/B,IACC;GAAEF,YAAY;GAAMI,mBAAmB;GAAShB;EAAmB;EAC1E,IAAIZ,SAAS6B,OAAO,OAClB,OACE,oBAAC,YAAD;GACE,MAAMb,MAAMc;GACNpB;GACN,WAAWU;GACX,OAAO,CAAC;IAAEW,OAAOrB;IAAMsB,QAAQtB;GAAK,GAAGG,KAAK;GAC5C,GAAIS;EAAK;EAIf,OAAO,oBAAC,eAAD;GAAe,MAAMN,MAAMiB;GAAgBvB;GAAM,OAAOU;GAAaP;GAAO,GAAIS;EAAK;CAC9F;CACAL,KAAKiB,cAAc,GAAGnB,KAAI;CAC1B,OAAOE;AACT;AAEA,MAAakB,YAAYrB,WAAW,OAAO;AAC3C,MAAasB,kBAAkBtB,WAAW,aAAa;AACvD,MAAauB,mBAAmBvB,WAAW,cAAc;AACzD,MAAawB,gBAAgBxB,WAAW,WAAW;AACnD,MAAayB,YAAYzB,WAAW,OAAO;AAC3C,MAAa0B,WAAW1B,WAAW,MAAM;AACzC,MAAa2B,cAAc3B,WAAW,SAAS;AAC/C,MAAa4B,YAAY5B,WAAW,OAAO;AAC3C,MAAa6B,WAAW7B,WAAW,MAAM;AACzC,MAAa8B,WAAW9B,WAAW,MAAM;AACzC,MAAa+B,WAAW/B,WAAW,MAAM;AACzC,MAAagC,WAAWhC,WAAW,MAAM;AACzC,MAAaiC,YAAYjC,WAAW,OAAO;AAC3C,MAAakC,aAAalC,WAAW,QAAQ;AAC7C,MAAamC,YAAYnC,WAAW,OAAO;AAC3C,MAAaoC,aAAapC,WAAW,QAAQ;AAC7C,MAAaqC,YAAYrC,WAAW,OAAO;AAC3C,MAAasC,aAAatC,WAAW,QAAQ;AAC7C,MAAauC,WAAWvC,WAAW,MAAM;AACzC,MAAawC,WAAWxC,WAAW,MAAM;AACzC,MAAayC,eAAezC,WAAW,UAAU;AACjD,MAAa0C,iBAAiB1C,WAAW,YAAY;AACrD,MAAa2C,WAAW3C,WAAW,MAAM;AACzC,MAAa4C,YAAY5C,WAAW,OAAO;AAC3C,MAAa6C,iBAAiB7C,WAAW,YAAY;AACrD,MAAa8C,eAAe9C,WAAW,UAAU;AACjD,MAAa+C,cAAc/C,WAAW,SAAS;AAC/C,MAAagD,gBAAgBhD,WAAW,WAAW;AACnD,MAAaiD,eAAejD,WAAW,UAAU;AACjD,MAAakD,WAAWlD,WAAW,MAAM;AAEzC,MAAamD,WAAWnD,WAAW,MAAM;AACzC,MAAaoD,aAAapD,WAAW,QAAQ;AAC7C,MAAaqD,YAAYrD,WAAW,OAAO;AAC3C,MAAasD,cAActD,WAAW,SAAS;AAC/C,MAAauD,eAAevD,WAAW,UAAU;AACjD,MAAawD,UAAUxD,WAAW,KAAK;AACvC,MAAayD,WAAWzD,WAAW,MAAM"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AgentAvatar, AgentState, agentInitials } from "./components/AgentAvatar.mjs";
2
+ import { AnnotationMark, AnnotationSurface, AnnotationSurfaceProps } from "./components/AnnotationSurface.mjs";
2
3
  import { Badge, BadgeProps, BadgeSize, BadgeTone } from "./components/Badge.mjs";
3
4
  import { Button, ButtonProps, ButtonSize, ButtonVariant } from "./components/Button.mjs";
4
5
  import { CodeBlock, CodeBlockProps } from "./components/CodeBlock.mjs";
@@ -26,10 +27,10 @@ import { TabBadge, TabBadgeProps, Tabs, TabsContent, TabsContentProps, TabsList,
26
27
  import { SyntaxLine, SyntaxLineProps, useSyntaxLines } from "./components/SyntaxLine.mjs";
27
28
  import { Textarea, TextareaProps } from "./components/Textarea.mjs";
28
29
  import { ToolPathLink, ToolPathLinkProps } from "./components/ToolPathLink.mjs";
29
- import { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, HomeIcon, IconProps, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
30
+ import { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HomeIcon, IconProps, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
30
31
  import { IconName } from "./icons/iconGlyphs.mjs";
31
32
  import { fontOf } from "./lib/fonts.mjs";
32
33
  import { IconColorContext } from "./icons/IconColorContext.mjs";
33
34
  import { impactLight, selectionTick } from "./lib/haptics.mjs";
34
35
  import { AnsiSpan, PresentedLine, ReviewComment, ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
35
- export { ActivityIcon, AgentAvatar, type AgentState, AlertIcon, type AnsiSpan, ArrowRightIcon, Badge, type BadgeProps, type BadgeSize, type BadgeTone, BranchIcon, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CodeBlock, type CodeBlockProps, CopyButton, type CopyButtonProps, CopyIcon, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, type DialogFooterProps, type DialogFooterVariant, DialogHeader, type DialogHeaderProps, type DialogPartProps, type DialogProps, DialogTitle, DialogTrigger, type DialogWidth, Dot, type DotProps, type DotSize, type DotTone, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuItemVariant, DropdownMenuLabel, type DropdownMenuPartProps, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, EditIcon, EmptyState, type EmptyStateProps, type FieldSize, type FieldVariant, FileIcon, type FileLinkHandler, FolderIcon, ForkIcon, GearIcon, HashlineLines, type HashlineLinesProps, HomeIcon, IconColorContext, type IconName, type IconProps, ImageIcon, Input, type InputProps, KebabIcon, Label, type LabelProps, LightbulbIcon, List, type ListProps, ListRow, type ListRowProps, LockIcon, Markdown, type MarkdownImageLoader, type MarkdownProps, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, type MessageItemGroupProps, MessageItemHeader, type MessageItemHeaderProps, type MessageItemPartProps, type MessageItemProps, type MessageItemState, MessageItemStatus, type MessageItemStatusProps, MicIcon, PaletteIcon, Panel, PanelBody, PanelHeader, type PanelPartProps, PlayCircleIcon, PlusIcon, PoNativeProvider, type PoNativeProviderProps, type PresentedLine, type ReviewComment, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, SearchIcon, SectionLabel, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, SendIcon, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, type SheetHeaderProps, SheetList, type SheetListProps, type SheetPartProps, type SheetProps, SheetTitle, SheetTrigger, ShowMore, type ShowMoreProps, SlidersIcon, SparklesIcon, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, type StatusTone, StopIcon, SyntaxLine, type SyntaxLineProps, TabBadge, type TabBadgeProps, Tabs, TabsContent, type TabsContentProps, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsTriggerProps, TaskIcon, Textarea, type TextareaProps, ToolPathLink, type ToolPathLinkProps, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, toolTone, useMessageItem, useSyntaxLines };
36
+ export { ActivityIcon, AgentAvatar, type AgentState, AlertIcon, type AnnotationMark, AnnotationSurface, type AnnotationSurfaceProps, type AnsiSpan, ArrowRightIcon, Badge, type BadgeProps, type BadgeSize, type BadgeTone, BranchIcon, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CodeBlock, type CodeBlockProps, CopyButton, type CopyButtonProps, CopyIcon, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, type DialogFooterProps, type DialogFooterVariant, DialogHeader, type DialogHeaderProps, type DialogPartProps, type DialogProps, DialogTitle, DialogTrigger, type DialogWidth, Dot, type DotProps, type DotSize, type DotTone, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuItemVariant, DropdownMenuLabel, type DropdownMenuPartProps, type DropdownMenuProps, DropdownMenuRadioGroup, type DropdownMenuRadioGroupProps, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, EditIcon, EmptyState, type EmptyStateProps, type FieldSize, type FieldVariant, FileIcon, type FileLinkHandler, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HashlineLines, type HashlineLinesProps, HomeIcon, IconColorContext, type IconName, type IconProps, ImageIcon, Input, type InputProps, KebabIcon, Label, type LabelProps, LightbulbIcon, List, type ListProps, ListRow, type ListRowProps, LockIcon, Markdown, type MarkdownImageLoader, type MarkdownProps, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, type MessageItemGroupProps, MessageItemHeader, type MessageItemHeaderProps, type MessageItemPartProps, type MessageItemProps, type MessageItemState, MessageItemStatus, type MessageItemStatusProps, MicIcon, PaletteIcon, Panel, PanelBody, PanelHeader, type PanelPartProps, PlayCircleIcon, PlusIcon, PoNativeProvider, type PoNativeProviderProps, type PresentedLine, type ReviewComment, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, SearchIcon, SectionLabel, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, SendIcon, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, type SheetHeaderProps, SheetList, type SheetListProps, type SheetPartProps, type SheetProps, SheetTitle, SheetTrigger, ShowMore, type ShowMoreProps, SlidersIcon, SparklesIcon, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, type StatusTone, StopIcon, SyntaxLine, type SyntaxLineProps, TabBadge, type TabBadgeProps, Tabs, TabsContent, type TabsContentProps, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsTriggerProps, TaskIcon, Textarea, type TextareaProps, ToolPathLink, type ToolPathLinkProps, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, toolTone, useMessageItem, useSyntaxLines };
package/dist/index.mjs CHANGED
@@ -1,12 +1,13 @@
1
1
  import { fontOf } from "./lib/fonts.mjs";
2
2
  import { Dot } from "./components/Dot.mjs";
3
3
  import { AgentAvatar, agentInitials } from "./components/AgentAvatar.mjs";
4
+ import { impactLight, selectionTick } from "./lib/haptics.mjs";
5
+ import { AnnotationSurface } from "./components/AnnotationSurface.mjs";
4
6
  import { Badge } from "./components/Badge.mjs";
5
7
  import { IconColorContext } from "./icons/IconColorContext.mjs";
6
- import { impactLight, selectionTick } from "./lib/haptics.mjs";
7
8
  import { Spinner } from "./components/Spinner.mjs";
8
9
  import { Button } from "./components/Button.mjs";
9
- import { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, HomeIcon, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
10
+ import { ActivityIcon, AlertIcon, ArrowRightIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HomeIcon, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
10
11
  import { CopyButton } from "./components/CopyButton.mjs";
11
12
  import { ShowMore } from "./components/ShowMore.mjs";
12
13
  import { CodeBlock } from "./components/CodeBlock.mjs";
@@ -32,4 +33,4 @@ import { Textarea } from "./components/Textarea.mjs";
32
33
  import { ToolPathLink } from "./components/ToolPathLink.mjs";
33
34
  import { ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
34
35
 
35
- export { ActivityIcon, AgentAvatar, AlertIcon, ArrowRightIcon, Badge, BranchIcon, Button, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CodeBlock, CopyButton, CopyIcon, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Dot, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, EditIcon, EmptyState, FileIcon, FolderIcon, ForkIcon, GearIcon, HashlineLines, HomeIcon, IconColorContext, ImageIcon, Input, KebabIcon, Label, LightbulbIcon, List, ListRow, LockIcon, Markdown, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, MessageItemHeader, MessageItemStatus, MicIcon, PaletteIcon, Panel, PanelBody, PanelHeader, PlayCircleIcon, PlusIcon, PoNativeProvider, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, SearchIcon, SectionLabel, SegmentedControl, SendIcon, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetList, SheetTitle, SheetTrigger, ShowMore, SlidersIcon, SparklesIcon, Spinner, StatusBadge, StopIcon, SyntaxLine, TabBadge, Tabs, TabsContent, TabsList, TabsTrigger, TaskIcon, Textarea, ToolPathLink, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, toolTone, useMessageItem, useSyntaxLines };
36
+ export { ActivityIcon, AgentAvatar, AlertIcon, AnnotationSurface, ArrowRightIcon, Badge, BranchIcon, Button, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CodeBlock, CopyButton, CopyIcon, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Dot, DownloadIcon, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger, EditIcon, EmptyState, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HashlineLines, HomeIcon, IconColorContext, ImageIcon, Input, KebabIcon, Label, LightbulbIcon, List, ListRow, LockIcon, Markdown, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, MessageItemHeader, MessageItemStatus, MicIcon, PaletteIcon, Panel, PanelBody, PanelHeader, PlayCircleIcon, PlusIcon, PoNativeProvider, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, SearchIcon, SectionLabel, SegmentedControl, SendIcon, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetList, SheetTitle, SheetTrigger, ShowMore, SlidersIcon, SparklesIcon, Spinner, StatusBadge, StopIcon, SyntaxLine, TabBadge, Tabs, TabsContent, TabsList, TabsTrigger, TaskIcon, Textarea, ToolPathLink, TrashIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, toolTone, useMessageItem, useSyntaxLines };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-native-components",
3
- "version": "0.0.0-alpha.41",
3
+ "version": "0.0.0-alpha.43",
4
4
  "description": "Shared React Native components for Po and its native plugins: the web component library's look and API on native parts, tuned to the Po palette.",
5
5
  "keywords": [
6
6
  "ai",
@@ -45,11 +45,11 @@
45
45
  "access": "public"
46
46
  },
47
47
  "dependencies": {
48
- "@agimon-ai/po-web-components": "0.0.0-alpha.41"
48
+ "@agimon-ai/po-web-components": "0.0.0-alpha.43"
49
49
  },
50
50
  "devDependencies": {
51
- "@agimon-ai/po-build": "0.0.0-alpha.41",
52
- "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.41",
51
+ "@agimon-ai/po-build": "0.0.0-alpha.43",
52
+ "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.43",
53
53
  "@babel/core": "7.29.7",
54
54
  "@expo/vector-icons": "15.1.1",
55
55
  "@fontsource-variable/ibm-plex-sans": "5.3.0",
@@ -59,6 +59,7 @@
59
59
  "@shopify/flash-list": "2.3.3",
60
60
  "@types/node": "26.6.5",
61
61
  "@types/react": "~19.3.0",
62
+ "babel-preset-expo": "~57.0.0",
62
63
  "expo": "57.0.27",
63
64
  "expo-clipboard": "~57.0.2",
64
65
  "expo-font": "~57.0.4",