Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
lukemojo committed Jan 31, 2025
2 parents 60dcbc0 + b45e5bb commit 6b80097
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 33 deletions.
17 changes: 9 additions & 8 deletions src/TextField/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import React from "react";
import { TextFieldProps } from "./TextField.types";

// masked input
const MaskedTextField = React.forwardRef((props, ref) => (
<MaskedInput
{...props}
mask={[/[1-9]/, /\d/, /\d/, "/", /[1-9]/, /\d/, "R", /[1-9]/, /\d/]}
keepCharPositions={true}
/>
));
MaskedTextField.displayName = "MaskedTextField";
const MaskedTextField = React.forwardRef(function MaskedTextField(props, ref) {
return (
<MaskedInput
{...props}
mask={[/[1-9]/, /\d/, /\d/, "/", /[1-9]/, /\d/, "R", /[1-9]/, /\d/]}
keepCharPositions={true}
/>
);
});

/**
* TextField components are used for collecting user provided information as a string.
Expand Down
3 changes: 1 addition & 2 deletions src/TruncatedTooltip/TruncatedTooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import { Box, Link as MuiLink, Typography } from "@mui/material";
import { Meta, StoryFn, StoryObj } from "@storybook/react";
import React from "react";
import TruncatedTooltip from "./TruncatedTooltip";
import { TruncatedTooltipProps } from "./TruncatedTooltip.types";

export default {
component: TruncatedTooltip,
title: "General/TruncatedTooltip"
} satisfies Meta<typeof TruncatedTooltip>;

const Template: StoryFn<TruncatedTooltipProps> = args => {
const Template: StoryFn<typeof TruncatedTooltip> = args => {
return (
<Box
sx={{
Expand Down
49 changes: 28 additions & 21 deletions src/TruncatedTooltip/TruncatedTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import { Box, Tooltip } from "@mui/material";
import React, {
Children,
ReactElement,
isValidElement,
useRef,
useState
} from "react";
import React, { Children, ReactElement, isValidElement, useState } from "react";

import { TruncatedTooltipProps } from "./TruncatedTooltip.types";

// https://fettblog.eu/typescript-react-generic-forward-refs/#option-3%3A-augment-forwardref
// Note; In React 19 we will no longer need to use (or augment) the forwardRef type.
declare module "react" {
// eslint-disable-next-line no-unused-vars
function forwardRef<T, P = {}>(
render: (props: P, ref: React.ForwardedRef<T>) => React.ReactNode
): (props: P & React.RefAttributes<T>) => React.ReactNode;
}

/**
* Truncates text and shows a tooltip if the text overflows.
* Automatically grabs the tooltip from child.
* Renders a specified MUI component or element otherwise wraps string in a span.
*/
const TruncatedTooltip = <T extends React.ElementType = "span">({
children,
component,
multiline,
sx,
tooltip,
alwaysShowTooltip = false,
TooltipProps = undefined,
...rest
}: TruncatedTooltipProps<T>) => {
// Ref to the text element.
const textElementRef = useRef<HTMLInputElement | null>(null);
function TruncatedTooltipInner<T extends React.ElementType = "span">(
{
children,
component,
multiline,
sx,
tooltip,
alwaysShowTooltip = false,
TooltipProps = undefined,
...rest
}: TruncatedTooltipProps<T>,
ref: React.ForwardedRef<T>
) {
// State to determine if the tooltip should show.
const [open, setOpen] = useState(false);

Expand Down Expand Up @@ -96,7 +100,6 @@ const TruncatedTooltip = <T extends React.ElementType = "span">({
>
<Box
component={component || "span"}
ref={textElementRef}
sx={[
{
"& > *": {
Expand All @@ -121,12 +124,16 @@ const TruncatedTooltip = <T extends React.ElementType = "span">({
// You cannot spread `sx` directly because `SxProps` (typeof sx) can be an array.
...(Array.isArray(sx) ? sx : [sx])
]}
ref={ref}
{...rest}
>
{children}
</Box>
</Tooltip>
);
};
}

// forward ref
const TruncatedTooltip = React.forwardRef(TruncatedTooltipInner);

export default TruncatedTooltip;
62 changes: 61 additions & 1 deletion src/VehicleSelector/VehicleSelector.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { Vehicle, VehicleSelectorProps } from "./VehicleSelector.types";
import { render, screen } from "@testing-library/react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";

import VehicleSelector from "./VehicleSelector";

Expand Down Expand Up @@ -235,4 +235,64 @@ describe("VehicleSelector", () => {
expect(screen.getByRole("combobox", { name: /variant/i })).toBeDisabled();
expect(screen.getByRole("combobox", { name: /gate/i })).toBeDisabled();
});

it("removes clear button when variant is deselected in single selection mode", async () => {
const value = [
{
_id: "64c8c4cccc8d6f00130b366b",
gate: "Gate 1",
modelYear: "2015",
projectCode: "911",
variant: "NN"
}
];

render(
<VehicleSelectorWithState
{...defaultProps}
value={value}
multipleSelection={false}
/>
);

expect(screen.getByRole("combobox", { name: /variant/i })).toHaveValue(
"NN"
);

const variantField = screen.getByRole("combobox", { name: /variant/i });
const clearButton = variantField.parentElement?.querySelector(
'[aria-label="Clear"]'
);

expect(clearButton).toBeInTheDocument();
(clearButton as HTMLElement)?.click();

await waitFor(() =>
expect(
variantField.parentElement?.querySelector('[aria-label="Clear"]')
).not.toBeInTheDocument()
);

expect(variantField).toHaveValue("");
});

it("filters model years based on selected project", async () => {
render(<VehicleSelectorWithState {...defaultProps} />);

const projectInput = screen.getByRole("combobox", {
name: /project code/i
});
fireEvent.mouseDown(projectInput);
fireEvent.click(screen.getByText("911"));

const modelYearInput = screen.getByRole("combobox", {
name: /model year/i
});
fireEvent.mouseDown(modelYearInput);

await waitFor(() => {
expect(screen.getByText("2015")).toBeInTheDocument();
expect(screen.getByText("2016")).toBeInTheDocument();
});
});
});
5 changes: 4 additions & 1 deletion src/VehicleSelector/VehicleSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,10 @@ function VehicleSelector({
}
}}
size={size}
value={selectedVariants}
// if array is empty, set value to null to avoid rendering the clear button
value={
multipleSelection ? selectedVariants : selectedVariants[0] || null
}
/>
</Box>
{gates.length > 0 && (
Expand Down

0 comments on commit 6b80097

Please sign in to comment.