Skip to content

Commit

Permalink
feat(experiences): add separate banner component (#6356)
Browse files Browse the repository at this point in the history
  • Loading branch information
Haroenv authored Sep 11, 2024
1 parent 67dfc82 commit 9c6bd28
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 0 deletions.
98 changes: 98 additions & 0 deletions packages/algolia-experiences/src/banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/** @jsx h */

import { cx } from 'instantsearch-ui-components';
import { connectHits } from 'instantsearch.js/es/connectors';
import { h, render } from 'preact';

import type { Banner } from 'algoliasearch-helper';
import type {
ComponentProps,
HitsClassNames,
} from 'instantsearch-ui-components';
import type { HitsConnectorParams } from 'instantsearch.js/es/connectors/hits/connectHits';

export type BannerWidgetParams = {
container: HTMLElement;
classNames?: BannerClassNames;
};

type BannerClassNames = Pick<
Partial<HitsClassNames>,
'bannerRoot' | 'bannerLink' | 'bannerImage'
>;

type BannerProps = ComponentProps<'aside'> & {
banner?: Banner;
classNames: BannerClassNames;
};

function DefaultBanner(props: BannerProps) {
if (!props.banner || !props.banner.image) {
return null;
}
if (!props.banner.image.urls[0].url) {
return null;
}
return (
<aside className={cx('ais-Hits-banner', props.classNames.bannerRoot)}>
{props.banner.link ? (
<a
className={cx('ais-Hits-banner-link', props.classNames.bannerLink)}
href={props.banner.link.url}
target={props.banner.link.target}
>
<img
className={cx(
'ais-Hits-banner-image',
props.classNames.bannerImage
)}
src={props.banner.image.urls[0].url}
alt={props.banner.image.title}
/>
</a>
) : (
<img
className={cx('ais-Hits-banner-image', props.classNames.bannerImage)}
src={props.banner.image.urls[0].url}
alt={props.banner.image.title}
/>
)}
</aside>
);
}

function renderer({
container,
classNames,
}: {
container: HTMLElement;
classNames: BannerClassNames;
}) {
return (props: { banner?: Banner }) =>
render(
<DefaultBanner banner={props.banner} classNames={classNames} />,
container
);
}

export function banner(widgetParams: BannerWidgetParams & HitsConnectorParams) {
const { container, classNames = {} } = widgetParams || {};

if (!container) {
throw new Error('The `container` option is required.');
}

const specializedRenderer = renderer({
container,
classNames,
});

const makeWidget = connectHits(specializedRenderer, () =>
render(null, container)
);

return {
$$widgetType: 'ais.experiences-banner',
...makeWidget({}),
};
}
9 changes: 9 additions & 0 deletions packages/algolia-experiences/src/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ function blockToWidget(child: Block, container: HTMLElement): Widget[] {
.flat(1);
}

if (child.type === 'banner') {
return [
widgets.banner({
container: widgetContainer,
}),
];
}

if (isTemplateWidget(child)) {
// type cast is needed here because the spread adding `container` and `templates` loses the type discriminant
const parameters = child.parameters as Parameters<
Expand All @@ -171,6 +179,7 @@ function blockToWidget(child: Block, container: HTMLElement): Widget[] {
...parameters,
container: widgetContainer,
templates: {
banner: () => null,
item: (hit: any, { components }) => {
if (!child.children.length) {
return <code> no item template given</code>;
Expand Down
3 changes: 3 additions & 0 deletions packages/algolia-experiences/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ export type Block =
| {
type: 'column';
children: Block[];
}
| {
type: 'banner';
};

export type Configuration = {
Expand Down
3 changes: 3 additions & 0 deletions packages/algolia-experiences/src/widgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import {
trendingItems,
} from 'instantsearch.js/es/widgets';

import { banner } from './banner';

export const widgets = {
banner,
'ais.breadcrumb': breadcrumb,
'ais.clearRefinements': clearRefinements,
'ais.configure': configure,
Expand Down

0 comments on commit 9c6bd28

Please sign in to comment.