From 2b73935c76cc5f8d872681f85f0510f9e3941b2a Mon Sep 17 00:00:00 2001 From: Fernando Rojo Date: Mon, 13 Jun 2022 15:06:25 +0200 Subject: [PATCH 1/6] Delete lerna-debug.log --- lerna-debug.log | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 lerna-debug.log diff --git a/lerna-debug.log b/lerna-debug.log deleted file mode 100644 index 353fb55..0000000 --- a/lerna-debug.log +++ /dev/null @@ -1,3 +0,0 @@ -102 error HttpError: Bad credentials -102 error at /Users/fernandorojo/Developer/madison-hacks/zeeg/node_modules/@octokit/request/dist-node/index.js:86:21 -102 error at processTicksAndRejections (node:internal/process/task_queues:96:5) From 8dcf3b8d31492a5b166207dbc7f6dcf7629209e3 Mon Sep 17 00:00:00 2001 From: Nishan Date: Tue, 14 Jun 2022 21:15:13 +0530 Subject: [PATCH 2/6] feat: android menu --- README.md | 8 +- packages/zeego/package.json | 3 +- .../create-android-menu/index.android.tsx | 730 ++++++++++-------- yarn.lock | 269 +------ 4 files changed, 431 insertions(+), 579 deletions(-) diff --git a/README.md b/README.md index 9afadc3..e4b8a8b 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,12 @@ yarn add zeego Add peer deps: ```sh -yarn add react-native-ios-context-menu react-native-popper +yarn add react-native-ios-context-menu @react-native-menu/menu ``` ### Solito -Be sure to install `react-native-ios-context-menu` in your Expo folder (likely `apps/expo`). +Be sure to install `react-native-ios-context-menu` (for iOS menu) and `@react-native-menu/menu` (for Android menu) in your Expo folder (likely `apps/expo`). You should also follow the Next.js steps below. @@ -53,8 +53,6 @@ Run `pod install` in your `ios` folder. The API follows that of Radix UI closely. - - ## Usage ```ts @@ -104,14 +102,12 @@ Under the hood, `menuify` applies a `displayName` to your component. This allows ## Example - For now, you should reference the [example in the repo](https://github.com/nandorojo/zeego/tree/master/examples/expo/src/App.tsx). I also added a [Moti + Dripsy example](https://github.com/nandorojo/zeego/blob/master/moti-example.mdx). In the future, I'll make an example app with Solito too. - ```tsx const DropdownMenuExample = () => { const [bookmarked, setBookmarked] = useState<'on' | 'off' | 'mixed'>('on') diff --git a/packages/zeego/package.json b/packages/zeego/package.json index abbd4bb..5356f3d 100644 --- a/packages/zeego/package.json +++ b/packages/zeego/package.json @@ -69,7 +69,6 @@ "react": "17.0.1", "react-native": "0.64.2", "react-native-builder-bob": "^0.18.0", - "react-native-popper": "^0.3.2", "release-it": "^14.2.2", "typescript": "^4.4" }, @@ -77,7 +76,7 @@ "react": "*", "react-native": "*", "react-native-ios-context-menu": "*", - "react-native-popper": "*" + "@react-native-menu/menu": "*" }, "jest": { "preset": "react-native", diff --git a/packages/zeego/src/menu/create-android-menu/index.android.tsx b/packages/zeego/src/menu/create-android-menu/index.android.tsx index a3c9e7a..2305a37 100644 --- a/packages/zeego/src/menu/create-android-menu/index.android.tsx +++ b/packages/zeego/src/menu/create-android-menu/index.android.tsx @@ -1,356 +1,442 @@ -import React, { - Children, - cloneElement, - createContext, - ReactElement, - ReactNode, - useCallback, - useContext, - useMemo, - useRef, - useState, -} from 'react' -import { View, Pressable, Image, Text } from 'react-native' - -import type { createIosMenu } from '../create-ios-menu' +import React, { Children, ReactElement } from 'react' + +import { MenuView } from '@react-native-menu/menu' + +import { + flattenChildren, + pickChildren, + isInstanceOfComponent, +} from '../children' +import { menuify } from '../display-names' +import { filterNull } from '../filter-null' import type { - MenuCheckboxItemProps, MenuContentProps, MenuGroupProps, - MenuItemIconProps, - MenuItemImageProps, - MenuItemIndicatorProps, MenuItemProps, MenuItemSubtitleProps, MenuItemTitleProps, - MenuLabelProps, MenuRootProps, - MenuSeparatorProps, MenuTriggerItemProps, MenuTriggerProps, + MenuItemIconProps, + MenuCheckboxItemProps, + MenuSeparatorProps, + MenuItemImageProps, + MenuItemIndicatorProps, + MenuLabelProps, } from '../types' - -import { menuify } from '../display-names' - -import { Popover } from 'react-native-popper' -import { pickChildren } from '../children' - -type MenuVisibleContext = { - isOpen: boolean - onClose: () => void - onShow: () => void - onOpenChange: (next: boolean) => void - closeRootMenu: () => void - onToggleOpen: () => void -} - -const VirtualizedMenuContext = createContext(false) -const useIsNestedMenu = () => useContext(VirtualizedMenuContext) - -const MenuVisibleContext = createContext(null as any) - -const useMenuVisibleContext = () => useContext(MenuVisibleContext) - -const TriggerItem = menuify( - ({ - style, - onFocus, - onBlur, - textValue, - disabled, - children, - }: MenuTriggerItemProps) => { - const { onToggleOpen } = useMenuVisibleContext() - return ( - - {children} - - ) - }, - 'TriggerItem' -) - -function MenuProvider({ children }: { children: ReactNode }) { - const [isOpen, setOpen] = useState(false) - - const parentContext = useMenuVisibleContext() - - const isNestedMenu = !!parentContext - - const closeRootMenu = parentContext?.closeRootMenu - - return ( - ({ - isOpen, - onShow: () => setOpen(true), - onClose: () => setOpen(false), - onOpenChange: setOpen, - closeRootMenu: closeRootMenu ?? (() => setOpen(false)), - onToggleOpen: () => setOpen((prev) => !prev), - }), - [isOpen] - )} - > - - {children} - - - ) -} - -const TriggerElementContext = createContext(null as any) -const useTriggerElement = () => useContext(TriggerElementContext) - -const Root = menuify(({ children }: MenuRootProps) => { - const isNested = useIsNestedMenu() - - if (isNested) { - return {children} +import { View } from 'react-native' + +const createAndroidMenu = (Menu: 'ContextMenu' | 'DropdownMenu') => { + const Trigger = menuify(({ children, style }: MenuTriggerProps) => { + const child = <>{children} + + return {Children.only(child)} + }, 'Trigger') + + const Group = menuify(({ children }: MenuGroupProps) => { + return <>{children} + }, 'Group') + + const Content = menuify(({ children }: MenuContentProps) => { + if (!children) { + console.error(`[zeego] children must be written directly inline. + +You cannot wrap this component into its own component. It should look like this: + + + + + + + + +Notice that the are all children of the component. That's important. + +If you want to use a custom component as your , you can use the menuify() method. But you still need to pass all items as children of .`) + } + return <>{children} + }, 'Content') + + const ItemTitle = menuify(({ children }: MenuItemTitleProps) => { + if (typeof children != 'string') { + throw new Error('[zeego] child must be a string') + } + return <>{children} + }, 'ItemTitle') + + const ItemIcon = menuify((props: MenuItemIconProps) => { + if (!props.iosIconName) { + console.warn( + '[zeego] missing iosIconName prop. Will do nothing on iOS. Consider passing an iosIconImage or switching to .' + ) + } + return <>{} + }, 'ItemIcon') + + const ItemImage = menuify((props: MenuItemImageProps) => { + // if (!props.source) { + // console.error('[zeego] missing source prop.') + // } + if (!props.iosIconName) { + console.warn( + '[zeego] will not use your custom image on iOS. You should use the iosIconName prop to render an icon on iOS too.' + ) + } + return <>{} + }, 'ItemImage') + + const ItemSubtitle = menuify(({ children }: MenuItemSubtitleProps) => { + if (children && typeof children != 'string') { + throw new Error('[zeego] child must be a string') + } + return <>{children} + }, 'ItemSubtitle') + + const Item = menuify(({ children }: MenuItemProps) => { + const titleChild = pickChildren(children, ItemTitle).targetChildren + if (typeof children != 'string' && !titleChild?.length) { + console.error( + `[zeego] Invalid . It either needs in the children. + + + + Title here + + + ` + ) + } + return <>{children} + }, 'Item') + + const TriggerItem = menuify(({ children }: MenuTriggerItemProps) => { + const titleChild = pickChildren(children, ItemTitle).targetChildren + if (typeof children != 'string' && !titleChild?.length) { + console.error( + `[zeego] Invalid . It either needs a string as the children, or a in the children. However, it got neither. + + + + + Title here + + + ` + ) + } + return <>{children} + }, 'TriggerItem') + + const CheckboxItem = menuify(({}: MenuCheckboxItemProps) => { + return <> + }, 'CheckboxItem') + + const Label = menuify(({ children }: MenuLabelProps) => { + if (typeof children != 'string') { + console.error('[zeego]