@ngbase/adk 0.1.1 → 0.1.2

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 (152) hide show
  1. package/accordion/accordion-item.d.ts +4 -0
  2. package/accordion/public-api.d.ts +1 -1
  3. package/autocomplete/autocomplete.d.ts +2 -2
  4. package/avatar/avatar.d.ts +1 -1
  5. package/breadcrumb/breadcrumb.d.ts +2 -3
  6. package/breadcrumb/public-api.d.ts +1 -1
  7. package/carousel/carousel.d.ts +1 -1
  8. package/chip/chip.d.ts +2 -2
  9. package/datepicker/calendar.d.ts +3 -3
  10. package/datepicker/datepicker.d.ts +2 -2
  11. package/datepicker/time.d.ts +2 -2
  12. package/dialog/dialog.d.ts +1 -1
  13. package/fesm2022/ngbase-adk-accordion.mjs +4 -1
  14. package/fesm2022/ngbase-adk-accordion.mjs.map +1 -1
  15. package/fesm2022/ngbase-adk-autocomplete.mjs +7 -36
  16. package/fesm2022/ngbase-adk-autocomplete.mjs.map +1 -1
  17. package/fesm2022/ngbase-adk-avatar.mjs +2 -2
  18. package/fesm2022/ngbase-adk-avatar.mjs.map +1 -1
  19. package/fesm2022/ngbase-adk-breadcrumb.mjs +2 -2
  20. package/fesm2022/ngbase-adk-breadcrumb.mjs.map +1 -1
  21. package/fesm2022/ngbase-adk-carousel.mjs +2 -2
  22. package/fesm2022/ngbase-adk-carousel.mjs.map +1 -1
  23. package/fesm2022/ngbase-adk-chip.mjs +4 -2
  24. package/fesm2022/ngbase-adk-chip.mjs.map +1 -1
  25. package/fesm2022/ngbase-adk-datepicker.mjs +114 -328
  26. package/fesm2022/ngbase-adk-datepicker.mjs.map +1 -1
  27. package/fesm2022/ngbase-adk-dialog.mjs +12 -13
  28. package/fesm2022/ngbase-adk-dialog.mjs.map +1 -1
  29. package/fesm2022/ngbase-adk-form-field.mjs +2 -156
  30. package/fesm2022/ngbase-adk-form-field.mjs.map +1 -1
  31. package/fesm2022/ngbase-adk-menu.mjs +15 -30
  32. package/fesm2022/ngbase-adk-menu.mjs.map +1 -1
  33. package/fesm2022/ngbase-adk-otp.mjs +164 -0
  34. package/fesm2022/ngbase-adk-otp.mjs.map +1 -0
  35. package/fesm2022/ngbase-adk-pagination.mjs +8 -65
  36. package/fesm2022/ngbase-adk-pagination.mjs.map +1 -1
  37. package/fesm2022/ngbase-adk-popover.mjs +423 -548
  38. package/fesm2022/ngbase-adk-popover.mjs.map +1 -1
  39. package/fesm2022/ngbase-adk-portal.mjs +0 -1
  40. package/fesm2022/ngbase-adk-portal.mjs.map +1 -1
  41. package/fesm2022/ngbase-adk-radio.mjs +2 -16
  42. package/fesm2022/ngbase-adk-radio.mjs.map +1 -1
  43. package/fesm2022/ngbase-adk-resizable.mjs +10 -43
  44. package/fesm2022/ngbase-adk-resizable.mjs.map +1 -1
  45. package/fesm2022/ngbase-adk-select.mjs +67 -173
  46. package/fesm2022/ngbase-adk-select.mjs.map +1 -1
  47. package/fesm2022/ngbase-adk-sheet.mjs +95 -0
  48. package/fesm2022/ngbase-adk-sheet.mjs.map +1 -0
  49. package/fesm2022/ngbase-adk-sidenav.mjs +2 -2
  50. package/fesm2022/ngbase-adk-sidenav.mjs.map +1 -1
  51. package/fesm2022/ngbase-adk-slider.mjs +9 -23
  52. package/fesm2022/ngbase-adk-slider.mjs.map +1 -1
  53. package/fesm2022/ngbase-adk-sonner.mjs +13 -63
  54. package/fesm2022/ngbase-adk-sonner.mjs.map +1 -1
  55. package/fesm2022/ngbase-adk-stepper.mjs +16 -114
  56. package/fesm2022/ngbase-adk-stepper.mjs.map +1 -1
  57. package/fesm2022/ngbase-adk-switch.mjs +2 -2
  58. package/fesm2022/ngbase-adk-switch.mjs.map +1 -1
  59. package/fesm2022/ngbase-adk-table.mjs +10 -30
  60. package/fesm2022/ngbase-adk-table.mjs.map +1 -1
  61. package/fesm2022/ngbase-adk-tabs.mjs +14 -94
  62. package/fesm2022/ngbase-adk-tabs.mjs.map +1 -1
  63. package/fesm2022/ngbase-adk-tooltip.mjs +49 -39
  64. package/fesm2022/ngbase-adk-tooltip.mjs.map +1 -1
  65. package/fesm2022/ngbase-adk-tour.mjs +1 -1
  66. package/fesm2022/ngbase-adk-tour.mjs.map +1 -1
  67. package/fesm2022/ngbase-adk-tree.mjs +11 -43
  68. package/fesm2022/ngbase-adk-tree.mjs.map +1 -1
  69. package/form-field/public-api.d.ts +0 -1
  70. package/menu/menu-trigger.d.ts +2 -2
  71. package/menu/menu.d.ts +6 -6
  72. package/otp/index.d.ts +5 -0
  73. package/{form-field → otp}/otp.d.ts +1 -1
  74. package/otp/public-api.d.ts +1 -0
  75. package/package.json +25 -17
  76. package/pagination/pagination.d.ts +5 -1
  77. package/popover/popover-arrow.ng.d.ts +34 -0
  78. package/popover/popover.d.ts +12 -3
  79. package/popover/popover.service.d.ts +5 -4
  80. package/popover/public-api.d.ts +1 -0
  81. package/popover/utils.d.ts +32 -48
  82. package/portal/dialog-ref.d.ts +0 -1
  83. package/resizable/resizable-group.d.ts +2 -2
  84. package/resizable/resizable.d.ts +2 -2
  85. package/schematics/components/files/accordion/accordion.ts.template +6 -8
  86. package/schematics/components/files/autocomplete/autocomplete.ts.template +2 -6
  87. package/schematics/components/files/avatar/avatar.ts.template +2 -2
  88. package/schematics/components/files/breadcrumb/breadcrumb.ts.template +5 -5
  89. package/schematics/components/files/carousel/carousel.ts.template +2 -2
  90. package/schematics/components/files/chip/chip.ts.template +2 -2
  91. package/schematics/components/files/datepicker/calendar.ts.template +6 -6
  92. package/schematics/components/files/datepicker/datepicker.ts.template +33 -3
  93. package/schematics/components/files/datepicker/index.ts.template +0 -1
  94. package/schematics/components/files/datepicker/time.ts.template +12 -4
  95. package/schematics/components/files/dialog/dialog.ts.template +8 -8
  96. package/schematics/components/files/form-field/{input.ts.template → form-field.ts.template} +13 -2
  97. package/schematics/components/files/form-field/index.ts.template +1 -2
  98. package/schematics/components/files/form-field/input-style.directive.ts.template +1 -1
  99. package/schematics/components/files/menu/menu.ts.template +3 -3
  100. package/schematics/components/files/otp/index.ts.template +5 -0
  101. package/schematics/components/files/{form-field → otp}/otp.ts.template +3 -3
  102. package/schematics/components/files/pagination/pagination.ts.template +2 -2
  103. package/schematics/components/files/popover/popover.ts.template +7 -30
  104. package/schematics/components/files/radio/radio.ts.template +3 -8
  105. package/schematics/components/files/resizable/resizable.ts.template +7 -7
  106. package/schematics/components/files/select/option.ts.template +1 -0
  107. package/schematics/components/files/select/select.ts.template +8 -8
  108. package/schematics/components/files/sheet/sheet.ts.template +11 -76
  109. package/schematics/components/files/sidenav/sidenav.ts.template +3 -3
  110. package/schematics/components/files/slider/slider.ts.template +3 -10
  111. package/schematics/components/files/sonner/sonner.ts.template +3 -2
  112. package/schematics/components/files/stepper/stepper.ts.template +4 -4
  113. package/schematics/components/files/switch/switch.ts.template +1 -1
  114. package/schematics/components/files/tabs/tab.ts.template +11 -8
  115. package/schematics/components/files/theme/theme.service.ts.template +0 -11
  116. package/schematics/components/files/tooltip/tooltip.ts.template +8 -3
  117. package/schematics/components/files/tour/index.ts.template +0 -2
  118. package/schematics/components/files/tour/tour.ts.template +13 -2
  119. package/schematics/components/files/tree/tree.ts.template +3 -3
  120. package/schematics/components/schema.json +8 -0
  121. package/select/option-group.d.ts +3 -3
  122. package/select/select.d.ts +2 -2
  123. package/sheet/index.d.ts +5 -0
  124. package/sheet/public-api.d.ts +2 -0
  125. package/sheet/sheet.d.ts +26 -0
  126. package/sheet/sheet.service.d.ts +13 -0
  127. package/sidenav/public-api.d.ts +1 -1
  128. package/sidenav/sidenav.d.ts +1 -1
  129. package/slider/public-api.d.ts +1 -1
  130. package/slider/slider.d.ts +5 -5
  131. package/sonner/sonner.d.ts +2 -1
  132. package/stepper/animation.d.ts +1 -1
  133. package/stepper/step.d.ts +1 -1
  134. package/stepper/stepper.d.ts +2 -2
  135. package/switch/switch.d.ts +1 -1
  136. package/table/body-row.d.ts +3 -3
  137. package/table/head-row.d.ts +3 -3
  138. package/table/table.d.ts +1 -1
  139. package/tabs/tab-group.d.ts +4 -4
  140. package/tabs/tab.d.ts +2 -2
  141. package/tooltip/public-api.d.ts +1 -1
  142. package/tooltip/tooltip.d.ts +5 -1
  143. package/tooltip/tooltip.directive.d.ts +1 -1
  144. package/tooltip/tooltip.service.d.ts +4 -2
  145. package/tour/tour.service.d.ts +3 -4
  146. package/tree/public-api.d.ts +2 -2
  147. package/tree/tree-node.d.ts +2 -2
  148. package/tree/tree.d.ts +2 -2
  149. package/schematics/components/files/datepicker/datepicker-trigger.ts.template +0 -27
  150. package/schematics/components/files/theme/theme.component.ts.template +0 -165
  151. package/schematics/components/files/tour/tour-step.ts.template +0 -8
  152. package/schematics/components/files/tour/tour.service.ts.template +0 -7
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, linkedSignal, Directive, viewChild, ViewContainerRef, ElementRef, signal, effect, Component, ChangeDetectionStrategy, InjectionToken, input } from '@angular/core';
2
+ import { InjectionToken, signal, inject, input, ElementRef, computed, Component, linkedSignal, Directive, viewChild, ViewContainerRef, effect } from '@angular/core';
3
3
  import * as i2 from '@ngbase/adk/portal';
4
4
  import { basePortal, BaseDialog, NgbPortalClose, DialogOptions } from '@ngbase/adk/portal';
5
5
  import { trigger, state, style, transition, animate } from '@angular/animations';
@@ -30,16 +30,7 @@ function basePopoverPortal(component) {
30
30
  return { open, closeAll };
31
31
  }
32
32
 
33
- const positionSwap = {
34
- top: 'bottom',
35
- bottom: 'top',
36
- left: 'right',
37
- right: 'left',
38
- tl: 'bl',
39
- tr: 'br',
40
- bl: 'tl',
41
- br: 'tr',
42
- };
33
+ // Main position enum with all supported positions
43
34
  var Position;
44
35
  (function (Position) {
45
36
  Position["Top"] = "top";
@@ -50,30 +41,171 @@ var Position;
50
41
  Position["TopRight"] = "tr";
51
42
  Position["BottomLeft"] = "bl";
52
43
  Position["BottomRight"] = "br";
44
+ Position["RightStart"] = "rs";
45
+ Position["RightEnd"] = "re";
46
+ Position["LeftStart"] = "ls";
47
+ Position["LeftEnd"] = "le";
53
48
  })(Position || (Position = {}));
49
+ // Position metadata definitions
50
+ const POSITION_META = {
51
+ [Position.Top]: {
52
+ main: 'vertical',
53
+ placement: 'before',
54
+ align: 'center',
55
+ oppositePosition: Position.Bottom,
56
+ fallbacks: [Position.Bottom],
57
+ getCoords: (target, element, offset) => ({
58
+ top: target.top - element.height - offset,
59
+ left: target.left + (target.width - element.width) / 2,
60
+ }),
61
+ },
62
+ [Position.Bottom]: {
63
+ main: 'vertical',
64
+ placement: 'after',
65
+ align: 'center',
66
+ oppositePosition: Position.Top,
67
+ fallbacks: [Position.Top, Position.Right, Position.Left],
68
+ getCoords: (target, element, offset) => ({
69
+ top: target.top + target.height + offset,
70
+ left: target.left + (target.width - element.width) / 2,
71
+ }),
72
+ },
73
+ [Position.Left]: {
74
+ main: 'horizontal',
75
+ placement: 'before',
76
+ align: 'center',
77
+ oppositePosition: Position.Right,
78
+ fallbacks: [Position.Right, Position.Top, Position.Bottom],
79
+ getCoords: (target, element, offset) => ({
80
+ top: target.top + (target.height - element.height) / 2,
81
+ left: target.left - element.width - offset,
82
+ }),
83
+ },
84
+ [Position.Right]: {
85
+ main: 'horizontal',
86
+ placement: 'after',
87
+ align: 'center',
88
+ oppositePosition: Position.Left,
89
+ fallbacks: [Position.Left, Position.Top, Position.Bottom],
90
+ getCoords: (target, element, offset) => ({
91
+ top: target.top + (target.height - element.height) / 2,
92
+ left: target.left + target.width + offset,
93
+ }),
94
+ },
95
+ [Position.TopLeft]: {
96
+ main: 'vertical',
97
+ placement: 'before',
98
+ align: 'start',
99
+ oppositePosition: Position.BottomLeft,
100
+ fallbacks: [Position.BottomLeft, Position.TopRight, Position.BottomRight],
101
+ getCoords: (target, element, offset) => ({
102
+ top: target.top - element.height - offset,
103
+ left: target.left,
104
+ }),
105
+ },
106
+ [Position.TopRight]: {
107
+ main: 'vertical',
108
+ placement: 'before',
109
+ align: 'end',
110
+ oppositePosition: Position.BottomRight,
111
+ fallbacks: [Position.BottomRight, Position.TopLeft, Position.BottomLeft],
112
+ getCoords: (target, element, offset) => ({
113
+ top: target.top - element.height - offset,
114
+ left: target.left + target.width - element.width,
115
+ }),
116
+ },
117
+ [Position.BottomLeft]: {
118
+ main: 'vertical',
119
+ placement: 'after',
120
+ align: 'start',
121
+ oppositePosition: Position.BottomRight,
122
+ fallbacks: [Position.BottomRight, Position.TopLeft, Position.TopRight],
123
+ getCoords: (target, element, offset) => ({
124
+ top: target.top + target.height + offset,
125
+ left: target.left,
126
+ }),
127
+ },
128
+ [Position.BottomRight]: {
129
+ main: 'vertical',
130
+ placement: 'after',
131
+ align: 'end',
132
+ oppositePosition: Position.BottomLeft,
133
+ fallbacks: [Position.BottomLeft, Position.TopRight, Position.TopLeft],
134
+ getCoords: (target, element, offset) => ({
135
+ top: target.top + target.height + offset,
136
+ left: target.left + target.width - element.width,
137
+ }),
138
+ },
139
+ [Position.RightStart]: {
140
+ main: 'horizontal',
141
+ placement: 'after',
142
+ align: 'start',
143
+ oppositePosition: Position.RightEnd,
144
+ fallbacks: [Position.RightEnd, Position.LeftStart, Position.LeftEnd],
145
+ getCoords: (target, element, offset) => ({
146
+ top: target.top,
147
+ left: target.left + target.width + offset,
148
+ }),
149
+ },
150
+ [Position.RightEnd]: {
151
+ main: 'horizontal',
152
+ placement: 'after',
153
+ align: 'end',
154
+ oppositePosition: Position.LeftEnd,
155
+ fallbacks: [Position.LeftEnd, Position.RightStart, Position.LeftStart],
156
+ getCoords: (target, element, offset) => ({
157
+ top: target.top + target.height - element.height,
158
+ left: target.left + target.width + offset,
159
+ }),
160
+ },
161
+ [Position.LeftStart]: {
162
+ main: 'horizontal',
163
+ placement: 'before',
164
+ align: 'start',
165
+ oppositePosition: Position.LeftEnd,
166
+ fallbacks: [Position.LeftEnd, Position.RightStart, Position.RightEnd],
167
+ getCoords: (target, element, offset) => ({
168
+ top: target.top,
169
+ left: target.left - element.width - offset,
170
+ }),
171
+ },
172
+ [Position.LeftEnd]: {
173
+ main: 'horizontal',
174
+ placement: 'before',
175
+ align: 'end',
176
+ oppositePosition: Position.RightEnd,
177
+ fallbacks: [Position.RightEnd, Position.LeftStart, Position.RightStart],
178
+ getCoords: (target, element, offset) => ({
179
+ top: target.top + target.height - element.height,
180
+ left: target.left - element.width - offset,
181
+ }),
182
+ },
183
+ };
54
184
  class PopoverPositioner {
55
- constructor(config, windowDimensions, scrollWidth) {
185
+ constructor(config, windowDimensions, scrollWidth = 0) {
56
186
  this.config = config;
57
187
  this.windowDimensions = windowDimensions;
58
188
  this.scrollWidth = scrollWidth;
59
189
  this.offset = this.config.offset || 5;
190
+ this.sideOffset = this.config.sideOffset || 0;
60
191
  }
61
192
  calculatePosition() {
62
193
  const targetRect = this.getTargetRect();
63
- const elRect = this.getElementRect();
64
- this.elRect = elRect;
65
- const initialPosition = this.getInitialPosition(targetRect, elRect, this.config.position || Position.Bottom);
66
- const adjustedPosition = this.adjustForOverflow(initialPosition, targetRect, elRect);
67
- return this.finalizePosition(adjustedPosition, elRect);
194
+ this.elementRect = this.getElementRect();
195
+ // Get initial position or use bottom as default
196
+ const initialPosition = this.config.position || Position.Bottom;
197
+ // Find best position
198
+ const bestPosition = this.findBestPosition(initialPosition, targetRect);
199
+ // Generate and finalize coordinates
200
+ const coords = POSITION_META[bestPosition].getCoords(targetRect, this.elementRect, this.offset);
201
+ return this.finalizePosition(coords, bestPosition, targetRect);
68
202
  }
69
203
  getTargetRect() {
70
204
  if (this.config.client) {
71
205
  const { x, y, w, h } = this.config.client;
72
206
  return { top: y, left: x, width: w, height: h };
73
207
  }
74
- const { top, left, width, height } = this.config.target.getBoundingClientRect();
75
- // return { top, left, width, height: Math.min(height, this.windowDimensions.height - top) };
76
- return { top, left, width, height };
208
+ return this.config.target.getBoundingClientRect();
77
209
  }
78
210
  getElementRect() {
79
211
  const el = this.config.el;
@@ -84,433 +216,289 @@ class PopoverPositioner {
84
216
  height: el.clientHeight,
85
217
  };
86
218
  }
87
- getInitialPosition(targetRect, elRect, position) {
88
- const coords = this.getCoordinatesForPosition(position, targetRect, elRect, this.offset);
89
- // coords.left = Math.max(0, coords.left);
90
- // coords.top = Math.max(0, coords.top);
91
- return { ...coords, position };
92
- }
93
- getCoordinatesForPosition(position, targetRect, elRect, offset) {
94
- switch (position) {
95
- case Position.Top:
96
- return {
97
- top: targetRect.top - elRect.height - offset,
98
- left: targetRect.left + (targetRect.width - elRect.width) / 2,
99
- };
100
- case Position.Bottom:
101
- return {
102
- top: targetRect.top + targetRect.height + offset,
103
- left: targetRect.left + (targetRect.width - elRect.width) / 2,
104
- };
105
- case Position.Left:
106
- return { top: targetRect.top, left: targetRect.left - elRect.width - offset };
107
- case Position.Right:
108
- return { top: targetRect.top, left: targetRect.left + targetRect.width + offset };
109
- case Position.TopLeft:
110
- return { top: targetRect.top - elRect.height - offset, left: targetRect.left };
111
- case Position.TopRight:
112
- return {
113
- top: targetRect.top - elRect.height - offset,
114
- left: targetRect.left - (elRect.width - targetRect.width),
115
- };
116
- case Position.BottomLeft:
117
- return { top: targetRect.top + targetRect.height + offset, left: targetRect.left };
118
- case Position.BottomRight:
119
- return {
120
- top: targetRect.top + targetRect.height + offset,
121
- left: targetRect.left - (elRect.width - targetRect.width),
122
- };
219
+ findBestPosition(initialPosition, targetRect) {
220
+ // If the initial position works, use it
221
+ if (!this.positionOverflows(initialPosition, targetRect)) {
222
+ return initialPosition;
123
223
  }
124
- }
125
- adjustForOverflow(position, targetRect, elRect) {
126
- const overflow = this.checkOverflow(position, elRect, targetRect);
127
- this.overflow = overflow;
128
- if (overflow.any) {
129
- const newPosition = this.getAlternativePosition(position.position, overflow);
130
- return this.getInitialPosition(targetRect, elRect, newPosition);
224
+ // Get available space in each direction
225
+ const space = this.getAvailableSpace(targetRect);
226
+ // Special handling for simple cases (e.g., choosing between top and bottom based on space)
227
+ const meta = POSITION_META[initialPosition];
228
+ // 1. Try the opposite position on the same axis (e.g., bottom for top)
229
+ const opposite = meta.oppositePosition;
230
+ if (!this.positionOverflows(opposite, targetRect)) {
231
+ return opposite;
131
232
  }
132
- return position;
133
- }
134
- checkOverflow(position, elRect, targetRect) {
135
- // Calculate available space on all sides
136
- const topSpace = position.top;
137
- const bottomSpace = this.windowDimensions.height - position.top;
138
- const leftSpace = position.left;
139
- const rightSpace = this.windowDimensions.width - position.left;
140
- // Calculate overflow amounts (negative means no overflow)
141
- const topOverflow = -(targetRect.top - elRect.height);
142
- const bottomOverflow = targetRect.top + targetRect.height + elRect.height - this.windowDimensions.height;
143
- // const leftOverflow = -(position.left - (elRect.width - targetRect.width));
144
- const leftOverflow = -(targetRect.left + targetRect.width - elRect.width);
145
- const leftSideOverflow = -(targetRect.left - elRect.width);
146
- const rightOverflow = targetRect.left + elRect.width - this.windowDimensions.width;
147
- const rightSideOverflow = -(targetRect.left + targetRect.width - elRect.width);
148
- const isTop = topOverflow > 0;
149
- const isBottom = bottomOverflow > 0;
150
- const isLeft = leftOverflow > 0;
151
- const isRight = rightOverflow > 0;
152
- const isLeftSide = leftSideOverflow > 0;
153
- const isRightSide = rightSideOverflow > 0;
154
- let preferredHorizontal;
155
- let preferredVertical;
156
- // If both left and right overflow, determine which side has more space
157
- if (isLeft || isRight) {
158
- preferredHorizontal = leftOverflow > rightOverflow ? 'right' : 'left';
233
+ // 2. For vertical positions, prefer the side with more space
234
+ if (meta.main === 'vertical') {
235
+ const preferredVertical = space.top > space.bottom ? Position.Top : Position.Bottom;
236
+ if (!this.positionOverflows(preferredVertical, targetRect)) {
237
+ return preferredVertical;
238
+ }
159
239
  }
160
- else if (isLeftSide || isRightSide) {
161
- preferredHorizontal = leftSideOverflow > rightSideOverflow ? 'right' : 'left';
240
+ // 3. For horizontal positions, prefer the side with more space
241
+ if (meta.main === 'horizontal') {
242
+ const preferredHorizontal = space.left > space.right ? Position.Left : Position.Right;
243
+ if (!this.positionOverflows(preferredHorizontal, targetRect)) {
244
+ return preferredHorizontal;
245
+ }
162
246
  }
163
- // If both top and bottom overflow, determine which side has more space
164
- if (isTop || isBottom) {
165
- preferredVertical = topOverflow > bottomOverflow ? 'bottom' : 'top';
247
+ // 4. Try fallbacks in order
248
+ for (const fallback of meta.fallbacks) {
249
+ if (!this.positionOverflows(fallback, targetRect)) {
250
+ return fallback;
251
+ }
166
252
  }
253
+ // 5. If all positions have issues, find the one with the best fit
254
+ return this.getPositionWithLeastOverflow(initialPosition, targetRect);
255
+ }
256
+ getAvailableSpace(targetRect) {
167
257
  return {
168
- top: isTop,
169
- bottom: isBottom,
170
- left: isLeft,
171
- right: isRight,
172
- leftSide: isLeftSide,
173
- rightSide: isRightSide,
174
- any: isTop || isBottom || isLeft || isRight || isLeftSide || isRightSide,
175
- preferredHorizontal,
176
- preferredVertical,
177
- overflowAmount: {
178
- top: topOverflow,
179
- bottom: bottomOverflow,
180
- left: leftOverflow,
181
- right: rightOverflow,
182
- leftSide: leftSideOverflow,
183
- rightSide: rightSideOverflow,
184
- },
258
+ top: targetRect.top,
259
+ right: this.windowDimensions.width - (targetRect.left + targetRect.width),
260
+ bottom: this.windowDimensions.height - (targetRect.top + targetRect.height),
261
+ left: targetRect.left,
185
262
  };
186
263
  }
187
- getAlternativePosition(position, overflow) {
188
- // if (overflow.top) {
189
- // if (position === Position.Top) {
190
- // return Position.Bottom;
191
- // }
192
- // }
193
- // if (
194
- // (overflow.preferredVertical === 'top' || !overflow.bottom) &&
195
- // (overflow.preferredHorizontal === 'left' || !overflow.right)
196
- // ) {
197
- // return Position.BottomRight;
198
- // }
199
- // if (
200
- // (overflow.preferredVertical === 'top' || !overflow.bottom) &&
201
- // (overflow.preferredHorizontal === 'right' || !overflow.left)
202
- // ) {
203
- // return Position.BottomLeft;
204
- // }
205
- // if (
206
- // (overflow.preferredVertical === 'bottom' || !overflow.top) &&
207
- // (overflow.preferredHorizontal === 'left' || !overflow.right)
208
- // ) {
209
- // return Position.TopRight;
210
- // }
211
- // if (
212
- // (overflow.preferredVertical === 'bottom' || !overflow.top) &&
213
- // (overflow.preferredHorizontal === 'right' || !overflow.left)
214
- // ) {
215
- // return Position.TopLeft;
216
- // }
217
- // if (overflow.bottom) {
218
- // if (position.includes('bottom')) {
219
- // return positionSwap[position] as Position;
220
- // } else if (position.includes('bl') && overflow.preferredVertical === 'top') {
221
- // return overflow.right && overflow.preferredHorizontal !== 'right'
222
- // ? Position.TopRight
223
- // : Position.TopLeft;
224
- // } else if (position.includes('bl') && overflow.preferredVertical === 'bottom') {
225
- // return overflow.right && overflow.preferredHorizontal !== 'right'
226
- // ? Position.BottomRight
227
- // : Position.BottomLeft;
228
- // }
229
- // }
230
- // if (overflow.left) {
231
- // if (position === Position.Left) {
232
- // return Position.Right;
233
- // }
234
- // if (overflow.preferredHorizontal === 'left' || !overflow.right) {
235
- // return overflow.bottom ? Position.TopLeft : Position.BottomLeft;
236
- // }
237
- // if (overflow.preferredHorizontal === 'right') {
238
- // return overflow.bottom ? Position.TopRight : Position.BottomRight;
239
- // }
240
- // }
241
- // if (overflow.right) {
242
- // if (position.includes('right')) {
243
- // return !overflow.left
244
- // ? Position.Left
245
- // : overflow.bottom && !overflow.left
246
- // ? (positionSwap[position] as Position)
247
- // : overflow.left && overflow.bottom
248
- // ? Position.Top
249
- // : Position.BottomRight;
250
- // } else if (position.includes('bl')) {
251
- // return overflow.bottom ? Position.TopRight : Position.BottomRight;
252
- // }
253
- // }
254
- // return position;
255
- if (!overflow.any) {
256
- return position;
257
- }
258
- // Simple mapping for opposite positions
259
- const opposites = {
260
- [Position.Top]: Position.Bottom,
261
- [Position.Bottom]: Position.Top,
262
- [Position.Left]: Position.Right,
263
- [Position.Right]: Position.Left,
264
- [Position.TopLeft]: Position.BottomRight,
265
- [Position.TopRight]: Position.BottomLeft,
266
- [Position.BottomLeft]: Position.TopRight,
267
- [Position.BottomRight]: Position.TopLeft,
268
- };
269
- // For cardinal positions (Top, Bottom, Left, Right)
270
- if ([Position.Top, Position.Bottom].includes(position)) {
271
- return overflow.preferredVertical || opposites[position];
272
- }
273
- if ([Position.Left, Position.Right].includes(position)) {
274
- return overflow.preferredHorizontal || opposites[position];
275
- }
276
- // For corner positions
277
- const isTop = position.includes('t');
278
- const isLeft = position.includes('l');
279
- const vertical = overflow.preferredVertical === 'top' ? 't' : 'b';
280
- const horizontal = overflow.preferredHorizontal === 'left' ? 'r' : 'l';
281
- // If current position overflows, use the preferred directions
282
- if ((isTop && overflow.top) ||
283
- (!isTop && overflow.bottom) ||
284
- (isLeft && overflow.left) ||
285
- (!isLeft && overflow.right) ||
286
- (horizontal === 'r' && overflow.right) ||
287
- (horizontal === 'l' && overflow.left)) {
288
- switch (vertical + horizontal) {
289
- case 'tl':
290
- return Position.TopLeft;
291
- case 'tr':
292
- return Position.TopRight;
293
- case 'bl':
294
- return Position.BottomLeft;
295
- case 'br':
296
- return Position.BottomRight;
297
- default:
298
- return opposites[position];
264
+ positionOverflows(position, targetRect) {
265
+ const meta = POSITION_META[position];
266
+ const element = this.elementRect;
267
+ const coords = meta.getCoords(targetRect, element, this.offset);
268
+ const { width: windowWidth, height: windowHeight } = this.windowDimensions;
269
+ // Check boundaries
270
+ return (coords.left < 0 ||
271
+ coords.left + element.width > windowWidth ||
272
+ coords.top < 0 ||
273
+ coords.top + element.height > windowHeight);
274
+ }
275
+ getOverflowAmount(position, targetRect) {
276
+ const meta = POSITION_META[position];
277
+ const element = this.elementRect;
278
+ const coords = meta.getCoords(targetRect, element, this.offset);
279
+ const { width: windowWidth, height: windowHeight } = this.windowDimensions;
280
+ let amount = 0;
281
+ // Calculate overflow for each edge
282
+ if (coords.left < 0)
283
+ amount += Math.abs(coords.left);
284
+ if (coords.left + element.width > windowWidth)
285
+ amount += coords.left + element.width - windowWidth;
286
+ if (coords.top < 0)
287
+ amount += Math.abs(coords.top);
288
+ if (coords.top + element.height > windowHeight)
289
+ amount += coords.top + element.height - windowHeight;
290
+ return amount;
291
+ }
292
+ getPositionWithLeastOverflow(initialPosition, targetRect) {
293
+ const positionsToCheck = [initialPosition, ...POSITION_META[initialPosition].fallbacks];
294
+ let bestPosition = initialPosition;
295
+ let leastOverflow = this.getOverflowAmount(initialPosition, targetRect);
296
+ for (const position of positionsToCheck) {
297
+ const overflow = this.getOverflowAmount(position, targetRect);
298
+ if (overflow < leastOverflow) {
299
+ leastOverflow = overflow;
300
+ bestPosition = position;
299
301
  }
300
302
  }
301
- return position;
303
+ return bestPosition;
302
304
  }
303
- finalizePosition(position, elRect) {
304
- const { top, left } = position;
305
- const bottom = position.position.startsWith('t')
306
- ? this.windowDimensions.height - (top + elRect.height)
307
- : undefined;
308
- // this is required if tooltip is going outside of the screen horizontally
309
- // this has to be done only if the position is top or bottom
310
- let right;
311
- right =
312
- left + elRect.width > this.windowDimensions.width
313
- ? 0
314
- : position.position.endsWith('r')
315
- ? this.windowDimensions.width - (left + elRect.width) - this.scrollWidth
316
- : undefined;
317
- let overallOffset = this.getOverallOffset(position);
305
+ finalizePosition(coords, position, targetRect) {
306
+ const { top, left } = coords;
307
+ const element = this.elementRect;
308
+ const { width: windowWidth, height: windowHeight } = this.windowDimensions;
309
+ const meta = POSITION_META[position];
310
+ // Calculate max dimensions
318
311
  let maxHeight;
319
- if (position.position.startsWith('t') &&
320
- this.overflow.overflowAmount.top > -overallOffset.vertical) {
321
- maxHeight = this.elRect.height - this.overflow.overflowAmount.top - overallOffset.vertical;
312
+ let maxWidth;
313
+ // Set maxHeight if needed
314
+ if (top - this.sideOffset < 0) {
315
+ maxHeight = element.height + top - this.sideOffset;
322
316
  }
323
- else if (position.position.startsWith('b') &&
324
- this.overflow.overflowAmount.bottom > -overallOffset.vertical) {
325
- maxHeight = this.elRect.height - this.overflow.overflowAmount.bottom - overallOffset.vertical;
317
+ else if (top + element.height + this.sideOffset > windowHeight) {
318
+ maxHeight = element.height - (top + element.height + this.sideOffset - windowHeight);
326
319
  }
327
- let maxWidth;
328
- if (position.position.endsWith('l') &&
329
- this.overflow.overflowAmount.right > -overallOffset.horizontal) {
330
- maxWidth = this.elRect.width - this.overflow.overflowAmount.right - overallOffset.horizontal;
320
+ // Set maxWidth if needed
321
+ if (left + element.width + this.sideOffset > windowWidth) {
322
+ maxWidth = windowWidth - left - this.sideOffset;
331
323
  }
332
- else if (position.position.endsWith('r') &&
333
- this.overflow.overflowAmount.left > -overallOffset.horizontal) {
334
- maxWidth = this.elRect.width - this.overflow.overflowAmount.left - overallOffset.horizontal;
324
+ // Add sideOffset to maxHeight and maxWidth because the sideOffset is used for the maxHeight and maxWidth
325
+ const h = maxHeight ? maxHeight + this.sideOffset : element.height;
326
+ const w = maxWidth ? maxWidth + this.sideOffset : element.width;
327
+ // Calculate adjusted coordinates
328
+ let adjustedTop = Math.max(0, Math.min(top, windowHeight - h));
329
+ let adjustedLeft = Math.max(0, Math.min(left, windowWidth - w));
330
+ // Calculate bottom and right (for RTL support)
331
+ let bottom;
332
+ let right;
333
+ // Set bottom if appropriate
334
+ if (meta.main === 'vertical' && meta.placement === 'before') {
335
+ bottom = windowHeight - (adjustedTop + h);
336
+ adjustedTop = undefined;
337
+ }
338
+ // Set right if appropriate
339
+ if (adjustedLeft + w > windowWidth) {
340
+ adjustedLeft = 0;
341
+ right = 0;
342
+ }
343
+ else if (meta.align === 'end' ||
344
+ (meta.main === 'horizontal' && meta.placement === 'before')) {
345
+ right = windowWidth - (adjustedLeft + w) - this.scrollWidth;
335
346
  }
336
347
  return {
337
- // top: Math.max(0, Math.min(top, this.windowDimensions.height - (maxHeight || elRect.height))),
338
- top: Math.max(0, top),
348
+ top: adjustedTop,
349
+ left: right !== undefined ? undefined : adjustedLeft,
339
350
  bottom,
340
- left: right ? 0 : Math.max(overallOffset.horizontal, left),
341
- right: right ? Math.max(overallOffset.horizontal, right) : undefined,
342
- position: position.position,
343
- maxHeight,
344
- maxWidth,
345
- };
346
- }
347
- getOverallOffset(position) {
348
- const overallOffset = this.config.sideOffset ?? 0;
349
- const isHorizontal = position.position === 'left' || position.position === 'right';
350
- return {
351
- horizontal: overallOffset + (isHorizontal ? this.offset : 0),
352
- vertical: overallOffset + (isHorizontal ? 0 : this.offset),
351
+ right,
352
+ position,
353
+ maxHeight: maxHeight && maxHeight > 0 ? maxHeight : undefined,
354
+ maxWidth: maxWidth && maxWidth > 0 ? maxWidth : undefined,
353
355
  };
354
356
  }
355
357
  }
356
358
  // Main function to use the class
357
- function tooltipPosition(config, windowDimensions = {
358
- width: window.innerWidth,
359
- height: window.innerHeight,
360
- }, scrollWidth = window.innerWidth - document.documentElement.clientWidth) {
359
+ function tooltipPosition(config, windowDimensions = { width: window.innerWidth, height: window.innerHeight }, scrollWidth = window.innerWidth - document.documentElement.clientWidth) {
361
360
  const positioner = new PopoverPositioner(config, windowDimensions, scrollWidth);
362
361
  return positioner.calculatePosition();
363
362
  }
364
- // export function tooltipPosition(config: OverlayConfig): {
365
- // top: number;
366
- // left: number;
367
- // bottom?: number;
368
- // right?: number;
369
- // position: DialogPosition;
370
- // } {
371
- // const { target, el, position: priority = 'bottom', offset = 5, client: clientXY = null } = config;
372
- // let position: DialogPosition = priority;
373
- // let { top, left, width, height } = target.getBoundingClientRect();
374
- // if (clientXY) {
375
- // top = clientXY.y;
376
- // left = clientXY.x;
377
- // width = clientXY.w;
378
- // height = clientXY.h;
379
- // }
380
- // const { clientWidth: elWidth, clientHeight: elHeight } = el!;
381
- // // we need to check whether the height of the target element is greater than the height then we need to adjust the height
382
- // if (height > window.innerHeight) {
383
- // height = window.innerHeight - top;
384
- // }
385
- // return tooltipPositionInternal({
386
- // top,
387
- // left,
388
- // width,
389
- // height,
390
- // elWidth,
391
- // elHeight,
392
- // offset,
393
- // priority,
394
- // position,
395
- // windowWidth: window.innerWidth,
396
- // windowHeight: window.innerHeight,
397
- // scrollWidth: window.innerWidth - document.documentElement.clientWidth,
398
- // });
399
- // }
400
- // export function tooltipPositionInternal(data: ConfigObj): {
401
- // top: number;
402
- // bottom?: number;
403
- // left: number;
404
- // right?: number;
405
- // position: DialogPosition;
406
- // } {
407
- // let { elHeight, position, windowHeight, windowWidth, offset, elWidth, scrollWidth } = data;
408
- // position = positionSwapBasedOnOverflow(data);
409
- // let { top: topPos, left: leftPos } = getTooltipCoordinates(position, data);
410
- // if (topPos <= 0) {
411
- // topPos = offset;
412
- // } else if (topPos + elHeight > windowHeight) {
413
- // topPos = windowHeight - elHeight - offset;
414
- // } else if (leftPos < 0) {
415
- // leftPos = 0;
416
- // }
417
- // const bottomPos = position.startsWith('t') ? windowHeight - (topPos + elHeight) : undefined;
418
- // const rightPos =
419
- // leftPos + elWidth > windowWidth
420
- // ? 0
421
- // : position.endsWith('r')
422
- // ? windowWidth - (leftPos + elWidth) - scrollWidth
423
- // : undefined;
424
- // return {
425
- // top: topPos,
426
- // bottom: bottomPos,
427
- // left: rightPos ? 0 : leftPos,
428
- // position,
429
- // right: rightPos,
430
- // };
431
- // }
432
- // function getTooltipCoordinates(
433
- // position: DialogPosition,
434
- // data: ConfigObj,
435
- // ): { top: number; left: number } {
436
- // const { top, left, width, height, elWidth, elHeight, offset } = data;
437
- // switch (position) {
438
- // case 'top':
439
- // return {
440
- // top: top - elHeight - offset,
441
- // left: left + (width - elWidth) / 2,
442
- // };
443
- // case 'bottom':
444
- // return { top: top + height + offset, left: left + (width - elWidth) / 2 };
445
- // case 'left':
446
- // return { top, left: left - elWidth - offset };
447
- // case 'right':
448
- // return { top, left: left + width + offset };
449
- // case 'tl':
450
- // return { top: top - elHeight - offset, left };
451
- // case 'tr':
452
- // return { top: top - elHeight - offset, left: left - (elWidth - width) };
453
- // case 'bl':
454
- // return { top: top + height + offset, left };
455
- // case 'br':
456
- // return { top: top + height + offset, left: left - (elWidth - width) };
457
- // default:
458
- // return {
459
- // top: top - elHeight - offset,
460
- // left: left + (width - elWidth) / 2,
461
- // };
462
- // }
463
- // }
464
- // // function to check the overflow sides for target and element
465
- // export function checkOverflow(data: ConfigObj) {
466
- // const isTop = data.top - data.elHeight < 0;
467
- // const isBottom = data.top + data.height + data.elHeight > data.windowHeight;
468
- // const isLeft = data.left - data.elWidth < 0;
469
- // const isRight = data.left + data.width + data.elWidth > data.windowWidth;
470
- // return { top: isTop, bottom: isBottom, left: isLeft, right: isRight };
471
- // }
472
- // // position swap based on the overflow and priority
473
- // function positionSwapBasedOnOverflow(data: ConfigObj): DialogPosition {
474
- // const {
475
- // bottom: bottomOverflow,
476
- // left: leftOverflow,
477
- // right: rightOverflow,
478
- // top: topOverflow,
479
- // } = checkOverflow(data);
480
- // const { priority } = data;
481
- // let position = priority;
482
- // if (topOverflow) {
483
- // if (position.includes('top')) {
484
- // position = positionSwap[position];
485
- // }
486
- // }
487
- // if (bottomOverflow) {
488
- // if (position.includes('bottom')) {
489
- // position = positionSwap[position];
490
- // } else if (position.includes('bl')) {
491
- // position = rightOverflow ? 'tr' : 'tl';
492
- // }
493
- // }
494
- // if (leftOverflow) {
495
- // if (position.includes('left')) {
496
- // position = positionSwap[position];
497
- // }
498
- // }
499
- // if (rightOverflow) {
500
- // if (position.includes('right')) {
501
- // position = !leftOverflow
502
- // ? 'left'
503
- // : bottomOverflow && !leftOverflow
504
- // ? positionSwap[position]
505
- // : leftOverflow && bottomOverflow
506
- // ? 'top'
507
- // : 'br';
508
- // } else if (position.includes('bl')) {
509
- // position = bottomOverflow ? 'tr' : 'br';
510
- // }
511
- // }
512
- // return position;
513
- // }
363
+
364
+ class PopoverArrowTracker {
365
+ constructor() {
366
+ this.top = 0;
367
+ this.left = 0;
368
+ this.right = 0;
369
+ this.bottom = 0;
370
+ }
371
+ }
372
+ const POPOVER_ARROW_TRACKER = new InjectionToken('popoverArrowTracker');
373
+ function providePopoverArrowTracker() {
374
+ return {
375
+ provide: POPOVER_ARROW_TRACKER,
376
+ useFactory: () => ({ values: signal(new PopoverArrowTracker()) }),
377
+ };
378
+ }
379
+ class NgbPopoverArrow {
380
+ constructor() {
381
+ this.arrowTracker = inject(POPOVER_ARROW_TRACKER);
382
+ this.anchor = input(false);
383
+ this.el = inject((ElementRef));
384
+ this.styles = computed(() => {
385
+ const { target, position } = this.arrowTracker.values();
386
+ if (target && position) {
387
+ return this.updateAnchorPosition(position, target, this.el.nativeElement);
388
+ }
389
+ return {};
390
+ });
391
+ }
392
+ updateAnchorPosition(position, target, el) {
393
+ const { height, width, top } = el.getBoundingClientRect();
394
+ const { height: tHeight, width: tWidth, top: tTop } = target.getBoundingClientRect();
395
+ let deg = '0deg';
396
+ let anchorTop = '50%';
397
+ let anchorLeft = '50%';
398
+ const anchorWidth = 8;
399
+ const thHeight = tHeight / 2 - anchorWidth / 2;
400
+ const thWidth = tWidth / 2;
401
+ switch (position) {
402
+ case 'top':
403
+ case 'tl':
404
+ case 'tr':
405
+ anchorTop = '100%';
406
+ break;
407
+ case 'left':
408
+ deg = '270deg';
409
+ anchorLeft = `calc(100% + ${anchorWidth / 2}px)`;
410
+ anchorTop =
411
+ tHeight > height
412
+ ? `calc(50% - ${anchorWidth / 2}px)`
413
+ : `calc(${thHeight + (tTop - top)}px)`;
414
+ break;
415
+ case 'right':
416
+ deg = '90deg';
417
+ anchorLeft = `-${anchorWidth / 2}px`;
418
+ anchorTop =
419
+ tHeight > height
420
+ ? `calc(50% - ${anchorWidth / 2}px)`
421
+ : `calc(${thHeight + (tTop - top)}px)`;
422
+ break;
423
+ case 'bottom':
424
+ case 'bl':
425
+ case 'br':
426
+ deg = '180deg';
427
+ anchorTop = '-0.5rem';
428
+ anchorLeft = thWidth > width ? '50%' : `calc(100% - ${thWidth}px)`;
429
+ break;
430
+ }
431
+ return { '--action-angle': deg, '--action-left': anchorLeft, '--action-top': anchorTop };
432
+ }
433
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgbPopoverArrow, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
434
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: NgbPopoverArrow, isStandalone: true, selector: "[ngbPopoverArrow]", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style": "styles()" } }, ngImport: i0, template: `
435
+ <ng-content />
436
+ @if (anchor()) {
437
+ <style>
438
+ :host {
439
+ --action-angle: 180deg;
440
+ --action-left: 50%;
441
+ --action-top: -1rem;
442
+ }
443
+ :host::before {
444
+ content: '';
445
+ position: absolute;
446
+ width: 0;
447
+ height: 0;
448
+ border-style: solid;
449
+ border-top: 0.5rem solid;
450
+ @apply border-foreground;
451
+ border-left: 0.45rem solid transparent;
452
+ border-right: 0.45rem solid transparent;
453
+ top: var(--action-top);
454
+ left: var(--action-left);
455
+ transform: translateX(-50%) rotate(var(--action-angle, 180deg));
456
+ /* Add shadow to match the container shadow */
457
+ /* filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
458
+ z-index: -1; */
459
+ }
460
+ </style>
461
+ }
462
+ `, isInline: true, styles: [":host{--action-angle: 180deg;--action-left: 50%;--action-top: -1rem}:host:before{content:\"\";position:absolute;width:0;height:0;border-style:solid;border-top:.5rem solid;@apply border-foreground;border-left:.45rem solid transparent;border-right:.45rem solid transparent;top:var(--action-top);left:var(--action-left);transform:translate(-50%) rotate(var(--action-angle, 180deg))}\n"] }); }
463
+ }
464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgbPopoverArrow, decorators: [{
465
+ type: Component,
466
+ args: [{
467
+ selector: '[ngbPopoverArrow]',
468
+ template: `
469
+ <ng-content />
470
+ @if (anchor()) {
471
+ <style>
472
+ :host {
473
+ --action-angle: 180deg;
474
+ --action-left: 50%;
475
+ --action-top: -1rem;
476
+ }
477
+ :host::before {
478
+ content: '';
479
+ position: absolute;
480
+ width: 0;
481
+ height: 0;
482
+ border-style: solid;
483
+ border-top: 0.5rem solid;
484
+ @apply border-foreground;
485
+ border-left: 0.45rem solid transparent;
486
+ border-right: 0.45rem solid transparent;
487
+ top: var(--action-top);
488
+ left: var(--action-left);
489
+ transform: translateX(-50%) rotate(var(--action-angle, 180deg));
490
+ /* Add shadow to match the container shadow */
491
+ /* filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
492
+ z-index: -1; */
493
+ }
494
+ </style>
495
+ }
496
+ `,
497
+ host: {
498
+ '[style]': 'styles()',
499
+ },
500
+ }]
501
+ }] });
514
502
 
515
503
  class NgbPopoverBackdrop {
516
504
  constructor() {
@@ -552,6 +540,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
552
540
  class NgbPopover extends BaseDialog {
553
541
  constructor() {
554
542
  super();
543
+ this.arrowTracker = inject(POPOVER_ARROW_TRACKER);
555
544
  this.disposals = disposals();
556
545
  this.myDialog = viewChild.required('myDialog', { read: ViewContainerRef });
557
546
  this.container = viewChild.required(NgbPopoverMain, {
@@ -668,16 +657,16 @@ class NgbPopover extends BaseDialog {
668
657
  sideOffset: this.options().sideOffset,
669
658
  });
670
659
  // change the anchor position
671
- if (this.options().anchor) {
672
- this.updateAnchorPosition(position, el, target);
673
- }
660
+ // if (this.options().anchor) {
661
+ // this.updateAnchorPosition(position, el, target);
662
+ // }
674
663
  this.lastPosition = position;
675
664
  // we need to update the values directly instead of signal to avoid too many CD checks
676
- if (bottom) {
665
+ if (bottom !== undefined) {
677
666
  el.style.bottom = `${bottom}px`;
678
667
  el.style.top = '';
679
668
  }
680
- else if (top) {
669
+ else {
681
670
  el.style.top = `${top}px`;
682
671
  el.style.bottom = '';
683
672
  }
@@ -695,87 +684,14 @@ class NgbPopover extends BaseDialog {
695
684
  if (maxWidth) {
696
685
  el.style.maxWidth = `${maxWidth}px`;
697
686
  }
698
- }
699
- updateAnchorPosition(position, el, target) {
700
- let deg = '0deg';
701
- let anchorTop = '50%';
702
- let anchorLeft = '50%';
703
- const anchorWidth = 12.8;
704
- const thHeight = target.offsetHeight / 2;
705
- const thWidth = target.offsetWidth / 2;
706
- switch (position) {
707
- case 'top':
708
- case 'tl':
709
- case 'tr':
710
- anchorTop = '100%';
711
- break;
712
- case 'left':
713
- deg = '270deg';
714
- anchorLeft = `calc(100% + ${anchorWidth / 2}px)`;
715
- anchorTop = thHeight > el.clientHeight ? '50%' : `calc(${thHeight}px)`;
716
- break;
717
- case 'right':
718
- deg = '90deg';
719
- anchorLeft = `-${anchorWidth / 2}px`;
720
- anchorTop = thHeight > el.clientHeight ? '50%' : `calc(${thHeight}px)`;
721
- break;
722
- case 'bottom':
723
- case 'bl':
724
- case 'br':
725
- deg = '180deg';
726
- anchorTop = '-1rem';
727
- anchorLeft = thWidth > el.clientWidth ? '50%' : `calc(100% - ${thWidth}px)`;
728
- break;
729
- }
730
- el.style.setProperty('--action-angle', deg);
731
- el.style.setProperty('--action-left', anchorLeft);
732
- el.style.setProperty('--action-top', anchorTop);
733
- // console.log('updateAnchorPosition', position, deg);
687
+ this.arrowTracker.values.set({ top, bottom, left, right, target, position });
734
688
  }
735
689
  setOptions(options) {
736
690
  // console.log('setOptions', options);
737
691
  this.options.set(options);
738
692
  }
739
693
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgbPopover, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
740
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: NgbPopover, isStandalone: true, selector: "ngb-popover", host: { listeners: { "@parentAnimation.done": "animationDone()" }, properties: { "@parentAnimation": "" }, classAttribute: "fixed top-0 left-0 w-full h-full pointer-events-none z-p flex items-center justify-center" }, viewQueries: [{ propertyName: "myDialog", first: true, predicate: ["myDialog"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "container", first: true, predicate: NgbPopoverMain, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "backdropElement", first: true, predicate: NgbPopoverBackdrop, descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: ` <style>
741
- .popover-anchor {
742
- --action-angle: 180deg;
743
- --action-left: 50%;
744
- --action-top: -1rem;
745
- }
746
- .popover-anchor::before {
747
- content: '';
748
- position: absolute;
749
- width: 0;
750
- height: 0;
751
- border-style: solid;
752
- border-top: 0.8rem solid;
753
- @apply border-foreground;
754
- border-left: 0.5rem solid transparent;
755
- border-right: 0.5rem solid transparent;
756
- top: var(--action-top);
757
- left: var(--action-left);
758
- transform: translateX(-50%) rotate(var(--action-angle, 180deg));
759
- }
760
- </style>
761
- <div
762
- ngbPopoverMain
763
- [@slideInOutAnimation]
764
- class="{{
765
- 'menu-container pointer-events-auto fixed z-10 flex flex-col rounded-lg border bg-foreground shadow-md ' +
766
- (options().anchor ? 'popover-anchor ' : 'overflow-auto ')
767
- }}"
768
- >
769
- <div class="flex flex-1 flex-col overflow-auto">
770
- <ng-container #myDialog />
771
- </div>
772
- </div>
773
- @if (options().backdrop) {
774
- <div
775
- ngbPopoverBackdrop
776
- class="popover-backdrop pointer-events-auto fixed top-0 h-full w-full"
777
- ></div>
778
- }`, isInline: true, styles: [".popover-anchor{--action-angle: 180deg;--action-left: 50%;--action-top: -1rem}.popover-anchor:before{content:\"\";position:absolute;width:0;height:0;border-style:solid;border-top:.8rem solid;@apply border-foreground;border-left:.5rem solid transparent;border-right:.5rem solid transparent;top:var(--action-top);left:var(--action-left);transform:translate(-50%) rotate(var(--action-angle, 180deg))}\n"], dependencies: [{ kind: "directive", type: NgbPopoverBackdrop, selector: "[ngbPopoverBackdrop]" }, { kind: "directive", type: NgbPopoverMain, selector: "[ngbPopoverMain]" }], animations: [
694
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.0", type: NgbPopover, isStandalone: true, selector: "ngb-popover", host: { listeners: { "@parentAnimation.done": "animationDone()" }, properties: { "@parentAnimation": "" } }, viewQueries: [{ propertyName: "myDialog", first: true, predicate: ["myDialog"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "container", first: true, predicate: NgbPopoverMain, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "backdropElement", first: true, predicate: NgbPopoverBackdrop, descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: '', isInline: true, animations: [
779
695
  createHostAnimation(['@slideInOutAnimation']),
780
696
  trigger('slideInOutAnimation', [
781
697
  state('1', style({ transform: 'none', opacity: 1 })),
@@ -783,55 +699,14 @@ class NgbPopover extends BaseDialog {
783
699
  state('0', style({ transform: 'translateY(-10px) scale(0.95)', opacity: 0 })),
784
700
  transition('* => *', animate('100ms ease-out')),
785
701
  ]),
786
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
702
+ ] }); }
787
703
  }
788
704
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgbPopover, decorators: [{
789
705
  type: Component,
790
706
  args: [{
791
707
  selector: 'ngb-popover',
792
- changeDetection: ChangeDetectionStrategy.OnPush,
793
- imports: [NgbPopoverBackdrop, NgbPopoverMain],
794
- template: ` <style>
795
- .popover-anchor {
796
- --action-angle: 180deg;
797
- --action-left: 50%;
798
- --action-top: -1rem;
799
- }
800
- .popover-anchor::before {
801
- content: '';
802
- position: absolute;
803
- width: 0;
804
- height: 0;
805
- border-style: solid;
806
- border-top: 0.8rem solid;
807
- @apply border-foreground;
808
- border-left: 0.5rem solid transparent;
809
- border-right: 0.5rem solid transparent;
810
- top: var(--action-top);
811
- left: var(--action-left);
812
- transform: translateX(-50%) rotate(var(--action-angle, 180deg));
813
- }
814
- </style>
815
- <div
816
- ngbPopoverMain
817
- [@slideInOutAnimation]
818
- class="{{
819
- 'menu-container pointer-events-auto fixed z-10 flex flex-col rounded-lg border bg-foreground shadow-md ' +
820
- (options().anchor ? 'popover-anchor ' : 'overflow-auto ')
821
- }}"
822
- >
823
- <div class="flex flex-1 flex-col overflow-auto">
824
- <ng-container #myDialog />
825
- </div>
826
- </div>
827
- @if (options().backdrop) {
828
- <div
829
- ngbPopoverBackdrop
830
- class="popover-backdrop pointer-events-auto fixed top-0 h-full w-full"
831
- ></div>
832
- }`,
708
+ template: '',
833
709
  host: {
834
- class: 'fixed top-0 left-0 w-full h-full pointer-events-none z-p flex items-center justify-center',
835
710
  '[@parentAnimation]': '',
836
711
  '(@parentAnimation.done)': 'animationDone()',
837
712
  },
@@ -886,8 +761,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
886
761
  hostDirectives: [{ directive: NgbPortalClose, inputs: ['ngbPortalClose: ngbPopoverClose'] }],
887
762
  }]
888
763
  }] });
889
- function providePopover(popover) {
890
- return { provide: NgbPopover, useExisting: popover };
764
+ function aliasPopover(popover) {
765
+ return [{ provide: NgbPopover, useExisting: popover }, providePopoverArrowTracker()];
891
766
  }
892
767
 
893
768
  class PopoverOptions extends DialogOptions {
@@ -949,5 +824,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
949
824
  * Generated bundle index. Do not edit.
950
825
  */
951
826
 
952
- export { NgbPopover, NgbPopoverBackdrop, NgbPopoverClose, NgbPopoverMain, NgbPopoverTrigger, PopoverOptions, basePopoverPortal, ngbPopoverPortal, providePopover, registerNgbPopover, tooltipPosition };
827
+ export { NgbPopover, NgbPopoverArrow, NgbPopoverBackdrop, NgbPopoverClose, NgbPopoverMain, NgbPopoverTrigger, POPOVER_ARROW_TRACKER, PopoverArrowTracker, PopoverOptions, aliasPopover, basePopoverPortal, ngbPopoverPortal, providePopoverArrowTracker, registerNgbPopover, tooltipPosition };
953
828
  //# sourceMappingURL=ngbase-adk-popover.mjs.map