diff options
Diffstat (limited to 'src/components/molecules')
| -rw-r--r-- | src/components/molecules/layout/meta.stories.tsx | 57 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.test.tsx | 8 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.tsx | 70 | 
3 files changed, 135 insertions, 0 deletions
| diff --git a/src/components/molecules/layout/meta.stories.tsx b/src/components/molecules/layout/meta.stories.tsx new file mode 100644 index 0000000..e7a932d --- /dev/null +++ b/src/components/molecules/layout/meta.stories.tsx @@ -0,0 +1,57 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import MetaComponent from './meta'; + +export default { +  title: 'Molecules/Layout', +  component: MetaComponent, +  argTypes: { +    className: { +      control: { +        type: 'text', +      }, +      description: 'Set additional classnames to the meta wrapper.', +      table: { +        category: 'Styles', +      }, +      type: { +        name: 'string', +        required: false, +      }, +    }, +    meta: { +      control: { +        type: null, +      }, +      description: 'The page metadata.', +      type: { +        name: 'object', +        required: true, +        value: {}, +      }, +    }, +  }, +} as ComponentMeta<typeof MetaComponent>; + +const Template: ComponentStory<typeof MetaComponent> = (args) => ( +  <MetaComponent {...args} /> +); + +const data = { +  publication: { name: 'Published on:', value: 'April 9th 2022' }, +  categories: { +    name: 'Categories:', +    value: [ +      <a key="category1" href="#"> +        Category 1 +      </a>, +      <a key="category2" href="#"> +        Category 2 +      </a>, +    ], +  }, +}; + +export const Meta = Template.bind({}); +Meta.args = { +  data, +}; diff --git a/src/components/molecules/layout/meta.test.tsx b/src/components/molecules/layout/meta.test.tsx new file mode 100644 index 0000000..a738bdb --- /dev/null +++ b/src/components/molecules/layout/meta.test.tsx @@ -0,0 +1,8 @@ +import { render } from '@test-utils'; +import Meta from './meta'; + +describe('Meta', () => { +  it('renders a Meta component', () => { +    render(<Meta data={{}} />); +  }); +}); diff --git a/src/components/molecules/layout/meta.tsx b/src/components/molecules/layout/meta.tsx new file mode 100644 index 0000000..ace6f89 --- /dev/null +++ b/src/components/molecules/layout/meta.tsx @@ -0,0 +1,70 @@ +import DescriptionList, { +  type DescriptionListProps, +  type DescriptionListItem, +} from '@components/atoms/lists/description-list'; +import { ReactNode, VFC } from 'react'; + +export type MetaItem = { +  /** +   * The meta name. +   */ +  name: string; +  /** +   * The meta value. +   */ +  value: ReactNode | ReactNode[]; +}; + +export type MetaMap = { +  [key: string]: MetaItem | undefined; +}; + +export type MetaProps = { +  /** +   * Set additional classnames to the meta wrapper. +   */ +  className?: string; +  /** +   * The meta data. +   */ +  data: MetaMap; +  /** +   * The meta layout. +   */ +  layout?: DescriptionListProps['layout']; +}; + +/** + * Meta component + * + * Renders the page metadata. + */ +const Meta: VFC<MetaProps> = ({ data, ...props }) => { +  /** +   * Transform the metadata to description list item format. +   * +   * @param {MetaMap} items - The meta. +   * @returns {DescriptionListItem[]} The formatted description list items. +   */ +  const getItems = (items: MetaMap): DescriptionListItem[] => { +    const listItems: DescriptionListItem[] = Object.entries(items) +      .map(([key, item]) => { +        if (!item) return; + +        const { name, value } = item; + +        return { +          id: key, +          term: name, +          value: Array.isArray(value) ? value : [value], +        } as DescriptionListItem; +      }) +      .filter((item): item is DescriptionListItem => !!item); + +    return listItems; +  }; + +  return <DescriptionList items={getItems(data)} {...props} />; +}; + +export default Meta; | 
