From a3a4c50f26b8750ae1c87f1f1103b84b7d2e6315 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Tue, 14 Nov 2023 15:11:22 +0100
Subject: refactor(components): replace LinksListWidget with LinksWidget

* avoid List component repeat
* rewrite tests and CSS
* add an id to LinksWidgetItemData (previously LinksListItems) type
because the label could be duplicated
---
 .../widgets/links-widget/links-widget.tsx          | 78 ++++++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 src/components/organisms/widgets/links-widget/links-widget.tsx

(limited to 'src/components/organisms/widgets/links-widget/links-widget.tsx')

diff --git a/src/components/organisms/widgets/links-widget/links-widget.tsx b/src/components/organisms/widgets/links-widget/links-widget.tsx
new file mode 100644
index 0000000..e28e15f
--- /dev/null
+++ b/src/components/organisms/widgets/links-widget/links-widget.tsx
@@ -0,0 +1,78 @@
+import { type ForwardRefRenderFunction, forwardRef, useCallback } from 'react';
+import { Link, List, ListItem } from '../../../atoms';
+import { Collapsible, type CollapsibleProps } from '../../../molecules';
+import styles from './links-widget.module.scss';
+
+export type LinksWidgetItemData = {
+  /**
+   * An array of name/url couple child of this list item.
+   */
+  child?: LinksWidgetItemData[];
+  /**
+   * The item id.
+   */
+  id: string;
+  /**
+   * The item name.
+   */
+  label: string;
+  /**
+   * The item url.
+   */
+  url: string;
+};
+
+export type LinksWidgetProps = Omit<
+  CollapsibleProps,
+  'children' | 'disablePadding' | 'hasBorders'
+> & {
+  /**
+   * Should the links be ordered?
+   *
+   * @default false
+   */
+  isOrdered?: boolean;
+  /**
+   * The links.
+   */
+  items: LinksWidgetItemData[];
+};
+
+const LinksWidgetWithRef: ForwardRefRenderFunction<
+  HTMLDivElement,
+  LinksWidgetProps
+> = ({ isOrdered = false, items, ...props }, ref) => {
+  const listClass = [
+    styles.list,
+    styles[isOrdered ? 'list--ordered' : 'list--unordered'],
+  ].join(' ');
+
+  const getLinksList = useCallback(
+    (data: LinksWidgetItemData[]) => (
+      <List className={listClass} hideMarker isOrdered={isOrdered}>
+        {data.map((item) => (
+          <ListItem className={styles.item} key={item.id}>
+            <Link className={styles.link} href={item.url}>
+              {item.label}
+            </Link>
+            {item.child?.length ? getLinksList(item.child) : null}
+          </ListItem>
+        ))}
+      </List>
+    ),
+    [isOrdered, listClass]
+  );
+
+  return (
+    <Collapsible {...props} disablePadding hasBorders ref={ref}>
+      {getLinksList(items)}
+    </Collapsible>
+  );
+};
+
+/**
+ * LinksWidget component
+ *
+ * Render a list of links inside a widget.
+ */
+export const LinksWidget = forwardRef(LinksWidgetWithRef);
-- 
cgit v1.2.3

