@dhis2-ui/transfer 10.10.2 → 10.12.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.
@@ -11,6 +11,10 @@ Given('the Transfer does not have enough items to fill the source list completel
11
11
  cy.visitStory('Transfer End Of List', 'Partial Source List');
12
12
  cy.wrap('source').as('listType');
13
13
  });
14
+ Given('the Transfer source options list does not fill the list completely', () => {
15
+ cy.visitStory('Transfer End Of List', 'Option Changes For Short List');
16
+ cy.wrap('source').as('listType');
17
+ });
14
18
  Given('the Transfer does not have enough items to fill the picked list completely', () => {
15
19
  cy.visitStory('Transfer End Of List', 'Partial Picked List');
16
20
  cy.wrap('picked').as('listType');
@@ -21,6 +25,12 @@ When('the user scroll to the end of the list', () => {
21
25
  cy.get(`{${listSelector}-endintersectiondetector}`).scrollIntoView();
22
26
  });
23
27
  });
28
+ When('the user adds an item by clicking the button', () => {
29
+ cy.contains('Increment options lists').click();
30
+ });
31
+ Then('the last list item should be fully visible', () => {
32
+ cy.contains('ARI treated with antibiotics (pneumonia) new').should('be.visible');
33
+ });
24
34
  Then('the callback for reaching the end should not be called', () => {
25
35
  cy.all(() => cy.window(), () => cy.get('@listType')).should(_ref => {
26
36
  let [win, listType] = _ref;
@@ -34,4 +44,29 @@ Then('the callback for reaching the end should be called', () => {
34
44
  const callback = listType === 'source' ? win.onEndReached : win.onEndReachedPicked;
35
45
  expect(callback).to.be.calledOnce;
36
46
  });
47
+ });
48
+ When('the user scrolls down to the source list end', () => {
49
+ cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]').find('[data-test="dhis2-uicore-intersectiondetector"]').scrollIntoView();
50
+ });
51
+ Then('the list end indicator of the source list should be visible', () => {
52
+ cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]').find('[data-test="dhis2-uicore-intersectiondetector"]').should('be.visible');
53
+ });
54
+ Then('the list end indicator of the source list should not be visible', () => {
55
+ cy.get('[data-test="dhis2-uicore-transfer-sourceoptions"]').find('[data-test="dhis2-uicore-intersectiondetector"]').should('not.be.visible');
56
+ });
57
+ Then('the callback for reaching the end of the source list should be called {int} times', function (int) {
58
+ cy.window().should(win => {
59
+ expect(win.onEndReached).to.have.callCount(int);
60
+ });
61
+ });
62
+ Then('the selected item is being displayed in the picked list', () => {
63
+ cy.get('[data-test="dhis2-uicore-transfer-pickedoptions"]').contains('Option nr. 9').should('be.visible');
64
+ });
65
+ When('the user selects option nr. {}', function (int) {
66
+ cy.contains(`Option nr. ${int}`).dblclick();
67
+ });
68
+ Then('the callback for reaching the end of the picked list should be called {int} times', function (int) {
69
+ cy.window().should(win => {
70
+ expect(win.onEndReachedPicked).to.have.callCount(int);
71
+ });
37
72
  });
@@ -27,3 +27,38 @@ Feature: The source and picked option lists notify the consumer when the end has
27
27
  | type |
28
28
  | source |
29
29
  | picked |
30
+
31
+ Scenario: The list is short and items are added within the list container
32
+ Given the Transfer source options list does not fill the list completely
33
+ # Initial state: the list has 7 items and the list ends well above the container bottom
34
+ Then the list end indicator of the source list should be visible
35
+ Then the callback for reaching the end of the source list should be called 1 times
36
+ Then the callback for reaching the end of the picked list should be called 1 times
37
+ # Selected item is not in the options array but is present in the `selectedOptionsLookup`
38
+ Then the selected item is being displayed in the picked list
39
+ When the user adds an item by clicking the button
40
+ # The indicator is still just in view
41
+ Then the list end indicator of the source list should be visible
42
+ Then the callback for reaching the end of the source list should be called 2 times
43
+ When the user adds an item by clicking the button
44
+ # This adds val-9, which is a selected item so it gets added to picked options
45
+ # not source options, but the callback is still called
46
+ Then the list end indicator of the source list should be visible
47
+ Then the callback for reaching the end of the source list should be called 3 times
48
+ # The picked list callback does not get called because the picked item was already present
49
+ Then the callback for reaching the end of the picked list should be called 1 times
50
+ When the user adds an item by clicking the button
51
+ # The indicator is still in view but only just
52
+ Then the list end indicator of the source list should be visible
53
+ Then the callback for reaching the end of the source list should be called 4 times
54
+ When the user adds an item by clicking the button
55
+ # The indicator now is out of view, no more calls
56
+ Then the list end indicator of the source list should not be visible
57
+ Then the callback for reaching the end of the source list should be called 4 times
58
+ # But scrolling down does trigger a call
59
+ When the user scrolls down to the source list end
60
+ Then the list end indicator of the source list should be visible
61
+ Then the callback for reaching the end of the source list should be called 5 times
62
+ # And selecting an item triggers a call in the picked list
63
+ When the user selects option nr. 11
64
+ Then the callback for reaching the end of the picked list should be called 2 times
@@ -3,9 +3,10 @@ import { CircularLoader } from '@dhis2-ui/loader';
3
3
  import PropTypes from 'prop-types';
4
4
  import React, { Fragment, useRef } from 'react';
5
5
  import { EndIntersectionDetector } from './end-intersection-detector.js';
6
- import { useResizeCounter } from './use-resize-counter.js';
6
+ import { useOptionsKeyMonitor } from './transfer/use-options-key-monitor.js';
7
7
  export const OptionsContainer = _ref => {
8
8
  let {
9
+ allOptionsKey,
9
10
  dataTest,
10
11
  emptyComponent,
11
12
  onEndReached,
@@ -18,19 +19,24 @@ export const OptionsContainer = _ref => {
18
19
  selectionHandler,
19
20
  toggleHighlightedOption
20
21
  } = _ref;
21
- const optionsRef = useRef(null);
22
- const wrapperRef = useRef(null);
23
- const resizeCounter = useResizeCounter(wrapperRef.current);
22
+ const scrollBoxRef = useRef(null);
23
+ const listRef = useRef(null);
24
+ useOptionsKeyMonitor({
25
+ scrollBoxRef,
26
+ listRef,
27
+ allOptionsKey,
28
+ onEndReached
29
+ });
24
30
  return /*#__PURE__*/React.createElement("div", {
25
31
  className: "jsx-1882699425" + " " + "optionsContainer"
26
32
  }, loading && /*#__PURE__*/React.createElement("div", {
27
33
  className: "jsx-1882699425" + " " + "loading"
28
34
  }, /*#__PURE__*/React.createElement(CircularLoader, null)), /*#__PURE__*/React.createElement("div", {
29
35
  "data-test": dataTest,
30
- ref: optionsRef,
36
+ ref: scrollBoxRef,
31
37
  className: "jsx-1882699425" + " " + "container"
32
38
  }, /*#__PURE__*/React.createElement("div", {
33
- ref: wrapperRef,
39
+ ref: listRef,
34
40
  className: "jsx-1882699425" + " " + "content-container"
35
41
  }, !options.length && emptyComponent, options.map(option => {
36
42
  const highlighted = !!highlightedOptions.find(highlightedSourceOption => highlightedSourceOption === option.value);
@@ -44,14 +50,14 @@ export const OptionsContainer = _ref => {
44
50
  }));
45
51
  }), onEndReached && /*#__PURE__*/React.createElement(EndIntersectionDetector, {
46
52
  dataTest: `${dataTest}-endintersectiondetector`,
47
- key: `key-${resizeCounter}`,
48
- rootRef: optionsRef,
53
+ rootRef: scrollBoxRef,
49
54
  onEndReached: onEndReached
50
55
  }))), /*#__PURE__*/React.createElement(_JSXStyle, {
51
56
  id: "1882699425"
52
57
  }, [".optionsContainer.jsx-1882699425{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;position:relative;overflow:hidden;}", ".container.jsx-1882699425{overflow-y:auto;height:100%;}", ".loading.jsx-1882699425{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;width:100%;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;position:absolute;z-index:2;top:0;inset-inline-start:0;}", ".content-container.jsx-1882699425{z-index:1;position:relative;}", ".loading.jsx-1882699425+.container.jsx-1882699425 .content-container.jsx-1882699425{-webkit-filter:blur(2px);filter:blur(2px);}"]));
53
58
  };
54
59
  OptionsContainer.propTypes = {
60
+ allOptionsKey: PropTypes.string.isRequired,
55
61
  dataTest: PropTypes.string.isRequired,
56
62
  getOptionClickHandlers: PropTypes.func.isRequired,
57
63
  emptyComponent: PropTypes.node,
@@ -10,4 +10,5 @@ export * from './move-highlighted-picked-option-up.js';
10
10
  export * from './remove-all-picked-options.js';
11
11
  export * from './remove-individual-picked-options.js';
12
12
  export * from './use-filter.js';
13
- export * from './use-highlighted-options.js';
13
+ export * from './use-highlighted-options.js';
14
+ export * from './use-options-key-monitor.js';
@@ -0,0 +1,35 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { INTERSECTION_DETECTOR_HEIGHT } from '../end-intersection-detector.js';
3
+ const isEndIntersectionDetectorWithinScrollBox = (scrollBoxRef, listRef) => {
4
+ if (!scrollBoxRef.current || !listRef.current) {
5
+ return false;
6
+ }
7
+ const scrollBoxRect = scrollBoxRef.current.getBoundingClientRect();
8
+ const listRect = listRef.current.getBoundingClientRect();
9
+ return listRect.bottom - scrollBoxRect.bottom < INTERSECTION_DETECTOR_HEIGHT;
10
+ };
11
+ export const useOptionsKeyMonitor = _ref => {
12
+ let {
13
+ scrollBoxRef,
14
+ listRef,
15
+ allOptionsKey,
16
+ onEndReached
17
+ } = _ref;
18
+ /* Store in ref so this works even if a consumer does not pass a stable
19
+ * function reference */
20
+ const onEndReachedRef = useRef(onEndReached);
21
+ const prevAllOptionsKey = useRef(allOptionsKey);
22
+ onEndReachedRef.current = onEndReached;
23
+ useEffect(() => {
24
+ /* When new options are loaded and the list end is (still) in
25
+ * view we need to call onEndReached, because the end of the list
26
+ * has indeed been reached but the interception detector will not pick
27
+ * up on this */
28
+ if (onEndReachedRef.current && prevAllOptionsKey.current !== allOptionsKey && isEndIntersectionDetectorWithinScrollBox(scrollBoxRef, listRef)) {
29
+ onEndReachedRef.current();
30
+ }
31
+ prevAllOptionsKey.current = allOptionsKey;
32
+ /* This effect will only run on mount and when allOptionsKey
33
+ * changes because scrollBoxRef, listRef are stable references */
34
+ }, [scrollBoxRef, listRef, allOptionsKey]);
35
+ };
@@ -1,5 +1,5 @@
1
1
  import PropTypes from 'prop-types';
2
- import React from 'react';
2
+ import React, { useMemo } from 'react';
3
3
  import { Actions } from './actions.js';
4
4
  import { AddAll } from './add-all.js';
5
5
  import { AddIndividual } from './add-individual.js';
@@ -19,6 +19,7 @@ import { addAllSelectableSourceOptions, addIndividualSourceOptions, createDouble
19
19
  import { TransferOption } from './transfer-option.js';
20
20
  const identity = value => value;
21
21
  const defaultSelected = [];
22
+ const defaultSelectedOptionsLookup = {};
22
23
  export const Transfer = _ref => {
23
24
  let {
24
25
  options,
@@ -42,6 +43,7 @@ export const Transfer = _ref => {
42
43
  hideFilterInputPicked,
43
44
  initialSearchTerm = '',
44
45
  initialSearchTermPicked = '',
46
+ selectedOptionsLookup = defaultSelectedOptionsLookup,
45
47
  leftFooter,
46
48
  leftHeader,
47
49
  loadingPicked,
@@ -124,16 +126,15 @@ export const Transfer = _ref => {
124
126
  * Actual picked options:
125
127
  * Extract the selected options. Can't use `options.filter`
126
128
  * because we need to keep the order of `selected`
129
+ * Note: Only map if selected is an array
127
130
  */
128
- let pickedOptions = [];
129
-
130
- // Only map if selected is an array
131
- if (Array.isArray(selected)) {
132
- pickedOptions = actualFilterPickedCallback(selected.map(value => options.find(option => value === option.value))
133
- // filter -> in case a selected value has been provided
134
- // that does not exist as option
135
- .filter(identity), actualFilterPicked);
136
- }
131
+ const pickedOptions = useMemo(() => Array.isArray(selected) ? actualFilterPickedCallback(selected.map(value => {
132
+ var _selectedOptionsLooku;
133
+ return (_selectedOptionsLooku = selectedOptionsLookup[value]) !== null && _selectedOptionsLooku !== void 0 ? _selectedOptionsLooku : options.find(option => value === option.value);
134
+ })
135
+ // filter -> in case a selected value has been provided
136
+ // that does not exist as option
137
+ .filter(identity), actualFilterPicked) : [], [selected, options, actualFilterPicked, actualFilterPickedCallback, selectedOptionsLookup]);
137
138
 
138
139
  /*
139
140
  * Source options highlighting:
@@ -176,6 +177,18 @@ export const Transfer = _ref => {
176
177
  const isAddIndividualDisabled = disabled || !highlightedSourceOptions.length;
177
178
  const isRemoveAllDisabled = disabled || !selected.length;
178
179
  const isRemoveIndividualDisabled = disabled || !highlightedPickedOptions.length;
180
+ const allOptionsKey = useMemo(() => options.map(_ref4 => {
181
+ let {
182
+ value
183
+ } = _ref4;
184
+ return value;
185
+ }).join('|'), [options]);
186
+ const pickedOptionsKey = useMemo(() => pickedOptions.map(_ref5 => {
187
+ let {
188
+ value
189
+ } = _ref5;
190
+ return value;
191
+ }).join('|'), [pickedOptions]);
179
192
  return /*#__PURE__*/React.createElement(Container, {
180
193
  dataTest: dataTest,
181
194
  className: className,
@@ -190,13 +203,14 @@ export const Transfer = _ref => {
190
203
  placeholder: filterPlaceholder,
191
204
  dataTest: `${dataTest}-filter`,
192
205
  filter: actualFilter,
193
- onChange: onFilterChange ? onFilterChange : _ref4 => {
206
+ onChange: onFilterChange ? onFilterChange : _ref6 => {
194
207
  let {
195
208
  value
196
- } = _ref4;
209
+ } = _ref6;
197
210
  return setInternalFilter(value);
198
211
  }
199
212
  })), /*#__PURE__*/React.createElement(OptionsContainer, {
213
+ allOptionsKey: allOptionsKey,
200
214
  dataTest: `${dataTest}-sourceoptions`,
201
215
  emptyComponent: sourceEmptyPlaceholder,
202
216
  getOptionClickHandlers: getOptionClickHandlers,
@@ -264,14 +278,15 @@ export const Transfer = _ref => {
264
278
  placeholder: filterPlaceholderPicked,
265
279
  dataTest: `${dataTest}-filter`,
266
280
  filter: actualFilterPicked,
267
- onChange: onFilterChangePicked ? onFilterChangePicked : _ref5 => {
281
+ onChange: onFilterChangePicked ? onFilterChangePicked : _ref7 => {
268
282
  let {
269
283
  value
270
- } = _ref5;
284
+ } = _ref7;
271
285
  return setInternalFilterPicked(value);
272
286
  }
273
287
  })), /*#__PURE__*/React.createElement(OptionsContainer, {
274
288
  selected: true,
289
+ allOptionsKey: pickedOptionsKey,
275
290
  dataTest: `${dataTest}-pickedoptions`,
276
291
  emptyComponent: selectedEmptyComponent,
277
292
  getOptionClickHandlers: getOptionClickHandlers,
@@ -350,6 +365,16 @@ Transfer.propTypes = {
350
365
  searchTermPicked: PropTypes.string,
351
366
  selected: PropTypes.arrayOf(PropTypes.string),
352
367
  selectedEmptyComponent: PropTypes.node,
368
+ /**
369
+ * To be used in scenarios where selected options may not be present
370
+ * in the options array. Like when having options that lazy load or can
371
+ * be filtered async.
372
+ */
373
+ selectedOptionsLookup: PropTypes.objectOf(PropTypes.shape({
374
+ label: PropTypes.string.isRequired,
375
+ value: PropTypes.string.isRequired,
376
+ disabled: PropTypes.bool
377
+ })),
353
378
  selectedWidth: PropTypes.string,
354
379
  sourceEmptyPlaceholder: PropTypes.node,
355
380
  onEndReached: PropTypes.func,
@@ -2,7 +2,7 @@ function _extends() { return _extends = Object.assign ? Object.assign.bind() : f
2
2
  import { SingleSelectField, SingleSelectOption } from '@dhis2-ui/select';
3
3
  import { Tab, TabBar } from '@dhis2-ui/tab';
4
4
  import PropTypes from 'prop-types';
5
- import React, { useEffect, useState } from 'react';
5
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
6
6
  import { TransferOption } from './transfer-option.js';
7
7
  import { Transfer } from './transfer.js';
8
8
  const subtitle = 'Allows users to select options from a list';
@@ -444,6 +444,8 @@ const pageSize = 5;
444
444
  * To keep the code as small as possible, handling selecting items is not
445
445
  included
446
446
  */
447
+ const preSelectedOptions = optionsPool.slice(optionsPool.length - 4);
448
+ const waitMs = async ms => new Promise(resolve => setTimeout(resolve, ms));
447
449
  export const InfiniteLoading = args => {
448
450
  useEffect(() => {
449
451
  console.clear();
@@ -451,59 +453,45 @@ export const InfiniteLoading = args => {
451
453
 
452
454
  // state for whether the next page's options are being loaded
453
455
  const [loading, setLoading] = useState(false);
454
- // captures the current page
455
- const [page, setPage] = useState(0);
456
- // all options (incl. available AND selected options)
456
+ // prevent fetches after list is complete
457
+ const [isOptionsListComplete, setIsOptionsListComplete] = useState(false);
457
458
  const [options, setOptions] = useState([]);
458
459
  // selected options
459
460
  const [selected] = useState(
460
- // second page is already selected
461
- optionsPool.slice(pageSize, pageSize * 2).map(_ref13 => {
461
+ // Last 4 options preselected
462
+ preSelectedOptions.map(_ref13 => {
462
463
  let {
463
464
  value
464
465
  } = _ref13;
465
466
  return value;
466
467
  }));
467
- const onEndReached = () => {
468
- // do nothing when loading already
469
- if (loading) {
470
- return;
471
- }
472
- setPage(page + 1);
473
- };
474
-
475
- // fake fetch request
476
- const fetchOptions = nextPage => new Promise(resolve => setTimeout(() => {
477
- const nextOptions = optionsPool.slice(options.length, nextPage * pageSize);
478
- resolve(nextOptions);
479
- }, 2000));
480
- const loadNextOptions = async () => {
468
+ const selectedOptionsLookup = useMemo(() => preSelectedOptions.reduce((lookup, option) => {
469
+ lookup[option.value] = option;
470
+ return lookup;
471
+ }, {}), []);
472
+ const loadMoreOptions = useCallback(async () => {
481
473
  setLoading(true);
482
- const nextOptions = await fetchOptions(page);
483
- setOptions([...options, ...nextOptions]);
484
- setLoading(false);
485
- const allAlreadySelected = nextOptions.length !== 0 && nextOptions.every(nextOption => {
486
- const {
487
- value
488
- } = nextOption;
489
- return selected.includes(value);
490
- });
491
- if (allAlreadySelected) {
492
- onEndReached();
474
+ await waitMs(2000);
475
+ const newOptions = optionsPool.slice(options.length, Math.min(options.length + pageSize, optionsPool.length));
476
+ const combinedOptions = [...options, ...newOptions];
477
+ setOptions(combinedOptions);
478
+ if (combinedOptions.length === optionsPool.length) {
479
+ setIsOptionsListComplete(true);
493
480
  }
494
- };
495
- useEffect(() => {
496
- // prevent initial call
497
- if (page > 0) {
498
- loadNextOptions();
481
+ setLoading(false);
482
+ }, [options]);
483
+ const onEndReached = useCallback(() => {
484
+ if (!isOptionsListComplete) {
485
+ loadMoreOptions();
499
486
  }
500
- }, [page]);
487
+ }, [loadMoreOptions, isOptionsListComplete]);
501
488
  return /*#__PURE__*/React.createElement(Transfer, _extends({}, args, {
502
489
  loading: loading,
503
490
  options: options,
504
491
  selected: selected,
505
492
  onChange: () => null /* noop */,
506
- onEndReached: onEndReached
493
+ onEndReached: onEndReached,
494
+ selectedOptionsLookup: selectedOptionsLookup
507
495
  }));
508
496
  };
509
497
  export const LoadingSource = StatefulTemplate.bind({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/transfer",
3
- "version": "10.10.2",
3
+ "version": "10.12.0",
4
4
  "description": "UI Transfer",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,12 +33,12 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@dhis2/prop-types": "^3.1.2",
36
- "@dhis2-ui/button": "10.10.2",
37
- "@dhis2-ui/field": "10.10.2",
38
- "@dhis2-ui/input": "10.10.2",
39
- "@dhis2-ui/intersection-detector": "10.10.2",
40
- "@dhis2-ui/loader": "10.10.2",
41
- "@dhis2/ui-constants": "10.10.2",
36
+ "@dhis2-ui/button": "10.12.0",
37
+ "@dhis2-ui/field": "10.12.0",
38
+ "@dhis2-ui/input": "10.12.0",
39
+ "@dhis2-ui/intersection-detector": "10.12.0",
40
+ "@dhis2-ui/loader": "10.12.0",
41
+ "@dhis2/ui-constants": "10.12.0",
42
42
  "classnames": "^2.3.1",
43
43
  "prop-types": "^15.7.2"
44
44
  },
package/types/index.d.ts CHANGED
@@ -44,6 +44,12 @@ export interface TransferProps {
44
44
  searchTermPicked?: string
45
45
  selected?: string[]
46
46
  selectedEmptyComponent?: React.ReactNode
47
+ /**
48
+ * To be used in scenarios where selected options may not be present
49
+ * in the options array. Like when having options that lazy load or can
50
+ * be filtered async.
51
+ */
52
+ selectedOptionsLookup?: Record<string, TransferOption>
47
53
  selectedWidth?: string
48
54
  sourceEmptyPlaceholder?: React.ReactNode
49
55
  onEndReached?: () => void
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.PickedOptions = void 0;
7
- var _style = _interopRequireDefault(require("styled-jsx/style"));
8
- var _uiConstants = require("@dhis2/ui-constants");
9
- var _propTypes = _interopRequireDefault(require("prop-types"));
10
- var _react = _interopRequireDefault(require("react"));
11
- var _endIntersectionDetector = require("./end-intersection-detector.js");
12
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
- const PickedOptions = _ref => {
14
- let {
15
- children,
16
- dataTest,
17
- selectedEmptyComponent,
18
- pickedOptionsRef,
19
- onPickedEndReached
20
- } = _ref;
21
- return /*#__PURE__*/_react.default.createElement("div", {
22
- "data-test": dataTest,
23
- ref: pickedOptionsRef,
24
- className: _style.default.dynamic([["392419471", [_uiConstants.spacers.dp4]]]) + " " + "container"
25
- }, /*#__PURE__*/_react.default.createElement("div", {
26
- className: _style.default.dynamic([["392419471", [_uiConstants.spacers.dp4]]]) + " " + "content-container"
27
- }, !_react.default.Children.count(children) && selectedEmptyComponent, children, onPickedEndReached && /*#__PURE__*/_react.default.createElement(_endIntersectionDetector.EndIntersectionDetector, {
28
- rootRef: pickedOptionsRef,
29
- onEndReached: onPickedEndReached
30
- })), /*#__PURE__*/_react.default.createElement(_style.default, {
31
- id: "392419471",
32
- dynamic: [_uiConstants.spacers.dp4]
33
- }, [`.container.__jsx-style-dynamic-selector{padding:${_uiConstants.spacers.dp4} 0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-y:auto;}`, ".content-container.__jsx-style-dynamic-selector{position:relative;}"]));
34
- };
35
- exports.PickedOptions = PickedOptions;
36
- PickedOptions.propTypes = {
37
- children: _propTypes.default.node.isRequired,
38
- dataTest: _propTypes.default.string.isRequired,
39
- pickedOptionsRef: _propTypes.default.shape({
40
- current: _propTypes.default.instanceOf(HTMLElement)
41
- }),
42
- selectedEmptyComponent: _propTypes.default.node,
43
- onPickedEndReached: _propTypes.default.func
44
- };
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.SourceOptions = void 0;
7
- var _style = _interopRequireDefault(require("styled-jsx/style"));
8
- var _uiConstants = require("@dhis2/ui-constants");
9
- var _propTypes = _interopRequireDefault(require("prop-types"));
10
- var _react = _interopRequireDefault(require("react"));
11
- var _endIntersectionDetector = require("./end-intersection-detector.js");
12
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
- const SourceOptions = _ref => {
14
- let {
15
- children,
16
- dataTest,
17
- sourceEmptyPlaceholder,
18
- sourceOptionsRef,
19
- onSourceEndReached
20
- } = _ref;
21
- return /*#__PURE__*/_react.default.createElement("div", {
22
- "data-test": dataTest,
23
- ref: sourceOptionsRef,
24
- className: _style.default.dynamic([["392419471", [_uiConstants.spacers.dp4]]]) + " " + "container"
25
- }, /*#__PURE__*/_react.default.createElement("div", {
26
- className: _style.default.dynamic([["392419471", [_uiConstants.spacers.dp4]]]) + " " + "content-container"
27
- }, children, !_react.default.Children.count(children) && sourceEmptyPlaceholder, onSourceEndReached && /*#__PURE__*/_react.default.createElement(_endIntersectionDetector.EndIntersectionDetector, {
28
- rootRef: sourceOptionsRef,
29
- onEndReached: onSourceEndReached
30
- })), /*#__PURE__*/_react.default.createElement(_style.default, {
31
- id: "392419471",
32
- dynamic: [_uiConstants.spacers.dp4]
33
- }, [`.container.__jsx-style-dynamic-selector{padding:${_uiConstants.spacers.dp4} 0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-y:auto;}`, ".content-container.__jsx-style-dynamic-selector{position:relative;}"]));
34
- };
35
- exports.SourceOptions = SourceOptions;
36
- SourceOptions.propTypes = {
37
- dataTest: _propTypes.default.string.isRequired,
38
- children: _propTypes.default.node,
39
- sourceEmptyPlaceholder: _propTypes.default.node,
40
- sourceOptionsRef: _propTypes.default.shape({
41
- current: _propTypes.default.instanceOf(HTMLElement)
42
- }),
43
- onSourceEndReached: _propTypes.default.func
44
- };
@@ -1,36 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useResizeCounter = void 0;
7
- var _react = require("react");
8
- /*
9
- * The initial call is irrelevant as there has been
10
- * no resize yet that we want to react to
11
- * So we start with -1 with will returned as 0 by this hook
12
- *
13
- * @param {Element} element
14
- * @returns {number}
15
- */
16
- const useResizeCounter = element => {
17
- const [counter, setCounter] = (0, _react.useState)(-1);
18
- (0, _react.useEffect)(() => {
19
- // using an internal counter as using the one from `useState`
20
- // would cause an infinite loop as this `useEffect` would
21
- // both depend on that value as well as change it every time
22
- // it's executed as the callback passed to `ResizeObserver`
23
- // will be executed on construction
24
- let internalCounter = counter;
25
- if (element) {
26
- const observer = new ResizeObserver(() => {
27
- ++internalCounter;
28
- setCounter(internalCounter);
29
- });
30
- observer.observe(element);
31
- return () => observer.disconnect();
32
- }
33
- }, [element, setCounter]);
34
- return counter < 1 ? 0 : counter;
35
- };
36
- exports.useResizeCounter = useResizeCounter;
@@ -1,36 +0,0 @@
1
- import _JSXStyle from "styled-jsx/style";
2
- import { spacers } from '@dhis2/ui-constants';
3
- import PropTypes from 'prop-types';
4
- import React from 'react';
5
- import { EndIntersectionDetector } from './end-intersection-detector.js';
6
- export const PickedOptions = _ref => {
7
- let {
8
- children,
9
- dataTest,
10
- selectedEmptyComponent,
11
- pickedOptionsRef,
12
- onPickedEndReached
13
- } = _ref;
14
- return /*#__PURE__*/React.createElement("div", {
15
- "data-test": dataTest,
16
- ref: pickedOptionsRef,
17
- className: _JSXStyle.dynamic([["392419471", [spacers.dp4]]]) + " " + "container"
18
- }, /*#__PURE__*/React.createElement("div", {
19
- className: _JSXStyle.dynamic([["392419471", [spacers.dp4]]]) + " " + "content-container"
20
- }, !React.Children.count(children) && selectedEmptyComponent, children, onPickedEndReached && /*#__PURE__*/React.createElement(EndIntersectionDetector, {
21
- rootRef: pickedOptionsRef,
22
- onEndReached: onPickedEndReached
23
- })), /*#__PURE__*/React.createElement(_JSXStyle, {
24
- id: "392419471",
25
- dynamic: [spacers.dp4]
26
- }, [`.container.__jsx-style-dynamic-selector{padding:${spacers.dp4} 0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-y:auto;}`, ".content-container.__jsx-style-dynamic-selector{position:relative;}"]));
27
- };
28
- PickedOptions.propTypes = {
29
- children: PropTypes.node.isRequired,
30
- dataTest: PropTypes.string.isRequired,
31
- pickedOptionsRef: PropTypes.shape({
32
- current: PropTypes.instanceOf(HTMLElement)
33
- }),
34
- selectedEmptyComponent: PropTypes.node,
35
- onPickedEndReached: PropTypes.func
36
- };
@@ -1,36 +0,0 @@
1
- import _JSXStyle from "styled-jsx/style";
2
- import { spacers } from '@dhis2/ui-constants';
3
- import PropTypes from 'prop-types';
4
- import React from 'react';
5
- import { EndIntersectionDetector } from './end-intersection-detector.js';
6
- export const SourceOptions = _ref => {
7
- let {
8
- children,
9
- dataTest,
10
- sourceEmptyPlaceholder,
11
- sourceOptionsRef,
12
- onSourceEndReached
13
- } = _ref;
14
- return /*#__PURE__*/React.createElement("div", {
15
- "data-test": dataTest,
16
- ref: sourceOptionsRef,
17
- className: _JSXStyle.dynamic([["392419471", [spacers.dp4]]]) + " " + "container"
18
- }, /*#__PURE__*/React.createElement("div", {
19
- className: _JSXStyle.dynamic([["392419471", [spacers.dp4]]]) + " " + "content-container"
20
- }, children, !React.Children.count(children) && sourceEmptyPlaceholder, onSourceEndReached && /*#__PURE__*/React.createElement(EndIntersectionDetector, {
21
- rootRef: sourceOptionsRef,
22
- onEndReached: onSourceEndReached
23
- })), /*#__PURE__*/React.createElement(_JSXStyle, {
24
- id: "392419471",
25
- dynamic: [spacers.dp4]
26
- }, [`.container.__jsx-style-dynamic-selector{padding:${spacers.dp4} 0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-y:auto;}`, ".content-container.__jsx-style-dynamic-selector{position:relative;}"]));
27
- };
28
- SourceOptions.propTypes = {
29
- dataTest: PropTypes.string.isRequired,
30
- children: PropTypes.node,
31
- sourceEmptyPlaceholder: PropTypes.node,
32
- sourceOptionsRef: PropTypes.shape({
33
- current: PropTypes.instanceOf(HTMLElement)
34
- }),
35
- onSourceEndReached: PropTypes.func
36
- };