@ultraviolet/ui 1.39.0 → 1.40.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.
@@ -78,6 +78,65 @@ const findOffsetParent = element => {
78
78
  // If no suitable offset parent is found, return the body element
79
79
  return document.body;
80
80
  };
81
+
82
+ /**
83
+ * This function will check if there is an overflow of the popup compared to the parent it is set in.
84
+ * Depending on the position, for top and bottom the overflow will be on X axis and for left and right
85
+ * the overflow will be Y axis. The function return the number of pixels the popup is overflowing.
86
+ * @param position the position of the popup
87
+ * @param offsetParentRect the rect of the parent element where the children is located in
88
+ * @param childrenRect the rect of the children element, the children element is the one that will trigger the popup
89
+ * @param popupStructuredRef the rect of the popup, the popup itself
90
+ */
91
+ const getPopupOverflowFromParent = (position, offsetParentRect, childrenRect, popupStructuredRef) => {
92
+ const {
93
+ top: parentTop,
94
+ left: parentLeft,
95
+ right: parentRight
96
+ } = offsetParentRect;
97
+ const {
98
+ top: childrenTop,
99
+ bottom: childrenBottom,
100
+ left: childrenLeft,
101
+ right: childrenRight,
102
+ width: childrenWidth
103
+ } = childrenRect;
104
+ const {
105
+ width: popupWidth,
106
+ height: popupHeight
107
+ } = popupStructuredRef;
108
+ const popupHalfWidthWithArrow = popupWidth / 2 - ARROW_WIDTH;
109
+ const popupHalfHeightWithArrow = popupHeight / 2 - ARROW_WIDTH;
110
+ if (position === 'top' || position === 'bottom') {
111
+ const popupOverflowRight = childrenRight - childrenWidth / 2 + popupWidth / 2;
112
+ const popupOverflowLeft = childrenLeft + childrenWidth / 2 - parentLeft - popupWidth / 2;
113
+ if (popupOverflowRight > parentRight) {
114
+ if (Math.abs(popupOverflowRight - parentRight) > popupHalfWidthWithArrow) {
115
+ return -popupHalfWidthWithArrow;
116
+ }
117
+ return parentRight - popupOverflowRight;
118
+ }
119
+ if (popupOverflowLeft < 0) {
120
+ if (Math.abs(popupOverflowLeft) > popupHalfWidthWithArrow) {
121
+ return popupHalfWidthWithArrow;
122
+ }
123
+ return Math.abs(popupOverflowLeft);
124
+ }
125
+ }
126
+ if (position === 'left' || position === 'right') {
127
+ const popupOverflowTop = childrenTop - parentTop - popupHeight / 2;
128
+ if (popupOverflowTop < 0) {
129
+ if (Math.abs(childrenTop - parentTop - popupHalfHeightWithArrow) > popupHalfHeightWithArrow) {
130
+ return popupHalfHeightWithArrow;
131
+ }
132
+ return Math.abs(popupOverflowTop);
133
+ }
134
+ if (childrenBottom + popupHeight > window.innerHeight) {
135
+ return -popupHalfHeightWithArrow;
136
+ }
137
+ }
138
+ return 0;
139
+ };
81
140
  /**
82
141
  * This function will compute the positions of popup and arrow based on children position and popup size
83
142
  */
@@ -128,19 +187,20 @@ const computePositions = ({
128
187
  const overloadedChildrenLeft = isPopupPortalTargetBody ? childrenLeft : childrenLeft - parentLeft;
129
188
  const overloadedChildrenTop = isPopupPortalTargetBody ? childrenTop : childrenTop - parentTop;
130
189
  const overloadedChildrenRight = isPopupPortalTargetBody ? childrenRight : childrenLeft - parentLeft + childrenWidth;
190
+ const popupOverflow = getPopupOverflowFromParent(placementBasedOnWindowSize, offsetParentRect, childrenRect, popupStructuredRef);
131
191
  switch (placementBasedOnWindowSize) {
132
192
  case 'bottom':
133
193
  {
134
194
  const positionX = overloadedChildrenLeft + childrenWidth / 2 - popupWidth / 2;
135
195
  const positionY = overloadedChildrenTop + scrollTopValue + childrenHeight + ARROW_WIDTH + SPACE;
136
196
  return {
137
- arrowLeft: popupWidth / 2,
197
+ arrowLeft: popupWidth / 2 + popupOverflow * -1,
138
198
  arrowTop: -ARROW_WIDTH - 5,
139
199
  arrowTransform: '',
140
200
  placement: 'bottom',
141
201
  rotate: 180,
142
- popupInitialPosition: `translate3d(${positionX}px, ${positionY - TOTAL_USED_SPACE}px, 0)`,
143
- popupPosition: `translate3d(${positionX}px, ${positionY}px, 0)`
202
+ popupInitialPosition: `translate3d(${positionX + popupOverflow}px, ${positionY - TOTAL_USED_SPACE}px, 0)`,
203
+ popupPosition: `translate3d(${positionX + popupOverflow}px, ${positionY}px, 0)`
144
204
  };
145
205
  }
146
206
  case 'left':
@@ -149,12 +209,12 @@ const computePositions = ({
149
209
  const positionY = overloadedChildrenTop + scrollTopValue - popupHeight / 2 + childrenHeight / 2;
150
210
  return {
151
211
  arrowLeft: popupWidth + ARROW_WIDTH + 5,
152
- arrowTop: popupHeight / 2,
212
+ arrowTop: popupHeight / 2 + popupOverflow * -1,
153
213
  arrowTransform: 'translate(-50%, -50%)',
154
214
  placement: 'left',
155
215
  rotate: -90,
156
- popupInitialPosition: `translate3d(${positionX + TOTAL_USED_SPACE}px, ${positionY}px, 0)`,
157
- popupPosition: `translate3d(${positionX}px, ${positionY}px, 0)`
216
+ popupInitialPosition: `translate3d(${positionX + TOTAL_USED_SPACE}px, ${positionY + popupOverflow}px, 0)`,
217
+ popupPosition: `translate3d(${positionX}px, ${positionY + popupOverflow}px, 0)`
158
218
  };
159
219
  }
160
220
  case 'right':
@@ -163,12 +223,12 @@ const computePositions = ({
163
223
  const positionY = overloadedChildrenTop + scrollTopValue - popupHeight / 2 + childrenHeight / 2;
164
224
  return {
165
225
  arrowLeft: -ARROW_WIDTH - 5,
166
- arrowTop: popupHeight / 2,
226
+ arrowTop: popupHeight / 2 + popupOverflow * -1,
167
227
  arrowTransform: 'translate(50%, -50%)',
168
228
  placement: 'right',
169
229
  rotate: 90,
170
- popupInitialPosition: `translate3d(${positionX - TOTAL_USED_SPACE}px, ${positionY}px, 0)`,
171
- popupPosition: `translate3d(${positionX}px, ${positionY}px, 0)`
230
+ popupInitialPosition: `translate3d(${positionX - TOTAL_USED_SPACE}px, ${positionY + popupOverflow}px, 0)`,
231
+ popupPosition: `translate3d(${positionX}px, ${positionY + popupOverflow}px, 0)`
172
232
  };
173
233
  }
174
234
  default:
@@ -177,13 +237,13 @@ const computePositions = ({
177
237
  const positionX = overloadedChildrenLeft + childrenWidth / 2 - popupWidth / 2;
178
238
  const positionY = overloadedChildrenTop + scrollTopValue - popupHeight - ARROW_WIDTH - SPACE;
179
239
  return {
180
- arrowLeft: popupWidth / 2,
240
+ arrowLeft: popupWidth / 2 + popupOverflow * -1,
181
241
  arrowTop: popupHeight - 1,
182
242
  arrowTransform: '',
183
243
  placement: 'top',
184
244
  rotate: 0,
185
- popupInitialPosition: `translate3d(${positionX}px, ${positionY + TOTAL_USED_SPACE}px, 0)`,
186
- popupPosition: `translate3d(${positionX}px, ${positionY}px, 0)`
245
+ popupInitialPosition: `translate3d(${positionX + popupOverflow}px, ${positionY + TOTAL_USED_SPACE}px, 0)`,
246
+ popupPosition: `translate3d(${positionX + popupOverflow}px, ${positionY}px, 0)`
187
247
  };
188
248
  }
189
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/ui",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "description": "Ultraviolet UI",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "default": "./dist/src/index.js"
34
34
  },
35
35
  "peerDependencies": {
36
- "@emotion/react": "11.11.3",
36
+ "@emotion/react": "11.11.4",
37
37
  "@emotion/styled": "11.11.0",
38
38
  "react": "18.2.0",
39
39
  "react-dom": "18.2.0"
@@ -41,7 +41,7 @@
41
41
  "devDependencies": {
42
42
  "@babel/core": "7.23.9",
43
43
  "@emotion/babel-plugin": "11.11.0",
44
- "@emotion/react": "11.11.3",
44
+ "@emotion/react": "11.11.4",
45
45
  "@emotion/styled": "11.11.0",
46
46
  "@types/react": "18.2.55",
47
47
  "@types/react-datepicker": "4.19.6",
@@ -67,7 +67,7 @@
67
67
  "react-use-clipboard": "1.0.9",
68
68
  "reakit": "1.3.11",
69
69
  "@ultraviolet/themes": "1.9.0",
70
- "@ultraviolet/icons": "2.9.1"
70
+ "@ultraviolet/icons": "2.9.2"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "rollup -c ../../rollup.config.mjs",