diff --git a/package-lock.json b/package-lock.json index 01dd92a..1f7b795 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@navikt/bedriftsmeny", - "version": "6.3.0", + "version": "6.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@navikt/bedriftsmeny", - "version": "6.3.0", + "version": "6.4.0", "license": "MIT", "dependencies": { "@types/amplitude-js": "^8.9.4", diff --git a/package.json b/package.json index 7abeb5f..09221de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@navikt/bedriftsmeny", - "version": "6.3.0", + "version": "6.4.0", "description": "Bedriftsvelger og -meny for innlogget arbeidsgiver. Laget av TAG (Tjenester for Arbeidsgivere).", "author": "NAVIKT", "license": "MIT", diff --git a/src/bedriftsmeny/velger/JuridiskEnhet.tsx b/src/bedriftsmeny/velger/JuridiskEnhet.tsx index 87c3f11..f43967e 100644 --- a/src/bedriftsmeny/velger/JuridiskEnhet.tsx +++ b/src/bedriftsmeny/velger/JuridiskEnhet.tsx @@ -1,7 +1,7 @@ -import React, {forwardRef, FunctionComponent, Ref} from 'react'; -import { Office1, Success } from '@navikt/ds-icons'; -import { Accordion, BodyShort, Button } from '@navikt/ds-react'; -import { JuridiskEnhetMedUnderEnheterArray, Organisasjon } from '../organisasjon'; +import React, {forwardRef, useState} from 'react'; +import {Office1, Success} from '@navikt/ds-icons'; +import {Accordion, BodyShort, Button} from '@navikt/ds-react'; +import {JuridiskEnhetMedUnderEnheterArray, Organisasjon} from '../organisasjon'; type Props = { juridiskEnhet: JuridiskEnhetMedUnderEnheterArray; @@ -19,14 +19,14 @@ const JuridiskEnhet = forwardRef(({ const juridiskEnhetErValgt = Underenheter.some( (enhet: Organisasjon) => enhet.OrganizationNumber === valgtOrganisasjon.OrganizationNumber ); + const [open, setOpen] = useState(juridiskEnhetErValgt) return (
  • - - + + { setOpen(!open); }}>
    {JuridiskEnhet.Name} diff --git a/src/bedriftsmeny/velger/Virksomhetsvelger.tsx b/src/bedriftsmeny/velger/Virksomhetsvelger.tsx index 154f346..903e431 100644 --- a/src/bedriftsmeny/velger/Virksomhetsvelger.tsx +++ b/src/bedriftsmeny/velger/Virksomhetsvelger.tsx @@ -6,8 +6,32 @@ import {VirksomhetsvelgerContext} from './VirksomhetsvelgerProvider'; import JuridiskEnhet from './JuridiskEnhet'; import Dropdown from "./Dropdown"; +export const useKeyboardEvent = (type: 'keydown' | 'keypress' | 'keyup', containerRef: React.RefObject, handler: (event: KeyboardEvent) => void) => { + React.useEffect(() => { + const listener = (event: KeyboardEvent) => { + const node = containerRef.current + if (node === null) { + return + } + + if (node !== event.target && !node.contains(event.target as HTMLElement)) { + return + } + + handler(event); + }; + document.addEventListener(type, listener); + return () => { + document.removeEventListener(type, listener); + }; + }, [type, containerRef, handler]); +} + const Velger = () => { const buttonRef = useRef(null); + const lukkKnappRef = useRef(null); + const søkefeltRef = useRef(null); + const listeRef = useRef(null); const valgtUnderenhetRef = useRef(null); const dropdownRef = useRef(null); const [åpen, setÅpen] = useState(false); @@ -19,6 +43,50 @@ const Velger = () => { søketekst, setSøketekst, } = useContext(VirksomhetsvelgerContext); + const [valgtUnderenhetIntern, velgOrganisasjonIntern] = useState(valgtOrganisasjon) + const underenheterFlat = aktivtOrganisasjonstre.flatMap(({Underenheter }) => [...Underenheter]); + const antallTreff = underenheterFlat.length; + + useKeyboardEvent('keydown', listeRef, (e) => { + if (e.key === 'Enter') { + valgtUnderenhetRef.current?.click() + e.preventDefault() + } + + if (e.key === 'Tab') { + if (e.shiftKey) { + lukkKnappRef.current?.focus() + } else { + søkefeltRef.current?.focus() + } + e.preventDefault() + } + + if (e.key === 'Home') { + velgOrganisasjonIntern(underenheterFlat[0]) + e.preventDefault() + } + + if (e.key === 'End') { + velgOrganisasjonIntern(underenheterFlat[underenheterFlat.length - 1]) + e.preventDefault() + } + + if (e.key === 'ArrowUp' || e.key === 'Up') { + const index = underenheterFlat.findIndex(({OrganizationNumber}) => OrganizationNumber === valgtUnderenhetIntern.OrganizationNumber) + const nextIndex = Math.max(0, index - 1) + velgOrganisasjonIntern(underenheterFlat[nextIndex]) + e.preventDefault() + } + + if (e.key === 'ArrowDown' || e.key === 'Down') { + const index = underenheterFlat.findIndex(({OrganizationNumber}) => OrganizationNumber === valgtUnderenhetIntern.OrganizationNumber) + const nextIndex = Math.min(underenheterFlat.length - 1, index + 1) + velgOrganisasjonIntern(underenheterFlat[nextIndex]) + e.preventDefault() + } + + }); const toggleVelger = (verdi?: boolean) => { setÅpen(verdi === undefined ? !åpen : verdi); @@ -32,14 +100,11 @@ const Velger = () => { useEffect(() => { if (åpen) { valgtUnderenhetRef.current?.focus(); + } else { + setSøketekst('') + velgOrganisasjonIntern(valgtOrganisasjon) } - }, [åpen]); - - const antallTreff = aktivtOrganisasjonstre.reduce( - (totaltAntall, juridiskEnhet) => totaltAntall + juridiskEnhet.Underenheter.length, - 0 - ); - + }, [åpen, valgtUnderenhetIntern]); const handleClickOutside: { (event: MouseEvent | KeyboardEvent): void } = ( e: MouseEvent | KeyboardEvent @@ -107,17 +172,39 @@ const Velger = () => { >
    { + if (e.key === 'Tab' && e.shiftKey) { + if (underenheterFlat.some(({OrganizationNumber}) => OrganizationNumber === valgtUnderenhetIntern.OrganizationNumber)) { + valgtUnderenhetRef.current?.focus() + } else { + velgOrganisasjonIntern(underenheterFlat[0]) + } + e.preventDefault() + } + }} /> @@ -130,13 +217,14 @@ const Velger = () => {
      {aktivtOrganisasjonstre.map((juridiskEnhet) => ( ))} diff --git a/tsconfig.json b/tsconfig.json index 8888ae8..8da0369 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "allowSyntheticDefaultImports": true, "moduleResolution": "node", "allowJs": true, - "target": "es2016", + "target": "esnext", "esModuleInterop": true }, "include": ["src/**/*", "index.tsx"]