@agimon-ai/po-native-components 0.0.0-alpha.80 → 0.0.0-alpha.81

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.
@@ -14,9 +14,11 @@ export declare function DropdownMenu({ open, defaultOpen, onOpenChange, children
14
14
  export declare function DropdownMenuTrigger({ onPress, accessibilityState, ...props }: ButtonProps): import("react").JSX.Element;
15
15
  export interface DropdownMenuContentProps {
16
16
  children?: ReactNode;
17
+ /** The native sheet has finished dismissing, including its closing animation. */
18
+ onDismiss?: () => void;
17
19
  }
18
20
  /** The action list, in a bottom sheet. */
19
- export declare function DropdownMenuContent({ children }: DropdownMenuContentProps): import("react").JSX.Element;
21
+ export declare function DropdownMenuContent({ children, onDismiss }: DropdownMenuContentProps): import("react").JSX.Element;
20
22
  export interface DropdownMenuPartProps extends Omit<ViewProps, 'children' | 'style'> {
21
23
  children?: ReactNode;
22
24
  style?: StyleProp<ViewStyle>;
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.d.mts","names":[],"sources":["../../src/components/DropdownMenu.tsx"],"mappings":";;;;iBAyCiB;;EAEf;EACA;EACA,gBAAgB;EAChB,WAAW;;wBAGG,eAAe,MAAM,aAAqB,cAAc,YAAY,oCAAiB,IAAA;;wBAMrF,sBAAsB,SAAS,uBAAuB,SAAS,8BAAW,IAAA;iBAczE;EACf,WAAW;;;wBAIG,sBAAsB,YAAY,2CAAwB,IAAA;iBAazD,8BAA8B,KAAK;EAClD,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,oBAAoB,aAAa,SAAS,wCAAqB,IAAA;YAInE;iBAEK;EACf,UAAU;;EAEV;EACA;;EAEA;;EAEA,WAAW;EACX,QAAQ,UAAU;;wBA8CJ,iBAAiB,OAAO,wCAAqB,IAAA;iBAI5C,sCAAsC,KAAK;EAC1D;EACA,mBAAmB;;;wBAIL,2BACd,SACA,iBACA,aACG,SACF,gDAA6B,IAAA;iBAef,oCAAoC;EACnD;EACA,iBAAiB;;;wBAIH,yBAAyB,OAAO,eAAe,aAAa,SAAS,8CAA2B,IAAA;iBAU/F,mCAAmC,KAAK;EACvD;;wBAGc,wBAAwB,OAAO,aAAa,SAAS,6CAA0B,IAAA;;wBAkB/E,oBAAoB,OAAO,aAAa,SAAS,4BAAS,IAAA;;wBAU1D,uBAAuB,UAAU,SAAS,4BAAS,IAAA;wBAInD,wBAAwB;EAAW,QAAQ,UAAU;oBAAY,IAAA"}
1
+ {"version":3,"file":"DropdownMenu.d.mts","names":[],"sources":["../../src/components/DropdownMenu.tsx"],"mappings":";;;;iBAyCiB;;EAEf;EACA;EACA,gBAAgB;EAChB,WAAW;;wBAGG,eAAe,MAAM,aAAqB,cAAc,YAAY,oCAAiB,IAAA;;wBAMrF,sBAAsB,SAAS,uBAAuB,SAAS,8BAAW,IAAA;iBAczE;EACf,WAAW;;EAEX;;;wBAIc,sBAAsB,UAAU,aAAa,2CAAwB,IAAA;iBAapE,8BAA8B,KAAK;EAClD,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,oBAAoB,aAAa,SAAS,wCAAqB,IAAA;YAInE;iBAEK;EACf,UAAU;;EAEV;EACA;;EAEA;;EAEA,WAAW;EACX,QAAQ,UAAU;;wBA8CJ,iBAAiB,OAAO,wCAAqB,IAAA;iBAI5C,sCAAsC,KAAK;EAC1D;EACA,mBAAmB;;;wBAIL,2BACd,SACA,iBACA,aACG,SACF,gDAA6B,IAAA;iBAef,oCAAoC;EACnD;EACA,iBAAiB;;;wBAIH,yBAAyB,OAAO,eAAe,aAAa,SAAS,8CAA2B,IAAA;iBAU/F,mCAAmC,KAAK;EACvD;;wBAGc,wBAAwB,OAAO,aAAa,SAAS,6CAA0B,IAAA;;wBAkB/E,oBAAoB,OAAO,aAAa,SAAS,4BAAS,IAAA;;wBAU1D,uBAAuB,UAAU,SAAS,4BAAS,IAAA;wBAInD,wBAAwB;EAAW,QAAQ,UAAU;oBAAY,IAAA"}
@@ -52,11 +52,12 @@ function DropdownMenuTrigger({ onPress, accessibilityState, ...props }) {
52
52
  });
53
53
  }
54
54
  /** The action list, in a bottom sheet. */
55
- function DropdownMenuContent({ children }) {
55
+ function DropdownMenuContent({ children, onDismiss }) {
56
56
  const { open, setOpen } = useContext(MenuContext);
57
57
  return /* @__PURE__ */ jsx(SheetFrame, {
58
58
  open,
59
59
  onClose: () => setOpen(false),
60
+ onDismiss,
60
61
  children: /* @__PURE__ */ jsx(MenuContext.Provider, {
61
62
  value: {
62
63
  open,
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.mjs","names":["createContext","ReactNode","useContext","StyleProp","TextProps","ViewProps","ViewStyle","StyleSheet","CheckIcon","fontOf","selectionTick","useControllable","wrapText","Button","ButtonProps","SheetFrame","INDICATOR_GUTTER","MIN_ROW_HEIGHT","DISABLED_OPACITY","RADIO_DOT","MenuState","open","setOpen","MenuContext","undefined","RadioState","value","onValueChange","RadioContext","DropdownMenuProps","defaultOpen","onOpenChange","children","DropdownMenu","current","DropdownMenuTrigger","onPress","accessibilityState","props","expanded","event","DropdownMenuContentProps","DropdownMenuContent","styles","content","DropdownMenuPartProps","Omit","style","DropdownMenuGroup","DropdownMenuItemVariant","DropdownMenuItemProps","variant","indented","disabled","onSelect","ItemRowProps","role","checked","indicator","ItemRow","_styles","useVariants","pressed","item","label","DropdownMenuItem","DropdownMenuCheckboxItemProps","onCheckedChange","DropdownMenuCheckboxItem","DropdownMenuRadioGroupProps","DropdownMenuRadioGroup","DropdownMenuRadioItemProps","DropdownMenuRadioItem","radio","radioDot","DropdownMenuLabel","charAt","toUpperCase","slice","menuLabel","DropdownMenuShortcut","shortcut","DropdownMenuSeparator","separator","create","theme","paddingVertical","spacing","uni__dependencies","flexDirection","alignItems","gap","minHeight","paddingHorizontal","paddingLeft","position","left","width","height","justifyContent","borderRadius","full","backgroundColor","colors","blue","deep","opacity","flexShrink","fontFamily","sans","fontSize","base","lineHeight","variants","default","color","hi","destructive","red","dim","sm","fontWeight","semibold","marginLeft","marginVertical"],"sources":["../../src/components/DropdownMenu.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } 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 { CheckIcon } from '../icons/icons';\nimport { fontOf } from '../lib/fonts';\nimport { selectionTick } from '../lib/haptics';\nimport { useControllable } from '../lib/useControllable';\nimport { wrapText } from '../lib/wrapText';\nimport { Button, type ButtonProps } from './Button';\nimport { SheetFrame } from './SheetFrame';\n\n/*\n * The web DropdownMenu as an action sheet: the same items rise in a bottom\n * sheet, each a full-width 44pt row, choosing one ticks once and closes the\n * menu, and destructive rows are red.\n *\n * ponytail: submenus are not ported; a native action list nests by opening a\n * second menu from an item.\n */\n\n/** A row that carries a check or bullet keeps a gutter for it, so labels line up whether or not one is set. */\nconst INDICATOR_GUTTER = 28;\nconst MIN_ROW_HEIGHT = 44;\nconst DISABLED_OPACITY = 0.4;\nconst RADIO_DOT = 6;\n\ninterface MenuState {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nconst MenuContext = createContext<MenuState>({ open: false, setOpen: () => undefined });\n\ninterface RadioState {\n value: string | undefined;\n onValueChange: ((value: string) => void) | undefined;\n}\n\nconst RadioContext = createContext<RadioState>({ value: undefined, onValueChange: undefined });\n\nexport interface DropdownMenuProps {\n /** Controlled mode; pair with onOpenChange. Omit it and the menu keeps its own state. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\nexport function DropdownMenu({ open, defaultOpen = false, onOpenChange, children }: DropdownMenuProps) {\n const [current, setOpen] = useControllable(open, defaultOpen, onOpenChange);\n return <MenuContext.Provider value={{ open: current, setOpen }}>{children}</MenuContext.Provider>;\n}\n\n/** A Button that opens the menu; announces that it opens a menu. */\nexport function DropdownMenuTrigger({ onPress, accessibilityState, ...props }: ButtonProps) {\n const { open, setOpen } = useContext(MenuContext);\n return (\n <Button\n accessibilityState={{ ...accessibilityState, expanded: open }}\n onPress={(event) => {\n onPress?.(event);\n setOpen(true);\n }}\n {...props}\n />\n );\n}\n\nexport interface DropdownMenuContentProps {\n children?: ReactNode;\n}\n\n/** The action list, in a bottom sheet. */\nexport function DropdownMenuContent({ children }: DropdownMenuContentProps) {\n const { open, setOpen } = useContext(MenuContext);\n return (\n <SheetFrame open={open} onClose={() => setOpen(false)}>\n <MenuContext.Provider value={{ open, setOpen }}>\n <View accessibilityRole=\"menu\" style={styles.content}>\n {children}\n </View>\n </MenuContext.Provider>\n </SheetFrame>\n );\n}\n\nexport interface DropdownMenuPartProps extends Omit<ViewProps, 'children' | 'style'> {\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** A run of items under one label, so the separator between groups is structural. */\nexport function DropdownMenuGroup({ children, ...props }: DropdownMenuPartProps) {\n return <View {...props}>{children}</View>;\n}\n\nexport type DropdownMenuItemVariant = 'default' | 'destructive';\n\nexport interface DropdownMenuItemProps {\n variant?: DropdownMenuItemVariant;\n /** Keep the indicator gutter, so the label lines up with checkbox and radio rows. */\n indented?: boolean;\n disabled?: boolean;\n /** Chosen: the menu ticks, runs this, then closes. */\n onSelect?: () => void;\n /** The label, optionally followed by a DropdownMenuShortcut. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\ninterface ItemRowProps extends DropdownMenuItemProps {\n role: 'menuitem' | 'checkbox' | 'radio';\n checked?: boolean;\n indicator?: ReactNode;\n}\n\nfunction ItemRow({\n variant = 'default',\n indented = false,\n disabled = false,\n onSelect,\n role,\n checked,\n indicator,\n children,\n style,\n}: ItemRowProps) {\n const { setOpen } = useContext(MenuContext);\n styles.useVariants({ variant: variant === 'destructive' ? 'destructive' : undefined });\n return (\n <Pressable\n accessibilityRole={role}\n accessibilityState={{ disabled, checked }}\n disabled={disabled}\n onPress={() => {\n selectionTick();\n onSelect?.();\n setOpen(false);\n }}\n style={({ pressed }) => [\n styles.item,\n (indented || indicator !== undefined) && styles.indented,\n pressed && styles.pressed,\n disabled && styles.disabled,\n style,\n ]}\n >\n {indicator !== undefined ? <View style={styles.indicator}>{indicator}</View> : null}\n {wrapText(children, styles.label)}\n </Pressable>\n );\n}\n\nexport function DropdownMenuItem(props: DropdownMenuItemProps) {\n return <ItemRow role=\"menuitem\" {...props} />;\n}\n\nexport interface DropdownMenuCheckboxItemProps extends Omit<DropdownMenuItemProps, 'indented'> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n}\n\n/** A row that toggles: the check lives in the gutter so the label never shifts. */\nexport function DropdownMenuCheckboxItem({\n checked = false,\n onCheckedChange,\n onSelect,\n ...props\n}: DropdownMenuCheckboxItemProps) {\n return (\n <ItemRow\n role=\"checkbox\"\n checked={checked}\n indicator={checked ? <CheckIcon size={12} color=\"blue\" /> : null}\n onSelect={() => {\n onCheckedChange?.(!checked);\n onSelect?.();\n }}\n {...props}\n />\n );\n}\n\nexport interface DropdownMenuRadioGroupProps extends DropdownMenuPartProps {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\n/** The exclusive-choice group; pair it with DropdownMenuRadioItem. */\nexport function DropdownMenuRadioGroup({ value, onValueChange, children, ...props }: DropdownMenuRadioGroupProps) {\n return (\n <RadioContext.Provider value={{ value, onValueChange }}>\n <View accessibilityRole=\"radiogroup\" {...props}>\n {children}\n </View>\n </RadioContext.Provider>\n );\n}\n\nexport interface DropdownMenuRadioItemProps extends Omit<DropdownMenuItemProps, 'indented'> {\n value: string;\n}\n\nexport function DropdownMenuRadioItem({ value, onSelect, ...props }: DropdownMenuRadioItemProps) {\n const radio = useContext(RadioContext);\n const checked = radio.value === value;\n return (\n <ItemRow\n role=\"radio\"\n checked={checked}\n indicator={checked ? <View style={styles.radioDot} /> : null}\n onSelect={() => {\n radio.onValueChange?.(value);\n onSelect?.();\n }}\n {...props}\n />\n );\n}\n\n/** The heading over a run of items, raised to sentence case as the web's `first-letter:uppercase`. */\nexport function DropdownMenuLabel({ style, children, ...props }: TextProps) {\n const label = typeof children === 'string' ? children.charAt(0).toUpperCase() + children.slice(1) : children;\n return (\n <Text accessibilityRole=\"header\" style={[styles.menuLabel, style]} {...props}>\n {label}\n </Text>\n );\n}\n\n/** The keystroke printed at the right of a row; the row supplies the gap. */\nexport function DropdownMenuShortcut({ style, ...props }: TextProps) {\n return <Text style={[styles.shortcut, style]} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ style }: { style?: StyleProp<ViewStyle> }) {\n return <View accessible={false} style={[styles.separator, style]} />;\n}\n\nconst styles = StyleSheet.create((theme) => ({\n content: { paddingVertical: theme.spacing(1) },\n item: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.spacing(2),\n minHeight: MIN_ROW_HEIGHT,\n paddingHorizontal: theme.spacing(4),\n },\n indented: { paddingLeft: theme.spacing(4) + INDICATOR_GUTTER },\n indicator: {\n position: 'absolute',\n left: theme.spacing(4),\n width: theme.spacing(3),\n height: theme.spacing(3),\n alignItems: 'center',\n justifyContent: 'center',\n },\n radioDot: {\n width: RADIO_DOT,\n height: RADIO_DOT,\n borderRadius: theme.borderRadius.full,\n backgroundColor: theme.colors.blue,\n },\n pressed: { backgroundColor: theme.colors.deep },\n disabled: { opacity: DISABLED_OPACITY },\n label: {\n flexShrink: 1,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n variants: {\n variant: {\n default: { color: theme.colors.hi },\n destructive: { color: theme.colors.red },\n },\n },\n },\n menuLabel: {\n paddingHorizontal: theme.spacing(4),\n paddingVertical: theme.spacing(1),\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n fontWeight: theme.fontWeight.semibold,\n },\n shortcut: {\n marginLeft: 'auto',\n flexShrink: 0,\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n separator: { height: 1, marginVertical: theme.spacing(1), backgroundColor: theme.colors['border-soft'] },\n}));\n"],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenu.mjs","names":["createContext","ReactNode","useContext","StyleProp","TextProps","ViewProps","ViewStyle","StyleSheet","CheckIcon","fontOf","selectionTick","useControllable","wrapText","Button","ButtonProps","SheetFrame","INDICATOR_GUTTER","MIN_ROW_HEIGHT","DISABLED_OPACITY","RADIO_DOT","MenuState","open","setOpen","MenuContext","undefined","RadioState","value","onValueChange","RadioContext","DropdownMenuProps","defaultOpen","onOpenChange","children","DropdownMenu","current","DropdownMenuTrigger","onPress","accessibilityState","props","expanded","event","DropdownMenuContentProps","onDismiss","DropdownMenuContent","styles","content","DropdownMenuPartProps","Omit","style","DropdownMenuGroup","DropdownMenuItemVariant","DropdownMenuItemProps","variant","indented","disabled","onSelect","ItemRowProps","role","checked","indicator","ItemRow","_styles","useVariants","pressed","item","label","DropdownMenuItem","DropdownMenuCheckboxItemProps","onCheckedChange","DropdownMenuCheckboxItem","DropdownMenuRadioGroupProps","DropdownMenuRadioGroup","DropdownMenuRadioItemProps","DropdownMenuRadioItem","radio","radioDot","DropdownMenuLabel","charAt","toUpperCase","slice","menuLabel","DropdownMenuShortcut","shortcut","DropdownMenuSeparator","separator","create","theme","paddingVertical","spacing","uni__dependencies","flexDirection","alignItems","gap","minHeight","paddingHorizontal","paddingLeft","position","left","width","height","justifyContent","borderRadius","full","backgroundColor","colors","blue","deep","opacity","flexShrink","fontFamily","sans","fontSize","base","lineHeight","variants","default","color","hi","destructive","red","dim","sm","fontWeight","semibold","marginLeft","marginVertical"],"sources":["../../src/components/DropdownMenu.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } 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 { CheckIcon } from '../icons/icons';\nimport { fontOf } from '../lib/fonts';\nimport { selectionTick } from '../lib/haptics';\nimport { useControllable } from '../lib/useControllable';\nimport { wrapText } from '../lib/wrapText';\nimport { Button, type ButtonProps } from './Button';\nimport { SheetFrame } from './SheetFrame';\n\n/*\n * The web DropdownMenu as an action sheet: the same items rise in a bottom\n * sheet, each a full-width 44pt row, choosing one ticks once and closes the\n * menu, and destructive rows are red.\n *\n * ponytail: submenus are not ported; a native action list nests by opening a\n * second menu from an item.\n */\n\n/** A row that carries a check or bullet keeps a gutter for it, so labels line up whether or not one is set. */\nconst INDICATOR_GUTTER = 28;\nconst MIN_ROW_HEIGHT = 44;\nconst DISABLED_OPACITY = 0.4;\nconst RADIO_DOT = 6;\n\ninterface MenuState {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\nconst MenuContext = createContext<MenuState>({ open: false, setOpen: () => undefined });\n\ninterface RadioState {\n value: string | undefined;\n onValueChange: ((value: string) => void) | undefined;\n}\n\nconst RadioContext = createContext<RadioState>({ value: undefined, onValueChange: undefined });\n\nexport interface DropdownMenuProps {\n /** Controlled mode; pair with onOpenChange. Omit it and the menu keeps its own state. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\nexport function DropdownMenu({ open, defaultOpen = false, onOpenChange, children }: DropdownMenuProps) {\n const [current, setOpen] = useControllable(open, defaultOpen, onOpenChange);\n return <MenuContext.Provider value={{ open: current, setOpen }}>{children}</MenuContext.Provider>;\n}\n\n/** A Button that opens the menu; announces that it opens a menu. */\nexport function DropdownMenuTrigger({ onPress, accessibilityState, ...props }: ButtonProps) {\n const { open, setOpen } = useContext(MenuContext);\n return (\n <Button\n accessibilityState={{ ...accessibilityState, expanded: open }}\n onPress={(event) => {\n onPress?.(event);\n setOpen(true);\n }}\n {...props}\n />\n );\n}\n\nexport interface DropdownMenuContentProps {\n children?: ReactNode;\n /** The native sheet has finished dismissing, including its closing animation. */\n onDismiss?: () => void;\n}\n\n/** The action list, in a bottom sheet. */\nexport function DropdownMenuContent({ children, onDismiss }: DropdownMenuContentProps) {\n const { open, setOpen } = useContext(MenuContext);\n return (\n <SheetFrame open={open} onClose={() => setOpen(false)} onDismiss={onDismiss}>\n <MenuContext.Provider value={{ open, setOpen }}>\n <View accessibilityRole=\"menu\" style={styles.content}>\n {children}\n </View>\n </MenuContext.Provider>\n </SheetFrame>\n );\n}\n\nexport interface DropdownMenuPartProps extends Omit<ViewProps, 'children' | 'style'> {\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** A run of items under one label, so the separator between groups is structural. */\nexport function DropdownMenuGroup({ children, ...props }: DropdownMenuPartProps) {\n return <View {...props}>{children}</View>;\n}\n\nexport type DropdownMenuItemVariant = 'default' | 'destructive';\n\nexport interface DropdownMenuItemProps {\n variant?: DropdownMenuItemVariant;\n /** Keep the indicator gutter, so the label lines up with checkbox and radio rows. */\n indented?: boolean;\n disabled?: boolean;\n /** Chosen: the menu ticks, runs this, then closes. */\n onSelect?: () => void;\n /** The label, optionally followed by a DropdownMenuShortcut. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\ninterface ItemRowProps extends DropdownMenuItemProps {\n role: 'menuitem' | 'checkbox' | 'radio';\n checked?: boolean;\n indicator?: ReactNode;\n}\n\nfunction ItemRow({\n variant = 'default',\n indented = false,\n disabled = false,\n onSelect,\n role,\n checked,\n indicator,\n children,\n style,\n}: ItemRowProps) {\n const { setOpen } = useContext(MenuContext);\n styles.useVariants({ variant: variant === 'destructive' ? 'destructive' : undefined });\n return (\n <Pressable\n accessibilityRole={role}\n accessibilityState={{ disabled, checked }}\n disabled={disabled}\n onPress={() => {\n selectionTick();\n onSelect?.();\n setOpen(false);\n }}\n style={({ pressed }) => [\n styles.item,\n (indented || indicator !== undefined) && styles.indented,\n pressed && styles.pressed,\n disabled && styles.disabled,\n style,\n ]}\n >\n {indicator !== undefined ? <View style={styles.indicator}>{indicator}</View> : null}\n {wrapText(children, styles.label)}\n </Pressable>\n );\n}\n\nexport function DropdownMenuItem(props: DropdownMenuItemProps) {\n return <ItemRow role=\"menuitem\" {...props} />;\n}\n\nexport interface DropdownMenuCheckboxItemProps extends Omit<DropdownMenuItemProps, 'indented'> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n}\n\n/** A row that toggles: the check lives in the gutter so the label never shifts. */\nexport function DropdownMenuCheckboxItem({\n checked = false,\n onCheckedChange,\n onSelect,\n ...props\n}: DropdownMenuCheckboxItemProps) {\n return (\n <ItemRow\n role=\"checkbox\"\n checked={checked}\n indicator={checked ? <CheckIcon size={12} color=\"blue\" /> : null}\n onSelect={() => {\n onCheckedChange?.(!checked);\n onSelect?.();\n }}\n {...props}\n />\n );\n}\n\nexport interface DropdownMenuRadioGroupProps extends DropdownMenuPartProps {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\n/** The exclusive-choice group; pair it with DropdownMenuRadioItem. */\nexport function DropdownMenuRadioGroup({ value, onValueChange, children, ...props }: DropdownMenuRadioGroupProps) {\n return (\n <RadioContext.Provider value={{ value, onValueChange }}>\n <View accessibilityRole=\"radiogroup\" {...props}>\n {children}\n </View>\n </RadioContext.Provider>\n );\n}\n\nexport interface DropdownMenuRadioItemProps extends Omit<DropdownMenuItemProps, 'indented'> {\n value: string;\n}\n\nexport function DropdownMenuRadioItem({ value, onSelect, ...props }: DropdownMenuRadioItemProps) {\n const radio = useContext(RadioContext);\n const checked = radio.value === value;\n return (\n <ItemRow\n role=\"radio\"\n checked={checked}\n indicator={checked ? <View style={styles.radioDot} /> : null}\n onSelect={() => {\n radio.onValueChange?.(value);\n onSelect?.();\n }}\n {...props}\n />\n );\n}\n\n/** The heading over a run of items, raised to sentence case as the web's `first-letter:uppercase`. */\nexport function DropdownMenuLabel({ style, children, ...props }: TextProps) {\n const label = typeof children === 'string' ? children.charAt(0).toUpperCase() + children.slice(1) : children;\n return (\n <Text accessibilityRole=\"header\" style={[styles.menuLabel, style]} {...props}>\n {label}\n </Text>\n );\n}\n\n/** The keystroke printed at the right of a row; the row supplies the gap. */\nexport function DropdownMenuShortcut({ style, ...props }: TextProps) {\n return <Text style={[styles.shortcut, style]} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ style }: { style?: StyleProp<ViewStyle> }) {\n return <View accessible={false} style={[styles.separator, style]} />;\n}\n\nconst styles = StyleSheet.create((theme) => ({\n content: { paddingVertical: theme.spacing(1) },\n item: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.spacing(2),\n minHeight: MIN_ROW_HEIGHT,\n paddingHorizontal: theme.spacing(4),\n },\n indented: { paddingLeft: theme.spacing(4) + INDICATOR_GUTTER },\n indicator: {\n position: 'absolute',\n left: theme.spacing(4),\n width: theme.spacing(3),\n height: theme.spacing(3),\n alignItems: 'center',\n justifyContent: 'center',\n },\n radioDot: {\n width: RADIO_DOT,\n height: RADIO_DOT,\n borderRadius: theme.borderRadius.full,\n backgroundColor: theme.colors.blue,\n },\n pressed: { backgroundColor: theme.colors.deep },\n disabled: { opacity: DISABLED_OPACITY },\n label: {\n flexShrink: 1,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n variants: {\n variant: {\n default: { color: theme.colors.hi },\n destructive: { color: theme.colors.red },\n },\n },\n },\n menuLabel: {\n paddingHorizontal: theme.spacing(4),\n paddingVertical: theme.spacing(1),\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n fontWeight: theme.fontWeight.semibold,\n },\n shortcut: {\n marginLeft: 'auto',\n flexShrink: 0,\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n separator: { height: 1, marginVertical: theme.spacing(1), backgroundColor: theme.colors['border-soft'] },\n}));\n"],"mappings":"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"}
@@ -16,7 +16,11 @@ export interface OpenSheet {
16
16
  close: () => void;
17
17
  setNote: (note: string | undefined) => void;
18
18
  }
19
+ /** Closing sheets still occlude their canvas until native dismissal or unmount. */
20
+ export declare function hasPresentedSheets(): boolean;
21
+ export declare function subscribePresentedSheets(listener: () => void): () => void;
19
22
  export declare function registerSheet(sheet: OpenSheet): void;
23
+ export declare function dismissSheet(sheet: OpenSheet): void;
20
24
  export declare function unregisterSheet(sheet: OpenSheet): void;
21
25
  /** A prompt holds the screen, so sheets must not open over it without a person's action. */
22
26
  export declare function sheetsYielded(): boolean;
@@ -1 +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"}
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;;;wBAUI;wBAIA,yBAAyB;wBAOzB,cAAc,OAAO;wBAOrB,aAAa,OAAO;wBAIpB,gBAAgB,OAAO;;wBAMvB;;wBAKA,YAAY"}
@@ -10,9 +10,27 @@ const MessageItemContext = createContext({
10
10
  const MessageItemGroupContext = createContext(null);
11
11
  /** One shell-owned list across every downloaded UI module, oldest sheet first. */
12
12
  const openSheets = [];
13
+ const presentedSheets = /* @__PURE__ */ new Set();
14
+ const sheetListeners = /* @__PURE__ */ new Set();
13
15
  let yielded = false;
16
+ /** Closing sheets still occlude their canvas until native dismissal or unmount. */
17
+ function hasPresentedSheets() {
18
+ return presentedSheets.size > 0;
19
+ }
20
+ function subscribePresentedSheets(listener) {
21
+ sheetListeners.add(listener);
22
+ return () => {
23
+ sheetListeners.delete(listener);
24
+ };
25
+ }
14
26
  function registerSheet(sheet) {
15
27
  if (!openSheets.includes(sheet)) openSheets.push(sheet);
28
+ if (presentedSheets.has(sheet)) return;
29
+ presentedSheets.add(sheet);
30
+ for (const listener of sheetListeners) listener();
31
+ }
32
+ function dismissSheet(sheet) {
33
+ if (presentedSheets.delete(sheet)) for (const listener of sheetListeners) listener();
16
34
  }
17
35
  function unregisterSheet(sheet) {
18
36
  const index = openSheets.indexOf(sheet);
@@ -39,5 +57,5 @@ function yieldSheets(note) {
39
57
  }
40
58
 
41
59
  //#endregion
42
- export { MessageItemContext, MessageItemGroupContext, registerSheet, sheetsYielded, unregisterSheet, yieldSheets };
60
+ export { MessageItemContext, MessageItemGroupContext, dismissSheet, hasPresentedSheets, registerSheet, sheetsYielded, subscribePresentedSheets, unregisterSheet, yieldSheets };
43
61
  //# sourceMappingURL=NativeShellState.mjs.map
@@ -1 +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
+ {"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[] = [];\nconst presentedSheets = new Set<OpenSheet>();\nconst sheetListeners = new Set<() => void>();\nlet yielded = false;\n\n/** Closing sheets still occlude their canvas until native dismissal or unmount. */\nexport function hasPresentedSheets(): boolean {\n return presentedSheets.size > 0;\n}\n\nexport function subscribePresentedSheets(listener: () => void): () => void {\n sheetListeners.add(listener);\n return () => {\n sheetListeners.delete(listener);\n };\n}\n\nexport function registerSheet(sheet: OpenSheet): void {\n if (!openSheets.includes(sheet)) openSheets.push(sheet);\n if (presentedSheets.has(sheet)) return;\n presentedSheets.add(sheet);\n for (const listener of sheetListeners) listener();\n}\n\nexport function dismissSheet(sheet: OpenSheet): void {\n if (presentedSheets.delete(sheet)) for (const listener of sheetListeners) listener();\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,MAAM,kCAAkB,IAAI,IAAe;AAC3C,MAAM,iCAAiB,IAAI,IAAgB;AAC3C,IAAI,UAAU;;AAGd,SAAgB,qBAA8B;CAC5C,OAAO,gBAAgB,OAAO;AAChC;AAEA,SAAgB,yBAAyB,UAAkC;CACzE,eAAe,IAAI,QAAQ;CAC3B,aAAa;EACX,eAAe,OAAO,QAAQ;CAChC;AACF;AAEA,SAAgB,cAAc,OAAwB;CACpD,IAAI,CAAC,WAAW,SAAS,KAAK,GAAG,WAAW,KAAK,KAAK;CACtD,IAAI,gBAAgB,IAAI,KAAK,GAAG;CAChC,gBAAgB,IAAI,KAAK;CACzB,KAAK,MAAM,YAAY,gBAAgB,SAAS;AAClD;AAEA,SAAgB,aAAa,OAAwB;CACnD,IAAI,gBAAgB,OAAO,KAAK,GAAG,KAAK,MAAM,YAAY,gBAAgB,SAAS;AACrF;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"}
@@ -6,7 +6,7 @@ import { BackHandler, Keyboard } from "react-native";
6
6
  import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
7
7
  import { useCallback, useContext, useEffect, useRef, useState } from "react";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
- import { InsideSheetContext, registerSheet, unregisterSheet } from "@agimon-ai/po-native-components/shell";
9
+ import { InsideSheetContext, dismissSheet, 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
 
@@ -60,6 +60,7 @@ function SheetFrame({ open, onClose, onDismiss, children, scrollable = true, foo
60
60
  }, [open]);
61
61
  useEffect(() => () => {
62
62
  unregisterSheet(entry.current);
63
+ dismissSheet?.(entry.current);
63
64
  }, []);
64
65
  useEffect(() => {
65
66
  if (!open) return void 0;
@@ -113,6 +114,7 @@ function SheetFrame({ open, onClose, onDismiss, children, scrollable = true, foo
113
114
  handleIndicatorStyle: { backgroundColor: theme.colors.border },
114
115
  onDismiss: () => {
115
116
  presented.current = false;
117
+ dismissSheet?.(entry.current);
116
118
  if (openRef.current) latest.current.onClose();
117
119
  latest.current.onDismiss?.();
118
120
  },
@@ -1 +1 @@
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","onDismiss","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 onDismiss?: () => 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({\n open,\n onClose,\n onDismiss,\n children,\n scrollable = true,\n footer,\n keep = false,\n}: 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, onDismiss });\n latest.current = { keep, onClose, onDismiss };\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) latest.current.onClose();\n latest.current.onDismiss?.();\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":["dismissSheet","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","onDismiss","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 dismissSheet,\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 onDismiss?: () => 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({\n open,\n onClose,\n onDismiss,\n children,\n scrollable = true,\n footer,\n keep = false,\n}: 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, onDismiss });\n latest.current = { keep, onClose, onDismiss };\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 dismissSheet?.(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 dismissSheet?.(entry.current);\n if (openRef.current) latest.current.onClose();\n latest.current.onDismiss?.();\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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"}
@@ -0,0 +1,12 @@
1
+ import { ImageProps } from "react-native";
2
+ import { WebPluginSlotProps } from "@agimon-ai/po-core/native";
3
+ //#region src/components/ToolResultImage.d.ts
4
+ export interface ToolResultImageProps extends Omit<ImageProps, 'source'> {
5
+ host: Pick<WebPluginSlotProps, 'sessionId' | 'slotData' | 'openTransientTab' | 'openTab'>;
6
+ data: string;
7
+ mimeType: string;
8
+ }
9
+ /** Keeps the thumbnail's appearance; with Author installed, a tap opens its feedback canvas. */
10
+ export declare function ToolResultImage({ host, data, mimeType, accessibilityLabel, ...props }: ToolResultImageProps): import("react").JSX.Element;
11
+ //#endregion
12
+ //# sourceMappingURL=ToolResultImage.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolResultImage.d.mts","names":[],"sources":["../../src/components/ToolResultImage.tsx"],"mappings":";;;iBAyBiB,6BAA6B,KAAK;EACjD,MAAM,KAAK;EACX;EACA;;;wBAIc,kBACd,MACA,MACA,UACA,uBACG,SACF,uCAAoB,IAAA"}
@@ -0,0 +1,48 @@
1
+ import { Alert } from "react-native";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Pressable } from "react-native-unistyles/components/native/Pressable";
4
+ import { Image } from "react-native-unistyles/components/native/Image";
5
+
6
+ //#region src/components/ToolResultImage.tsx
7
+ const authorImages = {
8
+ slot: "author.open-source",
9
+ parse(input) {
10
+ if (typeof input !== "object" || input === null) return null;
11
+ const action = input;
12
+ return action.version === 1 && typeof action.createImageTab === "function" ? action : null;
13
+ }
14
+ };
15
+ /** Keeps the thumbnail's appearance; with Author installed, a tap opens its feedback canvas. */
16
+ function ToolResultImage({ host, data, mimeType, accessibilityLabel = "Image", ...props }) {
17
+ const action = host.sessionId === null ? void 0 : host.slotData?.(authorImages)[0]?.data;
18
+ const image = /* @__PURE__ */ jsx(Image, {
19
+ ...props,
20
+ source: { uri: `data:${mimeType};base64,${data}` },
21
+ accessibilityLabel
22
+ });
23
+ if (action === void 0) return image;
24
+ return /* @__PURE__ */ jsx(Pressable, {
25
+ accessibilityRole: "button",
26
+ accessibilityLabel: `Open ${accessibilityLabel} in Author`,
27
+ accessibilityHint: "View full size and give feedback",
28
+ onPress: async () => {
29
+ try {
30
+ const tab = await action.createImageTab({
31
+ sessionId: host.sessionId,
32
+ data,
33
+ mimeType,
34
+ title: accessibilityLabel
35
+ });
36
+ host.openTransientTab(tab);
37
+ host.openTab(tab.id);
38
+ } catch (error) {
39
+ Alert.alert("Couldn't open this image", error instanceof Error ? error.message : String(error));
40
+ }
41
+ },
42
+ children: image
43
+ });
44
+ }
45
+
46
+ //#endregion
47
+ export { ToolResultImage };
48
+ //# sourceMappingURL=ToolResultImage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolResultImage.mjs","names":["SlotDeclaration","WebPluginSlotProps","TransientTab","Alert","ImageProps","ImageSource","sessionId","data","mimeType","title","authorImages","createImageTab","input","Promise","slot","parse","action","version","ToolResultImageProps","Omit","host","Pick","ToolResultImage","accessibilityLabel","props","undefined","slotData","image","uri","tab","openTransientTab","openTab","id","error","alert","Error","message","String"],"sources":["../../src/components/ToolResultImage.tsx"],"sourcesContent":["import type { SlotDeclaration, WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport type { TransientTab } from '@agimon-ai/po-core/web';\nimport { Alert, Image, Pressable, type ImageProps } from 'react-native';\n\ninterface ImageSource {\n sessionId: string;\n data: string;\n mimeType: string;\n title: string;\n}\n\n// Duck-typed like the artifact browser: shared UI never imports an optional mode.\nconst authorImages: SlotDeclaration<{\n createImageTab(input: ImageSource): Promise<TransientTab>;\n}> = {\n slot: 'author.open-source',\n parse(input) {\n if (typeof input !== 'object' || input === null) return null;\n const action = input as { version?: unknown; createImageTab?: unknown };\n return action.version === 1 && typeof action.createImageTab === 'function'\n ? (action as { createImageTab(input: ImageSource): Promise<TransientTab> })\n : null;\n },\n};\n\nexport interface ToolResultImageProps extends Omit<ImageProps, 'source'> {\n host: Pick<WebPluginSlotProps, 'sessionId' | 'slotData' | 'openTransientTab' | 'openTab'>;\n data: string;\n mimeType: string;\n}\n\n/** Keeps the thumbnail's appearance; with Author installed, a tap opens its feedback canvas. */\nexport function ToolResultImage({\n host,\n data,\n mimeType,\n accessibilityLabel = 'Image',\n ...props\n}: ToolResultImageProps) {\n const action = host.sessionId === null ? undefined : host.slotData?.(authorImages)[0]?.data;\n const image = (\n <Image {...props} source={{ uri: `data:${mimeType};base64,${data}` }} accessibilityLabel={accessibilityLabel} />\n );\n if (action === undefined) return image;\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={`Open ${accessibilityLabel} in Author`}\n accessibilityHint=\"View full size and give feedback\"\n onPress={async () => {\n try {\n const tab = await action.createImageTab({\n sessionId: host.sessionId!,\n data,\n mimeType,\n title: accessibilityLabel,\n });\n host.openTransientTab(tab);\n host.openTab(tab.id);\n } catch (error) {\n Alert.alert(\"Couldn't open this image\", error instanceof Error ? error.message : String(error));\n }\n }}\n >\n {image}\n </Pressable>\n );\n}\n"],"mappings":";;;;;;AAYA,MAAMU,eAED;CACHI,MAAM;CACNC,MAAMH,OAAO;EACX,IAAI,OAAOA,UAAU,YAAYA,UAAU,MAAM,OAAO;EACxD,MAAMI,SAASJ;EACf,OAAOI,OAAOC,YAAY,KAAK,OAAOD,OAAOL,mBAAmB,aAC3DK,SACD;CACN;AACF;;AASA,SAAgBM,gBAAgB,EAC9BF,MACAb,MACAC,UACAe,qBAAqB,SACrB,GAAGC,SACoB;CACvB,MAAMR,SAASI,KAAKd,cAAc,OAAOmB,SAAYL,KAAKM,WAAWhB,YAAY,CAAC,CAAC,EAAE,EAAEH;CACvF,MAAMoB,QACJ,oBAAC,OAAD;EAAO,GAAIH;EAAO,QAAQ,EAAEI,KAAK,QAAQpB,SAAQ,UAAWD,OAAO;EAAuBgB;CAAmB;CAE/G,IAAIP,WAAWS,QAAW,OAAOE;CACjC,OACE,oBAAC,WAAD;EACE,mBAAkB;EAClB,oBAAoB,QAAQJ,mBAAkB;EAC9C,mBAAkB;EAClB,SAAS,YAAY;GACnB,IAAI;IACF,MAAMM,MAAM,MAAMb,OAAOL,eAAe;KACtCL,WAAWc,KAAKd;KAChBC;KACAC;KACAC,OAAOc;IACT,CAAC;IACDH,KAAKU,iBAAiBD,GAAG;IACzBT,KAAKW,QAAQF,IAAIG,EAAE;GACrB,SAASC,OAAO;IACd9B,MAAM+B,MAAM,4BAA4BD,iBAAiBE,QAAQF,MAAMG,UAAUC,OAAOJ,KAAK,CAAC;GAChG;EACF;YAECN;CACQ;AAEf"}
package/dist/index.d.mts CHANGED
@@ -3,6 +3,7 @@ import { AnnotationMark, AnnotationSurface, AnnotationSurfaceProps } from "./com
3
3
  import { Badge, BadgeProps, BadgeSize, BadgeTone } from "./components/Badge.mjs";
4
4
  import { Button, ButtonProps, ButtonSize, ButtonVariant } from "./components/Button.mjs";
5
5
  import { CodeBlock, CodeBlockProps } from "./components/CodeBlock.mjs";
6
+ import { ToolResultImage, ToolResultImageProps } from "./components/ToolResultImage.mjs";
6
7
  import { CopyButton, CopyButtonProps } from "./components/CopyButton.mjs";
7
8
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogContentProps, DialogDescription, DialogFooter, DialogFooterProps, DialogFooterVariant, DialogHeader, DialogHeaderProps, DialogPartProps, DialogProps, DialogTitle, DialogTrigger, DialogWidth } from "./components/Dialog.mjs";
8
9
  import { CountBadge, CountBadgeProps } from "./components/CountBadge.mjs";
@@ -36,4 +37,4 @@ import { HostTag } from "./components/HostTag.mjs";
36
37
  import { InfoStrip } from "./components/InfoStrip.mjs";
37
38
  import { AnsiSpan, PresentedLine, ReviewComment, ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
38
39
  import { IconColorContext, LiveDuration, LiveDurationProps, LiveDurationReading, PoNativeProvider, PoNativeProviderProps, sheetsYielded, yieldSheets } from "@agimon-ai/po-native-components/shell";
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 };
40
+ 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, ToolResultImage, type ToolResultImageProps, TrashIcon, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, sheetsYielded, toolTone, useMessageItem, useSyntaxLines, yieldSheets };
package/dist/index.mjs CHANGED
@@ -10,6 +10,7 @@ import { ActivityIcon, AlertIcon, ArrowRightIcon, AudioLinesIcon, BranchIcon, Ch
10
10
  import { CopyButton } from "./components/CopyButton.mjs";
11
11
  import { ShowMore } from "./components/ShowMore.mjs";
12
12
  import { CodeBlock } from "./components/CodeBlock.mjs";
13
+ import { ToolResultImage } from "./components/ToolResultImage.mjs";
13
14
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "./components/Dialog.mjs";
14
15
  import { CountBadge } from "./components/CountBadge.mjs";
15
16
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger } from "./components/DropdownMenu.mjs";
@@ -36,4 +37,4 @@ import { InfoStrip } from "./components/InfoStrip.mjs";
36
37
  import { ansiSpans, buildReviewPrompt, collapseLines, hashlineBody, resultTextLines } from "@agimon-ai/po-web-components/text";
37
38
  import { IconColorContext, LiveDuration, PoNativeProvider, sheetsYielded, yieldSheets } from "@agimon-ai/po-native-components/shell";
38
39
 
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 };
40
+ 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, ToolResultImage, TrashIcon, UserIcon, UsersIcon, WorkflowIcon, WrenchIcon, agentInitials, ansiSpans, buildReviewPrompt, collapseLines, fontOf, hashlineBody, impactLight, resultTextLines, selectionTick, sheetsYielded, toolTone, useMessageItem, useSyntaxLines, yieldSheets };
package/dist/shell.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LiveDuration, LiveDurationProps, LiveDurationReading } from "./components/LiveDuration.mjs";
2
- import { MessageItemContext, MessageItemGroupContext, MessageItemState, OpenSheet, registerSheet, sheetsYielded, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
2
+ import { MessageItemContext, MessageItemGroupContext, MessageItemState, OpenSheet, dismissSheet, hasPresentedSheets, registerSheet, sheetsYielded, subscribePresentedSheets, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
3
3
  import { PoNativeProvider, PoNativeProviderProps } from "./components/PoNativeProvider.mjs";
4
4
  import { IconColorContext } from "./icons/IconColorContext.mjs";
5
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 };
6
+ export { IconColorContext, InsideSheetContext, LiveDuration, type LiveDurationProps, type LiveDurationReading, MessageItemContext, MessageItemGroupContext, type MessageItemState, type OpenSheet, PoNativeProvider, type PoNativeProviderProps, dismissSheet, hasPresentedSheets, registerSheet, sheetsYielded, subscribePresentedSheets, unregisterSheet, useInsideSheet, yieldSheets };
package/dist/shell.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { LiveDuration } from "./components/LiveDuration.mjs";
2
- import { MessageItemContext, MessageItemGroupContext, registerSheet, sheetsYielded, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
2
+ import { MessageItemContext, MessageItemGroupContext, dismissSheet, hasPresentedSheets, registerSheet, sheetsYielded, subscribePresentedSheets, unregisterSheet, yieldSheets } from "./components/NativeShellState.mjs";
3
3
  import { PoNativeProvider } from "./components/PoNativeProvider.mjs";
4
4
  import { IconColorContext } from "./icons/IconColorContext.mjs";
5
5
  import { InsideSheetContext, useInsideSheet } from "./lib/insideSheet.mjs";
6
6
 
7
- export { IconColorContext, InsideSheetContext, LiveDuration, MessageItemContext, MessageItemGroupContext, PoNativeProvider, registerSheet, sheetsYielded, unregisterSheet, useInsideSheet, yieldSheets };
7
+ export { IconColorContext, InsideSheetContext, LiveDuration, MessageItemContext, MessageItemGroupContext, PoNativeProvider, dismissSheet, hasPresentedSheets, registerSheet, sheetsYielded, subscribePresentedSheets, 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.80",
3
+ "version": "0.0.0-alpha.81",
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",
@@ -49,11 +49,12 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@agimon-ai/po-web-components": "0.0.0-alpha.80"
52
+ "@agimon-ai/po-web-components": "0.0.0-alpha.81"
53
53
  },
54
54
  "devDependencies": {
55
- "@agimon-ai/po-build": "0.0.0-alpha.80",
56
- "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.80",
55
+ "@agimon-ai/po-build": "0.0.0-alpha.81",
56
+ "@agimon-ai/po-core": "0.0.0-alpha.81",
57
+ "@agimon-ai/vibe-lint-plugin-po-web": "0.0.0-alpha.81",
57
58
  "@babel/core": "7.29.7",
58
59
  "@expo/vector-icons": "15.1.1",
59
60
  "@fontsource-variable/ibm-plex-sans": "5.3.0",