import { TypeGuards } from '@codeleap/types' import { memoBy } from '@codeleap/utils' import { Button } from '../Button' import { AugmentedSectionRenderItemInfo, SectionComponentProps, Sections } from '../Sections' import { Text } from '../Text' import { SectionsFilterContext, useSectionFiltersContext } from './context' import { SectionFilterComponentProps, SectionFiltersProps } from './types' import { TSectionFilterItem, useSectionFilters } from './useSectionFilters' export * from './types' export * from './context' export * from './useSectionFilters' const SectionComponent = memoBy((props: SectionComponentProps & { renderWith: (props: SectionFilterComponentProps) => React.ReactElement }) => { const { renderWith: Component, index } = props const handle = useSectionFiltersContext() if (!Component) return null return ( handle.clearSelectedItemsWithSection(index)} /> ) }, ['renderWith']) /** * `handle` can be provided externally to make the filter state controlled from outside; * if omitted, an internal `useSectionFilters` instance is created from the same props. * Either way, the handle is published to `SectionsFilterContext` so `renderSectionHeader` * and `renderSectionFooter` can read per-section selection state via `useSectionFiltersContext`. */ export function SectionFilters(props: SectionFiltersProps) { const { sections, renderItem: RenderItem, renderSectionHeader, renderSectionFooter, children, ...rest } = { ...SectionFilters.defaultProps, ...props, } const handle = props.handle ?? useSectionFilters(props) const renderItem = (section: AugmentedSectionRenderItemInfo) => { const hasSection = !TypeGuards.isNil(section?.index) && !TypeGuards.isNil(section) const sectionLimitReached = hasSection && handle.sectionLimitReached(section?.index) const limitReached = handle.limitReached() const disableOnReachLimit = handle.disableItemsOnLimitReached const disableNonSelectedItems = (limitReached || sectionLimitReached) && disableOnReachLimit const isSelected = handle.isSelected(section?.item) const isDisabled = disableNonSelectedItems && !isSelected return ( handle.toggleItem(section?.item)} selected={isSelected} disabled={isDisabled} text={section?.item?.label} /> ) } return ( } renderSectionFooter={(props) => } /> {children} ) } SectionFilters.defaultProps = { renderItem: Button as unknown, renderSectionHeader: ({ title }) => } as Partial