1
1
import { NumberInput } from '@angular/cdk/coercion' ;
2
- import { ConnectionPositionPair } from '@angular/cdk/overlay' ;
2
+ import { ConnectedOverlayPositionChange } from '@angular/cdk/overlay' ;
3
3
import {
4
4
afterNextRender ,
5
5
computed ,
@@ -14,14 +14,17 @@ import {
14
14
signal ,
15
15
untracked
16
16
} from '@angular/core' ;
17
- import { getArrowPositionParams , getSideAndAlignFromAllPossibleConnectedPositions } from '@radix-ng/primitives/core' ;
17
+ import { toSignal } from '@angular/core/rxjs-interop' ;
18
+ import {
19
+ getArrowPositionParams ,
20
+ getSideAndAlignFromAllPossibleConnectedPositions ,
21
+ RDX_POSITIONING_DEFAULTS
22
+ } from '@radix-ng/primitives/core' ;
18
23
import { RdxTooltipArrowToken } from './tooltip-arrow.token' ;
19
- import { RdxTooltipContentToken } from './tooltip-content.token' ;
20
- import { injectTooltipRoot } from './tooltip-root.directive' ;
24
+ import { injectTooltipRoot } from './tooltip-root.inject' ;
21
25
22
26
@Directive ( {
23
27
selector : '[rdxTooltipArrow]' ,
24
- standalone : true ,
25
28
providers : [
26
29
{
27
30
provide : RdxTooltipArrowToken ,
@@ -30,32 +33,24 @@ import { injectTooltipRoot } from './tooltip-root.directive';
30
33
]
31
34
} )
32
35
export class RdxTooltipArrowDirective {
33
- /** @ignore */
34
- readonly tooltipRoot = injectTooltipRoot ( ) ;
35
36
/** @ignore */
36
37
private readonly renderer = inject ( Renderer2 ) ;
37
38
/** @ignore */
38
- private readonly contentDirective = inject ( RdxTooltipContentToken ) ;
39
+ private readonly rootDirective = injectTooltipRoot ( ) ;
39
40
/** @ignore */
40
- private readonly elementRef = inject < ElementRef < HTMLElement > > ( ElementRef ) ;
41
+ readonly elementRef = inject ( ElementRef ) ;
41
42
42
43
/**
43
- * The width of the arrow in pixels.
44
+ * @description The width of the arrow in pixels.
45
+ * @default 10
44
46
*/
45
- readonly width = input < number , NumberInput > ( 10 , { transform : numberAttribute } ) ;
47
+ readonly width = input < number , NumberInput > ( RDX_POSITIONING_DEFAULTS . arrow . width , { transform : numberAttribute } ) ;
46
48
47
49
/**
48
- * The height of the arrow in pixels.
50
+ * @description The height of the arrow in pixels.
51
+ * @default 5
49
52
*/
50
- readonly height = input < number , NumberInput > ( 5 , { transform : numberAttribute } ) ;
51
-
52
- /**
53
- * @ignore
54
- * */
55
- private triggerRect : DOMRect ;
56
-
57
- /** @ignore */
58
- private readonly currentArrowSvgElement = signal < HTMLOrSVGElement | undefined > ( void 0 ) ;
53
+ readonly height = input < number , NumberInput > ( RDX_POSITIONING_DEFAULTS . arrow . height , { transform : numberAttribute } ) ;
59
54
60
55
/** @ignore */
61
56
readonly arrowSvgElement = computed < HTMLElement > ( ( ) => {
@@ -74,6 +69,14 @@ export class RdxTooltipArrowDirective {
74
69
return svgElement ;
75
70
} ) ;
76
71
72
+ /** @ignore */
73
+ private readonly currentArrowSvgElement = signal < HTMLOrSVGElement | undefined > ( void 0 ) ;
74
+ /** @ignore */
75
+ private readonly position = toSignal ( this . rootDirective . contentDirective ( ) . positionChange ( ) ) ;
76
+
77
+ /** @ignore */
78
+ private anchorOrTriggerRect : DOMRect ;
79
+
77
80
constructor ( ) {
78
81
afterNextRender ( {
79
82
write : ( ) => {
@@ -85,20 +88,24 @@ export class RdxTooltipArrowDirective {
85
88
this . renderer . setStyle ( this . elementRef . nativeElement , 'fontSize' , '0px' ) ;
86
89
}
87
90
} ) ;
91
+ this . onArrowSvgElementChangeEffect ( ) ;
92
+ this . onContentPositionAndArrowDimensionsChangeEffect ( ) ;
88
93
}
89
94
90
95
/** @ignore */
91
- private setTriggerRect ( ) {
92
- this . triggerRect = this . tooltipRoot . tooltipTriggerDirective ( ) . elementRef . nativeElement . getBoundingClientRect ( ) ;
96
+ private setAnchorOrTriggerRect ( ) {
97
+ this . anchorOrTriggerRect = (
98
+ this . rootDirective . anchorDirective ( ) ?? this . rootDirective . triggerDirective ( )
99
+ ) . elementRef . nativeElement . getBoundingClientRect ( ) ;
93
100
}
94
101
95
102
/** @ignore */
96
- private setPosition ( position : ConnectionPositionPair , arrowDimensions : { width : number ; height : number } ) {
97
- this . setTriggerRect ( ) ;
103
+ private setPosition ( position : ConnectedOverlayPositionChange , arrowDimensions : { width : number ; height : number } ) {
104
+ this . setAnchorOrTriggerRect ( ) ;
98
105
const posParams = getArrowPositionParams (
99
- getSideAndAlignFromAllPossibleConnectedPositions ( position ) ,
106
+ getSideAndAlignFromAllPossibleConnectedPositions ( position . connectionPair ) ,
100
107
{ width : arrowDimensions . width , height : arrowDimensions . height } ,
101
- { width : this . triggerRect . width , height : this . triggerRect . height }
108
+ { width : this . anchorOrTriggerRect . width , height : this . anchorOrTriggerRect . height }
102
109
) ;
103
110
104
111
this . renderer . setStyle ( this . elementRef . nativeElement , 'top' , posParams . top ) ;
@@ -110,29 +117,33 @@ export class RdxTooltipArrowDirective {
110
117
}
111
118
112
119
/** @ignore */
113
- private readonly onArrowSvgElementChangeEffect = effect ( ( ) => {
114
- const arrowElement = this . arrowSvgElement ( ) ;
115
- untracked ( ( ) => {
116
- const currentArrowSvgElement = this . currentArrowSvgElement ( ) ;
117
- if ( currentArrowSvgElement ) {
118
- this . renderer . removeChild ( this . elementRef . nativeElement , currentArrowSvgElement ) ;
119
- }
120
- this . currentArrowSvgElement . set ( arrowElement ) ;
121
- this . renderer . setStyle ( this . elementRef . nativeElement , 'width' , `${ this . width ( ) } px` ) ;
122
- this . renderer . setStyle ( this . elementRef . nativeElement , 'height' , `${ this . height ( ) } px` ) ;
123
- this . renderer . appendChild ( this . elementRef . nativeElement , this . currentArrowSvgElement ( ) ) ;
120
+ private onArrowSvgElementChangeEffect ( ) {
121
+ effect ( ( ) => {
122
+ const arrowElement = this . arrowSvgElement ( ) ;
123
+ untracked ( ( ) => {
124
+ const currentArrowSvgElement = this . currentArrowSvgElement ( ) ;
125
+ if ( currentArrowSvgElement ) {
126
+ this . renderer . removeChild ( this . elementRef . nativeElement , currentArrowSvgElement ) ;
127
+ }
128
+ this . currentArrowSvgElement . set ( arrowElement ) ;
129
+ this . renderer . setStyle ( this . elementRef . nativeElement , 'width' , `${ this . width ( ) } px` ) ;
130
+ this . renderer . setStyle ( this . elementRef . nativeElement , 'height' , `${ this . height ( ) } px` ) ;
131
+ this . renderer . appendChild ( this . elementRef . nativeElement , this . currentArrowSvgElement ( ) ) ;
132
+ } ) ;
124
133
} ) ;
125
- } ) ;
134
+ }
126
135
127
136
/** @ignore */
128
- private readonly onContentPositionAndArrowDimensionsChangeEffect = effect ( ( ) => {
129
- const position = this . contentDirective . position ( ) ;
130
- const arrowDimensions = { width : this . width ( ) , height : this . height ( ) } ;
131
- untracked ( ( ) => {
132
- if ( ! position ) {
133
- return ;
134
- }
135
- this . setPosition ( position , arrowDimensions ) ;
137
+ private onContentPositionAndArrowDimensionsChangeEffect ( ) {
138
+ effect ( ( ) => {
139
+ const position = this . position ( ) ;
140
+ const arrowDimensions = { width : this . width ( ) , height : this . height ( ) } ;
141
+ untracked ( ( ) => {
142
+ if ( ! position ) {
143
+ return ;
144
+ }
145
+ this . setPosition ( position , arrowDimensions ) ;
146
+ } ) ;
136
147
} ) ;
137
- } ) ;
148
+ }
138
149
}
0 commit comments