@app-studio/web 0.9.14 → 0.9.15

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.
package/dist/web.esm.js CHANGED
@@ -5735,6 +5735,24 @@ var PieChart = _ref => {
5735
5735
  var {
5736
5736
  getColor
5737
5737
  } = useTheme();
5738
+ // Use useElementPosition for intelligent tooltip positioning
5739
+ var {
5740
+ ref: positionRef,
5741
+ relation
5742
+ } = useElementPosition({
5743
+ trackChanges: true,
5744
+ trackOnHover: true,
5745
+ trackOnScroll: true,
5746
+ trackOnResize: true
5747
+ });
5748
+ // Create a separate ref for the SVG element
5749
+ var chartRef = useRef(null);
5750
+ // Sync the position ref with the chart ref for positioning calculations
5751
+ useEffect(() => {
5752
+ if (chartRef.current && positionRef) {
5753
+ positionRef.current = chartRef.current;
5754
+ }
5755
+ }, [chartRef, positionRef]);
5738
5756
  // Calculate chart dimensions
5739
5757
  var size = Math.min(width, height);
5740
5758
  var radius = size / 2 * 0.8;
@@ -5803,12 +5821,30 @@ var PieChart = _ref => {
5803
5821
  return result;
5804
5822
  }, [dataPoints, total, radius, centerX, centerY, donutRadius, animationProgress, isDonut]);
5805
5823
  return /*#__PURE__*/React.createElement("svg", {
5824
+ ref: chartRef,
5806
5825
  width: width,
5807
5826
  height: height
5808
5827
  }, slices.map((slice, index) => {
5809
5828
  var handleMouseEnter = e => {
5810
5829
  var tooltipContent = slice.label + ": " + slice.value + " (" + slice.percentage + ")";
5811
- showTooltip(e.clientX, e.clientY, tooltipContent);
5830
+ // Use intelligent positioning based on useElementPosition relation data
5831
+ var x = e.clientX;
5832
+ var y = e.clientY;
5833
+ if (relation && chartRef.current) {
5834
+ var chartRect = chartRef.current.getBoundingClientRect();
5835
+ // Adjust tooltip position based on available space
5836
+ if (relation.space.horizontal === 'left') {
5837
+ x = e.clientX - 100; // Offset tooltip to the left
5838
+ } else {
5839
+ x = e.clientX + 10; // Offset tooltip to the right
5840
+ }
5841
+ if (relation.space.vertical === 'top') {
5842
+ y = e.clientY - 30; // Offset tooltip above
5843
+ } else {
5844
+ y = e.clientY + 10; // Offset tooltip below
5845
+ }
5846
+ }
5847
+ showTooltip(x, y, tooltipContent);
5812
5848
  };
5813
5849
  var handleClick = () => {
5814
5850
  if (onSliceClick) {
@@ -13104,6 +13140,16 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13104
13140
  var [mentionStartPos, setMentionStartPos] = useState(-1);
13105
13141
  var [selectedMentionIndex, setSelectedMentionIndex] = useState(-1);
13106
13142
  var [filteredMentions, setFilteredMentions] = useState([]);
13143
+ // Use useElementPosition for intelligent dropdown positioning
13144
+ var {
13145
+ ref: positionRef,
13146
+ relation
13147
+ } = useElementPosition({
13148
+ trackChanges: true,
13149
+ trackOnHover: true,
13150
+ trackOnScroll: true,
13151
+ trackOnResize: true
13152
+ });
13107
13153
  // Positioning state for dropdowns
13108
13154
  var [mentionPosition, setMentionPosition] = useState({
13109
13155
  x: 0,
@@ -13113,7 +13159,6 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13113
13159
  x: 0,
13114
13160
  y: 0
13115
13161
  });
13116
- // Note: Using custom positioning logic for better control over dropdown placement
13117
13162
  // Update the content of the editable div when the value prop changes
13118
13163
  useEffect(() => {
13119
13164
  var editableDiv = ref;
@@ -13165,7 +13210,13 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13165
13210
  setMentionStartPos(-1);
13166
13211
  setSelectedMentionIndex(-1);
13167
13212
  }, [mentionData, mentionTrigger]);
13168
- // Calculate optimal position for dropdowns
13213
+ // Sync the position ref with the container ref for positioning calculations
13214
+ useEffect(() => {
13215
+ if (containerRef.current && positionRef) {
13216
+ positionRef.current = containerRef.current;
13217
+ }
13218
+ }, [containerRef, positionRef]);
13219
+ // Calculate optimal position for dropdowns using useElementPosition
13169
13220
  var calculateDropdownPosition = useCallback(function (dropdownHeight) {
13170
13221
  if (dropdownHeight === void 0) {
13171
13222
  dropdownHeight = 200;
@@ -13175,22 +13226,26 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13175
13226
  y: 0
13176
13227
  };
13177
13228
  var containerRect = containerRef.current.getBoundingClientRect();
13229
+ // Use relation data for intelligent positioning if available
13230
+ if (relation) {
13231
+ var _useTopPlacement = relation.space.vertical === 'top';
13232
+ return {
13233
+ x: containerRect.left,
13234
+ y: _useTopPlacement ? containerRect.top - dropdownHeight - 8 : containerRect.bottom + 8
13235
+ };
13236
+ }
13237
+ // Fallback to manual calculation if relation data is not available
13178
13238
  var viewportHeight = window.innerHeight;
13179
- var viewportWidth = window.innerWidth;
13180
- // Calculate available space
13181
13239
  var availableSpace = {
13182
13240
  top: containerRect.top,
13183
- bottom: viewportHeight - containerRect.bottom,
13184
- left: containerRect.left,
13185
- right: viewportWidth - containerRect.right
13241
+ bottom: viewportHeight - containerRect.bottom
13186
13242
  };
13187
- // Prefer bottom placement, but use top if not enough space
13188
13243
  var useTopPlacement = availableSpace.bottom < dropdownHeight + 8 && availableSpace.top > availableSpace.bottom;
13189
13244
  return {
13190
13245
  x: containerRect.left,
13191
13246
  y: useTopPlacement ? containerRect.top - dropdownHeight - 8 : containerRect.bottom + 8
13192
13247
  };
13193
- }, []);
13248
+ }, [relation]);
13194
13249
  // Handle focus events
13195
13250
  var handleFocus = useCallback(() => {
13196
13251
  setIsFocused(true);
@@ -13396,7 +13451,7 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13396
13451
  opacity: 0.7,
13397
13452
  padding: '4px'
13398
13453
  }
13399
- }, "Mentions (Trigger: ", mentionTrigger, ")"))))), showSuggestions && suggestions.length > 0 && !showMentions && isFocused && !value && (/*#__PURE__*/React.createElement(View, Object.assign({
13454
+ }, "Mentions (Trigger: ", mentionTrigger, ")", relation && (/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), "Space: ", relation.space.vertical, "-", relation.space.horizontal))))))), showSuggestions && suggestions.length > 0 && !showMentions && isFocused && !value && (/*#__PURE__*/React.createElement(View, Object.assign({
13400
13455
  position: "fixed",
13401
13456
  left: suggestionPosition.x,
13402
13457
  top: suggestionPosition.y,
@@ -13442,7 +13497,7 @@ var EditableInput = /*#__PURE__*/forwardRef((_ref, ref) => {
13442
13497
  opacity: 0.7,
13443
13498
  padding: '4px'
13444
13499
  }
13445
- }, "Suggestions (Focus-triggered)"))))));
13500
+ }, "Suggestions (Focus-triggered)", relation && (/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), "Space: ", relation.space.vertical, "-", relation.space.horizontal))))))));
13446
13501
  });
13447
13502
  EditableInput.displayName = 'EditableInput';
13448
13503
 
@@ -17584,109 +17639,103 @@ var DropdownMenuContent = _ref3 => {
17584
17639
  triggerRef
17585
17640
  } = useDropdownMenuContext();
17586
17641
  var contentRef = useRef(null);
17642
+ // Use useElementPosition for intelligent positioning
17643
+ var {
17644
+ ref: positionRef,
17645
+ relation
17646
+ } = useElementPosition({
17647
+ trackChanges: true,
17648
+ trackOnHover: true,
17649
+ trackOnScroll: true,
17650
+ trackOnResize: true
17651
+ });
17587
17652
  var [optimalPosition, setOptimalPosition] = useState({
17588
17653
  x: 0,
17589
17654
  y: 0,
17590
17655
  placement: side
17591
17656
  });
17592
- // Calculate optimal position when the dropdown opens
17657
+ // Sync the position ref with the trigger ref for positioning calculations
17658
+ useEffect(() => {
17659
+ if (triggerRef.current && positionRef) {
17660
+ positionRef.current = triggerRef.current;
17661
+ }
17662
+ }, [triggerRef, positionRef, isOpen]);
17663
+ // Calculate optimal position using useElementPosition when the dropdown opens
17593
17664
  useEffect(() => {
17594
17665
  if (isOpen && contentRef.current && triggerRef.current) {
17595
- var contentRect = contentRef.current.getBoundingClientRect();
17596
17666
  var triggerRect = triggerRef.current.getBoundingClientRect();
17597
- // Get content dimensions
17598
- var contentWidth = Math.max(contentRect.width || 180, 180);
17599
- var contentHeight = Math.max(contentRect.height || 100, 100);
17600
- // Get viewport dimensions
17601
- var viewportWidth = window.innerWidth;
17602
- var viewportHeight = window.innerHeight;
17603
- // Calculate available space on all sides from the trigger
17604
- var availableSpace = {
17605
- top: triggerRect.top,
17606
- right: viewportWidth - triggerRect.right,
17607
- bottom: viewportHeight - triggerRect.bottom,
17608
- left: triggerRect.left
17609
- };
17610
- // Determine optimal placement based on available space and preferred side
17611
- var placements = [{
17612
- placement: 'bottom',
17613
- space: availableSpace.bottom,
17614
- fits: availableSpace.bottom >= contentHeight + 8,
17615
- x: align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - contentWidth : triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
17616
- y: triggerRect.bottom + 8
17617
- }, {
17618
- placement: 'top',
17619
- space: availableSpace.top,
17620
- fits: availableSpace.top >= contentHeight + 8,
17621
- x: align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - contentWidth : triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
17622
- y: triggerRect.top - contentHeight - 8
17623
- }, {
17624
- placement: 'right',
17625
- space: availableSpace.right,
17626
- fits: availableSpace.right >= contentWidth + 8,
17627
- x: triggerRect.right + 8,
17628
- y: align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - contentHeight : triggerRect.top + triggerRect.height / 2 - contentHeight / 2
17629
- }, {
17630
- placement: 'left',
17631
- space: availableSpace.left,
17632
- fits: availableSpace.left >= contentWidth + 8,
17633
- x: triggerRect.left - contentWidth - 8,
17634
- y: align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - contentHeight : triggerRect.top + triggerRect.height / 2 - contentHeight / 2
17635
- }];
17636
- // First try the preferred side if it fits
17637
- var preferredPlacement = placements.find(p => p.placement === side && p.fits);
17638
- if (preferredPlacement) {
17639
- setOptimalPosition({
17640
- x: preferredPlacement.x,
17641
- y: preferredPlacement.y,
17642
- placement: preferredPlacement.placement
17643
- });
17644
- return;
17645
- }
17646
- // Otherwise, find the best fitting placement
17647
- var fittingPlacement = placements.find(p => p.fits);
17648
- if (fittingPlacement) {
17649
- setOptimalPosition({
17650
- x: fittingPlacement.x,
17651
- y: fittingPlacement.y,
17652
- placement: fittingPlacement.placement
17653
- });
17654
- return;
17655
- }
17656
- // If nothing fits, choose the placement with the most space
17657
- var bestPlacement = placements.reduce((best, current) => current.space > best.space ? current : best);
17658
- // Ensure the content stays within viewport bounds
17659
- var finalX = bestPlacement.x;
17660
- var finalY = bestPlacement.y;
17661
- if (finalX + contentWidth > viewportWidth) {
17662
- finalX = viewportWidth - contentWidth - 8;
17663
- }
17664
- if (finalX < 8) {
17665
- finalX = 8;
17666
- }
17667
- if (finalY + contentHeight > viewportHeight) {
17668
- finalY = viewportHeight - contentHeight - 8;
17667
+ var placement = side;
17668
+ // Use relation data to determine optimal placement
17669
+ if (relation) {
17670
+ // If preferred side doesn't have enough space, use the side with more space
17671
+ if (side === 'bottom' && relation.space.vertical === 'top') {
17672
+ placement = 'top';
17673
+ } else if (side === 'top' && relation.space.vertical === 'bottom') {
17674
+ placement = 'bottom';
17675
+ } else if (side === 'right' && relation.space.horizontal === 'left') {
17676
+ placement = 'left';
17677
+ } else if (side === 'left' && relation.space.horizontal === 'right') {
17678
+ placement = 'right';
17679
+ }
17669
17680
  }
17670
- if (finalY < 8) {
17671
- finalY = 8;
17681
+ // Calculate position based on optimal placement and alignment
17682
+ var x = 0;
17683
+ var y = 0;
17684
+ switch (placement) {
17685
+ case 'bottom':
17686
+ x = align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - 180 // Estimated content width
17687
+ : triggerRect.left + triggerRect.width / 2 - 90; // Half of estimated width
17688
+ y = triggerRect.bottom + 8;
17689
+ break;
17690
+ case 'top':
17691
+ x = align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - 180 : triggerRect.left + triggerRect.width / 2 - 90;
17692
+ y = triggerRect.top - 8; // Will be adjusted with transform
17693
+ break;
17694
+ case 'right':
17695
+ x = triggerRect.right + 8;
17696
+ y = align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - 100 // Estimated content height
17697
+ : triggerRect.top + triggerRect.height / 2 - 50; // Half of estimated height
17698
+ break;
17699
+ case 'left':
17700
+ x = triggerRect.left - 8; // Will be adjusted with transform
17701
+ y = align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - 100 : triggerRect.top + triggerRect.height / 2 - 50;
17702
+ break;
17672
17703
  }
17673
17704
  setOptimalPosition({
17674
- x: finalX,
17675
- y: finalY,
17676
- placement: bestPlacement.placement
17705
+ x,
17706
+ y,
17707
+ placement
17677
17708
  });
17678
17709
  }
17679
- }, [isOpen, side, align, triggerRef]);
17710
+ }, [isOpen, side, align, triggerRef, relation]);
17680
17711
  if (!isOpen) {
17681
17712
  return null;
17682
17713
  }
17683
- // Create intelligent positioning styles
17684
- var positionStyles = {
17685
- position: 'fixed',
17686
- left: optimalPosition.x,
17687
- top: optimalPosition.y,
17688
- zIndex: 1000
17714
+ // Create intelligent positioning styles with transform for better placement
17715
+ var getPositionStyles = () => {
17716
+ var baseStyles = {
17717
+ position: 'fixed',
17718
+ left: optimalPosition.x,
17719
+ top: optimalPosition.y,
17720
+ zIndex: 1000
17721
+ };
17722
+ // Add transform based on placement for better positioning
17723
+ switch (optimalPosition.placement) {
17724
+ case 'top':
17725
+ return Object.assign({}, baseStyles, {
17726
+ transform: 'translateY(-100%)'
17727
+ });
17728
+ case 'left':
17729
+ return Object.assign({}, baseStyles, {
17730
+ transform: 'translateX(-100%)'
17731
+ });
17732
+ case 'bottom':
17733
+ case 'right':
17734
+ default:
17735
+ return baseStyles;
17736
+ }
17689
17737
  };
17738
+ var positionStyles = getPositionStyles();
17690
17739
  return /*#__PURE__*/React.createElement(View, Object.assign({
17691
17740
  ref: contentRef,
17692
17741
  id: "dropdown-menu",
@@ -17706,7 +17755,13 @@ var DropdownMenuContent = _ref3 => {
17706
17755
  item: item,
17707
17756
  views: views
17708
17757
  });
17709
- }));
17758
+ }), process.env.NODE_ENV === 'development' && (/*#__PURE__*/React.createElement("div", {
17759
+ style: {
17760
+ fontSize: '10px',
17761
+ opacity: 0.7,
17762
+ padding: '4px'
17763
+ }
17764
+ }, "Placement: ", optimalPosition.placement, relation && (/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), "Space: ", relation.space.vertical, "-", relation.space.horizontal)))));
17710
17765
  };
17711
17766
  // DropdownMenu Item component
17712
17767
  var DropdownMenuItem = _ref4 => {
@@ -20890,111 +20945,99 @@ var HoverCardContent = _ref3 => {
20890
20945
  contentId,
20891
20946
  triggerId
20892
20947
  } = useHoverCardContext();
20893
- var [optimalPosition, setOptimalPosition] = useState({
20894
- x: 0,
20895
- y: 0,
20896
- placement: side
20948
+ // Use useElementPosition for intelligent positioning
20949
+ var {
20950
+ ref: positionRef,
20951
+ relation
20952
+ } = useElementPosition({
20953
+ trackChanges: true,
20954
+ trackOnHover: true,
20955
+ trackOnScroll: true,
20956
+ trackOnResize: true
20897
20957
  });
20898
- // Calculate optimal position when the card opens or content dimensions change
20958
+ // Sync the position ref with the trigger ref for positioning calculations
20899
20959
  useEffect(() => {
20900
- if (isOpen && contentRef != null && contentRef.current && triggerRef != null && triggerRef.current) {
20901
- var contentRect = contentRef.current.getBoundingClientRect();
20902
- var triggerRect = triggerRef.current.getBoundingClientRect();
20903
- // Get content dimensions
20904
- var contentWidth = Math.max(contentRect.width || 200, 200);
20905
- var contentHeight = Math.max(contentRect.height || 100, 100);
20906
- // Get viewport dimensions
20907
- var viewportWidth = window.innerWidth;
20908
- var viewportHeight = window.innerHeight;
20909
- // Calculate available space on all sides from the trigger
20910
- var availableSpace = {
20911
- top: triggerRect.top,
20912
- right: viewportWidth - triggerRect.right,
20913
- bottom: viewportHeight - triggerRect.bottom,
20914
- left: triggerRect.left
20915
- };
20916
- // Determine optimal placement based on available space and preferred side
20917
- var placements = [{
20918
- placement: 'bottom',
20919
- space: availableSpace.bottom,
20920
- fits: availableSpace.bottom >= contentHeight + sideOffset,
20921
- x: triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
20922
- y: triggerRect.bottom + sideOffset
20923
- }, {
20924
- placement: 'top',
20925
- space: availableSpace.top,
20926
- fits: availableSpace.top >= contentHeight + sideOffset,
20927
- x: triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
20928
- y: triggerRect.top - contentHeight - sideOffset
20929
- }, {
20930
- placement: 'right',
20931
- space: availableSpace.right,
20932
- fits: availableSpace.right >= contentWidth + sideOffset,
20933
- x: triggerRect.right + sideOffset,
20934
- y: triggerRect.top + triggerRect.height / 2 - contentHeight / 2
20935
- }, {
20936
- placement: 'left',
20937
- space: availableSpace.left,
20938
- fits: availableSpace.left >= contentWidth + sideOffset,
20939
- x: triggerRect.left - contentWidth - sideOffset,
20940
- y: triggerRect.top + triggerRect.height / 2 - contentHeight / 2
20941
- }];
20942
- // First try the preferred side if it fits
20943
- var preferredPlacement = placements.find(p => p.placement === side && p.fits);
20944
- if (preferredPlacement) {
20945
- setOptimalPosition({
20946
- x: preferredPlacement.x,
20947
- y: preferredPlacement.y,
20948
- placement: preferredPlacement.placement
20949
- });
20950
- return;
20951
- }
20952
- // Otherwise, find the best fitting placement
20953
- var fittingPlacement = placements.find(p => p.fits);
20954
- if (fittingPlacement) {
20955
- setOptimalPosition({
20956
- x: fittingPlacement.x,
20957
- y: fittingPlacement.y,
20958
- placement: fittingPlacement.placement
20959
- });
20960
- return;
20961
- }
20962
- // If nothing fits, choose the placement with the most space
20963
- var bestPlacement = placements.reduce((best, current) => current.space > best.space ? current : best);
20964
- // Ensure the content stays within viewport bounds
20965
- var finalX = bestPlacement.x;
20966
- var finalY = bestPlacement.y;
20967
- if (finalX + contentWidth > viewportWidth) {
20968
- finalX = viewportWidth - contentWidth - 8;
20969
- }
20970
- if (finalX < 8) {
20971
- finalX = 8;
20972
- }
20973
- if (finalY + contentHeight > viewportHeight) {
20974
- finalY = viewportHeight - contentHeight - 8;
20975
- }
20976
- if (finalY < 8) {
20977
- finalY = 8;
20960
+ if (triggerRef != null && triggerRef.current && (positionRef == null ? void 0 : positionRef.current) !== triggerRef.current) {
20961
+ // Update the position tracking to use the trigger element
20962
+ if (positionRef) {
20963
+ positionRef.current = triggerRef.current;
20978
20964
  }
20979
- setOptimalPosition({
20980
- x: finalX,
20981
- y: finalY,
20982
- placement: bestPlacement.placement
20983
- });
20984
20965
  }
20985
- }, [isOpen, side, sideOffset, contentRef, triggerRef]);
20966
+ }, [triggerRef, positionRef, isOpen]);
20986
20967
  var handleMouseEnter = () => cancelCloseTimer(); // Keep card open if mouse enters content
20987
20968
  var handleMouseLeave = () => closeCard();
20988
20969
  if (!isOpen) {
20989
20970
  return null; // Don't render content if not open
20990
20971
  }
20991
- // Create intelligent positioning styles
20992
- var positionStyles = {
20993
- position: 'fixed',
20994
- left: optimalPosition.x,
20995
- top: optimalPosition.y,
20996
- zIndex: 1000
20972
+ // Create intelligent positioning styles based on useElementPosition relation data
20973
+ var getPositionStyles = () => {
20974
+ if (!relation || !(triggerRef != null && triggerRef.current)) {
20975
+ // Fallback positioning if relation data is not available
20976
+ return {
20977
+ position: 'absolute',
20978
+ top: 0,
20979
+ left: 0,
20980
+ zIndex: 1000
20981
+ };
20982
+ }
20983
+ var triggerRect = triggerRef.current.getBoundingClientRect();
20984
+ var placement = side;
20985
+ // Use relation data to determine optimal placement
20986
+ // If preferred side doesn't have enough space, use the side with more space
20987
+ if (side === 'bottom' && relation.space.vertical === 'top') {
20988
+ placement = 'top';
20989
+ } else if (side === 'top' && relation.space.vertical === 'bottom') {
20990
+ placement = 'bottom';
20991
+ } else if (side === 'right' && relation.space.horizontal === 'left') {
20992
+ placement = 'left';
20993
+ } else if (side === 'left' && relation.space.horizontal === 'right') {
20994
+ placement = 'right';
20995
+ }
20996
+ // Calculate position based on optimal placement
20997
+ var x = 0;
20998
+ var y = 0;
20999
+ switch (placement) {
21000
+ case 'bottom':
21001
+ x = triggerRect.left + triggerRect.width / 2;
21002
+ y = triggerRect.bottom + sideOffset;
21003
+ break;
21004
+ case 'top':
21005
+ x = triggerRect.left + triggerRect.width / 2;
21006
+ y = triggerRect.top - sideOffset;
21007
+ break;
21008
+ case 'right':
21009
+ x = triggerRect.right + sideOffset;
21010
+ y = triggerRect.top + triggerRect.height / 2;
21011
+ break;
21012
+ case 'left':
21013
+ x = triggerRect.left - sideOffset;
21014
+ y = triggerRect.top + triggerRect.height / 2;
21015
+ break;
21016
+ }
21017
+ return {
21018
+ position: 'fixed',
21019
+ left: x,
21020
+ top: y,
21021
+ zIndex: 1000,
21022
+ transform: getTransformOrigin(placement)
21023
+ };
21024
+ };
21025
+ // Helper function to set transform origin for better positioning
21026
+ var getTransformOrigin = placement => {
21027
+ switch (placement) {
21028
+ case 'bottom':
21029
+ return 'translate(-50%, 0)';
21030
+ case 'top':
21031
+ return 'translate(-50%, -100%)';
21032
+ case 'right':
21033
+ return 'translate(0, -50%)';
21034
+ case 'left':
21035
+ return 'translate(-100%, -50%)';
21036
+ default:
21037
+ return 'translate(-50%, 0)';
21038
+ }
20997
21039
  };
21040
+ var positionStyles = getPositionStyles();
20998
21041
  return /*#__PURE__*/React.createElement(View, Object.assign({
20999
21042
  ref: contentRef,
21000
21043
  id: contentId,
@@ -21011,7 +21054,13 @@ var HoverCardContent = _ref3 => {
21011
21054
  maxWidth: maxWidth,
21012
21055
  // Combine intelligent position styles with user styles
21013
21056
  style: Object.assign({}, positionStyles, userStyle)
21014
- }, views == null ? void 0 : views.container, props), children);
21057
+ }, views == null ? void 0 : views.container, props), children, process.env.NODE_ENV === 'development' && relation && (/*#__PURE__*/React.createElement("div", {
21058
+ style: {
21059
+ fontSize: '10px',
21060
+ opacity: 0.7,
21061
+ marginTop: '4px'
21062
+ }
21063
+ }, "Position: ", relation.position.vertical, "-", relation.position.horizontal, /*#__PURE__*/React.createElement("br", null), "More space: ", relation.space.vertical, "-", relation.space.horizontal)));
21015
21064
  };
21016
21065
 
21017
21066
  var _excluded$_ = ["children", "views", "openDelay", "closeDelay"];
@@ -24458,108 +24507,102 @@ var TooltipView = _ref4 => {
24458
24507
  contentId,
24459
24508
  triggerId
24460
24509
  } = useTooltipContext();
24510
+ // Use useElementPosition for intelligent positioning
24511
+ var {
24512
+ ref: positionRef,
24513
+ relation
24514
+ } = useElementPosition({
24515
+ trackChanges: true,
24516
+ trackOnHover: true,
24517
+ trackOnScroll: true,
24518
+ trackOnResize: true
24519
+ });
24461
24520
  var [optimalPosition, setOptimalPosition] = useState({
24462
24521
  x: 0,
24463
24522
  y: 0,
24464
24523
  placement: position
24465
24524
  });
24466
- // Calculate optimal position when the tooltip opens
24525
+ // Sync the position ref with the trigger ref for positioning calculations
24526
+ useEffect(() => {
24527
+ if (triggerRef != null && triggerRef.current && positionRef) {
24528
+ positionRef.current = triggerRef.current;
24529
+ }
24530
+ }, [triggerRef, positionRef, isOpen]);
24531
+ // Calculate optimal position using useElementPosition when the tooltip opens
24467
24532
  useEffect(() => {
24468
24533
  if (isOpen && contentRef != null && contentRef.current && triggerRef != null && triggerRef.current) {
24469
- var contentRect = contentRef.current.getBoundingClientRect();
24470
24534
  var triggerRect = triggerRef.current.getBoundingClientRect();
24471
- // Get content dimensions
24472
- var contentWidth = Math.max(contentRect.width || 120, 120);
24473
- var contentHeight = Math.max(contentRect.height || 32, 32);
24474
- // Get viewport dimensions
24475
- var viewportWidth = window.innerWidth;
24476
- var viewportHeight = window.innerHeight;
24477
- // Calculate available space on all sides from the trigger
24478
- var availableSpace = {
24479
- top: triggerRect.top,
24480
- right: viewportWidth - triggerRect.right,
24481
- bottom: viewportHeight - triggerRect.bottom,
24482
- left: triggerRect.left
24483
- };
24484
- // Determine optimal placement based on available space and preferred position
24485
- var placements = [{
24486
- placement: 'top',
24487
- space: availableSpace.top,
24488
- fits: availableSpace.top >= contentHeight + 16,
24489
- x: align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - contentWidth : triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
24490
- y: triggerRect.top - contentHeight - 8
24491
- }, {
24492
- placement: 'bottom',
24493
- space: availableSpace.bottom,
24494
- fits: availableSpace.bottom >= contentHeight + 16,
24495
- x: align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - contentWidth : triggerRect.left + triggerRect.width / 2 - contentWidth / 2,
24496
- y: triggerRect.bottom + 8
24497
- }, {
24498
- placement: 'right',
24499
- space: availableSpace.right,
24500
- fits: availableSpace.right >= contentWidth + 16,
24501
- x: triggerRect.right + 8,
24502
- y: align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - contentHeight : triggerRect.top + triggerRect.height / 2 - contentHeight / 2
24503
- }, {
24504
- placement: 'left',
24505
- space: availableSpace.left,
24506
- fits: availableSpace.left >= contentWidth + 16,
24507
- x: triggerRect.left - contentWidth - 8,
24508
- y: align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - contentHeight : triggerRect.top + triggerRect.height / 2 - contentHeight / 2
24509
- }];
24510
- // First try the preferred position if it fits
24511
- var preferredPlacement = placements.find(p => p.placement === position && p.fits);
24512
- if (preferredPlacement) {
24513
- setOptimalPosition({
24514
- x: preferredPlacement.x,
24515
- y: preferredPlacement.y,
24516
- placement: preferredPlacement.placement
24517
- });
24518
- return;
24519
- }
24520
- // Otherwise, find the best fitting placement
24521
- var fittingPlacement = placements.find(p => p.fits);
24522
- if (fittingPlacement) {
24523
- setOptimalPosition({
24524
- x: fittingPlacement.x,
24525
- y: fittingPlacement.y,
24526
- placement: fittingPlacement.placement
24527
- });
24528
- return;
24529
- }
24530
- // If nothing fits, choose the placement with the most space
24531
- var bestPlacement = placements.reduce((best, current) => current.space > best.space ? current : best);
24532
- // Ensure the content stays within viewport bounds
24533
- var finalX = bestPlacement.x;
24534
- var finalY = bestPlacement.y;
24535
- if (finalX + contentWidth > viewportWidth) {
24536
- finalX = viewportWidth - contentWidth - 8;
24537
- }
24538
- if (finalX < 8) {
24539
- finalX = 8;
24540
- }
24541
- if (finalY + contentHeight > viewportHeight) {
24542
- finalY = viewportHeight - contentHeight - 8;
24535
+ var placement = position;
24536
+ // Use relation data to determine optimal placement
24537
+ if (relation) {
24538
+ // If preferred position doesn't have enough space, use the position with more space
24539
+ if (position === 'top' && relation.space.vertical === 'bottom') {
24540
+ placement = 'bottom';
24541
+ } else if (position === 'bottom' && relation.space.vertical === 'top') {
24542
+ placement = 'top';
24543
+ } else if (position === 'right' && relation.space.horizontal === 'left') {
24544
+ placement = 'left';
24545
+ } else if (position === 'left' && relation.space.horizontal === 'right') {
24546
+ placement = 'right';
24547
+ }
24543
24548
  }
24544
- if (finalY < 8) {
24545
- finalY = 8;
24549
+ // Calculate position based on optimal placement and alignment
24550
+ var x = 0;
24551
+ var y = 0;
24552
+ switch (placement) {
24553
+ case 'top':
24554
+ x = align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - 120 // Estimated content width
24555
+ : triggerRect.left + triggerRect.width / 2 - 60; // Half of estimated width
24556
+ y = triggerRect.top - 8;
24557
+ break;
24558
+ case 'bottom':
24559
+ x = align === 'start' ? triggerRect.left : align === 'end' ? triggerRect.right - 120 : triggerRect.left + triggerRect.width / 2 - 60;
24560
+ y = triggerRect.bottom + 8;
24561
+ break;
24562
+ case 'right':
24563
+ x = triggerRect.right + 8;
24564
+ y = align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - 32 // Estimated content height
24565
+ : triggerRect.top + triggerRect.height / 2 - 16; // Half of estimated height
24566
+ break;
24567
+ case 'left':
24568
+ x = triggerRect.left - 8;
24569
+ y = align === 'start' ? triggerRect.top : align === 'end' ? triggerRect.bottom - 32 : triggerRect.top + triggerRect.height / 2 - 16;
24570
+ break;
24546
24571
  }
24547
24572
  setOptimalPosition({
24548
- x: finalX,
24549
- y: finalY,
24550
- placement: bestPlacement.placement
24573
+ x,
24574
+ y,
24575
+ placement
24551
24576
  });
24552
24577
  }
24553
- }, [isOpen, position, align, triggerRef, contentRef]);
24578
+ }, [isOpen, position, align, triggerRef, contentRef, relation]);
24554
24579
  // Get arrow styles based on optimal placement
24555
24580
  var arrowStyles = showArrow ? getArrowStyles(optimalPosition.placement) : {};
24556
- // Create intelligent positioning styles
24557
- var positionStyles = {
24558
- position: 'fixed',
24559
- left: optimalPosition.x,
24560
- top: optimalPosition.y,
24561
- zIndex: 1000
24581
+ // Create intelligent positioning styles with transform for better placement
24582
+ var getPositionStyles = () => {
24583
+ var baseStyles = {
24584
+ position: 'fixed',
24585
+ left: optimalPosition.x,
24586
+ top: optimalPosition.y,
24587
+ zIndex: 1000
24588
+ };
24589
+ // Add transform based on placement for better positioning
24590
+ switch (optimalPosition.placement) {
24591
+ case 'top':
24592
+ return Object.assign({}, baseStyles, {
24593
+ transform: 'translateY(-100%)'
24594
+ });
24595
+ case 'left':
24596
+ return Object.assign({}, baseStyles, {
24597
+ transform: 'translateX(-100%)'
24598
+ });
24599
+ case 'bottom':
24600
+ case 'right':
24601
+ default:
24602
+ return baseStyles;
24603
+ }
24562
24604
  };
24605
+ var positionStyles = getPositionStyles();
24563
24606
  return /*#__PURE__*/React.createElement(View, Object.assign({
24564
24607
  position: "relative",
24565
24608
  display: "inline-block"
@@ -24571,7 +24614,13 @@ var TooltipView = _ref4 => {
24571
24614
  borderRadius: 4,
24572
24615
  boxShadow: "0px 2px 8px rgba(0, 0, 0, 0.15)",
24573
24616
  style: positionStyles
24574
- }, TooltipSizes[size], TooltipVariants[variant], views == null ? void 0 : views.content), typeof content === 'string' ? (/*#__PURE__*/React.createElement(Text$1, Object.assign({}, views == null ? void 0 : views.text), content)) : content, showArrow && /*#__PURE__*/React.createElement(View, Object.assign({}, arrowStyles, views == null ? void 0 : views.arrow)))));
24617
+ }, TooltipSizes[size], TooltipVariants[variant], views == null ? void 0 : views.content), typeof content === 'string' ? (/*#__PURE__*/React.createElement(Text$1, Object.assign({}, views == null ? void 0 : views.text), content)) : content, showArrow && /*#__PURE__*/React.createElement(View, Object.assign({}, arrowStyles, views == null ? void 0 : views.arrow)), process.env.NODE_ENV === 'development' && (/*#__PURE__*/React.createElement("div", {
24618
+ style: {
24619
+ fontSize: '8px',
24620
+ opacity: 0.7,
24621
+ marginTop: '2px'
24622
+ }
24623
+ }, "Placement: ", optimalPosition.placement, relation && (/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), "Space: ", relation.space.vertical, "-", relation.space.horizontal)))))));
24575
24624
  };
24576
24625
 
24577
24626
  var _excluded$1b = ["content", "children", "position", "align", "size", "variant", "openDelay", "closeDelay", "showArrow", "defaultOpen", "isDisabled", "views"];