@proyecto-viviana/solidaria 0.2.2 → 0.2.4

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.
Files changed (210) hide show
  1. package/dist/autocomplete/createAutocomplete.d.ts +2 -2
  2. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  3. package/dist/index.js +233 -234
  4. package/dist/index.js.map +2 -2
  5. package/dist/index.ssr.js +233 -234
  6. package/dist/index.ssr.js.map +2 -2
  7. package/dist/interactions/PressEvent.d.ts +13 -10
  8. package/dist/interactions/PressEvent.d.ts.map +1 -1
  9. package/dist/interactions/createPress.d.ts.map +1 -1
  10. package/dist/interactions/index.d.ts +1 -1
  11. package/dist/interactions/index.d.ts.map +1 -1
  12. package/dist/select/createHiddenSelect.d.ts.map +1 -1
  13. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  14. package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
  15. package/package.json +9 -7
  16. package/src/autocomplete/createAutocomplete.ts +341 -0
  17. package/src/autocomplete/index.ts +9 -0
  18. package/src/breadcrumbs/createBreadcrumbs.ts +196 -0
  19. package/src/breadcrumbs/index.ts +8 -0
  20. package/src/button/createButton.ts +142 -0
  21. package/src/button/createToggleButton.ts +101 -0
  22. package/src/button/index.ts +4 -0
  23. package/src/button/types.ts +78 -0
  24. package/src/calendar/createCalendar.ts +138 -0
  25. package/src/calendar/createCalendarCell.ts +187 -0
  26. package/src/calendar/createCalendarGrid.ts +140 -0
  27. package/src/calendar/createRangeCalendar.ts +136 -0
  28. package/src/calendar/createRangeCalendarCell.ts +186 -0
  29. package/src/calendar/index.ts +34 -0
  30. package/src/checkbox/createCheckbox.ts +135 -0
  31. package/src/checkbox/createCheckboxGroup.ts +137 -0
  32. package/src/checkbox/createCheckboxGroupItem.ts +117 -0
  33. package/src/checkbox/createCheckboxGroupState.ts +193 -0
  34. package/src/checkbox/index.ts +13 -0
  35. package/src/color/createColorArea.ts +314 -0
  36. package/src/color/createColorField.ts +137 -0
  37. package/src/color/createColorSlider.ts +197 -0
  38. package/src/color/createColorSwatch.ts +40 -0
  39. package/src/color/createColorWheel.ts +208 -0
  40. package/src/color/index.ts +24 -0
  41. package/src/color/types.ts +116 -0
  42. package/src/combobox/createComboBox.ts +647 -0
  43. package/src/combobox/index.ts +6 -0
  44. package/src/combobox/intl/en-US.json +7 -0
  45. package/src/combobox/intl/es-ES.json +7 -0
  46. package/src/combobox/intl/index.ts +23 -0
  47. package/src/datepicker/createDateField.ts +154 -0
  48. package/src/datepicker/createDatePicker.ts +206 -0
  49. package/src/datepicker/createDateSegment.ts +229 -0
  50. package/src/datepicker/createTimeField.ts +154 -0
  51. package/src/datepicker/index.ts +28 -0
  52. package/src/dialog/createDialog.ts +120 -0
  53. package/src/dialog/index.ts +2 -0
  54. package/src/dialog/types.ts +19 -0
  55. package/src/disclosure/createDisclosure.ts +131 -0
  56. package/src/disclosure/createDisclosureGroup.ts +62 -0
  57. package/src/disclosure/index.ts +11 -0
  58. package/src/dnd/createDrag.ts +209 -0
  59. package/src/dnd/createDraggableCollection.ts +63 -0
  60. package/src/dnd/createDraggableItem.ts +243 -0
  61. package/src/dnd/createDrop.ts +321 -0
  62. package/src/dnd/createDroppableCollection.ts +293 -0
  63. package/src/dnd/createDroppableItem.ts +213 -0
  64. package/src/dnd/index.ts +47 -0
  65. package/src/dnd/types.ts +89 -0
  66. package/src/dnd/utils.ts +294 -0
  67. package/src/focus/FocusScope.tsx +408 -0
  68. package/src/focus/createAutoFocus.ts +321 -0
  69. package/src/focus/createFocusRestore.ts +313 -0
  70. package/src/focus/createVirtualFocus.ts +396 -0
  71. package/src/focus/index.ts +35 -0
  72. package/src/form/createFormReset.ts +51 -0
  73. package/src/form/createFormValidation.ts +224 -0
  74. package/src/form/index.ts +11 -0
  75. package/src/grid/GridKeyboardDelegate.ts +429 -0
  76. package/src/grid/createGrid.ts +261 -0
  77. package/src/grid/createGridCell.ts +182 -0
  78. package/src/grid/createGridRow.ts +153 -0
  79. package/src/grid/index.ts +18 -0
  80. package/src/grid/types.ts +133 -0
  81. package/src/gridlist/createGridList.ts +185 -0
  82. package/src/gridlist/createGridListItem.ts +180 -0
  83. package/src/gridlist/createGridListSelectionCheckbox.ts +59 -0
  84. package/src/gridlist/index.ts +16 -0
  85. package/src/gridlist/types.ts +81 -0
  86. package/src/i18n/NumberFormatter.ts +266 -0
  87. package/src/i18n/createCollator.ts +79 -0
  88. package/src/i18n/createDateFormatter.ts +83 -0
  89. package/src/i18n/createFilter.ts +131 -0
  90. package/src/i18n/createNumberFormatter.ts +52 -0
  91. package/src/i18n/createStringFormatter.ts +87 -0
  92. package/src/i18n/index.ts +40 -0
  93. package/src/i18n/locale.tsx +188 -0
  94. package/src/i18n/utils.ts +99 -0
  95. package/src/index.ts +670 -0
  96. package/src/interactions/FocusableProvider.tsx +44 -0
  97. package/src/interactions/PressEvent.ts +126 -0
  98. package/src/interactions/createFocus.ts +163 -0
  99. package/src/interactions/createFocusRing.ts +89 -0
  100. package/src/interactions/createFocusWithin.ts +206 -0
  101. package/src/interactions/createFocusable.ts +168 -0
  102. package/src/interactions/createHover.ts +254 -0
  103. package/src/interactions/createInteractionModality.ts +424 -0
  104. package/src/interactions/createKeyboard.ts +82 -0
  105. package/src/interactions/createLongPress.ts +174 -0
  106. package/src/interactions/createMove.ts +289 -0
  107. package/src/interactions/createPress.ts +834 -0
  108. package/src/interactions/index.ts +78 -0
  109. package/src/label/createField.ts +145 -0
  110. package/src/label/createLabel.ts +117 -0
  111. package/src/label/createLabels.ts +50 -0
  112. package/src/label/index.ts +19 -0
  113. package/src/landmark/createLandmark.ts +377 -0
  114. package/src/landmark/index.ts +8 -0
  115. package/src/link/createLink.ts +182 -0
  116. package/src/link/index.ts +1 -0
  117. package/src/listbox/createListBox.ts +269 -0
  118. package/src/listbox/createOption.ts +151 -0
  119. package/src/listbox/index.ts +12 -0
  120. package/src/live-announcer/announce.ts +322 -0
  121. package/src/live-announcer/index.ts +9 -0
  122. package/src/menu/createMenu.ts +396 -0
  123. package/src/menu/createMenuItem.ts +149 -0
  124. package/src/menu/createMenuTrigger.ts +88 -0
  125. package/src/menu/index.ts +18 -0
  126. package/src/meter/createMeter.ts +75 -0
  127. package/src/meter/index.ts +1 -0
  128. package/src/numberfield/createNumberField.ts +268 -0
  129. package/src/numberfield/index.ts +5 -0
  130. package/src/overlays/ariaHideOutside.ts +219 -0
  131. package/src/overlays/createInteractOutside.ts +149 -0
  132. package/src/overlays/createModal.tsx +202 -0
  133. package/src/overlays/createOverlay.ts +155 -0
  134. package/src/overlays/createOverlayTrigger.ts +85 -0
  135. package/src/overlays/createPreventScroll.ts +266 -0
  136. package/src/overlays/index.ts +44 -0
  137. package/src/popover/calculatePosition.ts +766 -0
  138. package/src/popover/createOverlayPosition.ts +356 -0
  139. package/src/popover/createPopover.ts +170 -0
  140. package/src/popover/index.ts +24 -0
  141. package/src/progress/createProgressBar.ts +128 -0
  142. package/src/progress/index.ts +5 -0
  143. package/src/radio/createRadio.ts +287 -0
  144. package/src/radio/createRadioGroup.ts +189 -0
  145. package/src/radio/createRadioGroupState.ts +201 -0
  146. package/src/radio/index.ts +23 -0
  147. package/src/searchfield/createSearchField.ts +186 -0
  148. package/src/searchfield/index.ts +2 -0
  149. package/src/select/createHiddenSelect.tsx +236 -0
  150. package/src/select/createSelect.ts +395 -0
  151. package/src/select/index.ts +14 -0
  152. package/src/selection/createTypeSelect.ts +201 -0
  153. package/src/selection/index.ts +6 -0
  154. package/src/separator/createSeparator.ts +82 -0
  155. package/src/separator/index.ts +6 -0
  156. package/src/slider/createSlider.ts +349 -0
  157. package/src/slider/index.ts +2 -0
  158. package/src/ssr/index.tsx +370 -0
  159. package/src/switch/createSwitch.ts +70 -0
  160. package/src/switch/index.ts +1 -0
  161. package/src/table/createTable.ts +526 -0
  162. package/src/table/createTableCell.ts +147 -0
  163. package/src/table/createTableColumnHeader.ts +115 -0
  164. package/src/table/createTableHeaderRow.ts +40 -0
  165. package/src/table/createTableRow.ts +155 -0
  166. package/src/table/createTableRowGroup.ts +32 -0
  167. package/src/table/createTableSelectAllCheckbox.ts +73 -0
  168. package/src/table/createTableSelectionCheckbox.ts +59 -0
  169. package/src/table/index.ts +30 -0
  170. package/src/table/types.ts +165 -0
  171. package/src/tabs/createTabs.ts +472 -0
  172. package/src/tabs/index.ts +14 -0
  173. package/src/tag/createTag.ts +194 -0
  174. package/src/tag/createTagGroup.ts +154 -0
  175. package/src/tag/index.ts +12 -0
  176. package/src/textfield/createTextField.ts +198 -0
  177. package/src/textfield/index.ts +5 -0
  178. package/src/toast/createToast.ts +118 -0
  179. package/src/toast/createToastRegion.ts +100 -0
  180. package/src/toast/index.ts +11 -0
  181. package/src/toggle/createToggle.ts +223 -0
  182. package/src/toggle/createToggleState.ts +94 -0
  183. package/src/toggle/index.ts +7 -0
  184. package/src/toolbar/createToolbar.ts +369 -0
  185. package/src/toolbar/index.ts +6 -0
  186. package/src/tooltip/createTooltip.ts +79 -0
  187. package/src/tooltip/createTooltipTrigger.ts +222 -0
  188. package/src/tooltip/index.ts +6 -0
  189. package/src/tree/createTree.ts +246 -0
  190. package/src/tree/createTreeItem.ts +233 -0
  191. package/src/tree/createTreeSelectionCheckbox.ts +68 -0
  192. package/src/tree/index.ts +16 -0
  193. package/src/tree/types.ts +87 -0
  194. package/src/utils/createDescription.ts +137 -0
  195. package/src/utils/dom.ts +327 -0
  196. package/src/utils/env.ts +54 -0
  197. package/src/utils/events.ts +106 -0
  198. package/src/utils/filterDOMProps.ts +116 -0
  199. package/src/utils/focus.ts +151 -0
  200. package/src/utils/geometry.ts +115 -0
  201. package/src/utils/globalListeners.ts +142 -0
  202. package/src/utils/index.ts +80 -0
  203. package/src/utils/mergeProps.ts +52 -0
  204. package/src/utils/platform.ts +52 -0
  205. package/src/utils/reactivity.ts +36 -0
  206. package/src/utils/textSelection.ts +114 -0
  207. package/src/visually-hidden/createVisuallyHidden.ts +124 -0
  208. package/src/visually-hidden/index.ts +6 -0
  209. package/dist/index.jsx +0 -15845
  210. package/dist/index.jsx.map +0 -7
@@ -0,0 +1,766 @@
1
+ /**
2
+ * Position calculation utilities for popovers and overlays.
3
+ * Ported from @react-aria/overlays calculatePosition.ts
4
+ */
5
+
6
+ // Types
7
+ export type Placement =
8
+ | 'bottom'
9
+ | 'bottom left'
10
+ | 'bottom right'
11
+ | 'bottom start'
12
+ | 'bottom end'
13
+ | 'top'
14
+ | 'top left'
15
+ | 'top right'
16
+ | 'top start'
17
+ | 'top end'
18
+ | 'left'
19
+ | 'left top'
20
+ | 'left bottom'
21
+ | 'right'
22
+ | 'right top'
23
+ | 'right bottom'
24
+ | 'start'
25
+ | 'start top'
26
+ | 'start bottom'
27
+ | 'end'
28
+ | 'end top'
29
+ | 'end bottom';
30
+
31
+ export type PlacementAxis = 'top' | 'bottom' | 'left' | 'right';
32
+ export type Axis = 'top' | 'left';
33
+ export type SizeAxis = 'width' | 'height';
34
+
35
+ interface Position {
36
+ top?: number;
37
+ left?: number;
38
+ bottom?: number;
39
+ right?: number;
40
+ }
41
+
42
+ interface Dimensions {
43
+ width: number;
44
+ height: number;
45
+ totalWidth: number;
46
+ totalHeight: number;
47
+ top: number;
48
+ left: number;
49
+ scroll: Position;
50
+ }
51
+
52
+ interface ParsedPlacement {
53
+ placement: PlacementAxis;
54
+ crossPlacement: PlacementAxis | 'center';
55
+ axis: Axis;
56
+ crossAxis: Axis;
57
+ size: SizeAxis;
58
+ crossSize: SizeAxis;
59
+ }
60
+
61
+ interface Offset {
62
+ top: number;
63
+ left: number;
64
+ width: number;
65
+ height: number;
66
+ }
67
+
68
+ export interface PositionOpts {
69
+ arrowSize: number;
70
+ placement: Placement;
71
+ targetNode: Element;
72
+ overlayNode: Element;
73
+ scrollNode: Element;
74
+ padding: number;
75
+ shouldFlip: boolean;
76
+ boundaryElement: Element;
77
+ offset: number;
78
+ crossOffset: number;
79
+ maxHeight?: number;
80
+ arrowBoundaryOffset?: number;
81
+ }
82
+
83
+ type HeightGrowthDirection = 'top' | 'bottom';
84
+
85
+ export interface PositionResult {
86
+ position: Position;
87
+ arrowOffsetLeft?: number;
88
+ arrowOffsetTop?: number;
89
+ triggerAnchorPoint: { x: number; y: number };
90
+ maxHeight: number;
91
+ placement: PlacementAxis;
92
+ }
93
+
94
+ // Constants
95
+ const AXIS: Record<string, Axis> = {
96
+ top: 'top',
97
+ bottom: 'top',
98
+ left: 'left',
99
+ right: 'left',
100
+ };
101
+
102
+ const FLIPPED_DIRECTION: Record<string, string> = {
103
+ top: 'bottom',
104
+ bottom: 'top',
105
+ left: 'right',
106
+ right: 'left',
107
+ };
108
+
109
+ const CROSS_AXIS: Record<string, Axis> = {
110
+ top: 'left',
111
+ left: 'top',
112
+ };
113
+
114
+ const AXIS_SIZE: Record<string, SizeAxis> = {
115
+ top: 'height',
116
+ left: 'width',
117
+ };
118
+
119
+ const TOTAL_SIZE: Record<string, string> = {
120
+ width: 'totalWidth',
121
+ height: 'totalHeight',
122
+ };
123
+
124
+ const PARSED_PLACEMENT_CACHE: Record<string, ParsedPlacement> = {};
125
+
126
+ function clamp(value: number, min: number, max: number): number {
127
+ return Math.min(Math.max(value, min), max);
128
+ }
129
+
130
+ function isWebKit(): boolean {
131
+ return typeof window !== 'undefined' && 'WebkitAppearance' in document.documentElement.style;
132
+ }
133
+
134
+ const getVisualViewport = () =>
135
+ typeof document !== 'undefined' ? window.visualViewport : null;
136
+
137
+ function getContainerDimensions(
138
+ containerNode: Element,
139
+ visualViewport: VisualViewport | null
140
+ ): Dimensions {
141
+ let width = 0,
142
+ height = 0,
143
+ totalWidth = 0,
144
+ totalHeight = 0,
145
+ top = 0,
146
+ left = 0;
147
+ const scroll: Position = {};
148
+ const isPinchZoomedIn = (visualViewport?.scale ?? 1) > 1;
149
+
150
+ if (containerNode.tagName === 'BODY' || containerNode.tagName === 'HTML') {
151
+ const documentElement = document.documentElement;
152
+ totalWidth = documentElement.clientWidth;
153
+ totalHeight = documentElement.clientHeight;
154
+ width = visualViewport?.width ?? totalWidth;
155
+ height = visualViewport?.height ?? totalHeight;
156
+ scroll.top = documentElement.scrollTop || (containerNode as HTMLElement).scrollTop;
157
+ scroll.left = documentElement.scrollLeft || (containerNode as HTMLElement).scrollLeft;
158
+
159
+ if (visualViewport) {
160
+ top = visualViewport.offsetTop;
161
+ left = visualViewport.offsetLeft;
162
+ }
163
+ } else {
164
+ ({ width, height, top, left } = getElementOffset(containerNode, false));
165
+ scroll.top = (containerNode as HTMLElement).scrollTop;
166
+ scroll.left = (containerNode as HTMLElement).scrollLeft;
167
+ totalWidth = width;
168
+ totalHeight = height;
169
+ }
170
+
171
+ if (
172
+ isWebKit() &&
173
+ (containerNode.tagName === 'BODY' || containerNode.tagName === 'HTML') &&
174
+ isPinchZoomedIn
175
+ ) {
176
+ scroll.top = 0;
177
+ scroll.left = 0;
178
+ top = visualViewport?.pageTop ?? 0;
179
+ left = visualViewport?.pageLeft ?? 0;
180
+ }
181
+
182
+ return { width, height, totalWidth, totalHeight, scroll, top, left };
183
+ }
184
+
185
+ function getScroll(node: Element): Offset {
186
+ return {
187
+ top: (node as HTMLElement).scrollTop,
188
+ left: (node as HTMLElement).scrollLeft,
189
+ width: (node as HTMLElement).scrollWidth,
190
+ height: (node as HTMLElement).scrollHeight,
191
+ };
192
+ }
193
+
194
+ function getDelta(
195
+ axis: Axis,
196
+ offset: number,
197
+ size: number,
198
+ boundaryDimensions: Dimensions,
199
+ containerDimensions: Dimensions,
200
+ padding: number,
201
+ containerOffsetWithBoundary: Offset
202
+ ): number {
203
+ const containerScroll = containerDimensions.scroll[axis] ?? 0;
204
+ const boundarySize = boundaryDimensions[AXIS_SIZE[axis]];
205
+
206
+ const boundaryStartEdge =
207
+ containerOffsetWithBoundary[axis] +
208
+ (boundaryDimensions.scroll[AXIS[axis]] ?? 0) +
209
+ padding;
210
+ const boundaryEndEdge =
211
+ containerOffsetWithBoundary[axis] +
212
+ (boundaryDimensions.scroll[AXIS[axis]] ?? 0) +
213
+ boundarySize -
214
+ padding;
215
+
216
+ const startEdgeOffset =
217
+ offset -
218
+ containerScroll +
219
+ (boundaryDimensions.scroll[AXIS[axis]] ?? 0) +
220
+ containerOffsetWithBoundary[axis] -
221
+ boundaryDimensions[AXIS[axis]];
222
+ const endEdgeOffset =
223
+ offset -
224
+ containerScroll +
225
+ size +
226
+ (boundaryDimensions.scroll[AXIS[axis]] ?? 0) +
227
+ containerOffsetWithBoundary[axis] -
228
+ boundaryDimensions[AXIS[axis]];
229
+
230
+ if (startEdgeOffset < boundaryStartEdge) {
231
+ return boundaryStartEdge - startEdgeOffset;
232
+ } else if (endEdgeOffset > boundaryEndEdge) {
233
+ return Math.max(boundaryEndEdge - endEdgeOffset, boundaryStartEdge - startEdgeOffset);
234
+ } else {
235
+ return 0;
236
+ }
237
+ }
238
+
239
+ function getMargins(node: Element): Position {
240
+ const style = window.getComputedStyle(node);
241
+ return {
242
+ top: parseInt(style.marginTop, 10) || 0,
243
+ bottom: parseInt(style.marginBottom, 10) || 0,
244
+ left: parseInt(style.marginLeft, 10) || 0,
245
+ right: parseInt(style.marginRight, 10) || 0,
246
+ };
247
+ }
248
+
249
+ function parsePlacement(input: Placement): ParsedPlacement {
250
+ if (PARSED_PLACEMENT_CACHE[input]) {
251
+ return PARSED_PLACEMENT_CACHE[input];
252
+ }
253
+
254
+ const [placement, crossPlacement = 'center'] = input.split(' ') as [PlacementAxis, string];
255
+ const axis: Axis = AXIS[placement] || 'right';
256
+ const crossAxis: Axis = CROSS_AXIS[axis];
257
+
258
+ let resolvedCrossPlacement: PlacementAxis | 'center' = 'center';
259
+ if (AXIS[crossPlacement]) {
260
+ resolvedCrossPlacement = crossPlacement as PlacementAxis;
261
+ }
262
+
263
+ const size = AXIS_SIZE[axis];
264
+ const crossSize = AXIS_SIZE[crossAxis];
265
+ PARSED_PLACEMENT_CACHE[input] = {
266
+ placement,
267
+ crossPlacement: resolvedCrossPlacement,
268
+ axis,
269
+ crossAxis,
270
+ size,
271
+ crossSize,
272
+ };
273
+ return PARSED_PLACEMENT_CACHE[input];
274
+ }
275
+
276
+ function computePosition(
277
+ childOffset: Offset,
278
+ _boundaryDimensions: Dimensions,
279
+ overlaySize: Offset,
280
+ placementInfo: ParsedPlacement,
281
+ offset: number,
282
+ crossOffset: number,
283
+ _containerOffsetWithBoundary: Offset,
284
+ isContainerPositioned: boolean,
285
+ arrowSize: number,
286
+ arrowBoundaryOffset: number,
287
+ containerDimensions: Dimensions
288
+ ): Position {
289
+ const { placement, crossPlacement, axis, crossAxis, size, crossSize } = placementInfo;
290
+ const position: Position = {};
291
+
292
+ position[crossAxis] = childOffset[crossAxis] ?? 0;
293
+ if (crossPlacement === 'center') {
294
+ position[crossAxis]! += ((childOffset[crossSize] ?? 0) - (overlaySize[crossSize] ?? 0)) / 2;
295
+ } else if (crossPlacement !== crossAxis) {
296
+ position[crossAxis]! += (childOffset[crossSize] ?? 0) - (overlaySize[crossSize] ?? 0);
297
+ }
298
+
299
+ position[crossAxis]! += crossOffset;
300
+
301
+ const minPosition =
302
+ childOffset[crossAxis] - overlaySize[crossSize] + arrowSize + arrowBoundaryOffset;
303
+ const maxPosition =
304
+ childOffset[crossAxis] + childOffset[crossSize] - arrowSize - arrowBoundaryOffset;
305
+ position[crossAxis] = clamp(position[crossAxis]!, minPosition, maxPosition);
306
+
307
+ if (placement === axis) {
308
+ const containerHeight = isContainerPositioned
309
+ ? containerDimensions[size]
310
+ : (containerDimensions as any)[TOTAL_SIZE[size]];
311
+ position[FLIPPED_DIRECTION[axis] as keyof Position] = Math.floor(
312
+ containerHeight - childOffset[axis] + offset
313
+ );
314
+ } else {
315
+ position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
316
+ }
317
+ return position;
318
+ }
319
+
320
+ function getMaxHeight(
321
+ position: Position,
322
+ boundaryDimensions: Dimensions,
323
+ containerOffsetWithBoundary: Offset,
324
+ _isContainerPositioned: boolean,
325
+ margins: Position,
326
+ padding: number,
327
+ overlayHeight: number,
328
+ heightGrowthDirection: HeightGrowthDirection,
329
+ containerDimensions: Dimensions,
330
+ isContainerDescendentOfBoundary: boolean,
331
+ visualViewport: VisualViewport | null
332
+ ): number {
333
+ const overlayTop =
334
+ (position.top != null
335
+ ? position.top
336
+ : (containerDimensions as any)[TOTAL_SIZE.height] -
337
+ (position.bottom ?? 0) -
338
+ overlayHeight) - (containerDimensions.scroll.top ?? 0);
339
+
340
+ const boundaryToContainerTransformOffset = isContainerDescendentOfBoundary
341
+ ? containerOffsetWithBoundary.top
342
+ : 0;
343
+ const boundingRect = {
344
+ top: Math.max(
345
+ boundaryDimensions.top + boundaryToContainerTransformOffset,
346
+ (visualViewport?.offsetTop ?? boundaryDimensions.top) + boundaryToContainerTransformOffset
347
+ ),
348
+ bottom: Math.min(
349
+ boundaryDimensions.top + boundaryDimensions.height + boundaryToContainerTransformOffset,
350
+ (visualViewport?.offsetTop ?? 0) + (visualViewport?.height ?? 0)
351
+ ),
352
+ };
353
+
354
+ const maxHeight =
355
+ heightGrowthDirection !== 'top'
356
+ ? Math.max(
357
+ 0,
358
+ boundingRect.bottom -
359
+ overlayTop -
360
+ ((margins.top ?? 0) + (margins.bottom ?? 0) + padding)
361
+ )
362
+ : Math.max(
363
+ 0,
364
+ overlayTop +
365
+ overlayHeight -
366
+ boundingRect.top -
367
+ ((margins.top ?? 0) + (margins.bottom ?? 0) + padding)
368
+ );
369
+ return maxHeight;
370
+ }
371
+
372
+ function getAvailableSpace(
373
+ boundaryDimensions: Dimensions,
374
+ containerOffsetWithBoundary: Offset,
375
+ childOffset: Offset,
376
+ margins: Position,
377
+ padding: number,
378
+ placementInfo: ParsedPlacement,
379
+ containerDimensions: Dimensions,
380
+ isContainerDescendentOfBoundary: boolean
381
+ ): number {
382
+ const { placement, axis, size } = placementInfo;
383
+ if (placement === axis) {
384
+ return Math.max(
385
+ 0,
386
+ childOffset[axis] -
387
+ (containerDimensions.scroll[axis] ?? 0) -
388
+ (boundaryDimensions[axis] +
389
+ (isContainerDescendentOfBoundary ? containerOffsetWithBoundary[axis] : 0)) -
390
+ (margins[axis] ?? 0) -
391
+ (margins[FLIPPED_DIRECTION[axis] as keyof Position] ?? 0) -
392
+ padding
393
+ );
394
+ }
395
+
396
+ return Math.max(
397
+ 0,
398
+ boundaryDimensions[size] +
399
+ boundaryDimensions[axis] +
400
+ (isContainerDescendentOfBoundary ? containerOffsetWithBoundary[axis] : 0) -
401
+ childOffset[axis] -
402
+ childOffset[size] +
403
+ (containerDimensions.scroll[axis] ?? 0) -
404
+ (margins[axis] ?? 0) -
405
+ (margins[FLIPPED_DIRECTION[axis] as keyof Position] ?? 0) -
406
+ padding
407
+ );
408
+ }
409
+
410
+ export function calculatePositionInternal(
411
+ placementInput: Placement,
412
+ childOffset: Offset,
413
+ overlaySize: Offset,
414
+ _scrollSize: Offset,
415
+ margins: Position,
416
+ padding: number,
417
+ flip: boolean,
418
+ boundaryDimensions: Dimensions,
419
+ containerDimensions: Dimensions,
420
+ containerOffsetWithBoundary: Offset,
421
+ offset: number,
422
+ crossOffset: number,
423
+ isContainerPositioned: boolean,
424
+ userSetMaxHeight: number | undefined,
425
+ arrowSize: number,
426
+ arrowBoundaryOffset: number,
427
+ isContainerDescendentOfBoundary: boolean,
428
+ visualViewport: VisualViewport | null
429
+ ): PositionResult {
430
+ let placementInfo = parsePlacement(placementInput);
431
+ let { size, crossAxis, crossSize, placement, crossPlacement } = placementInfo;
432
+ let position = computePosition(
433
+ childOffset,
434
+ boundaryDimensions,
435
+ overlaySize,
436
+ placementInfo,
437
+ offset,
438
+ crossOffset,
439
+ containerOffsetWithBoundary,
440
+ isContainerPositioned,
441
+ arrowSize,
442
+ arrowBoundaryOffset,
443
+ containerDimensions
444
+ );
445
+ let normalizedOffset = offset;
446
+ const space = getAvailableSpace(
447
+ boundaryDimensions,
448
+ containerOffsetWithBoundary,
449
+ childOffset,
450
+ margins,
451
+ padding + offset,
452
+ placementInfo,
453
+ containerDimensions,
454
+ isContainerDescendentOfBoundary
455
+ );
456
+
457
+ if (flip && overlaySize[size] > space) {
458
+ const flippedPlacementInfo = parsePlacement(
459
+ `${FLIPPED_DIRECTION[placement]} ${crossPlacement}` as Placement
460
+ );
461
+ const flippedPosition = computePosition(
462
+ childOffset,
463
+ boundaryDimensions,
464
+ overlaySize,
465
+ flippedPlacementInfo,
466
+ offset,
467
+ crossOffset,
468
+ containerOffsetWithBoundary,
469
+ isContainerPositioned,
470
+ arrowSize,
471
+ arrowBoundaryOffset,
472
+ containerDimensions
473
+ );
474
+
475
+ const flippedSpace = getAvailableSpace(
476
+ boundaryDimensions,
477
+ containerOffsetWithBoundary,
478
+ childOffset,
479
+ margins,
480
+ padding + offset,
481
+ flippedPlacementInfo,
482
+ containerDimensions,
483
+ isContainerDescendentOfBoundary
484
+ );
485
+
486
+ if (flippedSpace > space) {
487
+ placementInfo = flippedPlacementInfo;
488
+ position = flippedPosition;
489
+ normalizedOffset = offset;
490
+ }
491
+ }
492
+
493
+ let heightGrowthDirection: HeightGrowthDirection = 'bottom';
494
+ if (placementInfo.axis === 'top') {
495
+ if (placementInfo.placement === 'top') {
496
+ heightGrowthDirection = 'top';
497
+ } else if (placementInfo.placement === 'bottom') {
498
+ heightGrowthDirection = 'bottom';
499
+ }
500
+ } else if (placementInfo.crossAxis === 'top') {
501
+ if (placementInfo.crossPlacement === 'top') {
502
+ heightGrowthDirection = 'bottom';
503
+ } else if (placementInfo.crossPlacement === 'bottom') {
504
+ heightGrowthDirection = 'top';
505
+ }
506
+ }
507
+
508
+ let delta = getDelta(
509
+ crossAxis,
510
+ position[crossAxis]!,
511
+ overlaySize[crossSize],
512
+ boundaryDimensions,
513
+ containerDimensions,
514
+ padding,
515
+ containerOffsetWithBoundary
516
+ );
517
+ position[crossAxis]! += delta;
518
+
519
+ let maxHeight = getMaxHeight(
520
+ position,
521
+ boundaryDimensions,
522
+ containerOffsetWithBoundary,
523
+ isContainerPositioned,
524
+ margins,
525
+ padding,
526
+ overlaySize.height,
527
+ heightGrowthDirection,
528
+ containerDimensions,
529
+ isContainerDescendentOfBoundary,
530
+ visualViewport
531
+ );
532
+
533
+ if (userSetMaxHeight && userSetMaxHeight < maxHeight) {
534
+ maxHeight = userSetMaxHeight;
535
+ }
536
+
537
+ overlaySize.height = Math.min(overlaySize.height, maxHeight);
538
+
539
+ position = computePosition(
540
+ childOffset,
541
+ boundaryDimensions,
542
+ overlaySize,
543
+ placementInfo,
544
+ normalizedOffset,
545
+ crossOffset,
546
+ containerOffsetWithBoundary,
547
+ isContainerPositioned,
548
+ arrowSize,
549
+ arrowBoundaryOffset,
550
+ containerDimensions
551
+ );
552
+ delta = getDelta(
553
+ crossAxis,
554
+ position[crossAxis]!,
555
+ overlaySize[crossSize],
556
+ boundaryDimensions,
557
+ containerDimensions,
558
+ padding,
559
+ containerOffsetWithBoundary
560
+ );
561
+ position[crossAxis]! += delta;
562
+
563
+ const arrowPosition: Position = {};
564
+
565
+ ({ placement, crossPlacement } = placementInfo);
566
+ let origin = childOffset[crossAxis] - position[crossAxis]! - (margins[AXIS[crossAxis]] ?? 0);
567
+ let preferredArrowPosition = origin + 0.5 * childOffset[crossSize];
568
+
569
+ const arrowMinPosition = arrowSize / 2 + arrowBoundaryOffset;
570
+ const overlayMargin =
571
+ AXIS[crossAxis] === 'left'
572
+ ? (margins.left ?? 0) + (margins.right ?? 0)
573
+ : (margins.top ?? 0) + (margins.bottom ?? 0);
574
+ const arrowMaxPosition =
575
+ overlaySize[crossSize] - overlayMargin - arrowSize / 2 - arrowBoundaryOffset;
576
+
577
+ const arrowOverlappingChildMinEdge =
578
+ childOffset[crossAxis] +
579
+ arrowSize / 2 -
580
+ (position[crossAxis]! + (margins[AXIS[crossAxis]] ?? 0));
581
+ const arrowOverlappingChildMaxEdge =
582
+ childOffset[crossAxis] +
583
+ childOffset[crossSize] -
584
+ arrowSize / 2 -
585
+ (position[crossAxis]! + (margins[AXIS[crossAxis]] ?? 0));
586
+
587
+ const arrowPositionOverlappingChild = clamp(
588
+ preferredArrowPosition,
589
+ arrowOverlappingChildMinEdge,
590
+ arrowOverlappingChildMaxEdge
591
+ );
592
+ arrowPosition[crossAxis] = clamp(arrowPositionOverlappingChild, arrowMinPosition, arrowMaxPosition);
593
+
594
+ if (arrowSize) {
595
+ origin = arrowPosition[crossAxis]!;
596
+ } else if (crossPlacement === 'right' || crossPlacement === 'bottom') {
597
+ origin += childOffset[crossSize];
598
+ } else if (crossPlacement === 'center') {
599
+ origin += childOffset[crossSize] / 2;
600
+ }
601
+
602
+ const crossOrigin = placement === 'left' || placement === 'top' ? overlaySize[size] : 0;
603
+ const triggerAnchorPoint = {
604
+ x: placement === 'top' || placement === 'bottom' ? origin : crossOrigin,
605
+ y: placement === 'left' || placement === 'right' ? origin : crossOrigin,
606
+ };
607
+
608
+ return {
609
+ position,
610
+ maxHeight: maxHeight,
611
+ arrowOffsetLeft: arrowPosition.left,
612
+ arrowOffsetTop: arrowPosition.top,
613
+ placement,
614
+ triggerAnchorPoint,
615
+ };
616
+ }
617
+
618
+ export function getRect(node: Element, ignoreScale: boolean) {
619
+ const { top, left, width: bWidth, height: bHeight } = node.getBoundingClientRect();
620
+ let width = bWidth;
621
+ let height = bHeight;
622
+
623
+ if (ignoreScale && node instanceof (node.ownerDocument.defaultView as any).HTMLElement) {
624
+ width = (node as HTMLElement).offsetWidth;
625
+ height = (node as HTMLElement).offsetHeight;
626
+ }
627
+
628
+ return { top, left, width, height };
629
+ }
630
+
631
+ function getElementOffset(node: Element, ignoreScale: boolean): Offset {
632
+ const { top, left, width, height } = getRect(node, ignoreScale);
633
+ const { scrollTop, scrollLeft, clientTop, clientLeft } = document.documentElement;
634
+ return {
635
+ top: top + scrollTop - clientTop,
636
+ left: left + scrollLeft - clientLeft,
637
+ width,
638
+ height,
639
+ };
640
+ }
641
+
642
+ function getPosition(node: Element, parent: Element, ignoreScale: boolean): Offset {
643
+ const style = window.getComputedStyle(node);
644
+ let offset: Offset;
645
+ if (style.position === 'fixed') {
646
+ offset = getRect(node, ignoreScale);
647
+ } else {
648
+ offset = getElementOffset(node, ignoreScale);
649
+ const parentOffset = getElementOffset(parent, ignoreScale);
650
+ const parentStyle = window.getComputedStyle(parent);
651
+ parentOffset.top +=
652
+ (parseInt(parentStyle.borderTopWidth, 10) || 0) - (parent as HTMLElement).scrollTop;
653
+ parentOffset.left +=
654
+ (parseInt(parentStyle.borderLeftWidth, 10) || 0) - (parent as HTMLElement).scrollLeft;
655
+ offset.top -= parentOffset.top;
656
+ offset.left -= parentOffset.left;
657
+ }
658
+
659
+ offset.top -= parseInt(style.marginTop, 10) || 0;
660
+ offset.left -= parseInt(style.marginLeft, 10) || 0;
661
+ return offset;
662
+ }
663
+
664
+ function getContainingBlock(node: HTMLElement): Element {
665
+ let offsetParent = node.offsetParent;
666
+
667
+ if (
668
+ offsetParent &&
669
+ offsetParent === document.body &&
670
+ window.getComputedStyle(offsetParent).position === 'static' &&
671
+ !isContainingBlock(offsetParent)
672
+ ) {
673
+ offsetParent = document.documentElement;
674
+ }
675
+
676
+ if (offsetParent == null) {
677
+ offsetParent = node.parentElement;
678
+ while (offsetParent && !isContainingBlock(offsetParent)) {
679
+ offsetParent = offsetParent.parentElement;
680
+ }
681
+ }
682
+
683
+ return offsetParent || document.documentElement;
684
+ }
685
+
686
+ function isContainingBlock(node: Element): boolean {
687
+ const style = window.getComputedStyle(node);
688
+ return (
689
+ style.transform !== 'none' ||
690
+ /transform|perspective/.test(style.willChange) ||
691
+ style.filter !== 'none' ||
692
+ style.contain === 'paint' ||
693
+ ('backdropFilter' in style && (style as any).backdropFilter !== 'none') ||
694
+ ('WebkitBackdropFilter' in style && (style as any).WebkitBackdropFilter !== 'none')
695
+ );
696
+ }
697
+
698
+ /**
699
+ * Determines where to place the overlay with regards to the target and the position of an optional indicator.
700
+ */
701
+ export function calculatePosition(opts: PositionOpts): PositionResult {
702
+ const {
703
+ placement,
704
+ targetNode,
705
+ overlayNode,
706
+ scrollNode,
707
+ padding,
708
+ shouldFlip,
709
+ boundaryElement,
710
+ offset,
711
+ crossOffset,
712
+ maxHeight,
713
+ arrowSize = 0,
714
+ arrowBoundaryOffset = 0,
715
+ } = opts;
716
+
717
+ const visualViewport = getVisualViewport();
718
+ const container =
719
+ overlayNode instanceof HTMLElement
720
+ ? getContainingBlock(overlayNode)
721
+ : document.documentElement;
722
+ const isViewportContainer = container === document.documentElement;
723
+ const containerPositionStyle = window.getComputedStyle(container).position;
724
+ const isContainerPositioned = !!containerPositionStyle && containerPositionStyle !== 'static';
725
+ const childOffset: Offset = isViewportContainer
726
+ ? getElementOffset(targetNode, false)
727
+ : getPosition(targetNode, container, false);
728
+
729
+ if (!isViewportContainer) {
730
+ const { marginTop, marginLeft } = window.getComputedStyle(targetNode);
731
+ childOffset.top += parseInt(marginTop, 10) || 0;
732
+ childOffset.left += parseInt(marginLeft, 10) || 0;
733
+ }
734
+
735
+ const overlaySize: Offset = getElementOffset(overlayNode, true);
736
+ const margins = getMargins(overlayNode);
737
+ overlaySize.width += (margins.left ?? 0) + (margins.right ?? 0);
738
+ overlaySize.height += (margins.top ?? 0) + (margins.bottom ?? 0);
739
+
740
+ const scrollSize = getScroll(scrollNode);
741
+ const boundaryDimensions = getContainerDimensions(boundaryElement, visualViewport);
742
+ const containerDimensions = getContainerDimensions(container, visualViewport);
743
+ const containerOffsetWithBoundary: Offset = getPosition(boundaryElement, container, false);
744
+
745
+ const isContainerDescendentOfBoundary = boundaryElement.contains(container);
746
+ return calculatePositionInternal(
747
+ placement,
748
+ childOffset,
749
+ overlaySize,
750
+ scrollSize,
751
+ margins,
752
+ padding,
753
+ shouldFlip,
754
+ boundaryDimensions,
755
+ containerDimensions,
756
+ containerOffsetWithBoundary,
757
+ offset,
758
+ crossOffset,
759
+ isContainerPositioned,
760
+ maxHeight,
761
+ arrowSize,
762
+ arrowBoundaryOffset,
763
+ isContainerDescendentOfBoundary,
764
+ visualViewport
765
+ );
766
+ }