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