@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.
Files changed (28) hide show
  1. package/dist/components/ApiAutocomplete/index.js +21 -1
  2. package/dist/components/ApiAutocomplete/stories.js +20 -0
  3. package/dist/components/Form/Checkbox/index.js +10 -2
  4. package/dist/components/Form/Checkbox/stories.js +3 -0
  5. package/dist/components/Form/Select/Input/index.js +7 -4
  6. package/dist/components/Form/Select/stories.js +8 -1
  7. package/dist/components/Header/index.js +4 -4
  8. package/dist/components/MagicLine/index.js +70 -0
  9. package/dist/components/MagicLine/stories.js +33 -0
  10. package/dist/components/MagicLine/stories.scss +38 -0
  11. package/dist/components/{Header/AnimationWrapper → NavigationScroll}/index.js +6 -6
  12. package/dist/components/NavigationScroll/stories.js +10 -0
  13. package/dist/components/NavigationScroll/stories.scss +17 -0
  14. package/dist/components/{Header/AnimationWrapper → NavigationScroll}/style.scss +4 -5
  15. package/dist/components/SearchKit/Facets/ChipFacet/index.js +8 -7
  16. package/dist/components/SearchKit/Facets/HierarchicalFilterFacet/index.js +62 -0
  17. package/dist/components/SearchKit/Facets/HierarchicalMenuFacet/index.js +62 -0
  18. package/dist/components/SearchKit/Facets/ListFacet/index.js +9 -2
  19. package/dist/components/SearchKit/Facets/SelectFacet/index.js +4 -3
  20. package/dist/components/SearchKit/Query/index.js +8 -2
  21. package/dist/components/SearchKit/SearchFacets/index.js +9 -2
  22. package/dist/components/SearchKit/SearchPage/index.js +48 -1
  23. package/dist/components/SearchKit/SearchSelectedFilters/index.js +7 -2
  24. package/dist/components/SearchKit/SearchSorting/index.js +5 -1
  25. package/dist/components/SearchKit/index.js +5 -2
  26. package/dist/components/SearchKit/stories.js +77 -1
  27. package/dist/index.js +2 -0
  28. 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
- fetch(url).then(response => {
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);
@@ -22,6 +22,9 @@ export const Checkbox = () => {
22
22
  }
23
23
 
24
24
  return error;
25
+ },
26
+ onChange: e => {
27
+ console.log('change', e);
25
28
  }
26
29
  }));
27
30
  };
@@ -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, null, /*#__PURE__*/React.createElement(FormikSelect, {
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 AnimationWrapper from './AnimationWrapper';
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 onUpdateAnimationWrapper = (isVisible, hasReachedTop, scrolledPastNavHeight) => {
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(AnimationWrapper, {
70
- onUpdate: onUpdateAnimationWrapper,
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 AnimationWrapper = props => {
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('AnimationWrapper', {
75
- 'AnimationWrapper--hasBackground': hasBackground,
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
- AnimationWrapper.propTypes = {
89
+ NavigationScroll.propTypes = {
90
90
  children: PropTypes.element.isRequired,
91
91
  onUpdate: PropTypes.func
92
92
  };
93
- AnimationWrapper.defaultProps = {
93
+ NavigationScroll.defaultProps = {
94
94
  onUpdate: () => {}
95
95
  };
96
- export default AnimationWrapper;
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 '../../../styles/assets/variables';
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
- .AnimationWrapper {
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 background ease-in-out;
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, { useState } from '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: isSelected ? 'selected' : '',
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, { useState } from '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 App({
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 App;
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 = [...components, SelectFacet, ChipFacet, ListFacet].reduce((sum, component) => {
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?.results,
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
- export default withSearchkitRouting(SearchPage);
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?.results,
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?.results,
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uncinc/uncinc-react-kitchen-sink",
3
- "version": "2.1.4",
3
+ "version": "2.1.8",
4
4
  "description": "Default React components that are easily extended.",
5
5
  "author": "uncinc",
6
6
  "license": "MIT",