@zanichelli/albe-web-components 18.6.3 → 18.6.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 (189) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/cjs/{index-c48948bf.js → index-0d3de93e.js} +2 -2
  3. package/dist/cjs/{index-c48948bf.js.map → index-0d3de93e.js.map} +1 -1
  4. package/dist/cjs/index.cjs.js +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/{utils-93961cb6.js → utils-3dc316f8.js} +56 -1
  7. package/dist/cjs/utils-3dc316f8.js.map +1 -0
  8. package/dist/cjs/web-components-library.cjs.js +1 -1
  9. package/dist/cjs/z-anchor-navigation.cjs.entry.js +1 -1
  10. package/dist/cjs/z-anchor-navigation.cjs.entry.js.map +1 -1
  11. package/dist/cjs/z-app-header_12.cjs.entry.js +2 -2
  12. package/dist/cjs/z-app-header_12.cjs.entry.js.map +1 -1
  13. package/dist/cjs/z-book-card-deprecated.cjs.entry.js +1 -1
  14. package/dist/cjs/z-breadcrumb.cjs.entry.js +1 -1
  15. package/dist/cjs/z-card.cjs.entry.js +1 -1
  16. package/dist/cjs/z-card.cjs.entry.js.map +1 -1
  17. package/dist/cjs/z-combobox.cjs.entry.js +1 -1
  18. package/dist/cjs/z-menu.cjs.entry.js +1 -1
  19. package/dist/cjs/z-myz-card-info.cjs.entry.js +1 -1
  20. package/dist/cjs/z-myz-list-item.cjs.entry.js +1 -1
  21. package/dist/cjs/z-popover.cjs.entry.js +232 -264
  22. package/dist/cjs/z-popover.cjs.entry.js.map +1 -1
  23. package/dist/cjs/z-select.cjs.entry.js +5 -7
  24. package/dist/cjs/z-select.cjs.entry.js.map +1 -1
  25. package/dist/cjs/z-skip-to-content.cjs.entry.js +1 -1
  26. package/dist/cjs/z-slideshow.cjs.entry.js +1 -1
  27. package/dist/cjs/z-table.cjs.entry.js +2 -2
  28. package/dist/cjs/z-toggle-switch.cjs.entry.js +1 -1
  29. package/dist/cjs/z-tr.cjs.entry.js +2 -2
  30. package/dist/collection/components/list/z-list-element/styles.css +2 -4
  31. package/dist/collection/components/z-anchor-navigation/index.js +1 -1
  32. package/dist/collection/components/z-anchor-navigation/index.js.map +1 -1
  33. package/dist/collection/components/z-card/styles.css +4 -0
  34. package/dist/collection/components/z-popover/index.js +236 -268
  35. package/dist/collection/components/z-popover/index.js.map +1 -1
  36. package/dist/collection/components/z-popover/index.stories.js +92 -45
  37. package/dist/collection/components/z-popover/index.stories.js.map +1 -1
  38. package/dist/collection/components/z-popover/styles.css +4 -14
  39. package/dist/collection/components/z-select/index.js +4 -6
  40. package/dist/collection/components/z-select/index.js.map +1 -1
  41. package/dist/collection/components/z-select/styles.css +2 -6
  42. package/dist/collection/utils/utils.js +53 -0
  43. package/dist/collection/utils/utils.js.map +1 -1
  44. package/dist/components/index14.js +1 -1
  45. package/dist/components/index14.js.map +1 -1
  46. package/dist/components/index23.js +234 -266
  47. package/dist/components/index23.js.map +1 -1
  48. package/dist/components/index24.js +1 -1
  49. package/dist/components/utils.js +55 -2
  50. package/dist/components/utils.js.map +1 -1
  51. package/dist/components/z-anchor-navigation.js +1 -1
  52. package/dist/components/z-anchor-navigation.js.map +1 -1
  53. package/dist/components/z-card.js +1 -1
  54. package/dist/components/z-card.js.map +1 -1
  55. package/dist/components/z-select.js +5 -7
  56. package/dist/components/z-select.js.map +1 -1
  57. package/dist/esm/{index-10473b87.js → index-328b69a7.js} +2 -2
  58. package/dist/esm/{index-10473b87.js.map → index-328b69a7.js.map} +1 -1
  59. package/dist/esm/index.js +1 -1
  60. package/dist/esm/loader.js +1 -1
  61. package/dist/esm/{utils-c8abef2f.js → utils-6e2be2b6.js} +55 -2
  62. package/dist/esm/utils-6e2be2b6.js.map +1 -0
  63. package/dist/esm/web-components-library.js +1 -1
  64. package/dist/esm/z-anchor-navigation.entry.js +1 -1
  65. package/dist/esm/z-anchor-navigation.entry.js.map +1 -1
  66. package/dist/esm/z-app-header_12.entry.js +2 -2
  67. package/dist/esm/z-app-header_12.entry.js.map +1 -1
  68. package/dist/esm/z-book-card-deprecated.entry.js +1 -1
  69. package/dist/esm/z-breadcrumb.entry.js +1 -1
  70. package/dist/esm/z-card.entry.js +1 -1
  71. package/dist/esm/z-card.entry.js.map +1 -1
  72. package/dist/esm/z-combobox.entry.js +1 -1
  73. package/dist/esm/z-menu.entry.js +1 -1
  74. package/dist/esm/z-myz-card-info.entry.js +1 -1
  75. package/dist/esm/z-myz-list-item.entry.js +1 -1
  76. package/dist/esm/z-popover.entry.js +233 -265
  77. package/dist/esm/z-popover.entry.js.map +1 -1
  78. package/dist/esm/z-select.entry.js +5 -7
  79. package/dist/esm/z-select.entry.js.map +1 -1
  80. package/dist/esm/z-skip-to-content.entry.js +1 -1
  81. package/dist/esm/z-slideshow.entry.js +1 -1
  82. package/dist/esm/z-table.entry.js +2 -2
  83. package/dist/esm/z-toggle-switch.entry.js +1 -1
  84. package/dist/esm/z-tr.entry.js +2 -2
  85. package/dist/types/components/z-popover/index.d.ts +47 -45
  86. package/dist/types/components/z-popover/index.stories.d.ts +18 -7
  87. package/dist/types/components.d.ts +13 -17
  88. package/dist/types/utils/utils.d.ts +17 -0
  89. package/dist/web-components-library/index.esm.js +1 -1
  90. package/dist/web-components-library/{p-8b93bc6d.entry.js → p-01302e57.entry.js} +2 -2
  91. package/dist/web-components-library/{p-14f0bdf4.entry.js → p-1ad8810a.entry.js} +2 -2
  92. package/{www/build/p-c2ba8a6c.entry.js → dist/web-components-library/p-2e0923bd.entry.js} +2 -2
  93. package/dist/web-components-library/p-3284e37b.entry.js +2 -0
  94. package/dist/web-components-library/{p-61f76cab.js → p-43bc482a.js} +2 -2
  95. package/{www/build/p-2fb52cd0.entry.js → dist/web-components-library/p-539f99db.entry.js} +2 -2
  96. package/dist/web-components-library/p-625e2cee.js +2 -0
  97. package/dist/web-components-library/p-625e2cee.js.map +1 -0
  98. package/dist/web-components-library/p-62e1d867.entry.js +2 -0
  99. package/dist/web-components-library/p-62e1d867.entry.js.map +1 -0
  100. package/dist/web-components-library/p-63d220da.entry.js +2 -0
  101. package/dist/web-components-library/{p-8d5e3396.entry.js.map → p-63d220da.entry.js.map} +1 -1
  102. package/dist/web-components-library/{p-25935be3.entry.js → p-6d0fa7c1.entry.js} +2 -2
  103. package/dist/web-components-library/{p-25935be3.entry.js.map → p-6d0fa7c1.entry.js.map} +1 -1
  104. package/dist/web-components-library/{p-c8814ae1.entry.js → p-7916e0f7.entry.js} +2 -2
  105. package/{www/build/p-f5efb3fc.entry.js → dist/web-components-library/p-8bd4a2aa.entry.js} +2 -2
  106. package/dist/web-components-library/{p-c962e854.entry.js → p-8dec332e.entry.js} +2 -2
  107. package/dist/web-components-library/{p-72a7eb26.entry.js → p-966cbf03.entry.js} +2 -2
  108. package/{www/build/p-30575221.entry.js → dist/web-components-library/p-a0ed0c63.entry.js} +2 -2
  109. package/{www/build/p-e41442e0.entry.js → dist/web-components-library/p-b7b972c0.entry.js} +2 -2
  110. package/{www/build/p-e41442e0.entry.js.map → dist/web-components-library/p-b7b972c0.entry.js.map} +1 -1
  111. package/dist/web-components-library/p-b96ca9a0.entry.js +2 -0
  112. package/dist/web-components-library/p-b96ca9a0.entry.js.map +1 -0
  113. package/dist/web-components-library/{p-57b8bd19.entry.js → p-db9b7eb5.entry.js} +2 -2
  114. package/dist/web-components-library/p-db9b7eb5.entry.js.map +1 -0
  115. package/dist/web-components-library/web-components-library.esm.js +1 -1
  116. package/dist/web-components-library/web-components-library.esm.js.map +1 -1
  117. package/package.json +1 -1
  118. package/www/build/index.esm.js +1 -1
  119. package/www/build/{p-8b93bc6d.entry.js → p-01302e57.entry.js} +2 -2
  120. package/www/build/{p-14f0bdf4.entry.js → p-1ad8810a.entry.js} +2 -2
  121. package/{dist/web-components-library/p-c2ba8a6c.entry.js → www/build/p-2e0923bd.entry.js} +2 -2
  122. package/www/build/p-3284e37b.entry.js +2 -0
  123. package/www/build/{p-61f76cab.js → p-43bc482a.js} +2 -2
  124. package/{dist/web-components-library/p-2fb52cd0.entry.js → www/build/p-539f99db.entry.js} +2 -2
  125. package/www/build/p-625e2cee.js +2 -0
  126. package/www/build/p-625e2cee.js.map +1 -0
  127. package/www/build/p-62e1d867.entry.js +2 -0
  128. package/www/build/p-62e1d867.entry.js.map +1 -0
  129. package/www/build/p-63d220da.entry.js +2 -0
  130. package/www/build/{p-8d5e3396.entry.js.map → p-63d220da.entry.js.map} +1 -1
  131. package/www/build/{p-2870add3.js → p-6c6208e6.js} +1 -1
  132. package/www/build/{p-25935be3.entry.js → p-6d0fa7c1.entry.js} +2 -2
  133. package/www/build/{p-25935be3.entry.js.map → p-6d0fa7c1.entry.js.map} +1 -1
  134. package/www/build/{p-c8814ae1.entry.js → p-7916e0f7.entry.js} +2 -2
  135. package/{dist/web-components-library/p-f5efb3fc.entry.js → www/build/p-8bd4a2aa.entry.js} +2 -2
  136. package/www/build/{p-c962e854.entry.js → p-8dec332e.entry.js} +2 -2
  137. package/www/build/{p-72a7eb26.entry.js → p-966cbf03.entry.js} +2 -2
  138. package/{dist/web-components-library/p-30575221.entry.js → www/build/p-a0ed0c63.entry.js} +2 -2
  139. package/{dist/web-components-library/p-e41442e0.entry.js → www/build/p-b7b972c0.entry.js} +2 -2
  140. package/{dist/web-components-library/p-e41442e0.entry.js.map → www/build/p-b7b972c0.entry.js.map} +1 -1
  141. package/www/build/p-b96ca9a0.entry.js +2 -0
  142. package/www/build/p-b96ca9a0.entry.js.map +1 -0
  143. package/www/build/{p-57b8bd19.entry.js → p-db9b7eb5.entry.js} +2 -2
  144. package/www/build/p-db9b7eb5.entry.js.map +1 -0
  145. package/www/build/web-components-library.esm.js +1 -1
  146. package/www/build/web-components-library.esm.js.map +1 -1
  147. package/www/index.html +1 -1
  148. package/dist/cjs/utils-93961cb6.js.map +0 -1
  149. package/dist/esm/utils-c8abef2f.js.map +0 -1
  150. package/dist/web-components-library/p-37f271c8.entry.js +0 -2
  151. package/dist/web-components-library/p-37f271c8.entry.js.map +0 -1
  152. package/dist/web-components-library/p-57b8bd19.entry.js.map +0 -1
  153. package/dist/web-components-library/p-69a1a67a.entry.js +0 -2
  154. package/dist/web-components-library/p-8d5e3396.entry.js +0 -2
  155. package/dist/web-components-library/p-a06fbbc0.js +0 -2
  156. package/dist/web-components-library/p-a06fbbc0.js.map +0 -1
  157. package/dist/web-components-library/p-da30a6cb.entry.js +0 -2
  158. package/dist/web-components-library/p-da30a6cb.entry.js.map +0 -1
  159. package/www/build/p-37f271c8.entry.js +0 -2
  160. package/www/build/p-37f271c8.entry.js.map +0 -1
  161. package/www/build/p-57b8bd19.entry.js.map +0 -1
  162. package/www/build/p-69a1a67a.entry.js +0 -2
  163. package/www/build/p-8d5e3396.entry.js +0 -2
  164. package/www/build/p-a06fbbc0.js +0 -2
  165. package/www/build/p-a06fbbc0.js.map +0 -1
  166. package/www/build/p-da30a6cb.entry.js +0 -2
  167. package/www/build/p-da30a6cb.entry.js.map +0 -1
  168. /package/dist/web-components-library/{p-8b93bc6d.entry.js.map → p-01302e57.entry.js.map} +0 -0
  169. /package/dist/web-components-library/{p-14f0bdf4.entry.js.map → p-1ad8810a.entry.js.map} +0 -0
  170. /package/dist/web-components-library/{p-c2ba8a6c.entry.js.map → p-2e0923bd.entry.js.map} +0 -0
  171. /package/dist/web-components-library/{p-69a1a67a.entry.js.map → p-3284e37b.entry.js.map} +0 -0
  172. /package/dist/web-components-library/{p-61f76cab.js.map → p-43bc482a.js.map} +0 -0
  173. /package/dist/web-components-library/{p-2fb52cd0.entry.js.map → p-539f99db.entry.js.map} +0 -0
  174. /package/dist/web-components-library/{p-c8814ae1.entry.js.map → p-7916e0f7.entry.js.map} +0 -0
  175. /package/dist/web-components-library/{p-f5efb3fc.entry.js.map → p-8bd4a2aa.entry.js.map} +0 -0
  176. /package/dist/web-components-library/{p-c962e854.entry.js.map → p-8dec332e.entry.js.map} +0 -0
  177. /package/dist/web-components-library/{p-72a7eb26.entry.js.map → p-966cbf03.entry.js.map} +0 -0
  178. /package/dist/web-components-library/{p-30575221.entry.js.map → p-a0ed0c63.entry.js.map} +0 -0
  179. /package/www/build/{p-8b93bc6d.entry.js.map → p-01302e57.entry.js.map} +0 -0
  180. /package/www/build/{p-14f0bdf4.entry.js.map → p-1ad8810a.entry.js.map} +0 -0
  181. /package/www/build/{p-c2ba8a6c.entry.js.map → p-2e0923bd.entry.js.map} +0 -0
  182. /package/www/build/{p-69a1a67a.entry.js.map → p-3284e37b.entry.js.map} +0 -0
  183. /package/www/build/{p-61f76cab.js.map → p-43bc482a.js.map} +0 -0
  184. /package/www/build/{p-2fb52cd0.entry.js.map → p-539f99db.entry.js.map} +0 -0
  185. /package/www/build/{p-c8814ae1.entry.js.map → p-7916e0f7.entry.js.map} +0 -0
  186. /package/www/build/{p-f5efb3fc.entry.js.map → p-8bd4a2aa.entry.js.map} +0 -0
  187. /package/www/build/{p-c962e854.entry.js.map → p-8dec332e.entry.js.map} +0 -0
  188. /package/www/build/{p-72a7eb26.entry.js.map → p-966cbf03.entry.js.map} +0 -0
  189. /package/www/build/{p-30575221.entry.js.map → p-a0ed0c63.entry.js.map} +0 -0
@@ -1,98 +1,13 @@
1
1
  import { Host, h } from "@stencil/core";
2
- import { KeyboardCode, PopoverPosition } from "../../beans";
3
- const DOCUMENT_ELEMENT = document.documentElement;
4
- function getParentElement(element) {
5
- if (element.parentNode === element.shadowRoot) {
6
- return element.shadowRoot.host;
7
- }
8
- return element.parentElement;
9
- }
10
- /**
11
- * Find the closest scrollable parent of a node.
12
- *
13
- * @param {Element} element The node
14
- */
15
- function findScrollableParent(element) {
16
- let parent = getParentElement(element);
17
- while (parent && parent !== DOCUMENT_ELEMENT) {
18
- const style = window.getComputedStyle(parent);
19
- const { overflow, overflowX, overflowY } = style;
20
- // Check for hidden overflow first (early return)
21
- if (overflow === "hidden" || overflowY === "hidden" || overflowX === "hidden") {
22
- return parent;
23
- }
24
- // Only check scrollable if overflow is not visible
25
- const isOverflowNotVisible = overflow !== "visible";
26
- const isOverflowYNotVisible = overflowY !== "visible";
27
- const isOverflowXNotVisible = overflowX !== "visible";
28
- if ((parent.scrollHeight > parent.clientHeight && isOverflowNotVisible && isOverflowYNotVisible) ||
29
- (parent.scrollWidth > parent.clientWidth && isOverflowNotVisible && isOverflowXNotVisible)) {
30
- return parent;
31
- }
32
- parent = getParentElement(parent);
33
- }
34
- return DOCUMENT_ELEMENT;
35
- }
36
- /**
37
- * Calculate computed offset.
38
- * It includes matrix transformations.
39
- * @param element The target element.
40
- * @param targetParentOffset The relative offset parent.
41
- */
42
- function computeOffset(element, targetParentOffset) {
43
- const rect = element.getBoundingClientRect();
44
- const { width, height } = rect;
45
- let top = 0;
46
- let left = 0;
47
- let offsetParent = element;
48
- while (offsetParent && offsetParent !== targetParentOffset) {
49
- left += offsetParent.offsetLeft;
50
- // document.body sometimes has offsetTop == 0 but still has an offset because of children margins!
51
- if (offsetParent === document.body) {
52
- top += offsetParent.getBoundingClientRect().top + window.scrollY;
53
- }
54
- else {
55
- top += offsetParent.offsetTop;
56
- }
57
- // Handle CSS transforms only when DOMMatrix is available
58
- if (window.DOMMatrix) {
59
- const style = window.getComputedStyle(offsetParent);
60
- const { transform } = style;
61
- if (transform && transform !== "none") {
62
- const domMatrix = new DOMMatrix(transform);
63
- left += domMatrix.m41;
64
- if (offsetParent !== document.body) {
65
- top += domMatrix.m42;
66
- }
67
- }
68
- }
69
- if (!offsetParent.offsetParent) {
70
- break;
71
- }
72
- offsetParent = offsetParent.offsetParent;
73
- }
74
- let parentWidth;
75
- let parentHeight;
76
- if (offsetParent === document.body) {
77
- parentWidth = window.innerWidth;
78
- parentHeight = window.innerHeight;
79
- }
80
- else {
81
- parentWidth = offsetParent.offsetWidth;
82
- parentHeight = offsetParent.offsetHeight;
83
- }
84
- const right = parentWidth - left - width;
85
- const bottom = parentHeight - top - height;
86
- return { top, right, bottom, left, width, height };
87
- }
2
+ import { Device, KeyboardCode, PopoverPosition } from "../../beans";
3
+ import { containsElement, findScrollableParent, getDevice, isElementVisibleInContainer } from "../../utils/utils";
88
4
  /**
89
5
  * Popover component.
90
- * This component displays a popover that can be bound to an element.
91
- * It supports various positions and can automatically adjust its position based on available space.
6
+ * This component displays a popover bound to an element.
7
+ * It supports various positions and can automatically adjust it based on available space, accounting for scrollable containers.
92
8
  *
93
9
  * Notes:
94
- * - To ensure the positioning algorithm finds the right container when calculating the position, set its container's `position` to `relative`.
95
- * - Consider manually adjusting the size of the slotted element (using `max-width`, `max-height`, etc...) when its content is "fluid" (like a big text), because it can interfere with the position calculation (for example a long text on one single line can be bigger than the available space, letting the algorithm think that the popover doesn't fit in the available space).
10
+ * - If positioning has an odd behavior, consider manually adjusting the size of the slotted elements (using `width`, `height`, `max-width`, `max-height`, etc...) when its content is "fluid" (like text), because it can interfere with the position calculation (for example a long text on one single line can be bigger than the available space, letting the algorithm think the popover doesn't fits).
96
11
  *
97
12
  * @cssprop --z-popover-theme--surface - background color of the popover.
98
13
  * @cssprop --z-popover-theme--text - foreground color of the popover.
@@ -101,7 +16,8 @@ function computeOffset(element, targetParentOffset) {
101
16
  */
102
17
  export class ZPopover {
103
18
  constructor() {
104
- this.spaceTolerance = 3; // 3px tolerance for space calculations
19
+ /** space tolerance for space calculations */
20
+ this.spaceTolerance = 3;
105
21
  this.position = PopoverPosition.TOP;
106
22
  this.open = false;
107
23
  this.bindTo = undefined;
@@ -119,71 +35,97 @@ export class ZPopover {
119
35
  * Close the popover when clicking outside of its content.
120
36
  * Stop event propagation if the click was fired by popover's trigger element,
121
37
  * to prevent close and reopen glitches.
122
- * @param {MouseEvent} e
123
38
  */
124
39
  handleOutsideClick(e) {
125
- if (!this.closable || !this.open) {
40
+ const target = e.target;
41
+ if (!this.closable || !this.open || containsElement(this.host, target)) {
126
42
  return;
127
43
  }
128
- const eventPath = e.composedPath();
129
- if (!eventPath.includes(this.host)) {
130
- const target = e.target;
131
- let triggerElemClicked = false;
132
- if (typeof this.bindTo === "string") {
133
- triggerElemClicked = !!target.closest(this.bindTo);
134
- }
135
- else if (this.bindTo) {
136
- triggerElemClicked = this.bindTo.contains(target);
137
- }
138
- if (triggerElemClicked) {
139
- // stop propagation if the click was on the trigger element to prevent close and reopen glitches
140
- e.stopPropagation();
141
- }
142
- this.open = false;
143
- this.positionChange.emit({ position: this.currentPosition });
44
+ if (containsElement(this.boundElement, target)) {
45
+ // stop propagation if the click was on the trigger element to prevent close and reopen glitches
46
+ e.stopPropagation();
144
47
  }
48
+ this.open = false;
145
49
  }
146
50
  validatePosition(newValue) {
147
51
  if (!Object.values(PopoverPosition).includes(newValue) || newValue === PopoverPosition.AUTO) {
148
52
  newValue = PopoverPosition.TOP;
53
+ this.position = newValue;
149
54
  }
150
- this.position = newValue;
151
55
  this.currentPosition = newValue;
152
- this.positionChange.emit({ position: this.currentPosition });
153
- this.setPosition();
56
+ if (this.open) {
57
+ this.setPosition();
58
+ }
154
59
  }
155
- /**
156
- * Setup popover behaviors on opening.
157
- */
60
+ /** Setup popover behaviors when `open` changes. */
158
61
  onOpen() {
159
62
  cancelAnimationFrame(this.animationFrameRequestId);
160
- if (this.open) {
161
- const setPosition = () => {
162
- if (this.open) {
163
- this.setPosition();
164
- this.animationFrameRequestId = requestAnimationFrame(setPosition);
165
- }
166
- };
167
- // call `setPosition` after a tick to ensure the DOM is ready and sizes are available
168
- setTimeout(() => {
169
- setPosition();
170
- }, 0);
171
- }
172
63
  this.openChange.emit({ open: this.open });
64
+ if (!this.open) {
65
+ return;
66
+ }
67
+ const updatePositionLoop = () => {
68
+ if (!this.open) {
69
+ return;
70
+ }
71
+ this.setPosition();
72
+ this.animationFrameRequestId = requestAnimationFrame(updatePositionLoop);
73
+ };
74
+ // call `setPosition` after a tick to ensure the DOM is ready and sizes are available
75
+ setTimeout(() => {
76
+ updatePositionLoop();
77
+ }, 0);
78
+ }
79
+ onBindingChange() {
80
+ this.findBoundElement();
81
+ }
82
+ /** Returns the offset modifier to use in calculations to align the popover with the bound element. */
83
+ get offsetModifier() {
84
+ return this.center ? 0.5 : 0;
85
+ }
86
+ findBoundElement() {
87
+ if (typeof this.bindTo === "string") {
88
+ this.boundElement = this.host.ownerDocument.querySelector(this.bindTo);
89
+ }
90
+ else if (this.bindTo) {
91
+ this.boundElement = this.bindTo;
92
+ }
93
+ else {
94
+ this.boundElement = this.host.parentElement;
95
+ }
173
96
  }
174
97
  /**
175
- * Helper functions for space calculation
98
+ * Check if element has enough space to the right and left to be centered.
99
+ * Used for `TOP` and `BOTTOM` position.
100
+ * When `center` is not enabled, only one side needs to be checked and `RIGHT` is the default.
176
101
  */
177
- hasCenteredHorizontalSpace(availableLeft, availableRight, hostWidth, boundWidth, offsetModifier) {
178
- const requiredSpace = (hostWidth - boundWidth) * (1 - offsetModifier);
179
- return (availableLeft >= requiredSpace - this.spaceTolerance && availableRight >= requiredSpace - this.spaceTolerance);
102
+ hasCenteredHorizontalSpace(availableLeft, availableRight, hostWidth, boundElementWidth) {
103
+ const requiredSideSpace = (hostWidth - boundElementWidth) * (1 - this.offsetModifier);
104
+ if (!this.center) {
105
+ return availableRight >= requiredSideSpace - this.spaceTolerance;
106
+ }
107
+ return (availableRight >= requiredSideSpace - this.spaceTolerance &&
108
+ availableLeft >= requiredSideSpace - this.spaceTolerance);
180
109
  }
181
- hasCenteredVerticalSpace(availableTop, availableBottom, hostHeight, boundHeight, offsetModifier) {
182
- const requiredSpace = (hostHeight - boundHeight) * (1 - offsetModifier);
183
- return (availableTop >= requiredSpace - this.spaceTolerance && availableBottom >= requiredSpace - this.spaceTolerance);
110
+ /**
111
+ * Check if element has enough space to the top and bottom to be centered.
112
+ * Used for `RIGHT` and `LEFT` position.
113
+ * When `center` is not enabled, only one side needs to be checked and `BOTTOM` is the default.
114
+ */
115
+ hasCenteredVerticalSpace(availableTop, availableBottom, hostHeight, boundElementHeight) {
116
+ const requiredSideSpace = (hostHeight - boundElementHeight) * (1 - this.offsetModifier);
117
+ if (!this.center) {
118
+ return availableBottom >= requiredSideSpace - this.spaceTolerance;
119
+ }
120
+ return (availableTop >= requiredSideSpace - this.spaceTolerance &&
121
+ availableBottom >= requiredSideSpace - this.spaceTolerance);
184
122
  }
185
- hasOffsetSpace(availableSpace, hostSize, boundSize, offsetModifier) {
186
- return availableSpace >= hostSize - boundSize * (1 - offsetModifier) - this.spaceTolerance;
123
+ /**
124
+ * Check if there is enough space in the given direction to fit the popover.
125
+ * Used for composed positions like TOP_RIGHT, LEFT_BOTTOM, etc.
126
+ */
127
+ hasEnoughSideSpace(availableSpace, hostSize, boundElementSize, offsetModifier) {
128
+ return availableSpace >= hostSize - boundElementSize * (1 - offsetModifier) - this.spaceTolerance;
187
129
  }
188
130
  /**
189
131
  * Given a desired position and available space around the bound element, returns the best position
@@ -191,51 +133,52 @@ export class ZPopover {
191
133
  * Takes into account offsetModifier for centering.
192
134
  * @param desiredPosition The desired position of the popover.
193
135
  * @param availableSpace The available space around the bound element.
194
- * @param boundElemSizes The sizes of the bound element.
195
- * @param offsetModifier The modifier to apply to the offset for centering.
196
136
  */
197
- getOptimalPopoverPosition(desiredPosition, availableSpace, boundElemSizes, offsetModifier) {
137
+ getOptimalPopoverPosition(desiredPosition, availableSpace) {
198
138
  const hostWidth = this.host.offsetWidth;
199
139
  const hostHeight = this.host.offsetHeight;
200
- // Check if the desired position has enough space
140
+ const boundElementWidth = this.boundElement.getBoundingClientRect().width;
141
+ const boundElementHeight = this.boundElement.getBoundingClientRect().height;
142
+ const offsetModifier = this.offsetModifier;
143
+ /** Check if there is enough space to fit the popover in the desired position */
201
144
  const fits = (pos) => {
202
145
  switch (pos) {
203
146
  case PopoverPosition.TOP:
204
- return (availableSpace.top >= hostHeight &&
205
- this.hasCenteredHorizontalSpace(availableSpace.left, availableSpace.right, hostWidth, boundElemSizes.width, offsetModifier));
147
+ return (availableSpace.top >= hostHeight - this.spaceTolerance &&
148
+ this.hasCenteredHorizontalSpace(availableSpace.left, availableSpace.right, hostWidth, boundElementWidth));
206
149
  case PopoverPosition.TOP_RIGHT:
207
150
  return (availableSpace.top >= hostHeight &&
208
- this.hasOffsetSpace(availableSpace.right, hostWidth, boundElemSizes.width, offsetModifier));
151
+ this.hasEnoughSideSpace(availableSpace.right, hostWidth, boundElementWidth, offsetModifier));
209
152
  case PopoverPosition.TOP_LEFT:
210
153
  return (availableSpace.top >= hostHeight &&
211
- this.hasOffsetSpace(availableSpace.left, hostWidth, boundElemSizes.width, offsetModifier));
154
+ this.hasEnoughSideSpace(availableSpace.left, hostWidth, boundElementWidth, offsetModifier));
212
155
  case PopoverPosition.RIGHT:
213
156
  return (availableSpace.right >= hostWidth &&
214
- this.hasCenteredVerticalSpace(availableSpace.top, availableSpace.bottom, hostHeight, boundElemSizes.height, offsetModifier));
157
+ this.hasCenteredVerticalSpace(availableSpace.top, availableSpace.bottom, hostHeight, boundElementHeight));
215
158
  case PopoverPosition.RIGHT_BOTTOM:
216
159
  return (availableSpace.right >= hostWidth &&
217
- this.hasOffsetSpace(availableSpace.bottom, hostHeight, boundElemSizes.height, offsetModifier));
160
+ this.hasEnoughSideSpace(availableSpace.bottom, hostHeight, boundElementHeight, offsetModifier));
218
161
  case PopoverPosition.RIGHT_TOP:
219
162
  return (availableSpace.right >= hostWidth &&
220
- this.hasOffsetSpace(availableSpace.top, hostHeight, boundElemSizes.height, offsetModifier));
163
+ this.hasEnoughSideSpace(availableSpace.top, hostHeight, boundElementHeight, offsetModifier));
221
164
  case PopoverPosition.BOTTOM:
222
165
  return (availableSpace.bottom >= hostHeight &&
223
- this.hasCenteredHorizontalSpace(availableSpace.left, availableSpace.right, hostWidth, boundElemSizes.width, offsetModifier));
166
+ this.hasCenteredHorizontalSpace(availableSpace.left, availableSpace.right, hostWidth, boundElementWidth));
224
167
  case PopoverPosition.BOTTOM_LEFT:
225
168
  return (availableSpace.bottom >= hostHeight &&
226
- this.hasOffsetSpace(availableSpace.left, hostWidth, boundElemSizes.width, offsetModifier));
169
+ this.hasEnoughSideSpace(availableSpace.left, hostWidth, boundElementWidth, offsetModifier));
227
170
  case PopoverPosition.BOTTOM_RIGHT:
228
171
  return (availableSpace.bottom >= hostHeight &&
229
- this.hasOffsetSpace(availableSpace.right, hostWidth, boundElemSizes.width, offsetModifier));
172
+ this.hasEnoughSideSpace(availableSpace.right, hostWidth, boundElementWidth, offsetModifier));
230
173
  case PopoverPosition.LEFT:
231
174
  return (availableSpace.left >= hostWidth &&
232
- this.hasCenteredVerticalSpace(availableSpace.top, availableSpace.bottom, hostHeight, boundElemSizes.height, offsetModifier));
175
+ this.hasCenteredVerticalSpace(availableSpace.top, availableSpace.bottom, hostHeight, boundElementHeight));
233
176
  case PopoverPosition.LEFT_TOP:
234
177
  return (availableSpace.left >= hostWidth &&
235
- this.hasOffsetSpace(availableSpace.top, hostHeight, boundElemSizes.height, offsetModifier));
178
+ this.hasEnoughSideSpace(availableSpace.top, hostHeight, boundElementHeight, offsetModifier));
236
179
  case PopoverPosition.LEFT_BOTTOM:
237
180
  return (availableSpace.left >= hostWidth &&
238
- this.hasOffsetSpace(availableSpace.bottom, hostHeight, boundElemSizes.height, offsetModifier));
181
+ this.hasEnoughSideSpace(availableSpace.bottom, hostHeight, boundElementHeight, offsetModifier));
239
182
  default:
240
183
  return false;
241
184
  }
@@ -261,27 +204,25 @@ export class ZPopover {
261
204
  // If no position fits, find the best fallback based on available space
262
205
  return this.findBestFallbackPosition(availableSpace);
263
206
  }
264
- /**
265
- * Find the best fallback position based on available space when no position fits perfectly
266
- */
207
+ /** Find the best fallback position based on available space when no position fits perfectly. */
267
208
  findBestFallbackPosition(availableSpace) {
268
- // Determine the directions with the most space
209
+ // Determine which horizontal and vertical direction has the most available space
269
210
  const bestHorizontalDirection = availableSpace.right >= availableSpace.left ? PopoverPosition.RIGHT : PopoverPosition.LEFT;
270
211
  const bestVerticalDirection = availableSpace.bottom >= availableSpace.top ? PopoverPosition.BOTTOM : PopoverPosition.TOP;
271
- // Choose the main direction based on which has more space
212
+ // Choose the main direction based on which axis has more space overall
272
213
  const maxHorizontalSpace = Math.max(availableSpace.right, availableSpace.left);
273
214
  const maxVerticalSpace = Math.max(availableSpace.bottom, availableSpace.top);
274
215
  const mainDirection = maxVerticalSpace >= maxHorizontalSpace ? bestVerticalDirection : bestHorizontalDirection;
275
- // Check if secondary direction is necessary
276
- // Only add secondary direction if the difference between min and max in that direction is at least double
216
+ // Decide if a secondary direction is needed
217
+ // Only add a secondary direction if the difference between min and max in that axis is at least double
277
218
  let needsSecondaryDirection = false;
278
219
  if (mainDirection === bestVerticalDirection) {
279
- // Main direction is vertical, check horizontal space difference
220
+ // If main direction is vertical, check horizontal space difference
280
221
  const minHorizontalSpace = Math.min(availableSpace.right, availableSpace.left);
281
222
  needsSecondaryDirection = maxHorizontalSpace >= minHorizontalSpace * 2;
282
223
  }
283
224
  else {
284
- // Main direction is horizontal, check vertical space difference
225
+ // If main direction is horizontal, check vertical space difference
285
226
  const minVerticalSpace = Math.min(availableSpace.bottom, availableSpace.top);
286
227
  needsSecondaryDirection = maxVerticalSpace >= minVerticalSpace * 2;
287
228
  }
@@ -289,164 +230,188 @@ export class ZPopover {
289
230
  return mainDirection;
290
231
  }
291
232
  const secondaryDirection = mainDirection === bestVerticalDirection ? bestHorizontalDirection : bestVerticalDirection;
292
- // Create a combined position (e.g., "bottom_right")
233
+ // Return a combined position (e.g., "bottom_right")
293
234
  return `${mainDirection}_${secondaryDirection}`;
294
235
  }
295
236
  /**
296
- * Calculate available space around the bound element
237
+ * Calculate available space around the element bound with the popover, based on its nearest scrollable ancestor.
238
+ *
239
+ * Calculations for `right` and `bottom` can be a little bit confusing because `boundingRect.right` and `bottom` may not be what you expect...
240
+ * For more information see the explanation in the docs.
241
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#return_value
297
242
  */
298
- calculateAvailableSpace(boundElementRect, scrollContainer, scrollingBoundingRect) {
299
- const top = boundElementRect.top - scrollContainer.scrollTop;
300
- const bottom = scrollingBoundingRect.height - (boundElementRect.top + boundElementRect.height) + scrollContainer.scrollTop;
301
- const left = boundElementRect.left - scrollContainer.scrollLeft;
302
- const right = scrollingBoundingRect.width - (boundElementRect.left + boundElementRect.width) + scrollContainer.scrollLeft;
303
- const overflowBottom = Math.max(0, scrollingBoundingRect.top + scrollingBoundingRect.height - window.innerHeight);
304
- const overflowRight = Math.max(0, scrollingBoundingRect.left + scrollingBoundingRect.width - window.innerWidth);
305
- return {
306
- top: Math.min(top, top + scrollingBoundingRect.top),
307
- bottom: Math.min(bottom, bottom - overflowBottom),
308
- left: Math.min(left, left + scrollingBoundingRect.left),
309
- right: Math.min(right, right - overflowRight),
243
+ calculateAvailableSpace() {
244
+ const boundElementRect = this.boundElement.getBoundingClientRect();
245
+ if (this.lastBoundRect &&
246
+ this.lastBoundRect.x === boundElementRect.x &&
247
+ this.lastBoundRect.y === boundElementRect.y &&
248
+ this.lastBoundRect.width === boundElementRect.width &&
249
+ this.lastBoundRect.height === boundElementRect.height &&
250
+ this.cachedAvailableSpace) {
251
+ // If the bound element's rect hasn't changed, return the cached rect
252
+ return this.cachedAvailableSpace;
253
+ }
254
+ this.lastBoundRect = boundElementRect;
255
+ const scrollableParent = findScrollableParent(this.boundElement);
256
+ const scrollableParentRect = scrollableParent.getBoundingClientRect();
257
+ const hasNestedScrollableParent = scrollableParent !== this.boundElement.ownerDocument.documentElement;
258
+ const documentWidth = this.boundElement.ownerDocument.documentElement.clientWidth;
259
+ const documentHeight = this.boundElement.ownerDocument.documentElement.clientHeight;
260
+ const safeSpace = 8; // extra space to avoid popover being too close to the edges
261
+ // These deltas represent the offset between the scrollable parent and the viewport.
262
+ // They are used to adjust the available space calculations when the scrollable parent is not the document or body,
263
+ // to try to fit the popover inside the scrollable parent.
264
+ const deltaTop = hasNestedScrollableParent ? scrollableParentRect.top : 0;
265
+ const deltaRight = hasNestedScrollableParent ? documentWidth - scrollableParentRect.right : 0;
266
+ const deltaBottom = hasNestedScrollableParent ? documentHeight - scrollableParentRect.bottom : 0;
267
+ const deltaLeft = hasNestedScrollableParent ? scrollableParentRect.left : 0;
268
+ this.cachedAvailableSpace = {
269
+ top: boundElementRect.top - deltaTop - safeSpace,
270
+ right: documentWidth - boundElementRect.right - deltaRight - safeSpace,
271
+ bottom: documentHeight - boundElementRect.bottom - deltaBottom - safeSpace,
272
+ left: boundElementRect.left - deltaLeft - safeSpace,
310
273
  };
274
+ return this.cachedAvailableSpace;
311
275
  }
312
- /**
313
- * Calculate relative offsets for positioning
314
- */
315
- calculateRelativeOffsets(boundElementRect, relativeBoundingRect) {
276
+ /** Calculate the space around an element relative to the viewport. */
277
+ calculateElementOffsets(element) {
278
+ const elementRect = element.getBoundingClientRect();
279
+ const viewportWidth = element.ownerDocument.documentElement.clientWidth;
280
+ const viewportHeight = element.ownerDocument.documentElement.clientHeight;
316
281
  return {
317
- top: boundElementRect.top - relativeBoundingRect.top,
318
- right: boundElementRect.right - relativeBoundingRect.right,
319
- bottom: boundElementRect.bottom - relativeBoundingRect.bottom,
320
- left: boundElementRect.left - relativeBoundingRect.left,
282
+ top: elementRect.top,
283
+ right: viewportWidth - elementRect.right,
284
+ bottom: viewportHeight - elementRect.bottom,
285
+ left: elementRect.left,
321
286
  };
322
287
  }
323
- /**
324
- * Apply positioning styles based on position
325
- */
326
- applyPositionStyles(position, style, offsets, boundElementSizes, availableSpace, offsetModifier, arrowModifier) {
327
- const distanceFromBound = 8; // 8px is the distance of the popover from the bound element
328
- // Reset all positioning properties
329
- style.top = "auto";
330
- style.right = "auto";
331
- style.bottom = "auto";
332
- style.left = "auto";
333
- style.maxWidth = "";
334
- style.maxHeight = "";
288
+ /** Apply positioning styles based on passed position. */
289
+ applyPositionStyles(position, availableSpace) {
290
+ const boundElementWidth = this.boundElement.offsetWidth;
291
+ const boundElementHeight = this.boundElement.offsetHeight;
292
+ /** Distance between the popover and the bound element */
293
+ const distanceFromBound = 8;
294
+ const offsetModifier = this.offsetModifier;
295
+ /** Distance between the arrow center and the popover edge. Needed to align the center of the arrow with the center of the bound element when `showArrow` and `center` are enabled. */
296
+ const arrowModifier = this.showArrow && this.center ? 8 : 0;
297
+ const hostStyle = this.host.style;
298
+ const boundElementOffsets = this.calculateElementOffsets(this.boundElement);
299
+ let maxWidth;
300
+ let maxHeight;
335
301
  switch (position) {
336
302
  case PopoverPosition.TOP:
337
303
  case PopoverPosition.TOP_RIGHT:
338
- style.bottom = `${offsets.bottom + boundElementSizes.height}px`;
339
- style.left = `${offsets.left + boundElementSizes.width * offsetModifier - (position === PopoverPosition.TOP_RIGHT ? arrowModifier : 0)}px`;
340
- style.maxHeight = `${availableSpace.top - distanceFromBound}px`;
304
+ hostStyle.bottom = `${boundElementOffsets.bottom + boundElementHeight}px`;
305
+ hostStyle.left = `${boundElementOffsets.left + boundElementWidth * offsetModifier - (position === PopoverPosition.TOP_RIGHT ? arrowModifier : 0)}px`;
306
+ maxHeight = availableSpace.top - distanceFromBound;
341
307
  if (position === PopoverPosition.TOP_RIGHT) {
342
- style.maxWidth = `${availableSpace.right + boundElementSizes.width * offsetModifier}px`;
308
+ maxWidth = availableSpace.right + boundElementWidth * offsetModifier;
343
309
  }
344
310
  break;
345
311
  case PopoverPosition.TOP_LEFT:
346
- style.right = `${offsets.right + boundElementSizes.width * offsetModifier - arrowModifier}px`;
347
- style.bottom = `${offsets.bottom + boundElementSizes.height}px`;
348
- style.maxWidth = `${availableSpace.left}px`;
349
- style.maxHeight = `${availableSpace.top - distanceFromBound}px`;
312
+ hostStyle.right = `${boundElementOffsets.right + boundElementWidth * offsetModifier - arrowModifier}px`;
313
+ hostStyle.bottom = `${boundElementOffsets.bottom + boundElementHeight}px`;
314
+ maxWidth = availableSpace.left + boundElementWidth * offsetModifier;
315
+ maxHeight = availableSpace.top - distanceFromBound;
350
316
  break;
351
317
  case PopoverPosition.BOTTOM:
352
318
  case PopoverPosition.BOTTOM_RIGHT:
353
- style.top = `${offsets.top + boundElementSizes.height}px`;
354
- style.left = `${offsets.left + boundElementSizes.width * offsetModifier - (position === PopoverPosition.BOTTOM_RIGHT ? arrowModifier : 0)}px`;
355
- style.maxHeight = `${availableSpace.bottom - distanceFromBound}px`;
319
+ hostStyle.top = `${boundElementOffsets.top + boundElementHeight}px`;
320
+ hostStyle.left = `${boundElementOffsets.left + boundElementWidth * offsetModifier - (position === PopoverPosition.BOTTOM_RIGHT ? arrowModifier : 0)}px`;
321
+ maxHeight = availableSpace.bottom - distanceFromBound;
356
322
  if (position === PopoverPosition.BOTTOM_RIGHT) {
357
- style.maxWidth = `${availableSpace.right + boundElementSizes.width * offsetModifier}px`;
323
+ maxWidth = availableSpace.right + boundElementWidth * offsetModifier;
358
324
  }
359
325
  break;
360
326
  case PopoverPosition.BOTTOM_LEFT:
361
- style.top = `${offsets.top + boundElementSizes.height}px`;
362
- style.right = `${offsets.right + boundElementSizes.width * offsetModifier - arrowModifier}px`;
363
- style.maxWidth = `${availableSpace.left}px`;
364
- style.maxHeight = `${availableSpace.bottom - distanceFromBound}px`;
327
+ hostStyle.top = `${boundElementOffsets.top + boundElementHeight}px`;
328
+ hostStyle.right = `${boundElementOffsets.right + boundElementWidth * offsetModifier - arrowModifier}px`;
329
+ maxWidth = availableSpace.left + boundElementWidth * offsetModifier;
330
+ maxHeight = availableSpace.bottom - distanceFromBound;
365
331
  break;
366
332
  case PopoverPosition.RIGHT:
367
333
  case PopoverPosition.RIGHT_BOTTOM:
368
- style.top = `${offsets.top + boundElementSizes.height * offsetModifier - (position === PopoverPosition.RIGHT_BOTTOM ? arrowModifier : 0)}px`;
369
- style.left = `${offsets.left + boundElementSizes.width}px`;
370
- style.maxWidth = `${availableSpace.right - distanceFromBound}px`;
334
+ hostStyle.top = `${boundElementOffsets.top + boundElementHeight * offsetModifier - (position === PopoverPosition.RIGHT_BOTTOM ? arrowModifier : 0)}px`;
335
+ hostStyle.left = `${boundElementOffsets.left + boundElementWidth}px`;
336
+ maxWidth = availableSpace.right - distanceFromBound;
371
337
  if (position === PopoverPosition.RIGHT) {
372
- style.maxHeight = `${Math.min(availableSpace.top + availableSpace.bottom + boundElementSizes.height, window.innerHeight - 20)}px`;
338
+ maxHeight = availableSpace.top + availableSpace.bottom + boundElementHeight;
373
339
  }
374
340
  else {
375
- style.maxHeight = `${availableSpace.bottom + boundElementSizes.height * offsetModifier}px`;
341
+ maxHeight = availableSpace.bottom + boundElementHeight * offsetModifier;
376
342
  }
377
343
  break;
378
344
  case PopoverPosition.RIGHT_TOP:
379
- style.bottom = `${offsets.bottom + boundElementSizes.height * offsetModifier - arrowModifier}px`;
380
- style.left = `${offsets.left + boundElementSizes.width}px`;
381
- style.maxWidth = `${availableSpace.right - distanceFromBound}px`;
382
- if (position === PopoverPosition.RIGHT_TOP) {
383
- style.maxHeight = `${availableSpace.top + boundElementSizes.height * offsetModifier}px`;
384
- }
345
+ hostStyle.bottom = `${boundElementOffsets.bottom + boundElementHeight * offsetModifier - arrowModifier}px`;
346
+ hostStyle.left = `${boundElementOffsets.left + boundElementWidth}px`;
347
+ maxWidth = availableSpace.right - distanceFromBound;
348
+ maxHeight = availableSpace.top + boundElementHeight * offsetModifier;
385
349
  break;
386
350
  case PopoverPosition.LEFT:
387
351
  case PopoverPosition.LEFT_BOTTOM:
388
- style.top = `${offsets.top + boundElementSizes.height * offsetModifier - (position === PopoverPosition.LEFT_BOTTOM ? arrowModifier : 0)}px`;
389
- style.right = `${offsets.right + boundElementSizes.width}px`;
390
- style.maxWidth = `${availableSpace.left - distanceFromBound}px`;
352
+ hostStyle.top = `${boundElementOffsets.top + boundElementHeight * offsetModifier - (position === PopoverPosition.LEFT_BOTTOM ? arrowModifier : 0)}px`;
353
+ hostStyle.right = `${boundElementOffsets.right + boundElementWidth}px`;
354
+ maxWidth = availableSpace.left - distanceFromBound;
391
355
  if (position === PopoverPosition.LEFT_BOTTOM) {
392
- style.maxHeight = `${availableSpace.bottom + boundElementSizes.height * offsetModifier}px`;
356
+ maxHeight = availableSpace.bottom + boundElementHeight * offsetModifier;
393
357
  }
394
358
  break;
395
359
  case PopoverPosition.LEFT_TOP:
396
- style.right = `${offsets.right + boundElementSizes.width}px`;
397
- style.bottom = `${offsets.bottom + boundElementSizes.height * offsetModifier - arrowModifier}px`;
398
- style.maxWidth = `${availableSpace.left - distanceFromBound}px`;
399
- if (position === PopoverPosition.LEFT_TOP) {
400
- style.maxHeight = `${availableSpace.top + boundElementSizes.height * offsetModifier}px`;
401
- }
360
+ hostStyle.right = `${boundElementOffsets.right + boundElementWidth}px`;
361
+ hostStyle.bottom = `${boundElementOffsets.bottom + boundElementHeight * offsetModifier - arrowModifier}px`;
362
+ maxWidth = availableSpace.left - distanceFromBound;
363
+ maxHeight = availableSpace.top + boundElementHeight * offsetModifier;
402
364
  break;
403
365
  }
366
+ if (getDevice() !== Device.MOBILE) {
367
+ // Only force max sizes on non-mobile viewports
368
+ hostStyle.maxWidth = maxWidth ? `${maxWidth}px` : "";
369
+ hostStyle.maxHeight = maxHeight ? `${maxHeight}px` : "";
370
+ }
404
371
  }
405
- /**
406
- * Set the position of the popover.
407
- */
372
+ /** Set the position of the popover. */
408
373
  setPosition() {
409
- let boundElement;
410
- if (typeof this.bindTo === "string") {
411
- boundElement = this.host.ownerDocument.querySelector(this.bindTo);
412
- }
413
- else if (this.bindTo) {
414
- boundElement = this.bindTo;
415
- }
416
- else {
417
- boundElement = this.host.parentElement;
374
+ if (!this.boundElement) {
375
+ return;
418
376
  }
419
- if (!boundElement) {
377
+ if (!isElementVisibleInContainer(this.boundElement, findScrollableParent(this.boundElement))) {
378
+ // If the bound element is not visible, hide the popover too
379
+ this.open = false;
420
380
  return;
421
381
  }
422
- const scrollContainer = findScrollableParent(boundElement);
423
- const scrollingBoundingRect = scrollContainer.getBoundingClientRect();
424
- const offsetContainer = this.host.offsetParent;
425
- const relativeBoundingRect = offsetContainer
426
- ? computeOffset(offsetContainer, scrollContainer)
427
- : { top: 0, right: 0, bottom: 0, left: 0 };
428
- const boundElementRect = computeOffset(boundElement, scrollContainer);
429
- const availableSpace = this.calculateAvailableSpace(boundElementRect, scrollContainer, scrollingBoundingRect);
430
- const offsets = this.calculateRelativeOffsets(boundElementRect, relativeBoundingRect);
431
- const offsetModifier = this.center ? 0.5 : 0;
432
- const arrowModifier = this.showArrow && this.center ? 8 : 0; // 8px is the distance of the arrow center from the edge of the popover
433
- const position = this.getOptimalPopoverPosition(this.position, availableSpace, { width: boundElementRect.width, height: boundElementRect.height }, offsetModifier);
434
- const style = this.host.style;
435
- this.applyPositionStyles(position, style, offsets, boundElementRect, availableSpace, offsetModifier, arrowModifier);
382
+ Object.assign(this.host.style, {
383
+ // Reset all positioning properties
384
+ top: "auto",
385
+ right: "auto",
386
+ bottom: "auto",
387
+ left: "auto",
388
+ maxWidth: "",
389
+ maxHeight: "",
390
+ // Set initial visibility to hidden while calculating position...
391
+ visibility: "hidden",
392
+ });
393
+ const availableSpace = this.calculateAvailableSpace();
394
+ const position = this.getOptimalPopoverPosition(this.position, availableSpace);
395
+ this.applyPositionStyles(position, availableSpace);
436
396
  this.currentPosition = position;
397
+ this.positionChange.emit({ position: this.currentPosition });
398
+ // ...then restore the visibility
399
+ this.host.style.visibility = "visible";
437
400
  }
438
401
  componentWillLoad() {
439
402
  this.validatePosition(this.position);
440
- this.onOpen();
441
403
  }
442
404
  componentDidLoad() {
443
- this.setPosition();
405
+ this.findBoundElement();
406
+ if (this.open) {
407
+ this.onOpen();
408
+ }
444
409
  }
445
410
  disconnectedCallback() {
446
411
  cancelAnimationFrame(this.animationFrameRequestId);
447
412
  }
448
413
  render() {
449
- return (h(Host, { key: '8628b0f299deb808e4c554047c76b82f392782c9', "current-position": this.currentPosition }, h("slot", { key: '144294e8216d7ad673e4ee3a96651c053703d135' })));
414
+ return (h(Host, { key: '1eafd1bd08aa31a81378354542b0e74edc4cb0ce', "current-position": this.currentPosition }, h("slot", { key: '2ad916cf0e13766e2e5f92f4f964a4fe909cdc7a' })));
450
415
  }
451
416
  static get is() { return "z-popover"; }
452
417
  static get encapsulation() { return "shadow"; }
@@ -596,7 +561,7 @@ export class ZPopover {
596
561
  "composed": true,
597
562
  "docs": {
598
563
  "tags": [],
599
- "text": "Position change event."
564
+ "text": "Fired when the position changes."
600
565
  },
601
566
  "complexType": {
602
567
  "original": "any",
@@ -628,6 +593,9 @@ export class ZPopover {
628
593
  }, {
629
594
  "propName": "open",
630
595
  "methodName": "onOpen"
596
+ }, {
597
+ "propName": "bindTo",
598
+ "methodName": "onBindingChange"
631
599
  }];
632
600
  }
633
601
  static get listeners() {
@@ -648,17 +616,17 @@ export class ZPopover {
648
616
  }
649
617
  // Clockwise order of positions.
650
618
  ZPopover.positionOrder = [
651
- PopoverPosition.TOP_RIGHT,
652
619
  PopoverPosition.TOP,
620
+ PopoverPosition.TOP_RIGHT,
653
621
  PopoverPosition.TOP_LEFT,
654
- PopoverPosition.RIGHT_BOTTOM,
655
622
  PopoverPosition.RIGHT,
623
+ PopoverPosition.RIGHT_BOTTOM,
656
624
  PopoverPosition.RIGHT_TOP,
657
- PopoverPosition.BOTTOM_LEFT,
658
625
  PopoverPosition.BOTTOM,
626
+ PopoverPosition.BOTTOM_LEFT,
659
627
  PopoverPosition.BOTTOM_RIGHT,
660
- PopoverPosition.LEFT_TOP,
661
628
  PopoverPosition.LEFT,
629
+ PopoverPosition.LEFT_TOP,
662
630
  PopoverPosition.LEFT_BOTTOM,
663
631
  ];
664
632
  //# sourceMappingURL=index.js.map