Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Ny utility composeEventHandlers #2610

Merged
merged 16 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/happy-ducks-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@navikt/ds-react": minor
---

Intern state: Komponenter respekterer nå `e.preventDefault()` bedre når event overskrives internt i komponent.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function transformer(file: JSCodeshift, api) {

const jsImport = root.find(j.ImportDeclaration).filter((x) => {
return ["@navikt/ds-tokens/dist/tokens"].includes(
x.node.source.value as string
x.node.source.value as string,
);
});

Expand All @@ -36,7 +36,7 @@ export default function transformer(file: JSCodeshift, api) {
let foundName: string = "";

getImportSpecifier(j, root, name, "@navikt/ds-tokens/dist/tokens").forEach(
(x) => (foundName = x.node.imported.name)
(x) => (foundName = x.node.imported.name),
);

if (name === foundName) {
Expand All @@ -45,15 +45,15 @@ export default function transformer(file: JSCodeshift, api) {
j,
root,
name,
"@navikt/ds-tokens/dist/tokens"
"@navikt/ds-tokens/dist/tokens",
) || name;

renameImportSpecifier(
j,
root,
name,
out,
"@navikt/ds-tokens/dist/tokens"
"@navikt/ds-tokens/dist/tokens",
);

let code = root.toSource(getLineTerminator(file.source));
Expand Down
8 changes: 4 additions & 4 deletions @navikt/aksel/src/codemod/utils/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface TestT {

export function check(
dirName: string,
{ fixture, migration, extension = "js", options = {} }: TestT
{ fixture, migration, extension = "js", options = {} }: TestT,
) {
describe(migration, () => {
it(fixture, async () => {
Expand All @@ -22,7 +22,7 @@ export function check(
const source = fs.readFileSync(inputPath, "utf8");
const expected = fs.readFileSync(
path.join(fixtureDir, `${fixture}.output.${extension}`),
"utf8"
"utf8",
);
// Assumes transform is one level up from tests directory
const module = await import(path.join(dirName, "..", migration));
Expand All @@ -34,11 +34,11 @@ export function check(
expect(
await prettier.format(output, {
parser: parser === "js" ? "typescript" : parser,
})
}),
).toBe(
await prettier.format(expected, {
parser: parser === "js" ? "typescript" : parser,
})
}),
);
});
});
Expand Down
6 changes: 2 additions & 4 deletions @navikt/core/react/src/accordion/AccordionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { ChevronDownIcon } from "@navikt/aksel-icons";
import { Heading } from "../typography";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { AccordionContext } from "./AccordionContext";
import { AccordionItemContext } from "./AccordionItem";

Expand Down Expand Up @@ -30,10 +31,7 @@ const AccordionHeader = forwardRef<HTMLButtonElement, AccordionHeaderProps>(
ref={ref}
{...rest}
className={cl("navds-accordion__header", className)}
onClick={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
itemContext.toggleOpen();
onClick && onClick(e);
}}
onClick={composeEventHandlers(onClick, itemContext.toggleOpen)}
aria-expanded={itemContext.open}
type="button"
>
Expand Down
4 changes: 2 additions & 2 deletions @navikt/core/react/src/accordion/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const AccordionItemContext =
const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(
(
{ children, className, open, defaultOpen = false, onOpenChange, ...rest },
ref
ref,
) => {
const [_open, _setOpen] = useControllableState({
defaultValue: defaultOpen,
Expand Down Expand Up @@ -78,7 +78,7 @@ const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(
</AccordionItemContext.Provider>
</div>
);
}
},
);

export default AccordionItem;
19 changes: 8 additions & 11 deletions @navikt/core/react/src/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { forwardRef, useRef, useState } from "react";
import { Loader } from "../loader";
import { Label } from "../typography";
import { OverridableComponent, omit, useClientLayoutEffect } from "../util";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { useMergeRefs } from "../util/hooks/useMergeRefs";

export interface ButtonProps
Expand Down Expand Up @@ -99,22 +100,18 @@ export const Button: OverridableComponent<ButtonProps, HTMLButtonElement> =
const filterProps: React.ButtonHTMLAttributes<HTMLButtonElement> =
disabled ?? widthOverride ? omit(rest, ["href"]) : rest;

const handleKeyUp = (e: React.KeyboardEvent<HTMLButtonElement>) => {
if (e.key === " " && !disabled && !widthOverride) {
e.currentTarget.click();
}
};

return (
<Component
{...(Component !== "button" ? { role: "button" } : {})}
{...filterProps}
ref={mergedRef}
onKeyUp={(e: React.KeyboardEvent<HTMLButtonElement>) => {
filterProps.onKeyUp?.(e);
if (
e.key === " " &&
!disabled &&
!widthOverride &&
!e.isDefaultPrevented()
) {
e.currentTarget.click();
}
}}
onKeyUp={composeEventHandlers(filterProps.onKeyUp, handleKeyUp)}
className={cl(
className,
"navds-button",
Expand Down
7 changes: 3 additions & 4 deletions @navikt/core/react/src/chips/Removable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef } from "react";
import { XMarkIcon } from "@navikt/aksel-icons";
import { composeEventHandlers } from "../util/composeEventHandlers";

export interface RemovableChipsProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
Expand Down Expand Up @@ -33,6 +34,7 @@ export const RemovableChips = forwardRef<
removeLabel = "slett",
onDelete,
type = "button",
onClick,
...rest
},
ref,
Expand All @@ -48,10 +50,7 @@ export const RemovableChips = forwardRef<
`navds-chips__removable--${variant}`,
)}
aria-label={`${children} ${removeLabel}`}
onClick={(e) => {
onDelete?.();
rest?.onClick?.(e);
}}
onClick={composeEventHandlers(onClick, onDelete)}
>
<span className="navds-chips__chip-text">{children}</span>
<span className="navds-chips__removable-icon">
Expand Down
9 changes: 4 additions & 5 deletions @navikt/core/react/src/copybutton/CopyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
} from "react";
import { CheckmarkIcon, FilesIcon } from "@navikt/aksel-icons";
import { Label } from "../typography";
import { composeEventHandlers } from "../util/composeEventHandlers";
import copy from "../util/copy";

export interface CopyButtonProps
Expand Down Expand Up @@ -97,6 +98,7 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
title = "Kopier",
activeTitle = "Kopiert",
iconPosition = "left",
onClick,
...rest
},
ref,
Expand All @@ -110,14 +112,11 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
};
}, []);

const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
const handleClick = () => {
timeoutRef.current && clearTimeout(timeoutRef.current);
copy(copyText);
setActive(true);
onActiveChange?.(true);
rest.onClick?.(event);

timeoutRef.current = window.setTimeout(() => {
setActive(false);
Expand Down Expand Up @@ -160,7 +159,7 @@ export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
"navds-copybutton--active": active,
},
)}
onClick={handleClick}
onClick={composeEventHandlers(onClick, handleClick)}
>
<span className="navds-copybutton__content">
{iconPosition === "left" && copyIcon}
Expand Down
44 changes: 22 additions & 22 deletions @navikt/core/react/src/dropdown/Menu/GroupedList/GroupedItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { OverridableComponent } from "../../../util";
import { composeEventHandlers } from "../../../util/composeEventHandlers";
import { DropdownContext } from "../../context";

export interface GroupedItemProps
Expand All @@ -14,28 +15,27 @@ export interface GroupedItemProps
export const GroupedItem: OverridableComponent<
GroupedItemProps,
HTMLButtonElement
> = forwardRef(({ as: Component = "button", className, ...rest }, ref) => {
const context = useContext(DropdownContext);
> = forwardRef(
({ as: Component = "button", className, onClick, ...rest }, ref) => {
const context = useContext(DropdownContext);

return (
<dd className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
context?.onSelect?.(event);
rest?.onClick?.(event);
}}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</dd>
);
});
return (
<dd className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={composeEventHandlers(onClick, context?.onSelect)}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</dd>
);
},
);

export default GroupedItem;
44 changes: 22 additions & 22 deletions @navikt/core/react/src/dropdown/Menu/List/Item.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { OverridableComponent } from "../../../util";
import { composeEventHandlers } from "../../../util/composeEventHandlers";
import { DropdownContext } from "../../context";

export interface ListItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
Expand All @@ -11,28 +12,27 @@ export interface ListItemProps extends React.ButtonHTMLAttributes<HTMLElement> {
}

export const ListItem: OverridableComponent<ListItemProps, HTMLButtonElement> =
forwardRef(({ as: Component = "button", className, ...rest }, ref) => {
const context = useContext(DropdownContext);
forwardRef(
({ as: Component = "button", className, onClick, ...rest }, ref) => {
const context = useContext(DropdownContext);

return (
<li className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
context?.onSelect?.(event);
rest?.onClick?.(event);
}}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</li>
);
});
return (
<li className="navds-dropdown__list-item">
<Component
{...rest}
value={rest.children}
onClick={composeEventHandlers(onClick, context?.onSelect)}
ref={ref}
className={cl(
"navds-dropdown__item",
"navds-body-short",
"navds-body-short--small",
className,
)}
/>
</li>
);
},
);

export default ListItem;
16 changes: 10 additions & 6 deletions @navikt/core/react/src/dropdown/Toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { composeEventHandlers } from "../util/composeEventHandlers";
import { DropdownContext } from "./context";

export interface ToggleProps
Expand All @@ -21,6 +22,13 @@ export const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(

const { setAnchorEl, handleToggle, isOpen } = context;

const handleClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
setAnchorEl(e.currentTarget);
handleToggle(!isOpen);
};

return (
<button
{...rest}
Expand All @@ -33,16 +41,12 @@ export const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(
ref.current = el;
}
}}
onClick={(e) => {
setAnchorEl(e.currentTarget);
handleToggle(!isOpen);
onClick && onClick(e);
}}
onClick={composeEventHandlers(onClick, handleClick)}
aria-expanded={isOpen}
className={cl("navds-dropdown__toggle", className)}
/>
);
}
},
);

export default Toggle;
6 changes: 2 additions & 4 deletions @navikt/core/react/src/form/search/SearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cl from "clsx";
import React, { forwardRef, useContext } from "react";
import { MagnifyingGlassIcon } from "@navikt/aksel-icons";
import { Button, ButtonProps } from "../../button";
import { composeEventHandlers } from "../../util/composeEventHandlers";
import { SearchContext } from "./context";

export interface SearchButtonProps
Expand Down Expand Up @@ -36,10 +37,7 @@ const SearchButton: SearchButtonType = forwardRef(
variant={variant === "secondary" ? "secondary" : "primary"}
className={cl("navds-search__button-search", className)}
disabled={context?.disabled ?? disabled}
onClick={(e) => {
handleClick();
onClick?.(e);
}}
onClick={composeEventHandlers(onClick, handleClick)}
icon={
<MagnifyingGlassIcon
{...(children ? { "aria-hidden": true } : { title: "Søk" })}
Expand Down
Loading
Loading