@ndla/ui 47.4.0 → 48.0.0
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/es/Search/SearchField.js +4 -9
- package/es/Subject/index.js +1 -4
- package/es/index.js +1 -6
- package/es/locale/messages-nb.js +1 -1
- package/es/locale/messages-nn.js +1 -1
- package/lib/Search/SearchField.d.ts +1 -2
- package/lib/Search/SearchField.js +4 -9
- package/lib/Subject/index.d.ts +0 -3
- package/lib/Subject/index.js +0 -63
- package/lib/index.d.ts +1 -6
- package/lib/index.js +0 -143
- package/lib/locale/messages-nb.js +1 -1
- package/lib/locale/messages-nn.js +1 -1
- package/package.json +4 -4
- package/src/Search/SearchField.tsx +1 -5
- package/src/Subject/index.ts +0 -13
- package/src/index.ts +1 -32
- package/src/locale/messages-nb.ts +1 -1
- package/src/locale/messages-nn.ts +1 -1
- package/es/BlogPosts/BlogPost.js +0 -96
- package/es/BlogPosts/BlogPostWrapper.js +0 -28
- package/es/BlogPosts/index.js +0 -11
- package/es/Frontpage/FrontpageFilm.js +0 -66
- package/es/Frontpage/FrontpageHeader.js +0 -50
- package/es/Frontpage/FrontpageInfo.js +0 -23
- package/es/Frontpage/FrontpageMultidisciplinarySubject.js +0 -99
- package/es/Frontpage/FrontpageProgramMenu.js +0 -86
- package/es/Frontpage/FrontpageSearch.js +0 -157
- package/es/Frontpage/FrontpageToolbox.js +0 -57
- package/es/Frontpage/illustrations/Fellesfag.js +0 -99
- package/es/Frontpage/illustrations/FrontpageHeaderIllustration.js +0 -113
- package/es/Frontpage/illustrations/FrontpageIllustrations.js +0 -21
- package/es/Frontpage/illustrations/FrontpageSubjectIllustration.js +0 -184
- package/es/Frontpage/illustrations/MenuFellesfag.js +0 -80
- package/es/Frontpage/illustrations/MenuStudiespesialiserende.js +0 -77
- package/es/Frontpage/illustrations/MenuYrkesfag.js +0 -107
- package/es/Frontpage/illustrations/Studiespesialiserende.js +0 -87
- package/es/Frontpage/illustrations/Yrkesfag.js +0 -118
- package/es/Frontpage/illustrations/index.js +0 -18
- package/es/Frontpage/index.js +0 -9
- package/es/Frontpage/sortCategories.js +0 -25
- package/es/InfoBlock/InfoBlock.js +0 -58
- package/es/InfoBlock/index.js +0 -1
- package/es/InfoBox/InfoBox.js +0 -16
- package/es/InfoBox/index.js +0 -1
- package/es/InfoWidget/InfoWidget.js +0 -103
- package/es/InfoWidget/index.js +0 -2
- package/es/Subject/Subject.js +0 -143
- package/es/Subject/SubjectNewContent.js +0 -102
- package/es/Subject/SubjectSocial.js +0 -33
- package/lib/BlogPosts/BlogPost.d.ts +0 -22
- package/lib/BlogPosts/BlogPost.js +0 -103
- package/lib/BlogPosts/BlogPostWrapper.d.ts +0 -14
- package/lib/BlogPosts/BlogPostWrapper.js +0 -37
- package/lib/BlogPosts/index.d.ts +0 -10
- package/lib/BlogPosts/index.js +0 -20
- package/lib/Frontpage/FrontpageFilm.d.ts +0 -6
- package/lib/Frontpage/FrontpageFilm.js +0 -73
- package/lib/Frontpage/FrontpageHeader.d.ts +0 -8
- package/lib/Frontpage/FrontpageHeader.js +0 -57
- package/lib/Frontpage/FrontpageInfo.d.ts +0 -6
- package/lib/Frontpage/FrontpageInfo.js +0 -31
- package/lib/Frontpage/FrontpageMultidisciplinarySubject.d.ts +0 -33
- package/lib/Frontpage/FrontpageMultidisciplinarySubject.js +0 -114
- package/lib/Frontpage/FrontpageProgramMenu.d.ts +0 -9
- package/lib/Frontpage/FrontpageProgramMenu.js +0 -93
- package/lib/Frontpage/FrontpageSearch.d.ts +0 -21
- package/lib/Frontpage/FrontpageSearch.js +0 -164
- package/lib/Frontpage/FrontpageToolbox.d.ts +0 -8
- package/lib/Frontpage/FrontpageToolbox.js +0 -64
- package/lib/Frontpage/illustrations/Fellesfag.d.ts +0 -9
- package/lib/Frontpage/illustrations/Fellesfag.js +0 -105
- package/lib/Frontpage/illustrations/FrontpageHeaderIllustration.d.ts +0 -9
- package/lib/Frontpage/illustrations/FrontpageHeaderIllustration.js +0 -119
- package/lib/Frontpage/illustrations/FrontpageIllustrations.d.ts +0 -9
- package/lib/Frontpage/illustrations/FrontpageIllustrations.js +0 -30
- package/lib/Frontpage/illustrations/FrontpageSubjectIllustration.d.ts +0 -9
- package/lib/Frontpage/illustrations/FrontpageSubjectIllustration.js +0 -188
- package/lib/Frontpage/illustrations/MenuFellesfag.d.ts +0 -9
- package/lib/Frontpage/illustrations/MenuFellesfag.js +0 -86
- package/lib/Frontpage/illustrations/MenuStudiespesialiserende.d.ts +0 -9
- package/lib/Frontpage/illustrations/MenuStudiespesialiserende.js +0 -83
- package/lib/Frontpage/illustrations/MenuYrkesfag.d.ts +0 -9
- package/lib/Frontpage/illustrations/MenuYrkesfag.js +0 -113
- package/lib/Frontpage/illustrations/Studiespesialiserende.d.ts +0 -9
- package/lib/Frontpage/illustrations/Studiespesialiserende.js +0 -93
- package/lib/Frontpage/illustrations/Yrkesfag.d.ts +0 -9
- package/lib/Frontpage/illustrations/Yrkesfag.js +0 -124
- package/lib/Frontpage/illustrations/index.d.ts +0 -18
- package/lib/Frontpage/illustrations/index.js +0 -68
- package/lib/Frontpage/index.d.ts +0 -9
- package/lib/Frontpage/index.js +0 -99
- package/lib/Frontpage/sortCategories.d.ts +0 -9
- package/lib/Frontpage/sortCategories.js +0 -32
- package/lib/InfoBlock/InfoBlock.d.ts +0 -8
- package/lib/InfoBlock/InfoBlock.js +0 -64
- package/lib/InfoBlock/index.d.ts +0 -1
- package/lib/InfoBlock/index.js +0 -12
- package/lib/InfoBox/InfoBox.d.ts +0 -6
- package/lib/InfoBox/InfoBox.js +0 -24
- package/lib/InfoBox/index.d.ts +0 -1
- package/lib/InfoBox/index.js +0 -13
- package/lib/InfoWidget/InfoWidget.d.ts +0 -21
- package/lib/InfoWidget/InfoWidget.js +0 -110
- package/lib/InfoWidget/index.d.ts +0 -2
- package/lib/InfoWidget/index.js +0 -10
- package/lib/Subject/Subject.d.ts +0 -32
- package/lib/Subject/Subject.js +0 -156
- package/lib/Subject/SubjectNewContent.d.ts +0 -13
- package/lib/Subject/SubjectNewContent.js +0 -109
- package/lib/Subject/SubjectSocial.d.ts +0 -12
- package/lib/Subject/SubjectSocial.js +0 -41
- package/src/BlogPosts/BlogPost.tsx +0 -192
- package/src/BlogPosts/BlogPostWrapper.tsx +0 -49
- package/src/BlogPosts/index.ts +0 -12
- package/src/Frontpage/FrontpageFilm.tsx +0 -97
- package/src/Frontpage/FrontpageHeader.tsx +0 -72
- package/src/Frontpage/FrontpageInfo.tsx +0 -45
- package/src/Frontpage/FrontpageMultidisciplinarySubject.tsx +0 -110
- package/src/Frontpage/FrontpageProgramMenu.tsx +0 -86
- package/src/Frontpage/FrontpageSearch.tsx +0 -200
- package/src/Frontpage/FrontpageToolbox.tsx +0 -70
- package/src/Frontpage/__tests__/Frontpage-test.js +0 -158
- package/src/Frontpage/illustrations/Fellesfag.tsx +0 -99
- package/src/Frontpage/illustrations/FrontpageHeaderIllustration.tsx +0 -131
- package/src/Frontpage/illustrations/FrontpageIllustrations.tsx +0 -28
- package/src/Frontpage/illustrations/FrontpageSubjectIllustration.tsx +0 -151
- package/src/Frontpage/illustrations/MenuFellesfag.tsx +0 -73
- package/src/Frontpage/illustrations/MenuStudiespesialiserende.tsx +0 -70
- package/src/Frontpage/illustrations/MenuYrkesfag.tsx +0 -82
- package/src/Frontpage/illustrations/Studiespesialiserende.tsx +0 -79
- package/src/Frontpage/illustrations/Yrkesfag.tsx +0 -122
- package/src/Frontpage/illustrations/index.ts +0 -31
- package/src/Frontpage/index.ts +0 -17
- package/src/Frontpage/sortCategories.ts +0 -23
- package/src/InfoBlock/InfoBlock.tsx +0 -61
- package/src/InfoBlock/index.ts +0 -1
- package/src/InfoBox/InfoBox.tsx +0 -31
- package/src/InfoBox/index.ts +0 -1
- package/src/InfoWidget/InfoWidget.tsx +0 -127
- package/src/InfoWidget/index.ts +0 -3
- package/src/Subject/Subject.tsx +0 -199
- package/src/Subject/SubjectNewContent.tsx +0 -111
- package/src/Subject/SubjectSocial.tsx +0 -36
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import { spacing, spacingUnit, mq, breakpoints } from '@ndla/core';
|
|
4
|
-
|
|
5
|
-
const StyledWrapper = styled.div`
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-flow: column;
|
|
8
|
-
margin-top: ${spacing.large};
|
|
9
|
-
|
|
10
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
11
|
-
flex-flow: row;
|
|
12
|
-
margin-top: ${spacingUnit * 3}px;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
& > * {
|
|
16
|
-
margin-top: ${spacing.large};
|
|
17
|
-
|
|
18
|
-
${mq.range({ from: breakpoints.tablet, until: breakpoints.desktop })} {
|
|
19
|
-
margin-right: ${spacing.normal};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
23
|
-
margin-right: ${spacing.large};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
27
|
-
flex-basis: 50%;
|
|
28
|
-
flex-grow: 0;
|
|
29
|
-
margin-top: 0;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&:last-child {
|
|
33
|
-
margin-right: 0;
|
|
34
|
-
margin-top: 0;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
38
|
-
|
|
39
|
-
type Props = {
|
|
40
|
-
children: ReactNode;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const FrontpageInfo = ({ children }: Props) => <StyledWrapper>{children}</StyledWrapper>;
|
|
44
|
-
|
|
45
|
-
export default FrontpageInfo;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import SafeLink, { SafeLinkButton } from '@ndla/safelink';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import { spacing, breakpoints, mq } from '@ndla/core';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { HeadingLevel } from '@ndla/typography';
|
|
6
|
-
import SectionHeading from '../SectionHeading';
|
|
7
|
-
import { MultidisciplinarySubjectIllustration as Illustration } from './illustrations/FrontpageIllustrations';
|
|
8
|
-
|
|
9
|
-
export const StyledSection = styled.section`
|
|
10
|
-
position: relative;
|
|
11
|
-
margin-top: ${spacing.large};
|
|
12
|
-
margin-bottom: ${spacing.large};
|
|
13
|
-
background-color: rgb(250, 246, 240);
|
|
14
|
-
background: linear-gradient(304.38deg, rgba(239, 238, 220, 0.35), rgba(250, 246, 240, 0.75));
|
|
15
|
-
border-radius: 8px;
|
|
16
|
-
padding: ${spacing.medium};
|
|
17
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
18
|
-
padding: ${spacing.large};
|
|
19
|
-
margin: 124px 0;
|
|
20
|
-
}
|
|
21
|
-
`;
|
|
22
|
-
|
|
23
|
-
export const Wrapper = styled.div`
|
|
24
|
-
display: flex;
|
|
25
|
-
justify-content: flex-start;
|
|
26
|
-
align-items: flex-start;
|
|
27
|
-
`;
|
|
28
|
-
export const Content = styled.div`
|
|
29
|
-
max-width: 720px;
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
export const TargetItem = styled.div`
|
|
33
|
-
padding: ${spacing.small} 0 0;
|
|
34
|
-
`;
|
|
35
|
-
|
|
36
|
-
export const StyledText = styled.span`
|
|
37
|
-
width: 100%;
|
|
38
|
-
font-size: 16px;
|
|
39
|
-
line-height: 24px;
|
|
40
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
41
|
-
font-size: 20px;
|
|
42
|
-
line-height: 32px;
|
|
43
|
-
}
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
const Topics = styled.div`
|
|
47
|
-
display: flex;
|
|
48
|
-
flex-direction: column;
|
|
49
|
-
flex: 1;
|
|
50
|
-
padding: ${spacing.xxsmall} 0;
|
|
51
|
-
margin: ${spacing.small} 0;
|
|
52
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
53
|
-
flex-direction: row;
|
|
54
|
-
margin: 0;
|
|
55
|
-
}
|
|
56
|
-
`;
|
|
57
|
-
|
|
58
|
-
const Topic = styled.div`
|
|
59
|
-
margin: ${spacing.small} 0;
|
|
60
|
-
&:first-of-type {
|
|
61
|
-
margin-left: 0;
|
|
62
|
-
}
|
|
63
|
-
&:last-of-type {
|
|
64
|
-
margin-right: 0;
|
|
65
|
-
}
|
|
66
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
67
|
-
margin: ${spacing.small};
|
|
68
|
-
}
|
|
69
|
-
`;
|
|
70
|
-
|
|
71
|
-
type Props = {
|
|
72
|
-
url: string;
|
|
73
|
-
topics?: { url: string; title: string; id: string }[];
|
|
74
|
-
headingLevel: HeadingLevel;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const FrontpageMultidisciplinarySubject = ({ url, topics, headingLevel }: Props) => {
|
|
78
|
-
const { t } = useTranslation();
|
|
79
|
-
return (
|
|
80
|
-
<StyledSection>
|
|
81
|
-
<Wrapper>
|
|
82
|
-
<Content>
|
|
83
|
-
<SectionHeading headingLevel={headingLevel} large>
|
|
84
|
-
{t('frontpageMultidisciplinarySubject.heading')}
|
|
85
|
-
</SectionHeading>
|
|
86
|
-
{topics ? (
|
|
87
|
-
<Topics>
|
|
88
|
-
{topics.map((topic) => {
|
|
89
|
-
return (
|
|
90
|
-
<Topic key={topic.id}>
|
|
91
|
-
<SafeLink to={topic.url}>{topic.title}</SafeLink>
|
|
92
|
-
</Topic>
|
|
93
|
-
);
|
|
94
|
-
})}
|
|
95
|
-
</Topics>
|
|
96
|
-
) : null}
|
|
97
|
-
<StyledText>{t('frontpageMultidisciplinarySubject.text')}</StyledText>
|
|
98
|
-
</Content>
|
|
99
|
-
</Wrapper>
|
|
100
|
-
<TargetItem className="o-text-link__wrapper o-text-link__wrapper">
|
|
101
|
-
<SafeLinkButton to={url} size="medium" shape="pill">
|
|
102
|
-
{t('frontpageMultidisciplinarySubject.linkText')}
|
|
103
|
-
</SafeLinkButton>
|
|
104
|
-
</TargetItem>
|
|
105
|
-
<Illustration />
|
|
106
|
-
</StyledSection>
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export default FrontpageMultidisciplinarySubject;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import { ButtonV2 } from '@ndla/button';
|
|
4
|
-
import { fonts, breakpoints, mq } from '@ndla/core';
|
|
5
|
-
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import NavigationBox, { ItemProps } from '../Navigation/NavigationBox';
|
|
7
|
-
import FrontpageAllSubjects, { subjectsProps } from './FrontpageAllSubjects';
|
|
8
|
-
|
|
9
|
-
const StyledWrapper = styled.div`
|
|
10
|
-
margin: 0 0 60px;
|
|
11
|
-
padding-top: 4px;
|
|
12
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
13
|
-
padding-top: 16px;
|
|
14
|
-
margin: 0 0 134px;
|
|
15
|
-
}
|
|
16
|
-
`;
|
|
17
|
-
|
|
18
|
-
const StyledMenu = styled.div`
|
|
19
|
-
position: relative;
|
|
20
|
-
margin-bottom: 28px;
|
|
21
|
-
> *:first-of-type {
|
|
22
|
-
margin-right: 10px;
|
|
23
|
-
}
|
|
24
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
25
|
-
margin-bottom: 40px;
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
28
|
-
const StyledMenuItem = styled.span`
|
|
29
|
-
font-weight: ${fonts.weight.semibold};
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
type Props = {
|
|
33
|
-
programItems: ItemProps[];
|
|
34
|
-
subjectCategories: subjectsProps['categories'];
|
|
35
|
-
showBetaCursor?: boolean;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const FrontpageProgramMenu = ({ programItems, subjectCategories }: Props) => {
|
|
39
|
-
const { t } = useTranslation();
|
|
40
|
-
const [showSubjects, setShowSubjects] = useState(false);
|
|
41
|
-
const isWindowContext = typeof window !== 'undefined';
|
|
42
|
-
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (isWindowContext) {
|
|
45
|
-
const rememberSubjects = window.localStorage.getItem('frontpageShowSubjects') || '';
|
|
46
|
-
setShowSubjects(rememberSubjects.localeCompare('true') === 0);
|
|
47
|
-
}
|
|
48
|
-
}, [isWindowContext]);
|
|
49
|
-
|
|
50
|
-
const toggleSubjects = (toggle: boolean) => {
|
|
51
|
-
setShowSubjects(toggle);
|
|
52
|
-
if (isWindowContext) {
|
|
53
|
-
window.localStorage.setItem('frontpageShowSubjects', `${toggle}`);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<StyledWrapper>
|
|
59
|
-
<StyledMenu>
|
|
60
|
-
<ButtonV2
|
|
61
|
-
onClick={() => toggleSubjects(false)}
|
|
62
|
-
colorTheme={showSubjects ? 'lighter' : undefined}
|
|
63
|
-
size="medium"
|
|
64
|
-
shape="pill"
|
|
65
|
-
>
|
|
66
|
-
<StyledMenuItem>{t('frontpageMenu.program')}</StyledMenuItem>
|
|
67
|
-
</ButtonV2>
|
|
68
|
-
<ButtonV2
|
|
69
|
-
onClick={() => toggleSubjects(true)}
|
|
70
|
-
colorTheme={!showSubjects ? 'lighter' : undefined}
|
|
71
|
-
size="medium"
|
|
72
|
-
shape="pill"
|
|
73
|
-
>
|
|
74
|
-
<StyledMenuItem>{t('frontpageMenu.allsubjects')}</StyledMenuItem>
|
|
75
|
-
</ButtonV2>
|
|
76
|
-
</StyledMenu>
|
|
77
|
-
{showSubjects ? (
|
|
78
|
-
<FrontpageAllSubjects categories={subjectCategories} />
|
|
79
|
-
) : (
|
|
80
|
-
<NavigationBox colorMode="greyLightest" items={programItems} listDirection="vertical" />
|
|
81
|
-
)}
|
|
82
|
-
</StyledWrapper>
|
|
83
|
-
);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export default FrontpageProgramMenu;
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { FormEvent, useEffect, useRef } from 'react';
|
|
2
|
-
import { isIE, browserVersion, isMobileSafari } from 'react-device-detect';
|
|
3
|
-
import styled from '@emotion/styled';
|
|
4
|
-
import { colors, spacing, mq, breakpoints, animations } from '@ndla/core';
|
|
5
|
-
import { noScroll } from '@ndla/util';
|
|
6
|
-
import { useTranslation } from 'react-i18next';
|
|
7
|
-
import { SearchField } from '../Search';
|
|
8
|
-
import { SearchFieldForm } from '../Search/SearchFieldForm';
|
|
9
|
-
import SearchResultSleeve from '../Search/SearchResultSleeve';
|
|
10
|
-
import { ContentTypeResultType, Resource } from '../types';
|
|
11
|
-
import { getMastheadHeight } from '../Masthead';
|
|
12
|
-
|
|
13
|
-
const StyledWrapper = styled.section`
|
|
14
|
-
border-radius: 2px;
|
|
15
|
-
width: 100%;
|
|
16
|
-
padding: ${spacing.normal} 0;
|
|
17
|
-
${mq.range({ from: breakpoints.mobileWide })} {
|
|
18
|
-
width: 450px;
|
|
19
|
-
}
|
|
20
|
-
${mq.range({ from: breakpoints.tablet })} {
|
|
21
|
-
width: 550px;
|
|
22
|
-
}
|
|
23
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
24
|
-
width: 750px;
|
|
25
|
-
}
|
|
26
|
-
input {
|
|
27
|
-
border-color: ${colors.brand.tertiary};
|
|
28
|
-
}
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
const StyledSearchBackdrop = styled.div`
|
|
32
|
-
position: fixed;
|
|
33
|
-
z-index: 1;
|
|
34
|
-
top: 0;
|
|
35
|
-
left: 0;
|
|
36
|
-
right: 0;
|
|
37
|
-
bottom: 0;
|
|
38
|
-
background: rgba(1, 1, 1, 0.3);
|
|
39
|
-
${animations.fadeIn(animations.durations.fast)};
|
|
40
|
-
`;
|
|
41
|
-
|
|
42
|
-
type Props = {
|
|
43
|
-
inputHasFocus: boolean;
|
|
44
|
-
searchFieldValue: string;
|
|
45
|
-
onSearchFieldChange: (searchValue: string) => void;
|
|
46
|
-
searchFieldPlaceholder: string;
|
|
47
|
-
onInputBlur: VoidFunction;
|
|
48
|
-
onSearchInputFocus: VoidFunction;
|
|
49
|
-
resourceToLinkProps: (resource: Resource) => {
|
|
50
|
-
to: string;
|
|
51
|
-
};
|
|
52
|
-
onSearch: (event: FormEvent) => void;
|
|
53
|
-
allResultUrl: string;
|
|
54
|
-
searchResult?: Array<ContentTypeResultType>;
|
|
55
|
-
loading: boolean;
|
|
56
|
-
suggestion?: string;
|
|
57
|
-
suggestionUrl?: string;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const FrontpageSearch = ({
|
|
61
|
-
resourceToLinkProps,
|
|
62
|
-
inputHasFocus,
|
|
63
|
-
searchFieldValue,
|
|
64
|
-
onSearchFieldChange,
|
|
65
|
-
searchFieldPlaceholder,
|
|
66
|
-
onInputBlur,
|
|
67
|
-
onSearchInputFocus,
|
|
68
|
-
onSearch,
|
|
69
|
-
allResultUrl,
|
|
70
|
-
searchResult,
|
|
71
|
-
loading,
|
|
72
|
-
suggestion,
|
|
73
|
-
suggestionUrl,
|
|
74
|
-
}: Props) => {
|
|
75
|
-
const { t } = useTranslation();
|
|
76
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
77
|
-
const searchFieldRef = useRef<HTMLDivElement>(null);
|
|
78
|
-
const inputHasFocusRef = useRef(inputHasFocus);
|
|
79
|
-
inputHasFocusRef.current = inputHasFocus;
|
|
80
|
-
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
const onKeyEsc = (e: KeyboardEvent) => {
|
|
83
|
-
if (e.code === 'Escape') {
|
|
84
|
-
onInputBlur();
|
|
85
|
-
if (inputRef && inputRef.current) {
|
|
86
|
-
inputRef.current!.blur();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
window.addEventListener('keydown', onKeyEsc);
|
|
91
|
-
return () => {
|
|
92
|
-
window.removeEventListener('keydown', onKeyEsc);
|
|
93
|
-
};
|
|
94
|
-
}, [onInputBlur]);
|
|
95
|
-
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
let yCoordinate = 0;
|
|
98
|
-
const mastheadHeight = getMastheadHeight() || 84;
|
|
99
|
-
const resetScroll = () => {
|
|
100
|
-
window.scrollTo({ top: yCoordinate });
|
|
101
|
-
};
|
|
102
|
-
if (inputHasFocus && searchFieldRef && searchFieldRef.current) {
|
|
103
|
-
yCoordinate = searchFieldRef.current.getBoundingClientRect().top + window.pageYOffset - mastheadHeight;
|
|
104
|
-
const isIE11 = isIE && parseInt(browserVersion) < 12;
|
|
105
|
-
if (isIE11) {
|
|
106
|
-
// insta move on IE
|
|
107
|
-
window.scrollTo(0, yCoordinate);
|
|
108
|
-
} else if (isMobileSafari) {
|
|
109
|
-
// Because safari on iOS set position:fixed to static when keyboard is open, we need to scroll to top.
|
|
110
|
-
yCoordinate = 0;
|
|
111
|
-
// Strange scrolling is happening when keyboard opens in iOS, making scrollpos not to top.
|
|
112
|
-
// Use a small timeout so the scrolling starts after
|
|
113
|
-
setTimeout(
|
|
114
|
-
() =>
|
|
115
|
-
window.scrollTo({
|
|
116
|
-
top: yCoordinate,
|
|
117
|
-
behavior: 'smooth',
|
|
118
|
-
}),
|
|
119
|
-
100,
|
|
120
|
-
);
|
|
121
|
-
} else {
|
|
122
|
-
window.scrollTo({
|
|
123
|
-
top: yCoordinate,
|
|
124
|
-
behavior: 'smooth',
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
noScroll(true, 'preventPageScroll');
|
|
128
|
-
// Because change in content(click on show more elements button) triggers some strange scroll in browser,
|
|
129
|
-
// we must ensure that the scrollPos is the same all the time
|
|
130
|
-
// setTimeout is used so the 'smooth' scroll effect can finish
|
|
131
|
-
setTimeout(() => {
|
|
132
|
-
// If user has closed modal search before timeout. Don't add event-listener
|
|
133
|
-
if (inputHasFocusRef.current) {
|
|
134
|
-
window.addEventListener('scroll', resetScroll);
|
|
135
|
-
}
|
|
136
|
-
}, 1000);
|
|
137
|
-
} else {
|
|
138
|
-
noScroll(false, 'preventPageScroll');
|
|
139
|
-
window.removeEventListener('scroll', resetScroll);
|
|
140
|
-
}
|
|
141
|
-
return () => {
|
|
142
|
-
noScroll(false, 'preventPageScroll');
|
|
143
|
-
window.removeEventListener('scroll', resetScroll);
|
|
144
|
-
inputHasFocusRef.current = false;
|
|
145
|
-
};
|
|
146
|
-
}, [inputHasFocus]);
|
|
147
|
-
|
|
148
|
-
const onBlur = () => {
|
|
149
|
-
// This is needed when user tabs out of field
|
|
150
|
-
if (!searchFieldValue) {
|
|
151
|
-
onInputBlur();
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
<div ref={searchFieldRef}>
|
|
157
|
-
<StyledWrapper>
|
|
158
|
-
{inputHasFocus && (
|
|
159
|
-
<StyledSearchBackdrop
|
|
160
|
-
role="button"
|
|
161
|
-
onClick={() => {
|
|
162
|
-
onInputBlur();
|
|
163
|
-
if (inputRef && inputRef.current) {
|
|
164
|
-
inputRef.current!.blur();
|
|
165
|
-
}
|
|
166
|
-
}}
|
|
167
|
-
/>
|
|
168
|
-
)}
|
|
169
|
-
<SearchFieldForm inputHasFocus={inputHasFocus} onSubmit={onSearch}>
|
|
170
|
-
<SearchField
|
|
171
|
-
frontPageSearch={true}
|
|
172
|
-
inputRef={inputRef}
|
|
173
|
-
onFocus={onSearchInputFocus}
|
|
174
|
-
value={searchFieldValue}
|
|
175
|
-
onChange={onSearchFieldChange}
|
|
176
|
-
placeholder={searchFieldPlaceholder}
|
|
177
|
-
loading={loading}
|
|
178
|
-
onBlur={onBlur}
|
|
179
|
-
/>
|
|
180
|
-
{searchFieldValue !== '' && inputHasFocus && (
|
|
181
|
-
<SearchResultSleeve
|
|
182
|
-
frontpage
|
|
183
|
-
loading={loading}
|
|
184
|
-
ignoreContentTypeBadge
|
|
185
|
-
result={searchResult || []}
|
|
186
|
-
searchString={searchFieldValue}
|
|
187
|
-
allResultUrl={allResultUrl}
|
|
188
|
-
resourceToLinkProps={resourceToLinkProps}
|
|
189
|
-
infoText={t('welcomePage.searchDisclaimer')}
|
|
190
|
-
suggestion={suggestion}
|
|
191
|
-
suggestionUrl={suggestionUrl}
|
|
192
|
-
/>
|
|
193
|
-
)}
|
|
194
|
-
</SearchFieldForm>
|
|
195
|
-
</StyledWrapper>
|
|
196
|
-
</div>
|
|
197
|
-
);
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
export default FrontpageSearch;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import styled from '@emotion/styled';
|
|
2
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { spacing, breakpoints, mq } from '@ndla/core';
|
|
4
|
-
import { SafeLinkButton } from '@ndla/safelink';
|
|
5
|
-
import { HeadingLevel } from '@ndla/typography';
|
|
6
|
-
import SectionHeading from '../SectionHeading';
|
|
7
|
-
import { ToolboxIllustration as Illustration } from './illustrations/FrontpageIllustrations';
|
|
8
|
-
|
|
9
|
-
const StyledSection = styled.section`
|
|
10
|
-
margin-top: ${spacing.large};
|
|
11
|
-
margin-bottom: ${spacing.large};
|
|
12
|
-
border: 1px solid #e6e6e6;
|
|
13
|
-
border-radius: 8px;
|
|
14
|
-
padding: ${spacing.medium};
|
|
15
|
-
position: relative;
|
|
16
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
17
|
-
padding: ${spacing.large};
|
|
18
|
-
margin: 124px 0;
|
|
19
|
-
}
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
const ToolboxWrapper = styled.div`
|
|
23
|
-
display: flex;
|
|
24
|
-
justify-content: flex-start;
|
|
25
|
-
align-items: flex-start;
|
|
26
|
-
padding: ${spacing.small} 0 ${spacing.medium};
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
|
-
const StyledText = styled.span`
|
|
30
|
-
width: 100%;
|
|
31
|
-
font-size: 16px;
|
|
32
|
-
line-height: 24px;
|
|
33
|
-
${mq.range({ from: breakpoints.desktop })} {
|
|
34
|
-
font-size: 20px;
|
|
35
|
-
line-height: 32px;
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
38
|
-
|
|
39
|
-
const StyledStudentsButton = styled(SafeLinkButton)`
|
|
40
|
-
margin: 0 ${spacing.small} ${spacing.small} 0;
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
type Props = {
|
|
44
|
-
urlStudents: string;
|
|
45
|
-
urlTeachers: string;
|
|
46
|
-
headingLevel: HeadingLevel;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const FrontpageToolbox = ({ urlStudents, urlTeachers, headingLevel }: Props) => {
|
|
50
|
-
const { t } = useTranslation();
|
|
51
|
-
return (
|
|
52
|
-
<StyledSection>
|
|
53
|
-
<SectionHeading headingLevel={headingLevel} large>
|
|
54
|
-
{t('frontPageToolbox.heading')}
|
|
55
|
-
</SectionHeading>
|
|
56
|
-
<ToolboxWrapper>
|
|
57
|
-
<StyledText>{t('frontPageToolbox.text')}</StyledText>
|
|
58
|
-
</ToolboxWrapper>
|
|
59
|
-
<StyledStudentsButton to={urlStudents} size="medium" shape="pill">
|
|
60
|
-
{t('frontPageToolbox.linkTextStudents')}
|
|
61
|
-
</StyledStudentsButton>
|
|
62
|
-
<SafeLinkButton to={urlTeachers} size="medium" shape="pill">
|
|
63
|
-
{t('frontPageToolbox.linkTextTeachers')}
|
|
64
|
-
</SafeLinkButton>
|
|
65
|
-
<Illustration />
|
|
66
|
-
</StyledSection>
|
|
67
|
-
);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export default FrontpageToolbox;
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2019-present, NDLA.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/* eslint-env jest */
|
|
10
|
-
|
|
11
|
-
import { sortCategories } from '../sortCategories';
|
|
12
|
-
|
|
13
|
-
const arrayIsCorrect = (array) =>
|
|
14
|
-
array &&
|
|
15
|
-
array.length &&
|
|
16
|
-
array[0].name === 'fellesfag' &&
|
|
17
|
-
array[1].name === 'studiespesialiserende' &&
|
|
18
|
-
array[2].name === 'yrkesfag';
|
|
19
|
-
|
|
20
|
-
test('Frontpage/sortCategories function test', () => {
|
|
21
|
-
// Correct input and order
|
|
22
|
-
const testTruthy1 = [
|
|
23
|
-
{
|
|
24
|
-
name: 'fellesfag',
|
|
25
|
-
subjects: [
|
|
26
|
-
{
|
|
27
|
-
url: '#1',
|
|
28
|
-
text: 'Engelsk',
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: 'studiespesialiserende',
|
|
34
|
-
subjects: [
|
|
35
|
-
{
|
|
36
|
-
url: '#1',
|
|
37
|
-
text: 'Biologi 1',
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'yrkesfag',
|
|
43
|
-
subjects: [
|
|
44
|
-
{
|
|
45
|
-
url: '#1',
|
|
46
|
-
text: 'Barne- og undersarbeiderfag',
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
// Correct input, wrong order
|
|
52
|
-
const testTruthy2 = [
|
|
53
|
-
{
|
|
54
|
-
name: 'yrkesfag',
|
|
55
|
-
subjects: [
|
|
56
|
-
{
|
|
57
|
-
url: '#1',
|
|
58
|
-
text: 'Barne- og undersarbeiderfag',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: 'fellesfag',
|
|
64
|
-
subjects: [
|
|
65
|
-
{
|
|
66
|
-
url: '#1',
|
|
67
|
-
text: 'Engelsk',
|
|
68
|
-
},
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: 'studiespesialiserende',
|
|
73
|
-
subjects: [
|
|
74
|
-
{
|
|
75
|
-
url: '#1',
|
|
76
|
-
text: 'Biologi 1',
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
];
|
|
81
|
-
// And extra input in addition to correct onces
|
|
82
|
-
const testFalsy1 = [
|
|
83
|
-
{
|
|
84
|
-
name: 'yrkesfag',
|
|
85
|
-
subjects: [
|
|
86
|
-
{
|
|
87
|
-
url: '#1',
|
|
88
|
-
text: 'Barne- og undersarbeiderfag',
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
name: 'spoltefag',
|
|
94
|
-
subjects: [
|
|
95
|
-
{
|
|
96
|
-
url: '#1',
|
|
97
|
-
text: 'Engelsk',
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: 'fellesfag',
|
|
103
|
-
subjects: [
|
|
104
|
-
{
|
|
105
|
-
url: '#1',
|
|
106
|
-
text: 'Engelsk',
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
name: 'studiespesialiserende',
|
|
112
|
-
subjects: [
|
|
113
|
-
{
|
|
114
|
-
url: '#1',
|
|
115
|
-
text: 'Biologi 1',
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
];
|
|
120
|
-
// Name altered in one of the items
|
|
121
|
-
const testFalsy2 = [
|
|
122
|
-
{
|
|
123
|
-
name: 'yrkesfag1',
|
|
124
|
-
subjects: [
|
|
125
|
-
{
|
|
126
|
-
url: '#1',
|
|
127
|
-
text: 'Barne- og undersarbeiderfag',
|
|
128
|
-
},
|
|
129
|
-
],
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
name: 'fellesfag',
|
|
133
|
-
subjects: [
|
|
134
|
-
{
|
|
135
|
-
url: '#1',
|
|
136
|
-
text: 'Engelsk',
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: 'studiespesialiserende',
|
|
142
|
-
subjects: [
|
|
143
|
-
{
|
|
144
|
-
url: '#1',
|
|
145
|
-
text: 'Biologi 1',
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
},
|
|
149
|
-
];
|
|
150
|
-
const sortedTruthy1 = sortCategories(testTruthy1);
|
|
151
|
-
const sortedTruthy2 = sortCategories(testTruthy2);
|
|
152
|
-
const sortedFalsy1 = sortCategories(testFalsy1);
|
|
153
|
-
const sortedFalsy2 = sortCategories(testFalsy2);
|
|
154
|
-
expect(arrayIsCorrect(sortedTruthy1)).toBeTruthy();
|
|
155
|
-
expect(arrayIsCorrect(sortedTruthy2)).toBeTruthy();
|
|
156
|
-
expect(arrayIsCorrect(sortedFalsy1)).toBeFalsy();
|
|
157
|
-
expect(arrayIsCorrect(sortedFalsy2)).toBeFalsy();
|
|
158
|
-
});
|