Skip to content

Commit f21701a

Browse files
breynolds-devBrian Reynolds
andauthored
feat: update valueRenderer type to accept elements as well as strings as return values (#319)
Co-authored-by: Brian Reynolds <brian.reynolds@equipmentshare.com>
1 parent 206d73b commit f21701a

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

src/lib/interfaces.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ReactNode } from "react";
2+
13
export interface Option {
24
value;
35
label: string;
@@ -10,7 +12,7 @@ export interface ISelectProps {
1012
value: Option[];
1113
focusSearchOnOpen?: boolean;
1214
onChange?;
13-
valueRenderer?: (selected: Option[], options: Option[]) => string;
15+
valueRenderer?: (selected: Option[], options: Option[]) => ReactNode;
1416
ItemRenderer?: Function;
1517
ArrowRenderer?: ({ expanded }) => JSX.Element;
1618
selectAllLabel?: string;

stories/custom-element.stories.tsx

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { boolean, text, withKnobs } from "@storybook/addon-knobs";
2+
import React, { useState } from "react";
3+
4+
import { css } from "goober";
5+
import { cn } from "../src/lib/classnames";
6+
7+
import MultiSelect from "../src/multi-select";
8+
import { options } from "./constants";
9+
10+
const MultiSelectOverrides = css({
11+
".dropdown-container": {
12+
border: 0,
13+
display: "inline-block",
14+
width: "100%",
15+
"&:focus-within": {
16+
boxShadow: "none",
17+
borderColor: "transparent",
18+
},
19+
},
20+
".dropdown-heading": {
21+
padding: 0,
22+
height: "auto",
23+
},
24+
".dropdown-heading-dropdown-arrow": {
25+
display: "none",
26+
},
27+
});
28+
29+
export default {
30+
title: "Custom Element",
31+
decorators: [withKnobs],
32+
};
33+
34+
export const ExampleWithStrings = () => {
35+
const [selected, setSelected] = useState<typeof options>([]);
36+
37+
const valueRenderer = ( selected: typeof options ) => {
38+
if ( !selected.length ) {
39+
return "No Item Selected";
40+
}
41+
42+
return selected.length === 1
43+
? `${selected[0].label} 😶`
44+
: selected.map(({ label }) => "✔️ " + label)
45+
}
46+
47+
return (
48+
<div>
49+
<pre>{JSON.stringify(selected)}</pre>
50+
<MultiSelect
51+
options={options}
52+
focusSearchOnOpen={boolean("focusSearchOnOpen", true)}
53+
hasSelectAll={boolean("hasSelectAll", true)}
54+
isLoading={boolean("isLoading", false)}
55+
shouldToggleOnHover={boolean("shouldToggleOnHover", false)}
56+
disableSearch={boolean("disableSearch", false)}
57+
value={selected}
58+
disabled={boolean("disabled", false)}
59+
onChange={setSelected}
60+
valueRenderer={valueRenderer}
61+
labelledBy={text("labelledBy", "Select Fruits")}
62+
className={text("className", "multi-select")}
63+
/>
64+
</div>
65+
);
66+
};
67+
68+
ExampleWithStrings.story = {
69+
name: "With Strings",
70+
};
71+
72+
export const ExampleWithReactNode = () => {
73+
const [selected, setSelected] = useState<typeof options>([]);
74+
75+
const valueRenderer = ( selected: typeof options ) => {
76+
if ( !selected.length ) {
77+
return (
78+
<button>Toggle Dropdown!</button>
79+
);
80+
}
81+
82+
return selected.length === 1
83+
? ( <button>{selected[0].label} 😶</button> )
84+
: selected.map(({ label }) => ( <button key={label}>✔️ {label}</button>))
85+
}
86+
87+
return (
88+
<div>
89+
<pre>{JSON.stringify(selected)}</pre>
90+
<MultiSelect
91+
options={options}
92+
focusSearchOnOpen={boolean("focusSearchOnOpen", true)}
93+
hasSelectAll={boolean("hasSelectAll", true)}
94+
isLoading={boolean("isLoading", false)}
95+
shouldToggleOnHover={boolean("shouldToggleOnHover", false)}
96+
disableSearch={boolean("disableSearch", false)}
97+
value={selected}
98+
disabled={boolean("disabled", false)}
99+
onChange={setSelected}
100+
valueRenderer={valueRenderer}
101+
labelledBy={text("labelledBy", "Select Fruits")}
102+
className={cn( text("className", "multi-select"), MultiSelectOverrides )}
103+
/>
104+
</div>
105+
);
106+
};
107+
108+
ExampleWithReactNode.story = {
109+
name: "With Element",
110+
};

0 commit comments

Comments
 (0)