@ndla/ui 23.0.0 → 24.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 (95) hide show
  1. package/es/Article/ArticleAuthorContent.js +2 -4
  2. package/es/AuthorInfo/AuthorInfo.js +29 -16
  3. package/es/ContentCard/ContentCard.js +66 -25
  4. package/es/FileList/File.js +34 -8
  5. package/es/FileList/FileList.js +29 -3
  6. package/es/InfoBox/InfoBox.js +10 -3
  7. package/es/InfoWidget/InfoWidget.js +67 -22
  8. package/es/Portrait/Portrait.js +19 -13
  9. package/es/Search/ActiveFilterContent.js +4 -14
  10. package/es/Search/ActiveFilters.js +8 -19
  11. package/es/Search/SearchField.js +31 -52
  12. package/es/Search/SearchResult.js +113 -136
  13. package/es/Search/ToggleSearchButton.js +34 -43
  14. package/es/Search/index.js +2 -8
  15. package/es/all.css +1 -1
  16. package/es/index-javascript.js +0 -1
  17. package/es/index.js +2 -1
  18. package/lib/Article/ArticleAuthorContent.js +9 -4
  19. package/lib/AuthorInfo/AuthorInfo.d.ts +1 -11
  20. package/lib/AuthorInfo/AuthorInfo.js +36 -20
  21. package/lib/ContentCard/ContentCard.d.ts +1 -15
  22. package/lib/ContentCard/ContentCard.js +60 -28
  23. package/lib/FileList/File.js +36 -12
  24. package/lib/FileList/FileList.js +28 -5
  25. package/lib/InfoBox/InfoBox.js +11 -4
  26. package/lib/InfoWidget/InfoWidget.js +61 -25
  27. package/lib/Portrait/Portrait.js +19 -14
  28. package/lib/Search/ActiveFilterContent.d.ts +13 -0
  29. package/lib/Search/ActiveFilterContent.js +4 -15
  30. package/lib/Search/ActiveFilters.d.ts +13 -0
  31. package/lib/Search/ActiveFilters.js +8 -20
  32. package/lib/Search/SearchField.d.ts +19 -0
  33. package/lib/Search/SearchField.js +32 -56
  34. package/lib/Search/SearchResult.d.ts +36 -0
  35. package/lib/Search/SearchResult.js +116 -159
  36. package/lib/Search/ToggleSearchButton.d.ts +16 -0
  37. package/lib/Search/ToggleSearchButton.js +36 -46
  38. package/lib/Search/index.d.ts +12 -0
  39. package/lib/Search/index.js +0 -54
  40. package/lib/SearchTypeResult/SearchTypeHeader.d.ts +1 -1
  41. package/lib/all.css +1 -1
  42. package/lib/index-javascript.js +0 -74
  43. package/lib/index.d.ts +1 -0
  44. package/lib/index.js +38 -1
  45. package/package.json +5 -5
  46. package/src/Article/ArticleAuthorContent.tsx +1 -1
  47. package/src/AuthorInfo/AuthorInfo.tsx +53 -19
  48. package/src/ContentCard/ContentCard.tsx +127 -35
  49. package/src/FileList/File.tsx +47 -17
  50. package/src/FileList/FileList.tsx +37 -8
  51. package/src/InfoBox/InfoBox.tsx +24 -4
  52. package/src/InfoWidget/InfoWidget.tsx +83 -34
  53. package/src/Portrait/Portrait.tsx +25 -10
  54. package/src/Search/{ActiveFilterContent.jsx → ActiveFilterContent.tsx} +11 -12
  55. package/src/Search/{ActiveFilters.jsx → ActiveFilters.tsx} +20 -17
  56. package/src/Search/{SearchField.jsx → SearchField.tsx} +58 -68
  57. package/src/Search/SearchResult.tsx +360 -0
  58. package/src/Search/ToggleSearchButton.tsx +73 -0
  59. package/src/Search/component.search.scss +0 -4
  60. package/src/Search/index.ts +16 -0
  61. package/src/all.scss +0 -1
  62. package/src/index-javascript.js +0 -15
  63. package/src/index.ts +2 -0
  64. package/src/main.scss +0 -6
  65. package/es/Search/SearchFilter.js +0 -72
  66. package/es/Search/SearchFilterList.js +0 -115
  67. package/es/Search/SearchOverlay.js +0 -39
  68. package/es/Search/SearchPage.js +0 -178
  69. package/es/Search/SearchPopoverFilter.js +0 -152
  70. package/es/Search/SearchResultAuthor.js +0 -51
  71. package/lib/Search/SearchFilter.js +0 -88
  72. package/lib/Search/SearchFilterList.js +0 -137
  73. package/lib/Search/SearchOverlay.js +0 -62
  74. package/lib/Search/SearchPage.js +0 -207
  75. package/lib/Search/SearchPopoverFilter.js +0 -172
  76. package/lib/Search/SearchResultAuthor.js +0 -60
  77. package/src/AuthorInfo/component.author-info.scss +0 -54
  78. package/src/ContentCard/component.content-card.scss +0 -109
  79. package/src/FileList/component.file-list.scss +0 -102
  80. package/src/InfoBox/component.info-box.scss +0 -21
  81. package/src/InfoWidget/component.info-widget.scss +0 -52
  82. package/src/Portrait/component.portrait.scss +0 -29
  83. package/src/Search/SearchFilter.jsx +0 -82
  84. package/src/Search/SearchFilterList.jsx +0 -110
  85. package/src/Search/SearchOverlay.jsx +0 -38
  86. package/src/Search/SearchPage.jsx +0 -178
  87. package/src/Search/SearchPopoverFilter.jsx +0 -109
  88. package/src/Search/SearchResult.jsx +0 -239
  89. package/src/Search/SearchResultAuthor.jsx +0 -54
  90. package/src/Search/ToggleSearchButton.jsx +0 -64
  91. package/src/Search/component.search-filter.scss +0 -67
  92. package/src/Search/component.search-overlay.scss +0 -103
  93. package/src/Search/component.search-page.scss +0 -125
  94. package/src/Search/component.search-result-author.scss +0 -65
  95. package/src/Search/index.js +0 -34
@@ -1,13 +1,67 @@
1
+ import styled from '@emotion/styled';
2
+ import { css } from '@emotion/core';
1
3
  import React, { ReactNode } from 'react';
2
- import BEMHelper from 'react-bem-helper';
3
4
  import { Forward } from '@ndla/icons/common';
4
-
5
5
  import SafeLink from '@ndla/safelink';
6
+ import { colors, fonts, spacing } from '@ndla/core';
6
7
 
7
8
  import SectionHeading from '../SectionHeading';
8
9
 
9
- const classes = BEMHelper('c-info-widget');
10
+ interface InfoWidgetSectionProps {
11
+ center?: boolean;
12
+ }
13
+ const InfoWidgetSection = styled.section<InfoWidgetSectionProps>`
14
+ max-width: 600px;
15
+ margin: ${(p) => p.center && '0 auto'};
16
+ `;
17
+
18
+ const InfoWidgetDescription = styled.div`
19
+ padding: ${spacing.normal};
20
+ background: ${colors.brand.lighter};
21
+ color: ${colors.brand.dark};
22
+ ${fonts.sizes('18px', '26px')};
23
+
24
+ p {
25
+ margin-top: 0;
26
+ &:last-child {
27
+ margin-bottom: 0;
28
+ }
29
+ }
30
+ `;
31
+
32
+ const InfoWidgetLinksContainer = styled.div`
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: flex-end;
36
+ `;
37
+
38
+ const iconLinkStyle = css`
39
+ width: 47px;
40
+ height: 47px;
41
+ border-radius: 100%;
42
+ background: ${colors.brand.lighter};
43
+ color: ${colors.brand.dark};
44
+ box-shadow: none;
45
+ display: flex;
46
+ justify-content: center;
47
+ align-items: center;
48
+ margin-right: ${spacing.small};
10
49
 
50
+ .c-icon {
51
+ width: 20px;
52
+ height: 20px;
53
+ }
54
+ `;
55
+
56
+ const IconSafeLink = styled(SafeLink)(iconLinkStyle);
57
+
58
+ const IconAnchor = styled.a(iconLinkStyle);
59
+ const IconSpan = styled.span(iconLinkStyle);
60
+
61
+ const StyledMainLink = styled.a`
62
+ color: ${colors.brand.dark};
63
+ ${fonts.sizes('16px', '24px')};
64
+ `;
11
65
  interface Props {
12
66
  heading: string;
13
67
  description: string;
@@ -26,36 +80,33 @@ interface Props {
26
80
  }
27
81
 
28
82
  const InfoWidget = ({ heading, description, mainLink, iconLinks, center = false }: Props) => (
29
- <section {...classes('', { center })}>
30
- <SectionHeading large className={classes('heading').className}>
31
- {heading}
32
- </SectionHeading>
33
- <div {...classes('description')}>
83
+ <InfoWidgetSection center={center}>
84
+ <SectionHeading large>{heading}</SectionHeading>
85
+ <InfoWidgetDescription>
34
86
  <p>{description}</p>
35
- </div>
36
- <div {...classes('links')}>
37
- {iconLinks &&
38
- iconLinks.map((link) => {
39
- if (link.url) {
40
- return (
41
- <SafeLink key={link.url} {...classes('icon-link')} to={link.url} aria-label={link.name}>
42
- {link.icon}
43
- </SafeLink>
44
- );
45
- }
46
- if (link.href) {
47
- return (
48
- <a key={link.href} href={link.href} {...classes('icon-link')} aria-label={link.name}>
49
- {link.icon}
50
- </a>
51
- );
52
- }
87
+ </InfoWidgetDescription>
88
+ <InfoWidgetLinksContainer>
89
+ {iconLinks?.map((link) => {
90
+ if (link.url) {
91
+ return (
92
+ <IconSafeLink key={link.url} to={link.url} aria-label={link.name}>
93
+ {link.icon}
94
+ </IconSafeLink>
95
+ );
96
+ }
97
+ if (link.href) {
53
98
  return (
54
- <span key={link.name} {...classes('icon-link')} aria-label={link.name}>
99
+ <IconAnchor key={link.href} href={link.href} aria-label={link.name}>
55
100
  {link.icon}
56
- </span>
101
+ </IconAnchor>
57
102
  );
58
- })}
103
+ }
104
+ return (
105
+ <IconSpan key={link.name} aria-label={link.name}>
106
+ {link.icon}
107
+ </IconSpan>
108
+ );
109
+ })}
59
110
  {mainLink.url ? (
60
111
  <div className="o-text-link__wrapper o-text-link__wrapper--right">
61
112
  <SafeLink className="o-text-link" to={mainLink.url}>
@@ -63,12 +114,10 @@ const InfoWidget = ({ heading, description, mainLink, iconLinks, center = false
63
114
  </SafeLink>
64
115
  </div>
65
116
  ) : (
66
- <a {...classes('main-link')} href={mainLink.href}>
67
- {mainLink.name}
68
- </a>
117
+ <StyledMainLink href={mainLink.href}>{mainLink.name}</StyledMainLink>
69
118
  )}
70
- </div>
71
- </section>
119
+ </InfoWidgetLinksContainer>
120
+ </InfoWidgetSection>
72
121
  );
73
122
 
74
123
  export default InfoWidget;
@@ -6,13 +6,25 @@
6
6
  *
7
7
  */
8
8
 
9
+ import styled from '@emotion/styled';
9
10
  import React from 'react';
10
- import BEMHelper from 'react-bem-helper';
11
11
 
12
- const classes = new BEMHelper({
13
- name: 'portrait',
14
- prefix: 'c-',
15
- });
12
+ interface PortraitWrapperProps {
13
+ size: string;
14
+ }
15
+ const PortraitWrapper = styled.div<PortraitWrapperProps>`
16
+ width: ${(p) => p.size};
17
+ height: ${(p) => p.size};
18
+ span {
19
+ display: block;
20
+ border-radius: 50%;
21
+ background-color: rgba(0, 0, 0, 0.16);
22
+ background-size: cover;
23
+ background-position: center center;
24
+ width: ${(p) => p.size};
25
+ height: ${(p) => p.size};
26
+ }
27
+ `;
16
28
 
17
29
  interface Props {
18
30
  src: string;
@@ -21,10 +33,13 @@ interface Props {
21
33
  modifier?: 'small' | 'large';
22
34
  }
23
35
 
24
- const Portrait = ({ src, alt, modifier, className }: Props) => (
25
- <div {...classes('', modifier, className)}>
26
- <span role="img" aria-label={alt} style={{ backgroundImage: `url(${src})` }} />
27
- </div>
28
- );
36
+ const Portrait = ({ src, alt, modifier, className }: Props) => {
37
+ const size = modifier === 'small' ? '4rem' : modifier === 'large' ? '10rem' : '7rem';
38
+ return (
39
+ <PortraitWrapper size={size} className={className}>
40
+ <span role="img" aria-label={alt} style={{ backgroundImage: `url(${src})` }} />
41
+ </PortraitWrapper>
42
+ );
43
+ };
29
44
 
30
45
  export default Portrait;
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
2
  import styled from '@emotion/styled';
4
3
  import { Cross } from '@ndla/icons/action';
5
4
  import { spacing, mq, breakpoints, colors, misc, fonts } from '@ndla/core';
@@ -32,7 +31,17 @@ export const StyledActiveFilterTitle = styled('span')`
32
31
  padding-right: ${spacing.small};
33
32
  `;
34
33
 
35
- const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }) => (
34
+ interface Props {
35
+ filter: {
36
+ value: string;
37
+ title: string;
38
+ filterName?: string;
39
+ };
40
+ onFilterRemove: (value: string, filterName?: string) => void;
41
+ ariaLabel: string;
42
+ }
43
+
44
+ const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }: Props) => (
36
45
  <StyledActiveFilter
37
46
  aria-label={ariaLabel}
38
47
  type="button"
@@ -42,14 +51,4 @@ const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }) => (
42
51
  </StyledActiveFilter>
43
52
  );
44
53
 
45
- ActiveFilterContent.propTypes = {
46
- filter: PropTypes.shape({
47
- value: PropTypes.string.isRequired,
48
- title: PropTypes.string.isRequired,
49
- filterName: PropTypes.string,
50
- }),
51
- onFilterRemove: PropTypes.func.isRequired,
52
- ariaLabel: PropTypes.string.isRequired,
53
- };
54
-
55
54
  export default ActiveFilterContent;
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
2
  import styled from '@emotion/styled';
4
3
  import { css } from '@emotion/core';
5
4
  import { spacing, mq, breakpoints } from '@ndla/core';
@@ -7,7 +6,12 @@ import Tooltip from '@ndla/tooltip';
7
6
  import { useTranslation } from 'react-i18next';
8
7
  import ActiveFilterContent, { StyledActiveFilterTitle } from './ActiveFilterContent';
9
8
 
10
- const StyledActiveFilters = styled('ul')`
9
+ interface StyledActiveFiltersProps {
10
+ showOnSmallScreen?: boolean;
11
+ filterLength?: number;
12
+ }
13
+
14
+ const StyledActiveFilters = styled('ul')<StyledActiveFiltersProps>`
11
15
  margin: 0;
12
16
  padding: 0;
13
17
  flex-direction: column;
@@ -70,10 +74,22 @@ const StyledActiveFilterWrapper = styled('li')`
70
74
  }
71
75
  `;
72
76
 
73
- const getFilterLength = (filters) =>
77
+ const getFilterLength = (filters: Filter[]) =>
74
78
  filters.filter((filter) => filter.filterName === 'filter_subjects' && filter.title).length;
75
79
 
76
- const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
80
+ interface Filter {
81
+ title: string;
82
+ value: string;
83
+ filterName?: string;
84
+ }
85
+
86
+ interface Props {
87
+ filters: Filter[];
88
+ onFilterRemove: (value: string, filterName?: string) => void;
89
+ showOnSmallScreen?: boolean;
90
+ }
91
+
92
+ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }: Props) => {
77
93
  const { t } = useTranslation();
78
94
  if (filters && filters.length > 0) {
79
95
  const filterLength = getFilterLength(filters);
@@ -90,7 +106,6 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
90
106
  })}>
91
107
  <ActiveFilterContent
92
108
  filter={filter}
93
- filterLength={filterLength}
94
109
  ariaLabel={t('searchPage.searchFilterMessages.removeFilter', {
95
110
  filterName: filter.title,
96
111
  })}
@@ -100,7 +115,6 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
100
115
  ) : (
101
116
  <ActiveFilterContent
102
117
  filter={filter}
103
- filterLength={filterLength}
104
118
  onFilterRemove={onFilterRemove}
105
119
  ariaLabel={t('searchPage.searchFilterMessages.removeFilter', {
106
120
  filterName: filter.title,
@@ -121,15 +135,4 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
121
135
  return null;
122
136
  };
123
137
 
124
- ActiveFilters.propTypes = {
125
- filters: PropTypes.arrayOf(
126
- PropTypes.shape({
127
- value: PropTypes.string.isRequired,
128
- title: PropTypes.string.isRequired,
129
- filterName: PropTypes.string,
130
- }),
131
- ),
132
- onFilterRemove: PropTypes.func.isRequired,
133
- };
134
-
135
138
  export default ActiveFilters;
@@ -6,27 +6,30 @@
6
6
  *
7
7
  */
8
8
 
9
- import React from 'react';
10
- import PropTypes from 'prop-types';
9
+ import React, { FocusEvent, MouseEvent, RefObject } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
11
  import BEMHelper from 'react-bem-helper';
12
- import { Search as SearchIcon } from '@ndla/icons/common';
13
12
  import { css } from '@emotion/core';
13
+ import styled from '@emotion/styled';
14
+ import { Search as SearchIcon } from '@ndla/icons/common';
14
15
  import { colors, spacing, mq, breakpoints, misc, fonts } from '@ndla/core';
15
- import { useTranslation } from 'react-i18next';
16
16
 
17
17
  import ActiveFilters from './ActiveFilters';
18
18
  import LoadingWrapper from './LoadingWrapper';
19
19
 
20
- import { ContentTypeResultShape } from '../shapes';
21
-
22
20
  const classes = new BEMHelper('c-search-field');
23
21
 
24
- const inputStyle = (frontPageSearch) => css`
22
+ interface StyledInputProps {
23
+ frontPageSearch?: boolean;
24
+ hasFilters?: boolean;
25
+ }
26
+
27
+ const StyledInput = styled.input<StyledInputProps>`
25
28
  width: 100%;
26
29
  height: 48px;
27
30
  line-height: 28px;
28
31
  border: 1px solid ${colors.brand.greyLight};
29
- border-radius: ${frontPageSearch ? '100px' : misc.borderRadius};
32
+ border-radius: ${(p) => (p.frontPageSearch ? '100px' : misc.borderRadius)};
30
33
  padding-right: ${spacing.large};
31
34
  padding-left: ${spacing.normal};
32
35
  flex-grow: 1;
@@ -41,61 +44,71 @@ const inputStyle = (frontPageSearch) => css`
41
44
  line-height: 58px;
42
45
  ${fonts.sizes('18px', '24px')};
43
46
  }
44
- `;
45
47
 
46
- const filterStyle = css`
47
- ${mq.range({ from: breakpoints.desktop })} {
48
- padding-left: ${spacing.normal};
49
- }
50
- padding-left: 0;
51
- border-left: 0;
52
- border-top-left-radius: 0;
53
- border-bottom-left-radius: 0;
48
+ ${(p) =>
49
+ p.hasFilters &&
50
+ css`
51
+ ${mq.range({ from: breakpoints.desktop })} {
52
+ padding-left: ${spacing.normal};
53
+ }
54
+ padding-left: 0;
55
+ border-left: 0;
56
+ border-top-left-radius: 0;
57
+ border-bottom-left-radius: 0;
54
58
 
55
- &:focus {
56
- border: 1px solid ${colors.brand.primary};
57
- border-left: 0;
59
+ &:focus {
60
+ border: 1px solid ${colors.brand.primary};
61
+ border-left: 0;
58
62
 
59
- & + .c-search-field__filters {
60
- border: 1px solid ${colors.brand.primary};
61
- border-right: 0;
62
- }
63
- }
63
+ & + .c-search-field__filters {
64
+ border: 1px solid ${colors.brand.primary};
65
+ border-right: 0;
66
+ }
67
+ }
68
+ `};
64
69
  `;
65
70
 
71
+ interface Props {
72
+ value: string;
73
+ placeholder: string;
74
+ onChange: (value: string) => void;
75
+ filters?: { value: string; title: string }[];
76
+ onFilterRemove?: (value: string, filterName?: string) => void;
77
+ onFocus?: (event?: FocusEvent<HTMLInputElement>) => void;
78
+ onBlur?: () => void;
79
+ onClick?: (event: MouseEvent<HTMLInputElement>) => void;
80
+ loading?: boolean;
81
+ inputRef?: RefObject<HTMLInputElement>;
82
+ frontPageSearch?: boolean;
83
+ }
84
+
66
85
  const SearchField = ({
67
86
  placeholder,
68
87
  value,
69
88
  onChange,
70
89
  filters,
71
- small,
72
90
  onClick,
73
- onFocus = () => {},
74
- onBlur = () => {},
91
+ onFocus,
92
+ onBlur,
75
93
  loading,
76
94
  onFilterRemove,
77
95
  inputRef,
78
96
  frontPageSearch = false,
79
- }) => {
97
+ }: Props) => {
80
98
  const { t } = useTranslation();
81
- const handleOnFilterRemove = (value, filterName) => {
82
- onFilterRemove(value, filterName);
83
- if (inputRef) {
84
- inputRef.current.focus();
85
- }
86
- onFocus();
99
+ const handleOnFilterRemove = (value: string, filterName?: string) => {
100
+ onFilterRemove?.(value, filterName);
101
+ inputRef?.current?.focus();
102
+ onFocus?.();
87
103
  };
88
- const hasFilters = filters && filters.length > 0;
89
104
  return (
90
105
  <div {...classes('input-wrapper')}>
91
106
  {loading && <LoadingWrapper value={value} />}
92
- <input
107
+ <StyledInput
108
+ frontPageSearch={frontPageSearch}
109
+ hasFilters={!!filters?.length}
93
110
  ref={inputRef}
94
111
  type="search"
95
- css={css`
96
- ${inputStyle(frontPageSearch)};
97
- ${hasFilters && filterStyle};
98
- `}
99
112
  aria-autocomplete="list"
100
113
  autoComplete="off"
101
114
  id="search"
@@ -108,7 +121,7 @@ const SearchField = ({
108
121
  onFocus={onFocus}
109
122
  onClick={onClick}
110
123
  />
111
- {hasFilters && (
124
+ {filters && filters.length > 0 && (
112
125
  <div {...classes('filters')}>
113
126
  <ActiveFilters filters={filters} onFilterRemove={handleOnFilterRemove} />
114
127
  </div>
@@ -119,41 +132,18 @@ const SearchField = ({
119
132
  type="button"
120
133
  onClick={() => {
121
134
  onChange('');
122
- onFocus();
123
- if (inputRef) {
124
- inputRef.current.focus();
125
- }
135
+ onFocus?.();
136
+ inputRef?.current?.focus();
126
137
  }}
127
138
  onBlur={onBlur}>
128
139
  {t('welcomePage.resetSearch')}
129
140
  </button>
130
141
  )}
131
- <button tabIndex="-1" {...classes('button', 'searchIcon')} type="submit" value="Search">
142
+ <button tabIndex={-1} {...classes('button', 'searchIcon')} type="submit" value="Search">
132
143
  <SearchIcon />
133
144
  </button>
134
145
  </div>
135
146
  );
136
147
  };
137
148
 
138
- SearchField.propTypes = {
139
- value: PropTypes.string.isRequired,
140
- placeholder: PropTypes.string.isRequired,
141
- onChange: PropTypes.func.isRequired,
142
- filters: PropTypes.arrayOf(
143
- PropTypes.shape({
144
- value: PropTypes.string.isRequired,
145
- title: PropTypes.string.isRequired,
146
- }),
147
- ),
148
- searchResult: PropTypes.arrayOf(ContentTypeResultShape),
149
- allResultUrl: PropTypes.string,
150
- onFilterRemove: PropTypes.func,
151
- small: PropTypes.bool,
152
- onNavigate: PropTypes.func,
153
- onFocus: PropTypes.func,
154
- onBlur: PropTypes.func,
155
- onClick: PropTypes.func,
156
- loading: PropTypes.bool,
157
- };
158
-
159
149
  export default SearchField;