@agimon-ai/po-native-components 0.0.0-alpha.77 → 0.0.0-alpha.79

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.
@@ -1,12 +1,12 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
2
  import { impactLight } from "../lib/haptics.mjs";
3
3
  import { wrapText } from "../lib/wrapText.mjs";
4
- import { IconColorContext } from "../icons/IconColorContext.mjs";
5
4
  import { Spinner } from "./Spinner.mjs";
6
5
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
7
6
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
8
7
  import { jsx, jsxs } from "react/jsx-runtime";
9
8
  import { Pressable } from "react-native-unistyles/components/native/Pressable";
9
+ import { IconColorContext } from "@agimon-ai/po-native-components/shell";
10
10
 
11
11
  //#region src/components/Button.tsx
12
12
  /** Apple's and Google's minimum tap target; a smaller visual box makes up the rest with hitSlop. */
@@ -1 +1 @@
1
- {"version":3,"file":"Button.mjs","names":["NativeColorToken","withAlpha","ReactNode","PressableProps","StyleProp","ViewStyle","StyleSheet","useUnistyles","IconColorContext","fontOf","impactLight","wrapText","Spinner","ButtonVariant","ButtonSize","MIN_TAP_TARGET","DISABLED_OPACITY","PRESSED_FILL_OPACITY","RIPPLE_ALPHA_PERCENT","PRESSED_EDGE_ALPHA_PERCENT","SIZE_HEIGHT","Readonly","Record","xs","sm","md","lg","icon","card","INK","rest","pressed","primary","secondary","outline","ghost","subtle","danger","success","link","HAPTIC_VARIANTS","ReadonlySet","Set","ButtonProps","Omit","variant","size","loading","loadingLabel","children","style","Button","disabled","onPress","hitSlop","accessibilityState","props","theme","_styles","styles","useVariants","inactive","slop","Math","max","ink","busy","undefined","text","color","colors","borderless","event","has","button","borderColor","green","token","label","labelPressed","create","flexDirection","alignItems","justifyContent","gap","spacing","borderRadius","borderWidth","overflow","variants","backgroundColor","selected","border","panel","red","height","paddingHorizontal","DEFAULT","width","padding","alignSelf","minHeight","paddingVertical","uni__dependencies","opacity","deep","fontFamily","sans","fontWeight","medium","semibold","fontSize","lineHeight","base","textDecorationLine"],"sources":["../../src/components/Button.tsx"],"sourcesContent":["import { type NativeColorToken, withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport type { ReactNode } from 'react';\nimport { Pressable, type PressableProps, type StyleProp, type ViewStyle } from 'react-native';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { IconColorContext } from '../icons/IconColorContext';\nimport { fontOf } from '../lib/fonts';\nimport { impactLight } from '../lib/haptics';\nimport { wrapText } from '../lib/wrapText';\nimport { Spinner } from './Spinner';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'subtle'\n | 'danger'\n | 'danger-outline'\n | 'success'\n | 'link';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon' | 'icon-md' | 'card';\n\n/** Apple's and Google's minimum tap target; a smaller visual box makes up the rest with hitSlop. */\nconst MIN_TAP_TARGET = 44;\nconst DISABLED_OPACITY = 0.4;\nconst PRESSED_FILL_OPACITY = 0.85;\nconst RIPPLE_ALPHA_PERCENT = 20;\n/** `hover:border-po-green/50`. */\nconst PRESSED_EDGE_ALPHA_PERCENT = 50;\n\n/** The visual height of each size, from which hitSlop pads the tap target to 44pt. */\nconst SIZE_HEIGHT: Readonly<Record<ButtonSize, number>> = {\n xs: 24,\n sm: 28,\n md: 32,\n lg: 36,\n icon: 24,\n 'icon-md': 32,\n card: MIN_TAP_TARGET,\n};\n\n/** The label ink of each variant, and the ink it lifts to while pressed (the web hover). */\nconst INK: Readonly<Record<ButtonVariant, { rest: NativeColorToken; pressed: NativeColorToken }>> = {\n primary: { rest: 'on-selected', pressed: 'on-selected' },\n secondary: { rest: 'magenta', pressed: 'magenta' },\n outline: { rest: 'dim', pressed: 'hi' },\n ghost: { rest: 'dim', pressed: 'hi' },\n subtle: { rest: 'dim', pressed: 'hi' },\n danger: { rest: 'rail', pressed: 'rail' },\n 'danger-outline': { rest: 'red', pressed: 'red' },\n success: { rest: 'rail', pressed: 'rail' },\n link: { rest: 'blue', pressed: 'blue' },\n};\n\n/** Presses that commit something get a light impact; the rest stay quiet. */\nconst HAPTIC_VARIANTS: ReadonlySet<ButtonVariant> = new Set(['primary', 'danger', 'success']);\n\nexport interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Work is in flight: the button shows a spinner and stops accepting presses. */\n loading?: boolean;\n /** What the spinner announces while loading; omit it and the wait is silent. */\n loadingLabel?: string;\n /** A bare string is drawn as the label; elements (an icon, a card's lines) render as given. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** The one button: every variant is a theme token, a press dims or lifts it, and committing presses buzz once. */\nexport function Button({\n variant = 'outline',\n size = 'md',\n loading = false,\n loadingLabel,\n disabled,\n onPress,\n children,\n style,\n hitSlop,\n accessibilityState,\n ...props\n}: ButtonProps) {\n const { theme } = useUnistyles();\n styles.useVariants({ variant, size });\n const inactive = (disabled ?? false) || loading;\n const slop = Math.max(0, (MIN_TAP_TARGET - SIZE_HEIGHT[size]) / 2);\n const ink = INK[variant];\n return (\n <Pressable\n accessibilityRole={variant === 'link' ? 'link' : 'button'}\n accessibilityState={{ ...accessibilityState, disabled: inactive, busy: loading }}\n accessibilityValue={loading && loadingLabel !== undefined ? { text: loadingLabel } : undefined}\n disabled={inactive}\n hitSlop={hitSlop ?? slop}\n android_ripple={{ color: withAlpha(theme.colors[ink.pressed], RIPPLE_ALPHA_PERCENT), borderless: false }}\n onPress={(event) => {\n if (HAPTIC_VARIANTS.has(variant)) impactLight();\n onPress?.(event);\n }}\n style={({ pressed }) => [\n styles.button,\n pressed && styles.pressed,\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n pressed && variant === 'outline' && { borderColor: withAlpha(theme.colors.green, PRESSED_EDGE_ALPHA_PERCENT) },\n inactive && styles.disabled,\n style,\n ]}\n {...props}\n >\n {({ pressed }) => {\n const token = pressed ? ink.pressed : ink.rest;\n return (\n <IconColorContext.Provider value={token}>\n {loading ? <Spinner color={token} /> : null}\n {wrapText(children, [styles.label, pressed && styles.labelPressed, { color: theme.colors[token] }])}\n </IconColorContext.Provider>\n );\n }}\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1.5),\n borderRadius: theme.borderRadius.md,\n borderWidth: 1,\n borderColor: 'transparent',\n overflow: 'hidden',\n variants: {\n variant: {\n primary: { backgroundColor: theme.colors.selected },\n secondary: { borderColor: theme.colors['edge-magenta'], backgroundColor: theme.colors['tint-magenta'] },\n outline: { borderColor: theme.colors.border },\n ghost: {},\n subtle: { backgroundColor: theme.colors.panel },\n danger: { backgroundColor: theme.colors.red },\n 'danger-outline': { borderColor: theme.colors['edge-red'], backgroundColor: theme.colors['tint-red'] },\n success: { backgroundColor: theme.colors.green },\n link: {},\n },\n size: {\n xs: { height: SIZE_HEIGHT.xs, paddingHorizontal: theme.spacing(1.5), borderRadius: theme.borderRadius.DEFAULT },\n sm: { height: SIZE_HEIGHT.sm, paddingHorizontal: theme.spacing(2.5) },\n md: { height: SIZE_HEIGHT.md, paddingHorizontal: theme.spacing(3) },\n lg: { height: SIZE_HEIGHT.lg, paddingHorizontal: theme.spacing(3.5) },\n icon: {\n width: SIZE_HEIGHT.icon,\n height: SIZE_HEIGHT.icon,\n padding: 0,\n borderRadius: theme.borderRadius.DEFAULT,\n },\n 'icon-md': { width: SIZE_HEIGHT['icon-md'], height: SIZE_HEIGHT['icon-md'], padding: 0 },\n card: {\n alignSelf: 'stretch',\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'flex-start',\n gap: theme.spacing(1),\n minHeight: SIZE_HEIGHT.card,\n paddingHorizontal: 11,\n paddingVertical: theme.spacing(2.5),\n },\n },\n },\n },\n pressed: {\n variants: {\n variant: {\n primary: { opacity: PRESSED_FILL_OPACITY },\n secondary: { opacity: PRESSED_FILL_OPACITY },\n outline: {},\n ghost: { backgroundColor: theme.colors.panel },\n subtle: { backgroundColor: theme.colors.deep },\n danger: { opacity: PRESSED_FILL_OPACITY },\n 'danger-outline': { opacity: PRESSED_FILL_OPACITY },\n success: { opacity: PRESSED_FILL_OPACITY },\n link: {},\n },\n },\n },\n disabled: { opacity: DISABLED_OPACITY },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontWeight: theme.fontWeight.medium,\n variants: {\n variant: {\n primary: { fontWeight: theme.fontWeight.semibold },\n secondary: { fontWeight: theme.fontWeight.semibold },\n outline: {},\n ghost: {},\n subtle: {},\n danger: { fontWeight: theme.fontWeight.semibold },\n 'danger-outline': { fontWeight: theme.fontWeight.semibold },\n success: { fontWeight: theme.fontWeight.semibold },\n link: {},\n },\n size: {\n xs: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n sm: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n md: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n lg: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n icon: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n 'icon-md': { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n card: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n },\n },\n },\n labelPressed: {\n variants: {\n variant: {\n primary: {},\n secondary: {},\n outline: {},\n ghost: {},\n subtle: {},\n danger: {},\n 'danger-outline': {},\n success: {},\n link: { textDecorationLine: 'underline' },\n },\n },\n },\n}));\n"],"mappings":"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"}
1
+ {"version":3,"file":"Button.mjs","names":["IconColorContext","NativeColorToken","withAlpha","ReactNode","PressableProps","StyleProp","ViewStyle","StyleSheet","useUnistyles","fontOf","impactLight","wrapText","Spinner","ButtonVariant","ButtonSize","MIN_TAP_TARGET","DISABLED_OPACITY","PRESSED_FILL_OPACITY","RIPPLE_ALPHA_PERCENT","PRESSED_EDGE_ALPHA_PERCENT","SIZE_HEIGHT","Readonly","Record","xs","sm","md","lg","icon","card","INK","rest","pressed","primary","secondary","outline","ghost","subtle","danger","success","link","HAPTIC_VARIANTS","ReadonlySet","Set","ButtonProps","Omit","variant","size","loading","loadingLabel","children","style","Button","disabled","onPress","hitSlop","accessibilityState","props","theme","_styles","styles","useVariants","inactive","slop","Math","max","ink","busy","undefined","text","color","colors","borderless","event","has","button","borderColor","green","token","label","labelPressed","create","flexDirection","alignItems","justifyContent","gap","spacing","borderRadius","borderWidth","overflow","variants","backgroundColor","selected","border","panel","red","height","paddingHorizontal","DEFAULT","width","padding","alignSelf","minHeight","paddingVertical","uni__dependencies","opacity","deep","fontFamily","sans","fontWeight","medium","semibold","fontSize","lineHeight","base","textDecorationLine"],"sources":["../../src/components/Button.tsx"],"sourcesContent":["import { IconColorContext } from '@agimon-ai/po-native-components/shell';\nimport { type NativeColorToken, withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport type { ReactNode } from 'react';\nimport { Pressable, type PressableProps, type StyleProp, type ViewStyle } from 'react-native';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\nimport { impactLight } from '../lib/haptics';\nimport { wrapText } from '../lib/wrapText';\nimport { Spinner } from './Spinner';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'subtle'\n | 'danger'\n | 'danger-outline'\n | 'success'\n | 'link';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon' | 'icon-md' | 'card';\n\n/** Apple's and Google's minimum tap target; a smaller visual box makes up the rest with hitSlop. */\nconst MIN_TAP_TARGET = 44;\nconst DISABLED_OPACITY = 0.4;\nconst PRESSED_FILL_OPACITY = 0.85;\nconst RIPPLE_ALPHA_PERCENT = 20;\n/** `hover:border-po-green/50`. */\nconst PRESSED_EDGE_ALPHA_PERCENT = 50;\n\n/** The visual height of each size, from which hitSlop pads the tap target to 44pt. */\nconst SIZE_HEIGHT: Readonly<Record<ButtonSize, number>> = {\n xs: 24,\n sm: 28,\n md: 32,\n lg: 36,\n icon: 24,\n 'icon-md': 32,\n card: MIN_TAP_TARGET,\n};\n\n/** The label ink of each variant, and the ink it lifts to while pressed (the web hover). */\nconst INK: Readonly<Record<ButtonVariant, { rest: NativeColorToken; pressed: NativeColorToken }>> = {\n primary: { rest: 'on-selected', pressed: 'on-selected' },\n secondary: { rest: 'magenta', pressed: 'magenta' },\n outline: { rest: 'dim', pressed: 'hi' },\n ghost: { rest: 'dim', pressed: 'hi' },\n subtle: { rest: 'dim', pressed: 'hi' },\n danger: { rest: 'rail', pressed: 'rail' },\n 'danger-outline': { rest: 'red', pressed: 'red' },\n success: { rest: 'rail', pressed: 'rail' },\n link: { rest: 'blue', pressed: 'blue' },\n};\n\n/** Presses that commit something get a light impact; the rest stay quiet. */\nconst HAPTIC_VARIANTS: ReadonlySet<ButtonVariant> = new Set(['primary', 'danger', 'success']);\n\nexport interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Work is in flight: the button shows a spinner and stops accepting presses. */\n loading?: boolean;\n /** What the spinner announces while loading; omit it and the wait is silent. */\n loadingLabel?: string;\n /** A bare string is drawn as the label; elements (an icon, a card's lines) render as given. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** The one button: every variant is a theme token, a press dims or lifts it, and committing presses buzz once. */\nexport function Button({\n variant = 'outline',\n size = 'md',\n loading = false,\n loadingLabel,\n disabled,\n onPress,\n children,\n style,\n hitSlop,\n accessibilityState,\n ...props\n}: ButtonProps) {\n const { theme } = useUnistyles();\n styles.useVariants({ variant, size });\n const inactive = (disabled ?? false) || loading;\n const slop = Math.max(0, (MIN_TAP_TARGET - SIZE_HEIGHT[size]) / 2);\n const ink = INK[variant];\n return (\n <Pressable\n accessibilityRole={variant === 'link' ? 'link' : 'button'}\n accessibilityState={{ ...accessibilityState, disabled: inactive, busy: loading }}\n accessibilityValue={loading && loadingLabel !== undefined ? { text: loadingLabel } : undefined}\n disabled={inactive}\n hitSlop={hitSlop ?? slop}\n android_ripple={{ color: withAlpha(theme.colors[ink.pressed], RIPPLE_ALPHA_PERCENT), borderless: false }}\n onPress={(event) => {\n if (HAPTIC_VARIANTS.has(variant)) impactLight();\n onPress?.(event);\n }}\n style={({ pressed }) => [\n styles.button,\n pressed && styles.pressed,\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n pressed && variant === 'outline' && { borderColor: withAlpha(theme.colors.green, PRESSED_EDGE_ALPHA_PERCENT) },\n inactive && styles.disabled,\n style,\n ]}\n {...props}\n >\n {({ pressed }) => {\n const token = pressed ? ink.pressed : ink.rest;\n return (\n <IconColorContext.Provider value={token}>\n {loading ? <Spinner color={token} /> : null}\n {wrapText(children, [styles.label, pressed && styles.labelPressed, { color: theme.colors[token] }])}\n </IconColorContext.Provider>\n );\n }}\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1.5),\n borderRadius: theme.borderRadius.md,\n borderWidth: 1,\n borderColor: 'transparent',\n overflow: 'hidden',\n variants: {\n variant: {\n primary: { backgroundColor: theme.colors.selected },\n secondary: { borderColor: theme.colors['edge-magenta'], backgroundColor: theme.colors['tint-magenta'] },\n outline: { borderColor: theme.colors.border },\n ghost: {},\n subtle: { backgroundColor: theme.colors.panel },\n danger: { backgroundColor: theme.colors.red },\n 'danger-outline': { borderColor: theme.colors['edge-red'], backgroundColor: theme.colors['tint-red'] },\n success: { backgroundColor: theme.colors.green },\n link: {},\n },\n size: {\n xs: { height: SIZE_HEIGHT.xs, paddingHorizontal: theme.spacing(1.5), borderRadius: theme.borderRadius.DEFAULT },\n sm: { height: SIZE_HEIGHT.sm, paddingHorizontal: theme.spacing(2.5) },\n md: { height: SIZE_HEIGHT.md, paddingHorizontal: theme.spacing(3) },\n lg: { height: SIZE_HEIGHT.lg, paddingHorizontal: theme.spacing(3.5) },\n icon: {\n width: SIZE_HEIGHT.icon,\n height: SIZE_HEIGHT.icon,\n padding: 0,\n borderRadius: theme.borderRadius.DEFAULT,\n },\n 'icon-md': { width: SIZE_HEIGHT['icon-md'], height: SIZE_HEIGHT['icon-md'], padding: 0 },\n card: {\n alignSelf: 'stretch',\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'flex-start',\n gap: theme.spacing(1),\n minHeight: SIZE_HEIGHT.card,\n paddingHorizontal: 11,\n paddingVertical: theme.spacing(2.5),\n },\n },\n },\n },\n pressed: {\n variants: {\n variant: {\n primary: { opacity: PRESSED_FILL_OPACITY },\n secondary: { opacity: PRESSED_FILL_OPACITY },\n outline: {},\n ghost: { backgroundColor: theme.colors.panel },\n subtle: { backgroundColor: theme.colors.deep },\n danger: { opacity: PRESSED_FILL_OPACITY },\n 'danger-outline': { opacity: PRESSED_FILL_OPACITY },\n success: { opacity: PRESSED_FILL_OPACITY },\n link: {},\n },\n },\n },\n disabled: { opacity: DISABLED_OPACITY },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontWeight: theme.fontWeight.medium,\n variants: {\n variant: {\n primary: { fontWeight: theme.fontWeight.semibold },\n secondary: { fontWeight: theme.fontWeight.semibold },\n outline: {},\n ghost: {},\n subtle: {},\n danger: { fontWeight: theme.fontWeight.semibold },\n 'danger-outline': { fontWeight: theme.fontWeight.semibold },\n success: { fontWeight: theme.fontWeight.semibold },\n link: {},\n },\n size: {\n xs: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n sm: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n md: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n lg: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n icon: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n 'icon-md': { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n card: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n },\n },\n },\n labelPressed: {\n variants: {\n variant: {\n primary: {},\n secondary: {},\n outline: {},\n ghost: {},\n subtle: {},\n danger: {},\n 'danger-outline': {},\n success: {},\n link: { textDecorationLine: 'underline' },\n },\n },\n },\n}));\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
- import { useInsideSheet } from "../lib/insideSheet.mjs";
3
2
  import { StyleSheet, useUnistyles, withUnistyles } from "react-native-unistyles";
4
3
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
5
4
  import { useState } from "react";
6
5
  import { jsx } from "react/jsx-runtime";
6
+ import { useInsideSheet } from "@agimon-ai/po-native-components/shell";
7
7
  import { BottomSheetTextInput } from "@gorhom/bottom-sheet";
8
8
  import { TextInput } from "react-native-unistyles/components/native/TextInput";
9
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"Input.mjs","names":["withAlpha","BottomSheetTextInput","useState","TextInputProps","StyleSheet","useUnistyles","withUnistyles","fontOf","useInsideSheet","FieldVariant","FieldSize","FOCUS_EDGE_ALPHA_PERCENT","DISABLED_OPACITY","ThemedSheetTextInput","InputProps","Omit","variant","size","invalid","disabled","Input","style","onFocus","onBlur","accessibilityState","props","theme","rt","focused","setFocused","Field","TextInput","_styles","styles","useVariants","undefined","themeName","colors","faint","green","event","field","borderColor","create","minWidth","minHeight","color","hi","fontFamily","sans","variants","default","borderRadius","DEFAULT","borderWidth","border","backgroundColor","deep","bare","padding","xs","paddingHorizontal","spacing","paddingVertical","fontSize","sm","md","base","lg","compoundVariants","uni__dependencies","red","opacity"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport { BottomSheetTextInput } from '@gorhom/bottom-sheet';\nimport { useState } from 'react';\nimport { TextInput, type TextInputProps } from 'react-native';\nimport { StyleSheet, useUnistyles, withUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\nimport { useInsideSheet } from '../lib/insideSheet';\n\nexport type FieldVariant = 'default' | 'bare';\nexport type FieldSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/** `focus:border-po-green/60`. */\nconst FOCUS_EDGE_ALPHA_PERCENT = 60;\nconst DISABLED_OPACITY = 0.5;\n\nconst ThemedSheetTextInput = withUnistyles(BottomSheetTextInput);\nexport interface InputProps extends Omit<TextInputProps, 'editable'> {\n variant?: FieldVariant;\n /** The same rungs Button names, so a field and the button beside it line up. */\n size?: FieldSize;\n /** The value is wrong: red edge and red text, as `aria-invalid` on the web. */\n invalid?: boolean;\n disabled?: boolean;\n}\n\n/**\n * The one text field: deep well, quiet border, jade edge and cursor on focus,\n * red edge when invalid. Inside a Sheet it becomes the sheet's own input.\n */\nexport function Input({\n variant = 'default',\n size = 'md',\n invalid = false,\n disabled = false,\n style,\n onFocus,\n onBlur,\n accessibilityState,\n ...props\n}: InputProps) {\n const { theme, rt } = useUnistyles();\n const [focused, setFocused] = useState(false);\n // Inside a Sheet the field must be the sheet's own input, so the sheet rises with the keyboard.\n const Field = useInsideSheet() ? ThemedSheetTextInput : TextInput;\n // Unistyles reserves a variant named `default` as the fallback for an unset variant.\n styles.useVariants({ variant: variant === 'bare' ? 'bare' : undefined, size });\n return (\n <Field\n autoCorrect={false}\n // iOS draws the keyboard light by default, a bright slab under a dark screen.\n keyboardAppearance={rt.themeName === 'dark' ? 'dark' : 'light'}\n spellCheck={false}\n placeholderTextColor={theme.colors.faint}\n selectionColor={theme.colors.green}\n cursorColor={theme.colors.green}\n editable={!disabled}\n accessibilityState={{ ...accessibilityState, disabled }}\n onFocus={(event) => {\n setFocused(true);\n onFocus?.(event);\n }}\n onBlur={(event) => {\n setFocused(false);\n onBlur?.(event);\n }}\n style={[\n styles.field,\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n focused && variant === 'default' && { borderColor: withAlpha(theme.colors.green, FOCUS_EDGE_ALPHA_PERCENT) },\n invalid && styles.invalid,\n disabled && styles.disabled,\n style,\n ]}\n {...props}\n />\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n field: {\n minWidth: 0,\n minHeight: 44,\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n variants: {\n variant: {\n default: {\n borderRadius: theme.borderRadius.DEFAULT,\n borderWidth: 1,\n borderColor: theme.colors.border,\n backgroundColor: theme.colors.deep,\n },\n /** No well: a composer or a search that draws its own surface keeps the type and drops the box. */\n bare: { borderWidth: 0, backgroundColor: 'transparent', padding: 0 },\n },\n size: {\n xs: {\n paddingHorizontal: theme.spacing(1.5),\n paddingVertical: theme.spacing(0.5),\n fontSize: theme.fontSize.sm,\n },\n sm: {\n paddingHorizontal: theme.spacing(2),\n paddingVertical: theme.spacing(1),\n fontSize: theme.fontSize.sm,\n },\n md: {\n paddingHorizontal: theme.spacing(2.5),\n paddingVertical: theme.spacing(1.5),\n fontSize: theme.fontSize.base,\n },\n lg: {\n paddingHorizontal: theme.spacing(3),\n paddingVertical: theme.spacing(1.5),\n fontSize: theme.fontSize.base,\n },\n },\n },\n compoundVariants: [{ variant: 'bare', styles: { padding: 0, paddingHorizontal: 0, paddingVertical: 0 } }],\n },\n invalid: { borderColor: theme.colors['edge-red'], color: theme.colors.red },\n disabled: { opacity: DISABLED_OPACITY },\n}));\n"],"mappings":";;;;;;;;;;;AAaA,MAAMW,2BAA2B;AACjC,MAAMC,mBAAmB;AAEzB,MAAMC,uBAAuBP,cAAcL,oBAAoB;;;;;AAc/D,SAAgBmB,MAAM,EACpBJ,UAAU,WACVC,OAAO,MACPC,UAAU,OACVC,WAAW,OACXE,OACAC,SACAC,QACAC,oBACA,GAAGC,SACU;CACb,MAAM,EAAEC,OAAOC,OAAOtB,aAAa;CACnC,MAAM,CAACuB,SAASC,cAAc3B,SAAS,KAAK;CAE5C,MAAM4B,QAAQtB,eAAe,IAAIK,uBAAuBkB;CACxD,MAAAC,UAAAC;CAAA;EAAA,MAAAA,SAAAD,QAAAE,YACmB;GAAElB,SAASA,YAAY,SAAS,SAASmB;GAAWlB;EAAK,CAAC;EAC7E,OACE,oBAAC,OAAD;GACE,aAAa;GAEb,oBAAoBU,GAAGS,cAAc,SAAS,SAAS;GACvD,YAAY;GACZ,sBAAsBV,MAAMW,OAAOC;GACnC,gBAAgBZ,MAAMW,OAAOE;GAC7B,aAAab,MAAMW,OAAOE;GAC1B,UAAU,CAACpB;GACX,oBAAoB;IAAE,GAAGK;IAAoBL;GAAS;GACtD,UAAUqB,UAAU;IAClBX,WAAW,IAAI;IACfP,UAAUkB,KAAK;GACjB;GACA,SAASA,UAAU;IACjBX,WAAW,KAAK;IAChBN,SAASiB,KAAK;GAChB;GACA,OAAO;IACLP,OAAOQ;IAGPb,WAAWZ,YAAY,aAAa,EAAE0B,aAAa1C,UAAU0B,MAAMW,OAAOE,OAAO5B,wBAAwB,EAAE;IAC3GO,WAAWe,OAAOf;IAClBC,YAAYc,OAAOd;IACnBE;GAAK;GAEP,GAAII;EAAM;CAEZ;AACJ;AAEA,MAAMQ,SAAS7B,WAAWuC,QAAQjB,WAAW;CAC3Ce,OAAO;EACLG,UAAU;EACVC,WAAW;EACXC,OAAOpB,MAAMW,OAAOU;EACpBC,YAAYzC,OAAOmB,MAAMsB,WAAWC,IAAI;EACxCC,UAAU;GACRlC,SAAS;IACPmC,SAAS;KACPC,cAAc1B,MAAM0B,aAAaC;KACjCC,aAAa;KACbZ,aAAahB,MAAMW,OAAOkB;KAC1BC,iBAAiB9B,MAAMW,OAAOoB;IAChC;;IAEAC,MAAM;KAAEJ,aAAa;KAAGE,iBAAiB;KAAeG,SAAS;IAAE;GACrE;GACA1C,MAAM;IACJ2C,IAAI;KACFC,mBAAmBnC,MAAMoC,QAAQ,GAAG;KACpCC,iBAAiBrC,MAAMoC,QAAQ,EAAG;KAClCE,UAAUtC,MAAMsC,SAASC;IAC3B;IACAA,IAAI;KACFJ,mBAAmBnC,MAAMoC,QAAQ,CAAC;KAClCC,iBAAiBrC,MAAMoC,QAAQ,CAAC;KAChCE,UAAUtC,MAAMsC,SAASC;IAC3B;IACAC,IAAI;KACFL,mBAAmBnC,MAAMoC,QAAQ,GAAG;KACpCC,iBAAiBrC,MAAMoC,QAAQ,GAAG;KAClCE,UAAUtC,MAAMsC,SAASG;IAC3B;IACAC,IAAI;KACFP,mBAAmBnC,MAAMoC,QAAQ,CAAC;KAClCC,iBAAiBrC,MAAMoC,QAAQ,GAAG;KAClCE,UAAUtC,MAAMsC,SAASG;IAC3B;GACF;EACF;EACAE,kBAAkB,CAAC;GAAErD,SAAS;GAAQiB,QAAQ;IAAE0B,SAAS;IAAGE,mBAAmB;IAAGE,iBAAiB;GAAE;EAAE,CAAC;EAACO,mBAAA,CAAA,GAAA,CAAA;CAC3G;CACApD,SAAS;EAAEwB,aAAahB,MAAMW,OAAO;EAAaS,OAAOpB,MAAMW,OAAOkC;EAAGD,mBAAA,CAAA,CAAA;CAAC;CAC1EnD,UAAU,EAAEqD,SAAS5D,iBAAiB;AACxC,EAAE"}
1
+ {"version":3,"file":"Input.mjs","names":["useInsideSheet","withAlpha","BottomSheetTextInput","useState","TextInputProps","StyleSheet","useUnistyles","withUnistyles","fontOf","FieldVariant","FieldSize","FOCUS_EDGE_ALPHA_PERCENT","DISABLED_OPACITY","ThemedSheetTextInput","InputProps","Omit","variant","size","invalid","disabled","Input","style","onFocus","onBlur","accessibilityState","props","theme","rt","focused","setFocused","Field","TextInput","_styles","styles","useVariants","undefined","themeName","colors","faint","green","event","field","borderColor","create","minWidth","minHeight","color","hi","fontFamily","sans","variants","default","borderRadius","DEFAULT","borderWidth","border","backgroundColor","deep","bare","padding","xs","paddingHorizontal","spacing","paddingVertical","fontSize","sm","md","base","lg","compoundVariants","uni__dependencies","red","opacity"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import { useInsideSheet } from '@agimon-ai/po-native-components/shell';\nimport { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport { BottomSheetTextInput } from '@gorhom/bottom-sheet';\nimport { useState } from 'react';\nimport { TextInput, type TextInputProps } from 'react-native';\nimport { StyleSheet, useUnistyles, withUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\n\nexport type FieldVariant = 'default' | 'bare';\nexport type FieldSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/** `focus:border-po-green/60`. */\nconst FOCUS_EDGE_ALPHA_PERCENT = 60;\nconst DISABLED_OPACITY = 0.5;\n\nconst ThemedSheetTextInput = withUnistyles(BottomSheetTextInput);\nexport interface InputProps extends Omit<TextInputProps, 'editable'> {\n variant?: FieldVariant;\n /** The same rungs Button names, so a field and the button beside it line up. */\n size?: FieldSize;\n /** The value is wrong: red edge and red text, as `aria-invalid` on the web. */\n invalid?: boolean;\n disabled?: boolean;\n}\n\n/**\n * The one text field: deep well, quiet border, jade edge and cursor on focus,\n * red edge when invalid. Inside a Sheet it becomes the sheet's own input.\n */\nexport function Input({\n variant = 'default',\n size = 'md',\n invalid = false,\n disabled = false,\n style,\n onFocus,\n onBlur,\n accessibilityState,\n ...props\n}: InputProps) {\n const { theme, rt } = useUnistyles();\n const [focused, setFocused] = useState(false);\n // Inside a Sheet the field must be the sheet's own input, so the sheet rises with the keyboard.\n const Field = useInsideSheet() ? ThemedSheetTextInput : TextInput;\n // Unistyles reserves a variant named `default` as the fallback for an unset variant.\n styles.useVariants({ variant: variant === 'bare' ? 'bare' : undefined, size });\n return (\n <Field\n autoCorrect={false}\n // iOS draws the keyboard light by default, a bright slab under a dark screen.\n keyboardAppearance={rt.themeName === 'dark' ? 'dark' : 'light'}\n spellCheck={false}\n placeholderTextColor={theme.colors.faint}\n selectionColor={theme.colors.green}\n cursorColor={theme.colors.green}\n editable={!disabled}\n accessibilityState={{ ...accessibilityState, disabled }}\n onFocus={(event) => {\n setFocused(true);\n onFocus?.(event);\n }}\n onBlur={(event) => {\n setFocused(false);\n onBlur?.(event);\n }}\n style={[\n styles.field,\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n focused && variant === 'default' && { borderColor: withAlpha(theme.colors.green, FOCUS_EDGE_ALPHA_PERCENT) },\n invalid && styles.invalid,\n disabled && styles.disabled,\n style,\n ]}\n {...props}\n />\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n field: {\n minWidth: 0,\n minHeight: 44,\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n variants: {\n variant: {\n default: {\n borderRadius: theme.borderRadius.DEFAULT,\n borderWidth: 1,\n borderColor: theme.colors.border,\n backgroundColor: theme.colors.deep,\n },\n /** No well: a composer or a search that draws its own surface keeps the type and drops the box. */\n bare: { borderWidth: 0, backgroundColor: 'transparent', padding: 0 },\n },\n size: {\n xs: {\n paddingHorizontal: theme.spacing(1.5),\n paddingVertical: theme.spacing(0.5),\n fontSize: theme.fontSize.sm,\n },\n sm: {\n paddingHorizontal: theme.spacing(2),\n paddingVertical: theme.spacing(1),\n fontSize: theme.fontSize.sm,\n },\n md: {\n paddingHorizontal: theme.spacing(2.5),\n paddingVertical: theme.spacing(1.5),\n fontSize: theme.fontSize.base,\n },\n lg: {\n paddingHorizontal: theme.spacing(3),\n paddingVertical: theme.spacing(1.5),\n fontSize: theme.fontSize.base,\n },\n },\n },\n compoundVariants: [{ variant: 'bare', styles: { padding: 0, paddingHorizontal: 0, paddingVertical: 0 } }],\n },\n invalid: { borderColor: theme.colors['edge-red'], color: theme.colors.red },\n disabled: { opacity: DISABLED_OPACITY },\n}));\n"],"mappings":";;;;;;;;;;;AAaA,MAAMW,2BAA2B;AACjC,MAAMC,mBAAmB;AAEzB,MAAMC,uBAAuBN,cAAcL,oBAAoB;;;;;AAc/D,SAAgBkB,MAAM,EACpBJ,UAAU,WACVC,OAAO,MACPC,UAAU,OACVC,WAAW,OACXE,OACAC,SACAC,QACAC,oBACA,GAAGC,SACU;CACb,MAAM,EAAEC,OAAOC,OAAOrB,aAAa;CACnC,MAAM,CAACsB,SAASC,cAAc1B,SAAS,KAAK;CAE5C,MAAM2B,QAAQ9B,eAAe,IAAIa,uBAAuBkB;CACxD,MAAAC,UAAAC;CAAA;EAAA,MAAAA,SAAAD,QAAAE,YACmB;GAAElB,SAASA,YAAY,SAAS,SAASmB;GAAWlB;EAAK,CAAC;EAC7E,OACE,oBAAC,OAAD;GACE,aAAa;GAEb,oBAAoBU,GAAGS,cAAc,SAAS,SAAS;GACvD,YAAY;GACZ,sBAAsBV,MAAMW,OAAOC;GACnC,gBAAgBZ,MAAMW,OAAOE;GAC7B,aAAab,MAAMW,OAAOE;GAC1B,UAAU,CAACpB;GACX,oBAAoB;IAAE,GAAGK;IAAoBL;GAAS;GACtD,UAAUqB,UAAU;IAClBX,WAAW,IAAI;IACfP,UAAUkB,KAAK;GACjB;GACA,SAASA,UAAU;IACjBX,WAAW,KAAK;IAChBN,SAASiB,KAAK;GAChB;GACA,OAAO;IACLP,OAAOQ;IAGPb,WAAWZ,YAAY,aAAa,EAAE0B,aAAazC,UAAUyB,MAAMW,OAAOE,OAAO5B,wBAAwB,EAAE;IAC3GO,WAAWe,OAAOf;IAClBC,YAAYc,OAAOd;IACnBE;GAAK;GAEP,GAAII;EAAM;CAEZ;AACJ;AAEA,MAAMQ,SAAS5B,WAAWsC,QAAQjB,WAAW;CAC3Ce,OAAO;EACLG,UAAU;EACVC,WAAW;EACXC,OAAOpB,MAAMW,OAAOU;EACpBC,YAAYxC,OAAOkB,MAAMsB,WAAWC,IAAI;EACxCC,UAAU;GACRlC,SAAS;IACPmC,SAAS;KACPC,cAAc1B,MAAM0B,aAAaC;KACjCC,aAAa;KACbZ,aAAahB,MAAMW,OAAOkB;KAC1BC,iBAAiB9B,MAAMW,OAAOoB;IAChC;;IAEAC,MAAM;KAAEJ,aAAa;KAAGE,iBAAiB;KAAeG,SAAS;IAAE;GACrE;GACA1C,MAAM;IACJ2C,IAAI;KACFC,mBAAmBnC,MAAMoC,QAAQ,GAAG;KACpCC,iBAAiBrC,MAAMoC,QAAQ,EAAG;KAClCE,UAAUtC,MAAMsC,SAASC;IAC3B;IACAA,IAAI;KACFJ,mBAAmBnC,MAAMoC,QAAQ,CAAC;KAClCC,iBAAiBrC,MAAMoC,QAAQ,CAAC;KAChCE,UAAUtC,MAAMsC,SAASC;IAC3B;IACAC,IAAI;KACFL,mBAAmBnC,MAAMoC,QAAQ,GAAG;KACpCC,iBAAiBrC,MAAMoC,QAAQ,GAAG;KAClCE,UAAUtC,MAAMsC,SAASG;IAC3B;IACAC,IAAI;KACFP,mBAAmBnC,MAAMoC,QAAQ,CAAC;KAClCC,iBAAiBrC,MAAMoC,QAAQ,GAAG;KAClCE,UAAUtC,MAAMsC,SAASG;IAC3B;GACF;EACF;EACAE,kBAAkB,CAAC;GAAErD,SAAS;GAAQiB,QAAQ;IAAE0B,SAAS;IAAGE,mBAAmB;IAAGE,iBAAiB;GAAE;EAAE,CAAC;EAACO,mBAAA,CAAA,GAAA,CAAA;CAC3G;CACApD,SAAS;EAAEwB,aAAahB,MAAMW,OAAO;EAAaS,OAAOpB,MAAMW,OAAOkC;EAAGD,mBAAA,CAAA,CAAA;CAAC;CAC1EnD,UAAU,EAAEqD,SAAS5D,iBAAiB;AACxC,EAAE"}
@@ -1,14 +1,8 @@
1
1
  import { StatusTone } from "./StatusBadge.mjs";
2
2
  import { StyleProp, TextProps, ViewProps, ViewStyle } from "react-native";
3
3
  import { ReactNode } from "react";
4
+ import { MessageItemState, MessageItemState as MessageItemState$1 } from "@agimon-ai/po-native-components/shell";
4
5
  //#region src/components/MessageItem.d.ts
5
- export interface MessageItemState {
6
- tone: StatusTone;
7
- /** Whether the header offers the toggle; an item that hides nothing offers none. */
8
- expandable: boolean;
9
- expanded: boolean;
10
- toggle: () => void;
11
- }
12
6
  /** The enclosing item's state, for a part that lives deeper than the item's render prop. */
13
7
  export declare function useMessageItem(): MessageItemState;
14
8
  /** The tone a tool call's item wears: running while the tool runs, then its outcome. */
@@ -84,4 +78,5 @@ export interface MessageItemStatusProps extends Omit<TextProps, 'children'> {
84
78
  /** The one-line status under a body: `running`, `failed`, `done`, or the hint that more is hidden. */
85
79
  export declare function MessageItemStatus({ tone, glyph, expands, children, containerStyle, style, ...props }: MessageItemStatusProps): import("react").JSX.Element;
86
80
  //#endregion
81
+ export type { MessageItemState$1 as MessageItemState };
87
82
  //# sourceMappingURL=MessageItem.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageItem.d.mts","names":[],"sources":["../../src/components/MessageItem.tsx"],"mappings":";;;;iBA6BiB;EACf,MAAM;;EAEN;EACA;EACA;;;wBAWc,kBAAkB;;wBAQlB,SAAS;EAAS;EAAkB;IAAqB;;qBAK5D,cAAc,SAAS,OAAO;;qBAU9B,cAAc,SAAS,OAAO;iBAmB1B,yBAAyB,KAAK;EAC7C,OAAO;;EAEP;EACA;;EAEA;EACA,oBAAoB;;EAEpB,WAAW,cAAc,OAAO,qBAAqB;EACrD,QAAQ,UAAU;;wBAGJ,cACd,MACA,YACA,iBACA,UACA,kBACA,UACA,UACG,SACF,mCAAgB,IAAA;iBA2FF,8BAA8B,KAAK;EAClD,OAAO;;EAEP,OAAO;;EAEP,UAAU;;EAEV,QAAQ;EACR,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAQJ,mBACd,MACA,OACA,SACA,OACA,UACA,UACG,SACF,wCAAqB,IAAA;iBAmBP,+BAA+B,KAAK;;EAEnD,OAAO;;EAEP,QAAQ;;EAER,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAQJ,oBAAoB,OAAO,OAAO,UAAU,UAAU,SAAS,yCAAsB,IAAA;iBAoCpF,6BAA6B,KAAK;EACjD,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,kBAAkB,UAAU,UAAU,SAAS,uCAAoB,IAAA;iBAQlE,+BAA+B,KAAK;EACnD,OAAO;;EAEP;;EAEA;EACA,WAAW;;EAEX,iBAAiB,UAAU;;;wBAIb,oBACd,MACA,OACA,SACA,UACA,gBACA,UACG,SACF,yCAAsB,IAAA"}
1
+ {"version":3,"file":"MessageItem.d.mts","names":[],"sources":["../../src/components/MessageItem.tsx"],"mappings":";;;;;;wBAqCgB,kBAAkB;;wBAKlB,SAAS;EAAS;EAAkB;IAAqB;;qBAK5D,cAAc,SAAS,OAAO;;qBAU9B,cAAc,SAAS,OAAO;iBAmB1B,yBAAyB,KAAK;EAC7C,OAAO;;EAEP;EACA;;EAEA;EACA,oBAAoB;;EAEpB,WAAW,cAAc,OAAO,qBAAqB;EACrD,QAAQ,UAAU;;wBAGJ,cACd,MACA,YACA,iBACA,UACA,kBACA,UACA,UACG,SACF,mCAAgB,IAAA;iBA2FF,8BAA8B,KAAK;EAClD,OAAO;;EAEP,OAAO;;EAEP,UAAU;;EAEV,QAAQ;EACR,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAQJ,mBACd,MACA,OACA,SACA,OACA,UACA,UACG,SACF,wCAAqB,IAAA;iBAmBP,+BAA+B,KAAK;;EAEnD,OAAO;;EAEP,QAAQ;;EAER,WAAW;EACX,QAAQ,UAAU;;;;;;;wBAQJ,oBAAoB,OAAO,OAAO,UAAU,UAAU,SAAS,yCAAsB,IAAA;iBAoCpF,6BAA6B,KAAK;EACjD,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,kBAAkB,UAAU,UAAU,SAAS,uCAAoB,IAAA;iBAQlE,+BAA+B,KAAK;EACnD,OAAO;;EAEP;;EAEA;EACA,WAAW;;EAEX,iBAAiB,UAAU;;;wBAIb,oBACd,MACA,OACA,SACA,UACA,gBACA,UACG,SACF,yCAAsB,IAAA"}
@@ -9,9 +9,10 @@ import { STATUS_EDGE, StatusBadge } from "./StatusBadge.mjs";
9
9
  import { View } from "react-native-unistyles/components/native/View";
10
10
  import { Text } from "react-native-unistyles/components/native/Text";
11
11
  import { StyleSheet } from "react-native-unistyles";
12
- import { createContext, useContext, useMemo } from "react";
12
+ import { useContext, useMemo } from "react";
13
13
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { Pressable } from "react-native-unistyles/components/native/Pressable";
15
+ import { MessageItemContext, MessageItemGroupContext } from "@agimon-ai/po-native-components/shell";
15
16
 
16
17
  //#region src/components/MessageItem.tsx
17
18
  /** Tones whose outcome reads as an icon alone; the rest keep their worded badge. */
@@ -23,18 +24,10 @@ const ICON_TONES = /* @__PURE__ */ new Set([
23
24
  const MIN_ROW_HEIGHT = 44;
24
25
  const LEAD_CHIP = 36;
25
26
  const ROW_EDGE_WIDTH = 2;
26
- const MessageItemContext = createContext({
27
- tone: "neutral",
28
- expandable: false,
29
- expanded: false,
30
- toggle: () => void 0
31
- });
32
27
  /** The enclosing item's state, for a part that lives deeper than the item's render prop. */
33
28
  function useMessageItem() {
34
29
  return useContext(MessageItemContext);
35
30
  }
36
- /** The group an item is a row of, or null for an item that is a card of its own. */
37
- const MessageItemGroupContext = createContext(null);
38
31
  /** The tone a tool call's item wears: running while the tool runs, then its outcome. */
39
32
  function toolTone(state) {
40
33
  return state.running ? "running" : state.isError ? "error" : "ok";
@@ -1 +1 @@
1
- {"version":3,"file":"MessageItem.mjs","names":["NativeColorToken","createContext","ReactNode","useContext","useMemo","StyleProp","TextProps","ViewProps","ViewStyle","StyleSheet","AlertIcon","CheckIcon","ChevronDownIcon","ChevronRightIcon","WrenchIcon","fontOf","STATUS_COLORS","useControllable","wrapText","Button","Spinner","STATUS_EDGE","StatusBadge","StatusTone","ICON_TONES","ReadonlySet","Set","MIN_ROW_HEIGHT","LEAD_CHIP","ROW_EDGE_WIDTH","MessageItemState","tone","expandable","expanded","toggle","MessageItemContext","undefined","useMessageItem","MessageItemGroupContext","toolTone","state","running","isError","STATUS_LABEL","Readonly","Record","neutral","ok","error","info","accent","STATUS_GLYPH","cardEdge","rowEdge","MessageItemProps","Omit","defaultExpanded","onExpandedChange","children","style","MessageItem","props","current","setExpanded","group","styles","Summary","summary","summaryText","ToolCallLead","title","caption","chip","lead","titleLine","RowLead","Outcome","ink","has","outcomeIcon","outcome","MessageItemGroupProps","badge","MessageItemGroup","label","header","MessageItemHeaderProps","MessageItemHeader","content","pressed","headerPressed","MessageItemPartProps","MessageItemBody","body","bodyText","MessageItemStatusProps","glyph","expands","containerStyle","MessageItemStatus","line","status","more","create","theme","token","overflow","borderRadius","lg","borderWidth","borderColor","colors","uni__dependencies","borderTopWidth","borderTopColor","borderLeftWidth","borderLeftColor","flexDirection","alignItems","gap","spacing","minHeight","paddingHorizontal","paddingVertical","backgroundColor","panel","justifyContent","width","height","flexShrink","full","rail","flex","minWidth","color","dim","fontFamily","sans","fontSize","sm","lineHeight","hi","base","fontWeight","semibold","faint","alignSelf"],"sources":["../../src/components/MessageItem.tsx"],"sourcesContent":["import type { NativeColorToken } from '@agimon-ai/po-web-components/nativeTheme';\nimport { createContext, type ReactNode, useContext, useMemo } from 'react';\nimport { Pressable, type StyleProp, Text, type TextProps, View, type ViewProps, type ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { AlertIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, WrenchIcon } from '../icons/icons';\nimport { fontOf } from '../lib/fonts';\nimport { STATUS_COLORS } from '../lib/tone';\nimport { useControllable } from '../lib/useControllable';\nimport { wrapText } from '../lib/wrapText';\nimport { Button } from './Button';\nimport { Spinner } from './Spinner';\nimport { STATUS_EDGE, StatusBadge, type StatusTone } from './StatusBadge';\n\n/** Tones whose outcome reads as an icon alone; the rest keep their worded badge. */\nconst ICON_TONES: ReadonlySet<StatusTone> = new Set<StatusTone>(['running', 'ok', 'error']);\n\n/*\n * The message item: the timeline card a tool call, a run or a notice sits in.\n * The item owns its outcome tone and its expand state; the header, body and\n * status parts read both from it, so a card composes the parts and never\n * threads `expanded` by hand. The header is one Pressable that expands the\n * item, the native stand-in for the web's small chevron button.\n */\n\nconst MIN_ROW_HEIGHT = 44;\nconst LEAD_CHIP = 36;\nconst ROW_EDGE_WIDTH = 2;\n\nexport interface MessageItemState {\n tone: StatusTone;\n /** Whether the header offers the toggle; an item that hides nothing offers none. */\n expandable: boolean;\n expanded: boolean;\n toggle: () => void;\n}\n\nconst MessageItemContext = createContext<MessageItemState>({\n tone: 'neutral',\n expandable: false,\n expanded: false,\n toggle: () => undefined,\n});\n\n/** The enclosing item's state, for a part that lives deeper than the item's render prop. */\nexport function useMessageItem(): MessageItemState {\n return useContext(MessageItemContext);\n}\n\n/** The group an item is a row of, or null for an item that is a card of its own. */\nconst MessageItemGroupContext = createContext<{ tone: StatusTone } | null>(null);\n\n/** The tone a tool call's item wears: running while the tool runs, then its outcome. */\nexport function toolTone(state: { running: boolean; isError: boolean }): StatusTone {\n return state.running ? 'running' : state.isError ? 'error' : 'ok';\n}\n\n/** The badge text a tone reads as when the header is not told otherwise; empty hides the badge. */\nexport const STATUS_LABEL: Readonly<Record<StatusTone, string>> = {\n neutral: '',\n running: 'Running',\n ok: 'Completed',\n error: 'Failed',\n info: 'Info',\n accent: 'Note',\n};\n\n/** The glyph a tone reads as in a status line. */\nexport const STATUS_GLYPH: Readonly<Record<StatusTone, string>> = {\n neutral: '\\u2026',\n running: '\\u25d0',\n ok: '\\u2713',\n error: '\\u2717',\n info: '\\u25cf',\n accent: '\\u25cf',\n};\n\n/** A settled OK is the calm default and keeps the soft border; only work in flight or a failure colours the edge. */\nfunction cardEdge(tone: StatusTone): NativeColorToken {\n return tone === 'ok' ? 'border-soft' : STATUS_EDGE[tone];\n}\n\n/** As a row, a settled or neutral item keeps a quiet edge. */\nfunction rowEdge(tone: StatusTone): NativeColorToken | undefined {\n return tone === 'ok' || tone === 'neutral' ? undefined : STATUS_EDGE[tone];\n}\n\nexport interface MessageItemProps extends Omit<ViewProps, 'children' | 'style'> {\n tone?: StatusTone;\n /** Whether the header offers the expand toggle. A toggle that reveals nothing reads as broken, so the card decides. */\n expandable?: boolean;\n defaultExpanded?: boolean;\n /** Controlled mode; pair with onExpandedChange. Omit it and the item keeps its own state. */\n expanded?: boolean;\n onExpandedChange?: (expanded: boolean) => void;\n /** Plain content, or a function of the item's state for a card that picks its lines by `expanded`. */\n children?: ReactNode | ((state: MessageItemState) => ReactNode);\n style?: StyleProp<ViewStyle>;\n}\n\nexport function MessageItem({\n tone = 'neutral',\n expandable = false,\n defaultExpanded = false,\n expanded,\n onExpandedChange,\n children,\n style,\n ...props\n}: MessageItemProps) {\n const [current, setExpanded] = useControllable(expanded, defaultExpanded, onExpandedChange);\n const group = useContext(MessageItemGroupContext);\n const state: MessageItemState = { tone, expandable, expanded: current, toggle: () => setExpanded(!current) };\n return (\n <MessageItemContext.Provider value={state}>\n <View\n style={[group === null ? styles.cardEdge(cardEdge(tone)) : styles.rowEdge(rowEdge(tone)), style]}\n {...props}\n >\n {typeof children === 'function' ? children(state) : children}\n </View>\n </MessageItemContext.Provider>\n );\n}\n\n/** The line beside the title; a bare string stays on one line and truncates, as the web's `truncate`. */\nfunction Summary({ children }: { children?: ReactNode }) {\n return (\n <View style={styles.summary}>\n {typeof children === 'string' ? (\n <Text numberOfLines={1} style={styles.summaryText}>\n {children}\n </Text>\n ) : (\n wrapText(children, styles.summaryText)\n )}\n </View>\n );\n}\n\n/** The card's lead: the tool chip, the \"Tool call\" caption, then the name and its summary on one line. */\nfunction ToolCallLead({\n title,\n caption = 'Tool call',\n children,\n}: {\n title: ReactNode;\n caption?: string | null;\n children?: ReactNode;\n}) {\n return (\n <>\n <View accessible={false} style={styles.chip}>\n <WrenchIcon size={16} />\n </View>\n <View style={styles.lead}>\n {caption === null ? null : <Text style={styles.caption}>{caption}</Text>}\n <View style={styles.titleLine}>\n {wrapText(title, styles.title)}\n <Summary>{children}</Summary>\n </View>\n </View>\n </>\n );\n}\n\n/** A row's lead inside a group: the name and its summary, no chip or caption, since the group header carries them. */\nfunction RowLead({ title, children }: { title: ReactNode; children?: ReactNode }) {\n return (\n <View style={[styles.lead, styles.titleLine]}>\n {wrapText(title, styles.title)}\n <Summary>{children}</Summary>\n </View>\n );\n}\n\n/** The outcome: an icon for running, done and failed, announced by its label; a worded badge for other tones. */\nfunction Outcome({ tone, children }: { tone: StatusTone; children: ReactNode }) {\n const ink = STATUS_COLORS[tone].ink;\n if (ICON_TONES.has(tone)) {\n return (\n <View\n accessible\n accessibilityRole=\"image\"\n accessibilityLabel={typeof children === 'string' ? children : STATUS_LABEL[tone]}\n style={styles.outcomeIcon}\n >\n {tone === 'running' ? <Spinner color={ink} /> : null}\n {tone === 'ok' ? <CheckIcon size={14} color={ink} /> : null}\n {tone === 'error' ? <AlertIcon size={14} color={ink} /> : null}\n </View>\n );\n }\n return (\n <StatusBadge tone={tone} size=\"md\" style={styles.outcome}>\n {children}\n </StatusBadge>\n );\n}\n\nexport interface MessageItemGroupProps extends Omit<ViewProps, 'children' | 'style'> {\n tone?: StatusTone;\n /** The bold label at the left of the group header, such as \"7 tool calls\". */\n title: ReactNode;\n /** The line beside it, such as which tools the group holds. */\n summary?: ReactNode;\n /** The outcome's label; defaults to the tone's label, null hides the outcome. */\n badge?: ReactNode | null;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * One frame around a run of items that belong together. It stays open: each\n * item inside becomes a row with its own name, outcome and expand, no card of\n * its own, and its tone an edge down its left side.\n */\nexport function MessageItemGroup({\n tone = 'neutral',\n title,\n summary,\n badge,\n children,\n style,\n ...props\n}: MessageItemGroupProps) {\n const label = badge === undefined ? STATUS_LABEL[tone] : badge;\n // A stable value, so a group re-render does not re-render every memoised row's item.\n const group = useMemo(() => ({ tone }), [tone]);\n return (\n <MessageItem tone={tone} style={style} {...props}>\n <View style={styles.header}>\n <ToolCallLead title={title} caption={null}>\n {summary}\n </ToolCallLead>\n {label !== null && label !== '' ? <Outcome tone={tone}>{label}</Outcome> : null}\n </View>\n <MessageItemGroupContext.Provider value={group}>\n <View>{children}</View>\n </MessageItemGroupContext.Provider>\n </MessageItem>\n );\n}\n\nexport interface MessageItemHeaderProps extends Omit<ViewProps, 'children' | 'style'> {\n /** The bold label at the left: the tool name. */\n title: ReactNode;\n /** The badge text; defaults to the tone's label, null hides the badge. */\n badge?: ReactNode | null;\n /** The summary beside the title; it gets the remaining width. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * The title row: label, summary, the tone's outcome and, when the item is\n * expandable, a chevron; the whole row is the toggle. A row inside a group\n * keeps its name but drops the chip and caption the group header carries.\n */\nexport function MessageItemHeader({ title, badge, children, style, ...props }: MessageItemHeaderProps) {\n const { tone, expandable, expanded, toggle } = useMessageItem();\n const group = useContext(MessageItemGroupContext);\n const label = badge === undefined ? STATUS_LABEL[tone] : badge;\n const content = (\n <>\n {group === null ? (\n <ToolCallLead title={title}>{children}</ToolCallLead>\n ) : (\n <RowLead title={title}>{children}</RowLead>\n )}\n {label !== null && label !== '' ? <Outcome tone={tone}>{label}</Outcome> : null}\n {expandable ? expanded ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} /> : null}\n </>\n );\n if (!expandable) {\n return (\n <View style={[styles.header, style]} {...props}>\n {content}\n </View>\n );\n }\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ expanded }}\n accessibilityHint={expanded ? 'collapse' : 'expand'}\n onPress={toggle}\n style={({ pressed }) => [styles.header, pressed && styles.headerPressed, style]}\n {...props}\n >\n {content}\n </Pressable>\n );\n}\n\nexport interface MessageItemPartProps extends Omit<ViewProps, 'children' | 'style'> {\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** The body under the header, on the card's own surface. */\nexport function MessageItemBody({ children, style, ...props }: MessageItemPartProps) {\n return (\n <View style={[styles.body, style]} {...props}>\n {wrapText(children, styles.bodyText)}\n </View>\n );\n}\n\nexport interface MessageItemStatusProps extends Omit<TextProps, 'children'> {\n tone?: StatusTone;\n /** Replaces the tone's glyph. */\n glyph?: string;\n /** Renders as a button that expands the item: the \"N more line(s)\" hint. */\n expands?: boolean;\n children?: ReactNode;\n /** Applied to the row; with `expands`, to the button. */\n containerStyle?: StyleProp<ViewStyle>;\n}\n\n/** The one-line status under a body: `running`, `failed`, `done`, or the hint that more is hidden. */\nexport function MessageItemStatus({\n tone = 'neutral',\n glyph,\n expands = false,\n children,\n containerStyle,\n style,\n ...props\n}: MessageItemStatusProps) {\n const { toggle } = useMessageItem();\n const line = (\n <Text style={[styles.status, style]} {...props}>\n <Text style={styles.glyph(tone)}>{glyph ?? STATUS_GLYPH[tone]}</Text> {children}\n </Text>\n );\n if (expands) {\n return (\n <Button variant=\"ghost\" size=\"xs\" onPress={toggle} style={[styles.more, containerStyle]}>\n {line}\n </Button>\n );\n }\n return <View style={containerStyle}>{line}</View>;\n}\n\nconst styles = StyleSheet.create((theme) => ({\n cardEdge: (token: NativeColorToken) => ({\n overflow: 'hidden',\n borderRadius: theme.borderRadius.lg,\n borderWidth: 1,\n borderColor: theme.colors[token],\n }),\n // A row's top rule is the group's separator; its left edge carries the tone.\n rowEdge: (token: NativeColorToken | undefined) => ({\n overflow: 'hidden',\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n borderLeftWidth: ROW_EDGE_WIDTH,\n borderLeftColor: token === undefined ? 'transparent' : theme.colors[token],\n }),\n header: {\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(3),\n },\n headerPressed: { backgroundColor: theme.colors.panel },\n chip: {\n alignItems: 'center',\n justifyContent: 'center',\n width: LEAD_CHIP,\n height: LEAD_CHIP,\n flexShrink: 0,\n borderRadius: theme.borderRadius.full,\n backgroundColor: theme.colors.rail,\n },\n lead: { flex: 1, minWidth: 0 },\n caption: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n titleLine: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n title: {\n flexShrink: 0,\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.semibold,\n },\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n summaryText: {\n flexShrink: 1,\n color: theme.colors.faint,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n outcome: { gap: theme.spacing(1) },\n outcomeIcon: { alignItems: 'center', justifyContent: 'center', width: 20, height: 20, flexShrink: 0 },\n body: {\n gap: theme.spacing(1),\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n paddingHorizontal: theme.spacing(4),\n paddingVertical: theme.spacing(3),\n },\n bodyText: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n status: {\n color: theme.colors.faint,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n glyph: (tone: StatusTone) => ({ color: theme.colors[STATUS_COLORS[tone].ink] }),\n more: { alignSelf: 'flex-start' },\n}));\n"],"mappings":"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"}
1
+ {"version":3,"file":"MessageItem.mjs","names":["MessageItemContext","MessageItemGroupContext","MessageItemState","NativeColorToken","ReactNode","useContext","useMemo","StyleProp","TextProps","ViewProps","ViewStyle","StyleSheet","AlertIcon","CheckIcon","ChevronDownIcon","ChevronRightIcon","WrenchIcon","fontOf","STATUS_COLORS","useControllable","wrapText","Button","Spinner","STATUS_EDGE","StatusBadge","StatusTone","ICON_TONES","ReadonlySet","Set","MIN_ROW_HEIGHT","LEAD_CHIP","ROW_EDGE_WIDTH","useMessageItem","toolTone","state","running","isError","STATUS_LABEL","Readonly","Record","neutral","ok","error","info","accent","STATUS_GLYPH","cardEdge","tone","rowEdge","undefined","MessageItemProps","Omit","expandable","defaultExpanded","expanded","onExpandedChange","children","style","MessageItem","props","current","setExpanded","group","toggle","styles","Summary","summary","summaryText","ToolCallLead","title","caption","chip","lead","titleLine","RowLead","Outcome","ink","has","outcomeIcon","outcome","MessageItemGroupProps","badge","MessageItemGroup","label","header","MessageItemHeaderProps","MessageItemHeader","content","pressed","headerPressed","MessageItemPartProps","MessageItemBody","body","bodyText","MessageItemStatusProps","glyph","expands","containerStyle","MessageItemStatus","line","status","more","create","theme","token","overflow","borderRadius","lg","borderWidth","borderColor","colors","uni__dependencies","borderTopWidth","borderTopColor","borderLeftWidth","borderLeftColor","flexDirection","alignItems","gap","spacing","minHeight","paddingHorizontal","paddingVertical","backgroundColor","panel","justifyContent","width","height","flexShrink","full","rail","flex","minWidth","color","dim","fontFamily","sans","fontSize","sm","lineHeight","hi","base","fontWeight","semibold","faint","alignSelf"],"sources":["../../src/components/MessageItem.tsx"],"sourcesContent":["import {\n MessageItemContext,\n MessageItemGroupContext,\n type MessageItemState,\n} from '@agimon-ai/po-native-components/shell';\nimport type { NativeColorToken } from '@agimon-ai/po-web-components/nativeTheme';\nimport { type ReactNode, useContext, useMemo } from 'react';\nimport { Pressable, type StyleProp, Text, type TextProps, View, type ViewProps, type ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { AlertIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, WrenchIcon } from '../icons/icons';\nimport { fontOf } from '../lib/fonts';\nimport { STATUS_COLORS } from '../lib/tone';\nimport { useControllable } from '../lib/useControllable';\nimport { wrapText } from '../lib/wrapText';\nimport { Button } from './Button';\nimport { Spinner } from './Spinner';\nimport { STATUS_EDGE, StatusBadge, type StatusTone } from './StatusBadge';\n\n/** Tones whose outcome reads as an icon alone; the rest keep their worded badge. */\nconst ICON_TONES: ReadonlySet<StatusTone> = new Set<StatusTone>(['running', 'ok', 'error']);\n\n/*\n * The message item: the timeline card a tool call, a run or a notice sits in.\n * The item owns its outcome tone and its expand state; the header, body and\n * status parts read both from it, so a card composes the parts and never\n * threads `expanded` by hand. The header is one Pressable that expands the\n * item, the native stand-in for the web's small chevron button.\n */\n\nconst MIN_ROW_HEIGHT = 44;\nconst LEAD_CHIP = 36;\nconst ROW_EDGE_WIDTH = 2;\n\nexport type { MessageItemState } from '@agimon-ai/po-native-components/shell';\n\n/** The enclosing item's state, for a part that lives deeper than the item's render prop. */\nexport function useMessageItem(): MessageItemState {\n return useContext(MessageItemContext);\n}\n\n/** The tone a tool call's item wears: running while the tool runs, then its outcome. */\nexport function toolTone(state: { running: boolean; isError: boolean }): StatusTone {\n return state.running ? 'running' : state.isError ? 'error' : 'ok';\n}\n\n/** The badge text a tone reads as when the header is not told otherwise; empty hides the badge. */\nexport const STATUS_LABEL: Readonly<Record<StatusTone, string>> = {\n neutral: '',\n running: 'Running',\n ok: 'Completed',\n error: 'Failed',\n info: 'Info',\n accent: 'Note',\n};\n\n/** The glyph a tone reads as in a status line. */\nexport const STATUS_GLYPH: Readonly<Record<StatusTone, string>> = {\n neutral: '\\u2026',\n running: '\\u25d0',\n ok: '\\u2713',\n error: '\\u2717',\n info: '\\u25cf',\n accent: '\\u25cf',\n};\n\n/** A settled OK is the calm default and keeps the soft border; only work in flight or a failure colours the edge. */\nfunction cardEdge(tone: StatusTone): NativeColorToken {\n return tone === 'ok' ? 'border-soft' : STATUS_EDGE[tone];\n}\n\n/** As a row, a settled or neutral item keeps a quiet edge. */\nfunction rowEdge(tone: StatusTone): NativeColorToken | undefined {\n return tone === 'ok' || tone === 'neutral' ? undefined : STATUS_EDGE[tone];\n}\n\nexport interface MessageItemProps extends Omit<ViewProps, 'children' | 'style'> {\n tone?: StatusTone;\n /** Whether the header offers the expand toggle. A toggle that reveals nothing reads as broken, so the card decides. */\n expandable?: boolean;\n defaultExpanded?: boolean;\n /** Controlled mode; pair with onExpandedChange. Omit it and the item keeps its own state. */\n expanded?: boolean;\n onExpandedChange?: (expanded: boolean) => void;\n /** Plain content, or a function of the item's state for a card that picks its lines by `expanded`. */\n children?: ReactNode | ((state: MessageItemState) => ReactNode);\n style?: StyleProp<ViewStyle>;\n}\n\nexport function MessageItem({\n tone = 'neutral',\n expandable = false,\n defaultExpanded = false,\n expanded,\n onExpandedChange,\n children,\n style,\n ...props\n}: MessageItemProps) {\n const [current, setExpanded] = useControllable(expanded, defaultExpanded, onExpandedChange);\n const group = useContext(MessageItemGroupContext);\n const state: MessageItemState = { tone, expandable, expanded: current, toggle: () => setExpanded(!current) };\n return (\n <MessageItemContext.Provider value={state}>\n <View\n style={[group === null ? styles.cardEdge(cardEdge(tone)) : styles.rowEdge(rowEdge(tone)), style]}\n {...props}\n >\n {typeof children === 'function' ? children(state) : children}\n </View>\n </MessageItemContext.Provider>\n );\n}\n\n/** The line beside the title; a bare string stays on one line and truncates, as the web's `truncate`. */\nfunction Summary({ children }: { children?: ReactNode }) {\n return (\n <View style={styles.summary}>\n {typeof children === 'string' ? (\n <Text numberOfLines={1} style={styles.summaryText}>\n {children}\n </Text>\n ) : (\n wrapText(children, styles.summaryText)\n )}\n </View>\n );\n}\n\n/** The card's lead: the tool chip, the \"Tool call\" caption, then the name and its summary on one line. */\nfunction ToolCallLead({\n title,\n caption = 'Tool call',\n children,\n}: {\n title: ReactNode;\n caption?: string | null;\n children?: ReactNode;\n}) {\n return (\n <>\n <View accessible={false} style={styles.chip}>\n <WrenchIcon size={16} />\n </View>\n <View style={styles.lead}>\n {caption === null ? null : <Text style={styles.caption}>{caption}</Text>}\n <View style={styles.titleLine}>\n {wrapText(title, styles.title)}\n <Summary>{children}</Summary>\n </View>\n </View>\n </>\n );\n}\n\n/** A row's lead inside a group: the name and its summary, no chip or caption, since the group header carries them. */\nfunction RowLead({ title, children }: { title: ReactNode; children?: ReactNode }) {\n return (\n <View style={[styles.lead, styles.titleLine]}>\n {wrapText(title, styles.title)}\n <Summary>{children}</Summary>\n </View>\n );\n}\n\n/** The outcome: an icon for running, done and failed, announced by its label; a worded badge for other tones. */\nfunction Outcome({ tone, children }: { tone: StatusTone; children: ReactNode }) {\n const ink = STATUS_COLORS[tone].ink;\n if (ICON_TONES.has(tone)) {\n return (\n <View\n accessible\n accessibilityRole=\"image\"\n accessibilityLabel={typeof children === 'string' ? children : STATUS_LABEL[tone]}\n style={styles.outcomeIcon}\n >\n {tone === 'running' ? <Spinner color={ink} /> : null}\n {tone === 'ok' ? <CheckIcon size={14} color={ink} /> : null}\n {tone === 'error' ? <AlertIcon size={14} color={ink} /> : null}\n </View>\n );\n }\n return (\n <StatusBadge tone={tone} size=\"md\" style={styles.outcome}>\n {children}\n </StatusBadge>\n );\n}\n\nexport interface MessageItemGroupProps extends Omit<ViewProps, 'children' | 'style'> {\n tone?: StatusTone;\n /** The bold label at the left of the group header, such as \"7 tool calls\". */\n title: ReactNode;\n /** The line beside it, such as which tools the group holds. */\n summary?: ReactNode;\n /** The outcome's label; defaults to the tone's label, null hides the outcome. */\n badge?: ReactNode | null;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * One frame around a run of items that belong together. It stays open: each\n * item inside becomes a row with its own name, outcome and expand, no card of\n * its own, and its tone an edge down its left side.\n */\nexport function MessageItemGroup({\n tone = 'neutral',\n title,\n summary,\n badge,\n children,\n style,\n ...props\n}: MessageItemGroupProps) {\n const label = badge === undefined ? STATUS_LABEL[tone] : badge;\n // A stable value, so a group re-render does not re-render every memoised row's item.\n const group = useMemo(() => ({ tone }), [tone]);\n return (\n <MessageItem tone={tone} style={style} {...props}>\n <View style={styles.header}>\n <ToolCallLead title={title} caption={null}>\n {summary}\n </ToolCallLead>\n {label !== null && label !== '' ? <Outcome tone={tone}>{label}</Outcome> : null}\n </View>\n <MessageItemGroupContext.Provider value={group}>\n <View>{children}</View>\n </MessageItemGroupContext.Provider>\n </MessageItem>\n );\n}\n\nexport interface MessageItemHeaderProps extends Omit<ViewProps, 'children' | 'style'> {\n /** The bold label at the left: the tool name. */\n title: ReactNode;\n /** The badge text; defaults to the tone's label, null hides the badge. */\n badge?: ReactNode | null;\n /** The summary beside the title; it gets the remaining width. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/**\n * The title row: label, summary, the tone's outcome and, when the item is\n * expandable, a chevron; the whole row is the toggle. A row inside a group\n * keeps its name but drops the chip and caption the group header carries.\n */\nexport function MessageItemHeader({ title, badge, children, style, ...props }: MessageItemHeaderProps) {\n const { tone, expandable, expanded, toggle } = useMessageItem();\n const group = useContext(MessageItemGroupContext);\n const label = badge === undefined ? STATUS_LABEL[tone] : badge;\n const content = (\n <>\n {group === null ? (\n <ToolCallLead title={title}>{children}</ToolCallLead>\n ) : (\n <RowLead title={title}>{children}</RowLead>\n )}\n {label !== null && label !== '' ? <Outcome tone={tone}>{label}</Outcome> : null}\n {expandable ? expanded ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} /> : null}\n </>\n );\n if (!expandable) {\n return (\n <View style={[styles.header, style]} {...props}>\n {content}\n </View>\n );\n }\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ expanded }}\n accessibilityHint={expanded ? 'collapse' : 'expand'}\n onPress={toggle}\n style={({ pressed }) => [styles.header, pressed && styles.headerPressed, style]}\n {...props}\n >\n {content}\n </Pressable>\n );\n}\n\nexport interface MessageItemPartProps extends Omit<ViewProps, 'children' | 'style'> {\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** The body under the header, on the card's own surface. */\nexport function MessageItemBody({ children, style, ...props }: MessageItemPartProps) {\n return (\n <View style={[styles.body, style]} {...props}>\n {wrapText(children, styles.bodyText)}\n </View>\n );\n}\n\nexport interface MessageItemStatusProps extends Omit<TextProps, 'children'> {\n tone?: StatusTone;\n /** Replaces the tone's glyph. */\n glyph?: string;\n /** Renders as a button that expands the item: the \"N more line(s)\" hint. */\n expands?: boolean;\n children?: ReactNode;\n /** Applied to the row; with `expands`, to the button. */\n containerStyle?: StyleProp<ViewStyle>;\n}\n\n/** The one-line status under a body: `running`, `failed`, `done`, or the hint that more is hidden. */\nexport function MessageItemStatus({\n tone = 'neutral',\n glyph,\n expands = false,\n children,\n containerStyle,\n style,\n ...props\n}: MessageItemStatusProps) {\n const { toggle } = useMessageItem();\n const line = (\n <Text style={[styles.status, style]} {...props}>\n <Text style={styles.glyph(tone)}>{glyph ?? STATUS_GLYPH[tone]}</Text> {children}\n </Text>\n );\n if (expands) {\n return (\n <Button variant=\"ghost\" size=\"xs\" onPress={toggle} style={[styles.more, containerStyle]}>\n {line}\n </Button>\n );\n }\n return <View style={containerStyle}>{line}</View>;\n}\n\nconst styles = StyleSheet.create((theme) => ({\n cardEdge: (token: NativeColorToken) => ({\n overflow: 'hidden',\n borderRadius: theme.borderRadius.lg,\n borderWidth: 1,\n borderColor: theme.colors[token],\n }),\n // A row's top rule is the group's separator; its left edge carries the tone.\n rowEdge: (token: NativeColorToken | undefined) => ({\n overflow: 'hidden',\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n borderLeftWidth: ROW_EDGE_WIDTH,\n borderLeftColor: token === undefined ? 'transparent' : theme.colors[token],\n }),\n header: {\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(3),\n },\n headerPressed: { backgroundColor: theme.colors.panel },\n chip: {\n alignItems: 'center',\n justifyContent: 'center',\n width: LEAD_CHIP,\n height: LEAD_CHIP,\n flexShrink: 0,\n borderRadius: theme.borderRadius.full,\n backgroundColor: theme.colors.rail,\n },\n lead: { flex: 1, minWidth: 0 },\n caption: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n titleLine: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n title: {\n flexShrink: 0,\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.semibold,\n },\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n summaryText: {\n flexShrink: 1,\n color: theme.colors.faint,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n outcome: { gap: theme.spacing(1) },\n outcomeIcon: { alignItems: 'center', justifyContent: 'center', width: 20, height: 20, flexShrink: 0 },\n body: {\n gap: theme.spacing(1),\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n paddingHorizontal: theme.spacing(4),\n paddingVertical: theme.spacing(3),\n },\n bodyText: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n status: {\n color: theme.colors.faint,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n glyph: (tone: StatusTone) => ({ color: theme.colors[STATUS_COLORS[tone].ink] }),\n more: { alignSelf: 'flex-start' },\n}));\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,MAAM0B,6BAAsC,IAAIE,IAAgB;CAAC;CAAW;CAAM;AAAO,CAAC;AAU1F,MAAMC,iBAAiB;AACvB,MAAMC,YAAY;AAClB,MAAMC,iBAAiB;;AAKvB,SAAgBC,iBAAmC;CACjD,OAAO3B,WAAWL,kBAAkB;AACtC;;AAGA,SAAgBiC,SAASC,OAA2D;CAClF,OAAOA,MAAMC,UAAU,YAAYD,MAAME,UAAU,UAAU;AAC/D;;AAGA,MAAaC,eAAqD;CAChEG,SAAS;CACTL,SAAS;CACTM,IAAI;CACJC,OAAO;CACPC,MAAM;CACNC,QAAQ;AACV;;AAGA,MAAaC,eAAqD;CAChEL,SAAS;CACTL,SAAS;CACTM,IAAI;CACJC,OAAO;CACPC,MAAM;CACNC,QAAQ;AACV;;AAGA,SAASE,SAASC,MAAoC;CACpD,OAAOA,SAAS,OAAO,gBAAgBxB,YAAYwB;AACrD;;AAGA,SAASC,QAAQD,MAAgD;CAC/D,OAAOA,SAAS,QAAQA,SAAS,YAAYE,SAAY1B,YAAYwB;AACvE;AAeA,SAAgBW,YAAY,EAC1BX,OAAO,WACPK,aAAa,OACbC,kBAAkB,OAClBC,UACAC,kBACAC,UACAC,OACA,GAAGE,SACgB;CACnB,MAAM,CAACC,SAASC,eAAe1C,gBAAgBmC,UAAUD,iBAAiBE,gBAAgB;CAC1F,MAAMO,QAAQzD,WAAWJ,uBAAuB;CAChD,MAAMiC,QAA0B;EAAEa;EAAMK;EAAYE,UAAUM;EAASG,cAAcF,YAAY,CAACD,OAAO;CAAE;CAC3G,OACE,oBAAC,mBAAmB,UAApB;EAA6B,OAAO1B;YAClC,oBAAC,MAAD;GACE,OAAO,CAAC4B,UAAU,OAAOE,OAAOlB,SAASA,SAASC,IAAI,CAAC,IAAIiB,OAAOhB,QAAQA,QAAQD,IAAI,CAAC,GAAGU,KAAK;GAC/F,GAAIE;aAEH,OAAOH,aAAa,aAAaA,SAAStB,KAAK,IAAIsB;EAChD;CACqB;AAEjC;;AAGA,SAASS,QAAQ,EAAET,YAAsC;CACvD,OACE,oBAAC,MAAD;EAAM,OAAOQ,OAAOE;YACjB,OAAOV,aAAa,WACnB,oBAAC,MAAD;GAAM,eAAe;GAAG,OAAOQ,OAAOG;GACnCX;EACG,KAENpC,SAASoC,UAAUQ,OAAOG,WAAW;CAEnC;AAEV;;AAGA,SAASC,aAAa,EACpBC,OACAC,UAAU,aACVd,YAKC;CACD,OACE,4CACE,oBAAC,MAAD;EAAM,YAAY;EAAO,OAAOQ,OAAOO;YACrC,oBAAC,YAAD,EAAY,MAAM,GAAG;CACjB,IACN,qBAAC,MAAD;EAAM,OAAOP,OAAOQ;YAApB,CACGF,YAAY,OAAO,OAAO,oBAAC,MAAD;GAAM,OAAON,OAAOM;aAAUA;EAAc,IACvE,qBAAC,MAAD;GAAM,OAAON,OAAOS;aAApB,CACGrD,SAASiD,OAAOL,OAAOK,KAAK,GAC7B,oBAAC,SAAD,EAAUb,SAAkB,EACxB;IACF;GACR;AAEJ;;AAGA,SAASkB,QAAQ,EAAEL,OAAOb,YAAwD;CAChF,OACE,qBAAC,MAAD;EAAM,OAAO,CAACQ,OAAOQ,MAAMR,OAAOS,SAAS;YAA3C,CACGrD,SAASiD,OAAOL,OAAOK,KAAK,GAC7B,oBAAC,SAAD,EAAUb,SAAkB,EACxB;;AAEV;;AAGA,SAASmB,QAAQ,EAAE5B,MAAMS,YAAuD;CAC9E,MAAMoB,MAAM1D,cAAc6B,KAAK,CAAC6B;CAChC,IAAIlD,WAAWmD,IAAI9B,IAAI,GACrB,OACE,qBAAC,MAAD;EACE;EACA,mBAAkB;EAClB,oBAAoB,OAAOS,aAAa,WAAWA,WAAWnB,aAAaU;EAC3E,OAAOiB,OAAOc;YAJhB;GAMG/B,SAAS,YAAY,oBAAC,SAAD,EAAS,OAAO6B,IAAI,KAAM;GAC/C7B,SAAS,OAAO,oBAAC,WAAD;IAAW,MAAM;IAAI,OAAO6B;GAAI,KAAM;GACtD7B,SAAS,UAAU,oBAAC,WAAD;IAAW,MAAM;IAAI,OAAO6B;GAAI,KAAM;EACtD;;CAGV,OACE,oBAAC,aAAD;EAAmB7B;EAAM,MAAK;EAAK,OAAOiB,OAAOe;EAC9CvB;CACU;AAEjB;;;;;;AAmBA,SAAgB0B,iBAAiB,EAC/BnC,OAAO,WACPsB,OACAH,SACAe,OACAzB,UACAC,OACA,GAAGE,SACqB;CACxB,MAAMwB,QAAQF,UAAUhC,SAAYZ,aAAaU,QAAQkC;CAEzD,MAAMnB,QAAQxD,eAAe,EAAEyC,KAAK,IAAI,CAACA,IAAI,CAAC;CAC9C,OACE,qBAAC,aAAD;EAAmBA;EAAaU;EAAO,GAAIE;YAA3C,CACE,qBAAC,MAAD;GAAM,OAAOK,OAAOoB;aAApB,CACE,oBAAC,cAAD;IAAqBf;IAAO,SAAS;cAClCH;GACW,IACbiB,UAAU,QAAQA,UAAU,KAAK,oBAAC,SAAD;IAAepC;cAAOoC;GAAe,KAAI,IACvE;MACN,oBAAC,wBAAwB,UAAzB;GAAkC,OAAOrB;aACvC,oBAAC,MAAD,EAAON,SAAe;EACU,EACvB;;AAEjB;;;;;;AAiBA,SAAgB8B,kBAAkB,EAAEjB,OAAOY,OAAOzB,UAAUC,OAAO,GAAGE,SAAiC;CACrG,MAAM,EAAEZ,MAAMK,YAAYE,UAAUS,WAAW/B,eAAe;CAC9D,MAAM8B,QAAQzD,WAAWJ,uBAAuB;CAChD,MAAMkF,QAAQF,UAAUhC,SAAYZ,aAAaU,QAAQkC;CACzD,MAAMM,UACJ;EACGzB,UAAU,OACT,oBAAC,cAAD;GAAqBO;GAAQb;EAAuB,KAEpD,oBAAC,SAAD;GAAgBa;GAAQb;EAAkB;EAE3C2B,UAAU,QAAQA,UAAU,KAAK,oBAAC,SAAD;GAAepC;aAAOoC;EAAe,KAAI;EAC1E/B,aAAaE,WAAW,oBAAC,iBAAD,EAAiB,MAAM,GAAG,KAAM,oBAAC,kBAAD,EAAkB,MAAM,GAAG,KAAM;CAC5F;CAEF,IAAI,CAACF,YACH,OACE,oBAAC,MAAD;EAAM,OAAO,CAACY,OAAOoB,QAAQ3B,KAAK;EAAG,GAAIE;YACtC4B;CACG;CAGV,OACE,oBAAC,WAAD;EACE,mBAAkB;EAClB,oBAAoB,EAAEjC,SAAS;EAC/B,mBAAmBA,WAAW,aAAa;EAC3C,SAASS;EACT,QAAQ,EAAEyB,cAAc;GAACxB,OAAOoB;GAAQI,WAAWxB,OAAOyB;GAAehC;EAAK;EAC9E,GAAIE;YAEH4B;CACQ;AAEf;;AAQA,SAAgBI,gBAAgB,EAAEnC,UAAUC,OAAO,GAAGE,SAA+B;CACnF,OACE,oBAAC,MAAD;EAAM,OAAO,CAACK,OAAO4B,MAAMnC,KAAK;EAAG,GAAIE;YACpCvC,SAASoC,UAAUQ,OAAO6B,QAAQ;CAC/B;AAEV;;AAcA,SAAgBK,kBAAkB,EAChCnD,OAAO,WACPgD,OACAC,UAAU,OACVxC,UACAyC,gBACAxC,OACA,GAAGE,SACsB;CACzB,MAAM,EAAEI,WAAW/B,eAAe;CAClC,MAAMmE,OACJ,qBAAC,MAAD;EAAM,OAAO,CAACnC,OAAOoC,QAAQ3C,KAAK;EAAG,GAAIE;YAAzC;GACE,oBAAC,MAAD;IAAM,OAAOK,OAAO+B,MAAMhD,IAAI;cAAIgD,SAASlD,aAAaE;GAAY;GAAC;GAAES;EACnE;;CAER,IAAIwC,SACF,OACE,oBAAC,QAAD;EAAQ,SAAQ;EAAQ,MAAK;EAAK,SAASjC;EAAQ,OAAO,CAACC,OAAOqC,MAAMJ,cAAc;YACnFE;CACK;CAGZ,OAAO,oBAAC,MAAD;EAAM,OAAOF;YAAiBE;CAAW;AAClD;AAEA,MAAMnC,SAASrD,WAAW2F,QAAQC,WAAW;CAC3CzD,WAAW0D,WAA6B;EACtCC,UAAU;EACVC,cAAcH,MAAMG,aAAaC;EACjCC,aAAa;EACbC,aAAaN,MAAMO,OAAON;EAAMO,mBAAA,CAAA,CAAA;CAClC;CAEA/D,UAAUwD,WAAyC;EACjDC,UAAU;EACVO,gBAAgB;EAChBC,gBAAgBV,MAAMO,OAAO;EAC7BI,iBAAiBnF;EACjBoF,iBAAiBX,UAAUvD,SAAY,gBAAgBsD,MAAMO,OAAON;EAAMO,mBAAA,CAAA,CAAA;CAC5E;CACA3B,QAAQ;EACNgC,eAAe;EACfC,YAAY;EACZC,KAAKf,MAAMgB,QAAQ,CAAC;EACpBC,WAAW3F;EACX4F,mBAAmBlB,MAAMgB,QAAQ,CAAC;EAClCG,iBAAiBnB,MAAMgB,QAAQ,CAAC;EAACR,mBAAA,CAAA,CAAA;CACnC;CACAtB,eAAe;EAAEkC,iBAAiBpB,MAAMO,OAAOc;EAAKb,mBAAA,CAAA,CAAA;CAAC;CACrDxC,MAAM;EACJ8C,YAAY;EACZQ,gBAAgB;EAChBC,OAAOhG;EACPiG,QAAQjG;EACRkG,YAAY;EACZtB,cAAcH,MAAMG,aAAauB;EACjCN,iBAAiBpB,MAAMO,OAAOoB;EAAInB,mBAAA,CAAA,CAAA;CACpC;CACAvC,MAAM;EAAE2D,MAAM;EAAGC,UAAU;CAAE;CAC7B9D,SAAS;EACP+D,OAAO9B,MAAMO,OAAOwB;EACpBC,YAAYtH,OAAOsF,MAAMgC,WAAWC,IAAI;EACxCC,UAAUlC,MAAMkC,SAASC;EACzBC,YAAYpC,MAAMoC,WAAWD;EAAE3B,mBAAA,CAAA,CAAA;CACjC;CACAtC,WAAW;EAAE2C,eAAe;EAAOC,YAAY;EAAUC,KAAKf,MAAMgB,QAAQ,CAAC;EAAGa,UAAU;EAACrB,mBAAA,CAAA,CAAA;CAAC;CAC5F1C,OAAO;EACL2D,YAAY;EACZK,OAAO9B,MAAMO,OAAO8B;EACpBL,YAAYtH,OAAOsF,MAAMgC,WAAWC,IAAI;EACxCC,UAAUlC,MAAMkC,SAASI;EACzBF,YAAYpC,MAAMoC,WAAWE;EAC7BC,YAAYvC,MAAMuC,WAAWC;EAAQhC,mBAAA,CAAA,CAAA;CACvC;CACA7C,SAAS;EAAEiE,MAAM;EAAGf,eAAe;EAAOC,YAAY;EAAUC,KAAKf,MAAMgB,QAAQ,CAAC;EAAGa,UAAU;EAACrB,mBAAA,CAAA,CAAA;CAAC;CACnG5C,aAAa;EACX6D,YAAY;EACZK,OAAO9B,MAAMO,OAAOkC;EACpBT,YAAYtH,OAAOsF,MAAMgC,WAAWC,IAAI;EACxCC,UAAUlC,MAAMkC,SAASI;EACzBF,YAAYpC,MAAMoC,WAAWE;EAAI9B,mBAAA,CAAA,CAAA;CACnC;CACAhC,SAAS;EAAEuC,KAAKf,MAAMgB,QAAQ,CAAC;EAACR,mBAAA,CAAA,CAAA;CAAC;CACjCjC,aAAa;EAAEuC,YAAY;EAAUQ,gBAAgB;EAAUC,OAAO;EAAIC,QAAQ;EAAIC,YAAY;CAAE;CACpGpC,MAAM;EACJ0B,KAAKf,MAAMgB,QAAQ,CAAC;EACpBP,gBAAgB;EAChBC,gBAAgBV,MAAMO,OAAO;EAC7BW,mBAAmBlB,MAAMgB,QAAQ,CAAC;EAClCG,iBAAiBnB,MAAMgB,QAAQ,CAAC;EAACR,mBAAA,CAAA,CAAA;CACnC;CACAlB,UAAU;EACRwC,OAAO9B,MAAMO,OAAOwB;EACpBC,YAAYtH,OAAOsF,MAAMgC,WAAWC,IAAI;EACxCC,UAAUlC,MAAMkC,SAASI;EACzBF,YAAYpC,MAAMoC,WAAWE;EAAI9B,mBAAA,CAAA,CAAA;CACnC;CACAX,QAAQ;EACNiC,OAAO9B,MAAMO,OAAOkC;EACpBT,YAAYtH,OAAOsF,MAAMgC,WAAWC,IAAI;EACxCC,UAAUlC,MAAMkC,SAASC;EACzBC,YAAYpC,MAAMoC,WAAWD;EAAE3B,mBAAA,CAAA,CAAA;CACjC;CACAhB,QAAQhD,UAAsB;EAAEsF,OAAO9B,MAAMO,OAAO5F,cAAc6B,KAAK,CAAC6B;EAAImC,mBAAA,CAAA,CAAA;CAAC;CAC7EV,MAAM,EAAE4C,WAAW,aAAa;AAClC,EAAE"}
@@ -0,0 +1,26 @@
1
+ import { StatusTone } from "./StatusBadge.mjs";
2
+ //#region src/components/NativeShellState.d.ts
3
+ /** State shared by shell-rendered timeline frames and downloaded tool content. */
4
+ export interface MessageItemState {
5
+ tone: StatusTone;
6
+ expandable: boolean;
7
+ expanded: boolean;
8
+ toggle: () => void;
9
+ }
10
+ export declare const MessageItemContext: import("react").Context<MessageItemState>;
11
+ export declare const MessageItemGroupContext: import("react").Context<{
12
+ tone: StatusTone;
13
+ } | null>;
14
+ export interface OpenSheet {
15
+ keep: () => boolean;
16
+ close: () => void;
17
+ setNote: (note: string | undefined) => void;
18
+ }
19
+ export declare function registerSheet(sheet: OpenSheet): void;
20
+ export declare function unregisterSheet(sheet: OpenSheet): void;
21
+ /** A prompt holds the screen, so sheets must not open over it without a person's action. */
22
+ export declare function sheetsYielded(): boolean;
23
+ /** Close top-down until unsaved work keeps a sheet open; undefined only clears the note. */
24
+ export declare function yieldSheets(note: string | undefined): void;
25
+ //#endregion
26
+ //# sourceMappingURL=NativeShellState.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeShellState.d.mts","names":[],"sources":["../../src/components/NativeShellState.tsx"],"mappings":";;;iBAKiB;EACf,MAAM;EACN;EACA;EACA;;qBAGW,oCAAkB,QAAA;qBAOlB,yCAAuB;EAAyB,MAAA;;iBAE5C;EACf;EACA;EACA,UAAU;;wBAOI,cAAc,OAAO;wBAIrB,gBAAgB,OAAO;;wBAMvB;;wBAKA,YAAY"}
@@ -0,0 +1,43 @@
1
+ import { createContext } from "react";
2
+
3
+ //#region src/components/NativeShellState.tsx
4
+ const MessageItemContext = createContext({
5
+ tone: "neutral",
6
+ expandable: false,
7
+ expanded: false,
8
+ toggle: () => void 0
9
+ });
10
+ const MessageItemGroupContext = createContext(null);
11
+ /** One shell-owned list across every downloaded UI module, oldest sheet first. */
12
+ const openSheets = [];
13
+ let yielded = false;
14
+ function registerSheet(sheet) {
15
+ if (!openSheets.includes(sheet)) openSheets.push(sheet);
16
+ }
17
+ function unregisterSheet(sheet) {
18
+ const index = openSheets.indexOf(sheet);
19
+ if (index >= 0) openSheets.splice(index, 1);
20
+ }
21
+ /** A prompt holds the screen, so sheets must not open over it without a person's action. */
22
+ function sheetsYielded() {
23
+ return yielded;
24
+ }
25
+ /** Close top-down until unsaved work keeps a sheet open; undefined only clears the note. */
26
+ function yieldSheets(note) {
27
+ yielded = note !== void 0;
28
+ if (note === void 0) {
29
+ for (const sheet of openSheets) sheet.setNote(void 0);
30
+ return;
31
+ }
32
+ for (let index = openSheets.length - 1; index >= 0; index -= 1) {
33
+ if (openSheets[index].keep()) {
34
+ for (const sheet of openSheets.slice(0, index + 1)) sheet.setNote(note);
35
+ return;
36
+ }
37
+ openSheets[index].close();
38
+ }
39
+ }
40
+
41
+ //#endregion
42
+ export { MessageItemContext, MessageItemGroupContext, registerSheet, sheetsYielded, unregisterSheet, yieldSheets };
43
+ //# sourceMappingURL=NativeShellState.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeShellState.mjs","names":[],"sources":["../../src/components/NativeShellState.tsx"],"sourcesContent":["import { createContext } from 'react';\n\nimport type { StatusTone } from './StatusBadge';\n\n/** State shared by shell-rendered timeline frames and downloaded tool content. */\nexport interface MessageItemState {\n tone: StatusTone;\n expandable: boolean;\n expanded: boolean;\n toggle: () => void;\n}\n\nexport const MessageItemContext = createContext<MessageItemState>({\n tone: 'neutral',\n expandable: false,\n expanded: false,\n toggle: () => undefined,\n});\n\nexport const MessageItemGroupContext = createContext<{ tone: StatusTone } | null>(null);\n\nexport interface OpenSheet {\n keep: () => boolean;\n close: () => void;\n setNote: (note: string | undefined) => void;\n}\n\n/** One shell-owned list across every downloaded UI module, oldest sheet first. */\nconst openSheets: OpenSheet[] = [];\nlet yielded = false;\n\nexport function registerSheet(sheet: OpenSheet): void {\n if (!openSheets.includes(sheet)) openSheets.push(sheet);\n}\n\nexport function unregisterSheet(sheet: OpenSheet): void {\n const index = openSheets.indexOf(sheet);\n if (index >= 0) openSheets.splice(index, 1);\n}\n\n/** A prompt holds the screen, so sheets must not open over it without a person's action. */\nexport function sheetsYielded(): boolean {\n return yielded;\n}\n\n/** Close top-down until unsaved work keeps a sheet open; undefined only clears the note. */\nexport function yieldSheets(note: string | undefined): void {\n yielded = note !== undefined;\n if (note === undefined) {\n for (const sheet of openSheets) sheet.setNote(undefined);\n return;\n }\n for (let index = openSheets.length - 1; index >= 0; index -= 1) {\n if (openSheets[index].keep()) {\n for (const sheet of openSheets.slice(0, index + 1)) sheet.setNote(note);\n return;\n }\n openSheets[index].close();\n }\n}\n"],"mappings":";;;AAYA,MAAa,qBAAqB,cAAgC;CAChE,MAAM;CACN,YAAY;CACZ,UAAU;CACV,cAAc;AAChB,CAAC;AAED,MAAa,0BAA0B,cAA2C,IAAI;;AAStF,MAAM,aAA0B,CAAC;AACjC,IAAI,UAAU;AAEd,SAAgB,cAAc,OAAwB;CACpD,IAAI,CAAC,WAAW,SAAS,KAAK,GAAG,WAAW,KAAK,KAAK;AACxD;AAEA,SAAgB,gBAAgB,OAAwB;CACtD,MAAM,QAAQ,WAAW,QAAQ,KAAK;CACtC,IAAI,SAAS,GAAG,WAAW,OAAO,OAAO,CAAC;AAC5C;;AAGA,SAAgB,gBAAyB;CACvC,OAAO;AACT;;AAGA,SAAgB,YAAY,MAAgC;CAC1D,UAAU,SAAS;CACnB,IAAI,SAAS,QAAW;EACtB,KAAK,MAAM,SAAS,YAAY,MAAM,QAAQ,MAAS;EACvD;CACF;CACA,KAAK,IAAI,QAAQ,WAAW,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;EAC9D,IAAI,WAAW,MAAM,CAAC,KAAK,GAAG;GAC5B,KAAK,MAAM,SAAS,WAAW,MAAM,GAAG,QAAQ,CAAC,GAAG,MAAM,QAAQ,IAAI;GACtE;EACF;EACA,WAAW,MAAM,CAAC,MAAM;CAC1B;AACF"}
@@ -1,5 +1,4 @@
1
1
  import { fontOf } from "../lib/fonts.mjs";
2
- import { InsideSheetContext } from "../lib/insideSheet.mjs";
3
2
  import { View } from "react-native-unistyles/components/native/View";
4
3
  import { Text } from "react-native-unistyles/components/native/Text";
5
4
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
@@ -7,39 +6,13 @@ import { BackHandler, Keyboard } from "react-native";
7
6
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
8
7
  import { useCallback, useContext, useEffect, useRef, useState } from "react";
9
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ import { InsideSheetContext, registerSheet, unregisterSheet } from "@agimon-ai/po-native-components/shell";
10
10
  import { BottomSheetBackdrop, BottomSheetFooter, BottomSheetModal, BottomSheetScrollView } from "@gorhom/bottom-sheet";
11
11
  import { SafeAreaInsetsContext } from "react-native-safe-area-context";
12
12
 
13
13
  //#region src/components/SheetFrame.tsx
14
14
  /** `bg-po-deep/70`, the overlay every web sheet and dialog draws. */
15
15
  const BACKDROP_ALPHA_PERCENT = 70;
16
- /** Presented sheets, oldest first: one opened from inside another sits after it. */
17
- const openSheets = [];
18
- let yielded = false;
19
- /** True while a prompt in the conversation holds the screen: a sheet should not open over it on its own. */
20
- function sheetsYielded() {
21
- return yielded;
22
- }
23
- /**
24
- * Clear the screen for a prompt in the conversation: close sheets from the top down, as a backdrop tap
25
- * would. The first sheet that keeps unsaved work stops the walk, and it and every sheet under it stay
26
- * open showing `note`, since closing a sheet also unmounts the sheets opened inside it. Undefined clears
27
- * the note and closes nothing.
28
- */
29
- function yieldSheets(note) {
30
- yielded = note !== void 0;
31
- if (note === void 0) {
32
- for (const sheet of openSheets) sheet.setNote(void 0);
33
- return;
34
- }
35
- for (let index = openSheets.length - 1; index >= 0; index -= 1) {
36
- if (openSheets[index].keep()) {
37
- for (const sheet of openSheets.slice(0, index + 1)) sheet.setNote(note);
38
- return;
39
- }
40
- openSheets[index].close();
41
- }
42
- }
43
16
  /**
44
17
  * The bottom sheet both Sheet and DropdownMenu sit in: a drag handle, sized
45
18
  * to its content, closed by dragging down, tapping the backdrop or Android
@@ -69,14 +42,13 @@ function SheetFrame({ open, onClose, children, scrollable = true, footer, keep =
69
42
  });
70
43
  useEffect(() => {
71
44
  openRef.current = open;
72
- const listed = openSheets.indexOf(entry.current);
73
45
  if (open) {
74
46
  presented.current = true;
75
- if (listed < 0) openSheets.push(entry.current);
47
+ registerSheet(entry.current);
76
48
  Keyboard.dismiss();
77
49
  sheet.current?.present();
78
50
  } else {
79
- if (listed >= 0) openSheets.splice(listed, 1);
51
+ unregisterSheet(entry.current);
80
52
  setNote(void 0);
81
53
  if (presented.current) {
82
54
  presented.current = false;
@@ -85,8 +57,7 @@ function SheetFrame({ open, onClose, children, scrollable = true, footer, keep =
85
57
  }
86
58
  }, [open]);
87
59
  useEffect(() => () => {
88
- const listed = openSheets.indexOf(entry.current);
89
- if (listed >= 0) openSheets.splice(listed, 1);
60
+ unregisterSheet(entry.current);
90
61
  }, []);
91
62
  useEffect(() => {
92
63
  if (!open) return void 0;
@@ -177,5 +148,5 @@ const styles = StyleSheet.create((theme) => ({
177
148
  }));
178
149
 
179
150
  //#endregion
180
- export { SheetFrame, sheetsYielded, yieldSheets };
151
+ export { SheetFrame };
181
152
  //# sourceMappingURL=SheetFrame.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SheetFrame.mjs","names":["withAlpha","BottomSheetBackdrop","BottomSheetBackdropProps","BottomSheetModal","BottomSheetFooter","BottomSheetFooterProps","BottomSheetScrollView","ReactNode","useCallback","useContext","useEffect","useRef","useState","BackHandler","Keyboard","SafeAreaInsetsContext","StyleSheet","useUnistyles","fontOf","InsideSheetContext","BACKDROP_ALPHA_PERCENT","SheetFrameProps","open","onClose","children","footer","scrollable","keep","OpenSheet","close","setNote","note","openSheets","yielded","sheetsYielded","yieldSheets","undefined","sheet","index","length","slice","SheetFrame","theme","insets","openRef","presented","footerHeight","setFooterHeight","latest","current","entry","listed","indexOf","push","dismiss","present","splice","subscription","addEventListener","remove","backdropColor","colors","deep","renderBackdrop","props","style","backgroundColor","renderFooter","event","nativeEvent","layout","height","paddingBottom","bottom","rail","top","footerComponent","borderRadius","lg","border","styles","content","SheetNote","create","flexGrow","marginHorizontal","spacing","marginBottom","color","magenta","fontFamily","sans","fontSize","sm","lineHeight","uni__dependencies"],"sources":["../../src/components/SheetFrame.tsx"],"sourcesContent":["import { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport {\n BottomSheetBackdrop,\n type BottomSheetBackdropProps,\n BottomSheetModal,\n BottomSheetFooter,\n type BottomSheetFooterProps,\n BottomSheetScrollView,\n} from '@gorhom/bottom-sheet';\nimport { type ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { BackHandler, Keyboard, Text, View } from 'react-native';\nimport { SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\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 footer?: ReactNode;\n /** False when the content supplies its own Gorhom virtualized scroll owner. */\n scrollable?: boolean;\n /** The sheet holds work not yet saved, so a prompt arriving leaves it open with a note instead of closing it. */\n keep?: boolean;\n}\n\ninterface OpenSheet {\n keep: () => boolean;\n close: () => void;\n setNote: (note: string | undefined) => void;\n}\n\n/** Presented sheets, oldest first: one opened from inside another sits after it. */\nconst openSheets: OpenSheet[] = [];\nlet yielded = false;\n\n/** True while a prompt in the conversation holds the screen: a sheet should not open over it on its own. */\nexport function sheetsYielded(): boolean {\n return yielded;\n}\n\n/**\n * Clear the screen for a prompt in the conversation: close sheets from the top down, as a backdrop tap\n * would. The first sheet that keeps unsaved work stops the walk, and it and every sheet under it stay\n * open showing `note`, since closing a sheet also unmounts the sheets opened inside it. Undefined clears\n * the note and closes nothing.\n */\nexport function yieldSheets(note: string | undefined) {\n yielded = note !== undefined;\n if (note === undefined) {\n for (const sheet of openSheets) sheet.setNote(undefined);\n return;\n }\n for (let index = openSheets.length - 1; index >= 0; index -= 1) {\n if (openSheets[index].keep()) {\n for (const sheet of openSheets.slice(0, index + 1)) sheet.setNote(note);\n return;\n }\n openSheets[index].close();\n }\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, footer, keep = false }: 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 const [footerHeight, setFooterHeight] = useState(0);\n const [note, setNote] = useState<string>();\n const latest = useRef({ keep, onClose });\n latest.current = { keep, onClose };\n const entry = useRef<OpenSheet>({\n keep: () => latest.current.keep,\n close: () => latest.current.onClose(),\n setNote,\n });\n\n useEffect(() => {\n openRef.current = open;\n const listed = openSheets.indexOf(entry.current);\n if (open) {\n presented.current = true;\n if (listed < 0) openSheets.push(entry.current);\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 {\n if (listed >= 0) openSheets.splice(listed, 1);\n setNote(undefined);\n 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 }\n }, [open]);\n\n useEffect(\n () => () => {\n const listed = openSheets.indexOf(entry.current);\n if (listed >= 0) openSheets.splice(listed, 1);\n },\n [],\n );\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 const renderFooter = useCallback(\n (props: BottomSheetFooterProps) => (\n <BottomSheetFooter {...props}>\n <View\n onLayout={(event) => setFooterHeight(event.nativeEvent.layout.height)}\n style={{ paddingBottom: insets?.bottom ?? 0, backgroundColor: theme.colors.rail }}\n >\n <InsideSheetContext.Provider value>{footer}</InsideSheetContext.Provider>\n </View>\n </BottomSheetFooter>\n ),\n [footer, insets?.bottom, theme.colors.rail],\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 {...(footer === undefined ? {} : { footerComponent: renderFooter })}\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={[\n styles.content,\n { paddingBottom: footer === undefined ? (insets?.bottom ?? 0) : footerHeight },\n ]}\n >\n {note ? <SheetNote note={note} /> : null}\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </BottomSheetScrollView>\n ) : (\n <>\n {note ? <SheetNote note={note} /> : null}\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </>\n )}\n </BottomSheetModal>\n );\n}\n\n/** A gentle rose line: the person is asked something below, never told to hurry. */\nfunction SheetNote({ note }: { note: string }) {\n return (\n <Text style={styles.note} accessibilityRole=\"alert\">\n {note}\n </Text>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n content: { flexGrow: 1 },\n note: {\n marginHorizontal: theme.spacing(4),\n marginBottom: theme.spacing(2),\n color: theme.colors.magenta,\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":"SheetFrame.mjs","names":["InsideSheetContext","OpenSheet","registerSheet","unregisterSheet","withAlpha","BottomSheetBackdrop","BottomSheetBackdropProps","BottomSheetModal","BottomSheetFooter","BottomSheetFooterProps","BottomSheetScrollView","ReactNode","useCallback","useContext","useEffect","useRef","useState","BackHandler","Keyboard","SafeAreaInsetsContext","StyleSheet","useUnistyles","fontOf","BACKDROP_ALPHA_PERCENT","SheetFrameProps","open","onClose","children","footer","scrollable","keep","sheetsYielded","yieldSheets","SheetFrame","theme","insets","sheet","openRef","presented","footerHeight","setFooterHeight","note","setNote","latest","current","entry","close","dismiss","present","undefined","subscription","addEventListener","remove","backdropColor","colors","deep","renderBackdrop","props","style","backgroundColor","renderFooter","event","nativeEvent","layout","height","paddingBottom","bottom","rail","top","footerComponent","borderRadius","lg","border","styles","content","SheetNote","create","flexGrow","marginHorizontal","spacing","marginBottom","color","magenta","fontFamily","sans","fontSize","sm","lineHeight","uni__dependencies"],"sources":["../../src/components/SheetFrame.tsx"],"sourcesContent":["import {\n InsideSheetContext,\n type OpenSheet,\n registerSheet,\n unregisterSheet,\n} from '@agimon-ai/po-native-components/shell';\nimport { withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport {\n BottomSheetBackdrop,\n type BottomSheetBackdropProps,\n BottomSheetModal,\n BottomSheetFooter,\n type BottomSheetFooterProps,\n BottomSheetScrollView,\n} from '@gorhom/bottom-sheet';\nimport { type ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { BackHandler, Keyboard, Text, View } from 'react-native';\nimport { SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\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 footer?: ReactNode;\n /** False when the content supplies its own Gorhom virtualized scroll owner. */\n scrollable?: boolean;\n /** The sheet holds work not yet saved, so a prompt arriving leaves it open with a note instead of closing it. */\n keep?: boolean;\n}\n\nexport { sheetsYielded, yieldSheets } from '@agimon-ai/po-native-components/shell';\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, footer, keep = false }: 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 const [footerHeight, setFooterHeight] = useState(0);\n const [note, setNote] = useState<string>();\n const latest = useRef({ keep, onClose });\n latest.current = { keep, onClose };\n const entry = useRef<OpenSheet>({\n keep: () => latest.current.keep,\n close: () => latest.current.onClose(),\n setNote,\n });\n\n useEffect(() => {\n openRef.current = open;\n if (open) {\n presented.current = true;\n registerSheet(entry.current);\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 {\n unregisterSheet(entry.current);\n setNote(undefined);\n 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 }\n }, [open]);\n\n useEffect(\n () => () => {\n unregisterSheet(entry.current);\n },\n [],\n );\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 const renderFooter = useCallback(\n (props: BottomSheetFooterProps) => (\n <BottomSheetFooter {...props}>\n <View\n onLayout={(event) => setFooterHeight(event.nativeEvent.layout.height)}\n style={{ paddingBottom: insets?.bottom ?? 0, backgroundColor: theme.colors.rail }}\n >\n <InsideSheetContext.Provider value>{footer}</InsideSheetContext.Provider>\n </View>\n </BottomSheetFooter>\n ),\n [footer, insets?.bottom, theme.colors.rail],\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 {...(footer === undefined ? {} : { footerComponent: renderFooter })}\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={[\n styles.content,\n { paddingBottom: footer === undefined ? (insets?.bottom ?? 0) : footerHeight },\n ]}\n >\n {note ? <SheetNote note={note} /> : null}\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </BottomSheetScrollView>\n ) : (\n <>\n {note ? <SheetNote note={note} /> : null}\n <InsideSheetContext.Provider value>{children}</InsideSheetContext.Provider>\n </>\n )}\n </BottomSheetModal>\n );\n}\n\n/** A gentle rose line: the person is asked something below, never told to hurry. */\nfunction SheetNote({ note }: { note: string }) {\n return (\n <Text style={styles.note} accessibilityRole=\"alert\">\n {note}\n </Text>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n content: { flexGrow: 1 },\n note: {\n marginHorizontal: theme.spacing(4),\n marginBottom: theme.spacing(2),\n color: theme.colors.magenta,\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,9 +1,9 @@
1
- import { IconColorContext } from "./IconColorContext.mjs";
2
1
  import { ICON_GLYPHS } from "./iconGlyphs.mjs";
3
2
  import { useUnistyles } from "react-native-unistyles";
4
3
  import { Platform } from "react-native";
5
4
  import { useContext } from "react";
6
5
  import { jsx } from "react/jsx-runtime";
6
+ import { IconColorContext } from "@agimon-ai/po-native-components/shell";
7
7
  import MaterialIcons from "@expo/vector-icons/MaterialIcons";
8
8
  import { SymbolView } from "expo-symbols";
9
9
 
@@ -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","MenuIcon","EditIcon","GearIcon","SendIcon","TaskIcon","TrashIcon","WrenchIcon","CloseIcon","FolderIcon","GlobeIcon","BranchIcon","ForkIcon","HomeIcon","ActivityIcon","ArrowRightIcon","PlusIcon","UserIcon","UsersIcon","PlayCircleIcon","WorkflowIcon","PaletteIcon","LightbulbIcon","SparklesIcon","LockIcon","ShieldIcon","FileIcon","SearchIcon","ImageIcon","SlidersIcon","DownloadIcon","MicIcon","AudioLinesIcon","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 MenuIcon = createIcon('Menu');\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 UserIcon = createIcon('User');\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');\nexport const ShieldIcon = createIcon('Shield');\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 AudioLinesIcon = createIcon('AudioLines');\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,WAAWjC,WAAW,MAAM;AACzC,MAAakC,YAAYlC,WAAW,OAAO;AAC3C,MAAamC,aAAanC,WAAW,QAAQ;AAC7C,MAAaoC,YAAYpC,WAAW,OAAO;AAC3C,MAAaqC,aAAarC,WAAW,QAAQ;AAC7C,MAAasC,YAAYtC,WAAW,OAAO;AAC3C,MAAauC,aAAavC,WAAW,QAAQ;AAC7C,MAAawC,WAAWxC,WAAW,MAAM;AACzC,MAAayC,WAAWzC,WAAW,MAAM;AACzC,MAAa0C,eAAe1C,WAAW,UAAU;AACjD,MAAa2C,iBAAiB3C,WAAW,YAAY;AACrD,MAAa4C,WAAW5C,WAAW,MAAM;AACzC,MAAa6C,WAAW7C,WAAW,MAAM;AACzC,MAAa8C,YAAY9C,WAAW,OAAO;AAC3C,MAAa+C,iBAAiB/C,WAAW,YAAY;AACrD,MAAagD,eAAehD,WAAW,UAAU;AACjD,MAAaiD,cAAcjD,WAAW,SAAS;AAC/C,MAAakD,gBAAgBlD,WAAW,WAAW;AACnD,MAAamD,eAAenD,WAAW,UAAU;AACjD,MAAaoD,WAAWpD,WAAW,MAAM;AACzC,MAAaqD,aAAarD,WAAW,QAAQ;AAE7C,MAAasD,WAAWtD,WAAW,MAAM;AACzC,MAAauD,aAAavD,WAAW,QAAQ;AAC7C,MAAawD,YAAYxD,WAAW,OAAO;AAC3C,MAAayD,cAAczD,WAAW,SAAS;AAC/C,MAAa0D,eAAe1D,WAAW,UAAU;AACjD,MAAa2D,UAAU3D,WAAW,KAAK;AACvC,MAAa4D,iBAAiB5D,WAAW,YAAY;AACrD,MAAa6D,WAAW7D,WAAW,MAAM"}
1
+ {"version":3,"file":"icons.mjs","names":["IconColorContext","NativeColorToken","MaterialIcons","SymbolView","useContext","Platform","StyleProp","ViewStyle","useUnistyles","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","MenuIcon","EditIcon","GearIcon","SendIcon","TaskIcon","TrashIcon","WrenchIcon","CloseIcon","FolderIcon","GlobeIcon","BranchIcon","ForkIcon","HomeIcon","ActivityIcon","ArrowRightIcon","PlusIcon","UserIcon","UsersIcon","PlayCircleIcon","WorkflowIcon","PaletteIcon","LightbulbIcon","SparklesIcon","LockIcon","ShieldIcon","FileIcon","SearchIcon","ImageIcon","SlidersIcon","DownloadIcon","MicIcon","AudioLinesIcon","StopIcon"],"sources":["../../src/icons/icons.tsx"],"sourcesContent":["import { IconColorContext } from '@agimon-ai/po-native-components/shell';\nimport 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 { 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 MenuIcon = createIcon('Menu');\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 UserIcon = createIcon('User');\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');\nexport const ShieldIcon = createIcon('Shield');\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 AudioLinesIcon = createIcon('AudioLines');\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,UAAUd,aAAa;EAC/B,MAAMe,YAAYnB,WAAWJ,gBAAgB;EAC7C,MAAMwB,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,IAAIX,SAAS4B,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,WAAWjC,WAAW,MAAM;AACzC,MAAakC,YAAYlC,WAAW,OAAO;AAC3C,MAAamC,aAAanC,WAAW,QAAQ;AAC7C,MAAaoC,YAAYpC,WAAW,OAAO;AAC3C,MAAaqC,aAAarC,WAAW,QAAQ;AAC7C,MAAasC,YAAYtC,WAAW,OAAO;AAC3C,MAAauC,aAAavC,WAAW,QAAQ;AAC7C,MAAawC,WAAWxC,WAAW,MAAM;AACzC,MAAayC,WAAWzC,WAAW,MAAM;AACzC,MAAa0C,eAAe1C,WAAW,UAAU;AACjD,MAAa2C,iBAAiB3C,WAAW,YAAY;AACrD,MAAa4C,WAAW5C,WAAW,MAAM;AACzC,MAAa6C,WAAW7C,WAAW,MAAM;AACzC,MAAa8C,YAAY9C,WAAW,OAAO;AAC3C,MAAa+C,iBAAiB/C,WAAW,YAAY;AACrD,MAAagD,eAAehD,WAAW,UAAU;AACjD,MAAaiD,cAAcjD,WAAW,SAAS;AAC/C,MAAakD,gBAAgBlD,WAAW,WAAW;AACnD,MAAamD,eAAenD,WAAW,UAAU;AACjD,MAAaoD,WAAWpD,WAAW,MAAM;AACzC,MAAaqD,aAAarD,WAAW,QAAQ;AAE7C,MAAasD,WAAWtD,WAAW,MAAM;AACzC,MAAauD,aAAavD,WAAW,QAAQ;AAC7C,MAAawD,YAAYxD,WAAW,OAAO;AAC3C,MAAayD,cAAczD,WAAW,SAAS;AAC/C,MAAa0D,eAAe1D,WAAW,UAAU;AACjD,MAAa2D,UAAU3D,WAAW,KAAK;AACvC,MAAa4D,iBAAiB5D,WAAW,YAAY;AACrD,MAAa6D,WAAW7D,WAAW,MAAM"}
package/dist/index.d.mts CHANGED
@@ -13,16 +13,13 @@ import { HashlineLines, HashlineLinesProps } from "./components/HashlineLines.mj
13
13
  import { FieldSize, FieldVariant, Input, InputProps } from "./components/Input.mjs";
14
14
  import { Label, LabelProps } from "./components/Label.mjs";
15
15
  import { List, ListProps, ListRow, ListRowProps } from "./components/List.mjs";
16
- import { LiveDuration, LiveDurationProps, LiveDurationReading } from "./components/LiveDuration.mjs";
17
16
  import { FileLinkHandler, Markdown, MarkdownImageLoader, MarkdownProps } from "./components/Markdown.mjs";
18
17
  import { STATUS_EDGE, StatusBadge, StatusBadgeProps, StatusBadgeSize, StatusTone } from "./components/StatusBadge.mjs";
19
18
  import { MessageItem, MessageItemBody, MessageItemGroup, MessageItemGroupProps, MessageItemHeader, MessageItemHeaderProps, MessageItemPartProps, MessageItemProps, MessageItemState, MessageItemStatus, MessageItemStatusProps, STATUS_GLYPH, STATUS_LABEL, toolTone, useMessageItem } from "./components/MessageItem.mjs";
20
19
  import { Panel, PanelBody, PanelHeader, PanelPartProps } from "./components/Panel.mjs";
21
- import { PoNativeProvider, PoNativeProviderProps } from "./components/PoNativeProvider.mjs";
22
20
  import { SectionLabel } from "./components/SectionLabel.mjs";
23
21
  import { SegmentedControl, SegmentedControlOption, SegmentedControlProps } from "./components/SegmentedControl.mjs";
24
22
  import { Sheet, SheetBody, SheetClose, SheetContent, SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetHeaderProps, SheetPartProps, SheetProps, SheetTitle, SheetTrigger } from "./components/Sheet.mjs";
25
- import { sheetsYielded, yieldSheets } from "./components/SheetFrame.mjs";
26
23
  import { SheetList, SheetListProps } from "./components/SheetList.mjs";
27
24
  import { ShowMore, ShowMoreProps } from "./components/ShowMore.mjs";
28
25
  import { Spinner, SpinnerProps } from "./components/Spinner.mjs";
@@ -33,10 +30,10 @@ import { ToolPathLink, ToolPathLinkProps } from "./components/ToolPathLink.mjs";
33
30
  import { ActivityIcon, AlertIcon, ArrowRightIcon, AudioLinesIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HomeIcon, IconProps, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MenuIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, ShieldIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
34
31
  import { IconName } from "./icons/iconGlyphs.mjs";
35
32
  import { fontOf } from "./lib/fonts.mjs";
36
- import { IconColorContext } from "./icons/IconColorContext.mjs";
37
33
  import { impactLight, selectionTick } from "./lib/haptics.mjs";
38
34
  import { HostFilter, HostFilterProps } from "./components/HostFilter.mjs";
39
35
  import { HostTag } from "./components/HostTag.mjs";
40
36
  import { InfoStrip } from "./components/InfoStrip.mjs";
41
37
  import { AnsiSpan, PresentedLine, ReviewComment, ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
38
+ import { IconColorContext, LiveDuration, LiveDurationProps, LiveDurationReading, PoNativeProvider, PoNativeProviderProps, sheetsYielded, yieldSheets } from "@agimon-ai/po-native-components/shell";
42
39
  export { ActivityIcon, AgentAvatar, type AgentState, AlertIcon, type AnnotationMark, AnnotationSurface, type AnnotationSurfaceProps, type AnsiSpan, ArrowRightIcon, AudioLinesIcon, 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, CountBadge, type CountBadgeProps, 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, HostFilter, type HostFilterProps, HostTag, IconColorContext, type IconName, type IconProps, ImageIcon, InfoStrip, Input, type InputProps, KebabIcon, Label, type LabelProps, LightbulbIcon, List, type ListProps, ListRow, type ListRowProps, LiveDuration, type LiveDurationProps, type LiveDurationReading, LockIcon, Markdown, type MarkdownImageLoader, type MarkdownProps, MenuIcon, 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, ShieldIcon, 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, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, sheetsYielded, toolTone, useMessageItem, useSyntaxLines, yieldSheets };
package/dist/index.mjs CHANGED
@@ -4,7 +4,6 @@ import { AgentAvatar, agentInitials } from "./components/AgentAvatar.mjs";
4
4
  import { impactLight, selectionTick } from "./lib/haptics.mjs";
5
5
  import { AnnotationSurface } from "./components/AnnotationSurface.mjs";
6
6
  import { Badge } from "./components/Badge.mjs";
7
- import { IconColorContext } from "./icons/IconColorContext.mjs";
8
7
  import { Spinner } from "./components/Spinner.mjs";
9
8
  import { Button } from "./components/Button.mjs";
10
9
  import { ActivityIcon, AlertIcon, ArrowRightIcon, AudioLinesIcon, BranchIcon, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CopyIcon, DownloadIcon, EditIcon, FileIcon, FolderIcon, ForkIcon, GearIcon, GlobeIcon, HomeIcon, ImageIcon, KebabIcon, LightbulbIcon, LockIcon, MenuIcon, MessageIcon, MicIcon, PaletteIcon, PlayCircleIcon, PlusIcon, SearchIcon, SendIcon, ShieldIcon, SlidersIcon, SparklesIcon, StopIcon, TaskIcon, TrashIcon, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon } from "./icons/icons.mjs";
@@ -13,7 +12,6 @@ import { ShowMore } from "./components/ShowMore.mjs";
13
12
  import { CodeBlock } from "./components/CodeBlock.mjs";
14
13
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./components/Dialog.mjs";
15
14
  import { CountBadge } from "./components/CountBadge.mjs";
16
- import { sheetsYielded, yieldSheets } from "./components/SheetFrame.mjs";
17
15
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger } from "./components/DropdownMenu.mjs";
18
16
  import { EmptyState } from "./components/EmptyState.mjs";
19
17
  import { SyntaxLine, useSyntaxLines } from "./components/SyntaxLine.mjs";
@@ -21,12 +19,10 @@ import { HashlineLines } from "./components/HashlineLines.mjs";
21
19
  import { Input } from "./components/Input.mjs";
22
20
  import { Label } from "./components/Label.mjs";
23
21
  import { List, ListRow } from "./components/List.mjs";
24
- import { LiveDuration } from "./components/LiveDuration.mjs";
25
22
  import { Markdown } from "./components/Markdown.mjs";
26
23
  import { STATUS_EDGE, StatusBadge } from "./components/StatusBadge.mjs";
27
24
  import { MessageItem, MessageItemBody, MessageItemGroup, MessageItemHeader, MessageItemStatus, STATUS_GLYPH, STATUS_LABEL, toolTone, useMessageItem } from "./components/MessageItem.mjs";
28
25
  import { Panel, PanelBody, PanelHeader } from "./components/Panel.mjs";
29
- import { PoNativeProvider } from "./components/PoNativeProvider.mjs";
30
26
  import { SectionLabel } from "./components/SectionLabel.mjs";
31
27
  import { SegmentedControl } from "./components/SegmentedControl.mjs";
32
28
  import { Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "./components/Sheet.mjs";
@@ -38,5 +34,6 @@ import { HostFilter } from "./components/HostFilter.mjs";
38
34
  import { HostTag } from "./components/HostTag.mjs";
39
35
  import { InfoStrip } from "./components/InfoStrip.mjs";
40
36
  import { ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
37
+ import { IconColorContext, LiveDuration, PoNativeProvider, sheetsYielded, yieldSheets } from "@agimon-ai/po-native-components/shell";
41
38
 
42
39
  export { ActivityIcon, AgentAvatar, AlertIcon, AnnotationSurface, ArrowRightIcon, AudioLinesIcon, Badge, BranchIcon, Button, CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, CloseIcon, CodeBlock, CopyButton, CopyIcon, CountBadge, 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, HostFilter, HostTag, IconColorContext, ImageIcon, InfoStrip, Input, KebabIcon, Label, LightbulbIcon, List, ListRow, LiveDuration, LockIcon, Markdown, MenuIcon, 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, ShieldIcon, ShowMore, SlidersIcon, SparklesIcon, Spinner, StatusBadge, StopIcon, SyntaxLine, TabBadge, Tabs, TabsContent, TabsList, TabsTrigger, TaskIcon, Textarea, ToolPathLink, TrashIcon, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, sheetsYielded, toolTone, useMessageItem, useSyntaxLines, yieldSheets };
@@ -0,0 +1,10 @@
1
+ //#region src/lib/insideSheet.d.ts
2
+ /**
3
+ * Whether the caller renders inside a bottom sheet. A sheet's text field has
4
+ * to be the bottom sheet's own TextInput, or the keyboard covers it and the
5
+ * sheet never moves; Input reads this instead of asking callers to pick.
6
+ */
7
+ export declare const InsideSheetContext: import("react").Context<boolean>;
8
+ export declare function useInsideSheet(): boolean;
9
+ //#endregion
10
+ //# sourceMappingURL=insideSheet.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insideSheet.d.mts","names":[],"sources":["../../src/lib/insideSheet.ts"],"mappings":";;;;;;qBAOa,oCAAkB;wBAEf"}
@@ -0,0 +1,6 @@
1
+ import { LiveDuration, LiveDurationProps, LiveDurationReading } from "./components/LiveDuration.mjs";
2
+ import { MessageItemContext, MessageItemGroupContext, MessageItemState, OpenSheet, registerSheet, sheetsYielded, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
3
+ import { PoNativeProvider, PoNativeProviderProps } from "./components/PoNativeProvider.mjs";
4
+ import { IconColorContext } from "./icons/IconColorContext.mjs";
5
+ import { InsideSheetContext, useInsideSheet } from "./lib/insideSheet.mjs";
6
+ export { IconColorContext, InsideSheetContext, LiveDuration, type LiveDurationProps, type LiveDurationReading, MessageItemContext, MessageItemGroupContext, type MessageItemState, type OpenSheet, PoNativeProvider, type PoNativeProviderProps, registerSheet, sheetsYielded, unregisterSheet, useInsideSheet, yieldSheets };
package/dist/shell.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import { LiveDuration } from "./components/LiveDuration.mjs";
2
+ import { MessageItemContext, MessageItemGroupContext, registerSheet, sheetsYielded, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
3
+ import { PoNativeProvider } from "./components/PoNativeProvider.mjs";
4
+ import { IconColorContext } from "./icons/IconColorContext.mjs";
5
+ import { InsideSheetContext, useInsideSheet } from "./lib/insideSheet.mjs";
6
+
7
+ export { IconColorContext, InsideSheetContext, LiveDuration, MessageItemContext, MessageItemGroupContext, PoNativeProvider, registerSheet, sheetsYielded, unregisterSheet, useInsideSheet, yieldSheets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-native-components",
3
- "version": "0.0.0-alpha.77",
3
+ "version": "0.0.0-alpha.79",
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",
@@ -39,17 +39,21 @@
39
39
  "types": "./dist/index.d.mts",
40
40
  "default": "./dist/index.mjs"
41
41
  },
42
+ "./shell": {
43
+ "types": "./dist/shell.d.mts",
44
+ "default": "./dist/shell.mjs"
45
+ },
42
46
  "./package.json": "./package.json"
43
47
  },
44
48
  "publishConfig": {
45
49
  "access": "public"
46
50
  },
47
51
  "dependencies": {
48
- "@agimon-ai/po-web-components": "0.0.0-alpha.77"
52
+ "@agimon-ai/po-web-components": "0.0.0-alpha.79"
49
53
  },
50
54
  "devDependencies": {
51
- "@agimon-ai/po-build": "0.0.0-alpha.77",
52
- "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.77",
55
+ "@agimon-ai/po-build": "0.0.0-alpha.79",
56
+ "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.79",
53
57
  "@babel/core": "7.29.7",
54
58
  "@expo/vector-icons": "15.1.1",
55
59
  "@fontsource-variable/ibm-plex-sans": "5.3.0",
@@ -1,13 +0,0 @@
1
- import { ReactNode } from "react";
2
- //#region src/components/SheetFrame.d.ts
3
- /** True while a prompt in the conversation holds the screen: a sheet should not open over it on its own. */
4
- export declare function sheetsYielded(): boolean;
5
- /**
6
- * Clear the screen for a prompt in the conversation: close sheets from the top down, as a backdrop tap
7
- * would. The first sheet that keeps unsaved work stops the walk, and it and every sheet under it stay
8
- * open showing `note`, since closing a sheet also unmounts the sheets opened inside it. Undefined clears
9
- * the note and closes nothing.
10
- */
11
- export declare function yieldSheets(note: string | undefined): void;
12
- //#endregion
13
- //# sourceMappingURL=SheetFrame.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SheetFrame.d.mts","names":[],"sources":["../../src/components/SheetFrame.tsx"],"mappings":";;;wBA2CgB;;;;;;;wBAUA,YAAY"}