@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.
@@ -152,7 +152,7 @@ const styles$1 = ({ css, theme: t, rootSize }) => css `
152
152
  ${({ $contentType }) => calculateGap({
153
153
  direction: t.parentDirection,
154
154
  type: $contentType,
155
- value: value([t.gap], rootSize),
155
+ value: value(t.gap, rootSize),
156
156
  css,
157
157
  })}
158
158
  `};
@@ -713,8 +713,8 @@ const component$3 = ({ children, blocked, setBlocked, setUnblocked, }) => (React
713
713
  var useOverlay = ({ isOpen = false, openOn = 'click', // click | hover
714
714
  closeOn = 'click', // click | 'clickOnTrigger' | 'clickOutsideContent' | hover | manual
715
715
  type = 'dropdown', // dropdown | tooltip | popover | modal
716
- align = 'bottom', // * main align prop * top | left | bottom | right
717
716
  position = 'fixed', // absolute | fixed | relative | static
717
+ align = 'bottom', // * main align prop * top | left | bottom | right
718
718
  alignX = 'left', // left | center | right
719
719
  alignY = 'bottom', // top | center | bottom
720
720
  offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc = true, disabled, onOpen, onClose, }) => {
@@ -722,9 +722,6 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
722
722
  const ctx = useOverlayContext();
723
723
  const [blocked, handleBlocked] = useState(false);
724
724
  const [active, handleActive] = useState(isOpen);
725
- const [innerAlign, setInnerAlign] = useState(align);
726
- const [innerAlignX, setInnerAlignX] = useState(alignX);
727
- const [innerAlignY, setInnerAlignY] = useState(alignY);
728
725
  const triggerRef = useRef();
729
726
  const contentRef = useRef();
730
727
  const setBlocked = useCallback(() => handleBlocked(true), []);
@@ -735,39 +732,36 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
735
732
  const hideContent = useCallback(() => {
736
733
  handleActive(false);
737
734
  }, []);
738
- useEffect(() => {
739
- if (active) {
740
- if (onOpen)
741
- onOpen();
742
- }
743
- else {
744
- if (onClose)
745
- onClose();
746
- }
747
- }, [active, onOpen, onClose]);
748
735
  useEffect(() => {
749
736
  if (disabled) {
750
737
  hideContent();
751
738
  }
752
739
  }, [disabled]);
740
+ // calculate position on every position change state
741
+ useEffect(() => {
742
+ if (active) {
743
+ // hack-ish way to correctly calculate position for the first time
744
+ // without calling it twice the posittion is somehow wrong
745
+ calculateContentPosition();
746
+ calculateContentPosition();
747
+ }
748
+ }, [active, align, alignX, alignX]);
753
749
  // if an Overlay has an Overlay child, this will prevent closing parent child
754
750
  // + calculate correct position when an Overlay is opened
755
751
  useEffect(() => {
756
752
  if (active) {
753
+ if (onOpen)
754
+ onOpen();
757
755
  if (ctx?.setBlocked)
758
756
  ctx.setBlocked();
759
757
  }
760
758
  else {
759
+ if (onClose)
760
+ onClose();
761
761
  if (ctx?.setUnblocked)
762
762
  ctx.setUnblocked();
763
763
  }
764
- }, [active, ctx]);
765
- // calculate position on every position change state
766
- useEffect(() => {
767
- if (active) {
768
- calculateContentPosition();
769
- }
770
- }, [active, innerAlign, innerAlignX, innerAlignY]);
764
+ }, [active, onOpen, onClose]);
771
765
  // handles calculating correct position of content
772
766
  // on document events (or custom scroll if set)
773
767
  useEffect(() => {
@@ -865,88 +859,105 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
865
859
  }
866
860
  return;
867
861
  }
868
- const triggerDimensions = triggerRef.current.getBoundingClientRect();
869
- const contentDimensions = contentRef.current.getBoundingClientRect();
870
862
  const overlayPosition = {
871
863
  position,
872
864
  };
865
+ const t = triggerRef.current.getBoundingClientRect();
866
+ const c = contentRef.current.getBoundingClientRect();
873
867
  if (['dropdown', 'tooltip', 'popover'].includes(type)) {
868
+ // align is top or bottom
874
869
  if (['top', 'bottom'].includes(align)) {
875
- const positionTop = triggerDimensions.top - offsetY - contentDimensions.height;
876
- const positionBottom = triggerDimensions.bottom + offsetY;
877
- const positionLeft = triggerDimensions.left - offsetX;
878
- const positionRight = triggerDimensions.right + offsetX - contentDimensions.width;
870
+ // axe Y position
871
+ // (assigned as top position)
872
+ const top = t.top - offsetY - c.height;
873
+ const bottom = t.bottom + offsetY;
874
+ // axe X position
875
+ // content position to trigger position
876
+ // (assigned as left position)
877
+ const left = t.left + offsetX;
878
+ const right = t.right - offsetX - c.width;
879
+ // calculate possible position
880
+ const isTop = top >= 0; // represents window.height = 0
881
+ const isBottom = bottom + c.height <= window.innerHeight;
882
+ const isLeft = left + c.width <= window.innerWidth;
883
+ const isRight = right >= 0; // represents window.width = 0
879
884
  if (align === 'top') {
880
- const isTop = positionTop >= 0;
881
- setInnerAlign(isTop ? 'top' : 'bottom');
882
- overlayPosition.top = isTop ? positionTop : positionBottom;
885
+ overlayPosition.top = isTop ? top : bottom;
883
886
  }
884
- else {
885
- const isBottom = positionBottom + contentDimensions.height <= window.innerHeight;
886
- setInnerAlign(isBottom ? 'bottom' : 'top');
887
- overlayPosition.top = isBottom ? positionBottom : positionTop;
887
+ else if (align === 'bottom') {
888
+ overlayPosition.top = isBottom ? bottom : top;
889
+ }
890
+ // left
891
+ if (alignX === 'left') {
892
+ overlayPosition.left = isLeft ? left : right;
888
893
  }
889
- switch (alignX) {
890
- case 'right': {
891
- const isRight = positionRight >= 0;
892
- setInnerAlignX(isRight ? 'right' : 'left');
893
- overlayPosition.left = isRight ? positionRight : positionLeft;
894
- break;
894
+ // center
895
+ else if (alignX === 'center') {
896
+ const center = t.left + (t.right - t.left) / 2 - c.width / 2;
897
+ const isCenteredLeft = center >= 0;
898
+ const isCenteredRight = center + c.width <= window.innerWidth;
899
+ if (isCenteredLeft && isCenteredRight) {
900
+ overlayPosition.left = center;
895
901
  }
896
- case 'center': {
897
- overlayPosition.left =
898
- triggerDimensions.left +
899
- (triggerDimensions.right - triggerDimensions.left) / 2 -
900
- contentDimensions.width / 2;
901
- break;
902
+ else if (isCenteredLeft) {
903
+ overlayPosition.left = left;
902
904
  }
903
- case 'left':
904
- default: {
905
- const isLeft = positionLeft + contentDimensions.width <= window.innerWidth;
906
- setInnerAlignX(isLeft ? 'left' : 'right');
907
- overlayPosition.left = isLeft ? positionLeft : positionRight;
908
- break;
905
+ else if (isCenteredRight) {
906
+ overlayPosition.left = right;
909
907
  }
910
908
  }
909
+ // right
910
+ else if (alignX === 'right') {
911
+ overlayPosition.left = isRight ? right : left;
912
+ }
911
913
  }
914
+ // align is left or right
912
915
  else if (['left', 'right'].includes(align)) {
913
- const positionLeft = triggerDimensions.left - offsetX - contentDimensions.width;
914
- const positionRight = triggerDimensions.right + offsetX;
915
- const positionTop = triggerDimensions.top + offsetY;
916
- const positionBottom = triggerDimensions.bottom - offsetY - contentDimensions.height;
916
+ // axe X position
917
+ // (assigned as left position)
918
+ const left = t.left - offsetX - c.width;
919
+ const right = t.right + offsetX;
920
+ // axe Y position
921
+ // content position to trigger position
922
+ // (assigned as top position)
923
+ const top = t.top + offsetY;
924
+ const bottom = t.bottom - offsetY - c.height;
925
+ const isLeft = left >= 0;
926
+ const isRight = right + c.width <= window.innerWidth;
927
+ const isTop = top + c.height <= window.innerHeight;
928
+ const isBottom = bottom >= 0;
917
929
  if (align === 'left') {
918
- const isLeft = positionLeft >= 0;
919
- setInnerAlign(isLeft ? 'left' : 'right');
920
- overlayPosition.left = isLeft ? positionLeft : positionRight;
930
+ overlayPosition.left = isLeft ? left : right;
921
931
  }
922
- else {
923
- const isRight = positionRight + contentDimensions.width <= window.innerWidth;
924
- setInnerAlign(isRight ? 'right' : 'left');
925
- overlayPosition.left = isRight ? positionRight : positionLeft;
932
+ else if (align === 'right') {
933
+ overlayPosition.left = isRight ? right : left;
934
+ }
935
+ // top
936
+ if (alignY === 'top') {
937
+ overlayPosition.top = isTop ? top : bottom;
926
938
  }
927
- switch (alignY) {
928
- case 'top': {
929
- const isTop = positionTop + contentDimensions.height <= window.innerHeight;
930
- setInnerAlignY(isTop ? 'top' : 'bottom');
931
- overlayPosition.top = isTop ? positionTop : positionBottom;
932
- break;
939
+ // center
940
+ else if (alignY === 'center') {
941
+ const center = t.top + (t.bottom - t.top) / 2 - c.height / 2;
942
+ const isCenteredTop = center >= 0;
943
+ const isCenteredBottom = center + c.height <= window.innerHeight;
944
+ if (isCenteredTop && isCenteredBottom) {
945
+ overlayPosition.top = center;
933
946
  }
934
- case 'center':
935
- overlayPosition.top =
936
- triggerDimensions.top -
937
- offsetY +
938
- (triggerDimensions.bottom - triggerDimensions.top) / 2 -
939
- contentDimensions.height / 2;
940
- break;
941
- case 'bottom':
942
- default: {
943
- const isBottom = positionBottom >= 0;
944
- setInnerAlignY(isBottom ? 'bottom' : 'top');
945
- overlayPosition.top = isBottom ? positionBottom : positionTop;
947
+ else if (isCenteredTop) {
948
+ overlayPosition.top = top;
946
949
  }
950
+ else if (isCenteredBottom) {
951
+ overlayPosition.top = bottom;
952
+ }
953
+ }
954
+ // bottom
955
+ else if (alignY === 'bottom') {
956
+ overlayPosition.top = isBottom ? bottom : top;
947
957
  }
948
958
  }
949
959
  }
960
+ // modal type
950
961
  else if (type === 'modal') {
951
962
  switch (alignX) {
952
963
  case 'right':
@@ -957,8 +968,7 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
957
968
  break;
958
969
  case 'center':
959
970
  default:
960
- overlayPosition.left =
961
- window.innerWidth / 2 - contentDimensions.width / 2;
971
+ overlayPosition.left = window.innerWidth / 2 - c.width / 2;
962
972
  break;
963
973
  }
964
974
  switch (alignY) {
@@ -966,8 +976,7 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
966
976
  overlayPosition.top = offsetY;
967
977
  break;
968
978
  case 'center':
969
- overlayPosition.top =
970
- window.innerHeight / 2 - contentDimensions.height / 2;
979
+ overlayPosition.top = window.innerHeight / 2 - c.height / 2;
971
980
  break;
972
981
  case 'bottom':
973
982
  default:
@@ -975,12 +984,13 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
975
984
  break;
976
985
  }
977
986
  }
987
+ const calc = (param) => value(param, rootSize);
978
988
  // ADD POSITION STYLES TO CONTENT
979
- contentRef.current.style.position = overlayPosition.position;
980
- contentRef.current.style.top = value([overlayPosition.top], rootSize);
981
- contentRef.current.style.bottom = value([overlayPosition.bottom], rootSize);
982
- contentRef.current.style.left = value([overlayPosition.left], rootSize);
983
- contentRef.current.style.right = value([overlayPosition.right], rootSize);
989
+ contentRef.current.style.position = position;
990
+ contentRef.current.style.top = calc(overlayPosition.top);
991
+ contentRef.current.style.bottom = calc(overlayPosition.bottom);
992
+ contentRef.current.style.left = calc(overlayPosition.left);
993
+ contentRef.current.style.right = calc(overlayPosition.right);
984
994
  };
985
995
  const handleVisibilityByEventType = (e) => {
986
996
  if (!active) {
@@ -1027,9 +1037,9 @@ offsetX = 0, offsetY = 0, throttleDelay = 200, customScrollListener, closeOnEsc
1027
1037
  triggerRef,
1028
1038
  contentRef,
1029
1039
  active,
1030
- align: innerAlign,
1031
- alignX: innerAlignX,
1032
- alignY: innerAlignY,
1040
+ align,
1041
+ alignX,
1042
+ alignY,
1033
1043
  showContent,
1034
1044
  hideContent,
1035
1045
  blocked,