Skip to content

Commit b5f36ae

Browse files
committed
Merge branch 'refs/heads/main' into forman-33-api_tests
2 parents d2490c4 + 1f6aaf9 commit b5f36ae

File tree

22 files changed

+247
-58
lines changed

22 files changed

+247
-58
lines changed

chartlets.js/CHANGES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@
3737
- using `schema` instead of `type` property for callback arguments
3838
- using `return` object with `schema` property for callback return values
3939

40-
* New components
40+
* New (MUI) components
4141
- `LinearProgress`
42+
- `Switch`
43+
44+
* Supporting `tooltip` property for interactive MUI components.
4245

4346
## Version 0.0.29 (from 2024/11/26)
4447

chartlets.js/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
22
"private": true,
3-
"workspaces": [ "packages/*"]
3+
"workspaces": [
4+
"packages/lib",
5+
"packages/demo"
6+
]
47
}

chartlets.js/packages/lib/src/plugins/mui/Button.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import MuiButton from "@mui/material/Button";
33
import MuiIcon from "@mui/material/Icon";
44

55
import type { ComponentState, ComponentProps } from "@/index";
6+
import { Tooltip } from "./Tooltip";
67

78
interface ButtonState extends ComponentState {
89
text?: string;
@@ -45,18 +46,20 @@ export function Button({
4546
}
4647
};
4748
return (
48-
<MuiButton
49-
id={id}
50-
name={name}
51-
style={style}
52-
variant={variant}
53-
color={color}
54-
disabled={disabled}
55-
startIcon={startIcon && <MuiIcon>{startIcon}</MuiIcon>}
56-
endIcon={endIcon && <MuiIcon>{endIcon}</MuiIcon>}
57-
onClick={handleClick}
58-
>
59-
{text}
60-
</MuiButton>
49+
<Tooltip>
50+
<MuiButton
51+
id={id}
52+
name={name}
53+
style={style}
54+
variant={variant}
55+
color={color}
56+
disabled={disabled}
57+
startIcon={startIcon && <MuiIcon>{startIcon}</MuiIcon>}
58+
endIcon={endIcon && <MuiIcon>{endIcon}</MuiIcon>}
59+
onClick={handleClick}
60+
>
61+
{text}
62+
</MuiButton>
63+
</Tooltip>
6164
);
6265
}

chartlets.js/packages/lib/src/plugins/mui/Checkbox.tsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import MuiFormControl from "@mui/material/FormControl";
44
import MuiFormControlLabel from "@mui/material/FormControlLabel";
55

66
import type { ComponentState, ComponentProps } from "@/index";
7+
import { Tooltip } from "@mui/material";
78

89
interface CheckboxState extends ComponentState {
910
label?: string;
@@ -19,6 +20,7 @@ export function Checkbox({
1920
value,
2021
disabled,
2122
style,
23+
tooltip,
2224
label,
2325
onChange,
2426
}: CheckboxProps) {
@@ -33,19 +35,21 @@ export function Checkbox({
3335
}
3436
};
3537
return (
36-
<MuiFormControl variant="filled" size="small" style={style}>
37-
<MuiFormControlLabel
38-
label={label}
39-
control={
40-
<MuiCheckbox
41-
id={id}
42-
name={name}
43-
checked={Boolean(value)}
44-
disabled={disabled}
45-
onChange={handleChange}
46-
/>
47-
}
48-
/>
49-
</MuiFormControl>
38+
<Tooltip title={tooltip}>
39+
<MuiFormControl variant="filled" size="small" style={style}>
40+
<MuiFormControlLabel
41+
label={label}
42+
control={
43+
<MuiCheckbox
44+
id={id}
45+
name={name}
46+
checked={Boolean(value)}
47+
disabled={disabled}
48+
onChange={handleChange}
49+
/>
50+
}
51+
/>
52+
</MuiFormControl>
53+
</Tooltip>
5054
);
5155
}

chartlets.js/packages/lib/src/plugins/mui/IconButton.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import MuiIconButton from "@mui/material/IconButton";
33
import MuiIcon from "@mui/material/Icon";
44

55
import type { ComponentState, ComponentProps } from "@/index";
6+
import { Tooltip } from "./Tooltip";
67

78
interface IconButtonState extends ComponentState {
89
icon?: string;
@@ -24,6 +25,7 @@ export function IconButton({
2425
id,
2526
name,
2627
style,
28+
tooltip,
2729
color,
2830
icon,
2931
size,
@@ -41,16 +43,18 @@ export function IconButton({
4143
}
4244
};
4345
return (
44-
<MuiIconButton
45-
id={id}
46-
name={name}
47-
style={style}
48-
color={color}
49-
size={size}
50-
disabled={disabled}
51-
onClick={handleClick}
52-
>
53-
<MuiIcon>{icon}</MuiIcon>
54-
</MuiIconButton>
46+
<Tooltip title={tooltip}>
47+
<MuiIconButton
48+
id={id}
49+
name={name}
50+
style={style}
51+
color={color}
52+
size={size}
53+
disabled={disabled}
54+
onClick={handleClick}
55+
>
56+
<MuiIcon>{icon}</MuiIcon>
57+
</MuiIconButton>
58+
</Tooltip>
5559
);
5660
}

chartlets.js/packages/lib/src/plugins/mui/Select.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import MuiSelect, { type SelectChangeEvent } from "@mui/material/Select";
55

66
import type { ComponentState, ComponentProps } from "@/index";
77
import { isString } from "@/utils/isString";
8+
import { Tooltip } from "./Tooltip";
89

910
export type SelectOption =
1011
| string
@@ -27,6 +28,7 @@ export function Select({
2728
options,
2829
disabled,
2930
style,
31+
tooltip,
3032
label,
3133
onChange,
3234
}: SelectProps) {
@@ -45,24 +47,26 @@ export function Select({
4547
}
4648
};
4749
return (
48-
<MuiFormControl variant="filled" size="small" style={style}>
49-
{label && <MuiInputLabel id={`${id}-label`}>{label}</MuiInputLabel>}
50-
<MuiSelect
51-
labelId={`${id}-label`}
52-
id={id}
53-
name={name}
54-
value={`${value}`}
55-
disabled={disabled}
56-
onChange={handleChange}
57-
>
58-
{Array.isArray(options) &&
59-
options.map(normalizeSelectOption).map(([value, text], index) => (
60-
<MuiMenuItem key={index} value={value}>
61-
{text}
62-
</MuiMenuItem>
63-
))}
64-
</MuiSelect>
65-
</MuiFormControl>
50+
<Tooltip title={tooltip}>
51+
<MuiFormControl variant="filled" size="small" style={style}>
52+
{label && <MuiInputLabel id={`${id}-label`}>{label}</MuiInputLabel>}
53+
<MuiSelect
54+
labelId={`${id}-label`}
55+
id={id}
56+
name={name}
57+
value={`${value}`}
58+
disabled={disabled}
59+
onChange={handleChange}
60+
>
61+
{Array.isArray(options) &&
62+
options.map(normalizeSelectOption).map(([value, text], index) => (
63+
<MuiMenuItem key={index} value={value}>
64+
{text}
65+
</MuiMenuItem>
66+
))}
67+
</MuiSelect>
68+
</MuiFormControl>
69+
</Tooltip>
6670
);
6771
}
6872

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import { createChangeHandler } from "./common.test";
4+
import { Switch } from "./Switch";
5+
6+
describe("Switch", () => {
7+
it("should render the Switch component", () => {
8+
render(
9+
<Switch id="cb" type={"Switch"} label={"Click!"} onChange={() => {}} />,
10+
);
11+
// to inspect rendered component, do:
12+
// expect(document.querySelector("#cb")).toEqual({});
13+
expect(screen.getByText("Click!")).not.toBeUndefined();
14+
});
15+
16+
it("should fire 'value' property", () => {
17+
const { recordedEvents, onChange } = createChangeHandler();
18+
render(
19+
<Switch
20+
data-testid="bt"
21+
id="cb"
22+
type={"Switch"}
23+
label={"Click!"}
24+
value={false}
25+
onChange={onChange}
26+
/>,
27+
);
28+
fireEvent.click(screen.getByText("Click!"));
29+
expect(recordedEvents.length).toEqual(1);
30+
expect(recordedEvents[0]).toEqual({
31+
componentType: "Switch",
32+
id: "cb",
33+
property: "value",
34+
value: true,
35+
});
36+
});
37+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { type ChangeEvent } from "react";
2+
import MuiSwitch from "@mui/material/Switch";
3+
import MuiFormControl from "@mui/material/FormControl";
4+
import MuiFormControlLabel from "@mui/material/FormControlLabel";
5+
6+
import type { ComponentState, ComponentProps } from "@/index";
7+
8+
interface SwitchState extends ComponentState {
9+
label?: string;
10+
value?: boolean | undefined;
11+
}
12+
13+
interface SwitchProps extends ComponentProps, SwitchState {}
14+
15+
export function Switch({
16+
type,
17+
id,
18+
name,
19+
value,
20+
disabled,
21+
style,
22+
label,
23+
onChange,
24+
}: SwitchProps) {
25+
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
26+
if (id) {
27+
return onChange({
28+
componentType: type,
29+
id: id,
30+
property: "value",
31+
value: event.currentTarget.checked,
32+
});
33+
}
34+
};
35+
return (
36+
<MuiFormControl variant="filled" size="small" style={style}>
37+
<MuiFormControlLabel
38+
label={label}
39+
control={
40+
<MuiSwitch
41+
id={id}
42+
name={name}
43+
checked={Boolean(value)}
44+
disabled={disabled}
45+
onChange={handleChange}
46+
/>
47+
}
48+
/>
49+
</MuiFormControl>
50+
);
51+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen } from "@testing-library/react";
3+
import { Tooltip } from "./Tooltip";
4+
5+
describe("Tooltip", () => {
6+
it("should render its child component", () => {
7+
render(
8+
<Tooltip title={"Does nothing :)"}>
9+
<button>Click Me</button>
10+
</Tooltip>,
11+
);
12+
// to inspect rendered component, do:
13+
// expect(document.querySelector("#typo")).toEqual({});
14+
expect(screen.getByText("Click Me")).not.toBeUndefined();
15+
});
16+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import MuiTooltip from "@mui/material/Tooltip";
2+
import type { ReactElement } from "react";
3+
4+
interface TooltipProps {
5+
title?: string;
6+
children: ReactElement;
7+
}
8+
9+
export function Tooltip({ title, children }: TooltipProps) {
10+
return title ? <MuiTooltip title={title}>{children}</MuiTooltip> : children;
11+
}

0 commit comments

Comments
 (0)