@vitus-labs/elements 0.41.0 → 0.44.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.
@@ -112,7 +112,7 @@ const styles$1 = ({ css, theme: t, rootSize }) => css `
112
112
  ${({ $contentType }) => calculateGap({
113
113
  direction: t.parentDirection,
114
114
  type: $contentType,
115
- value: value([t.gap], rootSize),
115
+ value: value(t.gap, rootSize),
116
116
  css,
117
117
  })}
118
118
  `};
@@ -617,8 +617,8 @@ const component$3 = ({ children, blocked, setBlocked, setUnblocked, }) => (React
617
617
  var useOverlay = ({ isOpen = false, openOn = 'click', // click | hover
618
618
  closeOn = 'click', // click | 'clickOnTrigger' | 'clickOutsideContent' | hover | manual
619
619
  type = 'dropdown', // dropdown | tooltip | popover | modal
620
- align = 'bottom', // * main align prop * top | left | bottom | right
621
620
  position = 'fixed', // absolute | fixed | relative | static
621
+ align = 'bottom', // * main align prop * top | left | bottom | right
622
622
  alignX = 'left', // left | center | right
623
623
  alignY = 'bottom', // top | center | bottom
624
624
  offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc = true, disabled, onOpen, onClose, }) => {
@@ -626,9 +626,6 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
626
626
  const ctx = useOverlayContext();
627
627
  const [blocked, handleBlocked] = useState(false);
628
628
  const [active, handleActive] = useState(isOpen);
629
- const [innerAlign, setInnerAlign] = useState(align);
630
- const [innerAlignX, setInnerAlignX] = useState(alignX);
631
- const [innerAlignY, setInnerAlignY] = useState(alignY);
632
629
  const triggerRef = useRef();
633
630
  const contentRef = useRef();
634
631
  const setBlocked = useCallback(() => handleBlocked(true), []);
@@ -639,39 +636,36 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
639
636
  const hideContent = useCallback(() => {
640
637
  handleActive(false);
641
638
  }, []);
642
- useEffect(() => {
643
- if (active) {
644
- if (onOpen)
645
- onOpen();
646
- }
647
- else {
648
- if (onClose)
649
- onClose();
650
- }
651
- }, [active, onOpen, onClose]);
652
639
  useEffect(() => {
653
640
  if (disabled) {
654
641
  hideContent();
655
642
  }
656
643
  }, [disabled]);
644
+ // calculate position on every position change state
645
+ useEffect(() => {
646
+ if (active) {
647
+ // hack-ish way to correctly calculate position for the first time
648
+ // without calling it twice the posittion is somehow wrong
649
+ calculateContentPosition();
650
+ calculateContentPosition();
651
+ }
652
+ }, [active, align, alignX, alignX]);
657
653
  // if an Overlay has an Overlay child, this will prevent closing parent child
658
654
  // + calculate correct position when an Overlay is opened
659
655
  useEffect(() => {
660
656
  if (active) {
657
+ if (onOpen)
658
+ onOpen();
661
659
  if (ctx?.setBlocked)
662
660
  ctx.setBlocked();
663
661
  }
664
662
  else {
663
+ if (onClose)
664
+ onClose();
665
665
  if (ctx?.setUnblocked)
666
666
  ctx.setUnblocked();
667
667
  }
668
- }, [active, ctx]);
669
- // calculate position on every position change state
670
- useEffect(() => {
671
- if (active) {
672
- calculateContentPosition();
673
- }
674
- }, [active, innerAlign, innerAlignX, innerAlignY]);
668
+ }, [active, onOpen, onClose]);
675
669
  // handles calculating correct position of content
676
670
  // on document events (or custom scroll if set)
677
671
  useEffect(() => {
@@ -769,88 +763,105 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
769
763
  }
770
764
  return;
771
765
  }
772
- const triggerDimensions = triggerRef.current.getBoundingClientRect();
773
- const contentDimensions = contentRef.current.getBoundingClientRect();
774
766
  const overlayPosition = {
775
767
  position,
776
768
  };
769
+ const t = triggerRef.current.getBoundingClientRect();
770
+ const c = contentRef.current.getBoundingClientRect();
777
771
  if (['dropdown', 'tooltip', 'popover'].includes(type)) {
772
+ // align is top or bottom
778
773
  if (['top', 'bottom'].includes(align)) {
779
- const positionTop = triggerDimensions.top - offsetY - contentDimensions.height;
780
- const positionBottom = triggerDimensions.bottom + offsetY;
781
- const positionLeft = triggerDimensions.left - offsetX;
782
- const positionRight = triggerDimensions.right + offsetX - contentDimensions.width;
774
+ // axe Y position
775
+ // (assigned as top position)
776
+ const top = t.top - offsetY - c.height;
777
+ const bottom = t.bottom + offsetY;
778
+ // axe X position
779
+ // content position to trigger position
780
+ // (assigned as left position)
781
+ const left = t.left + offsetX;
782
+ const right = t.right - offsetX - c.width;
783
+ // calculate possible position
784
+ const isTop = top >= 0; // represents window.height = 0
785
+ const isBottom = bottom + c.height <= window.innerHeight;
786
+ const isLeft = left + c.width <= window.innerWidth;
787
+ const isRight = right >= 0; // represents window.width = 0
783
788
  if (align === 'top') {
784
- const isTop = positionTop >= 0;
785
- setInnerAlign(isTop ? 'top' : 'bottom');
786
- overlayPosition.top = isTop ? positionTop : positionBottom;
789
+ overlayPosition.top = isTop ? top : bottom;
787
790
  }
788
- else {
789
- const isBottom = positionBottom + contentDimensions.height <= window.innerHeight;
790
- setInnerAlign(isBottom ? 'bottom' : 'top');
791
- overlayPosition.top = isBottom ? positionBottom : positionTop;
791
+ else if (align === 'bottom') {
792
+ overlayPosition.top = isBottom ? bottom : top;
793
+ }
794
+ // left
795
+ if (alignX === 'left') {
796
+ overlayPosition.left = isLeft ? left : right;
792
797
  }
793
- switch (alignX) {
794
- case 'right': {
795
- const isRight = positionRight >= 0;
796
- setInnerAlignX(isRight ? 'right' : 'left');
797
- overlayPosition.left = isRight ? positionRight : positionLeft;
798
- break;
798
+ // center
799
+ else if (alignX === 'center') {
800
+ const center = t.left + (t.right - t.left) / 2 - c.width / 2;
801
+ const isCenteredLeft = center >= 0;
802
+ const isCenteredRight = center + c.width <= window.innerWidth;
803
+ if (isCenteredLeft && isCenteredRight) {
804
+ overlayPosition.left = center;
799
805
  }
800
- case 'center': {
801
- overlayPosition.left =
802
- triggerDimensions.left +
803
- (triggerDimensions.right - triggerDimensions.left) / 2 -
804
- contentDimensions.width / 2;
805
- break;
806
+ else if (isCenteredLeft) {
807
+ overlayPosition.left = left;
806
808
  }
807
- case 'left':
808
- default: {
809
- const isLeft = positionLeft + contentDimensions.width <= window.innerWidth;
810
- setInnerAlignX(isLeft ? 'left' : 'right');
811
- overlayPosition.left = isLeft ? positionLeft : positionRight;
812
- break;
809
+ else if (isCenteredRight) {
810
+ overlayPosition.left = right;
813
811
  }
814
812
  }
813
+ // right
814
+ else if (alignX === 'right') {
815
+ overlayPosition.left = isRight ? right : left;
816
+ }
815
817
  }
818
+ // align is left or right
816
819
  else if (['left', 'right'].includes(align)) {
817
- const positionLeft = triggerDimensions.left - offsetX - contentDimensions.width;
818
- const positionRight = triggerDimensions.right + offsetX;
819
- const positionTop = triggerDimensions.top + offsetY;
820
- const positionBottom = triggerDimensions.bottom - offsetY - contentDimensions.height;
820
+ // axe X position
821
+ // (assigned as left position)
822
+ const left = t.left - offsetX - c.width;
823
+ const right = t.right + offsetX;
824
+ // axe Y position
825
+ // content position to trigger position
826
+ // (assigned as top position)
827
+ const top = t.top + offsetY;
828
+ const bottom = t.bottom - offsetY - c.height;
829
+ const isLeft = left >= 0;
830
+ const isRight = right + c.width <= window.innerWidth;
831
+ const isTop = top + c.height <= window.innerHeight;
832
+ const isBottom = bottom >= 0;
821
833
  if (align === 'left') {
822
- const isLeft = positionLeft >= 0;
823
- setInnerAlign(isLeft ? 'left' : 'right');
824
- overlayPosition.left = isLeft ? positionLeft : positionRight;
834
+ overlayPosition.left = isLeft ? left : right;
825
835
  }
826
- else {
827
- const isRight = positionRight + contentDimensions.width <= window.innerWidth;
828
- setInnerAlign(isRight ? 'right' : 'left');
829
- overlayPosition.left = isRight ? positionRight : positionLeft;
836
+ else if (align === 'right') {
837
+ overlayPosition.left = isRight ? right : left;
838
+ }
839
+ // top
840
+ if (alignY === 'top') {
841
+ overlayPosition.top = isTop ? top : bottom;
830
842
  }
831
- switch (alignY) {
832
- case 'top': {
833
- const isTop = positionTop + contentDimensions.height <= window.innerHeight;
834
- setInnerAlignY(isTop ? 'top' : 'bottom');
835
- overlayPosition.top = isTop ? positionTop : positionBottom;
836
- break;
843
+ // center
844
+ else if (alignY === 'center') {
845
+ const center = t.top + (t.bottom - t.top) / 2 - c.height / 2;
846
+ const isCenteredTop = center >= 0;
847
+ const isCenteredBottom = center + c.height <= window.innerHeight;
848
+ if (isCenteredTop && isCenteredBottom) {
849
+ overlayPosition.top = center;
837
850
  }
838
- case 'center':
839
- overlayPosition.top =
840
- triggerDimensions.top -
841
- offsetY +
842
- (triggerDimensions.bottom - triggerDimensions.top) / 2 -
843
- contentDimensions.height / 2;
844
- break;
845
- case 'bottom':
846
- default: {
847
- const isBottom = positionBottom >= 0;
848
- setInnerAlignY(isBottom ? 'bottom' : 'top');
849
- overlayPosition.top = isBottom ? positionBottom : positionTop;
851
+ else if (isCenteredTop) {
852
+ overlayPosition.top = top;
850
853
  }
854
+ else if (isCenteredBottom) {
855
+ overlayPosition.top = bottom;
856
+ }
857
+ }
858
+ // bottom
859
+ else if (alignY === 'bottom') {
860
+ overlayPosition.top = isBottom ? bottom : top;
851
861
  }
852
862
  }
853
863
  }
864
+ // modal type
854
865
  else if (type === 'modal') {
855
866
  switch (alignX) {
856
867
  case 'right':
@@ -861,8 +872,7 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
861
872
  break;
862
873
  case 'center':
863
874
  default:
864
- overlayPosition.left =
865
- window.innerWidth / 2 - contentDimensions.width / 2;
875
+ overlayPosition.left = window.innerWidth / 2 - c.width / 2;
866
876
  break;
867
877
  }
868
878
  switch (alignY) {
@@ -870,8 +880,7 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
870
880
  overlayPosition.top = offsetY;
871
881
  break;
872
882
  case 'center':
873
- overlayPosition.top =
874
- window.innerHeight / 2 - contentDimensions.height / 2;
883
+ overlayPosition.top = window.innerHeight / 2 - c.height / 2;
875
884
  break;
876
885
  case 'bottom':
877
886
  default:
@@ -879,12 +888,13 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
879
888
  break;
880
889
  }
881
890
  }
891
+ const calc = (param) => value(param, rootSize);
882
892
  // ADD POSITION STYLES TO CONTENT
883
- contentRef.current.style.position = overlayPosition.position;
884
- contentRef.current.style.top = value([overlayPosition.top], rootSize);
885
- contentRef.current.style.bottom = value([overlayPosition.bottom], rootSize);
886
- contentRef.current.style.left = value([overlayPosition.left], rootSize);
887
- contentRef.current.style.right = value([overlayPosition.right], rootSize);
893
+ contentRef.current.style.position = position;
894
+ contentRef.current.style.top = calc(overlayPosition.top);
895
+ contentRef.current.style.bottom = calc(overlayPosition.bottom);
896
+ contentRef.current.style.left = calc(overlayPosition.left);
897
+ contentRef.current.style.right = calc(overlayPosition.right);
888
898
  };
889
899
  const handleVisibilityByEventType = (e) => {
890
900
  if (!active) {
@@ -931,9 +941,9 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
931
941
  triggerRef,
932
942
  contentRef,
933
943
  active,
934
- align: innerAlign,
935
- alignX: innerAlignX,
936
- alignY: innerAlignY,
944
+ align,
945
+ alignX,
946
+ alignY,
937
947
  showContent,
938
948
  hideContent,
939
949
  blocked,