7.6 KiB
Oranguru Integration Guide
Overview
Oranguru is a React component library that provides enhanced Mantine-based components with advanced features and state management capabilities. For WhatsHooked, we'll use it to build data grids and forms for the admin interface.
Installation
npm install @warkypublic/oranguru
Peer Dependencies
npm install react zustand @mantine/core @mantine/hooks @warkypublic/artemis-kit @warkypublic/zustandsyncstore use-sync-external-store
Core Concepts
Enhanced Context Menus
Oranguru provides better menu positioning and visibility control than standard Mantine menus.
Custom Rendering
Support for custom menu item renderers and complete menu rendering.
State Management
Uses Zustand for component state management with sync capabilities.
Basic Setup
import { MantineBetterMenusProvider } from '@warkypublic/oranguru';
import { MantineProvider } from '@mantine/core';
function App() {
return (
<MantineProvider>
<MantineBetterMenusProvider>
{/* Your app content */}
</MantineBetterMenusProvider>
</MantineProvider>
);
}
Using Context Menus
import { useMantineBetterMenus } from '@warkypublic/oranguru';
function DataGrid() {
const { show, hide } = useMantineBetterMenus();
const handleContextMenu = (e: React.MouseEvent, record: any) => {
e.preventDefault();
show('record-menu', {
x: e.clientX,
y: e.clientY,
items: [
{
label: 'Edit',
onClick: () => handleEdit(record)
},
{
label: 'Delete',
onClick: () => handleDelete(record)
},
{
isDivider: true
},
{
label: 'View Details',
onClick: () => handleViewDetails(record)
}
]
});
};
return (
<table>
{records.map(record => (
<tr key={record.id} onContextMenu={(e) => handleContextMenu(e, record)}>
<td>{record.name}</td>
</tr>
))}
</table>
);
}
Async Actions
const asyncMenuItem = {
label: 'Sync Data',
onClickAsync: async () => {
await fetch('/api/sync', { method: 'POST' });
// Shows loading state automatically
}
};
Custom Menu Items
const customItem = {
renderer: ({ loading }: any) => (
<div style={{ padding: '8px 12px' }}>
{loading ? (
<Loader size="xs" />
) : (
<Group>
<IconCheck size={16} />
<Text>Custom Action</Text>
</Group>
)}
</div>
),
onClickAsync: async () => {
await performAction();
}
};
Integration with Data Grids
While Oranguru doesn't provide a built-in data grid component yet, it works excellently with Mantine's DataTable or custom table implementations:
import { useMantineBetterMenus } from '@warkypublic/oranguru';
import { DataTable } from '@mantine/datatable';
function UserGrid() {
const { show } = useMantineBetterMenus();
const [users, setUsers] = useState([]);
const columns = [
{ accessor: 'name', title: 'Name' },
{ accessor: 'email', title: 'Email' },
{ accessor: 'status', title: 'Status' }
];
const handleRowContextMenu = (e: React.MouseEvent, user: User) => {
e.preventDefault();
show('user-menu', {
x: e.clientX,
y: e.clientY,
items: [
{
label: 'Edit User',
onClick: () => navigate(`/users/${user.id}/edit`)
},
{
label: 'Deactivate',
onClickAsync: async () => {
await fetch(`/api/users/${user.id}/deactivate`, { method: 'POST' });
await refreshUsers();
}
},
{
isDivider: true
},
{
label: 'Delete',
onClick: () => handleDelete(user.id)
}
]
});
};
return (
<DataTable
columns={columns}
records={users}
onRowContextMenu={({ event, record }) => handleRowContextMenu(event, record)}
/>
);
}
Form Integration
For forms, use Mantine's form components with Oranguru's menu system for enhanced UX:
import { useForm } from '@mantine/form';
import { TextInput, Select, Button } from '@mantine/core';
function UserForm() {
const form = useForm({
initialValues: {
name: '',
email: '',
role: ''
},
validate: {
email: (value) => (/^\S+@\S+$/.test(value) ? null : 'Invalid email'),
name: (value) => (value.length < 2 ? 'Name too short' : null)
}
});
const handleSubmit = async (values: typeof form.values) => {
try {
await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(values)
});
notifications.show({ message: 'User created successfully' });
} catch (error) {
notifications.show({
message: 'Failed to create user',
color: 'red'
});
}
};
return (
<form onSubmit={form.onSubmit(handleSubmit)}>
<TextInput
label="Name"
placeholder="John Doe"
{...form.getInputProps('name')}
/>
<TextInput
label="Email"
placeholder="john@example.com"
{...form.getInputProps('email')}
/>
<Select
label="Role"
data={['Admin', 'User', 'Viewer']}
{...form.getInputProps('role')}
/>
<Button type="submit">Create User</Button>
</form>
);
}
Best Practices
- Provider Placement: Place MantineBetterMenusProvider at the root of your app
- Menu IDs: Use descriptive, unique IDs for each menu type
- Context Menus: Always prevent default on right-click events
- Loading States: Use onClickAsync for async operations to get automatic loading states
- Custom Renderers: Use custom renderers for complex menu items with icons, badges, etc.
- Portal Rendering: Oranguru uses portals for proper z-index handling
- State Management: Leverage Zustand store for complex menu state
- Accessibility: Ensure keyboard navigation works with context menus
Common Patterns
Multi-Select Context Menu
const handleBulkContextMenu = (e: React.MouseEvent, selectedIds: string[]) => {
e.preventDefault();
show('bulk-menu', {
x: e.clientX,
y: e.clientY,
items: [
{
label: `Delete ${selectedIds.length} items`,
onClickAsync: async () => {
await bulkDelete(selectedIds);
}
},
{
label: 'Export selection',
onClick: () => exportItems(selectedIds)
}
]
});
};
Conditional Menu Items
const menuItems = [
{
label: 'Edit',
onClick: () => handleEdit(record)
},
canDelete(record) && {
label: 'Delete',
onClick: () => handleDelete(record)
},
{
isDivider: true
},
isAdmin && {
label: 'Admin Actions',
onClick: () => showAdminActions(record)
}
].filter(Boolean); // Remove falsy items
Nested Menus (Future Feature)
While not yet supported, Oranguru is designed to support nested menus in future versions.
Integration with WhatsHooked
For WhatsHooked's admin interface:
- User Management Grid: Use DataTable with context menus for user actions
- Hook Configuration: Form with validation and async submission
- WhatsApp Account Management: Grid with QR code display and pairing actions
- API Key Management: Grid with copy-to-clipboard and revoke actions
- Event Logs: Read-only grid with filtering and export
References
- Official Repository: https://git.warky.dev/wdevs/oranguru
- Mantine Documentation: https://mantine.dev
- Mantine DataTable: https://icflorescu.github.io/mantine-datatable/