49 lines
1.7 KiB
TypeScript
49 lines
1.7 KiB
TypeScript
import React, { useSyncExternalStore } from 'react';
|
|
import { Avatar, Box, Text } from 'folds';
|
|
import { UILocation } from '@paarrot/plugin-manager';
|
|
import { NavItem, NavButton, NavItemContent } from '../../../components/nav';
|
|
import { pluginRegistry } from './PluginAPI';
|
|
import { subscribeToButtons, getStoreVersion } from './PluginButtonSlot';
|
|
|
|
interface PluginNavSlotProps {
|
|
/** The UI location to render nav list entries for. */
|
|
location: UILocation;
|
|
}
|
|
|
|
/**
|
|
* Renders plugin buttons as `NavItem` list entries, matching the style of
|
|
* built-in sidebar items like "Create Room" and "Message Search".
|
|
* Intended for locations that live inside the channel / room list, not toolbars.
|
|
*/
|
|
export function PluginNavSlot({ location }: PluginNavSlotProps): React.ReactElement | null {
|
|
useSyncExternalStore(subscribeToButtons, getStoreVersion);
|
|
|
|
const buttons = pluginRegistry.getButtonsForLocation(location);
|
|
if (buttons.length === 0) return null;
|
|
|
|
return (
|
|
<>
|
|
{buttons.map((button) => (
|
|
<NavItem key={button.id} variant="Background" radii="400">
|
|
<NavButton onClick={() => button.onClick?.()}>
|
|
<NavItemContent>
|
|
<Box as="span" grow="Yes" alignItems="Center" gap="200">
|
|
<Avatar size="200" radii="400">
|
|
<span aria-hidden style={{ fontSize: '1em', lineHeight: 1 }}>
|
|
{button.icon ?? '🔌'}
|
|
</span>
|
|
</Avatar>
|
|
<Box as="span" grow="Yes">
|
|
<Text as="span" size="Inherit" truncate>
|
|
{button.label}
|
|
</Text>
|
|
</Box>
|
|
</Box>
|
|
</NavItemContent>
|
|
</NavButton>
|
|
</NavItem>
|
|
))}
|
|
</>
|
|
);
|
|
}
|