-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAccordion.tsx
100 lines (91 loc) · 4.41 KB
/
Accordion.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import React, { useEffect, useRef, useState } from 'react';
import { Accordion as DSAccordion } from '@navikt/ds-react';
import { ParsedHtml } from 'components/_common/parsedHtml/ParsedHtml';
import { AnalyticsEvents, logAmplitudeEvent } from 'utils/amplitude';
import { Shortcuts, useShortcuts } from 'utils/useShortcuts';
import { usePageContentProps } from 'store/pageContext';
import { getDecoratorParams } from 'utils/decorator-utils';
import { innholdsTypeMap } from 'types/content-props/_content-common';
import { EditorHelp } from 'components/_editor-only/editor-help/EditorHelp';
import { PartConfigAccordion } from 'components/parts/accordion/AccordionPart';
import { classNames } from 'utils/classnames';
import { handleStickyScrollOffset } from 'utils/scroll-to';
import defaultHtml from 'components/_common/parsedHtml/DefaultHtmlStyling.module.scss';
import styles from './Accordion.module.scss';
type AccordionProps = PartConfigAccordion;
type PanelItem = AccordionProps['accordion'][number];
export const Accordion = ({ accordion }: AccordionProps) => {
const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
const contentProps = usePageContentProps();
const { context } = getDecoratorParams(contentProps);
const { editorView, type } = contentProps;
const [openAccordions, setOpenAccordions] = useState<number[]>([]);
const expandAll = () => {
setOpenAccordions(accordion.map((_, index) => index));
};
const validatePanel = (item: PanelItem) => !!(item.title && item.html);
useShortcuts({ shortcut: Shortcuts.SEARCH, callback: expandAll });
const openChangeHandler = (isOpening: boolean, tittel: string, index: number) => {
handleStickyScrollOffset(isOpening, itemRefs.current[index]);
if (isOpening) {
setOpenAccordions([...openAccordions, index]);
} else {
setOpenAccordions(openAccordions.filter((i) => i !== index));
}
logAmplitudeEvent(isOpening ? AnalyticsEvents.ACC_EXPAND : AnalyticsEvents.ACC_COLLAPSE, {
tittel,
opprinnelse: 'trekkspill',
komponent: 'Accordion',
målgruppe: context,
innholdstype: innholdsTypeMap[type],
});
};
useEffect(() => {
const anchorHash = window.location.hash || '';
const matchingAccordion = accordion.findIndex(
(item) => validatePanel(item) && item.anchorId === anchorHash.slice(1)
);
if (matchingAccordion !== -1) {
setOpenAccordions([matchingAccordion]);
}
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, []);
// Show all panels in edit mode, but only valid panels in view mode
const validAccordion = accordion.filter(validatePanel);
const relevantAccordion = editorView === 'edit' ? accordion : validAccordion;
return (
<DSAccordion className={styles.accordion}>
{relevantAccordion.map((item, index) => {
const isValid = validatePanel(item);
return (
<DSAccordion.Item
key={index}
className={styles.item}
open={openAccordions.includes(index)}
onOpenChange={(open) => openChangeHandler(open, item.title, index)}
ref={(el) => {
itemRefs.current[index] = el;
}}
tabIndex={-1}
>
<DSAccordion.Header className={styles.header} id={item.anchorId}>
{!isValid && (
<EditorHelp
text={
'Panelet mangler tittel eller innhold. Klikk for å redigere'
}
/>
)}
{isValid && <div className={styles.headerTitle}>{item.title}</div>}
</DSAccordion.Header>
<DSAccordion.Content className={styles.content}>
<div className={classNames(defaultHtml.html, 'parsedHtml')}>
<ParsedHtml htmlProps={item.html} />
</div>
</DSAccordion.Content>
</DSAccordion.Item>
);
})}
</DSAccordion>
);
};