stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
102 lines (89 loc) • 4.12 kB
text/typescript
import React, { useMemo } from 'react';
import { useComponentsContext } from '../../../contexts/componentsContext/ComponentsContext';
import type { TranslationContextValue } from '../../../contexts/translationContext/TranslationContext';
import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
import type { IconProps } from '../../../icons/utils/base';
/**
* Identifies a navigation row. The literals are the built-in sections rendered by default;
* consumers can also add their own rows with arbitrary section identifiers via `getNavigationItems`,
* so any string is allowed.
*/
export type ChannelDetailsNavigationSectionType =
| 'pinned-messages'
| 'photos-and-videos'
| 'files'
| string;
/**
* A single row in the channel details navigation section.
*/
export type ChannelDetailsNavigationItem = {
/** Icon rendered at the start of the row and reused in the built-in modal header. */
Icon: React.ComponentType<IconProps>;
/** Already-translated label rendered for the row and its built-in modal header. */
label: string;
/** Identifies which built-in section this row represents. */
section: ChannelDetailsNavigationSectionType;
/**
* Fired when the user taps the row. Leave unset to keep the built-in behavior (opening the
* built-in modal for the section); set it to route the row somewhere else (e.g. your own screen).
*/
onPress?: () => void;
};
/**
* Maps each navigation section to the icon (by its key in the components-context icons map) and
* (translatable) label rendered for its row and, when opened, its modal header. The declaration
* order also drives the order of the rendered rows.
*/
const SECTION_CONFIG: Record<
'pinned-messages' | 'photos-and-videos' | 'files',
{ icon: 'Pin' | 'Picture' | 'Folder'; label: string }
> = {
'pinned-messages': { icon: 'Pin', label: 'Pinned Messages' },
'photos-and-videos': { icon: 'Picture', label: 'Photos & Videos' },
files: { icon: 'Folder', label: 'Files' },
};
const SECTIONS = Object.keys(SECTION_CONFIG) as Array<keyof typeof SECTION_CONFIG>;
export type ChannelDetailsNavigationItemsContext = {
t: TranslationContextValue['t'];
};
/**
* Customizes the navigation rows rendered by `ChannelDetailsNavigationSection`. Receives the
* built-in `defaultItems` (and a `context`) and returns the items to render. Map over
* `defaultItems` to set a row's `onPress` (e.g. to push your own screen), or add/remove rows. Any
* row whose `onPress` you leave unset keeps its built-in behavior (opening the built-in modal) —
* including sections added in future SDK versions.
*/
export type GetChannelDetailsNavigationItems = (params: {
context: ChannelDetailsNavigationItemsContext;
defaultItems: ChannelDetailsNavigationItem[];
}) => ChannelDetailsNavigationItem[];
export const getChannelDetailsNavigationItems: GetChannelDetailsNavigationItems = ({
defaultItems,
}) => defaultItems;
/**
* Builds the navigation rows rendered by `ChannelDetailsNavigationSection`. Returns the items as a
* plain array — the section component owns the built-in modal and supplies the default open-modal
* behavior for any row without a custom `onPress`. Customize the rows by passing `getNavigationItems`
* to `ChannelDetails` (see {@link GetChannelDetailsNavigationItems}).
*/
export const useChannelDetailsNavigationItems = ({
getNavigationItems = getChannelDetailsNavigationItems,
}: {
getNavigationItems?: GetChannelDetailsNavigationItems;
} = {}): ChannelDetailsNavigationItem[] => {
const { icons } = useComponentsContext();
const { t } = useTranslationContext();
const context = useMemo<ChannelDetailsNavigationItemsContext>(() => ({ t }), [t]);
const defaultItems = useMemo<ChannelDetailsNavigationItem[]>(
() =>
SECTIONS.map((section) => {
const { icon, label } = SECTION_CONFIG[section];
return { Icon: icons[icon], label: t(label), section };
}),
[icons, t],
);
return useMemo(
() => getNavigationItems({ context, defaultItems }),
[context, defaultItems, getNavigationItems],
);
};