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

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 (178) 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.map +1 -1
  13. package/fesm2022/radix-ng-primitives-checkbox.mjs +378 -54
  14. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-collapsible.mjs +182 -81
  16. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-collection.mjs +40 -57
  18. package/fesm2022/radix-ng-primitives-collection.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-context-menu.mjs +140 -424
  21. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-core.mjs +735 -744
  23. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-cropper.mjs +1 -0
  25. package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-date-field.mjs +51 -45
  27. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-dialog.mjs +655 -327
  29. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +70 -46
  31. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-drawer.mjs +1059 -0
  33. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -0
  34. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  35. package/fesm2022/radix-ng-primitives-field.mjs +363 -0
  36. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -0
  37. package/fesm2022/radix-ng-primitives-fieldset.mjs +79 -0
  38. package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -0
  39. package/fesm2022/radix-ng-primitives-focus-scope.mjs +23 -8
  40. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  41. package/fesm2022/radix-ng-primitives-input.mjs +172 -0
  42. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -0
  43. package/fesm2022/radix-ng-primitives-label.mjs +6 -6
  44. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  45. package/fesm2022/radix-ng-primitives-menu.mjs +1480 -344
  46. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  47. package/fesm2022/radix-ng-primitives-menubar.mjs +290 -162
  48. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  49. package/fesm2022/radix-ng-primitives-meter.mjs +271 -0
  50. package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -0
  51. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +1052 -1553
  52. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  53. package/fesm2022/radix-ng-primitives-number-field.mjs +1102 -367
  54. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  55. package/fesm2022/radix-ng-primitives-pagination.mjs.map +1 -1
  56. package/fesm2022/radix-ng-primitives-popover.mjs +978 -989
  57. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  58. package/fesm2022/radix-ng-primitives-popper.mjs +91 -41
  59. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  60. package/fesm2022/radix-ng-primitives-portal.mjs +34 -10
  61. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  62. package/fesm2022/radix-ng-primitives-presence.mjs +134 -246
  63. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  64. package/fesm2022/radix-ng-primitives-preview-card.mjs +997 -0
  65. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -0
  66. package/fesm2022/radix-ng-primitives-progress.mjs +223 -84
  67. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  68. package/fesm2022/radix-ng-primitives-radio.mjs +191 -51
  69. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  70. package/fesm2022/radix-ng-primitives-roving-focus.mjs +96 -50
  71. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  72. package/fesm2022/radix-ng-primitives-select.mjs +791 -509
  73. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  74. package/fesm2022/radix-ng-primitives-separator.mjs +12 -35
  75. package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
  76. package/fesm2022/radix-ng-primitives-slider.mjs +969 -717
  77. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  78. package/fesm2022/radix-ng-primitives-stepper.mjs +15 -19
  79. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  80. package/fesm2022/radix-ng-primitives-switch.mjs +125 -113
  81. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  82. package/fesm2022/radix-ng-primitives-tabs.mjs +381 -108
  83. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  84. package/fesm2022/radix-ng-primitives-time-field.mjs +55 -46
  85. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  86. package/fesm2022/radix-ng-primitives-toggle-group.mjs +121 -247
  87. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  88. package/fesm2022/radix-ng-primitives-toggle.mjs +98 -61
  89. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  90. package/fesm2022/radix-ng-primitives-toolbar.mjs +303 -92
  91. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  92. package/fesm2022/radix-ng-primitives-tooltip.mjs +690 -1071
  93. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  94. package/fesm2022/radix-ng-primitives-visually-hidden.mjs +25 -66
  95. package/fesm2022/radix-ng-primitives-visually-hidden.mjs.map +1 -1
  96. package/meter/README.md +3 -0
  97. package/navigation-menu/README.md +2 -1
  98. package/package.json +31 -18
  99. package/portal/README.md +2 -0
  100. package/preview-card/README.md +3 -0
  101. package/schematics/collection.json +1 -0
  102. package/schematics/ng-add/index.d.ts +3 -2
  103. package/schematics/ng-add/index.js +62 -31
  104. package/schematics/ng-add/index.js.map +1 -1
  105. package/schematics/ng-add/package-config.d.ts +4 -2
  106. package/schematics/ng-add/package-config.js +10 -2
  107. package/schematics/ng-add/package-config.js.map +1 -1
  108. package/schematics/ng-add/schema.d.ts +3 -0
  109. package/schematics/ng-add/schema.js +3 -0
  110. package/schematics/ng-add/schema.js.map +1 -0
  111. package/schematics/ng-add/schema.json +14 -0
  112. package/select/README.md +2 -0
  113. package/types/radix-ng-primitives-accordion.d.ts +48 -14
  114. package/types/radix-ng-primitives-alert-dialog.d.ts +95 -38
  115. package/types/radix-ng-primitives-arrow.d.ts +1 -1
  116. package/types/radix-ng-primitives-aspect-ratio.d.ts +1 -1
  117. package/types/radix-ng-primitives-avatar.d.ts +7 -11
  118. package/types/radix-ng-primitives-button.d.ts +73 -0
  119. package/types/radix-ng-primitives-calendar.d.ts +1 -2
  120. package/types/radix-ng-primitives-checkbox.d.ts +201 -32
  121. package/types/radix-ng-primitives-collapsible.d.ts +112 -39
  122. package/types/radix-ng-primitives-collection.d.ts +38 -34
  123. package/types/radix-ng-primitives-config.d.ts +1 -1
  124. package/types/radix-ng-primitives-context-menu.d.ts +60 -116
  125. package/types/radix-ng-primitives-core.d.ts +307 -236
  126. package/types/radix-ng-primitives-cropper.d.ts +2 -2
  127. package/types/radix-ng-primitives-date-field.d.ts +38 -23
  128. package/types/radix-ng-primitives-dialog.d.ts +282 -165
  129. package/types/radix-ng-primitives-dismissable-layer.d.ts +15 -7
  130. package/types/radix-ng-primitives-drawer.d.ts +448 -0
  131. package/types/radix-ng-primitives-editable.d.ts +1 -1
  132. package/types/radix-ng-primitives-field.d.ts +373 -0
  133. package/types/radix-ng-primitives-fieldset.d.ts +48 -0
  134. package/types/radix-ng-primitives-focus-scope.d.ts +13 -5
  135. package/types/radix-ng-primitives-input.d.ts +87 -0
  136. package/types/radix-ng-primitives-label.d.ts +0 -1
  137. package/types/radix-ng-primitives-menu.d.ts +572 -99
  138. package/types/radix-ng-primitives-menubar.d.ts +60 -50
  139. package/types/radix-ng-primitives-meter.d.ts +193 -0
  140. package/types/radix-ng-primitives-navigation-menu.d.ts +422 -340
  141. package/types/radix-ng-primitives-number-field.d.ts +405 -145
  142. package/types/radix-ng-primitives-pagination.d.ts +2 -2
  143. package/types/radix-ng-primitives-popover.d.ts +365 -351
  144. package/types/radix-ng-primitives-popper.d.ts +49 -9
  145. package/types/radix-ng-primitives-portal.d.ts +14 -6
  146. package/types/radix-ng-primitives-presence.d.ts +28 -76
  147. package/types/radix-ng-primitives-preview-card.d.ts +359 -0
  148. package/types/radix-ng-primitives-progress.d.ts +174 -48
  149. package/types/radix-ng-primitives-radio.d.ts +55 -25
  150. package/types/radix-ng-primitives-roving-focus.d.ts +30 -21
  151. package/types/radix-ng-primitives-select.d.ts +475 -177
  152. package/types/radix-ng-primitives-separator.d.ts +7 -32
  153. package/types/radix-ng-primitives-slider.d.ts +315 -201
  154. package/types/radix-ng-primitives-stepper.d.ts +5 -7
  155. package/types/radix-ng-primitives-switch.d.ts +86 -71
  156. package/types/radix-ng-primitives-tabs.d.ts +213 -79
  157. package/types/radix-ng-primitives-time-field.d.ts +42 -27
  158. package/types/radix-ng-primitives-toggle-group.d.ts +85 -164
  159. package/types/radix-ng-primitives-toggle.d.ts +43 -53
  160. package/types/radix-ng-primitives-toolbar.d.ts +163 -38
  161. package/types/radix-ng-primitives-tooltip.d.ts +347 -384
  162. package/types/radix-ng-primitives-visually-hidden.d.ts +19 -19
  163. package/dropdown-menu/README.md +0 -1
  164. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +0 -581
  165. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs.map +0 -1
  166. package/fesm2022/radix-ng-primitives-hover-card.mjs +0 -1238
  167. package/fesm2022/radix-ng-primitives-hover-card.mjs.map +0 -1
  168. package/fesm2022/radix-ng-primitives-select2.mjs +0 -897
  169. package/fesm2022/radix-ng-primitives-select2.mjs.map +0 -1
  170. package/fesm2022/radix-ng-primitives-tooltip2.mjs +0 -735
  171. package/fesm2022/radix-ng-primitives-tooltip2.mjs.map +0 -1
  172. package/hover-card/README.md +0 -3
  173. package/select2/README.md +0 -3
  174. package/tooltip2/README.md +0 -3
  175. package/types/radix-ng-primitives-dropdown-menu.d.ts +0 -171
  176. package/types/radix-ng-primitives-hover-card.d.ts +0 -471
  177. package/types/radix-ng-primitives-select2.d.ts +0 -511
  178. package/types/radix-ng-primitives-tooltip2.d.ts +0 -325
@@ -1,1200 +1,819 @@
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
+ if (this.rootContext.disableHoverablePopup())
805
564
  return;
806
- }
807
- this.handleOpen();
565
+ this.rootContext.closeDelayed();
808
566
  });
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
567
  });
885
- this.rootDirective?.triggerDirective().elementRef.nativeElement.dispatchEvent(clickEvent);
568
+ this.dismissableLayer.focusOutside.subscribe((e) => e.preventDefault());
569
+ this.dismissableLayer.dismiss.subscribe(() => this.rootContext.close());
886
570
  }
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 }); }
571
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
572
+ 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
573
  }
895
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipAnchorDirective, decorators: [{
574
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, decorators: [{
896
575
  type: Directive,
897
576
  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: [
577
+ selector: '[rdxTooltipPositioner]',
578
+ providers: [provideRdxPopperContentConfig({ side: 'top', arrowPadding: 5, collisionPadding: 5 })],
579
+ hostDirectives: [
580
+ RdxDismissableLayer,
908
581
  {
909
- provide: RdxTooltipAnchorToken,
910
- useExisting: forwardRef(() => RdxTooltipAnchorDirective)
582
+ directive: RdxPopperContentWrapper,
583
+ inputs: [
584
+ 'anchor',
585
+ 'side',
586
+ 'sideOffset',
587
+ 'align',
588
+ 'alignOffset',
589
+ 'arrowPadding',
590
+ 'avoidCollisions',
591
+ 'collisionBoundary',
592
+ 'collisionPadding',
593
+ 'sticky',
594
+ 'hideWhenDetached',
595
+ 'positionStrategy',
596
+ 'updatePositionStrategy'
597
+ ]
911
598
  }
912
- ]
599
+ ],
600
+ host: {
601
+ '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
602
+ '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
603
+ '[attr.data-side]': 'wrapper.placedSide()',
604
+ '[attr.data-align]': 'wrapper.placedAlign()',
605
+ '[style]': `{
606
+ '--anchor-width': 'var(--radix-popper-anchor-width)',
607
+ '--anchor-height': 'var(--radix-popper-anchor-height)',
608
+ '--available-width': 'var(--radix-popper-available-width)',
609
+ '--available-height': 'var(--radix-popper-available-height)',
610
+ '--transform-origin': 'var(--radix-popper-transform-origin)'
611
+ }`
612
+ }
913
613
  }]
914
- }] });
614
+ }], 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
615
 
916
- class RdxTooltipArrowDirective {
616
+ class RdxTooltipTrigger {
917
617
  constructor() {
918
- /** @ignore */
919
- this.renderer = inject(Renderer2);
920
- /** @ignore */
921
- this.rootDirective = injectTooltipRoot();
922
- /** @ignore */
618
+ this.parentRootContext = injectRdxTooltipContext(true);
923
619
  this.elementRef = inject(ElementRef);
620
+ this.generatedId = injectId('rdx-tooltip-trigger-');
924
621
  /**
925
- * @description The width of the arrow in pixels.
926
- * @default 10
622
+ * Associates this trigger with a detached tooltip root.
927
623
  */
928
- this.width = input(RDX_POSITIONING_DEFAULTS.arrow.width, { ...(ngDevMode ? { debugName: "width" } : /* istanbul ignore next */ {}), transform: numberAttribute });
624
+ this.handle = input(...(ngDevMode ? [undefined, { debugName: "handle" }] : /* istanbul ignore next */ []));
929
625
  /**
930
- * @description The height of the arrow in pixels.
931
- * @default 5
626
+ * Data associated with this trigger while it is active.
932
627
  */
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');
628
+ this.payload = input(...(ngDevMode ? [undefined, { debugName: "payload" }] : /* istanbul ignore next */ []));
629
+ /**
630
+ * ID used to identify this trigger when opening a detached tooltip imperatively.
631
+ */
632
+ this.id = input(...(ngDevMode ? [undefined, { debugName: "id" }] : /* istanbul ignore next */ []));
633
+ /**
634
+ * Whether the tooltip should close when the trigger is clicked.
635
+ * @defaultValue true
636
+ */
637
+ this.closeOnClick = input(true, { ...(ngDevMode ? { debugName: "closeOnClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
638
+ /**
639
+ * Whether this trigger is disabled. A disabled trigger never opens the tooltip.
640
+ * @defaultValue false
641
+ */
642
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
643
+ /**
644
+ * Overrides the open delay (ms) for this trigger. Falls back to the root/provider/global delay.
645
+ */
646
+ this.delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
647
+ /**
648
+ * Overrides the close delay (ms) for this trigger. Falls back to the root/provider/global delay.
649
+ */
650
+ this.closeDelay = input(undefined, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: (value) => (value == null ? undefined : numberAttribute(value)) });
651
+ this.userOnPointerDown = input(undefined, { ...(ngDevMode ? { debugName: "userOnPointerDown" } : /* istanbul ignore next */ {}), alias: 'rdxOnPointerDown' });
652
+ this.triggerId = computed(() => this.id() ?? this.generatedId, ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
653
+ this.rootContext = computed(() => this.handle()?.context() ?? this.parentRootContext, ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
654
+ /** Disabled if either the root or this trigger is disabled. */
655
+ this.isDisabled = computed(() => (this.rootContext()?.disabled() ?? false) || this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
656
+ /** Whether this specific trigger is the active anchor of an open tooltip. */
657
+ this.isOpen = computed(() => this.rootContext()?.isOpen() === true && this.rootContext()?.trigger() === this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
658
+ this.isPointerDown = signal(false, ...(ngDevMode ? [{ debugName: "isPointerDown" }] : /* istanbul ignore next */ []));
659
+ this.hasPointerMoveOpened = signal(false, ...(ngDevMode ? [{ debugName: "hasPointerMoveOpened" }] : /* istanbul ignore next */ []));
660
+ effect((onCleanup) => {
661
+ const handle = this.handle();
662
+ if (handle) {
663
+ onCleanup(untracked(() => handle.registerTrigger(this.triggerId(), this.elementRef.nativeElement, () => this.payload())));
664
+ }
665
+ else if (this.parentRootContext) {
666
+ onCleanup(untracked(() => this.parentRootContext.registerTrigger(this.elementRef.nativeElement)));
960
667
  }
961
668
  });
962
- this.onArrowSvgElementChangeEffect();
963
- this.onContentPositionAndArrowDimensionsChangeEffect();
964
669
  }
965
- /** @ignore */
966
- setAnchorOrTriggerRect() {
967
- this.anchorOrTriggerRect = (this.rootDirective.anchorDirective() ?? this.rootDirective.triggerDirective()).elementRef.nativeElement.getBoundingClientRect();
670
+ handleFocus() {
671
+ const rootContext = this.rootContext();
672
+ if (!rootContext || this.isDisabled() || this.isPointerDown()) {
673
+ return;
674
+ }
675
+ rootContext.setDelays(this.delay(), this.closeDelay());
676
+ rootContext.open(this.elementRef.nativeElement, this.payload());
968
677
  }
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);
678
+ handleBlur() {
679
+ this.rootContext()?.closeDelayed();
979
680
  }
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
- });
681
+ handleClick() {
682
+ const rootContext = this.rootContext();
683
+ if (rootContext?.isOpen() && this.closeOnClick()) {
684
+ rootContext.close();
685
+ }
1008
686
  }
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();
687
+ handlePointerMove(event) {
688
+ if (event.pointerType === 'touch') {
689
+ return;
690
+ }
691
+ const rootContext = this.rootContext();
692
+ if (!rootContext || this.isDisabled()) {
693
+ return;
694
+ }
695
+ if (rootContext.trackCursorAxis() !== 'none') {
696
+ rootContext.setCursorPosition({ x: event.clientX, y: event.clientY });
697
+ }
698
+ if (!this.hasPointerMoveOpened()) {
699
+ rootContext.setDelays(this.delay(), this.closeDelay());
700
+ rootContext.onTriggerEnter(this.elementRef.nativeElement, this.payload());
701
+ this.hasPointerMoveOpened.set(true);
702
+ }
1042
703
  }
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
- });
704
+ handlePointerLeave() {
705
+ this.rootContext()?.onTriggerLeave();
706
+ this.hasPointerMoveOpened.set(false);
707
+ }
708
+ async handlePointerDown(event) {
709
+ const user = this.userOnPointerDown();
710
+ let result;
711
+ if (user) {
712
+ result = user(event);
713
+ if (result instanceof Promise)
714
+ result = await result;
715
+ }
716
+ if (event.defaultPrevented || result === false) {
717
+ return;
718
+ }
719
+ this.isPointerDown.set(true);
720
+ const handlePointerUp = () => {
721
+ setTimeout(() => this.isPointerDown.set(false), 1);
722
+ };
723
+ document.addEventListener('pointerup', handlePointerUp, { once: true });
1051
724
  }
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 }); }
725
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
726
+ 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
727
  }
1060
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipCloseDirective, decorators: [{
728
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, decorators: [{
1061
729
  type: Directive,
1062
730
  args: [{
1063
- selector: '[rdxTooltipClose]',
731
+ selector: '[rdxTooltipTrigger]',
732
+ hostDirectives: [RdxPopperAnchor],
1064
733
  host: {
1065
734
  type: 'button',
1066
- '(click)': 'rootDirective.handleClose(true)'
1067
- },
1068
- providers: [
1069
- {
1070
- provide: RdxTooltipCloseToken,
1071
- useExisting: forwardRef(() => RdxTooltipCloseDirective)
1072
- }
1073
- ]
735
+ 'data-grace-area-trigger': "''",
736
+ '[id]': 'triggerId()',
737
+ '[attr.aria-describedby]': 'isOpen() ? rootContext()?.contentId : undefined',
738
+ '[attr.data-popup-open]': 'isOpen() ? "" : undefined',
739
+ '[attr.data-trigger-disabled]': 'isDisabled() ? "" : undefined',
740
+ '(pointermove)': 'handlePointerMove($event)',
741
+ '(pointerleave)': 'handlePointerLeave()',
742
+ '(pointerdown)': 'handlePointerDown($event)',
743
+ '(focus)': 'handleFocus()',
744
+ '(blur)': 'handleBlur()',
745
+ '(click)': 'handleClick()'
746
+ }
1074
747
  }]
1075
- }], ctorParameters: () => [] });
748
+ }], 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
749
 
1077
- class RdxTooltipContentAttributesComponent {
750
+ class RdxTooltipHandle {
1078
751
  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();
752
+ this.rootContext = signal(undefined, ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
753
+ this.triggers = new Map();
754
+ this.rootTriggerCleanups = new Map();
755
+ this.isOpen = computed(() => this.rootContext()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
756
+ }
757
+ open(triggerId) {
758
+ const trigger = this.triggers.get(triggerId);
759
+ if (!trigger) {
760
+ throw new Error(`No tooltip trigger registered with id "${triggerId}".`);
761
+ }
762
+ this.rootContext()?.open(trigger.element, trigger.payload());
1101
763
  }
1102
- /** @ignore */
1103
- pointerleave() {
1104
- this.rootDirective.handleClose();
764
+ close() {
765
+ this.rootContext()?.close();
1105
766
  }
1106
- /** @ignore */
1107
- focus() {
1108
- this.rootDirective.handleOpen();
767
+ registerRoot(rootContext) {
768
+ this.rootContext.set(rootContext);
769
+ this.triggers.forEach((trigger, id) => {
770
+ this.rootTriggerCleanups.set(id, rootContext.registerTrigger(trigger.element));
771
+ });
772
+ return () => {
773
+ if (this.rootContext() === rootContext) {
774
+ this.rootTriggerCleanups.forEach((cleanup) => cleanup());
775
+ this.rootTriggerCleanups.clear();
776
+ this.rootContext.set(undefined);
777
+ }
778
+ };
1109
779
  }
1110
- /** @ignore */
1111
- blur() {
1112
- this.rootDirective.handleClose();
780
+ registerTrigger(id, trigger, payload) {
781
+ this.rootTriggerCleanups.get(id)?.();
782
+ this.triggers.set(id, { element: trigger, payload });
783
+ const unregisterFromRoot = this.rootContext()?.registerTrigger(trigger);
784
+ if (unregisterFromRoot) {
785
+ this.rootTriggerCleanups.set(id, unregisterFromRoot);
786
+ }
787
+ return () => {
788
+ this.rootTriggerCleanups.get(id)?.();
789
+ this.rootTriggerCleanups.delete(id);
790
+ if (this.triggers.get(id)?.element === trigger) {
791
+ this.triggers.delete(id);
792
+ }
793
+ };
1113
794
  }
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)));
795
+ context() {
796
+ return this.rootContext();
1119
797
  }
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
798
  }
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
- }] });
799
+ function createRdxTooltipHandle() {
800
+ return new RdxTooltipHandle();
801
+ }
1160
802
 
1161
- const _imports = [
1162
- RdxTooltipArrowDirective,
1163
- RdxTooltipCloseDirective,
1164
- RdxTooltipContentDirective,
1165
- RdxTooltipTriggerDirective,
1166
- RdxTooltipRootDirective,
1167
- RdxTooltipAnchorDirective,
1168
- RdxTooltipContentAttributesComponent
803
+ const tooltipImports = [
804
+ RdxTooltip,
805
+ RdxTooltipArrow,
806
+ RdxTooltipPopup,
807
+ RdxTooltipPortal,
808
+ RdxTooltipPortalPresence,
809
+ RdxTooltipPositioner,
810
+ RdxTooltipProvider,
811
+ RdxTooltipTrigger
1169
812
  ];
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
813
 
1195
814
  /**
1196
815
  * Generated bundle index. Do not edit.
1197
816
  */
1198
817
 
1199
- export { RdxTooltipAnchorDirective, RdxTooltipArrowDirective, RdxTooltipCloseDirective, RdxTooltipContentAttributesComponent, RdxTooltipContentDirective, RdxTooltipModule, RdxTooltipRootDirective, RdxTooltipTriggerDirective };
818
+ export { RdxTooltip, RdxTooltipArrow, RdxTooltipDefaultsToken, RdxTooltipHandle, RdxTooltipPopup, RdxTooltipPortal, RdxTooltipPortalPresence, RdxTooltipPositioner, RdxTooltipProvider, RdxTooltipTrigger, createRdxTooltipHandle, defaultTooltipConfig, injectRdxTooltipConfig, injectRdxTooltipContext, injectRdxTooltipProviderContext, provideRdxTooltipConfig, provideRdxTooltipContext, provideRdxTooltipProviderContext, tooltipImports };
1200
819
  //# sourceMappingURL=radix-ng-primitives-tooltip.mjs.map