@dreamcommerce/aurora 2.4.0-19 → 2.4.0-20

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 (19) hide show
  1. package/build/cjs/packages/aurora/src/components/dropdown/components/content.js +22 -22
  2. package/build/cjs/packages/aurora/src/components/dropdown/hooks/use_toggle.js +3 -1
  3. package/build/cjs/packages/aurora/src/components/dropdown/hooks/use_toggle.js.map +1 -1
  4. package/build/cjs/packages/aurora/src/components/dropdown/index.js +2 -2
  5. package/build/cjs/packages/aurora/src/components/dropdown/utilities.js +4 -4
  6. package/build/cjs/packages/aurora/src/components/file_picker/components/selected_file_preview.js +1 -1
  7. package/build/cjs/packages/utilities/build/esm/packages/utilities/src/ui_dom_utils.js +96 -0
  8. package/build/cjs/packages/utilities/build/esm/packages/utilities/src/ui_dom_utils.js.map +1 -0
  9. package/build/esm/packages/aurora/src/components/dropdown/components/content.js +23 -23
  10. package/build/esm/packages/aurora/src/components/dropdown/context/types.d.ts +2 -0
  11. package/build/esm/packages/aurora/src/components/dropdown/hooks/use_toggle.d.ts +1 -1
  12. package/build/esm/packages/aurora/src/components/dropdown/hooks/use_toggle.js +3 -1
  13. package/build/esm/packages/aurora/src/components/dropdown/hooks/use_toggle.js.map +1 -1
  14. package/build/esm/packages/aurora/src/components/dropdown/index.js +2 -2
  15. package/build/esm/packages/aurora/src/components/dropdown/utilities.js +4 -4
  16. package/build/esm/packages/aurora/src/components/file_picker/components/selected_file_preview.js +1 -1
  17. package/build/esm/packages/utilities/build/esm/packages/utilities/src/ui_dom_utils.js +92 -0
  18. package/build/esm/packages/utilities/build/esm/packages/utilities/src/ui_dom_utils.js.map +1 -0
  19. package/package.json +2 -2
@@ -18,6 +18,7 @@ var main_module = require('../../../css/dropdown/main.module.less.js');
18
18
  var utilities = require('../utilities.js');
19
19
  var use_click_outside = require('../../../hooks/use_click_outside.js');
20
20
  var icon_arrow = require('../../../assets/icon_arrow.js');
21
+ var ui_dom_utils = require('../../../../../utilities/build/esm/packages/utilities/src/ui_dom_utils.js');
21
22
 
22
23
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
23
24
 
@@ -32,7 +33,7 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
32
33
  const Content = ({ headerComponent, headerGoBackText, headerGoBackIcon, children, arrowSide = 'left', portalContainer }) => {
33
34
  const [t] = useTranslation.useTranslation();
34
35
  const contentRef = React.useRef(null);
35
- const { wrapperRef, toggleDropdown, isOpen } = index.useDropdownContext();
36
+ const { wrapperRef, toggleDropdown, isOpen, closeDropdown } = index.useDropdownContext();
36
37
  const [styles, setStyles] = React.useState({
37
38
  left: '0px',
38
39
  top: '0px',
@@ -60,36 +61,35 @@ const Content = ({ headerComponent, headerGoBackText, headerGoBackIcon, children
60
61
  toggleDropdown();
61
62
  }
62
63
  });
63
- const getDropdownPositionStyles = (isInModal, modalWrapperRect) => {
64
- const { x, y, height, top } = modalWrapperRect;
65
- const yOffset = 10;
66
- const { xModifier, yModifier } = utilities.getXYModifiersForNestedDropdowns(portalContainer === null || portalContainer === void 0 ? void 0 : portalContainer.current);
67
- const positionTop = top + height + yOffset - yModifier + window.scrollY;
68
- const positionBottom = windowHeightMinusYOffset - y + yOffset;
69
- const positionLeft = x - xModifier;
70
- const zIndex = isInModal ? constants.DROPDOWN_ON_MODAL_Z_INDEX : constants.DROPDOWN_Z_INDEX;
71
- const topPositionValue = !dropdownIsOutsideBottomViewport ? `${positionTop}px` : 'auto';
72
- const bottomPositionValue = dropdownIsOutsideBottomViewport ? `${positionBottom}px` : 'auto';
73
- return screenWidthName === responsive_breakpoints.SCREEN_XS
74
- ? { left: `0px`, top: `0px`, bottom: 'auto', zIndex }
75
- : { left: `${positionLeft}px`, top: topPositionValue, bottom: bottomPositionValue, zIndex };
76
- };
77
64
  React.useEffect(() => {
78
65
  if (wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) {
66
+ const { x, y, height } = wrapperRef.current.getBoundingClientRect();
67
+ const yOffset = 10;
68
+ const { xModifier, yModifier } = utilities.getXYModifiersForNestedDropdowns(portalContainer === null || portalContainer === void 0 ? void 0 : portalContainer.current);
69
+ const positionTop = height + y + yOffset - yModifier;
70
+ const positionBottom = windowHeightMinusYOffset - y + yOffset;
71
+ const positionLeft = x - xModifier;
79
72
  const isInModal = utilities.isChildOfModal(wrapperRef);
80
- setStyles(getDropdownPositionStyles(isInModal, wrapperRef.current.getBoundingClientRect()));
73
+ const zIndex = isInModal ? constants.DROPDOWN_ON_MODAL_Z_INDEX : constants.DROPDOWN_Z_INDEX;
74
+ const topPositionValue = !dropdownIsOutsideBottomViewport ? `${positionTop}px` : 'auto';
75
+ const bottomPositionValue = dropdownIsOutsideBottomViewport ? `${positionBottom}px` : 'auto';
76
+ screenWidthName === responsive_breakpoints.SCREEN_XS
77
+ ? setStyles({ left: `0px`, top: `0px`, bottom: 'auto', zIndex })
78
+ : setStyles({ left: `${positionLeft}px`, top: topPositionValue, bottom: bottomPositionValue, zIndex });
81
79
  }
82
80
  }, [portalContainer, screenWidthName, wrapperRef, isOpen, dropdownIsOutsideBottomViewport]);
83
81
  React.useEffect(() => {
82
+ var _a;
83
+ if (!(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) || !isOpen)
84
+ return;
85
+ const scrollableParent = (_a = ui_dom_utils.UiDomUtils.getFirstScrollableParent(wrapperRef.current)) !== null && _a !== void 0 ? _a : document.body;
84
86
  const handleWindowScroll = () => {
85
- if (wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) {
86
- const isInModal = utilities.isChildOfModal(wrapperRef);
87
- setStyles(getDropdownPositionStyles(isInModal, wrapperRef.current.getBoundingClientRect()));
87
+ if (typeof closeDropdown === 'function') {
88
+ closeDropdown();
88
89
  }
89
90
  };
90
- window.addEventListener('scroll', handleWindowScroll);
91
- return () => window.removeEventListener('scroll', handleWindowScroll);
92
- }, []);
91
+ scrollableParent.addEventListener('scroll', handleWindowScroll, { once: true });
92
+ }, [isOpen]);
93
93
  return reactDom.createPortal(React__default['default'].createElement(reactTransitionGroup.TransitionGroup, { component: null }, isOpen === true ? (React__default['default'].createElement(reactTransitionGroup.CSSTransition, { timeout: 200, classNames: {
94
94
  enter: main_module['default']['dropdown-enter'],
95
95
  enterActive: main_module['default']['dropdown-enter-active'],
@@ -14,12 +14,14 @@ var use_effect_after_mount = require('../../../hooks/use_effect_after_mount.js')
14
14
  function useToggle(defaultIsOpen = false, onToggleCb) {
15
15
  const [isOpen, setIsOpen] = React.useState(defaultIsOpen);
16
16
  const onToggle = React.useCallback(() => setIsOpen((oldIsOpen) => !oldIsOpen), []);
17
+ const open = React.useCallback(() => setIsOpen(true), []);
18
+ const close = React.useCallback(() => setIsOpen(false), []);
17
19
  use_effect_after_mount.useEffectAfterMount(() => {
18
20
  if (typeof onToggleCb === 'function') {
19
21
  onToggleCb(isOpen);
20
22
  }
21
23
  }, [isOpen]);
22
- return [isOpen, onToggle];
24
+ return [isOpen, onToggle, open, close];
23
25
  }
24
26
 
25
27
  exports.useToggle = useToggle;
@@ -1 +1 @@
1
- {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
@@ -44,11 +44,11 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
44
44
  */
45
45
  const Dropdown = ({ defaultIsOpen = false, onToggle, children }) => {
46
46
  const wrapperRef = React.useRef(null);
47
- const [isOpen, toggleDropdown] = use_toggle.useToggle(defaultIsOpen, onToggle);
47
+ const [isOpen, toggleDropdown, openDropdown, closeDropdown] = use_toggle.useToggle(defaultIsOpen, onToggle);
48
48
  /**
49
49
  * context values, they may be used with useContext in any component which is part of Dropdown composition
50
50
  */
51
- const value = React__default['default'].useMemo(() => ({ wrapperRef, isOpen, toggleDropdown }), [isOpen, toggleDropdown]);
51
+ const value = React__default['default'].useMemo(() => ({ wrapperRef, isOpen, toggleDropdown, openDropdown, closeDropdown }), [isOpen, toggleDropdown, openDropdown, closeDropdown]);
52
52
  return (React__default['default'].createElement(index.DropdownContext.Provider, { value: value },
53
53
  React__default['default'].createElement("div", { ref: wrapperRef, className: main_module['default'].dropdown }, children)));
54
54
  };
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  require('react');
6
- var main_module = require('../../css/modal/main.module.less.js');
6
+ var main_module$1 = require('../../css/modal/main.module.less.js');
7
7
  var css_classes = require('./css_classes.js');
8
8
  var fuzzy_search = require('../../utilities/fuzzy_search/fuzzy_search.js');
9
- var main_module$1 = require('../../css/dropdown/main.module.less.js');
9
+ var main_module = require('../../css/dropdown/main.module.less.js');
10
10
 
11
11
  /**
12
12
  * checks if the given option is selected within array of selectedValues array
@@ -47,7 +47,7 @@ const getXYModifiersForNestedDropdowns = (portalContainer) => {
47
47
  let xModifier = 0;
48
48
  let yModifier = 0;
49
49
  if (portalContainer) {
50
- const $parentDropdownContent = portalContainer.closest(`.${main_module$1['default'][css_classes.cssDropdownContent]}`);
50
+ const $parentDropdownContent = portalContainer.closest(`.${main_module['default'][css_classes.cssDropdownContent]}`);
51
51
  if ($parentDropdownContent) {
52
52
  const { x: portalX, y: portalY } = $parentDropdownContent.getBoundingClientRect();
53
53
  xModifier = portalX;
@@ -63,7 +63,7 @@ const isChildOfModal = (ref) => {
63
63
  var _a;
64
64
  let currentParent = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.parentElement;
65
65
  while (currentParent) {
66
- if (currentParent.classList.contains(main_module['default']['modal-window'])) {
66
+ if (currentParent.classList.contains(main_module$1['default']['modal-window'])) {
67
67
  return true;
68
68
  }
69
69
  currentParent = currentParent === null || currentParent === void 0 ? void 0 : currentParent.parentElement;
@@ -4,9 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
6
  var useTranslation = require('../../../../../../external/react-i18next/dist/es/useTranslation.js');
7
+ var file_utils = require('../../../../../utilities/build/esm/packages/utilities/src/file_utils.js');
7
8
  var main_module = require('../../../css/file_picker/main.module.less.js');
8
9
  var css_classes = require('../css_classes.js');
9
- var file_utils = require('../../../../../utilities/build/esm/packages/utilities/src/file_utils.js');
10
10
  var icon_delete = require('../../../assets/icon_delete.js');
11
11
 
12
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ class UiDomUtils {
6
+ static show($el) {
7
+ $el.removeAttribute('hidden');
8
+ }
9
+ static hide($el) {
10
+ $el.setAttribute('hidden', '');
11
+ }
12
+ static empty($el) {
13
+ $el.innerHTML = '';
14
+ }
15
+ static makeUnnavigable($el) {
16
+ $el.setAttribute('tabindex', '-1');
17
+ }
18
+ static makeNavigable($el) {
19
+ $el.setAttribute('tabindex', '0');
20
+ }
21
+ static getFocusableSelector() {
22
+ return ('' +
23
+ // Namespace problems of [xlink:href] explained in https://stackoverflow.com/a/23047888/515124
24
+ // svg a[*|href] does not match in IE9, but since we're filtering
25
+ // through is/focusable we can include all <a> from SVG
26
+ 'svg a,' +
27
+ // may behave as 'svg, svg *,' in chrome as *every* svg element with a focus event listener is focusable
28
+ // navigational elements
29
+ 'a[href],' +
30
+ // validity determined by is/valid-area.js
31
+ 'area[href],' +
32
+ // validity determined by is/disabled.js
33
+ 'input:not([type="hidden"]), select, textarea, button,' +
34
+ // browsing context containers
35
+ 'iframe, object, embed,' +
36
+ // interactive content
37
+ 'keygen,' +
38
+ // validity determined by is/valid-tabindex.js
39
+ '[tabindex]:not([tabindex="-1"]),' +
40
+ // editing hosts
41
+ '[contenteditable]');
42
+ }
43
+ static getFocusableElements($container) {
44
+ return [...$container.querySelectorAll(this.getFocusableSelector())].filter(($el) => !this._isNotFocusable($el));
45
+ }
46
+ static getFocusableElement($container) {
47
+ return [...$container.querySelectorAll(this.getFocusableSelector())].filter(($el) => !this._isNotFocusable($el))[0];
48
+ }
49
+ static _isNotFocusable($el) {
50
+ const displayValue = getComputedStyle($el).getPropertyValue('display');
51
+ return !!($el.hasAttribute('disabled') || $el.getAttribute('aria-hidden') || $el.hasAttribute('hidden') || displayValue === 'none');
52
+ }
53
+ static isFocusable($element) {
54
+ return $element.matches(this.getFocusableSelector());
55
+ }
56
+ static setFocusToFirstFocusableElementInContainer($container) {
57
+ var _a;
58
+ (_a = this.getFocusableElement($container)) === null || _a === void 0 ? void 0 : _a.focus();
59
+ }
60
+ static getDirectChildren($el, selector) {
61
+ return selector ? [...$el.children].filter((child) => child.matches(selector)) : [...$el.children];
62
+ }
63
+ static getAllClosest($el, selector, elements = []) {
64
+ if (!$el)
65
+ return elements;
66
+ const $closestEl = $el.closest(selector);
67
+ if ($closestEl)
68
+ elements.push($closestEl);
69
+ if (!$closestEl)
70
+ return elements;
71
+ return UiDomUtils.getAllClosest($closestEl.parentElement, selector, elements);
72
+ }
73
+ static getFirstParentNonStaticElement($el) {
74
+ let $currentEl = $el.parentElement;
75
+ while ($currentEl) {
76
+ if ($currentEl && window.getComputedStyle($currentEl).position !== 'static') {
77
+ return $currentEl;
78
+ }
79
+ $currentEl = $currentEl.parentElement;
80
+ }
81
+ return null;
82
+ }
83
+ static getFirstScrollableParent($el) {
84
+ let currentParent = $el.parentElement;
85
+ while (currentParent) {
86
+ if (currentParent.scrollHeight > currentParent.clientHeight) {
87
+ return currentParent;
88
+ }
89
+ currentParent = currentParent === null || currentParent === void 0 ? void 0 : currentParent.parentElement;
90
+ }
91
+ return null;
92
+ }
93
+ }
94
+
95
+ exports.UiDomUtils = UiDomUtils;
96
+ //# sourceMappingURL=ui_dom_utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
@@ -11,9 +11,10 @@ import { TransitionGroup, CSSTransition } from 'react-transition-group';
11
11
  import { DROPDOWN_Z_INDEX, DROPDOWN_ON_MODAL_Z_INDEX } from '../constants.js';
12
12
  import { cssDropdownContent, cssDropdownArrowHorizontalDirectionRight, cssDropdownArrowVerticalDirectionBottom, cssDropdownHeader, cssDropdownHeaderContent, cssDropdownHeaderTitle } from '../css_classes.js';
13
13
  import cssClasses from '../../../css/dropdown/main.module.less.js';
14
- import { isChildOfModal, getXYModifiersForNestedDropdowns } from '../utilities.js';
14
+ import { getXYModifiersForNestedDropdowns, isChildOfModal } from '../utilities.js';
15
15
  import { useClickOutside } from '../../../hooks/use_click_outside.js';
16
16
  import IconArrow from '../../../assets/icon_arrow.js';
17
+ import { UiDomUtils } from '../../../../../utilities/build/esm/packages/utilities/src/ui_dom_utils.js';
17
18
 
18
19
  /**
19
20
  * Dropdown.Content component. This togglable part of dropdown.
@@ -24,7 +25,7 @@ import IconArrow from '../../../assets/icon_arrow.js';
24
25
  const Content = ({ headerComponent, headerGoBackText, headerGoBackIcon, children, arrowSide = 'left', portalContainer }) => {
25
26
  const [t] = useTranslation();
26
27
  const contentRef = useRef(null);
27
- const { wrapperRef, toggleDropdown, isOpen } = useDropdownContext();
28
+ const { wrapperRef, toggleDropdown, isOpen, closeDropdown } = useDropdownContext();
28
29
  const [styles, setStyles] = useState({
29
30
  left: '0px',
30
31
  top: '0px',
@@ -52,36 +53,35 @@ const Content = ({ headerComponent, headerGoBackText, headerGoBackIcon, children
52
53
  toggleDropdown();
53
54
  }
54
55
  });
55
- const getDropdownPositionStyles = (isInModal, modalWrapperRect) => {
56
- const { x, y, height, top } = modalWrapperRect;
57
- const yOffset = 10;
58
- const { xModifier, yModifier } = getXYModifiersForNestedDropdowns(portalContainer === null || portalContainer === void 0 ? void 0 : portalContainer.current);
59
- const positionTop = top + height + yOffset - yModifier + window.scrollY;
60
- const positionBottom = windowHeightMinusYOffset - y + yOffset;
61
- const positionLeft = x - xModifier;
62
- const zIndex = isInModal ? DROPDOWN_ON_MODAL_Z_INDEX : DROPDOWN_Z_INDEX;
63
- const topPositionValue = !dropdownIsOutsideBottomViewport ? `${positionTop}px` : 'auto';
64
- const bottomPositionValue = dropdownIsOutsideBottomViewport ? `${positionBottom}px` : 'auto';
65
- return screenWidthName === SCREEN_XS
66
- ? { left: `0px`, top: `0px`, bottom: 'auto', zIndex }
67
- : { left: `${positionLeft}px`, top: topPositionValue, bottom: bottomPositionValue, zIndex };
68
- };
69
56
  useEffect(() => {
70
57
  if (wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) {
58
+ const { x, y, height } = wrapperRef.current.getBoundingClientRect();
59
+ const yOffset = 10;
60
+ const { xModifier, yModifier } = getXYModifiersForNestedDropdowns(portalContainer === null || portalContainer === void 0 ? void 0 : portalContainer.current);
61
+ const positionTop = height + y + yOffset - yModifier;
62
+ const positionBottom = windowHeightMinusYOffset - y + yOffset;
63
+ const positionLeft = x - xModifier;
71
64
  const isInModal = isChildOfModal(wrapperRef);
72
- setStyles(getDropdownPositionStyles(isInModal, wrapperRef.current.getBoundingClientRect()));
65
+ const zIndex = isInModal ? DROPDOWN_ON_MODAL_Z_INDEX : DROPDOWN_Z_INDEX;
66
+ const topPositionValue = !dropdownIsOutsideBottomViewport ? `${positionTop}px` : 'auto';
67
+ const bottomPositionValue = dropdownIsOutsideBottomViewport ? `${positionBottom}px` : 'auto';
68
+ screenWidthName === SCREEN_XS
69
+ ? setStyles({ left: `0px`, top: `0px`, bottom: 'auto', zIndex })
70
+ : setStyles({ left: `${positionLeft}px`, top: topPositionValue, bottom: bottomPositionValue, zIndex });
73
71
  }
74
72
  }, [portalContainer, screenWidthName, wrapperRef, isOpen, dropdownIsOutsideBottomViewport]);
75
73
  useEffect(() => {
74
+ var _a;
75
+ if (!(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) || !isOpen)
76
+ return;
77
+ const scrollableParent = (_a = UiDomUtils.getFirstScrollableParent(wrapperRef.current)) !== null && _a !== void 0 ? _a : document.body;
76
78
  const handleWindowScroll = () => {
77
- if (wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current) {
78
- const isInModal = isChildOfModal(wrapperRef);
79
- setStyles(getDropdownPositionStyles(isInModal, wrapperRef.current.getBoundingClientRect()));
79
+ if (typeof closeDropdown === 'function') {
80
+ closeDropdown();
80
81
  }
81
82
  };
82
- window.addEventListener('scroll', handleWindowScroll);
83
- return () => window.removeEventListener('scroll', handleWindowScroll);
84
- }, []);
83
+ scrollableParent.addEventListener('scroll', handleWindowScroll, { once: true });
84
+ }, [isOpen]);
85
85
  return createPortal(React.createElement(TransitionGroup, { component: null }, isOpen === true ? (React.createElement(CSSTransition, { timeout: 200, classNames: {
86
86
  enter: cssClasses['dropdown-enter'],
87
87
  enterActive: cssClasses['dropdown-enter-active'],
@@ -3,4 +3,6 @@ export interface IDropdownContext {
3
3
  wrapperRef?: React.RefObject<HTMLDivElement>;
4
4
  isOpen?: boolean;
5
5
  toggleDropdown?: () => void;
6
+ openDropdown?: () => void;
7
+ closeDropdown?: () => void;
6
8
  }
@@ -4,4 +4,4 @@
4
4
  * @param onToggleCb callback onToggle
5
5
  * @returns {Array} tuple - open state and and method to change open state
6
6
  */
7
- export declare function useToggle(defaultIsOpen?: boolean, onToggleCb?: (isOpen: boolean) => void): [boolean, () => void];
7
+ export declare function useToggle(defaultIsOpen?: boolean, onToggleCb?: (isOpen: boolean) => void): [boolean, () => void, () => void, () => void];
@@ -10,12 +10,14 @@ import { useEffectAfterMount } from '../../../hooks/use_effect_after_mount.js';
10
10
  function useToggle(defaultIsOpen = false, onToggleCb) {
11
11
  const [isOpen, setIsOpen] = useState(defaultIsOpen);
12
12
  const onToggle = useCallback(() => setIsOpen((oldIsOpen) => !oldIsOpen), []);
13
+ const open = useCallback(() => setIsOpen(true), []);
14
+ const close = useCallback(() => setIsOpen(false), []);
13
15
  useEffectAfterMount(() => {
14
16
  if (typeof onToggleCb === 'function') {
15
17
  onToggleCb(isOpen);
16
18
  }
17
19
  }, [isOpen]);
18
- return [isOpen, onToggle];
20
+ return [isOpen, onToggle, open, close];
19
21
  }
20
22
 
21
23
  export { useToggle };
@@ -1 +1 @@
1
- {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
@@ -36,11 +36,11 @@ import { useToggle } from './hooks/use_toggle.js';
36
36
  */
37
37
  const Dropdown = ({ defaultIsOpen = false, onToggle, children }) => {
38
38
  const wrapperRef = useRef(null);
39
- const [isOpen, toggleDropdown] = useToggle(defaultIsOpen, onToggle);
39
+ const [isOpen, toggleDropdown, openDropdown, closeDropdown] = useToggle(defaultIsOpen, onToggle);
40
40
  /**
41
41
  * context values, they may be used with useContext in any component which is part of Dropdown composition
42
42
  */
43
- const value = React.useMemo(() => ({ wrapperRef, isOpen, toggleDropdown }), [isOpen, toggleDropdown]);
43
+ const value = React.useMemo(() => ({ wrapperRef, isOpen, toggleDropdown, openDropdown, closeDropdown }), [isOpen, toggleDropdown, openDropdown, closeDropdown]);
44
44
  return (React.createElement(DropdownContext.Provider, { value: value },
45
45
  React.createElement("div", { ref: wrapperRef, className: cssClasses.dropdown }, children)));
46
46
  };
@@ -1,8 +1,8 @@
1
1
  import 'react';
2
- import cssClasses from '../../css/modal/main.module.less.js';
2
+ import cssClasses$1 from '../../css/modal/main.module.less.js';
3
3
  import { cssDropdownContent } from './css_classes.js';
4
4
  import { fuzzySearch } from '../../utilities/fuzzy_search/fuzzy_search.js';
5
- import cssClasses$1 from '../../css/dropdown/main.module.less.js';
5
+ import cssClasses from '../../css/dropdown/main.module.less.js';
6
6
 
7
7
  /**
8
8
  * checks if the given option is selected within array of selectedValues array
@@ -43,7 +43,7 @@ const getXYModifiersForNestedDropdowns = (portalContainer) => {
43
43
  let xModifier = 0;
44
44
  let yModifier = 0;
45
45
  if (portalContainer) {
46
- const $parentDropdownContent = portalContainer.closest(`.${cssClasses$1[cssDropdownContent]}`);
46
+ const $parentDropdownContent = portalContainer.closest(`.${cssClasses[cssDropdownContent]}`);
47
47
  if ($parentDropdownContent) {
48
48
  const { x: portalX, y: portalY } = $parentDropdownContent.getBoundingClientRect();
49
49
  xModifier = portalX;
@@ -59,7 +59,7 @@ const isChildOfModal = (ref) => {
59
59
  var _a;
60
60
  let currentParent = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.parentElement;
61
61
  while (currentParent) {
62
- if (currentParent.classList.contains(cssClasses['modal-window'])) {
62
+ if (currentParent.classList.contains(cssClasses$1['modal-window'])) {
63
63
  return true;
64
64
  }
65
65
  currentParent = currentParent === null || currentParent === void 0 ? void 0 : currentParent.parentElement;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { useTranslation } from '../../../../../../external/react-i18next/dist/es/useTranslation.js';
3
+ import { FileUtils } from '../../../../../utilities/build/esm/packages/utilities/src/file_utils.js';
3
4
  import styles from '../../../css/file_picker/main.module.less.js';
4
5
  import CSS_CLASSES from '../css_classes.js';
5
- import { FileUtils } from '../../../../../utilities/build/esm/packages/utilities/src/file_utils.js';
6
6
  import IconDelete from '../../../assets/icon_delete.js';
7
7
 
8
8
  const SelectedFilePreview = ({ file, isPreview, onPreviewError, onFileDelete }) => {
@@ -0,0 +1,92 @@
1
+ class UiDomUtils {
2
+ static show($el) {
3
+ $el.removeAttribute('hidden');
4
+ }
5
+ static hide($el) {
6
+ $el.setAttribute('hidden', '');
7
+ }
8
+ static empty($el) {
9
+ $el.innerHTML = '';
10
+ }
11
+ static makeUnnavigable($el) {
12
+ $el.setAttribute('tabindex', '-1');
13
+ }
14
+ static makeNavigable($el) {
15
+ $el.setAttribute('tabindex', '0');
16
+ }
17
+ static getFocusableSelector() {
18
+ return ('' +
19
+ // Namespace problems of [xlink:href] explained in https://stackoverflow.com/a/23047888/515124
20
+ // svg a[*|href] does not match in IE9, but since we're filtering
21
+ // through is/focusable we can include all <a> from SVG
22
+ 'svg a,' +
23
+ // may behave as 'svg, svg *,' in chrome as *every* svg element with a focus event listener is focusable
24
+ // navigational elements
25
+ 'a[href],' +
26
+ // validity determined by is/valid-area.js
27
+ 'area[href],' +
28
+ // validity determined by is/disabled.js
29
+ 'input:not([type="hidden"]), select, textarea, button,' +
30
+ // browsing context containers
31
+ 'iframe, object, embed,' +
32
+ // interactive content
33
+ 'keygen,' +
34
+ // validity determined by is/valid-tabindex.js
35
+ '[tabindex]:not([tabindex="-1"]),' +
36
+ // editing hosts
37
+ '[contenteditable]');
38
+ }
39
+ static getFocusableElements($container) {
40
+ return [...$container.querySelectorAll(this.getFocusableSelector())].filter(($el) => !this._isNotFocusable($el));
41
+ }
42
+ static getFocusableElement($container) {
43
+ return [...$container.querySelectorAll(this.getFocusableSelector())].filter(($el) => !this._isNotFocusable($el))[0];
44
+ }
45
+ static _isNotFocusable($el) {
46
+ const displayValue = getComputedStyle($el).getPropertyValue('display');
47
+ return !!($el.hasAttribute('disabled') || $el.getAttribute('aria-hidden') || $el.hasAttribute('hidden') || displayValue === 'none');
48
+ }
49
+ static isFocusable($element) {
50
+ return $element.matches(this.getFocusableSelector());
51
+ }
52
+ static setFocusToFirstFocusableElementInContainer($container) {
53
+ var _a;
54
+ (_a = this.getFocusableElement($container)) === null || _a === void 0 ? void 0 : _a.focus();
55
+ }
56
+ static getDirectChildren($el, selector) {
57
+ return selector ? [...$el.children].filter((child) => child.matches(selector)) : [...$el.children];
58
+ }
59
+ static getAllClosest($el, selector, elements = []) {
60
+ if (!$el)
61
+ return elements;
62
+ const $closestEl = $el.closest(selector);
63
+ if ($closestEl)
64
+ elements.push($closestEl);
65
+ if (!$closestEl)
66
+ return elements;
67
+ return UiDomUtils.getAllClosest($closestEl.parentElement, selector, elements);
68
+ }
69
+ static getFirstParentNonStaticElement($el) {
70
+ let $currentEl = $el.parentElement;
71
+ while ($currentEl) {
72
+ if ($currentEl && window.getComputedStyle($currentEl).position !== 'static') {
73
+ return $currentEl;
74
+ }
75
+ $currentEl = $currentEl.parentElement;
76
+ }
77
+ return null;
78
+ }
79
+ static getFirstScrollableParent($el) {
80
+ let currentParent = $el.parentElement;
81
+ while (currentParent) {
82
+ if (currentParent.scrollHeight > currentParent.clientHeight) {
83
+ return currentParent;
84
+ }
85
+ currentParent = currentParent === null || currentParent === void 0 ? void 0 : currentParent.parentElement;
86
+ }
87
+ return null;
88
+ }
89
+ }
90
+
91
+ export { UiDomUtils };
92
+ //# sourceMappingURL=ui_dom_utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@dreamcommerce/aurora",
3
3
  "packageManager": "yarn@3.2.0",
4
4
  "sideEffects": false,
5
- "version": "2.4.0-19",
5
+ "version": "2.4.0-20",
6
6
  "description": "aurora",
7
7
  "author": "k0ssak",
8
8
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "update-visuals": "jest -c .config/jest/jest.config.visual.js --updateSnapshot"
45
45
  },
46
46
  "devDependencies": {
47
- "@dreamcommerce/utilities": "^1.6.0",
47
+ "@dreamcommerce/utilities": "^1.7.0",
48
48
  "@shoper/jest_config": "^0.0.0",
49
49
  "@shoper/tsconfig": "^0.0.0",
50
50
  "@storybook/react": "6.5.7",