@radix-ng/primitives 0.51.0 → 1.0.0-beta.1

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 (186) hide show
  1. package/fesm2022/radix-ng-primitives-accordion.mjs +105 -38
  2. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  3. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +221 -129
  4. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-arrow.mjs +20 -4
  6. package/fesm2022/radix-ng-primitives-arrow.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-avatar.mjs +54 -61
  9. package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-button.mjs +123 -0
  11. package/fesm2022/radix-ng-primitives-button.mjs.map +1 -0
  12. package/fesm2022/radix-ng-primitives-calendar.mjs +95 -83
  13. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-checkbox.mjs +378 -54
  15. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-collapsible.mjs +182 -81
  17. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-collection.mjs +40 -57
  19. package/fesm2022/radix-ng-primitives-collection.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-context-menu.mjs +140 -424
  22. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-core.mjs +845 -744
  24. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-cropper.mjs +288 -308
  26. package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-date-field.mjs +104 -58
  28. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-dialog.mjs +655 -327
  30. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  31. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +70 -46
  32. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
  33. package/fesm2022/radix-ng-primitives-drawer.mjs +960 -0
  34. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -0
  35. package/fesm2022/radix-ng-primitives-editable.mjs +304 -23
  36. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  37. package/fesm2022/radix-ng-primitives-field.mjs +363 -0
  38. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -0
  39. package/fesm2022/radix-ng-primitives-fieldset.mjs +79 -0
  40. package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -0
  41. package/fesm2022/radix-ng-primitives-focus-scope.mjs +23 -8
  42. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  43. package/fesm2022/radix-ng-primitives-input.mjs +172 -0
  44. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -0
  45. package/fesm2022/radix-ng-primitives-label.mjs +6 -6
  46. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  47. package/fesm2022/radix-ng-primitives-menu.mjs +1907 -363
  48. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  49. package/fesm2022/radix-ng-primitives-menubar.mjs +290 -162
  50. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  51. package/fesm2022/radix-ng-primitives-meter.mjs +271 -0
  52. package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -0
  53. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +1052 -1553
  54. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  55. package/fesm2022/radix-ng-primitives-number-field.mjs +1102 -367
  56. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  57. package/fesm2022/radix-ng-primitives-pagination.mjs.map +1 -1
  58. package/fesm2022/radix-ng-primitives-popover.mjs +978 -989
  59. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  60. package/fesm2022/radix-ng-primitives-popper.mjs +111 -44
  61. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  62. package/fesm2022/radix-ng-primitives-portal.mjs +34 -10
  63. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  64. package/fesm2022/radix-ng-primitives-presence.mjs +134 -246
  65. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  66. package/fesm2022/radix-ng-primitives-preview-card.mjs +997 -0
  67. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -0
  68. package/fesm2022/radix-ng-primitives-progress.mjs +223 -84
  69. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  70. package/fesm2022/radix-ng-primitives-radio.mjs +191 -51
  71. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  72. package/fesm2022/radix-ng-primitives-roving-focus.mjs +96 -50
  73. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  74. package/fesm2022/radix-ng-primitives-scroll-area.mjs +923 -0
  75. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -0
  76. package/fesm2022/radix-ng-primitives-select.mjs +791 -509
  77. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  78. package/fesm2022/radix-ng-primitives-separator.mjs +12 -35
  79. package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
  80. package/fesm2022/radix-ng-primitives-slider.mjs +969 -717
  81. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  82. package/fesm2022/radix-ng-primitives-stepper.mjs +15 -19
  83. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  84. package/fesm2022/radix-ng-primitives-switch.mjs +125 -113
  85. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  86. package/fesm2022/radix-ng-primitives-tabs.mjs +390 -108
  87. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  88. package/fesm2022/radix-ng-primitives-time-field.mjs +55 -46
  89. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  90. package/fesm2022/radix-ng-primitives-toast.mjs +839 -0
  91. package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -0
  92. package/fesm2022/radix-ng-primitives-toggle-group.mjs +121 -247
  93. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  94. package/fesm2022/radix-ng-primitives-toggle.mjs +98 -61
  95. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  96. package/fesm2022/radix-ng-primitives-toolbar.mjs +303 -92
  97. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  98. package/fesm2022/radix-ng-primitives-tooltip.mjs +699 -1072
  99. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  100. package/fesm2022/radix-ng-primitives-visually-hidden.mjs +25 -66
  101. package/fesm2022/radix-ng-primitives-visually-hidden.mjs.map +1 -1
  102. package/meter/README.md +3 -0
  103. package/navigation-menu/README.md +2 -1
  104. package/package.json +39 -18
  105. package/portal/README.md +2 -0
  106. package/preview-card/README.md +3 -0
  107. package/schematics/collection.json +1 -0
  108. package/schematics/ng-add/index.d.ts +3 -2
  109. package/schematics/ng-add/index.js +62 -31
  110. package/schematics/ng-add/index.js.map +1 -1
  111. package/schematics/ng-add/package-config.d.ts +4 -2
  112. package/schematics/ng-add/package-config.js +10 -2
  113. package/schematics/ng-add/package-config.js.map +1 -1
  114. package/schematics/ng-add/schema.d.ts +3 -0
  115. package/schematics/ng-add/schema.js +3 -0
  116. package/schematics/ng-add/schema.js.map +1 -0
  117. package/schematics/ng-add/schema.json +14 -0
  118. package/select/README.md +2 -0
  119. package/types/radix-ng-primitives-accordion.d.ts +51 -16
  120. package/types/radix-ng-primitives-alert-dialog.d.ts +95 -38
  121. package/types/radix-ng-primitives-arrow.d.ts +1 -1
  122. package/types/radix-ng-primitives-aspect-ratio.d.ts +1 -1
  123. package/types/radix-ng-primitives-avatar.d.ts +7 -11
  124. package/types/radix-ng-primitives-button.d.ts +73 -0
  125. package/types/radix-ng-primitives-calendar.d.ts +39 -20
  126. package/types/radix-ng-primitives-checkbox.d.ts +204 -35
  127. package/types/radix-ng-primitives-collapsible.d.ts +114 -40
  128. package/types/radix-ng-primitives-collection.d.ts +38 -34
  129. package/types/radix-ng-primitives-config.d.ts +1 -1
  130. package/types/radix-ng-primitives-context-menu.d.ts +61 -116
  131. package/types/radix-ng-primitives-core.d.ts +345 -235
  132. package/types/radix-ng-primitives-cropper.d.ts +89 -56
  133. package/types/radix-ng-primitives-date-field.d.ts +49 -28
  134. package/types/radix-ng-primitives-dialog.d.ts +283 -165
  135. package/types/radix-ng-primitives-dismissable-layer.d.ts +15 -7
  136. package/types/radix-ng-primitives-drawer.d.ts +426 -0
  137. package/types/radix-ng-primitives-editable.d.ts +91 -14
  138. package/types/radix-ng-primitives-field.d.ts +374 -0
  139. package/types/radix-ng-primitives-fieldset.d.ts +49 -0
  140. package/types/radix-ng-primitives-focus-scope.d.ts +15 -6
  141. package/types/radix-ng-primitives-input.d.ts +87 -0
  142. package/types/radix-ng-primitives-label.d.ts +0 -1
  143. package/types/radix-ng-primitives-menu.d.ts +584 -99
  144. package/types/radix-ng-primitives-menubar.d.ts +61 -50
  145. package/types/radix-ng-primitives-meter.d.ts +194 -0
  146. package/types/radix-ng-primitives-navigation-menu.d.ts +422 -340
  147. package/types/radix-ng-primitives-number-field.d.ts +405 -145
  148. package/types/radix-ng-primitives-pagination.d.ts +2 -2
  149. package/types/radix-ng-primitives-popover.d.ts +366 -351
  150. package/types/radix-ng-primitives-popper.d.ts +68 -11
  151. package/types/radix-ng-primitives-portal.d.ts +14 -6
  152. package/types/radix-ng-primitives-presence.d.ts +28 -76
  153. package/types/radix-ng-primitives-preview-card.d.ts +359 -0
  154. package/types/radix-ng-primitives-progress.d.ts +175 -48
  155. package/types/radix-ng-primitives-radio.d.ts +55 -25
  156. package/types/radix-ng-primitives-roving-focus.d.ts +33 -23
  157. package/types/radix-ng-primitives-scroll-area.d.ts +253 -0
  158. package/types/radix-ng-primitives-select.d.ts +475 -177
  159. package/types/radix-ng-primitives-separator.d.ts +7 -32
  160. package/types/radix-ng-primitives-slider.d.ts +315 -201
  161. package/types/radix-ng-primitives-stepper.d.ts +5 -7
  162. package/types/radix-ng-primitives-switch.d.ts +86 -71
  163. package/types/radix-ng-primitives-tabs.d.ts +213 -79
  164. package/types/radix-ng-primitives-time-field.d.ts +42 -27
  165. package/types/radix-ng-primitives-toast.d.ts +378 -0
  166. package/types/radix-ng-primitives-toggle-group.d.ts +86 -164
  167. package/types/radix-ng-primitives-toggle.d.ts +43 -53
  168. package/types/radix-ng-primitives-toolbar.d.ts +164 -38
  169. package/types/radix-ng-primitives-tooltip.d.ts +348 -384
  170. package/types/radix-ng-primitives-visually-hidden.d.ts +19 -19
  171. package/dropdown-menu/README.md +0 -1
  172. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +0 -581
  173. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs.map +0 -1
  174. package/fesm2022/radix-ng-primitives-hover-card.mjs +0 -1238
  175. package/fesm2022/radix-ng-primitives-hover-card.mjs.map +0 -1
  176. package/fesm2022/radix-ng-primitives-select2.mjs +0 -897
  177. package/fesm2022/radix-ng-primitives-select2.mjs.map +0 -1
  178. package/fesm2022/radix-ng-primitives-tooltip2.mjs +0 -735
  179. package/fesm2022/radix-ng-primitives-tooltip2.mjs.map +0 -1
  180. package/hover-card/README.md +0 -3
  181. package/select2/README.md +0 -3
  182. package/tooltip2/README.md +0 -3
  183. package/types/radix-ng-primitives-dropdown-menu.d.ts +0 -171
  184. package/types/radix-ng-primitives-hover-card.d.ts +0 -471
  185. package/types/radix-ng-primitives-select2.d.ts +0 -511
  186. package/types/radix-ng-primitives-tooltip2.d.ts +0 -325
@@ -1,1200 +1,827 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, TemplateRef, DestroyRef, computed, input, numberAttribute, booleanAttribute, output, effect, untracked, SimpleChange, Directive, ElementRef, NgZone, Renderer2, isDevMode, VERSION, Injectable, makeEnvironmentProviders, signal, contentChild, ViewContainerRef, afterNextRender, assertInInjectionContext, forwardRef, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
3
- import * as i1 from '@angular/cdk/overlay';
4
- import { Overlay, CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
5
- import { RdxPositionSide, RdxPositionAlign, RDX_POSITIONING_DEFAULTS, getContentPosition, getAllPossibleConnectedPositions, injectDocument, injectWindow, getArrowPositionParams, getSideAndAlignFromAllPossibleConnectedPositions } from '@radix-ng/primitives/core';
6
- import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
7
- import { filter, tap, Subject, map, debounce, timer } from 'rxjs';
2
+ import { InjectionToken, inject, signal, numberAttribute, DestroyRef, input, Directive, model, booleanAttribute, output, computed, effect, untracked, ElementRef, afterNextRender } from '@angular/core';
3
+ import { createContext, injectId, watch, useGraceArea } from '@radix-ng/primitives/core';
4
+ import * as i1 from '@radix-ng/primitives/popper';
5
+ import { RdxPopper, RdxPopperContentWrapper, RdxPopperArrow, RdxPopperContent, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
6
+ import { RdxVisuallyHiddenDirective } from '@radix-ng/primitives/visually-hidden';
7
+ import * as i1$1 from '@radix-ng/primitives/portal';
8
+ import { RdxPortal } from '@radix-ng/primitives/portal';
9
+ import * as i1$2 from '@radix-ng/primitives/presence';
10
+ import { provideRdxPresenceContext, RdxPresenceDirective } from '@radix-ng/primitives/presence';
11
+ import { outputFromObservable, outputToObservable } from '@angular/core/rxjs-interop';
12
+ import * as i1$3 from '@radix-ng/primitives/dismissable-layer';
13
+ import { RdxDismissableLayer } from '@radix-ng/primitives/dismissable-layer';
8
14
 
9
- const RdxTooltipAnchorToken = new InjectionToken('RdxTooltipAnchorToken');
10
-
11
- const RdxTooltipArrowToken = new InjectionToken('RdxTooltipArrowToken');
12
-
13
- const RdxTooltipCloseToken = new InjectionToken('RdxTooltipCloseToken');
15
+ const defaultTooltipConfig = {
16
+ delay: 600,
17
+ closeDelay: 0,
18
+ timeout: 400,
19
+ disableHoverablePopup: false
20
+ };
21
+ const RdxTooltipDefaultsToken = new InjectionToken('RdxTooltipDefaultsToken');
22
+ function provideRdxTooltipConfig(config) {
23
+ return [
24
+ {
25
+ provide: RdxTooltipDefaultsToken,
26
+ useValue: { ...defaultTooltipConfig, ...config }
27
+ }
28
+ ];
29
+ }
30
+ function injectRdxTooltipConfig() {
31
+ return { ...defaultTooltipConfig, ...inject(RdxTooltipDefaultsToken, { optional: true }) };
32
+ }
14
33
 
15
- const RdxTooltipContentAttributesToken = new InjectionToken('RdxTooltipContentAttributesToken');
34
+ /**
35
+ * Tracks the shared "instant" window for a group of tooltips. Once one tooltip
36
+ * opens, sibling tooltips open instantly until `timeout` ms after the last close.
37
+ */
38
+ function createTooltipInstantController(timeout, destroyRef) {
39
+ const instant = signal(false, ...(ngDevMode ? [{ debugName: "instant" }] : /* istanbul ignore next */ []));
40
+ const timer = useTimeoutFn(() => instant.set(false), timeout, { immediate: false }, destroyRef);
41
+ return {
42
+ isInstant: instant.asReadonly(),
43
+ onOpen: () => {
44
+ timer.stop();
45
+ instant.set(true);
46
+ },
47
+ onClose: () => {
48
+ timer.start();
49
+ }
50
+ };
51
+ }
52
+ function useTimeoutFn(cb, delay, options = {}, destroyRef) {
53
+ let id = null;
54
+ const resolveDelay = () => (typeof delay === 'function' ? delay() : delay);
55
+ const stop = () => {
56
+ if (id != null) {
57
+ clearTimeout(id);
58
+ id = null;
59
+ }
60
+ };
61
+ const start = () => {
62
+ stop();
63
+ const ms = resolveDelay();
64
+ if (ms <= 0) {
65
+ queueMicrotask(cb);
66
+ return;
67
+ }
68
+ id = window.setTimeout(() => {
69
+ id = null;
70
+ cb();
71
+ }, ms);
72
+ };
73
+ if (options.immediate) {
74
+ start();
75
+ }
76
+ if (destroyRef) {
77
+ destroyRef.onDestroy(stop);
78
+ }
79
+ return { start, stop, isPending: () => id != null };
80
+ }
16
81
 
17
- var RdxTooltipState;
18
- (function (RdxTooltipState) {
19
- RdxTooltipState["OPEN"] = "open";
20
- RdxTooltipState["CLOSED"] = "closed";
21
- })(RdxTooltipState || (RdxTooltipState = {}));
22
- var RdxTooltipAction;
23
- (function (RdxTooltipAction) {
24
- RdxTooltipAction["OPEN"] = "open";
25
- RdxTooltipAction["CLOSE"] = "close";
26
- })(RdxTooltipAction || (RdxTooltipAction = {}));
27
- var RdxTooltipAttachDetachEvent;
28
- (function (RdxTooltipAttachDetachEvent) {
29
- RdxTooltipAttachDetachEvent["ATTACH"] = "attach";
30
- RdxTooltipAttachDetachEvent["DETACH"] = "detach";
31
- })(RdxTooltipAttachDetachEvent || (RdxTooltipAttachDetachEvent = {}));
32
- var RdxTooltipAnimationStatus;
33
- (function (RdxTooltipAnimationStatus) {
34
- RdxTooltipAnimationStatus["OPEN_STARTED"] = "open_started";
35
- RdxTooltipAnimationStatus["OPEN_ENDED"] = "open_ended";
36
- RdxTooltipAnimationStatus["CLOSED_STARTED"] = "closed_started";
37
- RdxTooltipAnimationStatus["CLOSED_ENDED"] = "closed_ended";
38
- })(RdxTooltipAnimationStatus || (RdxTooltipAnimationStatus = {}));
82
+ const [injectRdxTooltipProviderContext, provideRdxTooltipProviderContext] = createContext('RdxTooltipProviderContext');
83
+ const numberOrUndefined = (value) => (value == null ? undefined : numberAttribute(value));
84
+ const providerContext = () => {
85
+ const provider = inject(RdxTooltipProvider);
86
+ return {
87
+ delay: provider.delay,
88
+ closeDelay: provider.closeDelay,
89
+ isInstant: provider.instant.isInstant,
90
+ onOpen: () => provider.instant.onOpen(),
91
+ onClose: () => provider.instant.onClose()
92
+ };
93
+ };
94
+ /**
95
+ * Shares delay configuration and an instant-open window across a group of tooltips.
96
+ * Once one tooltip opens, adjacent ones open instantly until `timeout` ms after the last close.
97
+ */
98
+ class RdxTooltipProvider {
99
+ constructor() {
100
+ this.defaultConfig = injectRdxTooltipConfig();
101
+ this.destroyRef = inject(DestroyRef);
102
+ /**
103
+ * How long to wait before opening tooltips in this group. Specified in milliseconds.
104
+ */
105
+ this.delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: numberOrUndefined });
106
+ /**
107
+ * How long to wait before closing tooltips in this group. Specified in milliseconds.
108
+ */
109
+ this.closeDelay = input(undefined, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: numberOrUndefined });
110
+ /**
111
+ * The window during which an adjacent tooltip opens instantly. Specified in milliseconds.
112
+ */
113
+ this.timeout = input(this.defaultConfig.timeout, { ...(ngDevMode ? { debugName: "timeout" } : /* istanbul ignore next */ {}), transform: numberAttribute });
114
+ this.instant = createTooltipInstantController(() => this.timeout(), this.destroyRef);
115
+ }
116
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipProvider, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
117
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipProvider, isStandalone: true, selector: "[rdxTooltipProvider]", inputs: { delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, timeout: { classPropertyName: "timeout", publicName: "timeout", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideRdxTooltipProviderContext(providerContext)], exportAs: ["rdxTooltipProvider"], ngImport: i0 }); }
118
+ }
119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipProvider, decorators: [{
120
+ type: Directive,
121
+ args: [{
122
+ selector: '[rdxTooltipProvider]',
123
+ exportAs: 'rdxTooltipProvider',
124
+ providers: [provideRdxTooltipProviderContext(providerContext)]
125
+ }]
126
+ }], propDecorators: { delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], timeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeout", required: false }] }] } });
39
127
 
40
- class RdxTooltipContentDirective {
128
+ const [injectRdxTooltipContext, provideRdxTooltipContext] = createContext('RdxTooltipContext');
129
+ const context = () => contextFor(inject(RdxTooltip));
130
+ class RdxTooltip {
41
131
  constructor() {
42
- /** @ignore */
43
- this.rootDirective = injectTooltipRoot();
44
- /** @ignore */
45
- this.templateRef = inject(TemplateRef);
46
- /** @ignore */
47
- this.overlay = inject(Overlay);
48
- /** @ignore */
132
+ this.defaultConfig = injectRdxTooltipConfig();
133
+ this.provider = injectRdxTooltipProviderContext(true);
134
+ this.popper = inject(RdxPopper);
49
135
  this.destroyRef = inject(DestroyRef);
50
- /** @ignore */
51
- this.connectedOverlay = inject(CdkConnectedOverlay);
52
- /** @ignore */
53
- this.name = computed(() => `rdx-tooltip-trigger-${this.rootDirective.uniqueId()}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
136
+ this.hasAppliedDefaultOpen = false;
54
137
  /**
55
- * @description The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.
56
- * @default top
138
+ * Whether the tooltip is currently open.
57
139
  */
58
- this.side = input(RdxPositionSide.Top, ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
140
+ this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
59
141
  /**
60
- * @description The distance in pixels from the trigger.
61
- * @default undefined
142
+ * Whether the tooltip is initially open. Uncontrolled.
62
143
  */
63
- this.sideOffset = input(NaN, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
144
+ this.defaultOpen = input(false, { ...(ngDevMode ? { debugName: "defaultOpen" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
64
145
  /**
65
- * @description The preferred alignment against the trigger. May change when collisions occur.
66
- * @default center
146
+ * How long to wait before opening the tooltip. Specified in milliseconds.
147
+ * Falls back to the surrounding provider, then to the global config.
67
148
  */
68
- this.align = input(RdxPositionAlign.Center, ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
149
+ this.delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
69
150
  /**
70
- * @description An offset in pixels from the "start" or "end" alignment options.
71
- * @default undefined
151
+ * How long to wait before closing the tooltip. Specified in milliseconds.
72
152
  */
73
- this.alignOffset = input(NaN, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
153
+ this.closeDelay = input(undefined, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
74
154
  /**
75
- * @description Whether to add some alternate positions of the content.
76
- * @default false
155
+ * When `true`, the tooltip closes as the pointer leaves the trigger instead of
156
+ * staying open while the pointer moves over the popup.
77
157
  */
78
- this.alternatePositionsDisabled = input(false, { ...(ngDevMode ? { debugName: "alternatePositionsDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
79
- /** @description Whether to prevent `onOverlayEscapeKeyDown` handler from calling. */
80
- this.onOverlayEscapeKeyDownDisabled = input(false, { ...(ngDevMode ? { debugName: "onOverlayEscapeKeyDownDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
81
- /** @description Whether to prevent `onOverlayOutsideClick` handler from calling. */
82
- this.onOverlayOutsideClickDisabled = input(false, { ...(ngDevMode ? { debugName: "onOverlayOutsideClickDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
158
+ this.disableHoverablePopup = input(this.defaultConfig.disableHoverablePopup, { ...(ngDevMode ? { debugName: "disableHoverablePopup" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
83
159
  /**
84
- * @description Event handler called when the escape key is down.
85
- * It can be prevented by setting `onOverlayEscapeKeyDownDisabled` input to `true`.
160
+ * Determines which axis the tooltip should track the cursor on.
86
161
  */
87
- this.onOverlayEscapeKeyDown = output();
162
+ this.trackCursorAxis = input('none', ...(ngDevMode ? [{ debugName: "trackCursorAxis" }] : /* istanbul ignore next */ []));
88
163
  /**
89
- * @description Event handler called when a pointer event occurs outside the bounds of the component.
90
- * It can be prevented by setting `onOverlayOutsideClickDisabled` input to `true`.
164
+ * When `true`, the tooltip will not open.
91
165
  */
92
- this.onOverlayOutsideClick = output();
166
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
93
167
  /**
94
- * @description Event handler called after the overlay is open
168
+ * Associates this root with detached trigger elements.
95
169
  */
96
- this.onOpen = output();
170
+ this.handle = input(...(ngDevMode ? [undefined, { debugName: "handle" }] : /* istanbul ignore next */ []));
97
171
  /**
98
- * @description Event handler called after the overlay is closed
172
+ * Event handler called when the open state changes.
99
173
  */
100
- this.onClosed = output();
101
- /** @ingore */
102
- this.positions = computed(() => this.computePositions(), ...(ngDevMode ? [{ debugName: "positions" }] : /* istanbul ignore next */ []));
103
- this.onOriginChangeEffect();
104
- this.onPositionChangeEffect();
174
+ this.onOpenChange = output();
175
+ this.contentId = injectId('rdx-tooltip-content-');
176
+ this.trigger = signal(undefined, ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
177
+ this.triggers = signal([], ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
178
+ this.payload = signal(undefined, ...(ngDevMode ? [{ debugName: "payload" }] : /* istanbul ignore next */ []));
179
+ this.cursorPosition = signal(undefined, ...(ngDevMode ? [{ debugName: "cursorPosition" }] : /* istanbul ignore next */ []));
180
+ this.openedInstant = signal(false, ...(ngDevMode ? [{ debugName: "openedInstant" }] : /* istanbul ignore next */ []));
181
+ /** Local instant window used when this tooltip is not inside a provider. */
182
+ this.localInstant = createTooltipInstantController(() => this.defaultConfig.timeout, this.destroyRef);
183
+ this.instantGroup = this.provider ?? this.localInstant;
184
+ /** Per-trigger overrides set by the active trigger, taking precedence over the root/provider. */
185
+ this.triggerDelay = signal(undefined, ...(ngDevMode ? [{ debugName: "triggerDelay" }] : /* istanbul ignore next */ []));
186
+ this.triggerCloseDelay = signal(undefined, ...(ngDevMode ? [{ debugName: "triggerCloseDelay" }] : /* istanbul ignore next */ []));
187
+ this.resolvedDelay = computed(() => this.triggerDelay() ?? this.delay() ?? this.provider?.delay() ?? this.defaultConfig.delay, ...(ngDevMode ? [{ debugName: "resolvedDelay" }] : /* istanbul ignore next */ []));
188
+ this.resolvedCloseDelay = computed(() => this.triggerCloseDelay() ??
189
+ this.closeDelay() ??
190
+ this.provider?.closeDelay() ??
191
+ this.defaultConfig.closeDelay, ...(ngDevMode ? [{ debugName: "resolvedCloseDelay" }] : /* istanbul ignore next */ []));
192
+ /** Whether the most recent open happened without the delay. */
193
+ this.instant = this.openedInstant.asReadonly();
194
+ this.virtualAnchor = computed(() => {
195
+ const axis = this.trackCursorAxis();
196
+ const element = this.trigger();
197
+ if (axis === 'none' || !element) {
198
+ return element;
199
+ }
200
+ const position = this.cursorPosition();
201
+ if (!position) {
202
+ return element;
203
+ }
204
+ const followX = axis === 'x' || axis === 'both';
205
+ const followY = axis === 'y' || axis === 'both';
206
+ return {
207
+ getBoundingClientRect: () => {
208
+ const rect = element.getBoundingClientRect();
209
+ const width = followX ? 0 : rect.width;
210
+ const height = followY ? 0 : rect.height;
211
+ const x = followX ? position.x : rect.x;
212
+ const y = followY ? position.y : rect.y;
213
+ return { width, height, x, y, top: y, left: x, right: x + width, bottom: y + height };
214
+ }
215
+ };
216
+ }, ...(ngDevMode ? [{ debugName: "virtualAnchor" }] : /* istanbul ignore next */ []));
217
+ this.openTimer = useTimeoutFn(() => this.applyOpen(false), () => this.resolvedDelay(), { immediate: false }, this.destroyRef);
218
+ this.closeTimer = useTimeoutFn(() => this.applyClose(), () => this.resolvedCloseDelay(), { immediate: false }, this.destroyRef);
219
+ effect(() => {
220
+ const defaultOpen = this.defaultOpen();
221
+ if (!this.hasAppliedDefaultOpen && defaultOpen) {
222
+ this.hasAppliedDefaultOpen = true;
223
+ this.open.set(defaultOpen);
224
+ }
225
+ });
226
+ effect((onCleanup) => {
227
+ const handle = this.handle();
228
+ if (handle) {
229
+ onCleanup(untracked(() => handle.registerRoot(contextFor(this))));
230
+ }
231
+ });
232
+ // Keep the popper anchored to the active trigger, or to the cursor while tracking.
233
+ effect(() => this.popper.anchorOverride.set(this.virtualAnchor()));
234
+ watch([this.open], ([isOpen]) => {
235
+ this.onOpenChange.emit(isOpen);
236
+ if (isOpen) {
237
+ this.instantGroup.onOpen();
238
+ }
239
+ else {
240
+ this.instantGroup.onClose();
241
+ this.openedInstant.set(false);
242
+ }
243
+ }, { defer: true });
105
244
  }
106
- /** @ignore */
107
- ngOnInit() {
108
- this.setScrollStrategy();
109
- this.setHasBackdrop();
110
- this.setDisableClose();
111
- this.onAttach();
112
- this.onDetach();
113
- this.connectKeydownEscape();
114
- this.connectOutsideClick();
245
+ /** Opens immediately, optionally switching the active trigger/payload. */
246
+ show(trigger = this.trigger(), payload) {
247
+ this.applyOpen(true, trigger, payload);
115
248
  }
116
- /** @ignore */
117
- open() {
118
- if (this.connectedOverlay.open) {
119
- return;
249
+ close() {
250
+ this.openTimer.stop();
251
+ this.closeTimer.stop();
252
+ this.applyClose();
253
+ }
254
+ /** Closes after the resolved close delay, e.g. when the pointer or focus leaves. */
255
+ scheduleClose() {
256
+ this.openTimer.stop();
257
+ if (this.resolvedCloseDelay() <= 0) {
258
+ this.applyClose();
259
+ }
260
+ else {
261
+ this.closeTimer.start();
120
262
  }
121
- const prevOpen = this.connectedOverlay.open;
122
- this.connectedOverlay.open = true;
123
- this.fireOverlayNgOnChanges('open', this.connectedOverlay.open, prevOpen);
124
263
  }
125
- /** @ignore */
126
- close() {
127
- if (!this.connectedOverlay.open) {
264
+ /** Hover/focus entered — open after the delay, or instantly within the instant window. */
265
+ onTriggerEnter(trigger = this.trigger(), payload) {
266
+ if (this.disabled()) {
128
267
  return;
129
268
  }
130
- const prevOpen = this.connectedOverlay.open;
131
- this.connectedOverlay.open = false;
132
- this.fireOverlayNgOnChanges('open', this.connectedOverlay.open, prevOpen);
133
- }
134
- /** @ignore */
135
- positionChange() {
136
- return this.connectedOverlay.positionChange.asObservable();
137
- }
138
- /** @ignore */
139
- connectKeydownEscape() {
140
- this.connectedOverlay.overlayKeydown
141
- .asObservable()
142
- .pipe(filter(() => !this.onOverlayEscapeKeyDownDisabled() &&
143
- !this.rootDirective.rdxCdkEventService?.primitivePreventedFromCdkEvent(this.rootDirective, 'cdkOverlayEscapeKeyDown')), filter((event) => event.key === 'Escape'), tap((event) => {
144
- this.onOverlayEscapeKeyDown.emit(event);
145
- }), filter(() => !this.rootDirective.firstDefaultOpen()), tap(() => {
146
- this.rootDirective.handleClose();
147
- }), takeUntilDestroyed(this.destroyRef))
148
- .subscribe();
149
- }
150
- /** @ignore */
151
- connectOutsideClick() {
152
- this.connectedOverlay.overlayOutsideClick
153
- .asObservable()
154
- .pipe(filter(() => !this.onOverlayOutsideClickDisabled() &&
155
- !this.rootDirective.rdxCdkEventService?.primitivePreventedFromCdkEvent(this.rootDirective, 'cdkOverlayOutsideClick')),
156
- /**
157
- * Handle the situation when an anchor is added and the anchor becomes the origin of the overlay
158
- * hence the trigger will be considered the outside element
159
- */
160
- filter((event) => {
161
- return (!this.rootDirective.anchorDirective() ||
162
- !this.rootDirective
163
- .triggerDirective()
164
- .elementRef.nativeElement.contains(event.target));
165
- }), tap((event) => {
166
- this.onOverlayOutsideClick.emit(event);
167
- }), filter(() => !this.rootDirective.firstDefaultOpen()), tap(() => {
168
- this.rootDirective.handleClose();
169
- }), takeUntilDestroyed(this.destroyRef))
170
- .subscribe();
171
- }
172
- /** @ignore */
173
- onAttach() {
174
- this.connectedOverlay.attach
175
- .asObservable()
176
- .pipe(tap(() => {
177
- /**
178
- * `this.onOpen.emit();` is being delegated to the rootDirective directive due to the opening animation
179
- */
180
- this.rootDirective.attachDetachEvent.set(RdxTooltipAttachDetachEvent.ATTACH);
181
- }), takeUntilDestroyed(this.destroyRef))
182
- .subscribe();
183
- }
184
- /** @ignore */
185
- onDetach() {
186
- this.connectedOverlay.detach
187
- .asObservable()
188
- .pipe(tap(() => {
189
- /**
190
- * `this.onClosed.emit();` is being delegated to the rootDirective directive due to the closing animation
191
- */
192
- this.rootDirective.attachDetachEvent.set(RdxTooltipAttachDetachEvent.DETACH);
193
- }), takeUntilDestroyed(this.destroyRef))
194
- .subscribe();
195
- }
196
- /** @ignore */
197
- setScrollStrategy() {
198
- const prevScrollStrategy = this.connectedOverlay.scrollStrategy;
199
- this.connectedOverlay.scrollStrategy = this.overlay.scrollStrategies.reposition();
200
- this.fireOverlayNgOnChanges('scrollStrategy', this.connectedOverlay.scrollStrategy, prevScrollStrategy);
269
+ if (trigger) {
270
+ this.trigger.set(trigger);
271
+ }
272
+ this.payload.set(payload);
273
+ this.closeTimer.stop();
274
+ if (this.instantGroup.isInstant() || this.resolvedDelay() <= 0) {
275
+ this.applyOpen(true, trigger, payload);
276
+ }
277
+ else {
278
+ this.openTimer.start();
279
+ }
201
280
  }
202
- /** @ignore */
203
- setHasBackdrop() {
204
- const prevHasBackdrop = this.connectedOverlay.hasBackdrop;
205
- this.connectedOverlay.hasBackdrop = false;
206
- this.fireOverlayNgOnChanges('hasBackdrop', this.connectedOverlay.hasBackdrop, prevHasBackdrop);
281
+ onTriggerLeave() {
282
+ this.openTimer.stop();
283
+ if (this.disableHoverablePopup()) {
284
+ this.scheduleClose();
285
+ }
286
+ // Otherwise the positioner's grace area decides when to close.
207
287
  }
208
- /** @ignore */
209
- setDisableClose() {
210
- const prevDisableClose = this.connectedOverlay.disableClose;
211
- this.connectedOverlay.disableClose = true;
212
- this.fireOverlayNgOnChanges('disableClose', this.connectedOverlay.disableClose, prevDisableClose);
288
+ registerTrigger(trigger) {
289
+ this.triggers.update((triggers) => (triggers.includes(trigger) ? triggers : [...triggers, trigger]));
290
+ if (!this.trigger()) {
291
+ this.trigger.set(trigger);
292
+ }
293
+ return () => {
294
+ this.triggers.update((triggers) => triggers.filter((candidate) => candidate !== trigger));
295
+ if (this.trigger() === trigger) {
296
+ const nextTrigger = this.triggers()[0];
297
+ this.trigger.set(nextTrigger);
298
+ if (!nextTrigger && !this.destroyRef.destroyed) {
299
+ this.applyClose();
300
+ }
301
+ }
302
+ };
213
303
  }
214
- /** @ignore */
215
- setOrigin(origin) {
216
- const prevOrigin = this.connectedOverlay.origin;
217
- this.connectedOverlay.origin = origin;
218
- this.fireOverlayNgOnChanges('origin', this.connectedOverlay.origin, prevOrigin);
304
+ setCursorPosition(position) {
305
+ this.cursorPosition.set(position);
219
306
  }
220
- /** @ignore */
221
- setPositions(positions) {
222
- const prevPositions = this.connectedOverlay.positions;
223
- this.connectedOverlay.positions = positions;
224
- this.fireOverlayNgOnChanges('positions', this.connectedOverlay.positions, prevPositions);
225
- this.connectedOverlay.overlayRef?.updatePosition();
307
+ /** Applies per-trigger delay overrides from the trigger that is becoming active. */
308
+ setDelays(delay, closeDelay) {
309
+ this.triggerDelay.set(delay);
310
+ this.triggerCloseDelay.set(closeDelay);
226
311
  }
227
- /** @ignore */
228
- computePositions() {
229
- const arrowHeight = this.rootDirective.arrowDirective()?.height() ?? 0;
230
- const offsets = {
231
- sideOffset: arrowHeight + (isNaN(this.sideOffset()) ? RDX_POSITIONING_DEFAULTS.offsets.side : this.sideOffset()),
232
- alignOffset: isNaN(this.alignOffset()) ? RDX_POSITIONING_DEFAULTS.offsets.align : this.alignOffset()
233
- };
234
- const basePosition = getContentPosition({
235
- side: this.side(),
236
- align: this.align(),
237
- sideOffset: offsets.sideOffset,
238
- alignOffset: offsets.alignOffset
239
- });
240
- const positions = [basePosition];
241
- if (!this.alternatePositionsDisabled()) {
242
- /**
243
- * Alternate positions for better user experience along the X/Y axis (e.g. vertical/horizontal scrolling)
244
- */
245
- const allPossibleConnectedPositions = getAllPossibleConnectedPositions();
246
- allPossibleConnectedPositions.forEach((_, key) => {
247
- const sideAndAlignArray = key.split('|');
248
- if (sideAndAlignArray[0] !== this.side() ||
249
- sideAndAlignArray[1] !== this.align()) {
250
- positions.push(getContentPosition({
251
- side: sideAndAlignArray[0],
252
- align: sideAndAlignArray[1],
253
- sideOffset: offsets.sideOffset,
254
- alignOffset: offsets.alignOffset
255
- }));
256
- }
257
- });
312
+ applyOpen(instant, trigger = this.trigger(), payload) {
313
+ if (this.disabled()) {
314
+ return;
258
315
  }
259
- return positions;
260
- }
261
- onOriginChangeEffect() {
262
- effect(() => {
263
- const origin = (this.rootDirective.anchorDirective() ?? this.rootDirective.triggerDirective())
264
- .overlayOrigin;
265
- untracked(() => {
266
- this.setOrigin(origin);
267
- });
268
- });
316
+ this.openTimer.stop();
317
+ this.closeTimer.stop();
318
+ if (trigger) {
319
+ this.trigger.set(trigger);
320
+ }
321
+ if (payload !== undefined) {
322
+ this.payload.set(payload);
323
+ }
324
+ this.openedInstant.set(instant || this.instantGroup.isInstant());
325
+ this.open.set(true);
269
326
  }
270
- /** @ignore */
271
- onPositionChangeEffect() {
272
- effect(() => {
273
- const positions = this.positions();
274
- this.alternatePositionsDisabled();
275
- untracked(() => {
276
- this.setPositions(positions);
277
- });
278
- });
327
+ applyClose() {
328
+ this.openedInstant.set(this.instantGroup.isInstant());
329
+ this.open.set(false);
279
330
  }
280
- /** @ignore */
281
- fireOverlayNgOnChanges(input, currentValue, previousValue, firstChange = false) {
282
- this.connectedOverlay.ngOnChanges({
283
- [input]: new SimpleChange(previousValue, currentValue, firstChange)
331
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
332
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltip, isStandalone: true, selector: "[rdxTooltip]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, disableHoverablePopup: { classPropertyName: "disableHoverablePopup", publicName: "disableHoverablePopup", isSignal: true, isRequired: false, transformFunction: null }, trackCursorAxis: { classPropertyName: "trackCursorAxis", publicName: "trackCursorAxis", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", onOpenChange: "onOpenChange" }, providers: [provideRdxTooltipContext(context)], exportAs: ["rdxTooltip"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
333
+ }
334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltip, decorators: [{
335
+ type: Directive,
336
+ args: [{
337
+ selector: '[rdxTooltip]',
338
+ exportAs: 'rdxTooltip',
339
+ providers: [provideRdxTooltipContext(context)],
340
+ hostDirectives: [RdxPopper]
341
+ }]
342
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], disableHoverablePopup: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableHoverablePopup", required: false }] }], trackCursorAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackCursorAxis", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }] } });
343
+ function contextFor(root) {
344
+ return {
345
+ contentId: root.contentId,
346
+ isOpen: root.open,
347
+ instant: root.instant,
348
+ disabled: root.disabled,
349
+ disableHoverablePopup: root.disableHoverablePopup,
350
+ trackCursorAxis: root.trackCursorAxis,
351
+ trigger: root.trigger.asReadonly(),
352
+ triggers: root.triggers.asReadonly(),
353
+ payload: root.payload.asReadonly(),
354
+ open: (trigger, payload) => root.show(trigger, payload),
355
+ close: () => root.close(),
356
+ closeDelayed: () => root.scheduleClose(),
357
+ registerTrigger: (trigger) => root.registerTrigger(trigger),
358
+ onTriggerEnter: (trigger, payload) => root.onTriggerEnter(trigger, payload),
359
+ onTriggerLeave: () => root.onTriggerLeave(),
360
+ setCursorPosition: (position) => root.setCursorPosition(position),
361
+ setDelays: (delay, closeDelay) => root.setDelays(delay, closeDelay)
362
+ };
363
+ }
364
+
365
+ class RdxTooltipArrow {
366
+ constructor() {
367
+ this.rootContext = injectRdxTooltipContext();
368
+ this.wrapper = inject(RdxPopperContentWrapper, { optional: true });
369
+ this.side = computed(() => this.wrapper?.placedSide(), ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
370
+ this.align = computed(() => this.wrapper?.placedAlign(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
371
+ this.uncentered = computed(() => this.wrapper?.arrowUncentered() ?? false, ...(ngDevMode ? [{ debugName: "uncentered" }] : /* istanbul ignore next */ []));
372
+ this.isVisuallyHidden = !!inject(RdxVisuallyHiddenDirective, {
373
+ optional: true
284
374
  });
285
375
  }
286
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
287
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipContentDirective, isStandalone: true, selector: "[rdxTooltipContent]", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, alternatePositionsDisabled: { classPropertyName: "alternatePositionsDisabled", publicName: "alternatePositionsDisabled", isSignal: true, isRequired: false, transformFunction: null }, onOverlayEscapeKeyDownDisabled: { classPropertyName: "onOverlayEscapeKeyDownDisabled", publicName: "onOverlayEscapeKeyDownDisabled", isSignal: true, isRequired: false, transformFunction: null }, onOverlayOutsideClickDisabled: { classPropertyName: "onOverlayOutsideClickDisabled", publicName: "onOverlayOutsideClickDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOverlayEscapeKeyDown: "onOverlayEscapeKeyDown", onOverlayOutsideClick: "onOverlayOutsideClick", onOpen: "onOpen", onClosed: "onClosed" }, hostDirectives: [{ directive: i1.CdkConnectedOverlay }], ngImport: i0 }); }
376
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipArrow, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
377
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipArrow, isStandalone: true, selector: "[rdxTooltipArrow]", host: { properties: { "hidden": "isVisuallyHidden", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-side": "side()", "attr.data-align": "align()", "attr.data-uncentered": "uncentered() ? \"\" : undefined" } }, hostDirectives: [{ directive: i1.RdxPopperArrow }], ngImport: i0 }); }
288
378
  }
289
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipContentDirective, decorators: [{
379
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipArrow, decorators: [{
290
380
  type: Directive,
291
381
  args: [{
292
- selector: '[rdxTooltipContent]',
293
- hostDirectives: [CdkConnectedOverlay]
382
+ selector: '[rdxTooltipArrow]',
383
+ hostDirectives: [RdxPopperArrow],
384
+ host: {
385
+ '[hidden]': 'isVisuallyHidden',
386
+ '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
387
+ '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
388
+ '[attr.data-side]': 'side()',
389
+ '[attr.data-align]': 'align()',
390
+ '[attr.data-uncentered]': 'uncentered() ? "" : undefined'
391
+ }
294
392
  }]
295
- }], ctorParameters: () => [], propDecorators: { side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], alternatePositionsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "alternatePositionsDisabled", required: false }] }], onOverlayEscapeKeyDownDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "onOverlayEscapeKeyDownDisabled", required: false }] }], onOverlayOutsideClickDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "onOverlayOutsideClickDisabled", required: false }] }], onOverlayEscapeKeyDown: [{ type: i0.Output, args: ["onOverlayEscapeKeyDown"] }], onOverlayOutsideClick: [{ type: i0.Output, args: ["onOverlayOutsideClick"] }], onOpen: [{ type: i0.Output, args: ["onOpen"] }], onClosed: [{ type: i0.Output, args: ["onClosed"] }] } });
393
+ }] });
296
394
 
297
- class RdxTooltipTriggerDirective {
395
+ /**
396
+ * The tooltip popup. Renders the content with `role="tooltip"`.
397
+ */
398
+ class RdxTooltipPopup {
298
399
  constructor() {
299
- /** @ignore */
300
- this.rootDirective = injectTooltipRoot();
301
- /** @ignore */
302
- this.elementRef = inject(ElementRef);
303
- /** @ignore */
304
- this.overlayOrigin = inject(CdkOverlayOrigin);
305
- /** @ignore */
306
- this.name = computed(() => `rdx-tooltip-trigger-${this.rootDirective.uniqueId()}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
307
- }
308
- /** @ignore */
309
- pointerenter() {
310
- this.rootDirective.handleOpen();
400
+ this.rootContext = injectRdxTooltipContext();
401
+ this.wrapper = inject(RdxPopperContentWrapper, { optional: true });
402
+ this.side = computed(() => this.wrapper?.placedSide(), ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
403
+ this.align = computed(() => this.wrapper?.placedAlign(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
311
404
  }
312
- /** @ignore */
313
- pointerleave() {
314
- this.rootDirective.handleClose();
315
- }
316
- /** @ignore */
317
- focus() {
318
- this.rootDirective.handleOpen();
319
- }
320
- /** @ignore */
321
- blur() {
322
- this.rootDirective.handleClose();
323
- }
324
- /** @ignore */
325
- click() {
326
- this.rootDirective.handleClose();
327
- }
328
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
329
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipTriggerDirective, isStandalone: true, selector: "[rdxTooltipTrigger]", host: { attributes: { "type": "button" }, listeners: { "pointerenter": "pointerenter()", "pointerleave": "pointerleave()", "focus": "focus()", "blur": "blur()", "click": "click()" }, properties: { "attr.id": "name()", "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "rootDirective.isOpen()", "attr.aria-controls": "rootDirective.contentDirective().name()", "attr.data-state": "rootDirective.state()" } }, hostDirectives: [{ directive: i1.CdkOverlayOrigin }], ngImport: i0 }); }
405
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
406
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipPopup, isStandalone: true, selector: "[rdxTooltipPopup]", host: { attributes: { "role": "tooltip" }, properties: { "id": "rootContext.contentId", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "attr.data-side": "side()", "attr.data-align": "align()" } }, hostDirectives: [{ directive: i1.RdxPopperContent }], ngImport: i0 }); }
330
407
  }
331
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTriggerDirective, decorators: [{
408
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPopup, decorators: [{
332
409
  type: Directive,
333
410
  args: [{
334
- selector: '[rdxTooltipTrigger]',
335
- hostDirectives: [CdkOverlayOrigin],
411
+ selector: '[rdxTooltipPopup]',
412
+ hostDirectives: [RdxPopperContent],
336
413
  host: {
337
- type: 'button',
338
- '[attr.id]': 'name()',
339
- '[attr.aria-haspopup]': '"dialog"',
340
- '[attr.aria-expanded]': 'rootDirective.isOpen()',
341
- '[attr.aria-controls]': 'rootDirective.contentDirective().name()',
342
- '[attr.data-state]': 'rootDirective.state()',
343
- '(pointerenter)': 'pointerenter()',
344
- '(pointerleave)': 'pointerleave()',
345
- '(focus)': 'focus()',
346
- '(blur)': 'blur()',
347
- '(click)': 'click()'
414
+ role: 'tooltip',
415
+ '[id]': 'rootContext.contentId',
416
+ '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
417
+ '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
418
+ '[attr.data-instant]': 'rootContext.instant() ? "" : undefined',
419
+ '[attr.data-side]': 'side()',
420
+ '[attr.data-align]': 'align()'
348
421
  }
349
422
  }]
350
423
  }] });
351
424
 
352
- const RdxCdkEventServiceWindowKey = Symbol('__RdxCdkEventService__');
425
+ /**
426
+ * Moves the tooltip to a different part of the DOM.
427
+ */
428
+ class RdxTooltipPortal {
429
+ constructor() {
430
+ this.container = input.required(...(ngDevMode ? [{ debugName: "container" }] : /* istanbul ignore next */ []));
431
+ }
432
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
433
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipPortal, isStandalone: true, selector: "[rdxTooltipPortal]", inputs: { container: { classPropertyName: "container", publicName: "container", isSignal: true, isRequired: true, transformFunction: null } }, hostDirectives: [{ directive: i1$1.RdxPortal, inputs: ["container", "container"] }], ngImport: i0 }); }
434
+ }
435
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortal, decorators: [{
436
+ type: Directive,
437
+ args: [{
438
+ selector: '[rdxTooltipPortal]',
439
+ hostDirectives: [
440
+ {
441
+ directive: RdxPortal,
442
+ inputs: ['container']
443
+ }
444
+ ]
445
+ }]
446
+ }], propDecorators: { container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: true }] }] } });
353
447
 
354
- function eventTypeAsPrimitiveConfigKey(eventType) {
355
- return `prevent${eventType[0].toUpperCase()}${eventType.slice(1)}`;
448
+ class RdxTooltipPortalPresence {
449
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortalPresence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
450
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipPortalPresence, isStandalone: true, selector: "ng-template[rdxTooltipPortalPresence]", providers: [
451
+ provideRdxPresenceContext(() => {
452
+ const context = injectRdxTooltipContext();
453
+ return { present: context.isOpen };
454
+ })
455
+ ], hostDirectives: [{ directive: i1$2.RdxPresenceDirective }], ngImport: i0 }); }
356
456
  }
357
- class RdxCdkEventService {
358
- #clickDomRootEventCallbacks;
457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortalPresence, decorators: [{
458
+ type: Directive,
459
+ args: [{
460
+ selector: 'ng-template[rdxTooltipPortalPresence]',
461
+ hostDirectives: [RdxPresenceDirective],
462
+ providers: [
463
+ provideRdxPresenceContext(() => {
464
+ const context = injectRdxTooltipContext();
465
+ return { present: context.isOpen };
466
+ })
467
+ ]
468
+ }]
469
+ }] });
470
+
471
+ /**
472
+ * Positions the tooltip popup against its trigger (or a custom anchor).
473
+ */
474
+ class RdxTooltipPositioner {
359
475
  constructor() {
360
- this.document = injectDocument();
476
+ this.rootContext = injectRdxTooltipContext();
477
+ this.wrapper = inject(RdxPopperContentWrapper);
361
478
  this.destroyRef = inject(DestroyRef);
362
- this.ngZone = inject(NgZone);
363
- this.renderer2 = inject(Renderer2);
364
- this.window = injectWindow();
365
- this.onDestroyCallbacks = new Set([() => deleteRdxCdkEventServiceWindowKey(this.window)]);
366
- this.#clickDomRootEventCallbacks = new Set();
367
- this.#listenToClickDomRootEvent();
368
- this.#registerOnDestroyCallbacks();
369
- }
370
- registerPrimitive(primitiveInstance) {
371
- if (!this.primitiveConfigs) {
372
- this.primitiveConfigs = new Map();
373
- }
374
- if (!this.primitiveConfigs.has(primitiveInstance)) {
375
- this.primitiveConfigs.set(primitiveInstance, {});
376
- }
377
- }
378
- deregisterPrimitive(primitiveInstance) {
379
- if (this.primitiveConfigs?.has(primitiveInstance)) {
380
- this.primitiveConfigs.delete(primitiveInstance);
381
- }
382
- }
383
- preventPrimitiveFromCdkEvent(primitiveInstance, eventType) {
384
- this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
385
- }
386
- allowPrimitiveForCdkEvent(primitiveInstance, eventType) {
387
- this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
388
- }
389
- preventPrimitiveFromCdkMultiEvents(primitiveInstance, eventTypes) {
390
- eventTypes.forEach((eventType) => {
391
- this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, true);
392
- });
393
- }
394
- allowPrimitiveForCdkMultiEvents(primitiveInstance, eventTypes) {
395
- eventTypes.forEach((eventType) => {
396
- this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, false);
397
- });
398
- }
399
- setPreventPrimitiveFromCdkMixEvents(primitiveInstance, eventTypes) {
400
- Object.keys(eventTypes).forEach((eventType) => {
401
- this.#setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, eventTypes[eventTypeAsPrimitiveConfigKey(eventType)]);
402
- });
403
- }
404
- primitivePreventedFromCdkEvent(primitiveInstance, eventType) {
405
- return this.primitiveConfigs?.get(primitiveInstance)?.[eventTypeAsPrimitiveConfigKey(eventType)];
406
- }
407
- addClickDomRootEventCallback(callback) {
408
- this.#clickDomRootEventCallbacks.add(callback);
409
- }
410
- removeClickDomRootEventCallback(callback) {
411
- return this.#clickDomRootEventCallbacks.delete(callback);
412
- }
413
- #setPreventPrimitiveFromCdkEvent(primitiveInstance, eventType, value) {
414
- if (!this.primitiveConfigs?.has(primitiveInstance)) {
415
- isDevMode() &&
416
- console.error('[RdxCdkEventService.preventPrimitiveFromCdkEvent] RDX Primitive instance has not been registered!', primitiveInstance);
417
- return;
418
- }
419
- switch (eventType) {
420
- case 'cdkOverlayOutsideClick':
421
- this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayOutsideClick = value;
422
- break;
423
- case 'cdkOverlayEscapeKeyDown':
424
- this.primitiveConfigs.get(primitiveInstance).preventCdkOverlayEscapeKeyDown = value;
425
- break;
426
- }
427
- }
428
- #registerOnDestroyCallbacks() {
429
- this.destroyRef.onDestroy(() => {
430
- this.onDestroyCallbacks.forEach((onDestroyCallback) => onDestroyCallback());
431
- this.onDestroyCallbacks.clear();
432
- });
433
- }
434
- #listenToClickDomRootEvent() {
435
- const target = this.document;
436
- const eventName = 'click';
437
- const options = { capture: true };
438
- const callback = (event) => {
439
- this.#clickDomRootEventCallbacks.forEach((clickDomRootEventCallback) => clickDomRootEventCallback(event));
440
- };
441
- const major = parseInt(VERSION.major);
442
- const minor = parseInt(VERSION.minor);
443
- let destroyClickDomRootEventListener;
479
+ this.dismissableLayer = inject(RdxDismissableLayer);
480
+ this.elementRef = inject(ElementRef);
444
481
  /**
445
- * @see src/cdk/platform/features/backwards-compatibility.ts in @angular/cdk
482
+ * An element to position the popup against. Defaults to the trigger.
446
483
  */
447
- if (major > 19 || (major === 19 && minor > 0) || (major === 0 && minor === 0)) {
448
- destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
449
- const destroyClickDomRootEventListenerInternal = this.renderer2.listen(target, eventName, callback, options);
450
- return () => {
451
- destroyClickDomRootEventListenerInternal();
452
- this.#clickDomRootEventCallbacks.clear();
453
- };
454
- });
455
- }
456
- else {
457
- /**
458
- * This part can get removed when v19.1 or higher is on the board
459
- */
460
- destroyClickDomRootEventListener = this.ngZone.runOutsideAngular(() => {
461
- target.addEventListener(eventName, callback, options);
462
- return () => {
463
- this.ngZone.runOutsideAngular(() => target.removeEventListener(eventName, callback, options));
464
- this.#clickDomRootEventCallbacks.clear();
465
- };
466
- });
467
- }
468
- this.onDestroyCallbacks.add(destroyClickDomRootEventListener);
469
- }
470
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxCdkEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
471
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxCdkEventService }); }
472
- }
473
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxCdkEventService, decorators: [{
474
- type: Injectable
475
- }], ctorParameters: () => [] });
476
- const RdxCdkEventServiceToken = new InjectionToken('RdxCdkEventServiceToken');
477
- const existsErrorMessage = 'RdxCdkEventService should be provided only once!';
478
- const deleteRdxCdkEventServiceWindowKey = (window) => {
479
- delete window[RdxCdkEventServiceWindowKey];
480
- };
481
- const getProvider = (throwWhenExists = true) => ({
482
- provide: RdxCdkEventServiceToken,
483
- useFactory: () => {
484
- isDevMode() && console.log('providing RdxCdkEventService...');
485
- const window = injectWindow();
486
- if (window[RdxCdkEventServiceWindowKey]) {
487
- if (throwWhenExists) {
488
- throw Error(existsErrorMessage);
489
- }
490
- else {
491
- isDevMode() && console.warn(existsErrorMessage);
492
- }
493
- }
494
- window[RdxCdkEventServiceWindowKey] ??= new RdxCdkEventService();
495
- return window[RdxCdkEventServiceWindowKey];
496
- }
497
- });
498
- const provideRdxCdkEventServiceInRoot = () => makeEnvironmentProviders([getProvider()]);
499
- const provideRdxCdkEventService = () => getProvider(false);
500
- const injectRdxCdkEventService = () => inject(RdxCdkEventServiceToken, { optional: true });
501
-
502
- let nextId = 0;
503
- class RdxTooltipRootDirective {
504
- constructor() {
505
- /** @ignore */
506
- this.uniqueId = signal(++nextId, ...(ngDevMode ? [{ debugName: "uniqueId" }] : /* istanbul ignore next */ []));
507
- /** @ignore */
508
- this.name = computed(() => `rdx-tooltip-root-${this.uniqueId()}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
484
+ this.anchor = input(...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
509
485
  /**
510
- * @description The anchor directive that comes form outside the tooltip rootDirective
511
- * @default undefined
486
+ * The preferred side of the anchor to render against when open.
512
487
  */
513
- this.anchor = input(void 0, ...(ngDevMode ? [{ debugName: "anchor" }] : /* istanbul ignore next */ []));
488
+ this.side = input('top', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
514
489
  /**
515
- * @description The open state of the tooltip when it is initially rendered. Use when you do not need to control its open state.
516
- * @default false
490
+ * The distance in pixels from the anchor.
517
491
  */
518
- this.defaultOpen = input(false, { ...(ngDevMode ? { debugName: "defaultOpen" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
492
+ this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
519
493
  /**
520
- * @description The controlled state of the tooltip. `open` input take precedence of `defaultOpen` input.
521
- * @default undefined
494
+ * The preferred alignment against the anchor.
522
495
  */
523
- this.open = input(void 0, { ...(ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
496
+ this.align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
524
497
  /**
525
- * To customise the open delay for a specific tooltip.
498
+ * An offset in pixels from the `start` or `end` alignment options.
526
499
  */
527
- this.openDelay = input(500, { ...(ngDevMode ? { debugName: "openDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
500
+ this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
528
501
  /**
529
- * To customise the close delay for a specific tooltip.
502
+ * The padding between the arrow and the edges of the content.
530
503
  */
531
- this.closeDelay = input(200, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
504
+ this.arrowPadding = input(5, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
532
505
  /**
533
- * @description Whether to control the state of the tooltip from external. Use in conjunction with `open` input.
534
- * @default undefined
506
+ * When `true`, overrides the `side` and `align` preferences to prevent collisions with boundary edges.
535
507
  */
536
- this.externalControl = input(void 0, { ...(ngDevMode ? { debugName: "externalControl" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
508
+ this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
537
509
  /**
538
- * @description Whether to take into account CSS opening/closing animations.
539
- * @default false
510
+ * The element used as the collision boundary.
540
511
  */
541
- this.cssAnimation = input(false, { ...(ngDevMode ? { debugName: "cssAnimation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
512
+ this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
542
513
  /**
543
- * @description Whether to take into account CSS opening animations. `cssAnimation` input must be set to 'true'
544
- * @default false
514
+ * The distance in pixels from the boundary edges where collision detection should occur.
545
515
  */
546
- this.cssOpeningAnimation = input(false, { ...(ngDevMode ? { debugName: "cssOpeningAnimation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
516
+ this.collisionPadding = input(5, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
547
517
  /**
548
- * @description Whether to take into account CSS closing animations. `cssAnimation` input must be set to 'true'
549
- * @default false
518
+ * The sticky behavior on the `align` axis.
550
519
  */
551
- this.cssClosingAnimation = input(false, { ...(ngDevMode ? { debugName: "cssClosingAnimation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
552
- /** @ignore */
553
- this.cssAnimationStatus = signal(null, ...(ngDevMode ? [{ debugName: "cssAnimationStatus" }] : /* istanbul ignore next */ []));
554
- /** @ignore */
555
- this.contentDirective = contentChild.required(RdxTooltipContentDirective);
556
- /** @ignore */
557
- this.triggerDirective = contentChild.required(RdxTooltipTriggerDirective);
558
- /** @ignore */
559
- this.arrowDirective = contentChild(RdxTooltipArrowToken, ...(ngDevMode ? [{ debugName: "arrowDirective" }] : /* istanbul ignore next */ []));
560
- /** @ignore */
561
- this.closeDirective = contentChild(RdxTooltipCloseToken, ...(ngDevMode ? [{ debugName: "closeDirective" }] : /* istanbul ignore next */ []));
562
- /** @ignore */
563
- this.contentAttributesComponent = contentChild(RdxTooltipContentAttributesToken, ...(ngDevMode ? [{ debugName: "contentAttributesComponent" }] : /* istanbul ignore next */ []));
564
- /** @ignore */
565
- this.internalAnchorDirective = contentChild(RdxTooltipAnchorToken, ...(ngDevMode ? [{ debugName: "internalAnchorDirective" }] : /* istanbul ignore next */ []));
566
- /** @ignore */
567
- this.viewContainerRef = inject(ViewContainerRef);
568
- /** @ignore */
569
- this.rdxCdkEventService = injectRdxCdkEventService();
570
- /** @ignore */
571
- this.destroyRef = inject(DestroyRef);
572
- /** @ignore */
573
- this.state = signal(RdxTooltipState.CLOSED, ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
574
- /** @ignore */
575
- this.attachDetachEvent = signal(RdxTooltipAttachDetachEvent.DETACH, ...(ngDevMode ? [{ debugName: "attachDetachEvent" }] : /* istanbul ignore next */ []));
576
- /** @ignore */
577
- this.isFirstDefaultOpen = signal(false, ...(ngDevMode ? [{ debugName: "isFirstDefaultOpen" }] : /* istanbul ignore next */ []));
578
- /** @ignore */
579
- this.anchorDirective = computed(() => this.internalAnchorDirective() ?? this.anchor(), ...(ngDevMode ? [{ debugName: "anchorDirective" }] : /* istanbul ignore next */ []));
580
- /** @ignore */
581
- this.actionSubject$ = new Subject();
582
- /** @ignore */
583
- this.onAnchorChangeEffect = () => {
584
- effect(() => {
585
- const anchor = this.anchor();
586
- untracked(() => {
587
- if (anchor) {
588
- anchor.setRoot(this);
589
- }
590
- });
591
- });
592
- };
593
- this.rdxCdkEventService?.registerPrimitive(this);
594
- this.destroyRef.onDestroy(() => this.rdxCdkEventService?.deregisterPrimitive(this));
595
- this.actionSubscription();
596
- this.onStateChangeEffect();
597
- this.onCssAnimationStatusChangeChangeEffect();
598
- this.onOpenChangeEffect();
599
- this.onIsFirstDefaultOpenChangeEffect();
600
- this.onAnchorChangeEffect();
601
- this.emitOpenOrClosedEventEffect();
602
- afterNextRender({
603
- write: () => {
604
- if (this.defaultOpen() && !this.open()) {
605
- this.isFirstDefaultOpen.set(true);
606
- }
607
- }
608
- });
609
- }
610
- /** @ignore */
611
- getAnimationParamsSnapshot() {
612
- return {
613
- cssAnimation: this.cssAnimation(),
614
- cssOpeningAnimation: this.cssOpeningAnimation(),
615
- cssClosingAnimation: this.cssClosingAnimation(),
616
- cssAnimationStatus: this.cssAnimationStatus(),
617
- attachDetachEvent: this.attachDetachEvent(),
618
- state: this.state(),
619
- canEmitOnOpenOrOnClosed: this.canEmitOnOpenOrOnClosed()
620
- };
621
- }
622
- /** @ignore */
623
- controlledExternally() {
624
- return this.externalControl;
625
- }
626
- /** @ignore */
627
- firstDefaultOpen() {
628
- return this.isFirstDefaultOpen();
629
- }
630
- /** @ignore */
631
- handleOpen() {
632
- if (this.externalControl()) {
633
- return;
634
- }
635
- this.actionSubject$.next(RdxTooltipAction.OPEN);
636
- }
637
- /** @ignore */
638
- handleClose(closeButton) {
639
- if (this.isFirstDefaultOpen()) {
640
- this.isFirstDefaultOpen.set(false);
641
- }
642
- if (!closeButton && this.externalControl()) {
643
- return;
644
- }
645
- this.actionSubject$.next(RdxTooltipAction.CLOSE);
646
- }
647
- /** @ignore */
648
- handleToggle() {
649
- if (this.externalControl()) {
650
- return;
651
- }
652
- this.isOpen() ? this.handleClose() : this.handleOpen();
653
- }
654
- /** @ignore */
655
- isOpen(state) {
656
- return (state ?? this.state()) === RdxTooltipState.OPEN;
657
- }
658
- /** @ignore */
659
- setState(state = RdxTooltipState.CLOSED) {
660
- if (state === this.state()) {
661
- return;
662
- }
663
- this.state.set(state);
664
- }
665
- /** @ignore */
666
- openContent() {
667
- this.contentDirective().open();
668
- if (!this.cssAnimation() || !this.cssOpeningAnimation()) {
669
- this.cssAnimationStatus.set(null);
670
- }
671
- }
672
- /** @ignore */
673
- closeContent() {
674
- this.contentDirective().close();
675
- if (!this.cssAnimation() || !this.cssClosingAnimation()) {
676
- this.cssAnimationStatus.set(null);
677
- }
678
- }
679
- /** @ignore */
680
- emitOnOpen() {
681
- this.contentDirective().onOpen.emit();
682
- }
683
- /** @ignore */
684
- emitOnClosed() {
685
- this.contentDirective().onClosed.emit();
686
- }
687
- /** @ignore */
688
- ifOpenOrCloseWithoutAnimations(state) {
689
- return (!this.contentAttributesComponent() ||
690
- !this.cssAnimation() ||
691
- (this.cssAnimation() && !this.cssClosingAnimation() && state === RdxTooltipState.CLOSED) ||
692
- (this.cssAnimation() && !this.cssOpeningAnimation() && state === RdxTooltipState.OPEN) ||
693
- // !this.cssAnimationStatus() ||
694
- (this.cssOpeningAnimation() &&
695
- state === RdxTooltipState.OPEN &&
696
- [RdxTooltipAnimationStatus.OPEN_STARTED].includes(this.cssAnimationStatus())) ||
697
- (this.cssClosingAnimation() &&
698
- state === RdxTooltipState.CLOSED &&
699
- [RdxTooltipAnimationStatus.CLOSED_STARTED].includes(this.cssAnimationStatus())));
700
- }
701
- /** @ignore */
702
- ifOpenOrCloseWithAnimations(cssAnimationStatus) {
703
- return (this.contentAttributesComponent() &&
704
- this.cssAnimation() &&
705
- cssAnimationStatus &&
706
- ((this.cssOpeningAnimation() &&
707
- this.state() === RdxTooltipState.OPEN &&
708
- [RdxTooltipAnimationStatus.OPEN_ENDED].includes(cssAnimationStatus)) ||
709
- (this.cssClosingAnimation() &&
710
- this.state() === RdxTooltipState.CLOSED &&
711
- [RdxTooltipAnimationStatus.CLOSED_ENDED].includes(cssAnimationStatus))));
712
- }
713
- /** @ignore */
714
- openOrClose(state) {
715
- const isOpen = this.isOpen(state);
716
- isOpen ? this.openContent() : this.closeContent();
717
- }
718
- /** @ignore */
719
- emitOnOpenOrOnClosed(state) {
720
- this.isOpen(state)
721
- ? this.attachDetachEvent() === RdxTooltipAttachDetachEvent.ATTACH && this.emitOnOpen()
722
- : this.attachDetachEvent() === RdxTooltipAttachDetachEvent.DETACH && this.emitOnClosed();
723
- }
724
- /** @ignore */
725
- canEmitOnOpenOrOnClosed() {
726
- return (!this.cssAnimation() ||
727
- (!this.cssOpeningAnimation() && this.state() === RdxTooltipState.OPEN) ||
728
- (this.cssOpeningAnimation() &&
729
- this.state() === RdxTooltipState.OPEN &&
730
- this.cssAnimationStatus() === RdxTooltipAnimationStatus.OPEN_ENDED) ||
731
- (!this.cssClosingAnimation() && this.state() === RdxTooltipState.CLOSED) ||
732
- (this.cssClosingAnimation() &&
733
- this.state() === RdxTooltipState.CLOSED &&
734
- this.cssAnimationStatus() === RdxTooltipAnimationStatus.CLOSED_ENDED));
735
- }
736
- /** @ignore */
737
- onStateChangeEffect() {
738
- let isFirst = true;
739
- effect(() => {
740
- const state = this.state();
741
- untracked(() => {
742
- if (isFirst) {
743
- isFirst = false;
744
- return;
745
- }
746
- if (!this.ifOpenOrCloseWithoutAnimations(state)) {
747
- return;
748
- }
749
- this.openOrClose(state);
750
- });
751
- }, {});
752
- }
753
- /** @ignore */
754
- onCssAnimationStatusChangeChangeEffect() {
755
- let isFirst = true;
756
- effect(() => {
757
- const cssAnimationStatus = this.cssAnimationStatus();
758
- untracked(() => {
759
- if (isFirst) {
760
- isFirst = false;
761
- return;
762
- }
763
- if (!this.ifOpenOrCloseWithAnimations(cssAnimationStatus)) {
764
- return;
765
- }
766
- this.openOrClose(this.state());
767
- });
768
- });
769
- }
770
- /** @ignore */
771
- emitOpenOrClosedEventEffect() {
772
- let isFirst = true;
773
- effect(() => {
774
- this.attachDetachEvent();
775
- this.cssAnimationStatus();
776
- untracked(() => {
777
- if (isFirst) {
778
- isFirst = false;
779
- return;
780
- }
781
- const canEmitOpenClose = untracked(() => this.canEmitOnOpenOrOnClosed());
782
- if (!canEmitOpenClose) {
783
- return;
520
+ this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
521
+ /**
522
+ * Whether to hide the content when the trigger becomes fully occluded.
523
+ */
524
+ this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
525
+ /**
526
+ * The CSS position strategy used by Floating UI.
527
+ */
528
+ this.positionStrategy = input('fixed', ...(ngDevMode ? [{ debugName: "positionStrategy" }] : /* istanbul ignore next */ []));
529
+ /**
530
+ * Whether to update the position of the floating element on every animation frame if required.
531
+ */
532
+ this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
533
+ /**
534
+ * Emits when the element is placed.
535
+ */
536
+ this.placed = outputFromObservable(outputToObservable(this.wrapper.placed));
537
+ /**
538
+ * Event handler called when the escape key is down. Can be prevented.
539
+ */
540
+ this.escapeKeyDown = outputFromObservable(outputToObservable(this.dismissableLayer.escapeKeyDown));
541
+ /**
542
+ * Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
543
+ */
544
+ this.pointerDownOutside = outputFromObservable(outputToObservable(this.dismissableLayer.pointerDownOutside));
545
+ this.triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
546
+ this.containerEl = signal(null, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
547
+ this.graceArea = useGraceArea(this.triggerEl, this.containerEl, 300);
548
+ this.afterNextRender = afterNextRender(() => {
549
+ this.triggerEl.set(this.rootContext.trigger() ?? null);
550
+ this.containerEl.set(this.elementRef.nativeElement);
551
+ const handleScroll = (event) => {
552
+ const target = event.target;
553
+ const trigger = this.rootContext.trigger();
554
+ if (trigger && target?.contains(trigger)) {
555
+ this.rootContext.close();
784
556
  }
785
- this.emitOnOpenOrOnClosed(this.state());
786
- });
787
- });
788
- }
789
- /** @ignore */
790
- onOpenChangeEffect() {
791
- effect(() => {
792
- const open = this.open();
793
- untracked(() => {
794
- this.setState(open ? RdxTooltipState.OPEN : RdxTooltipState.CLOSED);
557
+ };
558
+ window.addEventListener('scroll', handleScroll, { capture: true });
559
+ this.destroyRef.onDestroy(() => {
560
+ window.removeEventListener('scroll', handleScroll, { capture: true });
795
561
  });
796
- });
797
- }
798
- /** @ignore */
799
- onIsFirstDefaultOpenChangeEffect() {
800
- const effectRef = effect(() => {
801
- const defaultOpen = this.defaultOpen();
802
- untracked(() => {
803
- if (!defaultOpen || this.open()) {
804
- effectRef.destroy();
562
+ this.graceArea.onPointerExit(() => {
563
+ // A disabled root is fully controlled by the consumer (e.g. the slider thumb drives
564
+ // `open` while dragging). Hover never opens it, so the hover grace area must not close
565
+ // it either — otherwise a drag that leaves the grace polygon would dismiss it and the
566
+ // one-way `open` binding could not bring it back.
567
+ if (this.rootContext.disabled() || this.rootContext.disableHoverablePopup())
805
568
  return;
806
- }
807
- this.handleOpen();
569
+ this.rootContext.closeDelayed();
808
570
  });
809
- }, ...(ngDevMode ? [{ debugName: "effectRef" }] : /* istanbul ignore next */ []));
810
- }
811
- /** @ignore */
812
- actionSubscription() {
813
- this.actionSubject$
814
- .asObservable()
815
- .pipe(map((action) => {
816
- switch (action) {
817
- case RdxTooltipAction.OPEN:
818
- return { action, duration: this.openDelay() };
819
- case RdxTooltipAction.CLOSE:
820
- return { action, duration: this.closeDelay() };
821
- }
822
- }), debounce((config) => timer(config.duration)), tap((config) => {
823
- switch (config.action) {
824
- case RdxTooltipAction.OPEN:
825
- this.setState(RdxTooltipState.OPEN);
826
- break;
827
- case RdxTooltipAction.CLOSE:
828
- this.setState(RdxTooltipState.CLOSED);
829
- break;
830
- }
831
- }), takeUntilDestroyed())
832
- .subscribe();
833
- }
834
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
835
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.9", type: RdxTooltipRootDirective, isStandalone: true, selector: "[rdxTooltipRoot]", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, openDelay: { classPropertyName: "openDelay", publicName: "openDelay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, externalControl: { classPropertyName: "externalControl", publicName: "externalControl", isSignal: true, isRequired: false, transformFunction: null }, cssAnimation: { classPropertyName: "cssAnimation", publicName: "cssAnimation", isSignal: true, isRequired: false, transformFunction: null }, cssOpeningAnimation: { classPropertyName: "cssOpeningAnimation", publicName: "cssOpeningAnimation", isSignal: true, isRequired: false, transformFunction: null }, cssClosingAnimation: { classPropertyName: "cssClosingAnimation", publicName: "cssClosingAnimation", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "contentDirective", first: true, predicate: RdxTooltipContentDirective, descendants: true, isSignal: true }, { propertyName: "triggerDirective", first: true, predicate: RdxTooltipTriggerDirective, descendants: true, isSignal: true }, { propertyName: "arrowDirective", first: true, predicate: RdxTooltipArrowToken, descendants: true, isSignal: true }, { propertyName: "closeDirective", first: true, predicate: RdxTooltipCloseToken, descendants: true, isSignal: true }, { propertyName: "contentAttributesComponent", first: true, predicate: RdxTooltipContentAttributesToken, descendants: true, isSignal: true }, { propertyName: "internalAnchorDirective", first: true, predicate: RdxTooltipAnchorToken, descendants: true, isSignal: true }], exportAs: ["rdxTooltipRoot"], ngImport: i0 }); }
836
- }
837
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipRootDirective, decorators: [{
838
- type: Directive,
839
- args: [{
840
- selector: '[rdxTooltipRoot]',
841
- exportAs: 'rdxTooltipRoot'
842
- }]
843
- }], ctorParameters: () => [], propDecorators: { anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], openDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "openDelay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], externalControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalControl", required: false }] }], cssAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssAnimation", required: false }] }], cssOpeningAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssOpeningAnimation", required: false }] }], cssClosingAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClosingAnimation", required: false }] }], contentDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipContentDirective), { isSignal: true }] }], triggerDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipTriggerDirective), { isSignal: true }] }], arrowDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipArrowToken), { isSignal: true }] }], closeDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipCloseToken), { isSignal: true }] }], contentAttributesComponent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipContentAttributesToken), { isSignal: true }] }], internalAnchorDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxTooltipAnchorToken), { isSignal: true }] }] } });
844
-
845
- function injectTooltipRoot(optional = false) {
846
- isDevMode() && assertInInjectionContext(injectTooltipRoot);
847
- return inject(RdxTooltipRootDirective, { optional });
848
- }
849
-
850
- class RdxTooltipAnchorDirective {
851
- constructor() {
852
- /**
853
- * @ignore
854
- * If outside the rootDirective then null, otherwise the rootDirective directive - with optional `true` passed in as the first param.
855
- * If outside the rootDirective and non-null value that means the html structure is wrong - tooltip inside tooltip.
856
- * */
857
- this.rootDirective = injectTooltipRoot(true);
858
- /** @ignore */
859
- this.elementRef = inject(ElementRef);
860
- /** @ignore */
861
- this.overlayOrigin = inject(CdkOverlayOrigin);
862
- /** @ignore */
863
- this.document = injectDocument();
864
- /** @ignore */
865
- this.name = computed(() => `rdx-tooltip-external-anchor-${this.rootDirective?.uniqueId()}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
866
- }
867
- /** @ignore */
868
- click() {
869
- this.emitOutsideClick();
870
- }
871
- /** @ignore */
872
- setRoot(root) {
873
- this.rootDirective = root;
874
- }
875
- emitOutsideClick() {
876
- if (!this.rootDirective?.isOpen() || this.rootDirective?.contentDirective().onOverlayOutsideClickDisabled()) {
877
- return;
878
- }
879
- const clickEvent = new MouseEvent('click', {
880
- view: this.document.defaultView,
881
- bubbles: true,
882
- cancelable: true,
883
- relatedTarget: this.elementRef.nativeElement
884
571
  });
885
- this.rootDirective?.triggerDirective().elementRef.nativeElement.dispatchEvent(clickEvent);
886
- }
887
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipAnchorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
888
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipAnchorDirective, isStandalone: true, selector: "[rdxTooltipAnchor]", host: { attributes: { "type": "button" }, listeners: { "click": "click()" }, properties: { "attr.id": "name()", "attr.aria-haspopup": "\"dialog\"" } }, providers: [
889
- {
890
- provide: RdxTooltipAnchorToken,
891
- useExisting: forwardRef(() => RdxTooltipAnchorDirective)
892
- }
893
- ], exportAs: ["rdxTooltipAnchor"], hostDirectives: [{ directive: i1.CdkOverlayOrigin }], ngImport: i0 }); }
572
+ this.dismissableLayer.focusOutside.subscribe((e) => e.preventDefault());
573
+ this.dismissableLayer.dismiss.subscribe(() => this.rootContext.close());
574
+ // While following the cursor the popup sits right under the pointer; if it could intercept
575
+ // the pointer it would steal hover from the trigger and the tooltip would flicker. Render it
576
+ // pointer-events: none so the pointer always passes through to the trigger underneath.
577
+ effect(() => this.wrapper.nonInteractive.set(this.rootContext.trackCursorAxis() !== 'none'));
578
+ }
579
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
580
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipPositioner, isStandalone: true, selector: "[rdxTooltipPositioner]", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, avoidCollisions: { classPropertyName: "avoidCollisions", publicName: "avoidCollisions", isSignal: true, isRequired: false, transformFunction: null }, collisionBoundary: { classPropertyName: "collisionBoundary", publicName: "collisionBoundary", isSignal: true, isRequired: false, transformFunction: null }, collisionPadding: { classPropertyName: "collisionPadding", publicName: "collisionPadding", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, hideWhenDetached: { classPropertyName: "hideWhenDetached", publicName: "hideWhenDetached", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, updatePositionStrategy: { classPropertyName: "updatePositionStrategy", publicName: "updatePositionStrategy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { placed: "placed", escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside" }, host: { properties: { "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-side": "wrapper.placedSide()", "attr.data-align": "wrapper.placedAlign()", "style": "{\n '--anchor-width': 'var(--radix-popper-anchor-width)',\n '--anchor-height': 'var(--radix-popper-anchor-height)',\n '--available-width': 'var(--radix-popper-available-width)',\n '--available-height': 'var(--radix-popper-available-height)',\n '--transform-origin': 'var(--radix-popper-transform-origin)'\n }" } }, providers: [provideRdxPopperContentConfig({ side: 'top', arrowPadding: 5, collisionPadding: 5 })], hostDirectives: [{ directive: i1$3.RdxDismissableLayer }, { directive: i1.RdxPopperContentWrapper, inputs: ["anchor", "anchor", "side", "side", "sideOffset", "sideOffset", "align", "align", "alignOffset", "alignOffset", "arrowPadding", "arrowPadding", "avoidCollisions", "avoidCollisions", "collisionBoundary", "collisionBoundary", "collisionPadding", "collisionPadding", "sticky", "sticky", "hideWhenDetached", "hideWhenDetached", "positionStrategy", "positionStrategy", "updatePositionStrategy", "updatePositionStrategy"] }], ngImport: i0 }); }
894
581
  }
895
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipAnchorDirective, decorators: [{
582
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, decorators: [{
896
583
  type: Directive,
897
584
  args: [{
898
- selector: '[rdxTooltipAnchor]',
899
- exportAs: 'rdxTooltipAnchor',
900
- hostDirectives: [CdkOverlayOrigin],
901
- host: {
902
- type: 'button',
903
- '[attr.id]': 'name()',
904
- '[attr.aria-haspopup]': '"dialog"',
905
- '(click)': 'click()'
906
- },
907
- providers: [
585
+ selector: '[rdxTooltipPositioner]',
586
+ providers: [provideRdxPopperContentConfig({ side: 'top', arrowPadding: 5, collisionPadding: 5 })],
587
+ hostDirectives: [
588
+ RdxDismissableLayer,
908
589
  {
909
- provide: RdxTooltipAnchorToken,
910
- useExisting: forwardRef(() => RdxTooltipAnchorDirective)
590
+ directive: RdxPopperContentWrapper,
591
+ inputs: [
592
+ 'anchor',
593
+ 'side',
594
+ 'sideOffset',
595
+ 'align',
596
+ 'alignOffset',
597
+ 'arrowPadding',
598
+ 'avoidCollisions',
599
+ 'collisionBoundary',
600
+ 'collisionPadding',
601
+ 'sticky',
602
+ 'hideWhenDetached',
603
+ 'positionStrategy',
604
+ 'updatePositionStrategy'
605
+ ]
911
606
  }
912
- ]
607
+ ],
608
+ host: {
609
+ '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
610
+ '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
611
+ '[attr.data-side]': 'wrapper.placedSide()',
612
+ '[attr.data-align]': 'wrapper.placedAlign()',
613
+ '[style]': `{
614
+ '--anchor-width': 'var(--radix-popper-anchor-width)',
615
+ '--anchor-height': 'var(--radix-popper-anchor-height)',
616
+ '--available-width': 'var(--radix-popper-available-width)',
617
+ '--available-height': 'var(--radix-popper-available-height)',
618
+ '--transform-origin': 'var(--radix-popper-transform-origin)'
619
+ }`
620
+ }
913
621
  }]
914
- }] });
622
+ }], ctorParameters: () => [], propDecorators: { anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], arrowPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrowPadding", required: false }] }], avoidCollisions: [{ type: i0.Input, args: [{ isSignal: true, alias: "avoidCollisions", required: false }] }], collisionBoundary: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionBoundary", required: false }] }], collisionPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionPadding", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], hideWhenDetached: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenDetached", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], updatePositionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "updatePositionStrategy", required: false }] }], placed: [{ type: i0.Output, args: ["placed"] }], escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }], pointerDownOutside: [{ type: i0.Output, args: ["pointerDownOutside"] }] } });
915
623
 
916
- class RdxTooltipArrowDirective {
624
+ class RdxTooltipTrigger {
917
625
  constructor() {
918
- /** @ignore */
919
- this.renderer = inject(Renderer2);
920
- /** @ignore */
921
- this.rootDirective = injectTooltipRoot();
922
- /** @ignore */
626
+ this.parentRootContext = injectRdxTooltipContext(true);
923
627
  this.elementRef = inject(ElementRef);
628
+ this.generatedId = injectId('rdx-tooltip-trigger-');
924
629
  /**
925
- * @description The width of the arrow in pixels.
926
- * @default 10
630
+ * Associates this trigger with a detached tooltip root.
927
631
  */
928
- this.width = input(RDX_POSITIONING_DEFAULTS.arrow.width, { ...(ngDevMode ? { debugName: "width" } : /* istanbul ignore next */ {}), transform: numberAttribute });
632
+ this.handle = input(...(ngDevMode ? [undefined, { debugName: "handle" }] : /* istanbul ignore next */ []));
929
633
  /**
930
- * @description The height of the arrow in pixels.
931
- * @default 5
634
+ * Data associated with this trigger while it is active.
932
635
  */
933
- this.height = input(RDX_POSITIONING_DEFAULTS.arrow.height, { ...(ngDevMode ? { debugName: "height" } : /* istanbul ignore next */ {}), transform: numberAttribute });
934
- /** @ignore */
935
- this.arrowSvgElement = computed(() => {
936
- const width = this.width();
937
- const height = this.height();
938
- const svgElement = this.renderer.createElement('svg', 'svg');
939
- this.renderer.setAttribute(svgElement, 'viewBox', '0 0 30 10');
940
- this.renderer.setAttribute(svgElement, 'width', String(width));
941
- this.renderer.setAttribute(svgElement, 'height', String(height));
942
- const polygonElement = this.renderer.createElement('polygon', 'svg');
943
- this.renderer.setAttribute(polygonElement, 'points', '0,0 30,0 15,10');
944
- this.renderer.setAttribute(svgElement, 'preserveAspectRatio', 'none');
945
- this.renderer.appendChild(svgElement, polygonElement);
946
- return svgElement;
947
- }, ...(ngDevMode ? [{ debugName: "arrowSvgElement" }] : /* istanbul ignore next */ []));
948
- /** @ignore */
949
- this.currentArrowSvgElement = signal(void 0, ...(ngDevMode ? [{ debugName: "currentArrowSvgElement" }] : /* istanbul ignore next */ []));
950
- /** @ignore */
951
- this.position = toSignal(this.rootDirective.contentDirective().positionChange());
952
- afterNextRender({
953
- write: () => {
954
- if (this.elementRef.nativeElement.parentElement) {
955
- this.renderer.setStyle(this.elementRef.nativeElement.parentElement, 'position', 'relative');
956
- }
957
- this.renderer.setStyle(this.elementRef.nativeElement, 'position', 'absolute');
958
- this.renderer.setStyle(this.elementRef.nativeElement, 'boxSizing', '');
959
- this.renderer.setStyle(this.elementRef.nativeElement, 'fontSize', '0px');
636
+ this.payload = input(...(ngDevMode ? [undefined, { debugName: "payload" }] : /* istanbul ignore next */ []));
637
+ /**
638
+ * ID used to identify this trigger when opening a detached tooltip imperatively.
639
+ */
640
+ this.id = input(...(ngDevMode ? [undefined, { debugName: "id" }] : /* istanbul ignore next */ []));
641
+ /**
642
+ * Whether the tooltip should close when the trigger is clicked.
643
+ * @defaultValue true
644
+ */
645
+ this.closeOnClick = input(true, { ...(ngDevMode ? { debugName: "closeOnClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
646
+ /**
647
+ * Whether this trigger is disabled. A disabled trigger never opens the tooltip.
648
+ * @defaultValue false
649
+ */
650
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
651
+ /**
652
+ * Overrides the open delay (ms) for this trigger. Falls back to the root/provider/global delay.
653
+ */
654
+ this.delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
655
+ /**
656
+ * Overrides the close delay (ms) for this trigger. Falls back to the root/provider/global delay.
657
+ */
658
+ this.closeDelay = input(undefined, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
659
+ this.userOnPointerDown = input(undefined, { ...(ngDevMode ? { debugName: "userOnPointerDown" } : /* istanbul ignore next */ {}), alias: 'rdxOnPointerDown' });
660
+ this.triggerId = computed(() => this.id() ?? this.generatedId, ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
661
+ this.rootContext = computed(() => this.handle()?.context() ?? this.parentRootContext, ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
662
+ /** Disabled if either the root or this trigger is disabled. */
663
+ this.isDisabled = computed(() => (this.rootContext()?.disabled() ?? false) || this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
664
+ /** Whether this specific trigger is the active anchor of an open tooltip. */
665
+ this.isOpen = computed(() => this.rootContext()?.isOpen() === true && this.rootContext()?.trigger() === this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
666
+ this.isPointerDown = signal(false, ...(ngDevMode ? [{ debugName: "isPointerDown" }] : /* istanbul ignore next */ []));
667
+ this.hasPointerMoveOpened = signal(false, ...(ngDevMode ? [{ debugName: "hasPointerMoveOpened" }] : /* istanbul ignore next */ []));
668
+ effect((onCleanup) => {
669
+ const handle = this.handle();
670
+ if (handle) {
671
+ onCleanup(untracked(() => handle.registerTrigger(this.triggerId(), this.elementRef.nativeElement, () => this.payload())));
672
+ }
673
+ else if (this.parentRootContext) {
674
+ onCleanup(untracked(() => this.parentRootContext.registerTrigger(this.elementRef.nativeElement)));
960
675
  }
961
676
  });
962
- this.onArrowSvgElementChangeEffect();
963
- this.onContentPositionAndArrowDimensionsChangeEffect();
964
677
  }
965
- /** @ignore */
966
- setAnchorOrTriggerRect() {
967
- this.anchorOrTriggerRect = (this.rootDirective.anchorDirective() ?? this.rootDirective.triggerDirective()).elementRef.nativeElement.getBoundingClientRect();
678
+ handleFocus() {
679
+ const rootContext = this.rootContext();
680
+ if (!rootContext || this.isDisabled() || this.isPointerDown()) {
681
+ return;
682
+ }
683
+ rootContext.setDelays(this.delay(), this.closeDelay());
684
+ rootContext.open(this.elementRef.nativeElement, this.payload());
968
685
  }
969
- /** @ignore */
970
- setPosition(position, arrowDimensions) {
971
- this.setAnchorOrTriggerRect();
972
- const posParams = getArrowPositionParams(getSideAndAlignFromAllPossibleConnectedPositions(position.connectionPair), { width: arrowDimensions.width, height: arrowDimensions.height }, { width: this.anchorOrTriggerRect.width, height: this.anchorOrTriggerRect.height });
973
- this.renderer.setStyle(this.elementRef.nativeElement, 'top', posParams.top);
974
- this.renderer.setStyle(this.elementRef.nativeElement, 'bottom', '');
975
- this.renderer.setStyle(this.elementRef.nativeElement, 'left', posParams.left);
976
- this.renderer.setStyle(this.elementRef.nativeElement, 'right', '');
977
- this.renderer.setStyle(this.elementRef.nativeElement, 'transform', posParams.transform);
978
- this.renderer.setStyle(this.elementRef.nativeElement, 'transformOrigin', posParams.transformOrigin);
686
+ handleBlur() {
687
+ this.rootContext()?.closeDelayed();
979
688
  }
980
- /** @ignore */
981
- onArrowSvgElementChangeEffect() {
982
- effect(() => {
983
- const arrowElement = this.arrowSvgElement();
984
- untracked(() => {
985
- const currentArrowSvgElement = this.currentArrowSvgElement();
986
- if (currentArrowSvgElement) {
987
- this.renderer.removeChild(this.elementRef.nativeElement, currentArrowSvgElement);
988
- }
989
- this.currentArrowSvgElement.set(arrowElement);
990
- this.renderer.setStyle(this.elementRef.nativeElement, 'width', `${this.width()}px`);
991
- this.renderer.setStyle(this.elementRef.nativeElement, 'height', `${this.height()}px`);
992
- this.renderer.appendChild(this.elementRef.nativeElement, this.currentArrowSvgElement());
993
- });
994
- });
995
- }
996
- /** @ignore */
997
- onContentPositionAndArrowDimensionsChangeEffect() {
998
- effect(() => {
999
- const position = this.position();
1000
- const arrowDimensions = { width: this.width(), height: this.height() };
1001
- untracked(() => {
1002
- if (!position) {
1003
- return;
1004
- }
1005
- this.setPosition(position, arrowDimensions);
1006
- });
1007
- });
689
+ handleClick() {
690
+ const rootContext = this.rootContext();
691
+ if (rootContext?.isOpen() && this.closeOnClick()) {
692
+ rootContext.close();
693
+ }
1008
694
  }
1009
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipArrowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1010
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipArrowDirective, isStandalone: true, selector: "[rdxTooltipArrow]", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1011
- {
1012
- provide: RdxTooltipArrowToken,
1013
- useExisting: forwardRef(() => RdxTooltipArrowDirective)
1014
- }
1015
- ], ngImport: i0 }); }
1016
- }
1017
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipArrowDirective, decorators: [{
1018
- type: Directive,
1019
- args: [{
1020
- selector: '[rdxTooltipArrow]',
1021
- providers: [
1022
- {
1023
- provide: RdxTooltipArrowToken,
1024
- useExisting: forwardRef(() => RdxTooltipArrowDirective)
1025
- }
1026
- ]
1027
- }]
1028
- }], ctorParameters: () => [], propDecorators: { width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
1029
-
1030
- /**
1031
- * TODO: to be removed? But it seems to be useful when controlled from outside
1032
- */
1033
- class RdxTooltipCloseDirective {
1034
- constructor() {
1035
- /** @ignore */
1036
- this.rootDirective = injectTooltipRoot();
1037
- /** @ignore */
1038
- this.elementRef = inject(ElementRef);
1039
- /** @ignore */
1040
- this.renderer = inject(Renderer2);
1041
- this.onIsControlledExternallyEffect();
695
+ handlePointerMove(event) {
696
+ if (event.pointerType === 'touch') {
697
+ return;
698
+ }
699
+ const rootContext = this.rootContext();
700
+ if (!rootContext || this.isDisabled()) {
701
+ return;
702
+ }
703
+ if (rootContext.trackCursorAxis() !== 'none') {
704
+ rootContext.setCursorPosition({ x: event.clientX, y: event.clientY });
705
+ }
706
+ if (!this.hasPointerMoveOpened()) {
707
+ rootContext.setDelays(this.delay(), this.closeDelay());
708
+ rootContext.onTriggerEnter(this.elementRef.nativeElement, this.payload());
709
+ this.hasPointerMoveOpened.set(true);
710
+ }
1042
711
  }
1043
- /** @ignore */
1044
- onIsControlledExternallyEffect() {
1045
- effect(() => {
1046
- const isControlledExternally = this.rootDirective.controlledExternally()();
1047
- untracked(() => {
1048
- this.renderer.setStyle(this.elementRef.nativeElement, 'display', isControlledExternally ? null : 'none');
1049
- });
1050
- });
712
+ handlePointerLeave() {
713
+ this.rootContext()?.onTriggerLeave();
714
+ this.hasPointerMoveOpened.set(false);
715
+ }
716
+ async handlePointerDown(event) {
717
+ const user = this.userOnPointerDown();
718
+ let result;
719
+ if (user) {
720
+ result = user(event);
721
+ if (result instanceof Promise)
722
+ result = await result;
723
+ }
724
+ if (event.defaultPrevented || result === false) {
725
+ return;
726
+ }
727
+ this.isPointerDown.set(true);
728
+ const handlePointerUp = () => {
729
+ setTimeout(() => this.isPointerDown.set(false), 1);
730
+ };
731
+ document.addEventListener('pointerup', handlePointerUp, { once: true });
1051
732
  }
1052
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1053
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipCloseDirective, isStandalone: true, selector: "[rdxTooltipClose]", host: { attributes: { "type": "button" }, listeners: { "click": "rootDirective.handleClose(true)" } }, providers: [
1054
- {
1055
- provide: RdxTooltipCloseToken,
1056
- useExisting: forwardRef(() => RdxTooltipCloseDirective)
1057
- }
1058
- ], ngImport: i0 }); }
733
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
734
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipTrigger, isStandalone: true, selector: "[rdxTooltipTrigger]", inputs: { handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, userOnPointerDown: { classPropertyName: "userOnPointerDown", publicName: "rdxOnPointerDown", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "data-grace-area-trigger": "''" }, listeners: { "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave()", "pointerdown": "handlePointerDown($event)", "focus": "handleFocus()", "blur": "handleBlur()", "click": "handleClick()" }, properties: { "id": "triggerId()", "attr.aria-describedby": "isOpen() ? rootContext()?.contentId : undefined", "attr.data-popup-open": "isOpen() ? \"\" : undefined", "attr.data-trigger-disabled": "isDisabled() ? \"\" : undefined" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
1059
735
  }
1060
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipCloseDirective, decorators: [{
736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, decorators: [{
1061
737
  type: Directive,
1062
738
  args: [{
1063
- selector: '[rdxTooltipClose]',
739
+ selector: '[rdxTooltipTrigger]',
740
+ hostDirectives: [RdxPopperAnchor],
1064
741
  host: {
1065
742
  type: 'button',
1066
- '(click)': 'rootDirective.handleClose(true)'
1067
- },
1068
- providers: [
1069
- {
1070
- provide: RdxTooltipCloseToken,
1071
- useExisting: forwardRef(() => RdxTooltipCloseDirective)
1072
- }
1073
- ]
743
+ 'data-grace-area-trigger': "''",
744
+ '[id]': 'triggerId()',
745
+ '[attr.aria-describedby]': 'isOpen() ? rootContext()?.contentId : undefined',
746
+ '[attr.data-popup-open]': 'isOpen() ? "" : undefined',
747
+ '[attr.data-trigger-disabled]': 'isDisabled() ? "" : undefined',
748
+ '(pointermove)': 'handlePointerMove($event)',
749
+ '(pointerleave)': 'handlePointerLeave()',
750
+ '(pointerdown)': 'handlePointerDown($event)',
751
+ '(focus)': 'handleFocus()',
752
+ '(blur)': 'handleBlur()',
753
+ '(click)': 'handleClick()'
754
+ }
1074
755
  }]
1075
- }], ctorParameters: () => [] });
756
+ }], ctorParameters: () => [], propDecorators: { handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], payload: [{ type: i0.Input, args: [{ isSignal: true, alias: "payload", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], userOnPointerDown: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxOnPointerDown", required: false }] }] } });
1076
757
 
1077
- class RdxTooltipContentAttributesComponent {
758
+ class RdxTooltipHandle {
1078
759
  constructor() {
1079
- /** @ignore */
1080
- this.rootDirective = injectTooltipRoot();
1081
- /** @ignore */
1082
- this.name = computed(() => `rdx-tooltip-content-attributes-${this.rootDirective.uniqueId()}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
1083
- /** @ignore */
1084
- this.disableAnimation = computed(() => !this.canAnimate(), ...(ngDevMode ? [{ debugName: "disableAnimation" }] : /* istanbul ignore next */ []));
1085
- }
1086
- /** @ignore */
1087
- onAnimationStart(_) {
1088
- this.rootDirective.cssAnimationStatus.set(this.rootDirective.state() === RdxTooltipState.OPEN
1089
- ? RdxTooltipAnimationStatus.OPEN_STARTED
1090
- : RdxTooltipAnimationStatus.CLOSED_STARTED);
1091
- }
1092
- /** @ignore */
1093
- onAnimationEnd(_) {
1094
- this.rootDirective.cssAnimationStatus.set(this.rootDirective.state() === RdxTooltipState.OPEN
1095
- ? RdxTooltipAnimationStatus.OPEN_ENDED
1096
- : RdxTooltipAnimationStatus.CLOSED_ENDED);
1097
- }
1098
- /** @ignore */
1099
- pointerenter() {
1100
- this.rootDirective.handleOpen();
760
+ this.rootContext = signal(undefined, ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
761
+ this.triggers = new Map();
762
+ this.rootTriggerCleanups = new Map();
763
+ this.isOpen = computed(() => this.rootContext()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
764
+ }
765
+ open(triggerId) {
766
+ const trigger = this.triggers.get(triggerId);
767
+ if (!trigger) {
768
+ throw new Error(`No tooltip trigger registered with id "${triggerId}".`);
769
+ }
770
+ this.rootContext()?.open(trigger.element, trigger.payload());
1101
771
  }
1102
- /** @ignore */
1103
- pointerleave() {
1104
- this.rootDirective.handleClose();
772
+ close() {
773
+ this.rootContext()?.close();
1105
774
  }
1106
- /** @ignore */
1107
- focus() {
1108
- this.rootDirective.handleOpen();
775
+ registerRoot(rootContext) {
776
+ this.rootContext.set(rootContext);
777
+ this.triggers.forEach((trigger, id) => {
778
+ this.rootTriggerCleanups.set(id, rootContext.registerTrigger(trigger.element));
779
+ });
780
+ return () => {
781
+ if (this.rootContext() === rootContext) {
782
+ this.rootTriggerCleanups.forEach((cleanup) => cleanup());
783
+ this.rootTriggerCleanups.clear();
784
+ this.rootContext.set(undefined);
785
+ }
786
+ };
1109
787
  }
1110
- /** @ignore */
1111
- blur() {
1112
- this.rootDirective.handleClose();
788
+ registerTrigger(id, trigger, payload) {
789
+ this.rootTriggerCleanups.get(id)?.();
790
+ this.triggers.set(id, { element: trigger, payload });
791
+ const unregisterFromRoot = this.rootContext()?.registerTrigger(trigger);
792
+ if (unregisterFromRoot) {
793
+ this.rootTriggerCleanups.set(id, unregisterFromRoot);
794
+ }
795
+ return () => {
796
+ this.rootTriggerCleanups.get(id)?.();
797
+ this.rootTriggerCleanups.delete(id);
798
+ if (this.triggers.get(id)?.element === trigger) {
799
+ this.triggers.delete(id);
800
+ }
801
+ };
1113
802
  }
1114
- /** @ignore */
1115
- canAnimate() {
1116
- return (this.rootDirective.cssAnimation() &&
1117
- ((this.rootDirective.cssOpeningAnimation() && this.rootDirective.state() === RdxTooltipState.OPEN) ||
1118
- (this.rootDirective.cssClosingAnimation() && this.rootDirective.state() === RdxTooltipState.CLOSED)));
803
+ context() {
804
+ return this.rootContext();
1119
805
  }
1120
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipContentAttributesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1121
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipContentAttributesComponent, isStandalone: true, selector: "[rdxTooltipContentAttributes]", host: { listeners: { "animationstart": "onAnimationStart($event)", "animationend": "onAnimationEnd($event)", "pointerenter": "pointerenter()", "pointerleave": "pointerleave()", "focus": "focus()", "blur": "blur()" }, properties: { "attr.role": "\"dialog\"", "attr.id": "name()", "attr.data-state": "rootDirective.state()", "attr.data-side": "rootDirective.contentDirective().side()", "attr.data-align": "rootDirective.contentDirective().align()", "style": "disableAnimation() ? {animation: \"none !important\"} : null" } }, providers: [
1122
- {
1123
- provide: RdxTooltipContentAttributesToken,
1124
- useExisting: forwardRef(() => RdxTooltipContentAttributesComponent)
1125
- }
1126
- ], ngImport: i0, template: `
1127
- <ng-content />
1128
- `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1129
806
  }
1130
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipContentAttributesComponent, decorators: [{
1131
- type: Component,
1132
- args: [{
1133
- selector: '[rdxTooltipContentAttributes]',
1134
- template: `
1135
- <ng-content />
1136
- `,
1137
- host: {
1138
- '[attr.role]': '"dialog"',
1139
- '[attr.id]': 'name()',
1140
- '[attr.data-state]': 'rootDirective.state()',
1141
- '[attr.data-side]': 'rootDirective.contentDirective().side()',
1142
- '[attr.data-align]': 'rootDirective.contentDirective().align()',
1143
- '[style]': 'disableAnimation() ? {animation: "none !important"} : null',
1144
- '(animationstart)': 'onAnimationStart($event)',
1145
- '(animationend)': 'onAnimationEnd($event)',
1146
- '(pointerenter)': 'pointerenter()',
1147
- '(pointerleave)': 'pointerleave()',
1148
- '(focus)': 'focus()',
1149
- '(blur)': 'blur()'
1150
- },
1151
- providers: [
1152
- {
1153
- provide: RdxTooltipContentAttributesToken,
1154
- useExisting: forwardRef(() => RdxTooltipContentAttributesComponent)
1155
- }
1156
- ],
1157
- changeDetection: ChangeDetectionStrategy.OnPush
1158
- }]
1159
- }] });
807
+ function createRdxTooltipHandle() {
808
+ return new RdxTooltipHandle();
809
+ }
1160
810
 
1161
- const _imports = [
1162
- RdxTooltipArrowDirective,
1163
- RdxTooltipCloseDirective,
1164
- RdxTooltipContentDirective,
1165
- RdxTooltipTriggerDirective,
1166
- RdxTooltipRootDirective,
1167
- RdxTooltipAnchorDirective,
1168
- RdxTooltipContentAttributesComponent
811
+ const tooltipImports = [
812
+ RdxTooltip,
813
+ RdxTooltipArrow,
814
+ RdxTooltipPopup,
815
+ RdxTooltipPortal,
816
+ RdxTooltipPortalPresence,
817
+ RdxTooltipPositioner,
818
+ RdxTooltipProvider,
819
+ RdxTooltipTrigger
1169
820
  ];
1170
- class RdxTooltipModule {
1171
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1172
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipModule, imports: [RdxTooltipArrowDirective,
1173
- RdxTooltipCloseDirective,
1174
- RdxTooltipContentDirective,
1175
- RdxTooltipTriggerDirective,
1176
- RdxTooltipRootDirective,
1177
- RdxTooltipAnchorDirective,
1178
- RdxTooltipContentAttributesComponent], exports: [RdxTooltipArrowDirective,
1179
- RdxTooltipCloseDirective,
1180
- RdxTooltipContentDirective,
1181
- RdxTooltipTriggerDirective,
1182
- RdxTooltipRootDirective,
1183
- RdxTooltipAnchorDirective,
1184
- RdxTooltipContentAttributesComponent] }); }
1185
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipModule }); }
1186
- }
1187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipModule, decorators: [{
1188
- type: NgModule,
1189
- args: [{
1190
- imports: [..._imports],
1191
- exports: [..._imports]
1192
- }]
1193
- }] });
1194
821
 
1195
822
  /**
1196
823
  * Generated bundle index. Do not edit.
1197
824
  */
1198
825
 
1199
- export { RdxTooltipAnchorDirective, RdxTooltipArrowDirective, RdxTooltipCloseDirective, RdxTooltipContentAttributesComponent, RdxTooltipContentDirective, RdxTooltipModule, RdxTooltipRootDirective, RdxTooltipTriggerDirective };
826
+ export { RdxTooltip, RdxTooltipArrow, RdxTooltipDefaultsToken, RdxTooltipHandle, RdxTooltipPopup, RdxTooltipPortal, RdxTooltipPortalPresence, RdxTooltipPositioner, RdxTooltipProvider, RdxTooltipTrigger, createRdxTooltipHandle, defaultTooltipConfig, injectRdxTooltipConfig, injectRdxTooltipContext, injectRdxTooltipProviderContext, provideRdxTooltipConfig, provideRdxTooltipContext, provideRdxTooltipProviderContext, tooltipImports };
1200
827
  //# sourceMappingURL=radix-ng-primitives-tooltip.mjs.map