Bluesky app fork with some witchin' additions 馃挮
witchsky.app
bluesky
fork
client
1import {
2 type AccessibilityRole,
3 type GestureResponderEvent,
4 type StyleProp,
5 type ViewStyle,
6} from 'react-native'
7import {type SharedValue} from 'react-native-reanimated'
8
9import type * as Dialog from '#/components/Dialog'
10import {
11 type ItemProps as MenuItemProps,
12 type RadixPassThroughTriggerProps,
13} from '#/components/Menu/types'
14
15export type {
16 GroupProps,
17 ItemIconProps,
18 ItemTextProps,
19} from '#/components/Menu/types'
20
21export type AuxiliaryViewProps = {
22 children?: React.ReactNode
23 align?: 'left' | 'right'
24 style?: StyleProp<ViewStyle>
25}
26
27export type ItemProps = Omit<MenuItemProps, 'onPress' | 'children'> & {
28 // remove default styles (i.e. for emoji reactions)
29 unstyled?: boolean
30 onPress: (evt?: GestureResponderEvent) => void
31 children?: React.ReactNode | ((hovered: boolean) => React.ReactNode)
32 // absolute position of the parent element. if undefined, assumed to
33 // be in the context menu. use this if using AuxiliaryView
34 position?: Measurement
35}
36
37export type Measurement = {
38 x: number
39 y: number
40 width: number
41 height: number
42}
43
44export type ContextType = {
45 isOpen: boolean
46 measurement: Measurement | null
47 /* Spring animation between 0 and 1 */
48 animationSV: SharedValue<number>
49 /* Translation in Y axis to ensure everything's onscreen */
50 translationSV: SharedValue<number>
51 mode: 'full' | 'auxiliary-only'
52 open: (evt: Measurement, mode: 'full' | 'auxiliary-only') => void
53 returnLocationSV: SharedValue<{x: number; y: number} | null>
54 close: () => void
55 registerHoverable: (
56 id: string,
57 rect: Measurement,
58 onTouchUp: () => void,
59 ) => void
60 hoverablesSV: SharedValue<Record<string, {id: string; rect: Measurement}>>
61 hoveredMenuItem: string | null
62 setHoveredMenuItem: React.Dispatch<React.SetStateAction<string | null>>
63 onTouchUpMenuItem: (id: string) => void
64}
65
66export type MenuContextType = {
67 align: 'left' | 'right'
68}
69
70export type ItemContextType = {
71 disabled: boolean
72}
73
74export type TriggerProps = {
75 children(props: TriggerChildProps): React.ReactNode
76 label: string
77 /**
78 * When activated, this is the accessibility label for the entire thing that has been triggered.
79 * For example, if the trigger is a message bubble, use the message content.
80 *
81 * @platform ios, android
82 */
83 contentLabel: string
84 hint?: string
85 role?: AccessibilityRole
86 style?: StyleProp<ViewStyle>
87 /**
88 * Callback for single taps. Composed with the double-tap and
89 * press-and-hold gestures via `Gesture.Exclusive`, so a double tap
90 * does not also fire this handler.
91 *
92 * @platform ios, android
93 */
94 onTap?: () => void
95}
96export type TriggerChildProps =
97 | {
98 IS_NATIVE: true
99 control: {
100 isOpen: boolean
101 open: (mode: 'full' | 'auxiliary-only') => void
102 }
103 state: {
104 hovered: false
105 focused: false
106 pressed: false
107 }
108 /**
109 * We don't necessarily know what these will be spread on to, so we
110 * should add props one-by-one.
111 *
112 * On web, these properties are applied to a parent `Pressable`, so this
113 * object is empty.
114 */
115 props: {
116 ref: null
117 onPress: null
118 onFocus: null
119 onBlur: null
120 onPressIn: null
121 onPressOut: null
122 accessibilityHint: null
123 accessibilityLabel: string
124 accessibilityRole: null
125 }
126 }
127 | {
128 IS_NATIVE: false
129 control: Dialog.DialogOuterProps['control']
130 state: {
131 hovered: false
132 focused: false
133 pressed: false
134 }
135 props: RadixPassThroughTriggerProps & {
136 onPress: () => void
137 onFocus: () => void
138 onBlur: () => void
139 onMouseEnter: () => void
140 onMouseLeave: () => void
141 accessibilityHint?: string
142 accessibilityLabel: string
143 accessibilityRole: AccessibilityRole
144 }
145 }