refactor(API): ✨ Relspect integration
This commit is contained in:
316
tooldoc/ORANGURU.md
Normal file
316
tooldoc/ORANGURU.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
npm install @warkypublic/oranguru
|
||||
```
|
||||
|
||||
### Peer Dependencies
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```tsx
|
||||
import { MantineBetterMenusProvider } from '@warkypublic/oranguru';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<MantineProvider>
|
||||
<MantineBetterMenusProvider>
|
||||
{/* Your app content */}
|
||||
</MantineBetterMenusProvider>
|
||||
</MantineProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Using Context Menus
|
||||
|
||||
```tsx
|
||||
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
|
||||
|
||||
```tsx
|
||||
const asyncMenuItem = {
|
||||
label: 'Sync Data',
|
||||
onClickAsync: async () => {
|
||||
await fetch('/api/sync', { method: 'POST' });
|
||||
// Shows loading state automatically
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Custom Menu Items
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
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
|
||||
|
||||
1. **Provider Placement**: Place MantineBetterMenusProvider at the root of your app
|
||||
2. **Menu IDs**: Use descriptive, unique IDs for each menu type
|
||||
3. **Context Menus**: Always prevent default on right-click events
|
||||
4. **Loading States**: Use onClickAsync for async operations to get automatic loading states
|
||||
5. **Custom Renderers**: Use custom renderers for complex menu items with icons, badges, etc.
|
||||
6. **Portal Rendering**: Oranguru uses portals for proper z-index handling
|
||||
7. **State Management**: Leverage Zustand store for complex menu state
|
||||
8. **Accessibility**: Ensure keyboard navigation works with context menus
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Multi-Select Context Menu
|
||||
```tsx
|
||||
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
|
||||
```tsx
|
||||
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:
|
||||
|
||||
1. **User Management Grid**: Use DataTable with context menus for user actions
|
||||
2. **Hook Configuration**: Form with validation and async submission
|
||||
3. **WhatsApp Account Management**: Grid with QR code display and pairing actions
|
||||
4. **API Key Management**: Grid with copy-to-clipboard and revoke actions
|
||||
5. **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/
|
||||
Reference in New Issue
Block a user