@radix-ng/primitives 1.0.0-beta.4 → 1.0.0-beta.5

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 (54) hide show
  1. package/fesm2022/radix-ng-primitives-checkbox.mjs +33 -18
  2. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  3. package/fesm2022/radix-ng-primitives-core.mjs +7 -0
  4. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-dialog.mjs +54 -12
  6. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-editable.mjs +12 -7
  8. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  9. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +294 -8
  10. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -1
  11. package/fesm2022/radix-ng-primitives-focus-scope.mjs +9 -0
  12. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-menu.mjs +34 -5
  14. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-number-field.mjs +7 -2
  16. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-popover.mjs +77 -20
  18. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-radio.mjs +19 -14
  20. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-select.mjs +59 -37
  22. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-slider.mjs +259 -28
  24. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-stepper.mjs +11 -7
  26. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-switch.mjs +10 -5
  28. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-tabs.mjs +15 -10
  30. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  31. package/fesm2022/radix-ng-primitives-toggle-group.mjs +9 -4
  32. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  33. package/fesm2022/radix-ng-primitives-toggle.mjs +12 -6
  34. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  35. package/fesm2022/radix-ng-primitives-tooltip.mjs +180 -35
  36. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/types/radix-ng-primitives-checkbox.d.ts +27 -15
  39. package/types/radix-ng-primitives-core.d.ts +2 -0
  40. package/types/radix-ng-primitives-dialog.d.ts +13 -2
  41. package/types/radix-ng-primitives-editable.d.ts +11 -5
  42. package/types/radix-ng-primitives-floating-focus-manager.d.ts +113 -16
  43. package/types/radix-ng-primitives-menu.d.ts +8 -2
  44. package/types/radix-ng-primitives-number-field.d.ts +8 -3
  45. package/types/radix-ng-primitives-popover.d.ts +18 -6
  46. package/types/radix-ng-primitives-radio.d.ts +13 -6
  47. package/types/radix-ng-primitives-select.d.ts +16 -20
  48. package/types/radix-ng-primitives-slider.d.ts +60 -9
  49. package/types/radix-ng-primitives-stepper.d.ts +11 -4
  50. package/types/radix-ng-primitives-switch.d.ts +10 -4
  51. package/types/radix-ng-primitives-tabs.d.ts +12 -6
  52. package/types/radix-ng-primitives-toggle-group.d.ts +11 -5
  53. package/types/radix-ng-primitives-toggle.d.ts +10 -3
  54. package/types/radix-ng-primitives-tooltip.d.ts +38 -14
@@ -6,7 +6,7 @@ import * as i2 from '@radix-ng/primitives/core';
6
6
  import { createContext, createFloatingRootContext, useTransitionStatus, createCancelableChangeEventDetails, provideFloatingTree, provideFloatingRootContext, injectId, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useAnchoredScrollLock, RdxFloatingNodeRegistration, rdxDevError, setupInternalBackdrop, getMaxTransitionDuration } from '@radix-ng/primitives/core';
7
7
  import { injectDirection } from '@radix-ng/primitives/direction-provider';
8
8
  import * as i3 from '@radix-ng/primitives/floating-focus-manager';
9
- import { getInteractionTypeFromEvent, RdxFloatingFocusManager, provideFloatingFocusManagerConfig } from '@radix-ng/primitives/floating-focus-manager';
9
+ import { getInteractionTypeFromEvent, RdxFloatingFocusManager, provideFloatingFocusManagerConfig, createRdxTriggerInteraction, useTriggerFocusGuards } from '@radix-ng/primitives/floating-focus-manager';
10
10
  import { outputFromObservable, outputToObservable } from '@angular/core/rxjs-interop';
11
11
  import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
12
12
  import { RdxFocusScope } from '@radix-ng/primitives/focus-scope';
@@ -38,6 +38,7 @@ function buildContext(instance) {
38
38
  hasTriggerInteractionHandler: instance.hasTriggerInteractionHandler.asReadonly(),
39
39
  trigger: instance.trigger.asReadonly(),
40
40
  popupElement: instance.popupElement.asReadonly(),
41
+ beforeContentFocusGuard: instance.beforeContentFocusGuard.asReadonly(),
41
42
  transitionStatus: instance.transitionStatus,
42
43
  close: (reason, event) => instance.close(reason, event),
43
44
  closeEntireMenu: (reason, event) => instance.closeEntireMenu(reason, event),
@@ -46,6 +47,7 @@ function buildContext(instance) {
46
47
  showWithoutAutoFocus: (reason, event) => instance.show(false, reason, event),
47
48
  registerTrigger: (el) => instance.registerTrigger(el),
48
49
  registerPopup: (el) => instance.registerPopup(el),
50
+ setBeforeContentFocusGuard: (element) => instance.setBeforeContentFocusGuard(element),
49
51
  registerTransitionElement: (el) => instance.registerTransitionElement(el),
50
52
  registerPopupArrowNavigationHandler: (handler) => instance.registerPopupArrowNavigationHandler(handler),
51
53
  registerTriggerInteractionHandler: (handler) => instance.registerTriggerInteractionHandler(handler),
@@ -105,6 +107,7 @@ class RdxMenuRoot {
105
107
  this.onOpenChangeComplete = output();
106
108
  this.trigger = signal(undefined, ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
107
109
  this.popupElement = signal(undefined, ...(ngDevMode ? [{ debugName: "popupElement" }] : /* istanbul ignore next */ []));
110
+ this.beforeContentFocusGuard = signal(null, ...(ngDevMode ? [{ debugName: "beforeContentFocusGuard" }] : /* istanbul ignore next */ []));
108
111
  this.transitionStatus = this.transition.status;
109
112
  /** Whether the popup grabs focus when it opens. Set false for menubar hover-switching. */
110
113
  this.autoFocus = signal('first', ...(ngDevMode ? [{ debugName: "autoFocus" }] : /* istanbul ignore next */ []));
@@ -257,6 +260,9 @@ class RdxMenuRoot {
257
260
  }
258
261
  };
259
262
  }
263
+ setBeforeContentFocusGuard(element) {
264
+ this.beforeContentFocusGuard.set(element);
265
+ }
260
266
  registerTransitionElement(element) {
261
267
  return this.transition.registerElement(element);
262
268
  }
@@ -1072,6 +1078,9 @@ class RdxMenuPopup {
1072
1078
  // disabled separately below; focus/marker policy should not disappear if a menu becomes
1073
1079
  // disabled while open, or if `preventUnmountOnClose()` keeps it mounted after close.
1074
1080
  enabled: () => rootContext.present(),
1081
+ restoreFocus: () => true,
1082
+ previousFocusableElement: () => rootContext.trigger() ?? null,
1083
+ beforeContentFocusGuardRef: () => (element) => rootContext.setBeforeContentFocusGuard(element),
1075
1084
  // Base UI's submenu policy: a submenu mount does not steal focus from its trigger.
1076
1085
  // Root menus still choose first / last item vs popup container from the menu's own
1077
1086
  // open policy (`autoFocus`), but the decision now lives in the focus manager instead
@@ -1126,6 +1135,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1126
1135
  // disabled separately below; focus/marker policy should not disappear if a menu becomes
1127
1136
  // disabled while open, or if `preventUnmountOnClose()` keeps it mounted after close.
1128
1137
  enabled: () => rootContext.present(),
1138
+ restoreFocus: () => true,
1139
+ previousFocusableElement: () => rootContext.trigger() ?? null,
1140
+ beforeContentFocusGuardRef: () => (element) => rootContext.setBeforeContentFocusGuard(element),
1129
1141
  // Base UI's submenu policy: a submenu mount does not steal focus from its trigger.
1130
1142
  // Root menus still choose first / last item vs popup container from the menu's own
1131
1143
  // open policy (`autoFocus`), but the decision now lives in the focus manager instead
@@ -2215,6 +2227,12 @@ class RdxMenuTrigger {
2215
2227
  this.closeDelay = input(undefined, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: numberOrUndefined });
2216
2228
  this.nativeButtonState = computed(() => this.nativeButton() || this.elementRef.nativeElement.tagName === 'BUTTON', ...(ngDevMode ? [{ debugName: "nativeButtonState" }] : /* istanbul ignore next */ []));
2217
2229
  this.isDisabled = computed(() => this.rootContext.disabled() || this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2230
+ this.triggerInteraction = createRdxTriggerInteraction({
2231
+ trigger: () => this.elementRef.nativeElement,
2232
+ activeTrigger: () => this.rootContext.trigger(),
2233
+ open: () => this.rootContext.isOpen(),
2234
+ disabled: () => this.isDisabled()
2235
+ });
2218
2236
  effect((onCleanup) => {
2219
2237
  const el = this.elementRef.nativeElement;
2220
2238
  const unregister = this.rootContext.registerTrigger(el);
@@ -2259,6 +2277,13 @@ class RdxMenuTrigger {
2259
2277
  // (A press/focus on the trigger no longer needs a dismissable-layer branch to avoid
2260
2278
  // self-dismissal: the trigger is registered in the menu's floating context, so the dismissal
2261
2279
  // capability already treats it as "inside" — ADR 0015 trigger registry replaces the branch.)
2280
+ useTriggerFocusGuards({
2281
+ trigger: () => this.elementRef.nativeElement,
2282
+ close: (event) => this.rootContext.close('focus-out', event),
2283
+ beforeContentFocusGuard: () => this.rootContext.beforeContentFocusGuard(),
2284
+ enabled: () => this.triggerInteraction.isActive(),
2285
+ popupElement: () => this.rootContext.popupElement()
2286
+ });
2262
2287
  this.destroyRef.onDestroy(() => {
2263
2288
  this.clearOpenTimer();
2264
2289
  this.clearCloseTimer();
@@ -2286,6 +2311,9 @@ class RdxMenuTrigger {
2286
2311
  this.armMouseUpGuard(event.currentTarget);
2287
2312
  }
2288
2313
  }
2314
+ handlePointerDown(event) {
2315
+ this.triggerInteraction.recordPointerDown(event);
2316
+ }
2289
2317
  handleClick(event) {
2290
2318
  if (this.isDisabled()) {
2291
2319
  return;
@@ -2464,7 +2492,7 @@ class RdxMenuTrigger {
2464
2492
  }
2465
2493
  }
2466
2494
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2467
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuTrigger, isStandalone: true, selector: "[rdxMenuTrigger]", inputs: { nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", 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 } }, host: { listeners: { "mousedown": "handleMouseDown($event)", "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave($event)", "keydown.arrowdown": "handleArrowDown($event)", "keydown.arrowup": "handleArrowUp($event)", "keydown.arrowleft": "handleArrowLeft($event)", "keydown.arrowright": "handleArrowRight($event)", "keydown.home": "handleHome($event)", "keydown.end": "handleEnd($event)", "keydown.escape": "handleEscape($event)", "keydown.enter": "handleKeyboardToggle($event)", "keydown.space": "handleKeyboardToggle($event)" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.role": "rootContext.hasTriggerInteractionHandler() ? \"menuitem\" : nativeButtonState() ? undefined : \"button\"", "attr.tabindex": "rootContext.hasTriggerInteractionHandler() ? \"-1\" : undefined", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "rootContext.isOpen()", "attr.aria-disabled": "isDisabled() ? true : undefined", "attr.disabled": "nativeButtonState() && isDisabled() ? \"\" : undefined", "attr.data-state": "rootContext.isOpen() ? \"open\" : \"closed\"", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-popup-open": "rootContext.isOpen() ? \"\" : undefined", "style.pointer-events": "rootContext.isOpen() && rootContext.modal() ? \"auto\" : undefined" } }, exportAs: ["rdxMenuTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
2495
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuTrigger, isStandalone: true, selector: "[rdxMenuTrigger]", inputs: { nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", 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 } }, host: { listeners: { "pointerdown": "handlePointerDown($event)", "mousedown": "handleMouseDown($event)", "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave($event)", "keydown.arrowdown": "handleArrowDown($event)", "keydown.arrowup": "handleArrowUp($event)", "keydown.arrowleft": "handleArrowLeft($event)", "keydown.arrowright": "handleArrowRight($event)", "keydown.home": "handleHome($event)", "keydown.end": "handleEnd($event)", "keydown.escape": "handleEscape($event)", "keydown.enter": "handleKeyboardToggle($event)", "keydown.space": "handleKeyboardToggle($event)" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.role": "rootContext.hasTriggerInteractionHandler() ? \"menuitem\" : nativeButtonState() ? undefined : \"button\"", "attr.tabindex": "rootContext.hasTriggerInteractionHandler() ? \"-1\" : undefined", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "triggerInteraction.ariaExpanded()", "attr.aria-disabled": "isDisabled() ? true : undefined", "attr.disabled": "nativeButtonState() && isDisabled() ? \"\" : undefined", "attr.data-state": "triggerInteraction.dataState()", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-popup-open": "triggerInteraction.dataPopupOpen()", "style.pointer-events": "rootContext.isOpen() && rootContext.modal() ? \"auto\" : undefined" } }, exportAs: ["rdxMenuTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
2468
2496
  }
2469
2497
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuTrigger, decorators: [{
2470
2498
  type: Directive,
@@ -2477,13 +2505,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2477
2505
  '[attr.role]': 'rootContext.hasTriggerInteractionHandler() ? "menuitem" : nativeButtonState() ? undefined : "button"',
2478
2506
  '[attr.tabindex]': 'rootContext.hasTriggerInteractionHandler() ? "-1" : undefined',
2479
2507
  '[attr.aria-haspopup]': '"menu"',
2480
- '[attr.aria-expanded]': 'rootContext.isOpen()',
2508
+ '[attr.aria-expanded]': 'triggerInteraction.ariaExpanded()',
2481
2509
  '[attr.aria-disabled]': 'isDisabled() ? true : undefined',
2482
2510
  '[attr.disabled]': 'nativeButtonState() && isDisabled() ? "" : undefined',
2483
- '[attr.data-state]': 'rootContext.isOpen() ? "open" : "closed"',
2511
+ '[attr.data-state]': 'triggerInteraction.dataState()',
2484
2512
  '[attr.data-disabled]': 'isDisabled() ? "" : undefined',
2485
- '[attr.data-popup-open]': 'rootContext.isOpen() ? "" : undefined',
2513
+ '[attr.data-popup-open]': 'triggerInteraction.dataPopupOpen()',
2486
2514
  '[style.pointer-events]': 'rootContext.isOpen() && rootContext.modal() ? "auto" : undefined',
2515
+ '(pointerdown)': 'handlePointerDown($event)',
2487
2516
  '(mousedown)': 'handleMouseDown($event)',
2488
2517
  '(click)': 'handleClick($event)',
2489
2518
  '(pointerenter)': 'handlePointerEnter($event)',