react-native-anchored-menu 0.0.7 β 0.0.9
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.
- package/README.md +64 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -122,6 +122,70 @@ open({
|
|
|
122
122
|
|
|
123
123
|
---
|
|
124
124
|
|
|
125
|
+
## πͺ Using inside React Native `<Modal>`
|
|
126
|
+
|
|
127
|
+
React Native `<Modal>` is rendered in a separate native layer. To ensure the menu appears **above** the modal content, mount a provider/layer **inside** the modal tree.
|
|
128
|
+
|
|
129
|
+
**Sheets & overlays**:
|
|
130
|
+
|
|
131
|
+
- **Native-layer overlays** (RN `<Modal>`, `react-native-navigation` modals/overlays, etc.): mount `AnchoredMenuLayer` inside that overlayβs content tree.
|
|
132
|
+
- **JS-only sheets** (rendered as normal React views in the same tree): you can keep a single provider at the app root.
|
|
133
|
+
|
|
134
|
+
Recommended:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import React, { useState } from "react";
|
|
138
|
+
import { Modal, Pressable, Text, View } from "react-native";
|
|
139
|
+
import {
|
|
140
|
+
AnchoredMenuLayer,
|
|
141
|
+
MenuAnchor,
|
|
142
|
+
useAnchoredMenuActions,
|
|
143
|
+
} from "react-native-anchored-menu";
|
|
144
|
+
|
|
145
|
+
export function ExampleModalMenu() {
|
|
146
|
+
const [visible, setVisible] = useState(false);
|
|
147
|
+
const { open } = useAnchoredMenuActions();
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<>
|
|
151
|
+
<Pressable onPress={() => setVisible(true)}>
|
|
152
|
+
<Text>Open modal</Text>
|
|
153
|
+
</Pressable>
|
|
154
|
+
|
|
155
|
+
<Modal transparent visible={visible} onRequestClose={() => setVisible(false)}>
|
|
156
|
+
<AnchoredMenuLayer>
|
|
157
|
+
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
|
|
158
|
+
<MenuAnchor id="modal-menu">
|
|
159
|
+
<Pressable
|
|
160
|
+
onPress={() =>
|
|
161
|
+
open({
|
|
162
|
+
id: "modal-menu",
|
|
163
|
+
host: "view",
|
|
164
|
+
render: ({ close }) => (
|
|
165
|
+
<View style={{ backgroundColor: "#111", padding: 12, borderRadius: 8 }}>
|
|
166
|
+
<Pressable onPress={close}>
|
|
167
|
+
<Text style={{ color: "#fff" }}>Action</Text>
|
|
168
|
+
</Pressable>
|
|
169
|
+
</View>
|
|
170
|
+
),
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
>
|
|
174
|
+
<Text>Open menu</Text>
|
|
175
|
+
</Pressable>
|
|
176
|
+
</MenuAnchor>
|
|
177
|
+
|
|
178
|
+
<Pressable onPress={() => setVisible(false)}>
|
|
179
|
+
<Text>Close modal</Text>
|
|
180
|
+
</Pressable>
|
|
181
|
+
</View>
|
|
182
|
+
</AnchoredMenuLayer>
|
|
183
|
+
</Modal>
|
|
184
|
+
</>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
125
189
|
## π§ API
|
|
126
190
|
|
|
127
191
|
### `useAnchoredMenuActions()`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-anchored-menu",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Headless anchored menu/popover for React Native with stable measurement (view host by default).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"react": "*",
|
|
31
31
|
"react-native": "*"
|
|
32
32
|
},
|
|
33
|
-
"readme": "# react-native-anchored-menu\n\nA **headless, anchor-based menu / popover system for React Native** designed to work reliably across:\n\n- iOS & Android\n- FlatList / SectionList\n- Complex layouts\n- New Architecture (Fabric)\n- Modal & non-modal contexts\n\nThis library focuses on **correct measurement and positioning**, not UI. \nYou fully control how the menu looks and behaves.\n\n---\n\n## π¬ Demo\n\n| View host (normal screens) | View host inside native `<Modal>` |\n| --- | --- |\n|  |  |\n\n---\n\n## β¨ Why this library exists\n\nMost React Native menu / popover libraries break in at least one of these cases:\n\n- Wrong position on Android\n- Unreliable measurement inside FlatList\n- Broken behavior with Fabric\n- Rendering behind or inside unexpected layers\n- Forced UI and styling\n\n**react-native-anchored-menu** solves these by:\n\n- Using **stable anchor measurement**\n- Separating **state (Provider)** from **rendering (Hosts)**\n- Supporting multiple rendering strategies (View / Modal)\n- Staying **100% headless**\n\n---\n\n## β
Features\n\n- π Anchor menus to any component\n- π Accurate positioning (`auto`, `top`, `bottom`)\n- π§ FlatList-safe measurement\n- πͺ Works inside and outside native `<Modal>`\n- π§© Fully headless render API\n- π§Ή Tap outside to dismiss\n- π Auto-close on scroll (optional)\n- π RTL-aware positioning\n- π§± Multiple host strategies\n\n---\n\n## π¦ Installation\n\n```bash\nnpm install react-native-anchored-menu\n# or\nyarn add react-native-anchored-menu\n```\n\nNo native linking required.\n\n---\n\n## π Basic Usage\n\n### 1οΈβ£ Wrap your app\n\n```tsx\nimport { AnchoredMenuProvider } from \"react-native-anchored-menu\";\n\nexport default function Root() {\n return (\n <AnchoredMenuProvider>\n <App />\n </AnchoredMenuProvider>\n );\n}\n```\n\n> β οΈ You **do NOT need** to manually mount any host by default. \n> Hosts are automatically mounted internally.\n\n---\n\n### 2οΈβ£ Add an anchor\n\n```tsx\nimport { MenuAnchor } from \"react-native-anchored-menu\";\n\n<MenuAnchor id=\"profile-menu\">\n <Pressable>\n <Text>Open menu</Text>\n </Pressable>\n</MenuAnchor>\n```\n\n---\n\n### 3οΈβ£ Open the menu\n\n```tsx\nimport { useAnchoredMenuActions } from \"react-native-anchored-menu\";\n\nconst { open, close } = useAnchoredMenuActions();\n\nopen({\n id: \"profile-menu\",\n render: ({ close }) => (\n <View style={{ backgroundColor: \"#111\", padding: 12, borderRadius: 8 }}>\n <Pressable onPress={close}>\n <Text style={{ color: \"#fff\" }}>Logout</Text>\n </Pressable>\n </View>\n ),\n});\n```\n\n---\n\n## π§ API\n\n### `useAnchoredMenuActions()`\n\n```ts\nconst { open, close } = useAnchoredMenuActions();\n```\n\n### `useAnchoredMenuState(selector?)`\n\n```ts\nconst isOpen = useAnchoredMenuState((s) => s.isOpen);\n```\n\n**Recommended (performance)**: prefer split hooks in large trees to reduce re-renders:\n\n```ts\nconst isOpen = useAnchoredMenuState((s) => s.isOpen);\nconst { open } = useAnchoredMenuActions();\n```\n\n> `useAnchoredMenu()` is still available for backwards compatibility, but the split hooks are recommended\n> to reduce re-renders in large trees.\n\n---\n\n### `open(options)`\n\n```ts\nopen({\n id: string;\n\n placement?: \"auto\" | \"top\" | \"bottom\";\n align?: \"start\" | \"center\" | \"end\";\n offset?: number;\n margin?: number;\n rtlAware?: boolean;\n\n render?: ({ close, anchor }) => ReactNode;\n content?: ReactNode;\n\n host?: \"view\" | \"modal\";\n\n animationType?: \"fade\" | \"none\";\n statusBarTranslucent?: boolean;\n\n /**\n * Measurement strategy.\n * - \"stable\" (default): waits for interactions and retries for correctness (best for FlatList/Android)\n * - \"fast\": one-frame measure (lowest latency, less reliable on complex layouts)\n */\n measurement?: \"stable\" | \"fast\";\n\n /**\n * Only used when `measurement=\"stable\"` (default: 8).\n */\n measurementTries?: number;\n});\n```\n\n---\n\n## π§ Placement Behavior\n\n- `auto` β below if space allows, otherwise above\n- `top` β prefer above, fallback below\n- `bottom` β prefer below, fallback above\n\n---\n\n## π§± Host System\n\n- Default host: **view**\n- Hosts are auto-mounted\n- `modal` host is disabled on Fabric and falls back to `view`\n\n---\n\n## π License\n\nMIT Β© Mahmoud Elfeky\n"
|
|
33
|
+
"readme": "# react-native-anchored-menu\n\nA **headless, anchor-based menu / popover system for React Native** designed to work reliably across:\n\n- iOS & Android\n- FlatList / SectionList\n- Complex layouts\n- New Architecture (Fabric)\n- Modal & non-modal contexts\n\nThis library focuses on **correct measurement and positioning**, not UI. \nYou fully control how the menu looks and behaves.\n\n---\n\n## π¬ Demo\n\n| View host (normal screens) | View host inside native `<Modal>` |\n| --- | --- |\n|  |  |\n\n---\n\n## β¨ Why this library exists\n\nMost React Native menu / popover libraries break in at least one of these cases:\n\n- Wrong position on Android\n- Unreliable measurement inside FlatList\n- Broken behavior with Fabric\n- Rendering behind or inside unexpected layers\n- Forced UI and styling\n\n**react-native-anchored-menu** solves these by:\n\n- Using **stable anchor measurement**\n- Separating **state (Provider)** from **rendering (Hosts)**\n- Supporting multiple rendering strategies (View / Modal)\n- Staying **100% headless**\n\n---\n\n## β
Features\n\n- π Anchor menus to any component\n- π Accurate positioning (`auto`, `top`, `bottom`)\n- π§ FlatList-safe measurement\n- πͺ Works inside and outside native `<Modal>`\n- π§© Fully headless render API\n- π§Ή Tap outside to dismiss\n- π Auto-close on scroll (optional)\n- π RTL-aware positioning\n- π§± Multiple host strategies\n\n---\n\n## π¦ Installation\n\n```bash\nnpm install react-native-anchored-menu\n# or\nyarn add react-native-anchored-menu\n```\n\nNo native linking required.\n\n---\n\n## π Basic Usage\n\n### 1οΈβ£ Wrap your app\n\n```tsx\nimport { AnchoredMenuProvider } from \"react-native-anchored-menu\";\n\nexport default function Root() {\n return (\n <AnchoredMenuProvider>\n <App />\n </AnchoredMenuProvider>\n );\n}\n```\n\n> β οΈ You **do NOT need** to manually mount any host by default. \n> Hosts are automatically mounted internally.\n\n---\n\n### 2οΈβ£ Add an anchor\n\n```tsx\nimport { MenuAnchor } from \"react-native-anchored-menu\";\n\n<MenuAnchor id=\"profile-menu\">\n <Pressable>\n <Text>Open menu</Text>\n </Pressable>\n</MenuAnchor>\n```\n\n---\n\n### 3οΈβ£ Open the menu\n\n```tsx\nimport { useAnchoredMenuActions } from \"react-native-anchored-menu\";\n\nconst { open, close } = useAnchoredMenuActions();\n\nopen({\n id: \"profile-menu\",\n render: ({ close }) => (\n <View style={{ backgroundColor: \"#111\", padding: 12, borderRadius: 8 }}>\n <Pressable onPress={close}>\n <Text style={{ color: \"#fff\" }}>Logout</Text>\n </Pressable>\n </View>\n ),\n});\n```\n\n---\n\n## πͺ Using inside React Native `<Modal>`\n\nReact Native `<Modal>` is rendered in a separate native layer. To ensure the menu appears **above** the modal content, mount a provider/layer **inside** the modal tree.\n\n**Sheets & overlays**:\n\n- **Native-layer overlays** (RN `<Modal>`, `react-native-navigation` modals/overlays, etc.): mount `AnchoredMenuLayer` inside that overlayβs content tree.\n- **JS-only sheets** (rendered as normal React views in the same tree): you can keep a single provider at the app root.\n\nRecommended:\n\n```tsx\nimport React, { useState } from \"react\";\nimport { Modal, Pressable, Text, View } from \"react-native\";\nimport {\n AnchoredMenuLayer,\n MenuAnchor,\n useAnchoredMenuActions,\n} from \"react-native-anchored-menu\";\n\nexport function ExampleModalMenu() {\n const [visible, setVisible] = useState(false);\n const { open } = useAnchoredMenuActions();\n\n return (\n <>\n <Pressable onPress={() => setVisible(true)}>\n <Text>Open modal</Text>\n </Pressable>\n\n <Modal transparent visible={visible} onRequestClose={() => setVisible(false)}>\n <AnchoredMenuLayer>\n <View style={{ flex: 1, justifyContent: \"center\", alignItems: \"center\" }}>\n <MenuAnchor id=\"modal-menu\">\n <Pressable\n onPress={() =>\n open({\n id: \"modal-menu\",\n host: \"view\",\n render: ({ close }) => (\n <View style={{ backgroundColor: \"#111\", padding: 12, borderRadius: 8 }}>\n <Pressable onPress={close}>\n <Text style={{ color: \"#fff\" }}>Action</Text>\n </Pressable>\n </View>\n ),\n })\n }\n >\n <Text>Open menu</Text>\n </Pressable>\n </MenuAnchor>\n\n <Pressable onPress={() => setVisible(false)}>\n <Text>Close modal</Text>\n </Pressable>\n </View>\n </AnchoredMenuLayer>\n </Modal>\n </>\n );\n}\n```\n\n## π§ API\n\n### `useAnchoredMenuActions()`\n\n```ts\nconst { open, close } = useAnchoredMenuActions();\n```\n\n### `useAnchoredMenuState(selector?)`\n\n```ts\nconst isOpen = useAnchoredMenuState((s) => s.isOpen);\n```\n\n**Recommended (performance)**: prefer split hooks in large trees to reduce re-renders:\n\n```ts\nconst isOpen = useAnchoredMenuState((s) => s.isOpen);\nconst { open } = useAnchoredMenuActions();\n```\n\n> `useAnchoredMenu()` is still available for backwards compatibility, but the split hooks are recommended\n> to reduce re-renders in large trees.\n\n---\n\n### `open(options)`\n\n```ts\nopen({\n id: string;\n\n placement?: \"auto\" | \"top\" | \"bottom\";\n align?: \"start\" | \"center\" | \"end\";\n offset?: number;\n margin?: number;\n rtlAware?: boolean;\n\n render?: ({ close, anchor }) => ReactNode;\n content?: ReactNode;\n\n host?: \"view\" | \"modal\";\n\n animationType?: \"fade\" | \"none\";\n statusBarTranslucent?: boolean;\n\n /**\n * Measurement strategy.\n * - \"stable\" (default): waits for interactions and retries for correctness (best for FlatList/Android)\n * - \"fast\": one-frame measure (lowest latency, less reliable on complex layouts)\n */\n measurement?: \"stable\" | \"fast\";\n\n /**\n * Only used when `measurement=\"stable\"` (default: 8).\n */\n measurementTries?: number;\n});\n```\n\n---\n\n## π§ Placement Behavior\n\n- `auto` β below if space allows, otherwise above\n- `top` β prefer above, fallback below\n- `bottom` β prefer below, fallback above\n\n---\n\n## π§± Host System\n\n- Default host: **view**\n- Hosts are auto-mounted\n- `modal` host is disabled on Fabric and falls back to `view`\n\n---\n\n## π License\n\nMIT Β© Mahmoud Elfeky\n"
|
|
34
34
|
}
|