@radix-ng/primitives 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/compodoc/documentation.json +2751 -957
  2. package/esm2022/popover/index.mjs +41 -0
  3. package/esm2022/popover/radix-ng-primitives-popover.mjs +5 -0
  4. package/esm2022/popover/src/popover-arrow.directive.mjs +112 -0
  5. package/esm2022/popover/src/popover-arrow.token.mjs +3 -0
  6. package/esm2022/popover/src/popover-close.directive.mjs +37 -0
  7. package/esm2022/popover/src/popover-content.directive.mjs +227 -0
  8. package/esm2022/popover/src/popover-root.directive.mjs +142 -0
  9. package/esm2022/popover/src/popover-root.inject.mjs +7 -0
  10. package/esm2022/popover/src/popover-root.token.mjs +3 -0
  11. package/esm2022/popover/src/popover-trigger.directive.mjs +42 -0
  12. package/esm2022/popover/src/popover.constants.mjs +90 -0
  13. package/esm2022/popover/src/popover.types.mjs +14 -0
  14. package/esm2022/popover/src/popover.utils.mjs +115 -0
  15. package/esm2022/radio/src/radio-indicator.directive.mjs +3 -3
  16. package/esm2022/radio/src/radio-item-input.directive.mjs +2 -2
  17. package/esm2022/radio/src/radio-item.directive.mjs +10 -13
  18. package/esm2022/radio/src/radio-root.directive.mjs +16 -20
  19. package/esm2022/radio/src/radio-tokens.mjs +1 -1
  20. package/fesm2022/radix-ng-primitives-popover.mjs +796 -0
  21. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -0
  22. package/fesm2022/radix-ng-primitives-radio.mjs +26 -33
  23. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  24. package/package.json +7 -1
  25. package/popover/README.md +3 -0
  26. package/popover/index.d.ts +17 -0
  27. package/popover/src/popover-arrow.directive.d.ts +37 -0
  28. package/popover/src/popover-arrow.token.d.ts +3 -0
  29. package/popover/src/popover-close.directive.d.ts +15 -0
  30. package/popover/src/popover-content.directive.d.ts +84 -0
  31. package/popover/src/popover-root.directive.d.ts +58 -0
  32. package/popover/src/popover-root.inject.d.ts +2 -0
  33. package/popover/src/popover-root.token.d.ts +3 -0
  34. package/popover/src/popover-trigger.directive.d.ts +18 -0
  35. package/popover/src/popover.constants.d.ts +8 -0
  36. package/popover/src/popover.types.d.ts +34 -0
  37. package/popover/src/popover.utils.d.ts +12 -0
  38. package/radio/src/radio-item.directive.d.ts +2 -2
  39. package/radio/src/radio-root.directive.d.ts +9 -8
  40. package/radio/src/radio-tokens.d.ts +6 -4
@@ -0,0 +1,796 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, isDevMode, assertInInjectionContext, inject, Renderer2, ElementRef, input, computed, signal, effect, untracked, forwardRef, Directive, TemplateRef, DestroyRef, output, SimpleChange, contentChild, ViewContainerRef, NgModule } from '@angular/core';
3
+ import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/cdk/overlay';
5
+ import { Overlay, CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
6
+ import { filter, tap } from 'rxjs';
7
+ import { DOCUMENT } from '@angular/common';
8
+
9
+ const RdxPopoverArrowToken = new InjectionToken('RdxPopoverArrowToken');
10
+
11
+ const RdxPopoverRootToken = new InjectionToken('RdxPopoverRootToken');
12
+
13
+ function injectPopoverRoot() {
14
+ isDevMode() && assertInInjectionContext(injectPopoverRoot);
15
+ return inject(RdxPopoverRootToken);
16
+ }
17
+
18
+ var RdxPopoverSide;
19
+ (function (RdxPopoverSide) {
20
+ RdxPopoverSide["Top"] = "top";
21
+ RdxPopoverSide["Right"] = "right";
22
+ RdxPopoverSide["Bottom"] = "bottom";
23
+ RdxPopoverSide["Left"] = "left";
24
+ })(RdxPopoverSide || (RdxPopoverSide = {}));
25
+ var RdxPopoverAlign;
26
+ (function (RdxPopoverAlign) {
27
+ RdxPopoverAlign["Start"] = "start";
28
+ RdxPopoverAlign["Center"] = "center";
29
+ RdxPopoverAlign["End"] = "end";
30
+ })(RdxPopoverAlign || (RdxPopoverAlign = {}));
31
+
32
+ const POPOVER_POSITIONS = {
33
+ [RdxPopoverSide.Top]: {
34
+ [RdxPopoverAlign.Center]: {
35
+ originX: 'center',
36
+ originY: 'top',
37
+ overlayX: 'center',
38
+ overlayY: 'bottom'
39
+ },
40
+ [RdxPopoverAlign.Start]: {
41
+ originX: 'start',
42
+ originY: 'top',
43
+ overlayX: 'start',
44
+ overlayY: 'bottom'
45
+ },
46
+ [RdxPopoverAlign.End]: {
47
+ originX: 'end',
48
+ originY: 'top',
49
+ overlayX: 'end',
50
+ overlayY: 'bottom'
51
+ }
52
+ },
53
+ [RdxPopoverSide.Right]: {
54
+ [RdxPopoverAlign.Center]: {
55
+ originX: 'end',
56
+ originY: 'center',
57
+ overlayX: 'start',
58
+ overlayY: 'center'
59
+ },
60
+ [RdxPopoverAlign.Start]: {
61
+ originX: 'end',
62
+ originY: 'top',
63
+ overlayX: 'start',
64
+ overlayY: 'top'
65
+ },
66
+ [RdxPopoverAlign.End]: {
67
+ originX: 'end',
68
+ originY: 'bottom',
69
+ overlayX: 'start',
70
+ overlayY: 'bottom'
71
+ }
72
+ },
73
+ [RdxPopoverSide.Bottom]: {
74
+ [RdxPopoverAlign.Center]: {
75
+ originX: 'center',
76
+ originY: 'bottom',
77
+ overlayX: 'center',
78
+ overlayY: 'top'
79
+ },
80
+ [RdxPopoverAlign.Start]: {
81
+ originX: 'start',
82
+ originY: 'bottom',
83
+ overlayX: 'start',
84
+ overlayY: 'top'
85
+ },
86
+ [RdxPopoverAlign.End]: {
87
+ originX: 'end',
88
+ originY: 'bottom',
89
+ overlayX: 'end',
90
+ overlayY: 'top'
91
+ }
92
+ },
93
+ [RdxPopoverSide.Left]: {
94
+ [RdxPopoverAlign.Center]: {
95
+ originX: 'start',
96
+ originY: 'center',
97
+ overlayX: 'end',
98
+ overlayY: 'center'
99
+ },
100
+ [RdxPopoverAlign.Start]: {
101
+ originX: 'start',
102
+ originY: 'top',
103
+ overlayX: 'end',
104
+ overlayY: 'top'
105
+ },
106
+ [RdxPopoverAlign.End]: {
107
+ originX: 'start',
108
+ originY: 'bottom',
109
+ overlayX: 'end',
110
+ overlayY: 'bottom'
111
+ }
112
+ }
113
+ };
114
+ const DEFAULTS = {
115
+ offsets: {
116
+ side: 10,
117
+ align: 10
118
+ }
119
+ };
120
+
121
+ let allPossibleConnectedPositions;
122
+ function getAllPossibleConnectedPositions() {
123
+ if (!allPossibleConnectedPositions) {
124
+ allPossibleConnectedPositions = new Map();
125
+ }
126
+ if (allPossibleConnectedPositions.size < 1) {
127
+ Object.keys(POPOVER_POSITIONS).forEach((side) => {
128
+ Object.keys(POPOVER_POSITIONS[side] ?? {}).forEach((align) => {
129
+ allPossibleConnectedPositions.set(`${side}|${align}`, POPOVER_POSITIONS[side][align]);
130
+ });
131
+ });
132
+ }
133
+ return allPossibleConnectedPositions;
134
+ }
135
+ function getSideAndAlignFromAllPossibleConnectedPositions(position) {
136
+ const allPossibleConnectedPositions = getAllPossibleConnectedPositions();
137
+ let sideAndAlign;
138
+ allPossibleConnectedPositions.forEach((value, key) => {
139
+ if (position.originX === value.originX &&
140
+ position.originY === value.originY &&
141
+ position.overlayX === value.overlayX &&
142
+ position.overlayY === value.overlayY) {
143
+ const sideAndAlignArray = key.split('|');
144
+ sideAndAlign = {
145
+ side: sideAndAlignArray[0],
146
+ align: sideAndAlignArray[1]
147
+ };
148
+ }
149
+ });
150
+ if (!sideAndAlign) {
151
+ throw Error(`[RdxPopover] cannot infer both side and align from the given position (${JSON.stringify(position)})`);
152
+ }
153
+ return sideAndAlign;
154
+ }
155
+ function getContentPosition(sideAndAlignWithOffsets) {
156
+ const { side, align, sideOffset, alignOffset } = sideAndAlignWithOffsets;
157
+ const position = {
158
+ ...(POPOVER_POSITIONS[side]?.[align] ?? POPOVER_POSITIONS[RdxPopoverSide.Top][RdxPopoverAlign.Center])
159
+ };
160
+ if (sideOffset > 0) {
161
+ let xFactor = 0;
162
+ let yFactor = 0;
163
+ switch (side) {
164
+ case RdxPopoverSide.Top:
165
+ yFactor = -1;
166
+ break;
167
+ case RdxPopoverSide.Bottom:
168
+ yFactor = 1;
169
+ break;
170
+ case RdxPopoverSide.Left:
171
+ xFactor = -1;
172
+ break;
173
+ case RdxPopoverSide.Right:
174
+ xFactor = 1;
175
+ break;
176
+ }
177
+ position.offsetX = xFactor * sideOffset;
178
+ position.offsetY = yFactor * sideOffset;
179
+ }
180
+ if ([RdxPopoverAlign.Start, RdxPopoverAlign.End].includes(align) && alignOffset) {
181
+ const alignOffsetFactor = align === RdxPopoverAlign.End ? -1 : 1;
182
+ position.offsetX = alignOffsetFactor * alignOffset;
183
+ }
184
+ return position;
185
+ }
186
+ function getArrowPositionParams(sideAndAlign, arrowWidthAndHeight, triggerWidthAndHeight) {
187
+ const posParams = {
188
+ top: '',
189
+ bottom: '',
190
+ left: '',
191
+ right: '',
192
+ transform: ''
193
+ };
194
+ if ([RdxPopoverSide.Top, RdxPopoverSide.Bottom].includes(sideAndAlign.side)) {
195
+ if (sideAndAlign.side === RdxPopoverSide.Top) {
196
+ posParams.top = '100%';
197
+ }
198
+ else {
199
+ posParams.top = `-${arrowWidthAndHeight.height}px`;
200
+ posParams.transform = `rotate(180deg)`;
201
+ }
202
+ if (sideAndAlign.align === RdxPopoverAlign.Start) {
203
+ posParams.left = `${(triggerWidthAndHeight.width - arrowWidthAndHeight.width) / 2}px`;
204
+ }
205
+ else if (sideAndAlign.align === RdxPopoverAlign.Center) {
206
+ posParams.left = `calc(50% - ${arrowWidthAndHeight.width / 2}px)`;
207
+ }
208
+ else if (sideAndAlign.align === RdxPopoverAlign.End) {
209
+ posParams.right = `${(triggerWidthAndHeight.width - arrowWidthAndHeight.width) / 2}px`;
210
+ }
211
+ }
212
+ else if ([RdxPopoverSide.Left, RdxPopoverSide.Right].includes(sideAndAlign.side)) {
213
+ if (sideAndAlign.side === RdxPopoverSide.Left) {
214
+ posParams.right = `-${arrowWidthAndHeight.width}px`;
215
+ posParams.transform = `rotate(-90deg) translate(0, -50%)`;
216
+ }
217
+ else {
218
+ posParams.left = `-${arrowWidthAndHeight.width}px`;
219
+ posParams.transform = `rotate(90deg) translate(0, -50%)`;
220
+ }
221
+ if (sideAndAlign.align === RdxPopoverAlign.Start) {
222
+ posParams.top = `${(triggerWidthAndHeight.height - arrowWidthAndHeight.height) / 2}px`;
223
+ }
224
+ else if (sideAndAlign.align === RdxPopoverAlign.Center) {
225
+ posParams.top = `calc(50% - ${arrowWidthAndHeight.height / 2}px)`;
226
+ }
227
+ else if (sideAndAlign.align === RdxPopoverAlign.End) {
228
+ posParams.bottom = `${(triggerWidthAndHeight.height - arrowWidthAndHeight.height) / 2}px`;
229
+ }
230
+ }
231
+ return posParams;
232
+ }
233
+
234
+ class RdxPopoverArrowDirective {
235
+ constructor() {
236
+ /** @ignore */
237
+ this.renderer = inject(Renderer2);
238
+ /** @ignore */
239
+ this.popoverRoot = injectPopoverRoot();
240
+ /** @ignore */
241
+ this.elementRef = inject(ElementRef);
242
+ /**
243
+ * The width of the arrow in pixels.
244
+ */
245
+ this.width = input(10);
246
+ /**
247
+ * The height of the arrow in pixels.
248
+ */
249
+ this.height = input(5);
250
+ /** @ignore */
251
+ this.arrowSvgElement = computed(() => {
252
+ const width = this.width();
253
+ const height = this.height();
254
+ const svgElement = this.renderer.createElement('svg', 'svg');
255
+ this.renderer.setAttribute(svgElement, 'viewBox', '0 0 30 10');
256
+ this.renderer.setAttribute(svgElement, 'width', String(width));
257
+ this.renderer.setAttribute(svgElement, 'height', String(height));
258
+ const polygonElement = this.renderer.createElement('polygon', 'svg');
259
+ this.renderer.setAttribute(polygonElement, 'points', '0,0 30,0 15,10');
260
+ this.renderer.setAttribute(svgElement, 'preserveAspectRatio', 'none');
261
+ this.renderer.appendChild(svgElement, polygonElement);
262
+ return svgElement;
263
+ });
264
+ /** @ignore */
265
+ this.currentArrowSvgElement = signal(void 0);
266
+ /** @ignore */
267
+ this.position = toSignal(this.popoverRoot.popoverContentDirective().positionChange());
268
+ this.onArrowSvgElementChangeEffect();
269
+ this.onContentPositionChangeEffect();
270
+ }
271
+ /** @ignore */
272
+ ngAfterViewInit() {
273
+ if (this.elementRef.nativeElement.parentElement) {
274
+ this.renderer.setStyle(this.elementRef.nativeElement.parentElement, 'position', 'relative');
275
+ }
276
+ this.renderer.setStyle(this.elementRef.nativeElement, 'position', 'absolute');
277
+ this.renderer.setStyle(this.elementRef.nativeElement, 'boxSizing', '');
278
+ this.renderer.setStyle(this.elementRef.nativeElement, 'fontSize', '0px');
279
+ this.triggerRect = this.popoverRoot.popoverTriggerDirective().elementRef.nativeElement.getBoundingClientRect();
280
+ }
281
+ /** @ignore */
282
+ setPosition(position) {
283
+ const posParams = getArrowPositionParams(getSideAndAlignFromAllPossibleConnectedPositions(position.connectionPair), { width: this.width(), height: this.height() }, { width: this.triggerRect.width, height: this.triggerRect.height });
284
+ this.renderer.setStyle(this.elementRef.nativeElement, 'top', posParams.top);
285
+ this.renderer.setStyle(this.elementRef.nativeElement, 'bottom', posParams.bottom);
286
+ this.renderer.setStyle(this.elementRef.nativeElement, 'left', posParams.left);
287
+ this.renderer.setStyle(this.elementRef.nativeElement, 'right', posParams.right);
288
+ this.renderer.setStyle(this.elementRef.nativeElement, 'transform', posParams.transform);
289
+ }
290
+ /** @ignore */
291
+ onArrowSvgElementChangeEffect() {
292
+ effect(() => {
293
+ const arrowElement = this.arrowSvgElement();
294
+ untracked(() => {
295
+ const currentArrowSvgElement = this.currentArrowSvgElement();
296
+ if (currentArrowSvgElement) {
297
+ this.renderer.removeChild(this.elementRef.nativeElement, currentArrowSvgElement);
298
+ }
299
+ this.currentArrowSvgElement.set(arrowElement);
300
+ this.renderer.setStyle(this.elementRef.nativeElement, 'width', `${this.width()}px`);
301
+ this.renderer.setStyle(this.elementRef.nativeElement, 'height', `${this.height()}px`);
302
+ this.renderer.appendChild(this.elementRef.nativeElement, this.currentArrowSvgElement());
303
+ });
304
+ });
305
+ }
306
+ /** @ignore */
307
+ onContentPositionChangeEffect() {
308
+ effect(() => {
309
+ const position = this.position();
310
+ untracked(() => {
311
+ if (!position) {
312
+ return;
313
+ }
314
+ this.setPosition(position);
315
+ });
316
+ });
317
+ }
318
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverArrowDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
319
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.11", type: RdxPopoverArrowDirective, isStandalone: true, selector: "[rdxPopoverArrow]", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
320
+ {
321
+ provide: RdxPopoverArrowToken,
322
+ useExisting: forwardRef(() => RdxPopoverArrowDirective)
323
+ }
324
+ ], ngImport: i0 }); }
325
+ }
326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverArrowDirective, decorators: [{
327
+ type: Directive,
328
+ args: [{
329
+ selector: '[rdxPopoverArrow]',
330
+ standalone: true,
331
+ providers: [
332
+ {
333
+ provide: RdxPopoverArrowToken,
334
+ useExisting: forwardRef(() => RdxPopoverArrowDirective)
335
+ }
336
+ ]
337
+ }]
338
+ }], ctorParameters: () => [] });
339
+
340
+ class RdxPopoverCloseDirective {
341
+ constructor() {
342
+ /** @ignore */
343
+ this.popoverRoot = injectPopoverRoot();
344
+ /** @ignore */
345
+ this.elementRef = inject((ElementRef));
346
+ /** @ignore */
347
+ this.renderer = inject(Renderer2);
348
+ this.onIsControlledExternallyEffect();
349
+ }
350
+ /** @ignore */
351
+ onIsControlledExternallyEffect() {
352
+ effect(() => {
353
+ const isControlledExternally = this.popoverRoot.controlledExternally()();
354
+ untracked(() => {
355
+ this.renderer.setStyle(this.elementRef.nativeElement, 'display', isControlledExternally ? 'none' : null);
356
+ });
357
+ });
358
+ }
359
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
360
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.11", type: RdxPopoverCloseDirective, isStandalone: true, selector: "[rdxPopoverClose]", host: { attributes: { "type": "button" }, listeners: { "click": "popoverRoot.handleClose()" } }, ngImport: i0 }); }
361
+ }
362
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverCloseDirective, decorators: [{
363
+ type: Directive,
364
+ args: [{
365
+ selector: '[rdxPopoverClose]',
366
+ standalone: true,
367
+ host: {
368
+ type: 'button',
369
+ '(click)': 'popoverRoot.handleClose()'
370
+ }
371
+ }]
372
+ }], ctorParameters: () => [] });
373
+
374
+ class RdxPopoverContentDirective {
375
+ constructor() {
376
+ /** @ignore */
377
+ this.popoverRoot = injectPopoverRoot();
378
+ /** @ignore */
379
+ this.templateRef = inject(TemplateRef);
380
+ /** @ignore */
381
+ this.overlay = inject(Overlay);
382
+ /** @ignore */
383
+ this.destroyRef = inject(DestroyRef);
384
+ /** @ignore */
385
+ this.connectedOverlay = inject(CdkConnectedOverlay);
386
+ /**
387
+ * The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.
388
+ */
389
+ this.side = input(RdxPopoverSide.Top);
390
+ /**
391
+ * The distance in pixels from the trigger.
392
+ */
393
+ this.sideOffset = input(void 0);
394
+ /**
395
+ * The preferred alignment against the trigger. May change when collisions occur.
396
+ */
397
+ this.align = input(RdxPopoverAlign.Center);
398
+ /**
399
+ * An offset in pixels from the "start" or "end" alignment options.
400
+ */
401
+ this.alignOffset = input(void 0);
402
+ /**
403
+ * Whether to add some alternate positions of the content.
404
+ */
405
+ this.disableAlternatePositions = input(false);
406
+ /** @ingore */
407
+ this.positions = computed(() => {
408
+ const greatestDimensionFromTheArrow = Math.max(this.popoverRoot.popoverArrowDirective()?.width() ?? 0, this.popoverRoot.popoverArrowDirective()?.height() ?? 0);
409
+ const offsets = {
410
+ sideOffset: this.sideOffset() ?? (greatestDimensionFromTheArrow || DEFAULTS.offsets.side),
411
+ alignOffset: this.alignOffset() ?? (greatestDimensionFromTheArrow || DEFAULTS.offsets.align)
412
+ };
413
+ const basePosition = getContentPosition({
414
+ side: this.side(),
415
+ align: this.align(),
416
+ sideOffset: offsets.sideOffset,
417
+ alignOffset: offsets.alignOffset
418
+ });
419
+ const positions = [basePosition];
420
+ if (!this.disableAlternatePositions()) {
421
+ /**
422
+ * Alternate positions for better user experience along the X/Y axis (e.g. vertical/horizontal scrolling)
423
+ */
424
+ const allPossibleConnectedPositions = getAllPossibleConnectedPositions();
425
+ allPossibleConnectedPositions.forEach((value, key) => {
426
+ const sideAndAlignArray = key.split('|');
427
+ if (sideAndAlignArray[0] !== this.side() ||
428
+ sideAndAlignArray[1] !== this.align()) {
429
+ positions.push(getContentPosition({
430
+ side: sideAndAlignArray[0],
431
+ align: sideAndAlignArray[1],
432
+ sideOffset: offsets.sideOffset,
433
+ alignOffset: offsets.alignOffset
434
+ }));
435
+ }
436
+ });
437
+ }
438
+ return positions;
439
+ });
440
+ /**
441
+ * Event handler called when the escape key is down. It can be prevented by calling event.preventDefault.
442
+ */
443
+ this.onEscapeKeyDown = output();
444
+ /**
445
+ * Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling event.preventDefault.
446
+ */
447
+ this.onPointerDownOutside = output();
448
+ /**
449
+ * Event handler called when the overlay is atached
450
+ */
451
+ this.onShow = output();
452
+ /**
453
+ * Event handler called when the overlay is detached
454
+ */
455
+ this.onHide = output();
456
+ this.onPositionChangeEffect();
457
+ this.onControlledExternallyChangeEffect();
458
+ }
459
+ /** @ignore */
460
+ ngOnInit() {
461
+ this.setOrigin();
462
+ this.setScrollStrategy();
463
+ this.onAttach();
464
+ this.onDetach();
465
+ this.connectKeydownEscape();
466
+ this.connectOutsideClick();
467
+ }
468
+ /** @ignore */
469
+ show() {
470
+ const prevOpen = this.connectedOverlay.open;
471
+ this.connectedOverlay.open = true;
472
+ if (!prevOpen) {
473
+ this.connectedOverlay.ngOnChanges({ open: new SimpleChange(prevOpen, true, false) });
474
+ }
475
+ }
476
+ /** @ignore */
477
+ hide() {
478
+ const prevOpen = this.connectedOverlay.open;
479
+ this.connectedOverlay.open = false;
480
+ if (prevOpen) {
481
+ this.connectedOverlay.ngOnChanges({ open: new SimpleChange(prevOpen, false, false) });
482
+ }
483
+ }
484
+ /** @ignore */
485
+ positionChange() {
486
+ return this.connectedOverlay.positionChange.asObservable();
487
+ }
488
+ /** @ignore */
489
+ connectKeydownEscape() {
490
+ this.connectedOverlay.overlayKeydown
491
+ .asObservable()
492
+ .pipe(filter((event) => event.key === 'Escape'), tap((event) => {
493
+ this.onEscapeKeyDown.emit(event);
494
+ if (!event.defaultPrevented) {
495
+ this.popoverRoot.handleClose();
496
+ }
497
+ }), takeUntilDestroyed(this.destroyRef))
498
+ .subscribe();
499
+ }
500
+ /** @ignore */
501
+ connectOutsideClick() {
502
+ this.connectedOverlay.overlayOutsideClick
503
+ .asObservable()
504
+ .pipe(tap((event) => {
505
+ this.onPointerDownOutside.emit(event);
506
+ }), takeUntilDestroyed(this.destroyRef))
507
+ .subscribe();
508
+ }
509
+ /** @ignore */
510
+ onAttach() {
511
+ this.connectedOverlay.attach
512
+ .asObservable()
513
+ .pipe(tap(() => {
514
+ this.onShow.emit();
515
+ }), takeUntilDestroyed(this.destroyRef))
516
+ .subscribe();
517
+ }
518
+ /** @ignore */
519
+ onDetach() {
520
+ this.connectedOverlay.detach
521
+ .asObservable()
522
+ .pipe(tap(() => {
523
+ this.onHide.emit();
524
+ }), takeUntilDestroyed(this.destroyRef))
525
+ .subscribe();
526
+ }
527
+ /** @ignore */
528
+ setScrollStrategy() {
529
+ const prevScrollStrategy = this.connectedOverlay.scrollStrategy;
530
+ this.connectedOverlay.scrollStrategy = this.overlay.scrollStrategies.reposition();
531
+ this.connectedOverlay.ngOnChanges({
532
+ scrollStrategy: new SimpleChange(prevScrollStrategy, this.connectedOverlay.scrollStrategy, false)
533
+ });
534
+ }
535
+ /** @ignore */
536
+ setDisableClose() {
537
+ const prevDisableClose = this.connectedOverlay.disableClose;
538
+ this.connectedOverlay.disableClose = this.popoverRoot.controlledExternally()();
539
+ this.connectedOverlay.ngOnChanges({
540
+ disableClose: new SimpleChange(prevDisableClose, this.connectedOverlay.disableClose, false)
541
+ });
542
+ }
543
+ /** @ignore */
544
+ setOrigin() {
545
+ const prevOrigin = this.connectedOverlay.origin;
546
+ this.connectedOverlay.origin = this.popoverRoot.popoverTriggerDirective().overlayOrigin;
547
+ this.connectedOverlay.ngOnChanges({
548
+ origin: new SimpleChange(prevOrigin, this.connectedOverlay.origin, false)
549
+ });
550
+ }
551
+ /** @ignore */
552
+ onPositionChangeEffect() {
553
+ effect(() => {
554
+ const positions = this.positions();
555
+ this.disableAlternatePositions();
556
+ untracked(() => {
557
+ const prevPositions = this.connectedOverlay.positions;
558
+ this.connectedOverlay.positions = positions;
559
+ this.connectedOverlay.ngOnChanges({
560
+ positions: new SimpleChange(prevPositions, this.connectedOverlay.positions, false)
561
+ });
562
+ this.connectedOverlay.overlayRef?.updatePosition();
563
+ });
564
+ });
565
+ }
566
+ /** @ignore */
567
+ onControlledExternallyChangeEffect() {
568
+ effect(() => {
569
+ this.popoverRoot.controlledExternally()();
570
+ untracked(() => {
571
+ this.setDisableClose();
572
+ });
573
+ });
574
+ }
575
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
576
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.11", type: RdxPopoverContentDirective, isStandalone: true, selector: "[rdxPopoverContent]", 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 }, disableAlternatePositions: { classPropertyName: "disableAlternatePositions", publicName: "disableAlternatePositions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onEscapeKeyDown: "onEscapeKeyDown", onPointerDownOutside: "onPointerDownOutside", onShow: "onShow", onHide: "onHide" }, hostDirectives: [{ directive: i1.CdkConnectedOverlay }], ngImport: i0 }); }
577
+ }
578
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverContentDirective, decorators: [{
579
+ type: Directive,
580
+ args: [{
581
+ selector: '[rdxPopoverContent]',
582
+ standalone: true,
583
+ hostDirectives: [
584
+ {
585
+ directive: CdkConnectedOverlay
586
+ }
587
+ ]
588
+ }]
589
+ }], ctorParameters: () => [] });
590
+
591
+ let nextId = 0;
592
+ class RdxPopoverTriggerDirective {
593
+ constructor() {
594
+ this.id = input(`rdx-popover-root-${nextId++}`);
595
+ this.popoverId = computed(() => `rdx-popover-${this.id()}`);
596
+ /** @ignore */
597
+ this.popoverRoot = injectPopoverRoot();
598
+ /** @ignore */
599
+ this.elementRef = inject((ElementRef));
600
+ /** @ignore */
601
+ this.overlayOrigin = inject(CdkOverlayOrigin);
602
+ }
603
+ /** @ignore */
604
+ onClick() {
605
+ this.popoverRoot.handleToggle();
606
+ }
607
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
608
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.11", type: RdxPopoverTriggerDirective, isStandalone: true, selector: "[rdxPopoverTrigger]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button" }, listeners: { "click": "onClick()" }, properties: { "attr.id": "id()", "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "popoverRoot.isOpen()", "attr.aria-controls": "popoverId()", "attr.data-state": "popoverRoot.state()" } }, hostDirectives: [{ directive: i1.CdkOverlayOrigin }], ngImport: i0 }); }
609
+ }
610
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverTriggerDirective, decorators: [{
611
+ type: Directive,
612
+ args: [{
613
+ selector: '[rdxPopoverTrigger]',
614
+ standalone: true,
615
+ hostDirectives: [CdkOverlayOrigin],
616
+ host: {
617
+ type: 'button',
618
+ '[attr.id]': 'id()',
619
+ '[attr.aria-haspopup]': '"dialog"',
620
+ '[attr.aria-expanded]': 'popoverRoot.isOpen()',
621
+ '[attr.aria-controls]': 'popoverId()',
622
+ '[attr.data-state]': 'popoverRoot.state()',
623
+ '(click)': 'onClick()'
624
+ }
625
+ }]
626
+ }] });
627
+
628
+ class RdxPopoverRootDirective {
629
+ constructor() {
630
+ /**
631
+ * The open state of the popover when it is initially rendered. Use when you do not need to control its open state.
632
+ */
633
+ this.defaultOpen = input(false);
634
+ /**
635
+ * The controlled open state of the popover. Must be used in conjunction with onOpenChange.
636
+ */
637
+ this.open = input();
638
+ /**
639
+ * Event handler called when the open state of the popover changes.
640
+ */
641
+ this.onOpenChange = output();
642
+ /** @ignore */
643
+ this.popoverContentDirective = contentChild.required(RdxPopoverContentDirective);
644
+ /** @ignore */
645
+ this.popoverTriggerDirective = contentChild.required(RdxPopoverTriggerDirective);
646
+ /** @ignore */
647
+ this.popoverArrowDirective = contentChild(RdxPopoverArrowToken);
648
+ /** @ignore */
649
+ this.viewContainerRef = inject(ViewContainerRef);
650
+ /** @ignore */
651
+ this.document = inject(DOCUMENT);
652
+ /** @ignore */
653
+ this.isOpen = signal(this.defaultOpen());
654
+ /** @ignore */
655
+ this.state = computed(() => {
656
+ const currentIsOpen = this.isOpen();
657
+ if (currentIsOpen) {
658
+ return 'open';
659
+ }
660
+ return 'closed';
661
+ });
662
+ /** @ignore */
663
+ this.isControlledExternally = computed(() => signal(this.open() !== void 0));
664
+ this.onOpenChangeEffect();
665
+ this.onIsOpenChangeEffect();
666
+ }
667
+ /** @ignore */
668
+ ngOnInit() {
669
+ if (this.defaultOpen()) {
670
+ this.handleOpen();
671
+ }
672
+ }
673
+ /** @ignore */
674
+ controlledExternally() {
675
+ return this.isControlledExternally().asReadonly();
676
+ }
677
+ /** @ignore */
678
+ handleOpen() {
679
+ if (this.isControlledExternally()()) {
680
+ return;
681
+ }
682
+ this.setOpen(true);
683
+ }
684
+ /** @ignore */
685
+ handleClose() {
686
+ if (this.isControlledExternally()()) {
687
+ return;
688
+ }
689
+ this.setOpen(false);
690
+ }
691
+ /** @ignore */
692
+ handleToggle() {
693
+ if (this.isControlledExternally()()) {
694
+ return;
695
+ }
696
+ this.isOpen() ? this.handleClose() : this.handleOpen();
697
+ }
698
+ /** @ignore */
699
+ setOpen(open = false) {
700
+ if (open) {
701
+ this.document.dispatchEvent(new CustomEvent('popover.open'));
702
+ }
703
+ this.isOpen.set(open);
704
+ this.onOpenChange.emit(open);
705
+ }
706
+ /** @ignore */
707
+ show() {
708
+ this.popoverContentDirective().show();
709
+ }
710
+ /** @ignore */
711
+ hide() {
712
+ this.popoverContentDirective().hide();
713
+ }
714
+ /** @ignore */
715
+ onIsOpenChangeEffect() {
716
+ effect(() => {
717
+ const isOpen = this.isOpen();
718
+ untracked(() => {
719
+ if (isOpen) {
720
+ this.show();
721
+ }
722
+ else {
723
+ this.hide();
724
+ }
725
+ });
726
+ });
727
+ }
728
+ /** @ignore */
729
+ onOpenChangeEffect() {
730
+ effect(() => {
731
+ const currentOpen = this.open();
732
+ untracked(() => {
733
+ this.isControlledExternally().set(currentOpen !== void 0);
734
+ if (this.isControlledExternally()()) {
735
+ this.setOpen(currentOpen);
736
+ }
737
+ });
738
+ });
739
+ }
740
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
741
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.2.11", type: RdxPopoverRootDirective, isStandalone: true, selector: "[rdxPopoverRoot]", inputs: { defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOpenChange: "onOpenChange" }, providers: [
742
+ {
743
+ provide: RdxPopoverRootToken,
744
+ useExisting: forwardRef(() => RdxPopoverRootDirective)
745
+ }
746
+ ], queries: [{ propertyName: "popoverContentDirective", first: true, predicate: RdxPopoverContentDirective, descendants: true, isSignal: true }, { propertyName: "popoverTriggerDirective", first: true, predicate: RdxPopoverTriggerDirective, descendants: true, isSignal: true }, { propertyName: "popoverArrowDirective", first: true, predicate: RdxPopoverArrowToken, descendants: true, isSignal: true }], exportAs: ["rdxPopoverRoot"], ngImport: i0 }); }
747
+ }
748
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverRootDirective, decorators: [{
749
+ type: Directive,
750
+ args: [{
751
+ selector: '[rdxPopoverRoot]',
752
+ standalone: true,
753
+ providers: [
754
+ {
755
+ provide: RdxPopoverRootToken,
756
+ useExisting: forwardRef(() => RdxPopoverRootDirective)
757
+ }
758
+ ],
759
+ exportAs: 'rdxPopoverRoot'
760
+ }]
761
+ }], ctorParameters: () => [] });
762
+
763
+ const _imports = [
764
+ RdxPopoverArrowDirective,
765
+ RdxPopoverCloseDirective,
766
+ RdxPopoverContentDirective,
767
+ RdxPopoverTriggerDirective,
768
+ RdxPopoverRootDirective
769
+ ];
770
+ class RdxPopoverModule {
771
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
772
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverModule, imports: [RdxPopoverArrowDirective,
773
+ RdxPopoverCloseDirective,
774
+ RdxPopoverContentDirective,
775
+ RdxPopoverTriggerDirective,
776
+ RdxPopoverRootDirective], exports: [RdxPopoverArrowDirective,
777
+ RdxPopoverCloseDirective,
778
+ RdxPopoverContentDirective,
779
+ RdxPopoverTriggerDirective,
780
+ RdxPopoverRootDirective] }); }
781
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverModule }); }
782
+ }
783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.11", ngImport: i0, type: RdxPopoverModule, decorators: [{
784
+ type: NgModule,
785
+ args: [{
786
+ imports: [..._imports],
787
+ exports: [..._imports]
788
+ }]
789
+ }] });
790
+
791
+ /**
792
+ * Generated bundle index. Do not edit.
793
+ */
794
+
795
+ export { RdxPopoverAlign, RdxPopoverArrowDirective, RdxPopoverCloseDirective, RdxPopoverContentDirective, RdxPopoverModule, RdxPopoverRootDirective, RdxPopoverSide, RdxPopoverTriggerDirective };
796
+ //# sourceMappingURL=radix-ng-primitives-popover.mjs.map