@uncinc/uncinc-react-kitchen-sink 2.1.4 → 2.1.8
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/dist/components/ApiAutocomplete/index.js +21 -1
- package/dist/components/ApiAutocomplete/stories.js +20 -0
- package/dist/components/Form/Checkbox/index.js +10 -2
- package/dist/components/Form/Checkbox/stories.js +3 -0
- package/dist/components/Form/Select/Input/index.js +7 -4
- package/dist/components/Form/Select/stories.js +8 -1
- package/dist/components/Header/index.js +4 -4
- package/dist/components/MagicLine/index.js +70 -0
- package/dist/components/MagicLine/stories.js +33 -0
- package/dist/components/MagicLine/stories.scss +38 -0
- package/dist/components/{Header/AnimationWrapper → NavigationScroll}/index.js +6 -6
- package/dist/components/NavigationScroll/stories.js +10 -0
- package/dist/components/NavigationScroll/stories.scss +17 -0
- package/dist/components/{Header/AnimationWrapper → NavigationScroll}/style.scss +4 -5
- package/dist/components/SearchKit/Facets/ChipFacet/index.js +8 -7
- package/dist/components/SearchKit/Facets/HierarchicalFilterFacet/index.js +62 -0
- package/dist/components/SearchKit/Facets/HierarchicalMenuFacet/index.js +62 -0
- package/dist/components/SearchKit/Facets/ListFacet/index.js +9 -2
- package/dist/components/SearchKit/Facets/SelectFacet/index.js +4 -3
- package/dist/components/SearchKit/Query/index.js +8 -2
- package/dist/components/SearchKit/SearchFacets/index.js +9 -2
- package/dist/components/SearchKit/SearchPage/index.js +48 -1
- package/dist/components/SearchKit/SearchSelectedFilters/index.js +7 -2
- package/dist/components/SearchKit/SearchSorting/index.js +5 -1
- package/dist/components/SearchKit/index.js +5 -2
- package/dist/components/SearchKit/stories.js +77 -1
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -2,6 +2,19 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import Autosuggest from 'react-autosuggest';
|
|
3
3
|
import './style.scss';
|
|
4
4
|
|
|
5
|
+
function abortableFetch(request, opts) {
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const signal = controller.signal;
|
|
8
|
+
return {
|
|
9
|
+
abort: () => controller.abort(),
|
|
10
|
+
ready: fetch(request, { ...opts,
|
|
11
|
+
signal
|
|
12
|
+
})
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let currentFetch = null;
|
|
17
|
+
|
|
5
18
|
const ApiAutocomplete = ({
|
|
6
19
|
endpoint,
|
|
7
20
|
placeholder,
|
|
@@ -16,7 +29,13 @@ const ApiAutocomplete = ({
|
|
|
16
29
|
|
|
17
30
|
const getSuggestions = query => {
|
|
18
31
|
const url = `${endpoint}?${queryParameter}=${query}`;
|
|
19
|
-
|
|
32
|
+
|
|
33
|
+
if (currentFetch) {
|
|
34
|
+
currentFetch.abort();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
currentFetch = abortableFetch(url);
|
|
38
|
+
currentFetch.ready.then(response => {
|
|
20
39
|
return response.json();
|
|
21
40
|
}).then(response => {
|
|
22
41
|
const ajaxResults = response.map((item, index) => {
|
|
@@ -24,6 +43,7 @@ const ApiAutocomplete = ({
|
|
|
24
43
|
return item;
|
|
25
44
|
});
|
|
26
45
|
setResults(ajaxResults);
|
|
46
|
+
}).catch(e => {// Catch the error so the browser does not output errors.
|
|
27
47
|
});
|
|
28
48
|
};
|
|
29
49
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ApiAutocomplete from './';
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Autocomplete'
|
|
5
|
+
};
|
|
6
|
+
export const Default = () => {
|
|
7
|
+
return /*#__PURE__*/React.createElement(ApiAutocomplete, {
|
|
8
|
+
endpoint: "http://nldoet.devinc.eu/autocomplete/json",
|
|
9
|
+
renderItem: item => {
|
|
10
|
+
console.log(item);
|
|
11
|
+
return /*#__PURE__*/React.createElement("div", null, item.name);
|
|
12
|
+
},
|
|
13
|
+
onSelectItem: item => {
|
|
14
|
+
console.log('Selected', item);
|
|
15
|
+
},
|
|
16
|
+
inputProps: {
|
|
17
|
+
label: 'test'
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -17,7 +17,8 @@ const Checkbox = props => {
|
|
|
17
17
|
touched,
|
|
18
18
|
error,
|
|
19
19
|
value,
|
|
20
|
-
displayRequiredIndicator
|
|
20
|
+
displayRequiredIndicator,
|
|
21
|
+
onChange
|
|
21
22
|
} = props;
|
|
22
23
|
return /*#__PURE__*/React.createElement(GenericFormElement, {
|
|
23
24
|
className: "Checkbox",
|
|
@@ -49,9 +50,16 @@ const Checkbox = props => {
|
|
|
49
50
|
name: fieldName,
|
|
50
51
|
type: "checkbox",
|
|
51
52
|
id: id,
|
|
52
|
-
checked: field.value
|
|
53
|
+
checked: field.value,
|
|
54
|
+
onChange: e => {
|
|
55
|
+
field.onChange(e);
|
|
56
|
+
onChange(!field.value);
|
|
57
|
+
}
|
|
53
58
|
})), title);
|
|
54
59
|
}));
|
|
55
60
|
};
|
|
56
61
|
|
|
62
|
+
Checkbox.defaultProps = {
|
|
63
|
+
onChange: () => {}
|
|
64
|
+
};
|
|
57
65
|
export default withMapping(Checkbox);
|
|
@@ -56,18 +56,21 @@ const SelectInput = props => {
|
|
|
56
56
|
if (e) {
|
|
57
57
|
if (onChange) {
|
|
58
58
|
onChange(e.value);
|
|
59
|
-
} else {
|
|
60
|
-
form.setFieldValue(fieldName, e.value);
|
|
61
59
|
}
|
|
60
|
+
|
|
61
|
+
form.setFieldValue(fieldName, e.value);
|
|
62
62
|
} else {
|
|
63
63
|
if (onChange) {
|
|
64
64
|
onChange('');
|
|
65
|
-
} else {
|
|
66
|
-
form.setFieldValue(fieldName, null);
|
|
67
65
|
}
|
|
66
|
+
|
|
67
|
+
form.setFieldValue(fieldName, null);
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
options: optionsTransformed,
|
|
71
|
+
isOptionDisabled: option => {
|
|
72
|
+
return option.disabled;
|
|
73
|
+
},
|
|
71
74
|
placeholder: placeholder,
|
|
72
75
|
isClearable: true,
|
|
73
76
|
theme: {
|
|
@@ -5,7 +5,11 @@ export default {
|
|
|
5
5
|
title: 'Molecules/Form'
|
|
6
6
|
};
|
|
7
7
|
export const Select = () => {
|
|
8
|
-
return /*#__PURE__*/React.createElement(FormikWrapper,
|
|
8
|
+
return /*#__PURE__*/React.createElement(FormikWrapper, {
|
|
9
|
+
initialValues: {
|
|
10
|
+
poison: 'beer'
|
|
11
|
+
}
|
|
12
|
+
}, /*#__PURE__*/React.createElement(FormikSelect, {
|
|
9
13
|
title: "Pick your poison",
|
|
10
14
|
required: true,
|
|
11
15
|
description: "This is a test input.",
|
|
@@ -25,6 +29,9 @@ export const Select = () => {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
return error;
|
|
32
|
+
},
|
|
33
|
+
onChange: e => {
|
|
34
|
+
console.log(e);
|
|
28
35
|
}
|
|
29
36
|
}));
|
|
30
37
|
};
|
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import classnames from 'classnames';
|
|
3
3
|
import Container from '../Layout/Container';
|
|
4
4
|
import Hamburger from '../Hamburger';
|
|
5
|
-
import
|
|
5
|
+
import NavigationScroll from '../NavigationScroll';
|
|
6
6
|
import './style.scss';
|
|
7
7
|
|
|
8
8
|
const Header = ({
|
|
@@ -33,7 +33,7 @@ const Header = ({
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const
|
|
36
|
+
const onUpdateNavigationScroll = (isVisible, hasReachedTop, scrolledPastNavHeight) => {
|
|
37
37
|
const shouldUpdate = state.visible !== isVisible || state.reachedTop !== hasReachedTop || state.scrolledPastNavHeight !== scrolledPastNavHeight;
|
|
38
38
|
|
|
39
39
|
if (shouldUpdate) {
|
|
@@ -66,8 +66,8 @@ const Header = ({
|
|
|
66
66
|
}, /*#__PURE__*/React.createElement(Container, null, subMenu)));
|
|
67
67
|
|
|
68
68
|
if (withAnimation) {
|
|
69
|
-
return /*#__PURE__*/React.createElement(
|
|
70
|
-
onUpdate:
|
|
69
|
+
return /*#__PURE__*/React.createElement(NavigationScroll, {
|
|
70
|
+
onUpdate: onUpdateNavigationScroll,
|
|
71
71
|
hasBackground: true
|
|
72
72
|
}, headerComponent);
|
|
73
73
|
} else {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
+
import c from 'classnames';
|
|
3
|
+
|
|
4
|
+
const MagicLine = ({
|
|
5
|
+
activeClassName = "Menu__item--active",
|
|
6
|
+
children
|
|
7
|
+
}) => {
|
|
8
|
+
const magicLineParentRef = useRef(null);
|
|
9
|
+
const magicLineRef = useRef(null);
|
|
10
|
+
const currentActiveItem = useRef(null);
|
|
11
|
+
const [loaded, setLoaded] = useState(false);
|
|
12
|
+
const [activeItemInNavigation, _setActiveItemInNavigation] = useState(false);
|
|
13
|
+
|
|
14
|
+
const setActiveItemInNavigation = value => {
|
|
15
|
+
if (value !== activeItemInNavigation) {
|
|
16
|
+
_setActiveItemInNavigation(value);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const MagicLineRefClasses = c('MagicLine__magic_line', {
|
|
21
|
+
'MagicLine__magic_line--visible': activeItemInNavigation && loaded
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const alignMagicLine = () => {
|
|
25
|
+
if (magicLineRef.current && currentActiveItem.current) {
|
|
26
|
+
const left = currentActiveItem.current.getBoundingClientRect().left - magicLineParentRef.current.getBoundingClientRect().left;
|
|
27
|
+
const right = magicLineParentRef.current.getBoundingClientRect().width - left - currentActiveItem.current.getBoundingClientRect().width;
|
|
28
|
+
magicLineRef.current.style.left = `${left}px`;
|
|
29
|
+
magicLineRef.current.style.right = `${right}px`;
|
|
30
|
+
setLoaded(true);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const hoverMagicLine = e => {
|
|
35
|
+
currentActiveItem.current = e.target;
|
|
36
|
+
alignMagicLine();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const setInitialMagicLine = () => {
|
|
40
|
+
currentActiveItem.current = document.getElementsByClassName(activeClassName)[0];
|
|
41
|
+
alignMagicLine();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const initialize = () => {
|
|
46
|
+
setInitialMagicLine();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleResize = () => {
|
|
50
|
+
alignMagicLine();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
document.fonts.ready.then(initialize);
|
|
54
|
+
window.addEventListener('load', initialize);
|
|
55
|
+
window.addEventListener("resize", handleResize);
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('load', initialize);
|
|
58
|
+
window.removeEventListener("resize", handleResize);
|
|
59
|
+
};
|
|
60
|
+
}, []);
|
|
61
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
62
|
+
ref: magicLineParentRef,
|
|
63
|
+
className: "MagicLine"
|
|
64
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
65
|
+
ref: magicLineRef,
|
|
66
|
+
className: MagicLineRefClasses
|
|
67
|
+
}), children(setInitialMagicLine, hoverMagicLine, setActiveItemInNavigation));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default MagicLine;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import c from 'classnames';
|
|
3
|
+
import MagicLine from './';
|
|
4
|
+
import './stories.scss';
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Molecules/MagicLine'
|
|
7
|
+
};
|
|
8
|
+
export const Default = () => /*#__PURE__*/React.createElement(MagicLine, null, (setInitialMagicLine, hoverMagicLine, setActiveItemInNavigation) => {
|
|
9
|
+
const items = ["one", "two with a longer name", "three"];
|
|
10
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
11
|
+
className: "Menu"
|
|
12
|
+
}, items.map(item => {
|
|
13
|
+
const active = item === "three";
|
|
14
|
+
|
|
15
|
+
if (active) {
|
|
16
|
+
setActiveItemInNavigation(true);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const classes = c('Menu__item', {
|
|
20
|
+
'Menu__item--active': active
|
|
21
|
+
});
|
|
22
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
23
|
+
key: item,
|
|
24
|
+
className: classes,
|
|
25
|
+
onMouseEnter: e => {
|
|
26
|
+
hoverMagicLine(e);
|
|
27
|
+
},
|
|
28
|
+
onMouseLeave: e => {
|
|
29
|
+
setInitialMagicLine();
|
|
30
|
+
}
|
|
31
|
+
}, item);
|
|
32
|
+
}));
|
|
33
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
.Menu {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
|
|
5
|
+
&__item {
|
|
6
|
+
margin: 0 1rem;
|
|
7
|
+
padding: 0 1rem;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.MagicLine {
|
|
12
|
+
position: relative;
|
|
13
|
+
|
|
14
|
+
&__magic_line {
|
|
15
|
+
pointer-events: none;
|
|
16
|
+
position: absolute;
|
|
17
|
+
bottom: 0;
|
|
18
|
+
left: 0;
|
|
19
|
+
right: 100%;
|
|
20
|
+
padding: 0;
|
|
21
|
+
margin: 0;
|
|
22
|
+
background-color: red;
|
|
23
|
+
height: .2rem;
|
|
24
|
+
z-index: 1000000;
|
|
25
|
+
opacity: 0;
|
|
26
|
+
|
|
27
|
+
&--visible {
|
|
28
|
+
opacity: 1;
|
|
29
|
+
transition: left .3s cubic-bezier(0.64, 0.04, 0.35, 1),
|
|
30
|
+
right .3s cubic-bezier(0.64, 0.04, 0.35, 1),
|
|
31
|
+
opacity 0.3s .3s cubic-bezier(0.64, 0.04, 0.35, 1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:hover .MagicLine__magic_line {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -3,7 +3,7 @@ import classNames from 'classnames';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import './style.scss';
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const NavigationScroll = props => {
|
|
7
7
|
const node = useRef(null);
|
|
8
8
|
const [state, setState] = useState({
|
|
9
9
|
pos: 0,
|
|
@@ -71,8 +71,8 @@ const AnimationWrapper = props => {
|
|
|
71
71
|
children,
|
|
72
72
|
hasBackground
|
|
73
73
|
} = props;
|
|
74
|
-
const classes = classNames('
|
|
75
|
-
'
|
|
74
|
+
const classes = classNames('NavigationScroll', {
|
|
75
|
+
'NavigationScroll--hasBackground': hasBackground,
|
|
76
76
|
's-scrolled-past-nav-height': scrolledPastNavHeight,
|
|
77
77
|
's-reached-page-top': reachedTop,
|
|
78
78
|
's-reached-page-bottom': reachedBottom
|
|
@@ -86,11 +86,11 @@ const AnimationWrapper = props => {
|
|
|
86
86
|
}, children);
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
NavigationScroll.propTypes = {
|
|
90
90
|
children: PropTypes.element.isRequired,
|
|
91
91
|
onUpdate: PropTypes.func
|
|
92
92
|
};
|
|
93
|
-
|
|
93
|
+
NavigationScroll.defaultProps = {
|
|
94
94
|
onUpdate: () => {}
|
|
95
95
|
};
|
|
96
|
-
export default
|
|
96
|
+
export default NavigationScroll;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import c from 'classnames';
|
|
3
|
+
import NavigationScroll from './';
|
|
4
|
+
import './stories.scss';
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Molecules/NavigationScroll'
|
|
7
|
+
};
|
|
8
|
+
export const Default = () => /*#__PURE__*/React.createElement("div", {
|
|
9
|
+
className: "NavigationScrollExample"
|
|
10
|
+
}, /*#__PURE__*/React.createElement(NavigationScroll, null, /*#__PURE__*/React.createElement("nav", null, /*#__PURE__*/React.createElement("div", null, "one"), /*#__PURE__*/React.createElement("div", null, "two"), /*#__PURE__*/React.createElement("div", null, "three"))));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.NavigationScrollExample {
|
|
2
|
+
min-height: 200vh;
|
|
3
|
+
background: linear-gradient(0deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%);
|
|
4
|
+
margin: -4rem;
|
|
5
|
+
|
|
6
|
+
nav {
|
|
7
|
+
background-color: grey;
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: row;
|
|
10
|
+
padding: 2rem;
|
|
11
|
+
|
|
12
|
+
& > div {
|
|
13
|
+
flex: 0 0 auto;
|
|
14
|
+
margin: 0 1rem;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@import '
|
|
1
|
+
@import '../../styles/assets/variables';
|
|
2
2
|
|
|
3
3
|
@keyframes animation-wrapper--slide-down {
|
|
4
4
|
from {
|
|
@@ -10,21 +10,20 @@
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
.
|
|
13
|
+
.NavigationScroll {
|
|
14
14
|
position: fixed;
|
|
15
15
|
top: 0;
|
|
16
16
|
left: 0;
|
|
17
17
|
width: 100%;
|
|
18
18
|
display: block;
|
|
19
19
|
z-index: $z-index-4;
|
|
20
|
-
transition: 0.5s
|
|
20
|
+
transition: background-color 0.5s ease-in-out;
|
|
21
21
|
|
|
22
22
|
&--hasBackground {
|
|
23
|
-
background: white;
|
|
23
|
+
background-color: white;
|
|
24
24
|
|
|
25
25
|
&.s-reached-page-bottom {
|
|
26
26
|
animation: animation-wrapper--slide-down 0.3s $animation-timing--cubic-bezier;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { useSearchkit } from '@searchkit/client';
|
|
3
3
|
import Button from '../../../Button';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
+
|
|
6
|
+
const makeSafeForCSS = value => {
|
|
7
|
+
return encodeURIComponent(value).replace(/\.|%[0-9a-z]{2}/gi, '');
|
|
8
|
+
};
|
|
9
|
+
|
|
5
10
|
export const ChipFacet = ({
|
|
6
11
|
facet
|
|
7
12
|
}) => {
|
|
8
13
|
const api = useSearchkit();
|
|
9
|
-
|
|
10
|
-
const makeSafeForCSS = value => {
|
|
11
|
-
return encodeURIComponent(value).replace(/\.|%[0-9a-z]{2}/gi, '');
|
|
12
|
-
};
|
|
13
|
-
|
|
14
14
|
return /*#__PURE__*/React.createElement("div", {
|
|
15
|
+
className: "Facet ChipFacet",
|
|
15
16
|
key: facet.identifier
|
|
16
17
|
}, /*#__PURE__*/React.createElement("span", null, facet.label), /*#__PURE__*/React.createElement("div", null, facet.entries.map(entry => {
|
|
17
18
|
const isSelected = api.isFilterSelected({
|
|
@@ -21,9 +22,9 @@ export const ChipFacet = ({
|
|
|
21
22
|
const classes = classNames('Button--Chip', makeSafeForCSS(`Button--${entry.label}`), {
|
|
22
23
|
'Button--selected': isSelected
|
|
23
24
|
});
|
|
24
|
-
console.log(entry);
|
|
25
25
|
return /*#__PURE__*/React.createElement(Button, {
|
|
26
26
|
className: classes,
|
|
27
|
+
disabled: parseInt(entry.count) === 0,
|
|
27
28
|
onClick: () => {
|
|
28
29
|
api.toggleFilter({
|
|
29
30
|
identifier: facet.identifier,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from 'react';
|
|
2
|
+
import { EuiFacetGroup, EuiTitle, EuiFacetButton } from '@elastic/eui';
|
|
3
|
+
import { useSearchkit, FilterLink } from '@searchkit/client';
|
|
4
|
+
|
|
5
|
+
const EntriesList = ({
|
|
6
|
+
entries,
|
|
7
|
+
loading,
|
|
8
|
+
facet
|
|
9
|
+
}) => {
|
|
10
|
+
console.log('entries', entries);
|
|
11
|
+
const api = useSearchkit();
|
|
12
|
+
const entriesElements = entries.map(entry => {
|
|
13
|
+
const ref = useRef();
|
|
14
|
+
return /*#__PURE__*/React.createElement(Fragment, {
|
|
15
|
+
key: entry.label
|
|
16
|
+
}, /*#__PURE__*/React.createElement(EuiFacetButton, {
|
|
17
|
+
style: {
|
|
18
|
+
height: '28px',
|
|
19
|
+
marginTop: 0,
|
|
20
|
+
marginBottom: 0
|
|
21
|
+
},
|
|
22
|
+
quantity: entry.count,
|
|
23
|
+
isSelected: api.isFilterSelected({
|
|
24
|
+
identifier: facet.identifier,
|
|
25
|
+
value: entry.label,
|
|
26
|
+
level: entry.level
|
|
27
|
+
}),
|
|
28
|
+
isLoading: loading,
|
|
29
|
+
onClick: e => {
|
|
30
|
+
ref.current.onClick(e);
|
|
31
|
+
}
|
|
32
|
+
}, /*#__PURE__*/React.createElement(FilterLink, {
|
|
33
|
+
ref: ref,
|
|
34
|
+
filter: {
|
|
35
|
+
identifier: facet.identifier,
|
|
36
|
+
value: entry.label,
|
|
37
|
+
level: entry.level
|
|
38
|
+
}
|
|
39
|
+
}, entry.label)), /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
style: {
|
|
41
|
+
marginLeft: '10px'
|
|
42
|
+
}
|
|
43
|
+
}, entry.entries && /*#__PURE__*/React.createElement(EntriesList, {
|
|
44
|
+
entries: entry.entries,
|
|
45
|
+
loading: loading,
|
|
46
|
+
facet: facet
|
|
47
|
+
})));
|
|
48
|
+
});
|
|
49
|
+
return /*#__PURE__*/React.createElement(EuiFacetGroup, null, entriesElements);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const HierarchicalFilterFacet = ({
|
|
53
|
+
facet,
|
|
54
|
+
loading
|
|
55
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EuiTitle, {
|
|
56
|
+
size: "xxs"
|
|
57
|
+
}, /*#__PURE__*/React.createElement("h3", null, facet.label)), /*#__PURE__*/React.createElement(EntriesList, {
|
|
58
|
+
entries: facet.entries,
|
|
59
|
+
facet: facet,
|
|
60
|
+
loading: loading
|
|
61
|
+
}));
|
|
62
|
+
HierarchicalFilterFacet.DISPLAY = 'HierarchicalFilterFacet';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from 'react';
|
|
2
|
+
import { EuiFacetGroup, EuiTitle, EuiFacetButton } from '@elastic/eui';
|
|
3
|
+
import { useSearchkit, FilterLink } from '@searchkit/client';
|
|
4
|
+
|
|
5
|
+
const EntriesList = ({
|
|
6
|
+
entries,
|
|
7
|
+
loading,
|
|
8
|
+
facet
|
|
9
|
+
}) => {
|
|
10
|
+
console.log('entries', entries);
|
|
11
|
+
const api = useSearchkit();
|
|
12
|
+
const entriesElements = entries.map(entry => {
|
|
13
|
+
const ref = useRef();
|
|
14
|
+
return /*#__PURE__*/React.createElement(Fragment, {
|
|
15
|
+
key: entry.label
|
|
16
|
+
}, /*#__PURE__*/React.createElement(EuiFacetButton, {
|
|
17
|
+
style: {
|
|
18
|
+
height: '28px',
|
|
19
|
+
marginTop: 0,
|
|
20
|
+
marginBottom: 0
|
|
21
|
+
},
|
|
22
|
+
quantity: entry.count,
|
|
23
|
+
isSelected: api.isFilterSelected({
|
|
24
|
+
identifier: facet.identifier,
|
|
25
|
+
value: entry.label,
|
|
26
|
+
level: entry.level
|
|
27
|
+
}),
|
|
28
|
+
isLoading: loading,
|
|
29
|
+
onClick: e => {
|
|
30
|
+
ref.current.onClick(e);
|
|
31
|
+
}
|
|
32
|
+
}, /*#__PURE__*/React.createElement(FilterLink, {
|
|
33
|
+
ref: ref,
|
|
34
|
+
filter: {
|
|
35
|
+
identifier: facet.identifier,
|
|
36
|
+
value: entry.label,
|
|
37
|
+
level: entry.level
|
|
38
|
+
}
|
|
39
|
+
}, entry.label)), /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
style: {
|
|
41
|
+
marginLeft: '10px'
|
|
42
|
+
}
|
|
43
|
+
}, entry.entries && /*#__PURE__*/React.createElement(EntriesList, {
|
|
44
|
+
entries: entry.entries,
|
|
45
|
+
loading: loading,
|
|
46
|
+
facet: facet
|
|
47
|
+
})));
|
|
48
|
+
});
|
|
49
|
+
return /*#__PURE__*/React.createElement(EuiFacetGroup, null, entriesElements);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const HierarchicalMenuFacet = ({
|
|
53
|
+
facet,
|
|
54
|
+
loading
|
|
55
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EuiTitle, {
|
|
56
|
+
size: "xxs"
|
|
57
|
+
}, /*#__PURE__*/React.createElement("h3", null, facet.label)), /*#__PURE__*/React.createElement(EntriesList, {
|
|
58
|
+
entries: facet.entries,
|
|
59
|
+
facet: facet,
|
|
60
|
+
loading: loading
|
|
61
|
+
}));
|
|
62
|
+
HierarchicalMenuFacet.DISPLAY = 'HierarchicalMenuFacet';
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useSearchkit } from '@searchkit/client';
|
|
3
|
+
import classNames from 'classnames';
|
|
3
4
|
export const ListFacet = ({
|
|
4
5
|
facet
|
|
5
6
|
}) => {
|
|
6
7
|
const api = useSearchkit();
|
|
7
8
|
return /*#__PURE__*/React.createElement("div", {
|
|
9
|
+
className: "Facet ListFacet",
|
|
8
10
|
key: facet.identifier
|
|
9
11
|
}, /*#__PURE__*/React.createElement("span", null, facet.label), /*#__PURE__*/React.createElement("ul", null, facet.entries.map(entry => {
|
|
10
12
|
const isSelected = api.isFilterSelected({
|
|
11
13
|
identifier: facet.identifier,
|
|
12
14
|
value: entry.label
|
|
13
15
|
});
|
|
16
|
+
const classes = classNames({
|
|
17
|
+
selected: isSelected,
|
|
18
|
+
disabled: parseInt(entry.count) === 0
|
|
19
|
+
});
|
|
14
20
|
return /*#__PURE__*/React.createElement("li", {
|
|
15
|
-
className:
|
|
21
|
+
className: classes,
|
|
16
22
|
key: entry.label
|
|
17
23
|
}, /*#__PURE__*/React.createElement("button", {
|
|
18
24
|
onClick: () => {
|
|
@@ -21,7 +27,8 @@ export const ListFacet = ({
|
|
|
21
27
|
value: entry.label
|
|
22
28
|
});
|
|
23
29
|
api.search();
|
|
24
|
-
}
|
|
30
|
+
},
|
|
31
|
+
disabled: parseInt(entry.count) === 0
|
|
25
32
|
}, entry.label, " (", entry.count, ")"));
|
|
26
33
|
})));
|
|
27
34
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { useSearchkit } from '@searchkit/client';
|
|
3
3
|
import Select from '../../../Form/Select';
|
|
4
4
|
import FormikWrapper from '../../../Form/FormikWrapper';
|
|
@@ -8,9 +8,11 @@ export const SelectFacet = ({
|
|
|
8
8
|
const api = useSearchkit();
|
|
9
9
|
const options = facet.entries.map(entry => ({
|
|
10
10
|
value: entry.label,
|
|
11
|
-
label: entry.label
|
|
11
|
+
label: entry.label,
|
|
12
|
+
disabled: parseInt(entry.count) === 0
|
|
12
13
|
}));
|
|
13
14
|
return /*#__PURE__*/React.createElement("div", {
|
|
15
|
+
className: "Facet SelectFacet",
|
|
14
16
|
key: facet.identifier
|
|
15
17
|
}, /*#__PURE__*/React.createElement(FormikWrapper, null, /*#__PURE__*/React.createElement(Select, {
|
|
16
18
|
title: facet.label,
|
|
@@ -19,7 +21,6 @@ export const SelectFacet = ({
|
|
|
19
21
|
fieldName: facet.identifier,
|
|
20
22
|
options: options,
|
|
21
23
|
onChange: value => {
|
|
22
|
-
console.log(value);
|
|
23
24
|
api.toggleFilter({
|
|
24
25
|
identifier: facet.identifier,
|
|
25
26
|
value: value
|
|
@@ -3,8 +3,9 @@ import { gql, useQuery } from '@apollo/client';
|
|
|
3
3
|
import { useSearchkitVariables } from '@searchkit/client';
|
|
4
4
|
import SearchPage from '../SearchPage';
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function Query({
|
|
7
7
|
query,
|
|
8
|
+
useRouting,
|
|
8
9
|
children
|
|
9
10
|
}) {
|
|
10
11
|
const graphQuery = useMemo(() => {
|
|
@@ -21,7 +22,12 @@ function App({
|
|
|
21
22
|
} = useQuery(graphQuery, {
|
|
22
23
|
variables
|
|
23
24
|
});
|
|
25
|
+
|
|
26
|
+
if (!useRouting) {
|
|
27
|
+
return /*#__PURE__*/React.createElement("div", null, children(data, loading));
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
return /*#__PURE__*/React.createElement(SearchPage, null, children(data, loading));
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
export default
|
|
33
|
+
export default Query;
|
|
@@ -2,9 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { SelectFacet } from '../Facets/SelectFacet';
|
|
3
3
|
import { ListFacet } from '../Facets/ListFacet';
|
|
4
4
|
import { ChipFacet } from '../Facets/ChipFacet';
|
|
5
|
+
import { HierarchicalFilterFacet } from '../Facets/HierarchicalFilterFacet';
|
|
6
|
+
import { HierarchicalMenuFacet } from '../Facets/HierarchicalMenuFacet';
|
|
5
7
|
|
|
6
8
|
const FacetList = (components = []) => {
|
|
7
|
-
const FacetsMapper = [
|
|
9
|
+
const FacetsMapper = [HierarchicalFilterFacet, HierarchicalMenuFacet, SelectFacet, ChipFacet, ListFacet, ...components].reduce((sum, component) => {
|
|
8
10
|
sum[component.DISPLAY] = component;
|
|
9
11
|
return sum;
|
|
10
12
|
}, {});
|
|
@@ -35,10 +37,15 @@ const SearchFacets = ({
|
|
|
35
37
|
facets
|
|
36
38
|
}) => {
|
|
37
39
|
const Facets = FacetList(facets);
|
|
40
|
+
|
|
41
|
+
if (!data) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
return /*#__PURE__*/React.createElement("div", {
|
|
39
46
|
className: "SearchFacets"
|
|
40
47
|
}, /*#__PURE__*/React.createElement(Facets, {
|
|
41
|
-
data: data
|
|
48
|
+
data: data.results,
|
|
42
49
|
loading: loading
|
|
43
50
|
}));
|
|
44
51
|
};
|
|
@@ -6,4 +6,51 @@ const SearchPage = ({
|
|
|
6
6
|
children
|
|
7
7
|
}) => /*#__PURE__*/React.createElement(EuiPage, null, children);
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
console.log('W', typeof withSearchkitRouting, withSearchkitRouting.getInitialProps);
|
|
10
|
+
export const routeToStateFn = routeState => {
|
|
11
|
+
const value = {
|
|
12
|
+
query: routeState.query || '',
|
|
13
|
+
sortBy: routeState.sort || '',
|
|
14
|
+
filters: routeState.filters || [],
|
|
15
|
+
page: {
|
|
16
|
+
size: Number(routeState.size) || 10,
|
|
17
|
+
from: Number(routeState.from) || 0
|
|
18
|
+
}
|
|
19
|
+
}; // Map Number values for min and max filters. By default they
|
|
20
|
+
// are parsed as strings, which does not comply to the schema.
|
|
21
|
+
// The 'qs' package is at fault here.
|
|
22
|
+
// @see https://github.com/ljharb/qs/issues/91
|
|
23
|
+
|
|
24
|
+
value.filters = value.filters.map(item => {
|
|
25
|
+
if (item.min) {
|
|
26
|
+
item.min = Number(item.min);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (item.max) {
|
|
30
|
+
item.max = Number(item.max);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (item.boolValue) {
|
|
34
|
+
item.boolValue = !!(item.boolValue.toString() === 'true');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (item.geoBoundingBox) {
|
|
38
|
+
item.geoBoundingBox.topLeft.lat = Number(item.geoBoundingBox.topLeft.lat);
|
|
39
|
+
item.geoBoundingBox.topLeft.lon = Number(item.geoBoundingBox.topLeft.lon);
|
|
40
|
+
item.geoBoundingBox.bottomRight.lat = Number(item.geoBoundingBox.bottomRight.lat);
|
|
41
|
+
item.geoBoundingBox.bottomRight.lon = Number(item.geoBoundingBox.bottomRight.lon);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (item.geoRadius) {
|
|
45
|
+
item.geoRadius.radius = Number(item.geoRadius.radius);
|
|
46
|
+
item.geoRadius.center.lat = Number(item.geoRadius.center.lat);
|
|
47
|
+
item.geoRadius.center.lon = Number(item.geoRadius.center.lon);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return item;
|
|
51
|
+
});
|
|
52
|
+
return value;
|
|
53
|
+
};
|
|
54
|
+
export default withSearchkitRouting(SearchPage, {
|
|
55
|
+
routeToState: routeToStateFn
|
|
56
|
+
});
|
|
@@ -20,15 +20,20 @@ const SearchSelectedFilters = ({
|
|
|
20
20
|
}, filter.label, ": ", filter.value);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
if (!data) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
return /*#__PURE__*/React.createElement("div", {
|
|
24
28
|
className: "SearchSelectedFilters"
|
|
25
29
|
}, /*#__PURE__*/React.createElement(SelectedFilters, {
|
|
26
|
-
data: data
|
|
30
|
+
data: data.results,
|
|
27
31
|
loading: loading,
|
|
28
32
|
customFilterComponents: {
|
|
29
33
|
SelectFacet: ValueFilter,
|
|
30
34
|
ListFacet: ValueFilter,
|
|
31
|
-
ChipFacet: ValueFilter
|
|
35
|
+
ChipFacet: ValueFilter,
|
|
36
|
+
HierarchicalFilterFacet: ValueFilter
|
|
32
37
|
}
|
|
33
38
|
}));
|
|
34
39
|
};
|
|
@@ -5,10 +5,14 @@ const SearchSorting = ({
|
|
|
5
5
|
data,
|
|
6
6
|
loading
|
|
7
7
|
}) => {
|
|
8
|
+
if (!data) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
return /*#__PURE__*/React.createElement("div", {
|
|
9
13
|
className: "SearchSorting"
|
|
10
14
|
}, /*#__PURE__*/React.createElement(SortingSelector, {
|
|
11
|
-
data: data
|
|
15
|
+
data: data.results,
|
|
12
16
|
loading: loading
|
|
13
17
|
}));
|
|
14
18
|
};
|
|
@@ -24,7 +24,9 @@ const defaultChildren = (data, loading) => /*#__PURE__*/React.createElement(Reac
|
|
|
24
24
|
const SearchKit = ({
|
|
25
25
|
query,
|
|
26
26
|
uri,
|
|
27
|
-
children
|
|
27
|
+
children,
|
|
28
|
+
pageSize = 5,
|
|
29
|
+
useRouting = true
|
|
28
30
|
}) => {
|
|
29
31
|
const client = new ApolloClient({
|
|
30
32
|
uri: uri,
|
|
@@ -36,7 +38,8 @@ const SearchKit = ({
|
|
|
36
38
|
}, /*#__PURE__*/React.createElement(SearchkitProvider, {
|
|
37
39
|
client: skClient
|
|
38
40
|
}, /*#__PURE__*/React.createElement(Query, {
|
|
39
|
-
query: query
|
|
41
|
+
query: query,
|
|
42
|
+
useRouting: useRouting
|
|
40
43
|
}, (data, loading) => children ? children(data, loading) : defaultChildren(data, loading))));
|
|
41
44
|
};
|
|
42
45
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { useSearchkit } from '@searchkit/client';
|
|
3
|
+
import classNames from 'classnames';
|
|
2
4
|
import SearchKit from '.';
|
|
3
5
|
import SearchField from './SearchField';
|
|
4
6
|
import SearchPagination from './SearchPagination';
|
|
@@ -24,6 +26,10 @@ const query = `
|
|
|
24
26
|
identifier
|
|
25
27
|
display
|
|
26
28
|
label
|
|
29
|
+
... on HierarchicalValueSelectedFilter {
|
|
30
|
+
level
|
|
31
|
+
value
|
|
32
|
+
}
|
|
27
33
|
... on DateRangeSelectedFilter {
|
|
28
34
|
dateMin
|
|
29
35
|
dateMax
|
|
@@ -68,6 +74,17 @@ const query = `
|
|
|
68
74
|
entries {
|
|
69
75
|
label
|
|
70
76
|
count
|
|
77
|
+
level
|
|
78
|
+
entries {
|
|
79
|
+
label
|
|
80
|
+
count
|
|
81
|
+
level
|
|
82
|
+
entries {
|
|
83
|
+
label
|
|
84
|
+
count
|
|
85
|
+
level
|
|
86
|
+
}
|
|
87
|
+
}
|
|
71
88
|
}
|
|
72
89
|
}
|
|
73
90
|
}
|
|
@@ -102,4 +119,63 @@ export const Default = () => /*#__PURE__*/React.createElement(SearchKit, {
|
|
|
102
119
|
renderHeader: SearchHeader
|
|
103
120
|
}), /*#__PURE__*/React.createElement(SearchPagination, {
|
|
104
121
|
data: data
|
|
105
|
-
})));
|
|
122
|
+
})));
|
|
123
|
+
|
|
124
|
+
const ListFacet = ({
|
|
125
|
+
facet
|
|
126
|
+
}) => {
|
|
127
|
+
const api = useSearchkit();
|
|
128
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
129
|
+
className: "Facet ListFacet",
|
|
130
|
+
key: facet.identifier
|
|
131
|
+
}, /*#__PURE__*/React.createElement("span", null, "CUSTOM ", facet.label), /*#__PURE__*/React.createElement("div", null, facet.entries.map(entry => {
|
|
132
|
+
const isSelected = api.isFilterSelected({
|
|
133
|
+
identifier: facet.identifier,
|
|
134
|
+
value: entry.label
|
|
135
|
+
});
|
|
136
|
+
const classes = classNames({
|
|
137
|
+
selected: isSelected,
|
|
138
|
+
disabled: parseInt(entry.count) === 0
|
|
139
|
+
});
|
|
140
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
141
|
+
className: classes,
|
|
142
|
+
key: entry.label
|
|
143
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
144
|
+
onClick: () => {
|
|
145
|
+
api.toggleFilter({
|
|
146
|
+
identifier: facet.identifier,
|
|
147
|
+
value: entry.label
|
|
148
|
+
});
|
|
149
|
+
api.search();
|
|
150
|
+
},
|
|
151
|
+
disabled: parseInt(entry.count) === 0
|
|
152
|
+
}, "- ", entry.label, " (", entry.count, ")"));
|
|
153
|
+
})));
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
ListFacet.DISPLAY = 'ListFacet';
|
|
157
|
+
export const CustomFacets = () => {
|
|
158
|
+
const customFacets = [ListFacet];
|
|
159
|
+
return /*#__PURE__*/React.createElement(SearchKit, {
|
|
160
|
+
uri: "http://localhost:4000/api/graphql",
|
|
161
|
+
query: query
|
|
162
|
+
}, (data, loading) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SearchField, null), /*#__PURE__*/React.createElement(SearchFacets, {
|
|
163
|
+
data: data,
|
|
164
|
+
loading: loading,
|
|
165
|
+
facets: customFacets
|
|
166
|
+
}), /*#__PURE__*/React.createElement(SearchSelectedFilters, {
|
|
167
|
+
data: data,
|
|
168
|
+
loading: loading
|
|
169
|
+
}), /*#__PURE__*/React.createElement(SearchSorting, {
|
|
170
|
+
data: data,
|
|
171
|
+
loading: loading
|
|
172
|
+
}), /*#__PURE__*/React.createElement(SearchReset, {
|
|
173
|
+
loading: loading
|
|
174
|
+
}), /*#__PURE__*/React.createElement(SearchResults, {
|
|
175
|
+
data: data,
|
|
176
|
+
renderItem: SearchItem,
|
|
177
|
+
renderHeader: SearchHeader
|
|
178
|
+
}), /*#__PURE__*/React.createElement(SearchPagination, {
|
|
179
|
+
data: data
|
|
180
|
+
})));
|
|
181
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@ export { default as Pagination } from './components/Pagination';
|
|
|
12
12
|
export { default as QuickLayout } from './components/Layout/QuickLayout';
|
|
13
13
|
export { default as Lottie } from './components/Lottie';
|
|
14
14
|
export { default as LottieAnimationWithMousePosition } from './components/Lottie/LottieAnimationWithMousePosition';
|
|
15
|
+
export { default as MagicLine } from './components/MagicLine';
|
|
16
|
+
export { default as NavigationScroll } from './components/NavigationScroll';
|
|
15
17
|
export { default as Image } from './components/Image';
|
|
16
18
|
export { default as ImageBackground } from './components/Image/Background';
|
|
17
19
|
export { default as InlineMenu } from './components/InlineMenu';
|