@aarhus-university/au-lib-react-components 11.1.0 → 11.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +34 -34
- package/.storybook/main.js +20 -20
- package/.storybook/preview.js +17 -17
- package/README.md +19 -19
- package/__tests__/jest/AUButtonComponent.test.tsx +165 -165
- package/__tests__/jest/AUErrorComponent.test.tsx +142 -142
- package/__tests__/jest/AUModalComponent.test.tsx +186 -186
- package/__tests__/jest/AUNotificationComponent.test.tsx +115 -115
- package/__tests__/jest/AUSpinnerComponent.test.tsx +57 -57
- package/__tests__/jest/AUToolbarComponent.test.tsx +46 -46
- package/__tests__/jest/context.test.ts +25 -25
- package/__tests__/jest/helpers.test.ts +15 -15
- package/__tests__/jest/setupTests.ts +2 -2
- package/babel.config.js +8 -8
- package/build/umd/all.css +2 -2
- package/build/umd/all.js +1 -1
- package/build/umd/alphabox.js +1 -1
- package/build/umd/databox.js +1 -1
- package/build/umd/diagramme.js +1 -1
- package/build/umd/flowbox.js +1 -1
- package/build/umd/universe.js +1 -1
- package/build-storybook.log +367 -367
- package/package.json +114 -114
- package/src/components/AUAlertComponent.tsx +70 -70
- package/src/components/AUAutoSuggestComponent.js +158 -158
- package/src/components/AUButtonComponent.tsx +84 -84
- package/src/components/AUCalendarComponent.tsx +493 -493
- package/src/components/AUContentToggleComponent.tsx +47 -49
- package/src/components/AUDatepickerComponent.tsx +121 -121
- package/src/components/AUErrorComponent.tsx +78 -78
- package/src/components/AUMobilePrefixComponent.tsx +15 -15
- package/src/components/AUModalComponent.tsx +68 -68
- package/src/components/AUNotificationComponent.tsx +43 -43
- package/src/components/AUReceiptComponent.tsx +33 -33
- package/src/components/AUSpinnerComponent.tsx +33 -33
- package/src/components/AUSubNavComponent.tsx +48 -48
- package/src/components/AUSubmitButtonContainerComponent.tsx +29 -29
- package/src/components/AUTabbedContentComponent.tsx +145 -145
- package/src/components/AUTableComponent.tsx +24 -24
- package/src/components/AUToastComponent.tsx +104 -104
- package/src/components/AUToolbarComponent.tsx +101 -101
- package/src/components/AUTruncatorComponent.tsx +129 -129
- package/src/components/wrapping/AUEmbedComponent.js +47 -47
- package/src/layout-2016/components/alphabox/AlphaBoxComponent.js +143 -143
- package/src/layout-2016/components/alphabox/AlphaBoxContentComponent.js +136 -136
- package/src/layout-2016/components/common/AUCollapsibleComponent.js +152 -152
- package/src/layout-2016/components/common/AUSpinnerComponent.js +103 -103
- package/src/layout-2016/components/databox/DataBoxAlphabetComponent.js +144 -144
- package/src/layout-2016/components/databox/DataBoxAssociationComponent.js +122 -122
- package/src/layout-2016/components/databox/DataBoxButtonComponent.js +157 -157
- package/src/layout-2016/components/databox/DataBoxComponent.js +297 -297
- package/src/layout-2016/components/databox/DataBoxGroupingComponent.js +64 -64
- package/src/layout-2016/components/databox/DataBoxSearchResultComponent.js +36 -36
- package/src/layout-2016/components/databox/DataBoxStackedAssociationComponent.js +54 -54
- package/src/layout-2016/components/databox/DataBoxSuggestionComponent.js +39 -39
- package/src/layout-2016/components/diagramme/AUDiagrammeComponent.js +309 -309
- package/src/layout-2016/components/flowbox/FlowBoxComponent.js +126 -126
- package/src/layout-2016/components/flowbox/FlowBoxPhoneComponent.js +104 -104
- package/src/layout-2016/components/profile/AUProfileAvatar2016Component.js +103 -103
- package/src/layout-2016/components/universe/StaffTopComponent.js +363 -363
- package/src/layout-2016/components/universe/StudentTopComponent.js +137 -137
- package/src/layout-2016/components/universe/UniverseContainerComponent.js +65 -65
- package/src/layout-2016/lib/all.js +3 -3
- package/src/layout-2016/lib/au-alphabox.js +100 -100
- package/src/layout-2016/lib/au-databox.js +400 -400
- package/src/layout-2016/lib/au-diagramme.js +85 -85
- package/src/layout-2016/lib/au-flowbox.js +93 -93
- package/src/layout-2016/lib/universe.js +9 -9
- package/src/lib/context.tsx +43 -43
- package/src/lib/dates.ts +50 -50
- package/src/lib/helpers.ts +208 -208
- package/src/lib/hooks.ts +63 -63
- package/src/lib/i18n.ts +600 -600
- package/src/lib/portals.ts +37 -37
- package/src/lib/tracking.ts +69 -69
- package/src/lib/wrapping.ts +21 -21
- package/src/styles/_settings.scss +10 -10
- package/src/styles/alphabox.scss +222 -222
- package/src/styles/app.scss +7 -7
- package/src/styles/autosuggest.scss +57 -57
- package/src/styles/databox.scss +563 -563
- package/src/styles/diagramme.scss +119 -119
- package/src/styles/flowbox.scss +72 -72
- package/src/styles/maps.scss +395 -395
- package/stories/AUButtonComponent.stories.tsx +127 -127
- package/stories/AUContentToggleComponent.stories.tsx +63 -63
- package/stories/AUErrorComponent.stories.tsx +98 -98
- package/stories/AUModalComponent.stories.tsx +83 -83
- package/stories/AUNotificationComponent.stories.tsx +116 -116
- package/stories/AUSpinnerComponent.stories.tsx +41 -41
- package/stories/AUStepComponent.stories.tsx +40 -40
- package/stories/AUToolbarComponent.stories.tsx +326 -220
- package/stories/lib/helpers.tsx +128 -128
- package/tsconfig.json +46 -46
- package/webpack.config.js +89 -89
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
/* eslint-disable react/no-array-index-key */
|
|
2
|
-
import React, { FC, Fragment } from 'react';
|
|
3
|
-
|
|
4
|
-
const AUNotificationComponent: FC<AUNotificationComponentProps> = ({
|
|
5
|
-
header,
|
|
6
|
-
content,
|
|
7
|
-
actions,
|
|
8
|
-
type,
|
|
9
|
-
classNames,
|
|
10
|
-
}: AUNotificationComponentProps) => {
|
|
11
|
-
const typeClass = type === 'default' ? '' : `notification--${type}`;
|
|
12
|
-
return (
|
|
13
|
-
<div className={[
|
|
14
|
-
'notification',
|
|
15
|
-
typeClass,
|
|
16
|
-
].concat(classNames || []).join(' ').replace(/\s+/g, ' ').trim()}
|
|
17
|
-
>
|
|
18
|
-
<div className="notification__content">
|
|
19
|
-
{
|
|
20
|
-
header && <h2 className="notification__header">{header}</h2>
|
|
21
|
-
}
|
|
22
|
-
{content.map((c, i) => <Fragment key={i}>{c}</Fragment>)}
|
|
23
|
-
</div>
|
|
24
|
-
{
|
|
25
|
-
(actions || []).length > 0 && (
|
|
26
|
-
<div className="notification__actions">
|
|
27
|
-
{(actions || []).map((a, i) => <Fragment key={i}>{a}</Fragment>)}
|
|
28
|
-
</div>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
</div>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
AUNotificationComponent.defaultProps = {
|
|
36
|
-
header: null,
|
|
37
|
-
actions: [],
|
|
38
|
-
type: 'default',
|
|
39
|
-
classNames: [],
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
AUNotificationComponent.displayName = 'AUNotificationComponent';
|
|
43
|
-
export default AUNotificationComponent;
|
|
1
|
+
/* eslint-disable react/no-array-index-key */
|
|
2
|
+
import React, { FC, Fragment } from 'react';
|
|
3
|
+
|
|
4
|
+
const AUNotificationComponent: FC<AUNotificationComponentProps> = ({
|
|
5
|
+
header,
|
|
6
|
+
content,
|
|
7
|
+
actions,
|
|
8
|
+
type,
|
|
9
|
+
classNames,
|
|
10
|
+
}: AUNotificationComponentProps) => {
|
|
11
|
+
const typeClass = type === 'default' ? '' : `notification--${type}`;
|
|
12
|
+
return (
|
|
13
|
+
<div className={[
|
|
14
|
+
'notification',
|
|
15
|
+
typeClass,
|
|
16
|
+
].concat(classNames || []).join(' ').replace(/\s+/g, ' ').trim()}
|
|
17
|
+
>
|
|
18
|
+
<div className="notification__content">
|
|
19
|
+
{
|
|
20
|
+
header && <h2 className="notification__header">{header}</h2>
|
|
21
|
+
}
|
|
22
|
+
{content.map((c, i) => <Fragment key={i}>{c}</Fragment>)}
|
|
23
|
+
</div>
|
|
24
|
+
{
|
|
25
|
+
(actions || []).length > 0 && (
|
|
26
|
+
<div className="notification__actions">
|
|
27
|
+
{(actions || []).map((a, i) => <Fragment key={i}>{a}</Fragment>)}
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
AUNotificationComponent.defaultProps = {
|
|
36
|
+
header: null,
|
|
37
|
+
actions: [],
|
|
38
|
+
type: 'default',
|
|
39
|
+
classNames: [],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
AUNotificationComponent.displayName = 'AUNotificationComponent';
|
|
43
|
+
export default AUNotificationComponent;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import React, { FC } from 'react';
|
|
2
|
-
|
|
3
|
-
const AUReceiptComponent: FC<AUReceiptComponentProps> = ({
|
|
4
|
-
receiptText,
|
|
5
|
-
helpText,
|
|
6
|
-
showGoTo,
|
|
7
|
-
buttons,
|
|
8
|
-
}: AUReceiptComponentProps) => {
|
|
9
|
-
const renderButtons = buttons.map((btn) => <a key={btn.gotoLink} href={btn.gotoLink} className="button">{btn.gotoText}</a>);
|
|
10
|
-
return (
|
|
11
|
-
<div className="receipt">
|
|
12
|
-
<div className="receipt__icon" data-icon="" />
|
|
13
|
-
<h1 className="receipt__header" dangerouslySetInnerHTML={{ __html: receiptText }} />
|
|
14
|
-
{helpText}
|
|
15
|
-
{
|
|
16
|
-
showGoTo && (
|
|
17
|
-
<div className="receipt__post-action">
|
|
18
|
-
{renderButtons}
|
|
19
|
-
</div>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
</div>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
AUReceiptComponent.defaultProps = {
|
|
27
|
-
showGoTo: true,
|
|
28
|
-
helpText: null,
|
|
29
|
-
buttons: [],
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
AUReceiptComponent.displayName = 'AUReceiptComponent';
|
|
33
|
-
export default AUReceiptComponent;
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
const AUReceiptComponent: FC<AUReceiptComponentProps> = ({
|
|
4
|
+
receiptText,
|
|
5
|
+
helpText,
|
|
6
|
+
showGoTo,
|
|
7
|
+
buttons,
|
|
8
|
+
}: AUReceiptComponentProps) => {
|
|
9
|
+
const renderButtons = buttons.map((btn) => <a key={btn.gotoLink} href={btn.gotoLink} className="button">{btn.gotoText}</a>);
|
|
10
|
+
return (
|
|
11
|
+
<div className="receipt">
|
|
12
|
+
<div className="receipt__icon" data-icon="" />
|
|
13
|
+
<h1 className="receipt__header" dangerouslySetInnerHTML={{ __html: receiptText }} />
|
|
14
|
+
{helpText}
|
|
15
|
+
{
|
|
16
|
+
showGoTo && (
|
|
17
|
+
<div className="receipt__post-action">
|
|
18
|
+
{renderButtons}
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
AUReceiptComponent.defaultProps = {
|
|
27
|
+
showGoTo: true,
|
|
28
|
+
helpText: null,
|
|
29
|
+
buttons: [],
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
AUReceiptComponent.displayName = 'AUReceiptComponent';
|
|
33
|
+
export default AUReceiptComponent;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
/* eslint-disable react/static-property-placement */
|
|
2
|
-
/* eslint-env browser */
|
|
3
|
-
import React, { FC } from 'react';
|
|
4
|
-
|
|
5
|
-
const AUSpinnerComponent: FC<AUSpinnerComponentProps> = ({
|
|
6
|
-
loaded,
|
|
7
|
-
init,
|
|
8
|
-
height,
|
|
9
|
-
className,
|
|
10
|
-
children,
|
|
11
|
-
}: AUSpinnerComponentProps) => {
|
|
12
|
-
if (!loaded) {
|
|
13
|
-
if (init === 'table' || init === 'box') {
|
|
14
|
-
return (
|
|
15
|
-
<div
|
|
16
|
-
className={`processing-state processing-state--init-${init} ${className}`}
|
|
17
|
-
style={{ minHeight: height }}
|
|
18
|
-
/>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
return (
|
|
22
|
-
<div
|
|
23
|
-
className={`processing-state ${className}`}
|
|
24
|
-
style={{ minHeight: height }}
|
|
25
|
-
/>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return children;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
AUSpinnerComponent.displayName = 'AUSpinnerComponent';
|
|
33
|
-
export default AUSpinnerComponent;
|
|
1
|
+
/* eslint-disable react/static-property-placement */
|
|
2
|
+
/* eslint-env browser */
|
|
3
|
+
import React, { FC } from 'react';
|
|
4
|
+
|
|
5
|
+
const AUSpinnerComponent: FC<AUSpinnerComponentProps> = ({
|
|
6
|
+
loaded,
|
|
7
|
+
init,
|
|
8
|
+
height,
|
|
9
|
+
className,
|
|
10
|
+
children,
|
|
11
|
+
}: AUSpinnerComponentProps) => {
|
|
12
|
+
if (!loaded) {
|
|
13
|
+
if (init === 'table' || init === 'box') {
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
className={`processing-state processing-state--init-${init} ${className}`}
|
|
17
|
+
style={{ minHeight: height }}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
className={`processing-state ${className}`}
|
|
24
|
+
style={{ minHeight: height }}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return children;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
AUSpinnerComponent.displayName = 'AUSpinnerComponent';
|
|
33
|
+
export default AUSpinnerComponent;
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
/* eslint-env browser */
|
|
2
|
-
import React, { useEffect, useRef, FC } from 'react';
|
|
3
|
-
import { setSubNavToggle } from '@aarhus-university/au-designsystem-delphinus/source/js/components/nav';
|
|
4
|
-
|
|
5
|
-
const AUSubNavComponent: FC<AUSubNavComponentProps> = ({
|
|
6
|
-
children,
|
|
7
|
-
className,
|
|
8
|
-
dataIcon,
|
|
9
|
-
text,
|
|
10
|
-
ariaLabel,
|
|
11
|
-
id,
|
|
12
|
-
}: AUSubNavComponentProps) => {
|
|
13
|
-
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
const subNavBtns = document.querySelectorAll('.sub-nav > button.nav__item');
|
|
16
|
-
const {
|
|
17
|
-
element,
|
|
18
|
-
bodyClickEvent,
|
|
19
|
-
buttonClickEvent,
|
|
20
|
-
} = setSubNavToggle(subNavBtns, buttonRef.current as Element);
|
|
21
|
-
return () => {
|
|
22
|
-
if (element) {
|
|
23
|
-
element.removeEventListener('click', bodyClickEvent);
|
|
24
|
-
}
|
|
25
|
-
buttonRef.current?.removeEventListener('click', buttonClickEvent);
|
|
26
|
-
};
|
|
27
|
-
}, []);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div className="sub-nav">
|
|
31
|
-
<button
|
|
32
|
-
ref={buttonRef}
|
|
33
|
-
id={id}
|
|
34
|
-
type="button"
|
|
35
|
-
className={className}
|
|
36
|
-
data-icon={dataIcon}
|
|
37
|
-
aria-label={ariaLabel}
|
|
38
|
-
aria-expanded={false}
|
|
39
|
-
>
|
|
40
|
-
{text}
|
|
41
|
-
</button>
|
|
42
|
-
{children}
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
AUSubNavComponent.displayName = 'AUSubNavComponent';
|
|
48
|
-
export default AUSubNavComponent;
|
|
1
|
+
/* eslint-env browser */
|
|
2
|
+
import React, { useEffect, useRef, FC } from 'react';
|
|
3
|
+
import { setSubNavToggle } from '@aarhus-university/au-designsystem-delphinus/source/js/components/nav';
|
|
4
|
+
|
|
5
|
+
const AUSubNavComponent: FC<AUSubNavComponentProps> = ({
|
|
6
|
+
children,
|
|
7
|
+
className,
|
|
8
|
+
dataIcon,
|
|
9
|
+
text,
|
|
10
|
+
ariaLabel,
|
|
11
|
+
id,
|
|
12
|
+
}: AUSubNavComponentProps) => {
|
|
13
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const subNavBtns = document.querySelectorAll('.sub-nav > button.nav__item');
|
|
16
|
+
const {
|
|
17
|
+
element,
|
|
18
|
+
bodyClickEvent,
|
|
19
|
+
buttonClickEvent,
|
|
20
|
+
} = setSubNavToggle(subNavBtns, buttonRef.current as Element);
|
|
21
|
+
return () => {
|
|
22
|
+
if (element) {
|
|
23
|
+
element.removeEventListener('click', bodyClickEvent);
|
|
24
|
+
}
|
|
25
|
+
buttonRef.current?.removeEventListener('click', buttonClickEvent);
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="sub-nav">
|
|
31
|
+
<button
|
|
32
|
+
ref={buttonRef}
|
|
33
|
+
id={id}
|
|
34
|
+
type="button"
|
|
35
|
+
className={className}
|
|
36
|
+
data-icon={dataIcon}
|
|
37
|
+
aria-label={ariaLabel}
|
|
38
|
+
aria-expanded={false}
|
|
39
|
+
>
|
|
40
|
+
{text}
|
|
41
|
+
</button>
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
AUSubNavComponent.displayName = 'AUSubNavComponent';
|
|
48
|
+
export default AUSubNavComponent;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import React, { FC } from 'react';
|
|
2
|
-
import AUButtonComponent from './AUButtonComponent';
|
|
3
|
-
|
|
4
|
-
const AUSubmitButtonContainerComponent: FC<AUSubmitButtonContainerComponentProps> = ({
|
|
5
|
-
disabled,
|
|
6
|
-
submitText,
|
|
7
|
-
cancelText,
|
|
8
|
-
onSubmit,
|
|
9
|
-
onCancel,
|
|
10
|
-
}: AUSubmitButtonContainerComponentProps) => (
|
|
11
|
-
<div className="submit button-container">
|
|
12
|
-
<AUButtonComponent
|
|
13
|
-
asSubmit
|
|
14
|
-
label={submitText}
|
|
15
|
-
classNames={[disabled ? 'button--processing' : '']}
|
|
16
|
-
disabled={disabled}
|
|
17
|
-
onClick={onSubmit}
|
|
18
|
-
/>
|
|
19
|
-
<AUButtonComponent
|
|
20
|
-
label={cancelText}
|
|
21
|
-
type="text"
|
|
22
|
-
disabled={disabled}
|
|
23
|
-
onClick={onCancel}
|
|
24
|
-
/>
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
AUSubmitButtonContainerComponent.displayName = 'AUSubmitButtonContainerComponent';
|
|
29
|
-
export default AUSubmitButtonContainerComponent;
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import AUButtonComponent from './AUButtonComponent';
|
|
3
|
+
|
|
4
|
+
const AUSubmitButtonContainerComponent: FC<AUSubmitButtonContainerComponentProps> = ({
|
|
5
|
+
disabled,
|
|
6
|
+
submitText,
|
|
7
|
+
cancelText,
|
|
8
|
+
onSubmit,
|
|
9
|
+
onCancel,
|
|
10
|
+
}: AUSubmitButtonContainerComponentProps) => (
|
|
11
|
+
<div className="submit button-container">
|
|
12
|
+
<AUButtonComponent
|
|
13
|
+
asSubmit
|
|
14
|
+
label={submitText}
|
|
15
|
+
classNames={[disabled ? 'button--processing' : '']}
|
|
16
|
+
disabled={disabled}
|
|
17
|
+
onClick={onSubmit}
|
|
18
|
+
/>
|
|
19
|
+
<AUButtonComponent
|
|
20
|
+
label={cancelText}
|
|
21
|
+
type="text"
|
|
22
|
+
disabled={disabled}
|
|
23
|
+
onClick={onCancel}
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
AUSubmitButtonContainerComponent.displayName = 'AUSubmitButtonContainerComponent';
|
|
29
|
+
export default AUSubmitButtonContainerComponent;
|
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
/* eslint-env browser */
|
|
2
|
-
/* eslint-disable max-len */
|
|
3
|
-
import React, { useEffect, useRef, FC } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
BrowserRouter as Router,
|
|
6
|
-
Routes,
|
|
7
|
-
Route,
|
|
8
|
-
NavLink,
|
|
9
|
-
useLocation,
|
|
10
|
-
} from 'react-router-dom';
|
|
11
|
-
import { setTabbedContent, isBelowViewportLimit, destroyTabs } from '@aarhus-university/au-designsystem-delphinus/source/js/components/tabs';
|
|
12
|
-
|
|
13
|
-
const TabRoutes: FC<TabRoutesProps> = ({ onRouteChange, content }: TabRoutesProps) => {
|
|
14
|
-
const location = useLocation();
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
onRouteChange(location);
|
|
17
|
-
}, [location]);
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Routes>
|
|
21
|
-
{content}
|
|
22
|
-
</Routes>
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
TabRoutes.displayName = 'Routes';
|
|
27
|
-
|
|
28
|
-
let windowInnerWidth = 0;
|
|
29
|
-
let tabbedObject: ITabbedObject | null = null;
|
|
30
|
-
|
|
31
|
-
const AUTabbedContentComponent: FC<AUTabbedContentComponentProps> = ({
|
|
32
|
-
tabKey,
|
|
33
|
-
tabs,
|
|
34
|
-
tabContent,
|
|
35
|
-
children,
|
|
36
|
-
focus,
|
|
37
|
-
initial,
|
|
38
|
-
lang,
|
|
39
|
-
callback,
|
|
40
|
-
withRouter,
|
|
41
|
-
classNames,
|
|
42
|
-
}: AUTabbedContentComponentProps) => {
|
|
43
|
-
const tabsElement = useRef<HTMLDivElement>(null);
|
|
44
|
-
|
|
45
|
-
const setTabs = () => {
|
|
46
|
-
if (tabbedObject != null) {
|
|
47
|
-
if (isBelowViewportLimit(tabbedObject.domElement.classList)) {
|
|
48
|
-
if (!tabbedObject.rendered) {
|
|
49
|
-
setTabbedContent(tabKey as number, tabbedObject.domElement, initial, focus, callback);
|
|
50
|
-
tabbedObject.rendered = true;
|
|
51
|
-
}
|
|
52
|
-
} else if (tabbedObject.rendered) {
|
|
53
|
-
destroyTabs(tabbedObject.domElement);
|
|
54
|
-
tabbedObject.rendered = false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
if (!withRouter) {
|
|
61
|
-
tabbedObject = {
|
|
62
|
-
domElement: tabsElement.current as HTMLElement,
|
|
63
|
-
rendered: false,
|
|
64
|
-
};
|
|
65
|
-
setTabs();
|
|
66
|
-
windowInnerWidth = window.innerWidth;
|
|
67
|
-
window.addEventListener('resize', () => {
|
|
68
|
-
if (windowInnerWidth > 0 && window.innerWidth !== windowInnerWidth) {
|
|
69
|
-
windowInnerWidth = window.innerWidth;
|
|
70
|
-
setTabs();
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}, []);
|
|
75
|
-
|
|
76
|
-
if (withRouter) {
|
|
77
|
-
const renderRouteTabs = tabs.map((tab) => (
|
|
78
|
-
<NavLink
|
|
79
|
-
key={tab.href}
|
|
80
|
-
to={tab.href}
|
|
81
|
-
className={({ isActive }) => (isActive ? 'nav__item nav__item--active' : 'nav__item')}
|
|
82
|
-
dangerouslySetInnerHTML={{ __html: tab.text }}
|
|
83
|
-
/>
|
|
84
|
-
));
|
|
85
|
-
const renderContent = (tabContent || []).map((content, index: number) => (
|
|
86
|
-
<Route
|
|
87
|
-
key={tabs[index].href}
|
|
88
|
-
path={tabs[index].href}
|
|
89
|
-
>
|
|
90
|
-
{content?.content}
|
|
91
|
-
</Route>
|
|
92
|
-
));
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<Router>
|
|
96
|
-
<div ref={tabsElement} className={classNames}>
|
|
97
|
-
<div className="nav nav--has-active-item">
|
|
98
|
-
<div className="nav__items">
|
|
99
|
-
{renderRouteTabs}
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
<TabRoutes
|
|
103
|
-
content={renderContent}
|
|
104
|
-
onRouteChange={() => {
|
|
105
|
-
if (typeof callback === 'function') {
|
|
106
|
-
callback();
|
|
107
|
-
}
|
|
108
|
-
}}
|
|
109
|
-
/>
|
|
110
|
-
</div>
|
|
111
|
-
</Router>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// eslint-disable-next-line jsx-a11y/control-has-associated-label
|
|
116
|
-
const renderTabs = tabs.map((tab: ITabbedTab) => <a key={tab.href} href={tab.href} className="nav__item" data-gtm={tab.dataGtm} dangerouslySetInnerHTML={{ __html: tab.text }} />);
|
|
117
|
-
|
|
118
|
-
return (
|
|
119
|
-
<div ref={tabsElement} className={classNames}>
|
|
120
|
-
<div className="nav nav--has-active-item">
|
|
121
|
-
<div className="nav__items">
|
|
122
|
-
{renderTabs}
|
|
123
|
-
</div>
|
|
124
|
-
<button type="button" className="nav__toggle">{lang === 'da' ? 'Mere' : 'More'}</button>
|
|
125
|
-
</div>
|
|
126
|
-
{children}
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
AUTabbedContentComponent.defaultProps = {
|
|
132
|
-
tabKey: 0,
|
|
133
|
-
children: null,
|
|
134
|
-
tabContent: null,
|
|
135
|
-
focus: true,
|
|
136
|
-
initial: 0,
|
|
137
|
-
lang: 'da',
|
|
138
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
139
|
-
callback: () => { },
|
|
140
|
-
withRouter: false,
|
|
141
|
-
classNames: 'tabbed-content',
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
AUTabbedContentComponent.displayName = 'AUTabbedContentComponent';
|
|
145
|
-
export default AUTabbedContentComponent;
|
|
1
|
+
/* eslint-env browser */
|
|
2
|
+
/* eslint-disable max-len */
|
|
3
|
+
import React, { useEffect, useRef, FC } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
BrowserRouter as Router,
|
|
6
|
+
Routes,
|
|
7
|
+
Route,
|
|
8
|
+
NavLink,
|
|
9
|
+
useLocation,
|
|
10
|
+
} from 'react-router-dom';
|
|
11
|
+
import { setTabbedContent, isBelowViewportLimit, destroyTabs } from '@aarhus-university/au-designsystem-delphinus/source/js/components/tabs';
|
|
12
|
+
|
|
13
|
+
const TabRoutes: FC<TabRoutesProps> = ({ onRouteChange, content }: TabRoutesProps) => {
|
|
14
|
+
const location = useLocation();
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
onRouteChange(location);
|
|
17
|
+
}, [location]);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Routes>
|
|
21
|
+
{content}
|
|
22
|
+
</Routes>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
TabRoutes.displayName = 'Routes';
|
|
27
|
+
|
|
28
|
+
let windowInnerWidth = 0;
|
|
29
|
+
let tabbedObject: ITabbedObject | null = null;
|
|
30
|
+
|
|
31
|
+
const AUTabbedContentComponent: FC<AUTabbedContentComponentProps> = ({
|
|
32
|
+
tabKey,
|
|
33
|
+
tabs,
|
|
34
|
+
tabContent,
|
|
35
|
+
children,
|
|
36
|
+
focus,
|
|
37
|
+
initial,
|
|
38
|
+
lang,
|
|
39
|
+
callback,
|
|
40
|
+
withRouter,
|
|
41
|
+
classNames,
|
|
42
|
+
}: AUTabbedContentComponentProps) => {
|
|
43
|
+
const tabsElement = useRef<HTMLDivElement>(null);
|
|
44
|
+
|
|
45
|
+
const setTabs = () => {
|
|
46
|
+
if (tabbedObject != null) {
|
|
47
|
+
if (isBelowViewportLimit(tabbedObject.domElement.classList)) {
|
|
48
|
+
if (!tabbedObject.rendered) {
|
|
49
|
+
setTabbedContent(tabKey as number, tabbedObject.domElement, initial, focus, callback);
|
|
50
|
+
tabbedObject.rendered = true;
|
|
51
|
+
}
|
|
52
|
+
} else if (tabbedObject.rendered) {
|
|
53
|
+
destroyTabs(tabbedObject.domElement);
|
|
54
|
+
tabbedObject.rendered = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!withRouter) {
|
|
61
|
+
tabbedObject = {
|
|
62
|
+
domElement: tabsElement.current as HTMLElement,
|
|
63
|
+
rendered: false,
|
|
64
|
+
};
|
|
65
|
+
setTabs();
|
|
66
|
+
windowInnerWidth = window.innerWidth;
|
|
67
|
+
window.addEventListener('resize', () => {
|
|
68
|
+
if (windowInnerWidth > 0 && window.innerWidth !== windowInnerWidth) {
|
|
69
|
+
windowInnerWidth = window.innerWidth;
|
|
70
|
+
setTabs();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}, []);
|
|
75
|
+
|
|
76
|
+
if (withRouter) {
|
|
77
|
+
const renderRouteTabs = tabs.map((tab) => (
|
|
78
|
+
<NavLink
|
|
79
|
+
key={tab.href}
|
|
80
|
+
to={tab.href}
|
|
81
|
+
className={({ isActive }) => (isActive ? 'nav__item nav__item--active' : 'nav__item')}
|
|
82
|
+
dangerouslySetInnerHTML={{ __html: tab.text }}
|
|
83
|
+
/>
|
|
84
|
+
));
|
|
85
|
+
const renderContent = (tabContent || []).map((content, index: number) => (
|
|
86
|
+
<Route
|
|
87
|
+
key={tabs[index].href}
|
|
88
|
+
path={tabs[index].href}
|
|
89
|
+
>
|
|
90
|
+
{content?.content}
|
|
91
|
+
</Route>
|
|
92
|
+
));
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Router>
|
|
96
|
+
<div ref={tabsElement} className={classNames}>
|
|
97
|
+
<div className="nav nav--has-active-item">
|
|
98
|
+
<div className="nav__items">
|
|
99
|
+
{renderRouteTabs}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
<TabRoutes
|
|
103
|
+
content={renderContent}
|
|
104
|
+
onRouteChange={() => {
|
|
105
|
+
if (typeof callback === 'function') {
|
|
106
|
+
callback();
|
|
107
|
+
}
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
</Router>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// eslint-disable-next-line jsx-a11y/control-has-associated-label
|
|
116
|
+
const renderTabs = tabs.map((tab: ITabbedTab) => <a key={tab.href} href={tab.href} className="nav__item" data-gtm={tab.dataGtm} dangerouslySetInnerHTML={{ __html: tab.text }} />);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div ref={tabsElement} className={classNames}>
|
|
120
|
+
<div className="nav nav--has-active-item">
|
|
121
|
+
<div className="nav__items">
|
|
122
|
+
{renderTabs}
|
|
123
|
+
</div>
|
|
124
|
+
<button type="button" className="nav__toggle">{lang === 'da' ? 'Mere' : 'More'}</button>
|
|
125
|
+
</div>
|
|
126
|
+
{children}
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
AUTabbedContentComponent.defaultProps = {
|
|
132
|
+
tabKey: 0,
|
|
133
|
+
children: null,
|
|
134
|
+
tabContent: null,
|
|
135
|
+
focus: true,
|
|
136
|
+
initial: 0,
|
|
137
|
+
lang: 'da',
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
139
|
+
callback: () => { },
|
|
140
|
+
withRouter: false,
|
|
141
|
+
classNames: 'tabbed-content',
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
AUTabbedContentComponent.displayName = 'AUTabbedContentComponent';
|
|
145
|
+
export default AUTabbedContentComponent;
|