/** @jsx h */ import { h, render } from 'preact'; import { cx } from '@algolia/ui-components-shared'; import type { BreadcrumbComponentCSSClasses, BreadcrumbComponentTemplates, } from '../../components/Breadcrumb/Breadcrumb'; import Breadcrumb from '../../components/Breadcrumb/Breadcrumb'; import type { BreadcrumbWidgetDescription, BreadcrumbConnectorParams, BreadcrumbRenderState, } from '../../connectors/breadcrumb/connectBreadcrumb'; import connectBreadcrumb from '../../connectors/breadcrumb/connectBreadcrumb'; import defaultTemplates from './defaultTemplates'; import { getContainerNode, createDocumentationMessageGenerator, } from '../../lib/utils'; import { prepareTemplateProps } from '../../lib/templating'; import { component } from '../../lib/suit'; import type { WidgetFactory, Template, Renderer } from '../../types'; import type { PreparedTemplateProps } from '../../lib/templating'; const withUsage = createDocumentationMessageGenerator({ name: 'breadcrumb' }); const suit = component('Breadcrumb'); const renderer = ({ containerNode, cssClasses, renderState, templates, }: { containerNode: HTMLElement; cssClasses: BreadcrumbComponentCSSClasses; renderState: { templateProps?: PreparedTemplateProps; }; templates: BreadcrumbTemplates; }): Renderer> => ( { canRefine, createURL, instantSearchInstance, items, refine }, isFirstRendering ) => { if (isFirstRendering) { renderState.templateProps = prepareTemplateProps({ defaultTemplates, templatesConfig: instantSearchInstance.templatesConfig, templates, }); return; } render( , containerNode ); }; export type BreadcrumbCSSClasses = Partial<{ /** * CSS class to add to the root element of the widget. */ root: string | string[]; /** * CSS class to add to the root element of the widget if there are no refinements. */ noRefinementRoot: string | string[]; /** * CSS class to add to the list element. */ list: string | string[]; /** * CSS class to add to the items of the list. The items contains the link and the separator. */ item: string | string[]; /** * CSS class to add to the selected item in the list: the last one or the home if there are no refinements. */ selectedItem: string | string[]; /** * CSS class to add to the separator. */ separator: string | string[]; /** * CSS class to add to the links in the items. */ link: string | string[]; }>; export type BreadcrumbTemplates = Partial<{ /** * Label of the breadcrumb's first element. */ home: Template; /** * Symbol used to separate the elements of the breadcrumb. */ separator: Template; }>; export type BreadcrumbWidgetParams = { /** * CSS Selector or HTMLElement to insert the widget. */ container: string | HTMLElement; /** * Templates to use for the widget. */ templates?: BreadcrumbTemplates; /** * CSS classes to add to the wrapping elements. */ cssClasses?: BreadcrumbCSSClasses; }; export type BreadcrumbWidget = WidgetFactory< BreadcrumbWidgetDescription & { $$widgetType: 'ais.breadcrumb' }, BreadcrumbConnectorParams, BreadcrumbWidgetParams >; const breadcrumb: BreadcrumbWidget = function breadcrumb(widgetParams) { const { container, attributes, separator, rootPath, transformItems, templates = {}, cssClasses: userCssClasses = {}, } = widgetParams || {}; if (!container) { throw new Error(withUsage('The `container` option is required.')); } const containerNode = getContainerNode(container); const cssClasses = { root: cx(suit(), userCssClasses.root), noRefinementRoot: cx( suit({ modifierName: 'noRefinement' }), userCssClasses.noRefinementRoot ), list: cx(suit({ descendantName: 'list' }), userCssClasses.list), item: cx(suit({ descendantName: 'item' }), userCssClasses.item), selectedItem: cx( suit({ descendantName: 'item', modifierName: 'selected' }), userCssClasses.selectedItem ), separator: cx( suit({ descendantName: 'separator' }), userCssClasses.separator ), link: cx(suit({ descendantName: 'link' }), userCssClasses.link), }; const specializedRenderer = renderer({ containerNode, cssClasses, renderState: {}, templates, }); const makeWidget = connectBreadcrumb(specializedRenderer, () => render(null, containerNode) ); return { ...makeWidget({ attributes, separator, rootPath, transformItems }), $$widgetType: 'ais.breadcrumb', }; }; export default breadcrumb;