1 | import React, { memo, forwardRef, type CSSProperties } from "react";
|
2 | import { Button } from "./Button";
|
3 | import { ButtonProps } from "./Button";
|
4 | import { symToStr } from "tsafe/symToStr";
|
5 | import { assert } from "tsafe/assert";
|
6 | import type { Equals } from "tsafe";
|
7 | import { fr } from "./fr";
|
8 | import { cx } from "./tools/cx";
|
9 | import { useAnalyticsId } from "./tools/useAnalyticsId";
|
10 |
|
11 | export type ButtonsGroupProps = ButtonsGroupProps.AlwaysStacked | ButtonsGroupProps.Inline;
|
12 |
|
13 | export namespace ButtonsGroupProps {
|
14 | export type Common = {
|
15 | id?: string;
|
16 | className?: string;
|
17 | buttonsSize?: ButtonProps["size"];
|
18 |
|
19 | buttonsIconPosition?: ButtonProps.WithIcon["iconPosition"];
|
20 |
|
21 | alignment?: "left" | "center" | "right";
|
22 |
|
23 | buttonsEquisized?: boolean;
|
24 | buttons: [ButtonProps, ...ButtonProps[]];
|
25 | style?: CSSProperties;
|
26 | };
|
27 |
|
28 | export type AlwaysStacked = Common & {
|
29 | |
30 |
|
31 |
|
32 |
|
33 | inlineLayoutWhen?: "never";
|
34 | isReverseOrder?: never;
|
35 | };
|
36 |
|
37 | export type Inline = Omit<Common, "alignment"> & {
|
38 | |
39 |
|
40 |
|
41 |
|
42 | inlineLayoutWhen?: "always" | `${"sm" | "md" | "lg"} and up`;
|
43 |
|
44 | isReverseOrder?: boolean;
|
45 |
|
46 | alignment?: Common["alignment"] | "between";
|
47 | };
|
48 | }
|
49 |
|
50 |
|
51 | export const ButtonsGroup = memo(
|
52 | forwardRef<HTMLUListElement, ButtonsGroupProps>((props, ref) => {
|
53 | const {
|
54 | id: props_id,
|
55 | className,
|
56 | buttonsSize = "medium",
|
57 | buttonsIconPosition = "left",
|
58 | inlineLayoutWhen = "never",
|
59 | alignment = "left",
|
60 | buttonsEquisized = false,
|
61 | isReverseOrder = false,
|
62 | buttons,
|
63 | style,
|
64 | ...rest
|
65 | } = props;
|
66 |
|
67 | assert<Equals<keyof typeof rest, never>>();
|
68 |
|
69 | const id = useAnalyticsId({
|
70 | "defaultIdPrefix": "fr-btns-group",
|
71 | "explicitlyProvidedId": props_id
|
72 | });
|
73 |
|
74 | const buttonsGroupClassName = cx(
|
75 | fr.cx(
|
76 | "fr-btns-group",
|
77 | buttonsSize !== "medium" &&
|
78 | `fr-btns-group--${(() => {
|
79 | switch (buttonsSize) {
|
80 | case "small":
|
81 | return "sm";
|
82 | case "large":
|
83 | return "lg";
|
84 | }
|
85 | })()}`,
|
86 | inlineLayoutWhen !== "never" &&
|
87 | `fr-btns-group--inline${(() => {
|
88 | switch (inlineLayoutWhen) {
|
89 | case "always":
|
90 | return "";
|
91 | case "sm and up":
|
92 | return "-sm";
|
93 | case "md and up":
|
94 | return "-md";
|
95 | case "lg and up":
|
96 | return "-lg";
|
97 | }
|
98 | })()}`,
|
99 | buttonsEquisized && `fr-btns-group--equisized`,
|
100 | `fr-btns-group--${alignment}`,
|
101 | isReverseOrder && "fr-btns-group--inline-reverse",
|
102 | `fr-btns-group--icon-${buttonsIconPosition}`
|
103 | ),
|
104 | className
|
105 | );
|
106 |
|
107 | return (
|
108 | <ul id={id} className={buttonsGroupClassName} style={style} ref={ref} {...rest}>
|
109 | {buttons.map((buttonProps, i) => (
|
110 | <li key={i}>
|
111 | <Button {...buttonProps} />
|
112 | </li>
|
113 | ))}
|
114 | </ul>
|
115 | );
|
116 | })
|
117 | );
|
118 |
|
119 | ButtonsGroup.displayName = symToStr({ ButtonsGroup });
|
120 |
|
121 | export default ButtonsGroup;
|
122 |
|
\ | No newline at end of file |