@ndla/ui 20.0.0 → 21.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.
Files changed (79) hide show
  1. package/README.md +1 -1
  2. package/es/LearningPaths/LearningPathInformation.js +21 -3
  3. package/es/LearningPaths/LearningPathMenu.js +8 -5
  4. package/es/LearningPaths/LearningPathMenuAsideCopyright.js +17 -4
  5. package/es/LearningPaths/LearningPathMenuIntro.js +19 -8
  6. package/es/Masthead/Masthead.js +1 -0
  7. package/es/Messages/MessageBanner.js +3 -3
  8. package/es/Resource/ListResource.js +6 -6
  9. package/es/TopicMenu/TopicMenu.js +14 -1
  10. package/es/TreeStructure/FolderItem.js +72 -51
  11. package/es/TreeStructure/FolderItems.js +33 -61
  12. package/es/TreeStructure/FolderNameInput.js +14 -13
  13. package/es/TreeStructure/TreeStructure.js +80 -96
  14. package/es/TreeStructure/helperFunctions.js +4 -73
  15. package/es/TreeStructure/{TreeStructure.types.js → types.js} +0 -0
  16. package/es/all.css +1 -1
  17. package/es/locale/messages-en.js +6 -1
  18. package/es/locale/messages-nb.js +6 -1
  19. package/es/locale/messages-nn.js +6 -1
  20. package/es/locale/messages-se.js +6 -1
  21. package/es/locale/messages-sma.js +6 -1
  22. package/lib/LearningPaths/LearningPathInformation.js +19 -2
  23. package/lib/LearningPaths/LearningPathMenu.d.ts +2 -1
  24. package/lib/LearningPaths/LearningPathMenu.js +8 -5
  25. package/lib/LearningPaths/LearningPathMenuAsideCopyright.js +16 -3
  26. package/lib/LearningPaths/LearningPathMenuIntro.d.ts +3 -1
  27. package/lib/LearningPaths/LearningPathMenuIntro.js +19 -8
  28. package/lib/Masthead/Masthead.js +1 -0
  29. package/lib/Messages/MessageBanner.js +3 -3
  30. package/lib/Resource/ListResource.js +6 -6
  31. package/lib/TopicMenu/TopicMenu.js +14 -1
  32. package/lib/TreeStructure/FolderItem.d.ts +6 -20
  33. package/lib/TreeStructure/FolderItem.js +74 -51
  34. package/lib/TreeStructure/FolderItems.d.ts +11 -2
  35. package/lib/TreeStructure/FolderItems.js +33 -61
  36. package/lib/TreeStructure/FolderNameInput.js +14 -13
  37. package/lib/TreeStructure/TreeStructure.d.ts +12 -2
  38. package/lib/TreeStructure/TreeStructure.js +78 -94
  39. package/lib/TreeStructure/helperFunctions.d.ts +2 -4
  40. package/lib/TreeStructure/helperFunctions.js +5 -80
  41. package/lib/TreeStructure/index.d.ts +2 -1
  42. package/lib/TreeStructure/types.d.ts +32 -0
  43. package/lib/TreeStructure/{TreeStructure.types.js → types.js} +0 -0
  44. package/lib/all.css +1 -1
  45. package/lib/index.d.ts +1 -1
  46. package/lib/locale/messages-en.d.ts +6 -1
  47. package/lib/locale/messages-en.js +6 -1
  48. package/lib/locale/messages-nb.d.ts +6 -1
  49. package/lib/locale/messages-nb.js +6 -1
  50. package/lib/locale/messages-nn.d.ts +6 -1
  51. package/lib/locale/messages-nn.js +6 -1
  52. package/lib/locale/messages-se.d.ts +6 -1
  53. package/lib/locale/messages-se.js +6 -1
  54. package/lib/locale/messages-sma.d.ts +6 -1
  55. package/lib/locale/messages-sma.js +6 -1
  56. package/package.json +15 -14
  57. package/src/LearningPaths/LearningPathInformation.tsx +27 -12
  58. package/src/LearningPaths/LearningPathMenu.tsx +9 -1
  59. package/src/LearningPaths/LearningPathMenuAsideCopyright.tsx +22 -20
  60. package/src/LearningPaths/LearningPathMenuIntro.tsx +15 -2
  61. package/src/Masthead/Masthead.tsx +4 -1
  62. package/src/Messages/MessageBanner.tsx +1 -1
  63. package/src/Resource/ListResource.tsx +1 -0
  64. package/src/TopicMenu/TopicMenu.jsx +15 -2
  65. package/src/TreeStructure/FolderItem.tsx +59 -67
  66. package/src/TreeStructure/FolderItems.tsx +30 -50
  67. package/src/TreeStructure/FolderNameInput.tsx +6 -11
  68. package/src/TreeStructure/TreeStructure.tsx +73 -71
  69. package/src/TreeStructure/helperFunctions.ts +3 -37
  70. package/src/TreeStructure/index.ts +2 -1
  71. package/src/TreeStructure/types.ts +37 -0
  72. package/src/index.ts +1 -1
  73. package/src/locale/messages-en.ts +6 -1
  74. package/src/locale/messages-nb.ts +7 -1
  75. package/src/locale/messages-nn.ts +6 -1
  76. package/src/locale/messages-se.ts +7 -1
  77. package/src/locale/messages-sma.ts +7 -1
  78. package/lib/TreeStructure/TreeStructure.types.d.ts +0 -61
  79. package/src/TreeStructure/TreeStructure.types.ts +0 -71
package/lib/index.d.ts CHANGED
@@ -88,4 +88,4 @@ export type { SnackBarItem } from './SnackBar';
88
88
  export { SnackBar } from './SnackBar';
89
89
  export { InfoBlock } from './InfoBlock';
90
90
  export { TreeStructure } from './TreeStructure';
91
- export type { FolderStructureProps, TreeStructureProps } from './TreeStructure';
91
+ export type { FolderType, TreeStructureProps, TreeStructureMenuProps } from './TreeStructure';
@@ -94,7 +94,12 @@ declare const messages: {
94
94
  ask: string;
95
95
  };
96
96
  wishToDelete: string;
97
- terms: string;
97
+ terms: {
98
+ terms: string;
99
+ term1: string;
100
+ term2: string;
101
+ term3: string;
102
+ };
98
103
  feide: string;
99
104
  newFavourite: string;
100
105
  storageInfo: {
@@ -989,7 +989,12 @@ var messages = _objectSpread(_objectSpread({
989
989
  ask: 'Ask us in the chat'
990
990
  },
991
991
  wishToDelete: 'Do you wish to delete your account?',
992
- terms: 'terms of use',
992
+ terms: {
993
+ terms: 'Terms of use',
994
+ term1: 'Do not write personal or sensitive information in text fields.',
995
+ term2: 'Do not write offensive statements in text fields.',
996
+ term3: 'NDLA reserves the right to update or remove resources if they are not up to date.'
997
+ },
993
998
  feide: 'We have retrieved this information from Feide',
994
999
  newFavourite: 'Recently favourited',
995
1000
  storageInfo: {
@@ -94,7 +94,12 @@ declare const messages: {
94
94
  ask: string;
95
95
  };
96
96
  wishToDelete: string;
97
- terms: string;
97
+ terms: {
98
+ terms: string;
99
+ term1: string;
100
+ term2: string;
101
+ term3: string;
102
+ };
98
103
  newFavourite: string;
99
104
  feide: string;
100
105
  storageInfo: {
@@ -989,7 +989,12 @@ var messages = _objectSpread(_objectSpread({
989
989
  ask: 'Spør oss i chatten'
990
990
  },
991
991
  wishToDelete: 'Ønsker du ikke ha brukerprofil hos oss lengre?',
992
- terms: 'vilkår for bruk',
992
+ terms: {
993
+ terms: 'Vilkår for bruk',
994
+ term1: 'Ikke skriv personsensitiv informasjon eller persondata i tekstfelt.',
995
+ term2: 'Ikke skriv noe støtende i tekstfelt.',
996
+ term3: 'NDLA forbeholder seg retten til å oppdatere eller eventuelt slette ressurser dersom disse blir utdatert.'
997
+ },
993
998
  newFavourite: 'Nylig lagt til',
994
999
  feide: 'Dette henter vi om deg fra Feide',
995
1000
  storageInfo: {
@@ -94,7 +94,12 @@ declare const messages: {
94
94
  ask: string;
95
95
  };
96
96
  wishToDelete: string;
97
- terms: string;
97
+ terms: {
98
+ terms: string;
99
+ term1: string;
100
+ term2: string;
101
+ term3: string;
102
+ };
98
103
  newFavourite: string;
99
104
  feide: string;
100
105
  storageInfo: {
@@ -989,7 +989,12 @@ var messages = _objectSpread(_objectSpread({
989
989
  ask: 'Spør oss i chatten'
990
990
  },
991
991
  wishToDelete: 'Ønsker du ikke ha brukerprofil hos oss lengre?',
992
- terms: 'vilkår for bruk',
992
+ terms: {
993
+ terms: 'Vilkår for bruk',
994
+ term1: 'Ikkje skriv personsensitiv informasjon eller persondata i tekstfelt.',
995
+ term2: 'Ikkje skriv noko støytande i tekstfelt.',
996
+ term3: 'NDLA atterhald seg retten til å oppdatere eller eventuelt slette ressursar dersom disse blir utdatert.'
997
+ },
993
998
  newFavourite: 'Nylig lagt til',
994
999
  feide: 'Dette henter vi om deg fra Feide',
995
1000
  storageInfo: {
@@ -94,7 +94,12 @@ declare const messages: {
94
94
  ask: string;
95
95
  };
96
96
  wishToDelete: string;
97
- terms: string;
97
+ terms: {
98
+ terms: string;
99
+ term1: string;
100
+ term2: string;
101
+ term3: string;
102
+ };
98
103
  newFavourite: string;
99
104
  feide: string;
100
105
  storageInfo: {
@@ -989,7 +989,12 @@ var messages = _objectSpread(_objectSpread({
989
989
  ask: 'Spør oss i chatten'
990
990
  },
991
991
  wishToDelete: 'Ønsker du ikke ha brukerprofil hos oss lengre?',
992
- terms: 'vilkår for bruk',
992
+ terms: {
993
+ terms: 'Vilkår for bruk',
994
+ term1: 'Ikke skriv personsensitiv informasjon eller persondata i tekstfelt.',
995
+ term2: 'Ikke skriv noe støtende i tekstfelt.',
996
+ term3: 'NDLA forbeholder seg retten til å oppdatere eller eventuelt slette ressurser dersom disse blir utdatert.'
997
+ },
993
998
  newFavourite: 'Nylig lagt til',
994
999
  feide: 'Dette henter vi om deg fra Feide',
995
1000
  storageInfo: {
@@ -94,7 +94,12 @@ declare const messages: {
94
94
  ask: string;
95
95
  };
96
96
  wishToDelete: string;
97
- terms: string;
97
+ terms: {
98
+ terms: string;
99
+ term1: string;
100
+ term2: string;
101
+ term3: string;
102
+ };
98
103
  newFavourite: string;
99
104
  feide: string;
100
105
  storageInfo: {
@@ -989,7 +989,12 @@ var messages = _objectSpread(_objectSpread({
989
989
  ask: 'Spør oss i chatten'
990
990
  },
991
991
  wishToDelete: 'Ønsker du ikke ha brukerprofil hos oss lengre?',
992
- terms: 'vilkår for bruk',
992
+ terms: {
993
+ terms: 'Vilkår for bruk',
994
+ term1: 'Ikke skriv personsensitiv informasjon eller persondata i tekstfelt.',
995
+ term2: 'Ikke skriv noe støtende i tekstfelt.',
996
+ term3: 'NDLA forbeholder seg retten til å oppdatere eller eventuelt slette ressurser dersom disse blir utdatert.'
997
+ },
993
998
  newFavourite: 'Nylig lagt til',
994
999
  feide: 'Dette henter vi om deg fra Feide',
995
1000
  storageInfo: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "20.0.0",
3
+ "version": "21.0.0",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -31,19 +31,20 @@
31
31
  "types"
32
32
  ],
33
33
  "dependencies": {
34
- "@ndla/button": "^3.1.3",
35
- "@ndla/carousel": "^1.2.12",
36
- "@ndla/core": "^2.3.0",
37
- "@ndla/forms": "^3.1.0",
34
+ "@ndla/button": "^3.1.5",
35
+ "@ndla/carousel": "^1.2.14",
36
+ "@ndla/core": "^2.3.2",
37
+ "@ndla/forms": "^3.1.2",
38
38
  "@ndla/hooks": "^1.1.4",
39
- "@ndla/icons": "^1.11.0",
40
- "@ndla/licenses": "^5.0.3",
41
- "@ndla/modal": "^1.2.13",
42
- "@ndla/notion": "^3.1.23",
43
- "@ndla/safelink": "^2.2.1",
44
- "@ndla/switch": "^0.1.7",
45
- "@ndla/tabs": "^1.1.11",
46
- "@ndla/tooltip": "^2.1.2",
39
+ "@ndla/icons": "^1.11.2",
40
+ "@ndla/licenses": "^5.0.5",
41
+ "@ndla/modal": "^1.2.15",
42
+ "@ndla/notion": "^3.1.25",
43
+ "@ndla/safelink": "^2.2.3",
44
+ "@ndla/switch": "^0.1.9",
45
+ "@ndla/tabs": "^1.1.13",
46
+ "@ndla/tooltip": "^2.1.4",
47
+ "@ndla/types-learningpath-api": "^0.0.12",
47
48
  "@ndla/util": "^3.0.0",
48
49
  "@reach/menu-button": "^0.16.2",
49
50
  "@reach/slider": "^0.16.0",
@@ -82,5 +83,5 @@
82
83
  "publishConfig": {
83
84
  "access": "public"
84
85
  },
85
- "gitHead": "92e4a15ab1e19af2c7b1055f56f90f5c415f87e7"
86
+ "gitHead": "57a015c6fe4a2106bb88d0f2ebea44592aa4d29e"
86
87
  }
@@ -8,7 +8,8 @@
8
8
 
9
9
  import React from 'react';
10
10
  import styled from '@emotion/styled';
11
- import { fonts, spacing, spacingUnit, breakpoints, mq } from '@ndla/core';
11
+ import { fonts, spacing, spacingUnit, breakpoints, mq, colors } from '@ndla/core';
12
+ import { getLicenseByAbbreviation, LicenseByline } from '@ndla/licenses';
12
13
 
13
14
  type StyledWrapperProps = {
14
15
  invertedStyle?: boolean;
@@ -50,6 +51,17 @@ const StyledWrapper = styled.div<StyledWrapperProps>`
50
51
  }
51
52
  `;
52
53
 
54
+ const LicenseWrapper = styled.div`
55
+ ul {
56
+ margin-left: 0;
57
+ margin-bottom: ${spacing.small};
58
+ }
59
+ `;
60
+
61
+ const StyledHeader = styled.h1`
62
+ margin-bottom: ${spacing.small};
63
+ `;
64
+
53
65
  interface Props {
54
66
  description?: string;
55
67
  title: string;
@@ -59,14 +71,17 @@ interface Props {
59
71
  };
60
72
  }
61
73
 
62
- export const LearningPathInformation = ({ description, title, license, invertedStyle }: Props) => (
63
- <section className="o-wrapper">
64
- <StyledWrapper invertedStyle={invertedStyle} className="c-article">
65
- <div>
66
- <h1>{title}</h1>
67
- {license && license.license}
68
- </div>
69
- {description && <div dangerouslySetInnerHTML={{ __html: description }} />}
70
- </StyledWrapper>
71
- </section>
72
- );
74
+ export const LearningPathInformation = ({ description, title, license, invertedStyle }: Props) => {
75
+ const { rights } = getLicenseByAbbreviation(license?.license || '', 'nb');
76
+ return (
77
+ <section className="o-wrapper">
78
+ <StyledWrapper invertedStyle={invertedStyle} className="c-article">
79
+ <LicenseWrapper>
80
+ <StyledHeader>{title}</StyledHeader>
81
+ <LicenseByline licenseRights={rights} color={colors.brand.tertiary} />
82
+ </LicenseWrapper>
83
+ {description && <div dangerouslySetInnerHTML={{ __html: description }} />}
84
+ </StyledWrapper>
85
+ </section>
86
+ );
87
+ };
@@ -76,6 +76,7 @@ export type StepProps = {
76
76
  };
77
77
 
78
78
  interface Props {
79
+ onToggleAddToFavorites?: () => void;
79
80
  learningsteps: StepProps[];
80
81
  name: string;
81
82
  lastUpdated: string;
@@ -109,6 +110,7 @@ const LearningPathMenu = ({
109
110
  learningPathURL,
110
111
  invertedStyle,
111
112
  cookies,
113
+ onToggleAddToFavorites,
112
114
  }: Props) => {
113
115
  const { t } = useTranslation();
114
116
  const [isOpen, toggleOpenState] = useState(false);
@@ -129,7 +131,13 @@ const LearningPathMenu = ({
129
131
  </StyledToggleMenubutton>
130
132
  </Tooltip>
131
133
  </div>
132
- <LearningPathMenuIntro isOpen={isOpen} name={name} invertedStyle={invertedStyle} />
134
+ <LearningPathMenuIntro
135
+ isOpen={isOpen}
136
+ name={name}
137
+ invertedStyle={invertedStyle}
138
+ id={learningPathId}
139
+ onToggleAddToFavorites={onToggleAddToFavorites}
140
+ />
133
141
  <LearningPathMenuContent
134
142
  learningsteps={learningsteps}
135
143
  learningPathId={learningPathId}
@@ -9,22 +9,20 @@
9
9
  import React from 'react';
10
10
  import styled from '@emotion/styled';
11
11
  import { User } from '@ndla/icons/common';
12
- import { spacing, fonts } from '@ndla/core';
12
+ import { spacing, fonts, colors } from '@ndla/core';
13
+ import { getLicenseByAbbreviation, LicenseByline } from '@ndla/licenses';
13
14
 
14
15
  const StyledLearningPathDetails = styled.div`
15
16
  ${fonts.sizes(14, 1.1)};
16
17
  font-weight: ${fonts.weight.normal};
17
- margin: 0;
18
+ `;
19
+
20
+ const UserLine = styled.div`
18
21
  display: flex;
19
- align-items: flex-start;
20
- justify-items: flex-start;
21
22
  margin-bottom: ${spacing.xsmall};
22
- p {
23
- margin: 0;
24
- padding-left: ${spacing.xsmall};
25
- }
23
+
26
24
  span {
27
- display: block;
25
+ margin-left: ${spacing.xsmall};
28
26
  }
29
27
  `;
30
28
 
@@ -40,16 +38,20 @@ type Props = {
40
38
  };
41
39
  };
42
40
 
43
- const LearningPathMenuAsideCopyright = ({ copyright }: Props) => (
44
- <StyledLearningPathDetails>
45
- <User />
46
- <p>
47
- {copyright.contributors.map((contributor) => (
48
- <span key={contributor.name}>{contributor.name}</span>
49
- ))}
50
- <span>{copyright.license.license}</span>
51
- </p>
52
- </StyledLearningPathDetails>
53
- );
41
+ const LearningPathMenuAsideCopyright = ({ copyright }: Props) => {
42
+ const { rights } = getLicenseByAbbreviation(copyright.license.license || '', 'nb');
43
+ return (
44
+ <StyledLearningPathDetails>
45
+ <UserLine>
46
+ <User />
47
+ {copyright.contributors.map((contributor) => (
48
+ <span key={contributor.name}>{contributor.name}</span>
49
+ ))}
50
+ </UserLine>
51
+
52
+ <LicenseByline licenseRights={rights} color={colors.brand.tertiary} />
53
+ </StyledLearningPathDetails>
54
+ );
55
+ };
54
56
 
55
57
  export default LearningPathMenuAsideCopyright;
@@ -11,6 +11,7 @@ import styled from '@emotion/styled';
11
11
  import { css } from '@emotion/core';
12
12
  import { useTranslation } from 'react-i18next';
13
13
  import { colors, spacing, spacingUnit, fonts, typography, mq, breakpoints, animations } from '@ndla/core';
14
+ import { ArticleFavoritesButton } from '../Article';
14
15
 
15
16
  const StyledInfoHeader = styled.p`
16
17
  ${typography.smallHeading}
@@ -94,18 +95,30 @@ const StyledIntroHeader = styled.h1`
94
95
  margin: ${spacing.small} 0 ${spacing.normal};
95
96
  `;
96
97
 
98
+ const StyledRow = styled.div`
99
+ display: flex;
100
+ gap: ${spacing.small};
101
+ `;
102
+
97
103
  interface Props {
98
104
  isOpen: boolean;
99
105
  invertedStyle?: boolean;
100
106
  name: string;
107
+ onToggleAddToFavorites?: () => void;
108
+ id: number;
101
109
  }
102
110
 
103
- const LearningPathMenuIntro = ({ isOpen, name, invertedStyle }: Props) => {
111
+ const LearningPathMenuIntro = ({ isOpen, name, invertedStyle, onToggleAddToFavorites, id }: Props) => {
104
112
  const { t } = useTranslation();
105
113
  return (
106
114
  <StyledMenuIntro isOpen={isOpen} invertedStyle={invertedStyle}>
107
115
  <div>
108
- <StyledInfoHeader>{t('learningPath.youAreInALearningPath')}</StyledInfoHeader>
116
+ <StyledRow>
117
+ <StyledInfoHeader>{t('learningPath.youAreInALearningPath')}</StyledInfoHeader>
118
+ {onToggleAddToFavorites && (
119
+ <ArticleFavoritesButton onToggleAddToFavorites={onToggleAddToFavorites} articleId={id.toString()} />
120
+ )}
121
+ </StyledRow>
109
122
  <StyledIntroHeader>{name}</StyledIntroHeader>
110
123
  </div>
111
124
  </StyledMenuIntro>
@@ -95,7 +95,10 @@ export const Masthead = ({
95
95
  )}
96
96
  <div id="masthead" {...classes('', { fixed: !!fixed, infoContent: !!infoContent, ndlaFilm: !!ndlaFilm })}>
97
97
  {messages?.map((message) => (
98
- <MessageBanner showCloseButton={message.closable} onClose={() => onCloseAlert?.(message.number)}>
98
+ <MessageBanner
99
+ key={message.number}
100
+ showCloseButton={message.closable}
101
+ onClose={() => onCloseAlert?.(message.number)}>
99
102
  {message.content}
100
103
  </MessageBanner>
101
104
  ))}
@@ -24,7 +24,7 @@ const MessageBannerWrapper = styled.div<WrapperProps>`
24
24
  padding: ${({ small }) => (small ? spacing.xxsmall : spacing.small)};
25
25
  background: ${colors.support.yellowLight};
26
26
  color: ${colors.brand.greyDark};
27
- border: none;
27
+ border-bottom: solid 1px ${colors.white};
28
28
  `;
29
29
 
30
30
  const TextWrapper = styled.div`
@@ -88,6 +88,7 @@ const StyledImageWrapper = styled.div<StyledImageProps>`
88
88
  width: 54px;
89
89
  height: 40px;
90
90
  }
91
+ overflow: hidden;
91
92
  `;
92
93
 
93
94
  const StyledImage = styled(Image)`
@@ -74,6 +74,7 @@ export const TopicMenu = ({
74
74
  currentProgramme,
75
75
  initialSelectedMenu,
76
76
  messages,
77
+ closeAlert,
77
78
  selectedGrade,
78
79
  onGradeChange,
79
80
  }) => {
@@ -149,11 +150,15 @@ export const TopicMenu = ({
149
150
  const disableSubTopic = disableMain && hasExpandedSubtopics;
150
151
 
151
152
  const sliderCounter = !expandedTopicId ? 0 : expandedSubtopicsId.length + 1;
152
-
153
153
  return (
154
154
  <nav>
155
155
  {messages?.map((message) => (
156
- <MessageBanner>{message}</MessageBanner>
156
+ <MessageBanner
157
+ key={message.number}
158
+ showCloseButton={message.closable}
159
+ onClose={() => closeAlert?.(message.number)}>
160
+ {message.content}
161
+ </MessageBanner>
157
162
  ))}
158
163
  <ModalHeader modifier={['white', 'menu']}>
159
164
  <div {...classes('masthead-left')}>
@@ -358,6 +363,7 @@ TopicMenu.propTypes = {
358
363
  topics: PropTypes.arrayOf(TopicShape).isRequired,
359
364
  toFrontpage: PropTypes.func.isRequired,
360
365
  toTopic: PropTypes.func,
366
+ closeAlert: PropTypes.func,
361
367
  toSubject: PropTypes.func,
362
368
  close: PropTypes.func,
363
369
  defaultCount: PropTypes.number,
@@ -369,6 +375,13 @@ TopicMenu.propTypes = {
369
375
  hideSearch: PropTypes.bool,
370
376
  searchFieldComponent: PropTypes.node,
371
377
  locale: PropTypes.string,
378
+ messages: PropTypes.arrayOf(
379
+ PropTypes.shape({
380
+ content: PropTypes.string.isRequired,
381
+ closable: PropTypes.bool.isRequired,
382
+ number: PropTypes.number.isRequired,
383
+ }),
384
+ ),
372
385
  subjectCategories: PropTypes.arrayOf(
373
386
  PropTypes.shape({
374
387
  name: PropTypes.string.isRequired,