fork
Configure Feed
Select the types of activity you want to include in your feed.
mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
fork
Configure Feed
Select the types of activity you want to include in your feed.
1import React from 'react'
2import {Pressable, StyleProp, View, ViewStyle} from 'react-native'
3import {msg, Trans} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5import flattenReactChildren from 'react-keyed-flatten-children'
6
7import {isNative} from 'platform/detection'
8import {atoms as a, useTheme} from '#/alf'
9import {Button, ButtonText} from '#/components/Button'
10import * as Dialog from '#/components/Dialog'
11import {useInteractionState} from '#/components/hooks/useInteractionState'
12import {Context} from '#/components/Menu/context'
13import {
14 ContextType,
15 GroupProps,
16 ItemIconProps,
17 ItemProps,
18 ItemTextProps,
19 TriggerProps,
20} from '#/components/Menu/types'
21import {Text} from '#/components/Typography'
22
23export {
24 type DialogControlProps as MenuControlProps,
25 useDialogControl as useMenuControl,
26} from '#/components/Dialog'
27
28export function useMemoControlContext() {
29 return React.useContext(Context)
30}
31
32export function Root({
33 children,
34 control,
35}: React.PropsWithChildren<{
36 control?: Dialog.DialogOuterProps['control']
37}>) {
38 const defaultControl = Dialog.useDialogControl()
39 const context = React.useMemo<ContextType>(
40 () => ({
41 control: control || defaultControl,
42 }),
43 [control, defaultControl],
44 )
45
46 return <Context.Provider value={context}>{children}</Context.Provider>
47}
48
49export function Trigger({children, label}: TriggerProps) {
50 const {control} = React.useContext(Context)
51 const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
52 const {
53 state: pressed,
54 onIn: onPressIn,
55 onOut: onPressOut,
56 } = useInteractionState()
57
58 return children({
59 isNative: true,
60 control,
61 state: {
62 hovered: false,
63 focused,
64 pressed,
65 },
66 props: {
67 onPress: control.open,
68 onFocus,
69 onBlur,
70 onPressIn,
71 onPressOut,
72 accessibilityLabel: label,
73 },
74 })
75}
76
77export function Outer({
78 children,
79 showCancel,
80}: React.PropsWithChildren<{
81 showCancel?: boolean
82 style?: StyleProp<ViewStyle>
83}>) {
84 const context = React.useContext(Context)
85
86 return (
87 <Dialog.Outer control={context.control}>
88 <Dialog.Handle />
89
90 {/* Re-wrap with context since Dialogs are portal-ed to root */}
91 <Context.Provider value={context}>
92 <Dialog.ScrollableInner label="Menu TODO">
93 <View style={[a.gap_lg]}>
94 {children}
95 {isNative && showCancel && <Cancel />}
96 </View>
97 <View style={{height: a.gap_lg.gap}} />
98 </Dialog.ScrollableInner>
99 </Context.Provider>
100 </Dialog.Outer>
101 )
102}
103
104export function Item({children, label, style, onPress, ...rest}: ItemProps) {
105 const t = useTheme()
106 const {control} = React.useContext(Context)
107 const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
108 const {
109 state: pressed,
110 onIn: onPressIn,
111 onOut: onPressOut,
112 } = useInteractionState()
113
114 return (
115 <Pressable
116 {...rest}
117 accessibilityHint=""
118 accessibilityLabel={label}
119 onPress={e => {
120 onPress(e)
121
122 if (!e.defaultPrevented) {
123 control?.close()
124 }
125 }}
126 onFocus={onFocus}
127 onBlur={onBlur}
128 onPressIn={onPressIn}
129 onPressOut={onPressOut}
130 style={[
131 a.flex_row,
132 a.align_center,
133 a.gap_sm,
134 a.px_md,
135 a.rounded_md,
136 a.border,
137 t.atoms.bg_contrast_25,
138 t.atoms.border_contrast_low,
139 {minHeight: 44, paddingVertical: 10},
140 style,
141 (focused || pressed) && [t.atoms.bg_contrast_50],
142 ]}>
143 {children}
144 </Pressable>
145 )
146}
147
148export function ItemText({children, style}: ItemTextProps) {
149 const t = useTheme()
150 return (
151 <Text
152 numberOfLines={1}
153 ellipsizeMode="middle"
154 style={[
155 a.flex_1,
156 a.text_md,
157 a.font_bold,
158 t.atoms.text_contrast_medium,
159 {paddingTop: 3},
160 style,
161 ]}>
162 {children}
163 </Text>
164 )
165}
166
167export function ItemIcon({icon: Comp}: ItemIconProps) {
168 const t = useTheme()
169 return <Comp size="lg" fill={t.atoms.text_contrast_medium.color} />
170}
171
172export function Group({children, style}: GroupProps) {
173 const t = useTheme()
174 return (
175 <View
176 style={[
177 a.rounded_md,
178 a.overflow_hidden,
179 a.border,
180 t.atoms.border_contrast_low,
181 style,
182 ]}>
183 {flattenReactChildren(children).map((child, i) => {
184 return React.isValidElement(child) && child.type === Item ? (
185 <React.Fragment key={i}>
186 {i > 0 ? (
187 <View style={[a.border_b, t.atoms.border_contrast_low]} />
188 ) : null}
189 {React.cloneElement(child, {
190 // @ts-ignore
191 style: {
192 borderRadius: 0,
193 borderWidth: 0,
194 },
195 })}
196 </React.Fragment>
197 ) : null
198 })}
199 </View>
200 )
201}
202
203function Cancel() {
204 const {_} = useLingui()
205 const {control} = React.useContext(Context)
206
207 return (
208 <Button
209 label={_(msg`Close this dialog`)}
210 size="small"
211 variant="ghost"
212 color="secondary"
213 onPress={() => control.close()}>
214 <ButtonText>
215 <Trans>Cancel</Trans>
216 </ButtonText>
217 </Button>
218 )
219}
220
221export function Divider() {
222 return null
223}