1 | import React, { memo, forwardRef, type ReactNode, type CSSProperties } from "react";
|
2 | import { symToStr } from "tsafe/symToStr";
|
3 | import { assert } from "tsafe/assert";
|
4 | import type { Equals } from "tsafe";
|
5 | import type { RegisteredLinkProps } from "./link";
|
6 | import { getLink } from "./link";
|
7 | import { fr } from "./fr";
|
8 | import { cx } from "./tools/cx";
|
9 | import { useAnalyticsId } from "./tools/useAnalyticsId";
|
10 |
|
11 |
|
12 | export type TileProps = {
|
13 | id?: string;
|
14 | className?: string;
|
15 | title: ReactNode;
|
16 | linkProps: RegisteredLinkProps;
|
17 | desc?: ReactNode;
|
18 | imageUrl?: string;
|
19 | imageAlt?: string;
|
20 | imageWidth?: string | number;
|
21 | imageHeight?: string | number;
|
22 | grey?: boolean;
|
23 |
|
24 |
|
25 | enlargeLink?: boolean;
|
26 | classes?: Partial<
|
27 | Record<"root" | "title" | "link" | "body" | "desc" | "img" | "imgTag", string>
|
28 | >;
|
29 |
|
30 | horizontal?: boolean;
|
31 | style?: CSSProperties;
|
32 | };
|
33 |
|
34 | export namespace TileProps {}
|
35 |
|
36 |
|
37 | export const Tile = memo(
|
38 | forwardRef<HTMLDivElement, TileProps>((props, ref) => {
|
39 | const {
|
40 | id: id_props,
|
41 | className,
|
42 | title,
|
43 | linkProps,
|
44 | desc,
|
45 | imageUrl,
|
46 | imageAlt,
|
47 | imageWidth,
|
48 | imageHeight,
|
49 | horizontal = false,
|
50 | grey = false,
|
51 | classes = {},
|
52 | enlargeLink = true,
|
53 | style,
|
54 | ...rest
|
55 | } = props;
|
56 |
|
57 | assert<Equals<keyof typeof rest, never>>();
|
58 |
|
59 | const { Link } = getLink();
|
60 |
|
61 | const id = useAnalyticsId({
|
62 | "defaultIdPrefix": "fr-tile",
|
63 | "explicitlyProvidedId": id_props
|
64 | });
|
65 |
|
66 | return (
|
67 | <div
|
68 | id={id}
|
69 | className={cx(
|
70 | fr.cx(
|
71 | "fr-tile",
|
72 | enlargeLink && "fr-enlarge-link",
|
73 | horizontal && "fr-tile--horizontal",
|
74 | grey && "fr-tile--grey"
|
75 | ),
|
76 | classes.root,
|
77 | className
|
78 | )}
|
79 | ref={ref}
|
80 | style={style}
|
81 | {...rest}
|
82 | >
|
83 | <div className={cx(fr.cx("fr-tile__body"), classes.body)}>
|
84 | <h3 className={cx(fr.cx("fr-tile__title"), classes.title)}>
|
85 | <Link {...linkProps} className={cx(classes.link, linkProps.className)}>
|
86 | {title}
|
87 | </Link>
|
88 | </h3>
|
89 | <p className={cx(fr.cx("fr-tile__desc"), classes.desc)}>{desc}</p>
|
90 | </div>
|
91 | {(imageUrl !== undefined && imageUrl.length && (
|
92 | <div className={cx(fr.cx("fr-tile__img"), classes.img)}>
|
93 | <img
|
94 | className={cx(fr.cx("fr-responsive-img"), classes.imgTag)}
|
95 | src={imageUrl}
|
96 | alt={imageAlt}
|
97 | width={imageWidth}
|
98 | height={imageHeight}
|
99 | />
|
100 | </div>
|
101 | )) ||
|
102 | null}
|
103 | </div>
|
104 | );
|
105 | })
|
106 | );
|
107 |
|
108 | Tile.displayName = symToStr({ Tile });
|
109 |
|
110 | export default Tile;
|
111 |
|
\ | No newline at end of file |