@flusys/ng-ui 8.1.2 → 8.1.4

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, Service, makeEnvironmentProviders, provideAppInitializer, inject, PLATFORM_ID, input, booleanAttribute, computed, Component, output, contentChild, viewChild, effect, ElementRef, Directive, numberAttribute, afterNextRender, TemplateRef, contentChildren, DestroyRef, untracked, forwardRef, model, viewChildren, Renderer2, InjectionToken, Injector, SecurityContext } from '@angular/core';
3
- import { isPlatformBrowser, NgTemplateOutlet, DOCUMENT, NgComponentOutlet } from '@angular/common';
2
+ import { signal, Service, makeEnvironmentProviders, provideAppInitializer, inject, PLATFORM_ID, input, booleanAttribute, computed, Component, output, contentChild, viewChild, effect, DestroyRef, ElementRef, Directive, numberAttribute, afterNextRender, TemplateRef, contentChildren, untracked, forwardRef, model, viewChildren, Renderer2, InjectionToken, Injector, SecurityContext } from '@angular/core';
3
+ import { isPlatformBrowser, DOCUMENT, NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
4
4
  import * as lucideNamespace from '@lucide/angular';
5
5
  import { isLucideIconComponent, LucideDynamicIcon, provideLucideIcons } from '@lucide/angular';
6
6
  import * as i1 from '@angular/forms';
@@ -730,6 +730,34 @@ function provideNgUI(options) {
730
730
  ]);
731
731
  }
732
732
 
733
+ const BASE_Z_INDEX = 1000;
734
+ const Z_INDEX_STEP = 2;
735
+ class OverlayStackService {
736
+ _doc = inject(DOCUMENT);
737
+ nextZIndex = BASE_Z_INDEX;
738
+ lockCount = 0;
739
+ open() {
740
+ const zIndex = this.nextZIndex;
741
+ this.nextZIndex += Z_INDEX_STEP;
742
+ return zIndex;
743
+ }
744
+ lockScroll() {
745
+ if (this.lockCount === 0)
746
+ this._doc.body.style.overflow = 'hidden';
747
+ this.lockCount++;
748
+ }
749
+ unlockScroll() {
750
+ this.lockCount = Math.max(0, this.lockCount - 1);
751
+ if (this.lockCount === 0)
752
+ this._doc.body.style.overflow = '';
753
+ }
754
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: OverlayStackService, deps: [], target: i0.ɵɵFactoryTarget.Service });
755
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.5", ngImport: i0, type: OverlayStackService });
756
+ }
757
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: OverlayStackService, decorators: [{
758
+ type: Service
759
+ }] });
760
+
733
761
  class BadgeComponent {
734
762
  value = input('', /* @ts-ignore */
735
763
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -929,12 +957,18 @@ const SEVERITY_CLASSES = {
929
957
  class UiIconComponent {
930
958
  name = input('', /* @ts-ignore */
931
959
  ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
932
- size = input(16, /* @ts-ignore */
960
+ // Unset by default so the icon renders at `1em` — it then scales with
961
+ // whatever font-size context (e.g. a Tailwind text-* class) surrounds it,
962
+ // instead of always rendering at a fixed pixel size regardless of that
963
+ // context. Pass an explicit size to opt out and pin an exact pixel value.
964
+ size = input(undefined, /* @ts-ignore */
933
965
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
934
966
  spin = input(false, { ...(ngDevMode ? { debugName: "spin" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
935
967
  fill = input(false, { ...(ngDevMode ? { debugName: "fill" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
936
968
  severity = input(null, /* @ts-ignore */
937
969
  ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
970
+ resolvedSize = computed(() => this.size() ?? '1em', /* @ts-ignore */
971
+ ...(ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []));
938
972
  lucideName = computed(() => {
939
973
  const n = this.name();
940
974
  return PI_TO_LUCIDE[n] ?? n;
@@ -953,32 +987,31 @@ class UiIconComponent {
953
987
  }, /* @ts-ignore */
954
988
  ...(ngDevMode ? [{ debugName: "iconClass" }] : /* istanbul ignore next */ []));
955
989
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: UiIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
956
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: UiIconComponent, isStandalone: true, selector: "ui-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, spin: { classPropertyName: "spin", publicName: "spin", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ui-icon-size": "size() + 'px'" }, classAttribute: "inline-flex items-center leading-none" }, providers: [provideLucideIcons(...allLucideIcons)], ngImport: i0, template: `
990
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: UiIconComponent, isStandalone: true, selector: "ui-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, spin: { classPropertyName: "spin", publicName: "spin", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-flex items-center leading-none" }, providers: [provideLucideIcons(...allLucideIcons)], ngImport: i0, template: `
957
991
  @if (lucideName()) {
958
992
  <svg
959
993
  ngSkipHydration
960
994
  [lucideIcon]="lucideName()"
961
- [size]="size()"
995
+ [size]="resolvedSize()"
962
996
  [class]="iconClass()"
963
997
  ></svg>
964
998
  }
965
- `, isInline: true, styles: [":host ::ng-deep svg[lucideIcon]{width:var(--ui-icon-size);height:var(--ui-icon-size);display:block}\n"], dependencies: [{ kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
999
+ `, isInline: true, styles: [":host ::ng-deep svg[lucideIcon]{display:block}\n"], dependencies: [{ kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
966
1000
  }
967
1001
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: UiIconComponent, decorators: [{
968
1002
  type: Component,
969
1003
  args: [{ selector: 'ui-icon', imports: [LucideDynamicIcon], providers: [provideLucideIcons(...allLucideIcons)], host: {
970
1004
  class: 'inline-flex items-center leading-none',
971
- '[style.--ui-icon-size]': "size() + 'px'",
972
1005
  }, template: `
973
1006
  @if (lucideName()) {
974
1007
  <svg
975
1008
  ngSkipHydration
976
1009
  [lucideIcon]="lucideName()"
977
- [size]="size()"
1010
+ [size]="resolvedSize()"
978
1011
  [class]="iconClass()"
979
1012
  ></svg>
980
1013
  }
981
- `, styles: [":host ::ng-deep svg[lucideIcon]{width:var(--ui-icon-size);height:var(--ui-icon-size);display:block}\n"] }]
1014
+ `, styles: [":host ::ng-deep svg[lucideIcon]{display:block}\n"] }]
982
1015
  }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], spin: [{ type: i0.Input, args: [{ isSignal: true, alias: "spin", required: false }] }], fill: [{ type: i0.Input, args: [{ isSignal: true, alias: "fill", required: false }] }], severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }] } });
983
1016
 
984
1017
  class ButtonComponent {
@@ -1312,10 +1345,10 @@ function plainVariant(kind) {
1312
1345
  const FOCUSABLE_SELECTOR$3 = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
1313
1346
  class ConfirmDialog {
1314
1347
  static idCounter = 0;
1315
- _doc = inject(DOCUMENT);
1316
1348
  headerId = `f-confirmdialog-header-${++ConfirmDialog.idCounter}`;
1317
1349
  descId = `f-confirmdialog-desc-${ConfirmDialog.idCounter}`;
1318
1350
  confirmationService = inject(ConfirmationService);
1351
+ _overlayStack = inject(OverlayStackService);
1319
1352
  key = input(undefined, /* @ts-ignore */
1320
1353
  ...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1321
1354
  icon = input('', /* @ts-ignore */
@@ -1350,24 +1383,40 @@ class ConfirmDialog {
1350
1383
  panelRef = viewChild('panel', /* @ts-ignore */
1351
1384
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
1352
1385
  _previouslyFocused = null;
1386
+ _scrollLocked = false;
1387
+ _zIndex = signal(null, /* @ts-ignore */
1388
+ ...(ngDevMode ? [{ debugName: "_zIndex" }] : /* istanbul ignore next */ []));
1389
+ zIndex = this._zIndex.asReadonly();
1353
1390
  constructor() {
1354
1391
  effect(() => {
1355
1392
  const visible = !!this.activeConfirmation();
1356
1393
  if (visible) {
1394
+ this._zIndex.set(this._overlayStack.open());
1357
1395
  this._previouslyFocused =
1358
1396
  typeof document !== 'undefined'
1359
1397
  ? document.activeElement
1360
1398
  : null;
1361
- if (this.blockScroll())
1362
- this._doc.body.style.overflow = 'hidden';
1399
+ if (this.blockScroll()) {
1400
+ this._overlayStack.lockScroll();
1401
+ this._scrollLocked = true;
1402
+ }
1363
1403
  }
1364
1404
  else {
1365
- if (this.blockScroll())
1366
- this._doc.body.style.overflow = '';
1405
+ this._zIndex.set(null);
1406
+ if (this._scrollLocked) {
1407
+ this._overlayStack.unlockScroll();
1408
+ this._scrollLocked = false;
1409
+ }
1367
1410
  this._previouslyFocused?.focus();
1368
1411
  this._previouslyFocused = null;
1369
1412
  }
1370
1413
  });
1414
+ inject(DestroyRef).onDestroy(() => {
1415
+ if (this._scrollLocked) {
1416
+ this._overlayStack.unlockScroll();
1417
+ this._scrollLocked = false;
1418
+ }
1419
+ });
1371
1420
  }
1372
1421
  resolvedIcon(c) {
1373
1422
  return c.icon || this.icon();
@@ -1426,7 +1475,10 @@ class ConfirmDialog {
1426
1475
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: ConfirmDialog, isStandalone: true, selector: "f-confirmdialog", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, acceptLabel: { classPropertyName: "acceptLabel", publicName: "acceptLabel", isSignal: true, isRequired: false, transformFunction: null }, rejectLabel: { classPropertyName: "rejectLabel", publicName: "rejectLabel", isSignal: true, isRequired: false, transformFunction: null }, acceptIcon: { classPropertyName: "acceptIcon", publicName: "acceptIcon", isSignal: true, isRequired: false, transformFunction: null }, rejectIcon: { classPropertyName: "rejectIcon", publicName: "rejectIcon", isSignal: true, isRequired: false, transformFunction: null }, acceptButtonStyleClass: { classPropertyName: "acceptButtonStyleClass", publicName: "acceptButtonStyleClass", isSignal: true, isRequired: false, transformFunction: null }, rejectButtonStyleClass: { classPropertyName: "rejectButtonStyleClass", publicName: "rejectButtonStyleClass", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, blockScroll: { classPropertyName: "blockScroll", publicName: "blockScroll", isSignal: true, isRequired: false, transformFunction: null }, defaultFocus: { classPropertyName: "defaultFocus", publicName: "defaultFocus", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "block" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
1427
1476
  @if (activeConfirmation(); as c) {
1428
1477
  @if (c.acceptVisible !== false || c.rejectVisible !== false) {
1429
- <div class="fixed inset-0 z-50 flex items-center justify-center p-4">
1478
+ <div
1479
+ class="fixed inset-0 flex items-center justify-center p-4"
1480
+ [style.z-index]="zIndex()"
1481
+ >
1430
1482
  <div
1431
1483
  class="confirm-backdrop absolute inset-0 bg-black/50 backdrop-blur-[2px]"
1432
1484
  (click)="c.closable !== false && reject(c.reject)"
@@ -1517,7 +1569,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
1517
1569
  args: [{ selector: 'f-confirmdialog', imports: [UiIconComponent, ButtonComponent], host: { class: 'block', '(document:keydown.escape)': 'onEscape()' }, template: `
1518
1570
  @if (activeConfirmation(); as c) {
1519
1571
  @if (c.acceptVisible !== false || c.rejectVisible !== false) {
1520
- <div class="fixed inset-0 z-50 flex items-center justify-center p-4">
1572
+ <div
1573
+ class="fixed inset-0 flex items-center justify-center p-4"
1574
+ [style.z-index]="zIndex()"
1575
+ >
1521
1576
  <div
1522
1577
  class="confirm-backdrop absolute inset-0 bg-black/50 backdrop-blur-[2px]"
1523
1578
  (click)="c.closable !== false && reject(c.reject)"
@@ -2650,9 +2705,13 @@ class ImageComponent {
2650
2705
  ...(ngDevMode ? [{ debugName: "fTemplates" }] : /* istanbul ignore next */ []));
2651
2706
  indicatorTpl = computed(() => this.fTemplates().find(t => t.fTemplate() === 'indicator')?.templateRef ?? null, /* @ts-ignore */
2652
2707
  ...(ngDevMode ? [{ debugName: "indicatorTpl" }] : /* istanbul ignore next */ []));
2708
+ _overlayStack = inject(OverlayStackService);
2653
2709
  _previewVisible = signal(false, /* @ts-ignore */
2654
2710
  ...(ngDevMode ? [{ debugName: "_previewVisible" }] : /* istanbul ignore next */ []));
2655
2711
  previewVisible = this._previewVisible.asReadonly();
2712
+ _zIndex = signal(null, /* @ts-ignore */
2713
+ ...(ngDevMode ? [{ debugName: "_zIndex" }] : /* istanbul ignore next */ []));
2714
+ zIndex = this._zIndex.asReadonly();
2656
2715
  _loaded = signal(false, /* @ts-ignore */
2657
2716
  ...(ngDevMode ? [{ debugName: "_loaded" }] : /* istanbul ignore next */ []));
2658
2717
  loaded = this._loaded.asReadonly();
@@ -2675,12 +2734,14 @@ class ImageComponent {
2675
2734
  if (this.hasError())
2676
2735
  return;
2677
2736
  this._previewVisible.set(true);
2737
+ this._zIndex.set(this._overlayStack.open());
2678
2738
  this.onShow.emit();
2679
2739
  }
2680
2740
  close() {
2681
2741
  this._previewVisible.set(false);
2682
2742
  this._rotate.set(0);
2683
2743
  this._scale.set(1);
2744
+ this._zIndex.set(null);
2684
2745
  this.onHide.emit();
2685
2746
  }
2686
2747
  onEscape() {
@@ -2751,7 +2812,8 @@ class ImageComponent {
2751
2812
 
2752
2813
  @if (previewVisible()) {
2753
2814
  <div
2754
- class="image-preview-overlay fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-6"
2815
+ class="image-preview-overlay fixed inset-0 flex items-center justify-center bg-black/80 p-6"
2816
+ [style.z-index]="zIndex()"
2755
2817
  (click)="close()"
2756
2818
  >
2757
2819
  <div class="absolute top-4 left-4 flex items-center gap-1" (click)="$event.stopPropagation()">
@@ -2837,7 +2899,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
2837
2899
 
2838
2900
  @if (previewVisible()) {
2839
2901
  <div
2840
- class="image-preview-overlay fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-6"
2902
+ class="image-preview-overlay fixed inset-0 flex items-center justify-center bg-black/80 p-6"
2903
+ [style.z-index]="zIndex()"
2841
2904
  (click)="close()"
2842
2905
  >
2843
2906
  <div class="absolute top-4 left-4 flex items-center gap-1" (click)="$event.stopPropagation()">
@@ -3199,17 +3262,170 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
3199
3262
  }]
3200
3263
  }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], scrollWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollWidth", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], onScrollIndexChange: [{ type: i0.Output, args: ["onScrollIndexChange"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], loaderTpl: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }] } });
3201
3264
 
3202
- // `capture: true` is required because scroll events on inner scroll containers don't bubble to window.
3203
- function repositionOnScroll(isActive, reposition) {
3204
- effect(onCleanup => {
3205
- if (!isActive() || typeof window === 'undefined')
3265
+ const DEFAULT_GAP = 4;
3266
+ const DEFAULT_MARGIN = 8;
3267
+ const DEFAULT_MIN_HEIGHT = 120;
3268
+ /**
3269
+ * Places a panel against an anchor inside the viewport: flips above the anchor
3270
+ * when there is more room there, clamps horizontally, and hands back a
3271
+ * `maxHeight` when the panel would otherwise be cut off by a viewport edge, so
3272
+ * it scrolls internally instead.
3273
+ */
3274
+ function computeOverlayPlacement(anchor, panel, viewport, options = {}) {
3275
+ const gap = options.gap ?? DEFAULT_GAP;
3276
+ const margin = options.margin ?? DEFAULT_MARGIN;
3277
+ const align = options.align ?? 'start';
3278
+ const minHeight = Math.min(options.minHeight ?? DEFAULT_MIN_HEIGHT, Math.max(0, viewport.height - margin * 2));
3279
+ const spaceBelow = viewport.height - anchor.bottom - gap - margin;
3280
+ const spaceAbove = anchor.top - gap - margin;
3281
+ const direction = panel.height <= spaceBelow || spaceBelow >= spaceAbove ? 'down' : 'up';
3282
+ const room = direction === 'down' ? spaceBelow : spaceAbove;
3283
+ const maxHeight = Math.max(minHeight, Math.round(room));
3284
+ const height = Math.min(panel.height, maxHeight);
3285
+ // Only take over the height when the panel genuinely doesn't fit; otherwise
3286
+ // leave it to the panel's own CSS (a design cap like `max-h-56`).
3287
+ const clamped = options.clampHeight !== false && panel.height > maxHeight ? maxHeight : null;
3288
+ const top = direction === 'down'
3289
+ ? Math.min(anchor.bottom + gap, Math.max(margin, viewport.height - margin - height))
3290
+ : Math.max(margin, anchor.top - gap - height);
3291
+ const width = options.matchAnchorWidth ? anchor.width : panel.width;
3292
+ const rawLeft = align === 'end' ? anchor.right - width : anchor.left;
3293
+ const left = width + margin * 2 > viewport.width
3294
+ ? margin
3295
+ : Math.max(margin, Math.min(rawLeft, viewport.width - width - margin));
3296
+ return {
3297
+ top: Math.round(top),
3298
+ left: Math.round(left),
3299
+ width: options.matchAnchorWidth ? Math.round(anchor.width) : null,
3300
+ maxHeight: clamped,
3301
+ direction,
3302
+ };
3303
+ }
3304
+ function overlayPlacementStyle(placement) {
3305
+ if (!placement)
3306
+ return {};
3307
+ const style = {
3308
+ top: `${placement.top}px`,
3309
+ left: `${placement.left}px`,
3310
+ };
3311
+ if (placement.maxHeight !== null)
3312
+ style['max-height'] = `${placement.maxHeight}px`;
3313
+ if (placement.width !== null)
3314
+ style['width'] = `${placement.width}px`;
3315
+ return style;
3316
+ }
3317
+ function overlayPlacementEquals(a, b) {
3318
+ if (a === b)
3319
+ return true;
3320
+ if (!a || !b)
3321
+ return false;
3322
+ return (a.top === b.top &&
3323
+ a.left === b.left &&
3324
+ a.width === b.width &&
3325
+ a.maxHeight === b.maxHeight &&
3326
+ a.direction === b.direction);
3327
+ }
3328
+ /**
3329
+ * How tall the panel wants to be, with our own `max-height` lifted for the
3330
+ * measurement — otherwise a panel we clamped once would report the clamped
3331
+ * height forever and could never claim more room after a scroll.
3332
+ */
3333
+ function measureNaturalSize(panel) {
3334
+ const previous = panel.style.maxHeight;
3335
+ // Cleared, not `none`: the panel's own CSS cap must still apply, so a panel
3336
+ // that fits inside its design cap never asks for more room than that.
3337
+ panel.style.maxHeight = '';
3338
+ // offsetWidth/Height, not getBoundingClientRect: several panels animate in
3339
+ // with a `scale()` transform, which would otherwise make us measure — and
3340
+ // place — a panel mid-animation at the wrong size.
3341
+ const size = { width: panel.offsetWidth, height: panel.offsetHeight };
3342
+ panel.style.maxHeight = previous;
3343
+ return size;
3344
+ }
3345
+ /**
3346
+ * Keeps a fixed-position panel glued to its anchor while it is open.
3347
+ *
3348
+ * Repositions on window scroll (capture: inner scroll containers don't bubble),
3349
+ * on resize, and — the case every hand-rolled copy of this math used to miss —
3350
+ * when the panel's own content resizes, e.g. a lazily loaded option list
3351
+ * arriving after the panel opened and pushing it past the bottom of the screen.
3352
+ * Work is coalesced into an animation frame so a scroll burst costs one layout.
3353
+ */
3354
+ function createOverlayPositioner(anchor, panel, options, emit) {
3355
+ let frame = null;
3356
+ let measuring = false;
3357
+ const update = () => {
3358
+ frame = null;
3359
+ if (typeof anchor.getBoundingClientRect !== 'function')
3360
+ return;
3361
+ measuring = true;
3362
+ const size = measureNaturalSize(panel);
3363
+ measuring = false;
3364
+ emit(computeOverlayPlacement(anchor.getBoundingClientRect(), size, { width: window.innerWidth, height: window.innerHeight }, options));
3365
+ };
3366
+ const schedule = () => {
3367
+ if (frame !== null)
3206
3368
  return;
3207
- window.addEventListener('scroll', reposition, true);
3208
- window.addEventListener('resize', reposition);
3209
- onCleanup(() => {
3210
- window.removeEventListener('scroll', reposition, true);
3211
- window.removeEventListener('resize', reposition);
3369
+ frame = requestAnimationFrame(update);
3370
+ };
3371
+ update();
3372
+ window.addEventListener('scroll', schedule, true);
3373
+ window.addEventListener('resize', schedule);
3374
+ const observer = typeof ResizeObserver === 'undefined'
3375
+ ? null
3376
+ : new ResizeObserver(() => {
3377
+ if (!measuring)
3378
+ schedule();
3212
3379
  });
3380
+ observer?.observe(panel);
3381
+ return () => {
3382
+ if (frame !== null)
3383
+ cancelAnimationFrame(frame);
3384
+ window.removeEventListener('scroll', schedule, true);
3385
+ window.removeEventListener('resize', schedule);
3386
+ observer?.disconnect();
3387
+ };
3388
+ }
3389
+ /**
3390
+ * Signal-based placement for components that render their panel from a
3391
+ * template. Bind the result through `overlayPlacementStyle()`. Must be called
3392
+ * in an injection context.
3393
+ */
3394
+ function overlayPosition(config) {
3395
+ const placement = signal(null, { ...(ngDevMode ? { debugName: "placement" } : /* istanbul ignore next */ {}), equal: overlayPlacementEquals });
3396
+ effect((onCleanup) => {
3397
+ const anchorEl = config.anchor();
3398
+ const panelEl = config.panel();
3399
+ const options = config.options?.() ?? {};
3400
+ if (!config.active() ||
3401
+ !anchorEl ||
3402
+ !panelEl ||
3403
+ typeof window === 'undefined') {
3404
+ placement.set(null);
3405
+ return;
3406
+ }
3407
+ onCleanup(createOverlayPositioner(anchorEl, panelEl, options, (next) => placement.set(next)));
3408
+ });
3409
+ return placement.asReadonly();
3410
+ }
3411
+ /**
3412
+ * Imperative twin of `overlayPosition()` for overlays that portal a plain DOM
3413
+ * node instead of rendering a template. Returns a dispose function.
3414
+ */
3415
+ function attachOverlayPosition(anchor, panel, options = {}) {
3416
+ if (typeof window === 'undefined')
3417
+ return () => undefined;
3418
+ let current = null;
3419
+ return createOverlayPositioner(anchor, panel, options, (placement) => {
3420
+ if (overlayPlacementEquals(current, placement))
3421
+ return;
3422
+ current = placement;
3423
+ panel.style.top = `${placement.top}px`;
3424
+ panel.style.left = `${placement.left}px`;
3425
+ panel.style.maxHeight =
3426
+ placement.maxHeight === null ? '' : `${placement.maxHeight}px`;
3427
+ if (placement.width !== null)
3428
+ panel.style.width = `${placement.width}px`;
3213
3429
  });
3214
3430
  }
3215
3431
 
@@ -3235,7 +3451,6 @@ class SelectComponent {
3235
3451
  queueMicrotask(() => this._filterInputRef()?.nativeElement.focus());
3236
3452
  }
3237
3453
  });
3238
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => { this.position(); this.adjustForViewport(); });
3239
3454
  }
3240
3455
  onDocumentClick(e) {
3241
3456
  if (this.open() && !this._el.nativeElement.contains(e.target)) {
@@ -3284,7 +3499,7 @@ class SelectComponent {
3284
3499
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
3285
3500
  style = input(null, /* @ts-ignore */
3286
3501
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
3287
- appendTo = input('self', /* @ts-ignore */
3502
+ appendTo = input('body', /* @ts-ignore */
3288
3503
  ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
3289
3504
  editable = input(false, { ...(ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3290
3505
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -3299,6 +3514,14 @@ class SelectComponent {
3299
3514
  virtualScrollItemSize = input(36, /* @ts-ignore */
3300
3515
  ...(ngDevMode ? [{ debugName: "virtualScrollItemSize" }] : /* istanbul ignore next */ []));
3301
3516
  lazy = input(false, { ...(ngDevMode ? { debugName: "lazy" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3517
+ /**
3518
+ * Full option object for the current `value()`, supplied by the consumer.
3519
+ * Pinned into the option pool (deduped by `optionValue`) whenever a lazy-loaded
3520
+ * or filtered `options()` page doesn't happen to contain it, so the trigger
3521
+ * label, checkmark and list row always resolve correctly on edit forms.
3522
+ */
3523
+ selectedObject = input(null, /* @ts-ignore */
3524
+ ...(ngDevMode ? [{ debugName: "selectedObject" }] : /* istanbul ignore next */ []));
3302
3525
  hostClass = computed(() => `block w-full ${this.styleClass()}`, /* @ts-ignore */
3303
3526
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
3304
3527
  onFilter = output();
@@ -3329,49 +3552,19 @@ class SelectComponent {
3329
3552
  ...(ngDevMode ? [{ debugName: "_filterInputRef" }] : /* istanbul ignore next */ []));
3330
3553
  _panelRef = viewChild('panel', /* @ts-ignore */
3331
3554
  ...(ngDevMode ? [{ debugName: "_panelRef" }] : /* istanbul ignore next */ []));
3332
- _panelTop = signal(0, /* @ts-ignore */
3333
- ...(ngDevMode ? [{ debugName: "_panelTop" }] : /* istanbul ignore next */ []));
3334
- _panelLeft = signal(0, /* @ts-ignore */
3335
- ...(ngDevMode ? [{ debugName: "_panelLeft" }] : /* istanbul ignore next */ []));
3336
- _panelWidth = signal(0, /* @ts-ignore */
3337
- ...(ngDevMode ? [{ debugName: "_panelWidth" }] : /* istanbul ignore next */ []));
3555
+ _placement = overlayPosition({
3556
+ active: () => this.open() && this.appendTo() === 'body',
3557
+ anchor: () => this._triggerRef()?.nativeElement,
3558
+ panel: () => this._panelRef()?.nativeElement,
3559
+ options: () => ({ matchAnchorWidth: true }),
3560
+ });
3338
3561
  panelClass = computed(() => {
3339
3562
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute w-full mt-1';
3340
- return `${position} z-50 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
3563
+ return `${position} z-50 flex flex-col bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
3341
3564
  }, /* @ts-ignore */
3342
3565
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
3343
- panelStyle = computed(() => {
3344
- if (this.appendTo() !== 'body')
3345
- return {};
3346
- return {
3347
- top: `${this._panelTop()}px`,
3348
- left: `${this._panelLeft()}px`,
3349
- width: `${this._panelWidth()}px`,
3350
- };
3351
- }, /* @ts-ignore */
3566
+ panelStyle = computed(() => this.appendTo() === 'body' ? overlayPlacementStyle(this._placement()) : {}, /* @ts-ignore */
3352
3567
  ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
3353
- position() {
3354
- const anchorEl = this._triggerRef()?.nativeElement;
3355
- if (!anchorEl || typeof window === 'undefined')
3356
- return;
3357
- const rect = anchorEl.getBoundingClientRect();
3358
- this._panelTop.set(rect.bottom + 4);
3359
- this._panelLeft.set(Math.max(8, rect.left));
3360
- this._panelWidth.set(rect.width);
3361
- }
3362
- adjustForViewport() {
3363
- const panelEl = this._panelRef()?.nativeElement;
3364
- const anchorEl = this._triggerRef()?.nativeElement;
3365
- if (!panelEl || !anchorEl || typeof window === 'undefined')
3366
- return;
3367
- const anchorRect = anchorEl.getBoundingClientRect();
3368
- const panelRect = panelEl.getBoundingClientRect();
3369
- const gap = 4;
3370
- this._panelLeft.set(Math.max(8, Math.min(anchorRect.left, window.innerWidth - panelRect.width - 8)));
3371
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
3372
- this._panelTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
3373
- }
3374
- }
3375
3568
  selectedItemRef = contentChild('selectedItem', /* @ts-ignore */
3376
3569
  ...(ngDevMode ? [{ debugName: "selectedItemRef" }] : /* istanbul ignore next */ []));
3377
3570
  itemRef = contentChild('item', /* @ts-ignore */
@@ -3463,8 +3656,28 @@ class SelectComponent {
3463
3656
  const rec = opt;
3464
3657
  return this.filterFieldList().some((f) => this.matchesFilter(rec[f], query));
3465
3658
  }
3659
+ // The pinned object only counts as "selected" once it actually matches the
3660
+ // current value — a stale/irrelevant selectedObject is never injected.
3661
+ selectedObjectEntry = computed(() => {
3662
+ const sel = this.selectedObject();
3663
+ if (sel == null)
3664
+ return null;
3665
+ return this.getOptionValue(sel) === this.value() ? sel : null;
3666
+ }, /* @ts-ignore */
3667
+ ...(ngDevMode ? [{ debugName: "selectedObjectEntry" }] : /* istanbul ignore next */ []));
3668
+ mergeSelected(base) {
3669
+ const sel = this.selectedObjectEntry();
3670
+ if (sel == null)
3671
+ return base;
3672
+ const selVal = this.getOptionValue(sel);
3673
+ return base.some((o) => this.getOptionValue(o) === selVal)
3674
+ ? base
3675
+ : [sel, ...base];
3676
+ }
3677
+ optionsWithSelected = computed(() => this.mergeSelected(this.options()), /* @ts-ignore */
3678
+ ...(ngDevMode ? [{ debugName: "optionsWithSelected" }] : /* istanbul ignore next */ []));
3466
3679
  filteredOptions = computed(() => {
3467
- const opts = this.options();
3680
+ const opts = this.group() ? this.options() : this.optionsWithSelected();
3468
3681
  const q = this.filterText();
3469
3682
  if (!q)
3470
3683
  return opts;
@@ -3473,9 +3686,10 @@ class SelectComponent {
3473
3686
  ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
3474
3687
  allLeafOptions = computed(() => {
3475
3688
  if (!this.group())
3476
- return this.options();
3689
+ return this.optionsWithSelected();
3477
3690
  const groups = this.options();
3478
- return groups.flatMap((g) => g[this.optionGroupChildren()] ?? []);
3691
+ const leaves = groups.flatMap((g) => g[this.optionGroupChildren()] ?? []);
3692
+ return this.mergeSelected(leaves);
3479
3693
  }, /* @ts-ignore */
3480
3694
  ...(ngDevMode ? [{ debugName: "allLeafOptions" }] : /* istanbul ignore next */ []));
3481
3695
  flatItems = computed(() => {
@@ -3613,10 +3827,6 @@ class SelectComponent {
3613
3827
  this.onShow.emit();
3614
3828
  if (this.lazy())
3615
3829
  this.onLazyLoad.emit({ filter: this.filterText() });
3616
- if (this.appendTo() === 'body') {
3617
- this.position();
3618
- setTimeout(() => this.adjustForViewport(), 0);
3619
- }
3620
3830
  }
3621
3831
  closeList() {
3622
3832
  this._open.set(false);
@@ -3752,7 +3962,7 @@ class SelectComponent {
3752
3962
  }
3753
3963
  setDisabledState() { }
3754
3964
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3755
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: SelectComponent, isStandalone: true, selector: "f-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, filterMatchMode: { classPropertyName: "filterMatchMode", publicName: "filterMatchMode", isSignal: true, isRequired: false, transformFunction: null }, filterLocale: { classPropertyName: "filterLocale", publicName: "filterLocale", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, resetFilterOnHide: { classPropertyName: "resetFilterOnHide", publicName: "resetFilterOnHide", isSignal: true, isRequired: false, transformFunction: null }, autofocusFilter: { classPropertyName: "autofocusFilter", publicName: "autofocusFilter", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingIcon: { classPropertyName: "loadingIcon", publicName: "loadingIcon", isSignal: true, isRequired: false, transformFunction: null }, dropdownIcon: { classPropertyName: "dropdownIcon", publicName: "dropdownIcon", isSignal: true, isRequired: false, transformFunction: null }, clearIcon: { classPropertyName: "clearIcon", publicName: "clearIcon", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, optionGroupLabel: { classPropertyName: "optionGroupLabel", publicName: "optionGroupLabel", isSignal: true, isRequired: false, transformFunction: null }, optionGroupChildren: { classPropertyName: "optionGroupChildren", publicName: "optionGroupChildren", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFilter: "onFilter", onChange: "onChange", onShow: "onShow", onHide: "onHide", onBlur: "onBlur", onFocus: "onFocus", onClear: "onClear", onLazyLoad: "onLazyLoad" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "hostClass()", "style": "style()" } }, providers: [
3965
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: SelectComponent, isStandalone: true, selector: "f-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, filterMatchMode: { classPropertyName: "filterMatchMode", publicName: "filterMatchMode", isSignal: true, isRequired: false, transformFunction: null }, filterLocale: { classPropertyName: "filterLocale", publicName: "filterLocale", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, resetFilterOnHide: { classPropertyName: "resetFilterOnHide", publicName: "resetFilterOnHide", isSignal: true, isRequired: false, transformFunction: null }, autofocusFilter: { classPropertyName: "autofocusFilter", publicName: "autofocusFilter", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingIcon: { classPropertyName: "loadingIcon", publicName: "loadingIcon", isSignal: true, isRequired: false, transformFunction: null }, dropdownIcon: { classPropertyName: "dropdownIcon", publicName: "dropdownIcon", isSignal: true, isRequired: false, transformFunction: null }, clearIcon: { classPropertyName: "clearIcon", publicName: "clearIcon", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, optionGroupLabel: { classPropertyName: "optionGroupLabel", publicName: "optionGroupLabel", isSignal: true, isRequired: false, transformFunction: null }, optionGroupChildren: { classPropertyName: "optionGroupChildren", publicName: "optionGroupChildren", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, selectedObject: { classPropertyName: "selectedObject", publicName: "selectedObject", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFilter: "onFilter", onChange: "onChange", onShow: "onShow", onHide: "onHide", onBlur: "onBlur", onFocus: "onFocus", onClear: "onClear", onLazyLoad: "onLazyLoad" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "hostClass()", "style": "style()" } }, providers: [
3756
3966
  {
3757
3967
  provide: NG_VALUE_ACCESSOR,
3758
3968
  useExisting: forwardRef(() => SelectComponent),
@@ -3873,7 +4083,7 @@ class SelectComponent {
3873
4083
  data-select-list
3874
4084
  [id]="listId()"
3875
4085
  role="listbox"
3876
- class="max-h-56 overflow-auto py-1"
4086
+ class="flex-1 min-h-0 max-h-56 overflow-auto py-1"
3877
4087
  >
3878
4088
  @if (loading()) {
3879
4089
  @if (loaderTpl()) {
@@ -4126,7 +4336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
4126
4336
  data-select-list
4127
4337
  [id]="listId()"
4128
4338
  role="listbox"
4129
- class="max-h-56 overflow-auto py-1"
4339
+ class="flex-1 min-h-0 max-h-56 overflow-auto py-1"
4130
4340
  >
4131
4341
  @if (loading()) {
4132
4342
  @if (loaderTpl()) {
@@ -4247,7 +4457,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
4247
4457
  </ng-template>
4248
4458
  `,
4249
4459
  }]
4250
- }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], filterMatchMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMatchMode", required: false }] }], filterLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocale", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], resetFilterOnHide: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterOnHide", required: false }] }], autofocusFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocusFilter", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], clearIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearIcon", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], checkmark: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkmark", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], onFilter: [{ type: i0.Output, args: ["onFilter"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], _triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], _editableInputRef: [{ type: i0.ViewChild, args: ['editableInputEl', { isSignal: true }] }], _filterInputRef: [{ type: i0.ViewChild, args: ['filterInput', { isSignal: true }] }], _panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], emptyFilterRef: [{ type: i0.ContentChild, args: ['emptyfilter', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], filterRef: [{ type: i0.ContentChild, args: ['filter', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
4460
+ }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], filterMatchMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMatchMode", required: false }] }], filterLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocale", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], resetFilterOnHide: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterOnHide", required: false }] }], autofocusFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocusFilter", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], clearIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearIcon", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], checkmark: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkmark", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], selectedObject: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedObject", required: false }] }], onFilter: [{ type: i0.Output, args: ["onFilter"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], _triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], _editableInputRef: [{ type: i0.ViewChild, args: ['editableInputEl', { isSignal: true }] }], _filterInputRef: [{ type: i0.ViewChild, args: ['filterInput', { isSignal: true }] }], _panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], emptyFilterRef: [{ type: i0.ContentChild, args: ['emptyfilter', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], filterRef: [{ type: i0.ContentChild, args: ['filter', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
4251
4461
 
4252
4462
  class MultiSelectComponent {
4253
4463
  _el = inject(ElementRef);
@@ -4269,10 +4479,6 @@ class MultiSelectComponent {
4269
4479
  queueMicrotask(() => this._filterInputRef()?.nativeElement.focus());
4270
4480
  }
4271
4481
  });
4272
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => {
4273
- this.position();
4274
- this.adjustForViewport();
4275
- });
4276
4482
  }
4277
4483
  onDocumentClick(e) {
4278
4484
  if (this.open() && !this._el.nativeElement.contains(e.target)) {
@@ -4285,49 +4491,19 @@ class MultiSelectComponent {
4285
4491
  ...(ngDevMode ? [{ debugName: "_filterInputRef" }] : /* istanbul ignore next */ []));
4286
4492
  _panelRef = viewChild('panel', /* @ts-ignore */
4287
4493
  ...(ngDevMode ? [{ debugName: "_panelRef" }] : /* istanbul ignore next */ []));
4288
- _panelTop = signal(0, /* @ts-ignore */
4289
- ...(ngDevMode ? [{ debugName: "_panelTop" }] : /* istanbul ignore next */ []));
4290
- _panelLeft = signal(0, /* @ts-ignore */
4291
- ...(ngDevMode ? [{ debugName: "_panelLeft" }] : /* istanbul ignore next */ []));
4292
- _panelWidth = signal(0, /* @ts-ignore */
4293
- ...(ngDevMode ? [{ debugName: "_panelWidth" }] : /* istanbul ignore next */ []));
4494
+ _placement = overlayPosition({
4495
+ active: () => this.open() && this.appendTo() === 'body',
4496
+ anchor: () => this._triggerRef()?.nativeElement,
4497
+ panel: () => this._panelRef()?.nativeElement,
4498
+ options: () => ({ matchAnchorWidth: true }),
4499
+ });
4294
4500
  panelClass = computed(() => {
4295
4501
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute w-full mt-1';
4296
- return `${position} z-50 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
4502
+ return `${position} z-50 flex flex-col bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
4297
4503
  }, /* @ts-ignore */
4298
4504
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
4299
- panelStyle = computed(() => {
4300
- if (this.appendTo() !== 'body')
4301
- return {};
4302
- return {
4303
- top: `${this._panelTop()}px`,
4304
- left: `${this._panelLeft()}px`,
4305
- width: `${this._panelWidth()}px`,
4306
- };
4307
- }, /* @ts-ignore */
4505
+ panelStyle = computed(() => this.appendTo() === 'body' ? overlayPlacementStyle(this._placement()) : {}, /* @ts-ignore */
4308
4506
  ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
4309
- position() {
4310
- const anchorEl = this._triggerRef()?.nativeElement;
4311
- if (!anchorEl || typeof window === 'undefined')
4312
- return;
4313
- const rect = anchorEl.getBoundingClientRect();
4314
- this._panelTop.set(rect.bottom + 4);
4315
- this._panelLeft.set(Math.max(8, rect.left));
4316
- this._panelWidth.set(rect.width);
4317
- }
4318
- adjustForViewport() {
4319
- const panelEl = this._panelRef()?.nativeElement;
4320
- const anchorEl = this._triggerRef()?.nativeElement;
4321
- if (!panelEl || !anchorEl || typeof window === 'undefined')
4322
- return;
4323
- const anchorRect = anchorEl.getBoundingClientRect();
4324
- const panelRect = panelEl.getBoundingClientRect();
4325
- const gap = 4;
4326
- this._panelLeft.set(Math.max(8, Math.min(anchorRect.left, window.innerWidth - panelRect.width - 8)));
4327
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
4328
- this._panelTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
4329
- }
4330
- }
4331
4507
  triggerClass = computed(() => {
4332
4508
  const base = 'w-full min-h-[34px] flex items-center gap-2 f-field-compact text-sm border bg-(--f-form-field-background) focus:outline-none focus-visible:ring-focus transition-all duration-[var(--f-transition-duration)]';
4333
4509
  const showInvalid = this.invalid() && this.touched();
@@ -4390,7 +4566,7 @@ class MultiSelectComponent {
4390
4566
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
4391
4567
  style = input(null, /* @ts-ignore */
4392
4568
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
4393
- appendTo = input('self', /* @ts-ignore */
4569
+ appendTo = input('body', /* @ts-ignore */
4394
4570
  ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
4395
4571
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4396
4572
  autofocus = input(false, { ...(ngDevMode ? { debugName: "autofocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -4410,6 +4586,14 @@ class MultiSelectComponent {
4410
4586
  virtualScrollItemSize = input(36, /* @ts-ignore */
4411
4587
  ...(ngDevMode ? [{ debugName: "virtualScrollItemSize" }] : /* istanbul ignore next */ []));
4412
4588
  lazy = input(false, { ...(ngDevMode ? { debugName: "lazy" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4589
+ /**
4590
+ * Full option objects for the currently selected `values()`, supplied by the
4591
+ * consumer. Pinned into the option pool (deduped by `optionValue`) whenever a
4592
+ * lazy-loaded or filtered `options()` page doesn't contain one of them, so
4593
+ * chips/labels always resolve correctly on edit forms.
4594
+ */
4595
+ selectedObjects = input([], /* @ts-ignore */
4596
+ ...(ngDevMode ? [{ debugName: "selectedObjects" }] : /* istanbul ignore next */ []));
4413
4597
  hostClass = computed(() => `block w-full ${this.styleClass()}`, /* @ts-ignore */
4414
4598
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
4415
4599
  onBlur = output();
@@ -4524,8 +4708,21 @@ class MultiSelectComponent {
4524
4708
  const rec = opt;
4525
4709
  return this.filterFieldList().some((f) => this.matchesFilter(rec[f], query));
4526
4710
  }
4711
+ // Only the selectedObjects entries that actually match a currently selected
4712
+ // value are pinned — anything stale/irrelevant is ignored.
4713
+ selectedObjectEntries = computed(() => {
4714
+ const vals = this.values();
4715
+ return this.selectedObjects().filter((o) => vals.includes(this.getOptionValue(o)));
4716
+ }, /* @ts-ignore */
4717
+ ...(ngDevMode ? [{ debugName: "selectedObjectEntries" }] : /* istanbul ignore next */ []));
4718
+ mergeSelected(base) {
4719
+ const extras = this.selectedObjectEntries().filter((sel) => !base.some((o) => this.getOptionValue(o) === this.getOptionValue(sel)));
4720
+ return extras.length ? [...extras, ...base] : base;
4721
+ }
4722
+ optionsWithSelected = computed(() => this.mergeSelected(this.options()), /* @ts-ignore */
4723
+ ...(ngDevMode ? [{ debugName: "optionsWithSelected" }] : /* istanbul ignore next */ []));
4527
4724
  filteredOptions = computed(() => {
4528
- const opts = this.options();
4725
+ const opts = this.group() ? this.options() : this.optionsWithSelected();
4529
4726
  const q = this.filterText();
4530
4727
  if (!q)
4531
4728
  return opts;
@@ -4534,9 +4731,10 @@ class MultiSelectComponent {
4534
4731
  ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
4535
4732
  allLeafOptions = computed(() => {
4536
4733
  if (!this.group())
4537
- return this.options();
4734
+ return this.optionsWithSelected();
4538
4735
  const groups = this.options();
4539
- return groups.flatMap((g) => g[this.optionGroupChildren()] ?? []);
4736
+ const leaves = groups.flatMap((g) => g[this.optionGroupChildren()] ?? []);
4737
+ return this.mergeSelected(leaves);
4540
4738
  }, /* @ts-ignore */
4541
4739
  ...(ngDevMode ? [{ debugName: "allLeafOptions" }] : /* istanbul ignore next */ []));
4542
4740
  flatItems = computed(() => {
@@ -4632,10 +4830,6 @@ class MultiSelectComponent {
4632
4830
  this.onShow.emit();
4633
4831
  if (this.lazy())
4634
4832
  this.onLazyLoad.emit({ filter: this.filterText() });
4635
- if (this.appendTo() === 'body') {
4636
- this.position();
4637
- setTimeout(() => this.adjustForViewport(), 0);
4638
- }
4639
4833
  }
4640
4834
  closeList() {
4641
4835
  this._open.set(false);
@@ -4811,7 +5005,7 @@ class MultiSelectComponent {
4811
5005
  }
4812
5006
  setDisabledState() { }
4813
5007
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: MultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4814
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: MultiSelectComponent, isStandalone: true, selector: "f-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, filterMatchMode: { classPropertyName: "filterMatchMode", publicName: "filterMatchMode", isSignal: true, isRequired: false, transformFunction: null }, filterLocale: { classPropertyName: "filterLocale", publicName: "filterLocale", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, resetFilterOnHide: { classPropertyName: "resetFilterOnHide", publicName: "resetFilterOnHide", isSignal: true, isRequired: false, transformFunction: null }, autofocusFilter: { classPropertyName: "autofocusFilter", publicName: "autofocusFilter", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectionLimit: { classPropertyName: "selectionLimit", publicName: "selectionLimit", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingIcon: { classPropertyName: "loadingIcon", publicName: "loadingIcon", isSignal: true, isRequired: false, transformFunction: null }, dropdownIcon: { classPropertyName: "dropdownIcon", publicName: "dropdownIcon", isSignal: true, isRequired: false, transformFunction: null }, clearIcon: { classPropertyName: "clearIcon", publicName: "clearIcon", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, optionGroupLabel: { classPropertyName: "optionGroupLabel", publicName: "optionGroupLabel", isSignal: true, isRequired: false, transformFunction: null }, optionGroupChildren: { classPropertyName: "optionGroupChildren", publicName: "optionGroupChildren", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onBlur: "onBlur", onFocus: "onFocus", onChange: "onChange", onFilter: "onFilter", onShow: "onShow", onHide: "onHide", onClear: "onClear", onLazyLoad: "onLazyLoad", onSelectAllChange: "onSelectAllChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "hostClass()", "style": "style()" } }, providers: [
5008
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: MultiSelectComponent, isStandalone: true, selector: "f-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, filterMatchMode: { classPropertyName: "filterMatchMode", publicName: "filterMatchMode", isSignal: true, isRequired: false, transformFunction: null }, filterLocale: { classPropertyName: "filterLocale", publicName: "filterLocale", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, resetFilterOnHide: { classPropertyName: "resetFilterOnHide", publicName: "resetFilterOnHide", isSignal: true, isRequired: false, transformFunction: null }, autofocusFilter: { classPropertyName: "autofocusFilter", publicName: "autofocusFilter", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, optionDisabled: { classPropertyName: "optionDisabled", publicName: "optionDisabled", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectionLimit: { classPropertyName: "selectionLimit", publicName: "selectionLimit", isSignal: true, isRequired: false, transformFunction: null }, showToggleAll: { classPropertyName: "showToggleAll", publicName: "showToggleAll", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingIcon: { classPropertyName: "loadingIcon", publicName: "loadingIcon", isSignal: true, isRequired: false, transformFunction: null }, dropdownIcon: { classPropertyName: "dropdownIcon", publicName: "dropdownIcon", isSignal: true, isRequired: false, transformFunction: null }, clearIcon: { classPropertyName: "clearIcon", publicName: "clearIcon", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, optionGroupLabel: { classPropertyName: "optionGroupLabel", publicName: "optionGroupLabel", isSignal: true, isRequired: false, transformFunction: null }, optionGroupChildren: { classPropertyName: "optionGroupChildren", publicName: "optionGroupChildren", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, selectedObjects: { classPropertyName: "selectedObjects", publicName: "selectedObjects", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onBlur: "onBlur", onFocus: "onFocus", onChange: "onChange", onFilter: "onFilter", onShow: "onShow", onHide: "onHide", onClear: "onClear", onLazyLoad: "onLazyLoad", onSelectAllChange: "onSelectAllChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "hostClass()", "style": "style()" } }, providers: [
4815
5009
  {
4816
5010
  provide: NG_VALUE_ACCESSOR,
4817
5011
  useExisting: forwardRef(() => MultiSelectComponent),
@@ -4972,7 +5166,7 @@ class MultiSelectComponent {
4972
5166
  [id]="listId()"
4973
5167
  role="listbox"
4974
5168
  [attr.aria-multiselectable]="true"
4975
- class="max-h-56 overflow-auto py-1"
5169
+ class="flex-1 min-h-0 max-h-56 overflow-auto py-1"
4976
5170
  >
4977
5171
  @if (loading()) {
4978
5172
  @if (loaderTpl()) {
@@ -5275,7 +5469,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
5275
5469
  [id]="listId()"
5276
5470
  role="listbox"
5277
5471
  [attr.aria-multiselectable]="true"
5278
- class="max-h-56 overflow-auto py-1"
5472
+ class="flex-1 min-h-0 max-h-56 overflow-auto py-1"
5279
5473
  >
5280
5474
  @if (loading()) {
5281
5475
  @if (loaderTpl()) {
@@ -5406,7 +5600,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
5406
5600
  </ng-template>
5407
5601
  `,
5408
5602
  }]
5409
- }], ctorParameters: () => [], propDecorators: { _triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], _filterInputRef: [{ type: i0.ViewChild, args: ['filterInput', { isSignal: true }] }], _panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], filterMatchMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMatchMode", required: false }] }], filterLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocale", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], resetFilterOnHide: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterOnHide", required: false }] }], autofocusFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocusFilter", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectionLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionLimit", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], clearIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearIcon", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onFilter: [{ type: i0.Output, args: ["onFilter"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], onSelectAllChange: [{ type: i0.Output, args: ["onSelectAllChange"] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], emptyFilterRef: [{ type: i0.ContentChild, args: ['emptyfilter', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], filterRef: [{ type: i0.ContentChild, args: ['filter', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
5603
+ }], ctorParameters: () => [], propDecorators: { _triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], _filterInputRef: [{ type: i0.ViewChild, args: ['filterInput', { isSignal: true }] }], _panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], filterMatchMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMatchMode", required: false }] }], filterLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocale", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], resetFilterOnHide: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterOnHide", required: false }] }], autofocusFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocusFilter", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], optionDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionDisabled", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectionLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionLimit", required: false }] }], showToggleAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggleAll", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], clearIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearIcon", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], selectedObjects: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedObjects", required: false }] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onFilter: [{ type: i0.Output, args: ["onFilter"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], onSelectAllChange: [{ type: i0.Output, args: ["onSelectAllChange"] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], emptyFilterRef: [{ type: i0.ContentChild, args: ['emptyfilter', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], filterRef: [{ type: i0.ContentChild, args: ['filter', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
5410
5604
 
5411
5605
  class CheckboxComponent {
5412
5606
  label = input('', /* @ts-ignore */
@@ -6803,13 +6997,22 @@ class InputIconComponent {
6803
6997
  const sideClass = this._resolvedPosition() === 'right'
6804
6998
  ? 'right-(--f-field-padding-x)'
6805
6999
  : 'left-(--f-field-padding-x)';
6806
- return `absolute ${sideClass} top-1/2 -translate-y-1/2 text-(--f-form-field-placeholder-color) ${this.styleClass()}`;
7000
+ // `position: absolute` blockifies this custom element, so its single
7001
+ // inline-flex child (`ui-icon`) would otherwise sit in a line box using
7002
+ // the browser's default baseline alignment, not true geometric centering
7003
+ // — inline-flex + items-center makes this element itself a flex
7004
+ // container so the icon centers against the box's real vertical
7005
+ // midpoint instead of ambient font baseline metrics.
7006
+ // Geometric center lands 1px low for a search-glass-shaped icon next to
7007
+ // text (its visual weight sits toward the bottom via the handle stroke),
7008
+ // so nudge up 1px for correct optical alignment.
7009
+ return `absolute inline-flex items-center ${sideClass} top-1/2 -translate-y-[calc(50%+1px)] text-(--f-form-field-placeholder-color) ${this.styleClass()}`;
6807
7010
  }, /* @ts-ignore */
6808
7011
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
6809
7012
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: InputIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6810
7013
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: InputIconComponent, isStandalone: true, selector: "f-inputicon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClass()", "style": "style()" } }, ngImport: i0, template: `
6811
7014
  @if (icon()) {
6812
- <ui-icon [name]="icon()"></ui-icon>
7015
+ <ui-icon [name]="icon()" [size]="17"></ui-icon>
6813
7016
  }
6814
7017
  <ng-content />
6815
7018
  `, isInline: true, dependencies: [{ kind: "component", type: UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }] });
@@ -6822,7 +7025,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6822
7025
  host: { '[class]': 'hostClass()', '[style]': 'style()' },
6823
7026
  template: `
6824
7027
  @if (icon()) {
6825
- <ui-icon [name]="icon()"></ui-icon>
7028
+ <ui-icon [name]="icon()" [size]="17"></ui-icon>
6826
7029
  }
6827
7030
  <ng-content />
6828
7031
  `,
@@ -6881,14 +7084,20 @@ class PopoverComponent {
6881
7084
  _visible = signal(false, /* @ts-ignore */
6882
7085
  ...(ngDevMode ? [{ debugName: "_visible" }] : /* istanbul ignore next */ []));
6883
7086
  visible = this._visible.asReadonly();
6884
- _top = signal(0, /* @ts-ignore */
6885
- ...(ngDevMode ? [{ debugName: "_top" }] : /* istanbul ignore next */ []));
6886
- top = this._top.asReadonly();
6887
- _left = signal(0, /* @ts-ignore */
6888
- ...(ngDevMode ? [{ debugName: "_left" }] : /* istanbul ignore next */ []));
6889
- left = this._left.asReadonly();
6890
7087
  panelRef = viewChild('panel', /* @ts-ignore */
6891
7088
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
7089
+ _placement = overlayPosition({
7090
+ active: () => this.visible() && this.appendTo() === 'body',
7091
+ anchor: () => this._anchor,
7092
+ panel: () => this.panelRef()?.nativeElement,
7093
+ options: () => ({ gap: 6 }),
7094
+ });
7095
+ top = computed(() => this._placement()?.top ?? 0, /* @ts-ignore */
7096
+ ...(ngDevMode ? [{ debugName: "top" }] : /* istanbul ignore next */ []));
7097
+ left = computed(() => this._placement()?.left ?? 0, /* @ts-ignore */
7098
+ ...(ngDevMode ? [{ debugName: "left" }] : /* istanbul ignore next */ []));
7099
+ maxHeight = computed(() => this._placement()?.maxHeight ?? null, /* @ts-ignore */
7100
+ ...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
6892
7101
  _anchor = null;
6893
7102
  _previouslyFocused = null;
6894
7103
  _windowWidth = signal(typeof window !== 'undefined' ? window.innerWidth : Number.POSITIVE_INFINITY, /* @ts-ignore */
@@ -6917,7 +7126,7 @@ class PopoverComponent {
6917
7126
  // positioning, which already escapes ancestor overflow clipping without a real
6918
7127
  // DOM reparent.
6919
7128
  panelClass = computed(() => {
6920
- const position = this.appendTo() === 'self' ? 'absolute top-full left-0 mt-1.5' : 'fixed';
7129
+ const position = this.appendTo() === 'self' ? 'absolute top-full left-0 mt-1.5' : 'fixed overflow-auto';
6921
7130
  return `popover-panel ${position} z-50 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay min-w-48 max-w-sm ${this.styleClass()}`;
6922
7131
  }, /* @ts-ignore */
6923
7132
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
@@ -6927,7 +7136,6 @@ class PopoverComponent {
6927
7136
  .pipe(takeUntilDestroyed())
6928
7137
  .subscribe(() => this._windowWidth.set(window.innerWidth));
6929
7138
  }
6930
- repositionOnScroll(() => this.visible() && this.appendTo() === 'body', () => { this.position(); this.adjustForViewport(); });
6931
7139
  }
6932
7140
  toggle(event) {
6933
7141
  this._anchor = event.target;
@@ -6943,11 +7151,9 @@ class PopoverComponent {
6943
7151
  }
6944
7152
  showInternal() {
6945
7153
  this._previouslyFocused = typeof document !== 'undefined' ? document.activeElement : null;
6946
- this.position();
6947
7154
  this._visible.set(true);
6948
7155
  this.onShow.emit();
6949
7156
  setTimeout(() => {
6950
- this.adjustForViewport();
6951
7157
  if (this.focusOnShow())
6952
7158
  this.focusPanel();
6953
7159
  }, 0);
@@ -6968,32 +7174,6 @@ class PopoverComponent {
6968
7174
  const focusable = panelEl.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
6969
7175
  (focusable ?? panelEl).focus();
6970
7176
  }
6971
- position() {
6972
- if (!this._anchor || this.appendTo() === 'self')
6973
- return;
6974
- const rect = this._anchor.getBoundingClientRect();
6975
- const gap = 6;
6976
- let top = rect.bottom + gap;
6977
- let left = rect.left;
6978
- if (typeof window !== 'undefined') {
6979
- left = Math.min(left, window.innerWidth - 200 - 8);
6980
- }
6981
- this._top.set(top);
6982
- this._left.set(Math.max(8, left));
6983
- }
6984
- adjustForViewport() {
6985
- if (this.appendTo() === 'self')
6986
- return;
6987
- const panelEl = this.panelRef()?.nativeElement;
6988
- if (!panelEl || !this._anchor || typeof window === 'undefined')
6989
- return;
6990
- const anchorRect = this._anchor.getBoundingClientRect();
6991
- const panelRect = panelEl.getBoundingClientRect();
6992
- const gap = 6;
6993
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
6994
- this._top.set(Math.max(8, anchorRect.top - panelRect.height - gap));
6995
- }
6996
- }
6997
7177
  onCloseIconClick(event) {
6998
7178
  event.stopPropagation();
6999
7179
  this.hide();
@@ -7020,6 +7200,7 @@ class PopoverComponent {
7020
7200
  [style]="panelStyle()"
7021
7201
  [style.top.px]="appendTo() === 'body' ? top() : null"
7022
7202
  [style.left.px]="appendTo() === 'body' ? left() : null"
7203
+ [style.max-height.px]="appendTo() === 'body' ? maxHeight() : null"
7023
7204
  (click)="$event.stopPropagation()"
7024
7205
  >
7025
7206
  @if (showCloseIcon()) {
@@ -7055,6 +7236,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
7055
7236
  [style]="panelStyle()"
7056
7237
  [style.top.px]="appendTo() === 'body' ? top() : null"
7057
7238
  [style.left.px]="appendTo() === 'body' ? left() : null"
7239
+ [style.max-height.px]="appendTo() === 'body' ? maxHeight() : null"
7058
7240
  (click)="$event.stopPropagation()"
7059
7241
  >
7060
7242
  @if (showCloseIcon()) {
@@ -9213,7 +9395,7 @@ const CLOSE_ANIMATION_MS$1 = 180;
9213
9395
  const FOCUSABLE_SELECTOR$2 = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
9214
9396
  class DialogComponent {
9215
9397
  static idCounter = 0;
9216
- _doc = inject(DOCUMENT);
9398
+ _overlayStack = inject(OverlayStackService);
9217
9399
  headerId = `f-dialog-header-${++DialogComponent.idCounter}`;
9218
9400
  header = input('', /* @ts-ignore */
9219
9401
  ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
@@ -9332,9 +9514,13 @@ class DialogComponent {
9332
9514
  _closing = signal(false, /* @ts-ignore */
9333
9515
  ...(ngDevMode ? [{ debugName: "_closing" }] : /* istanbul ignore next */ []));
9334
9516
  closing = this._closing.asReadonly();
9517
+ _zIndex = signal(null, /* @ts-ignore */
9518
+ ...(ngDevMode ? [{ debugName: "_zIndex" }] : /* istanbul ignore next */ []));
9519
+ zIndex = this._zIndex.asReadonly();
9335
9520
  panelRef = viewChild('panel', /* @ts-ignore */
9336
9521
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
9337
9522
  _previouslyFocused = null;
9523
+ _scrollLocked = false;
9338
9524
  constructor() {
9339
9525
  if (typeof window !== 'undefined') {
9340
9526
  fromEvent(window, 'resize')
@@ -9346,19 +9532,24 @@ class DialogComponent {
9346
9532
  if (visible) {
9347
9533
  this._closing.set(false);
9348
9534
  this._rendered.set(true);
9535
+ this._zIndex.set(this._overlayStack.open());
9349
9536
  this._previouslyFocused =
9350
9537
  typeof document !== 'undefined'
9351
9538
  ? document.activeElement
9352
9539
  : null;
9353
- if (this.modal() || this.blockScroll())
9354
- this._doc.body.style.overflow = 'hidden';
9540
+ if (this.modal() || this.blockScroll()) {
9541
+ this._overlayStack.lockScroll();
9542
+ this._scrollLocked = true;
9543
+ }
9355
9544
  this.onShow.emit();
9356
9545
  setTimeout(() => this.focusPanel(), 0);
9357
9546
  }
9358
9547
  else if (this._rendered()) {
9359
9548
  this._closing.set(true);
9360
- if (this.modal() || this.blockScroll())
9361
- this._doc.body.style.overflow = '';
9549
+ if (this._scrollLocked) {
9550
+ this._overlayStack.unlockScroll();
9551
+ this._scrollLocked = false;
9552
+ }
9362
9553
  if (this.returnFocusOnClose())
9363
9554
  this._previouslyFocused?.focus();
9364
9555
  this._previouslyFocused = null;
@@ -9368,9 +9559,16 @@ class DialogComponent {
9368
9559
  setTimeout(() => {
9369
9560
  this._rendered.set(false);
9370
9561
  this._closing.set(false);
9562
+ this._zIndex.set(null);
9371
9563
  }, CLOSE_ANIMATION_MS$1);
9372
9564
  }
9373
9565
  });
9566
+ inject(DestroyRef).onDestroy(() => {
9567
+ if (this._scrollLocked) {
9568
+ this._overlayStack.unlockScroll();
9569
+ this._scrollLocked = false;
9570
+ }
9571
+ });
9374
9572
  }
9375
9573
  onEscape() {
9376
9574
  if (this.visible() && this.closable() && this.closeOnEscape())
@@ -9488,7 +9686,8 @@ class DialogComponent {
9488
9686
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: DialogComponent, isStandalone: true, selector: "f-dialog", inputs: { header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, dismissableMask: { classPropertyName: "dismissableMask", publicName: "dismissableMask", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, maximizable: { classPropertyName: "maximizable", publicName: "maximizable", isSignal: true, isRequired: false, transformFunction: null }, blockScroll: { classPropertyName: "blockScroll", publicName: "blockScroll", isSignal: true, isRequired: false, transformFunction: null }, returnFocusOnClose: { classPropertyName: "returnFocusOnClose", publicName: "returnFocusOnClose", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, breakpoints: { classPropertyName: "breakpoints", publicName: "breakpoints", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", onShow: "onShow", onHide: "onHide", onMaximize: "onMaximize" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "headerRef", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "footerRef", first: true, predicate: ["footer"], descendants: true, isSignal: true }, { propertyName: "fTemplates", predicate: FTemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
9489
9687
  @if (rendered()) {
9490
9688
  <div
9491
- class="fixed inset-0 z-999 flex p-4"
9689
+ class="fixed inset-0 flex p-4"
9690
+ [style.z-index]="zIndex()"
9492
9691
  [class]="containerPositionClass()"
9493
9692
  [class.pointer-events-none]="!modal()"
9494
9693
  >
@@ -9579,7 +9778,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
9579
9778
  args: [{ selector: 'f-dialog', imports: [NgTemplateOutlet, UiIconComponent], host: { '(document:keydown.escape)': 'onEscape()' }, template: `
9580
9779
  @if (rendered()) {
9581
9780
  <div
9582
- class="fixed inset-0 z-999 flex p-4"
9781
+ class="fixed inset-0 flex p-4"
9782
+ [style.z-index]="zIndex()"
9583
9783
  [class]="containerPositionClass()"
9584
9784
  [class.pointer-events-none]="!modal()"
9585
9785
  >
@@ -9670,7 +9870,7 @@ const CLOSE_ANIMATION_MS = 200;
9670
9870
  const FOCUSABLE_SELECTOR$1 = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
9671
9871
  class DrawerComponent {
9672
9872
  static idCounter = 0;
9673
- _doc = inject(DOCUMENT);
9873
+ _overlayStack = inject(OverlayStackService);
9674
9874
  headerId = `f-drawer-header-${++DrawerComponent.idCounter}`;
9675
9875
  header = input('', /* @ts-ignore */
9676
9876
  ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
@@ -9743,36 +9943,52 @@ class DrawerComponent {
9743
9943
  _closing = signal(false, /* @ts-ignore */
9744
9944
  ...(ngDevMode ? [{ debugName: "_closing" }] : /* istanbul ignore next */ []));
9745
9945
  closing = this._closing.asReadonly();
9946
+ _zIndex = signal(null, /* @ts-ignore */
9947
+ ...(ngDevMode ? [{ debugName: "_zIndex" }] : /* istanbul ignore next */ []));
9948
+ zIndex = this._zIndex.asReadonly();
9746
9949
  panelRef = viewChild('panel', /* @ts-ignore */
9747
9950
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
9748
9951
  _previouslyFocused = null;
9952
+ _scrollLocked = false;
9749
9953
  constructor() {
9750
9954
  effect(() => {
9751
9955
  if (this.visible()) {
9752
9956
  this._closing.set(false);
9753
9957
  this._rendered.set(true);
9958
+ this._zIndex.set(this._overlayStack.open());
9754
9959
  this._previouslyFocused =
9755
9960
  typeof document !== 'undefined'
9756
9961
  ? document.activeElement
9757
9962
  : null;
9758
- if (this.modal() && this.blockScroll())
9759
- this._doc.body.style.overflow = 'hidden';
9963
+ if (this.modal() && this.blockScroll()) {
9964
+ this._overlayStack.lockScroll();
9965
+ this._scrollLocked = true;
9966
+ }
9760
9967
  this.onShow.emit();
9761
9968
  setTimeout(() => this.focusPanel(), 0);
9762
9969
  }
9763
9970
  else if (this._rendered()) {
9764
9971
  this._closing.set(true);
9765
- if (this.modal() && this.blockScroll())
9766
- this._doc.body.style.overflow = '';
9972
+ if (this._scrollLocked) {
9973
+ this._overlayStack.unlockScroll();
9974
+ this._scrollLocked = false;
9975
+ }
9767
9976
  if (this.returnFocusOnClose())
9768
9977
  this._previouslyFocused?.focus();
9769
9978
  this._previouslyFocused = null;
9770
9979
  setTimeout(() => {
9771
9980
  this._rendered.set(false);
9772
9981
  this._closing.set(false);
9982
+ this._zIndex.set(null);
9773
9983
  }, CLOSE_ANIMATION_MS);
9774
9984
  }
9775
9985
  });
9986
+ inject(DestroyRef).onDestroy(() => {
9987
+ if (this._scrollLocked) {
9988
+ this._overlayStack.unlockScroll();
9989
+ this._scrollLocked = false;
9990
+ }
9991
+ });
9776
9992
  }
9777
9993
  onEscape() {
9778
9994
  if (this.visible() && this.closeOnEscape())
@@ -9821,7 +10037,8 @@ class DrawerComponent {
9821
10037
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: DrawerComponent, isStandalone: true, selector: "f-drawer", inputs: { header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, fullScreen: { classPropertyName: "fullScreen", publicName: "fullScreen", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, dismissable: { classPropertyName: "dismissable", publicName: "dismissable", isSignal: true, isRequired: false, transformFunction: null }, blockScroll: { classPropertyName: "blockScroll", publicName: "blockScroll", isSignal: true, isRequired: false, transformFunction: null }, returnFocusOnClose: { classPropertyName: "returnFocusOnClose", publicName: "returnFocusOnClose", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", onShow: "onShow", onHide: "onHide" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "block" }, queries: [{ propertyName: "headerRef", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "footerRef", first: true, predicate: ["footer"], descendants: true, isSignal: true }, { propertyName: "contentRef", first: true, predicate: ["content"], descendants: true, isSignal: true }, { propertyName: "fTemplates", predicate: FTemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
9822
10038
  @if (rendered()) {
9823
10039
  <div
9824
- class="fixed inset-0 z-999 flex"
10040
+ class="fixed inset-0 flex"
10041
+ [style.z-index]="zIndex()"
9825
10042
  [class.pointer-events-none]="!modal()"
9826
10043
  >
9827
10044
  @if (modal()) {
@@ -9889,7 +10106,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
9889
10106
  args: [{ selector: 'f-drawer', imports: [UiIconComponent, NgTemplateOutlet], host: { class: 'block', '(document:keydown.escape)': 'onEscape()' }, template: `
9890
10107
  @if (rendered()) {
9891
10108
  <div
9892
- class="fixed inset-0 z-999 flex"
10109
+ class="fixed inset-0 flex"
10110
+ [style.z-index]="zIndex()"
9893
10111
  [class.pointer-events-none]="!modal()"
9894
10112
  >
9895
10113
  @if (modal()) {
@@ -11000,8 +11218,8 @@ class StepsComponent {
11000
11218
  } @else {
11001
11219
  <div role="tablist" [attr.aria-label]="ariaLabel()" [class]="'flex items-start w-full ' + styleClass()" [style]="style()">
11002
11220
  @for (item of model(); track $index; let i = $index; let last = $last) {
11003
- <div class="flex items-center" [class.flex-1]="!last">
11004
- <div class="flex flex-col items-center gap-2">
11221
+ <div class="flex items-start min-w-0" [class.flex-1]="!last">
11222
+ <div class="flex flex-col items-center gap-2 min-w-0">
11005
11223
  <button
11006
11224
  #stepBtn
11007
11225
  type="button"
@@ -11022,14 +11240,14 @@ class StepsComponent {
11022
11240
  }
11023
11241
  </button>
11024
11242
  @if (item.label) {
11025
- <span class="text-xs whitespace-nowrap transition-all duration-[var(--f-transition-duration)] leading-tight text-center max-w-[80px]"
11243
+ <span class="text-xs transition-all duration-[var(--f-transition-duration)] leading-tight text-center max-w-[120px] break-words"
11026
11244
  [class]="i === activeIndex() ? 'font-semibold text-primary' : i < activeIndex() ? 'font-medium text-(--f-text-muted-color)' : 'text-(--f-text-muted-color)'">
11027
11245
  {{ item.label }}
11028
11246
  </span>
11029
11247
  }
11030
11248
  </div>
11031
11249
  @if (!last) {
11032
- <div class="flex-1 h-[1.5px] mx-3 -mt-4 rounded-full transition-all duration-[var(--f-transition-duration)]" [class]="i < activeIndex() ? 'bg-primary' : 'bg-(--f-content-border-color)'"></div>
11250
+ <div class="flex-1 h-[1.5px] mx-3 mt-[15px] rounded-full transition-all duration-[var(--f-transition-duration)]" [class]="i < activeIndex() ? 'bg-primary' : 'bg-(--f-content-border-color)'"></div>
11033
11251
  }
11034
11252
  </div>
11035
11253
  }
@@ -11084,8 +11302,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
11084
11302
  } @else {
11085
11303
  <div role="tablist" [attr.aria-label]="ariaLabel()" [class]="'flex items-start w-full ' + styleClass()" [style]="style()">
11086
11304
  @for (item of model(); track $index; let i = $index; let last = $last) {
11087
- <div class="flex items-center" [class.flex-1]="!last">
11088
- <div class="flex flex-col items-center gap-2">
11305
+ <div class="flex items-start min-w-0" [class.flex-1]="!last">
11306
+ <div class="flex flex-col items-center gap-2 min-w-0">
11089
11307
  <button
11090
11308
  #stepBtn
11091
11309
  type="button"
@@ -11106,14 +11324,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
11106
11324
  }
11107
11325
  </button>
11108
11326
  @if (item.label) {
11109
- <span class="text-xs whitespace-nowrap transition-all duration-[var(--f-transition-duration)] leading-tight text-center max-w-[80px]"
11327
+ <span class="text-xs transition-all duration-[var(--f-transition-duration)] leading-tight text-center max-w-[120px] break-words"
11110
11328
  [class]="i === activeIndex() ? 'font-semibold text-primary' : i < activeIndex() ? 'font-medium text-(--f-text-muted-color)' : 'text-(--f-text-muted-color)'">
11111
11329
  {{ item.label }}
11112
11330
  </span>
11113
11331
  }
11114
11332
  </div>
11115
11333
  @if (!last) {
11116
- <div class="flex-1 h-[1.5px] mx-3 -mt-4 rounded-full transition-all duration-[var(--f-transition-duration)]" [class]="i < activeIndex() ? 'bg-primary' : 'bg-(--f-content-border-color)'"></div>
11334
+ <div class="flex-1 h-[1.5px] mx-3 mt-[15px] rounded-full transition-all duration-[var(--f-transition-duration)]" [class]="i < activeIndex() ? 'bg-primary' : 'bg-(--f-content-border-color)'"></div>
11117
11335
  }
11118
11336
  </div>
11119
11337
  }
@@ -14207,59 +14425,22 @@ class AutoCompleteComponent {
14207
14425
  ...(ngDevMode ? [{ debugName: "anchorRef" }] : /* istanbul ignore next */ []));
14208
14426
  panelRef = viewChild('panel', /* @ts-ignore */
14209
14427
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
14210
- _panelTop = signal(0, /* @ts-ignore */
14211
- ...(ngDevMode ? [{ debugName: "_panelTop" }] : /* istanbul ignore next */ []));
14212
- _panelLeft = signal(0, /* @ts-ignore */
14213
- ...(ngDevMode ? [{ debugName: "_panelLeft" }] : /* istanbul ignore next */ []));
14214
- _panelWidth = signal(0, /* @ts-ignore */
14215
- ...(ngDevMode ? [{ debugName: "_panelWidth" }] : /* istanbul ignore next */ []));
14428
+ _placement = overlayPosition({
14429
+ active: () => this.open() && this.appendTo() === 'body',
14430
+ anchor: () => this.anchorRef()?.nativeElement,
14431
+ panel: () => this.panelRef()?.nativeElement,
14432
+ options: () => ({ matchAnchorWidth: true }),
14433
+ });
14216
14434
  panelClass = computed(() => {
14217
14435
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute w-full mt-1';
14218
- return `${position} z-50 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
14436
+ return `${position} z-50 flex flex-col bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
14219
14437
  }, /* @ts-ignore */
14220
14438
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
14221
- panelStyle = computed(() => {
14222
- if (this.appendTo() !== 'body')
14223
- return {};
14224
- return {
14225
- top: `${this._panelTop()}px`,
14226
- left: `${this._panelLeft()}px`,
14227
- width: `${this._panelWidth()}px`,
14228
- };
14229
- }, /* @ts-ignore */
14439
+ panelStyle = computed(() => this.appendTo() === 'body' ? overlayPlacementStyle(this._placement()) : {}, /* @ts-ignore */
14230
14440
  ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
14231
- position() {
14232
- const anchorEl = this.anchorRef()?.nativeElement;
14233
- if (!anchorEl || typeof window === 'undefined')
14234
- return;
14235
- const rect = anchorEl.getBoundingClientRect();
14236
- this._panelTop.set(rect.bottom + 4);
14237
- this._panelLeft.set(Math.max(8, rect.left));
14238
- this._panelWidth.set(rect.width);
14239
- }
14240
- adjustForViewport() {
14241
- const panelEl = this.panelRef()?.nativeElement;
14242
- const anchorEl = this.anchorRef()?.nativeElement;
14243
- if (!panelEl || !anchorEl || typeof window === 'undefined')
14244
- return;
14245
- const anchorRect = anchorEl.getBoundingClientRect();
14246
- const panelRect = panelEl.getBoundingClientRect();
14247
- const gap = 4;
14248
- this._panelLeft.set(Math.max(8, Math.min(anchorRect.left, window.innerWidth - panelRect.width - 8)));
14249
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
14250
- this._panelTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
14251
- }
14252
- }
14253
14441
  openPanel() {
14254
- if (this.appendTo() === 'body') {
14255
- this.position();
14256
- setTimeout(() => this.adjustForViewport(), 0);
14257
- }
14258
14442
  this._open.set(true);
14259
14443
  }
14260
- constructor() {
14261
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => { this.position(); this.adjustForViewport(); });
14262
- }
14263
14444
  onDocumentClick(e) {
14264
14445
  if (this.open() && !this._el.nativeElement.contains(e.target)) {
14265
14446
  this._open.set(false);
@@ -14291,7 +14472,7 @@ class AutoCompleteComponent {
14291
14472
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
14292
14473
  style = input(null, /* @ts-ignore */
14293
14474
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
14294
- appendTo = input('self', /* @ts-ignore */
14475
+ appendTo = input('body', /* @ts-ignore */
14295
14476
  ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
14296
14477
  virtualScroll = input(false, { ...(ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
14297
14478
  virtualScrollItemSize = input(38, { ...(ngDevMode ? { debugName: "virtualScrollItemSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
@@ -14763,7 +14944,7 @@ class AutoCompleteComponent {
14763
14944
  } @else {
14764
14945
  <ul
14765
14946
  [id]="listboxId"
14766
- class="overflow-auto py-1"
14947
+ class="flex-1 min-h-0 max-h-64 overflow-auto py-1"
14767
14948
  [style.max-height]="scrollHeight()"
14768
14949
  role="listbox"
14769
14950
  [attr.aria-multiselectable]="multiple()"
@@ -15031,7 +15212,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
15031
15212
  } @else {
15032
15213
  <ul
15033
15214
  [id]="listboxId"
15034
- class="overflow-auto py-1"
15215
+ class="flex-1 min-h-0 max-h-64 overflow-auto py-1"
15035
15216
  [style.max-height]="scrollHeight()"
15036
15217
  role="listbox"
15037
15218
  [attr.aria-multiselectable]="multiple()"
@@ -15093,7 +15274,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
15093
15274
  </div>
15094
15275
  `,
15095
15276
  }]
15096
- }], ctorParameters: () => [], propDecorators: { anchorRef: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dropdown: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdown", required: false }] }], forceSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceSelection", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], completeOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "completeOnFocus", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], completeMethod: [{ type: i0.Output, args: ["completeMethod"] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], onUnselect: [{ type: i0.Output, args: ["onUnselect"] }], onDropdownClick: [{ type: i0.Output, args: ["onDropdownClick"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], focusEvent: [{ type: i0.Output, args: ["focusEvent"] }], blurEvent: [{ type: i0.Output, args: ["blurEvent"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
15277
+ }], propDecorators: { anchorRef: [{ type: i0.ViewChild, args: ['anchor', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dropdown: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdown", required: false }] }], forceSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceSelection", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], completeOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "completeOnFocus", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingIcon", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], scrollHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollHeight", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: false }] }], optionGroupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupLabel", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], completeMethod: [{ type: i0.Output, args: ["completeMethod"] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], onUnselect: [{ type: i0.Output, args: ["onUnselect"] }], onDropdownClick: [{ type: i0.Output, args: ["onDropdownClick"] }], onClear: [{ type: i0.Output, args: ["onClear"] }], focusEvent: [{ type: i0.Output, args: ["focusEvent"] }], blurEvent: [{ type: i0.Output, args: ["blurEvent"] }], onChange: [{ type: i0.Output, args: ["onChange"] }], onLazyLoad: [{ type: i0.Output, args: ["onLazyLoad"] }], itemRef: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], selectedItemRef: [{ type: i0.ContentChild, args: ['selectedItem', { isSignal: true }] }], loaderRef: [{ type: i0.ContentChild, args: ['loader', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
15097
15278
 
15098
15279
  function hexToRgb(hex) {
15099
15280
  const clean = hex.replace('#', '');
@@ -16037,15 +16218,18 @@ class SplitButtonComponent {
16037
16218
  _open = signal(false, /* @ts-ignore */
16038
16219
  ...(ngDevMode ? [{ debugName: "_open" }] : /* istanbul ignore next */ []));
16039
16220
  open = this._open.asReadonly();
16040
- _menuTop = signal(0, /* @ts-ignore */
16041
- ...(ngDevMode ? [{ debugName: "_menuTop" }] : /* istanbul ignore next */ []));
16042
- _menuLeft = signal(0, /* @ts-ignore */
16043
- ...(ngDevMode ? [{ debugName: "_menuLeft" }] : /* istanbul ignore next */ []));
16044
- menuTop = this._menuTop.asReadonly();
16045
- menuLeft = this._menuLeft.asReadonly();
16046
- constructor() {
16047
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => { this.positionMenu(); this.adjustMenuForViewport(); });
16048
- }
16221
+ _placement = overlayPosition({
16222
+ active: () => this.open() && this.appendTo() === 'body',
16223
+ anchor: () => this._group()?.nativeElement,
16224
+ panel: () => this._menuPanel()?.nativeElement,
16225
+ options: () => ({ align: 'end' }),
16226
+ });
16227
+ menuTop = computed(() => this._placement()?.top ?? 0, /* @ts-ignore */
16228
+ ...(ngDevMode ? [{ debugName: "menuTop" }] : /* istanbul ignore next */ []));
16229
+ menuLeft = computed(() => this._placement()?.left ?? 0, /* @ts-ignore */
16230
+ ...(ngDevMode ? [{ debugName: "menuLeft" }] : /* istanbul ignore next */ []));
16231
+ menuMaxHeight = computed(() => this._placement()?.maxHeight ?? null, /* @ts-ignore */
16232
+ ...(ngDevMode ? [{ debugName: "menuMaxHeight" }] : /* istanbul ignore next */ []));
16049
16233
  groupClass = computed(() => {
16050
16234
  const shape = this.rounded() ? 'rounded-full' : 'rounded-lg';
16051
16235
  const raisedCls = this.raised() ? 'shadow-md' : '';
@@ -16069,7 +16253,7 @@ class SplitButtonComponent {
16069
16253
  }, /* @ts-ignore */
16070
16254
  ...(ngDevMode ? [{ debugName: "dropdownClass" }] : /* istanbul ignore next */ []));
16071
16255
  menuPanelClass = computed(() => {
16072
- const base = 'z-50 min-w-[10rem] bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden';
16256
+ const base = 'z-50 flex flex-col min-w-[10rem] bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden';
16073
16257
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute right-0 top-full mt-1';
16074
16258
  return `${position} ${base} ${this.menuStyleClass()}`;
16075
16259
  }, /* @ts-ignore */
@@ -16148,10 +16332,6 @@ class SplitButtonComponent {
16148
16332
  if (this.open())
16149
16333
  return;
16150
16334
  this._open.set(true);
16151
- if (this.appendTo() === 'body') {
16152
- this.positionMenu();
16153
- queueMicrotask(() => this.adjustMenuForViewport());
16154
- }
16155
16335
  this.onShow.emit();
16156
16336
  }
16157
16337
  close(returnFocus) {
@@ -16172,29 +16352,6 @@ class SplitButtonComponent {
16172
16352
  const target = index === -1 ? items[items.length - 1] : items[index];
16173
16353
  target?.focus();
16174
16354
  }
16175
- positionMenu() {
16176
- const anchor = this._group()?.nativeElement;
16177
- if (!anchor || typeof window === 'undefined')
16178
- return;
16179
- const rect = anchor.getBoundingClientRect();
16180
- this._menuTop.set(rect.bottom + 4);
16181
- this._menuLeft.set(Math.max(8, rect.right - 160));
16182
- }
16183
- adjustMenuForViewport() {
16184
- const anchor = this._group()?.nativeElement;
16185
- const panel = this._menuPanel()?.nativeElement;
16186
- if (!anchor || !panel || typeof window === 'undefined')
16187
- return;
16188
- const anchorRect = anchor.getBoundingClientRect();
16189
- const panelRect = panel.getBoundingClientRect();
16190
- const gap = 4;
16191
- let left = anchorRect.right - panelRect.width;
16192
- left = Math.max(8, Math.min(left, window.innerWidth - panelRect.width - 8));
16193
- this._menuLeft.set(left);
16194
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
16195
- this._menuTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
16196
- }
16197
- }
16198
16355
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: SplitButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16199
16356
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: SplitButtonComponent, isStandalone: true, selector: "f-splitbutton", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, raised: { classPropertyName: "raised", publicName: "raised", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, outlined: { classPropertyName: "outlined", publicName: "outlined", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, iconPos: { classPropertyName: "iconPos", publicName: "iconPos", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, menuStyleClass: { classPropertyName: "menuStyleClass", publicName: "menuStyleClass", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, dropdownIcon: { classPropertyName: "dropdownIcon", publicName: "dropdownIcon", isSignal: true, isRequired: false, transformFunction: null }, expandAriaLabel: { classPropertyName: "expandAriaLabel", publicName: "expandAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClick: "onClick", onDropdownClick: "onDropdownClick", onShow: "onShow", onHide: "onHide" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "inline-flex" }, viewQueries: [{ propertyName: "_group", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "_dropdownBtn", first: true, predicate: ["dropdownButton"], descendants: true, isSignal: true }, { propertyName: "_menuPanel", first: true, predicate: ["menuPanel"], descendants: true, isSignal: true }], ngImport: i0, template: `
16200
16357
  <div class="relative inline-flex" [class.opacity-60]="disabled()" [class.pointer-events-none]="disabled()">
@@ -16234,11 +16391,12 @@ class SplitButtonComponent {
16234
16391
  [class]="menuPanelClass()"
16235
16392
  [style.top.px]="appendTo() === 'body' ? menuTop() : null"
16236
16393
  [style.left.px]="appendTo() === 'body' ? menuLeft() : null"
16394
+ [style.max-height.px]="appendTo() === 'body' ? menuMaxHeight() : null"
16237
16395
  role="menu"
16238
16396
  [attr.aria-label]="expandAriaLabel() || null"
16239
16397
  (keydown)="onMenuKeydown($event)"
16240
16398
  >
16241
- <ul class="py-1">
16399
+ <ul class="flex-1 min-h-0 overflow-auto py-1">
16242
16400
  @for (item of model(); track $index) {
16243
16401
  @if (item.separator) {
16244
16402
  <li role="separator" class="my-1 border-t border-(--f-content-border-color)"></li>
@@ -16316,11 +16474,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
16316
16474
  [class]="menuPanelClass()"
16317
16475
  [style.top.px]="appendTo() === 'body' ? menuTop() : null"
16318
16476
  [style.left.px]="appendTo() === 'body' ? menuLeft() : null"
16477
+ [style.max-height.px]="appendTo() === 'body' ? menuMaxHeight() : null"
16319
16478
  role="menu"
16320
16479
  [attr.aria-label]="expandAriaLabel() || null"
16321
16480
  (keydown)="onMenuKeydown($event)"
16322
16481
  >
16323
- <ul class="py-1">
16482
+ <ul class="flex-1 min-h-0 overflow-auto py-1">
16324
16483
  @for (item of model(); track $index) {
16325
16484
  @if (item.separator) {
16326
16485
  <li role="separator" class="my-1 border-t border-(--f-content-border-color)"></li>
@@ -16351,7 +16510,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
16351
16510
  </div>
16352
16511
  `,
16353
16512
  }]
16354
- }], ctorParameters: () => [], propDecorators: { _group: [{ type: i0.ViewChild, args: ['group', { isSignal: true }] }], _dropdownBtn: [{ type: i0.ViewChild, args: ['dropdownButton', { isSignal: true }] }], _menuPanel: [{ type: i0.ViewChild, args: ['menuPanel', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], raised: [{ type: i0.Input, args: [{ isSignal: true, alias: "raised", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], outlined: [{ type: i0.Input, args: [{ isSignal: true, alias: "outlined", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], iconPos: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPos", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], menuStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuStyleClass", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], expandAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandAriaLabel", required: false }] }], onClick: [{ type: i0.Output, args: ["onClick"] }], onDropdownClick: [{ type: i0.Output, args: ["onDropdownClick"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }] } });
16513
+ }], propDecorators: { _group: [{ type: i0.ViewChild, args: ['group', { isSignal: true }] }], _dropdownBtn: [{ type: i0.ViewChild, args: ['dropdownButton', { isSignal: true }] }], _menuPanel: [{ type: i0.ViewChild, args: ['menuPanel', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], raised: [{ type: i0.Input, args: [{ isSignal: true, alias: "raised", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], outlined: [{ type: i0.Input, args: [{ isSignal: true, alias: "outlined", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], iconPos: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPos", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], menuStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuStyleClass", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], expandAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandAriaLabel", required: false }] }], onClick: [{ type: i0.Output, args: ["onClick"] }], onDropdownClick: [{ type: i0.Output, args: ["onDropdownClick"] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }] } });
16355
16514
 
16356
16515
  let _uidCounter$2 = 0;
16357
16516
  function assignKey$2(node) {
@@ -16362,12 +16521,6 @@ function assignKey$2(node) {
16362
16521
  }
16363
16522
  class TreeSelectComponent {
16364
16523
  _el = inject(ElementRef);
16365
- constructor() {
16366
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => {
16367
- this.position();
16368
- this.adjustForViewport();
16369
- });
16370
- }
16371
16524
  options = input([], /* @ts-ignore */
16372
16525
  ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
16373
16526
  placeholder = input('Select', /* @ts-ignore */
@@ -16396,7 +16549,7 @@ class TreeSelectComponent {
16396
16549
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
16397
16550
  style = input(null, /* @ts-ignore */
16398
16551
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
16399
- appendTo = input('self', /* @ts-ignore */
16552
+ appendTo = input('body', /* @ts-ignore */
16400
16553
  ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
16401
16554
  hostClass = computed(() => `block w-full ${this.styleClass()}`, /* @ts-ignore */
16402
16555
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
@@ -16404,49 +16557,19 @@ class TreeSelectComponent {
16404
16557
  ...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
16405
16558
  panelRef = viewChild('panel', /* @ts-ignore */
16406
16559
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
16407
- _panelTop = signal(0, /* @ts-ignore */
16408
- ...(ngDevMode ? [{ debugName: "_panelTop" }] : /* istanbul ignore next */ []));
16409
- _panelLeft = signal(0, /* @ts-ignore */
16410
- ...(ngDevMode ? [{ debugName: "_panelLeft" }] : /* istanbul ignore next */ []));
16411
- _panelWidth = signal(0, /* @ts-ignore */
16412
- ...(ngDevMode ? [{ debugName: "_panelWidth" }] : /* istanbul ignore next */ []));
16560
+ _placement = overlayPosition({
16561
+ active: () => this.open() && this.appendTo() === 'body',
16562
+ anchor: () => this.triggerRef()?.nativeElement,
16563
+ panel: () => this.panelRef()?.nativeElement,
16564
+ options: () => ({ matchAnchorWidth: true }),
16565
+ });
16413
16566
  panelClass = computed(() => {
16414
16567
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute w-full mt-1';
16415
- return `${position} z-50 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
16568
+ return `${position} z-50 flex flex-col bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
16416
16569
  }, /* @ts-ignore */
16417
16570
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
16418
- panelStyle = computed(() => {
16419
- if (this.appendTo() !== 'body')
16420
- return {};
16421
- return {
16422
- top: `${this._panelTop()}px`,
16423
- left: `${this._panelLeft()}px`,
16424
- width: `${this._panelWidth()}px`,
16425
- };
16426
- }, /* @ts-ignore */
16571
+ panelStyle = computed(() => this.appendTo() === 'body' ? overlayPlacementStyle(this._placement()) : {}, /* @ts-ignore */
16427
16572
  ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
16428
- position() {
16429
- const anchorEl = this.triggerRef()?.nativeElement;
16430
- if (!anchorEl || typeof window === 'undefined')
16431
- return;
16432
- const rect = anchorEl.getBoundingClientRect();
16433
- this._panelTop.set(rect.bottom + 4);
16434
- this._panelLeft.set(Math.max(8, rect.left));
16435
- this._panelWidth.set(rect.width);
16436
- }
16437
- adjustForViewport() {
16438
- const panelEl = this.panelRef()?.nativeElement;
16439
- const anchorEl = this.triggerRef()?.nativeElement;
16440
- if (!panelEl || !anchorEl || typeof window === 'undefined')
16441
- return;
16442
- const anchorRect = anchorEl.getBoundingClientRect();
16443
- const panelRect = panelEl.getBoundingClientRect();
16444
- const gap = 4;
16445
- this._panelLeft.set(Math.max(8, Math.min(anchorRect.left, window.innerWidth - panelRect.width - 8)));
16446
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
16447
- this._panelTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
16448
- }
16449
- }
16450
16573
  _open = signal(false, /* @ts-ignore */
16451
16574
  ...(ngDevMode ? [{ debugName: "_open" }] : /* istanbul ignore next */ []));
16452
16575
  open = this._open.asReadonly();
@@ -16578,10 +16701,6 @@ class TreeSelectComponent {
16578
16701
  this._onTouched();
16579
16702
  return;
16580
16703
  }
16581
- if (this.appendTo() === 'body') {
16582
- this.position();
16583
- setTimeout(() => this.adjustForViewport(), 0);
16584
- }
16585
16704
  }
16586
16705
  onTriggerKeyDown(e) {
16587
16706
  if (this.disabled())
@@ -16879,7 +16998,7 @@ class TreeSelectComponent {
16879
16998
  </ng-template>
16880
16999
  </f-scroller>
16881
17000
  } @else {
16882
- <div class="max-h-64 overflow-auto py-1" role="tree">
17001
+ <div class="flex-1 min-h-0 max-h-64 overflow-auto py-1" role="tree">
16883
17002
  @for (row of visibleFlatNodes(); track row.key) {
16884
17003
  <ng-container
16885
17004
  [ngTemplateOutlet]="rowTpl"
@@ -17120,7 +17239,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
17120
17239
  </ng-template>
17121
17240
  </f-scroller>
17122
17241
  } @else {
17123
- <div class="max-h-64 overflow-auto py-1" role="tree">
17242
+ <div class="flex-1 min-h-0 max-h-64 overflow-auto py-1" role="tree">
17124
17243
  @for (row of visibleFlatNodes(); track row.key) {
17125
17244
  <ng-container
17126
17245
  [ngTemplateOutlet]="rowTpl"
@@ -17207,7 +17326,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
17207
17326
  </ng-template>
17208
17327
  `,
17209
17328
  }]
17210
- }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], propagateSelectionDown: [{ type: i0.Input, args: [{ isSignal: true, alias: "propagateSelectionDown", required: false }] }], propagateSelectionUp: [{ type: i0.Input, args: [{ isSignal: true, alias: "propagateSelectionUp", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], valueRef: [{ type: i0.ContentChild, args: ['value', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
17329
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterBy", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], propagateSelectionDown: [{ type: i0.Input, args: [{ isSignal: true, alias: "propagateSelectionDown", required: false }] }], propagateSelectionUp: [{ type: i0.Input, args: [{ isSignal: true, alias: "propagateSelectionUp", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], valueRef: [{ type: i0.ContentChild, args: ['value', { isSignal: true }] }], headerRef: [{ type: i0.ContentChild, args: ['header', { isSignal: true }] }], footerRef: [{ type: i0.ContentChild, args: ['footer', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
17211
17330
 
17212
17331
  class OverlayBadgeComponent {
17213
17332
  value = input('', /* @ts-ignore */
@@ -17840,15 +17959,13 @@ class MenuComponent {
17840
17959
  _visible = signal(false, /* @ts-ignore */
17841
17960
  ...(ngDevMode ? [{ debugName: "_visible" }] : /* istanbul ignore next */ []));
17842
17961
  visible = this._visible.asReadonly();
17843
- _top = signal(0, /* @ts-ignore */
17844
- ...(ngDevMode ? [{ debugName: "_top" }] : /* istanbul ignore next */ []));
17845
- _left = signal(0, /* @ts-ignore */
17846
- ...(ngDevMode ? [{ debugName: "_left" }] : /* istanbul ignore next */ []));
17962
+ _placement = overlayPosition({
17963
+ active: () => this.popup() && this.visible() && this.appendTo() === 'body',
17964
+ anchor: () => this._anchor,
17965
+ panel: () => this.containerRef()?.nativeElement,
17966
+ });
17847
17967
  _openedAt = 0;
17848
17968
  _anchor = null;
17849
- constructor() {
17850
- repositionOnScroll(() => this.popup() && this.visible() && this.appendTo() === 'body', () => { this.position(); this.adjustForViewport(); });
17851
- }
17852
17969
  fTemplates = contentChildren(FTemplateDirective, /* @ts-ignore */
17853
17970
  ...(ngDevMode ? [{ debugName: "fTemplates" }] : /* istanbul ignore next */ []));
17854
17971
  namedTemplate(name) {
@@ -17868,13 +17985,13 @@ class MenuComponent {
17868
17985
  return `w-full bg-(--f-content-background) border border-(--f-content-border-color) rounded-lg overflow-hidden ${this.styleClass()}`;
17869
17986
  }
17870
17987
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute mt-1';
17871
- return `${position} z-50 shadow-lg ${base} ${this.styleClass()}`;
17988
+ return `${position} z-50 flex flex-col shadow-lg ${base} ${this.styleClass()}`;
17872
17989
  }, /* @ts-ignore */
17873
17990
  ...(ngDevMode ? [{ debugName: "containerClass" }] : /* istanbul ignore next */ []));
17874
17991
  containerStyle = computed(() => {
17875
17992
  const style = this.style() ?? {};
17876
17993
  if (this.popup() && this.appendTo() === 'body') {
17877
- return { ...style, top: `${this._top()}px`, left: `${this._left()}px` };
17994
+ return { ...style, ...overlayPlacementStyle(this._placement()) };
17878
17995
  }
17879
17996
  return style;
17880
17997
  }, /* @ts-ignore */
@@ -17888,13 +18005,8 @@ class MenuComponent {
17888
18005
  show(event) {
17889
18006
  this._anchor = event?.currentTarget ?? null;
17890
18007
  this._openedAt = Date.now();
17891
- if (this.appendTo() === 'body')
17892
- this.position();
17893
18008
  this._visible.set(true);
17894
18009
  this.onShow.emit();
17895
- if (this.appendTo() === 'body') {
17896
- setTimeout(() => this.adjustForViewport(), 0);
17897
- }
17898
18010
  }
17899
18011
  hide() {
17900
18012
  if (!this._visible())
@@ -17902,27 +18014,6 @@ class MenuComponent {
17902
18014
  this._visible.set(false);
17903
18015
  this.onHide.emit();
17904
18016
  }
17905
- position() {
17906
- if (!this._anchor || typeof window === 'undefined')
17907
- return;
17908
- const rect = this._anchor.getBoundingClientRect();
17909
- this._top.set(rect.bottom + 4);
17910
- this._left.set(rect.left);
17911
- }
17912
- adjustForViewport() {
17913
- const el = this.containerRef()?.nativeElement;
17914
- if (!el || !this._anchor || typeof window === 'undefined')
17915
- return;
17916
- const anchorRect = this._anchor.getBoundingClientRect();
17917
- const panelRect = el.getBoundingClientRect();
17918
- const gap = 4;
17919
- let left = anchorRect.left;
17920
- left = Math.max(8, Math.min(left, window.innerWidth - panelRect.width - 8));
17921
- this._left.set(left);
17922
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
17923
- this._top.set(Math.max(8, anchorRect.top - panelRect.height - gap));
17924
- }
17925
- }
17926
18017
  onDocumentClick(e) {
17927
18018
  if (Date.now() - this._openedAt < 50)
17928
18019
  return;
@@ -18058,7 +18149,7 @@ class MenuComponent {
18058
18149
  <ng-container [ngTemplateOutlet]="startTpl()" />
18059
18150
  </div>
18060
18151
  }
18061
- <ul class="py-1" role="menu" (keydown)="onKeydown($event)">
18152
+ <ul class="flex-1 min-h-0 overflow-auto py-1" role="menu" (keydown)="onKeydown($event)">
18062
18153
  @if (hasGroups()) {
18063
18154
  @for (group of model(); track $index) {
18064
18155
  @if (group.separator) {
@@ -18174,7 +18265,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
18174
18265
  <ng-container [ngTemplateOutlet]="startTpl()" />
18175
18266
  </div>
18176
18267
  }
18177
- <ul class="py-1" role="menu" (keydown)="onKeydown($event)">
18268
+ <ul class="flex-1 min-h-0 overflow-auto py-1" role="menu" (keydown)="onKeydown($event)">
18178
18269
  @if (hasGroups()) {
18179
18270
  @for (group of model(); track $index) {
18180
18271
  @if (group.separator) {
@@ -18206,7 +18297,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
18206
18297
  }
18207
18298
  `,
18208
18299
  }]
18209
- }], ctorParameters: () => [], propDecorators: { containerRef: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], popup: [{ type: i0.Input, args: [{ isSignal: true, alias: "popup", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
18300
+ }], propDecorators: { containerRef: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], popup: [{ type: i0.Input, args: [{ isSignal: true, alias: "popup", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], onShow: [{ type: i0.Output, args: ["onShow"] }], onHide: [{ type: i0.Output, args: ["onHide"] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
18210
18301
 
18211
18302
  const SUBMENU_ESTIMATED_WIDTH$2 = 192;
18212
18303
  class MenubarComponent {
@@ -18827,12 +18918,17 @@ class TieredMenuComponent {
18827
18918
  _visible = signal(false, /* @ts-ignore */
18828
18919
  ...(ngDevMode ? [{ debugName: "_visible" }] : /* istanbul ignore next */ []));
18829
18920
  visible = this._visible.asReadonly();
18830
- _top = signal(0, /* @ts-ignore */
18831
- ...(ngDevMode ? [{ debugName: "_top" }] : /* istanbul ignore next */ []));
18832
- top = this._top.asReadonly();
18833
- _left = signal(0, /* @ts-ignore */
18834
- ...(ngDevMode ? [{ debugName: "_left" }] : /* istanbul ignore next */ []));
18835
- left = this._left.asReadonly();
18921
+ _placement = overlayPosition({
18922
+ active: () => this.popup() && this.visible(),
18923
+ anchor: () => this._anchor,
18924
+ panel: () => this.containerRef()?.nativeElement,
18925
+ // Submenus fly out of the container, so it must stay overflow-visible.
18926
+ options: () => ({ clampHeight: false }),
18927
+ });
18928
+ top = computed(() => this._placement()?.top ?? 0, /* @ts-ignore */
18929
+ ...(ngDevMode ? [{ debugName: "top" }] : /* istanbul ignore next */ []));
18930
+ left = computed(() => this._placement()?.left ?? 0, /* @ts-ignore */
18931
+ ...(ngDevMode ? [{ debugName: "left" }] : /* istanbul ignore next */ []));
18836
18932
  _openedAt = 0;
18837
18933
  _anchor = null;
18838
18934
  _activeItemPath = signal([], /* @ts-ignore */
@@ -18869,11 +18965,8 @@ class TieredMenuComponent {
18869
18965
  this._openedAt = Date.now();
18870
18966
  this._activeItemPath.set([]);
18871
18967
  this._flipByLevel.set({});
18872
- if (this._anchor)
18873
- this.position();
18874
18968
  this._visible.set(true);
18875
18969
  this.onShow.emit();
18876
- setTimeout(() => this.adjustForViewport(), 0);
18877
18970
  }
18878
18971
  hide() {
18879
18972
  if (!this._visible())
@@ -18882,27 +18975,6 @@ class TieredMenuComponent {
18882
18975
  this._activeItemPath.set([]);
18883
18976
  this.onHide.emit();
18884
18977
  }
18885
- position() {
18886
- if (!this._anchor || typeof window === 'undefined')
18887
- return;
18888
- const rect = this._anchor.getBoundingClientRect();
18889
- this._top.set(rect.bottom + 4);
18890
- this._left.set(rect.left);
18891
- }
18892
- adjustForViewport() {
18893
- const el = this.containerRef()?.nativeElement;
18894
- if (!el || !this._anchor || typeof window === 'undefined')
18895
- return;
18896
- const anchorRect = this._anchor.getBoundingClientRect();
18897
- const panelRect = el.getBoundingClientRect();
18898
- const gap = 4;
18899
- let left = anchorRect.left;
18900
- left = Math.max(8, Math.min(left, window.innerWidth - panelRect.width - 8));
18901
- this._left.set(left);
18902
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
18903
- this._top.set(Math.max(8, anchorRect.top - panelRect.height - gap));
18904
- }
18905
- }
18906
18978
  isItemActive(item, level) {
18907
18979
  return this._activeItemPath()[level] === item;
18908
18980
  }
@@ -20678,8 +20750,12 @@ class SpeedDialComponent {
20678
20750
  onHide = output();
20679
20751
  onVisibleChange = output();
20680
20752
  _el = inject(ElementRef);
20753
+ _overlayStack = inject(OverlayStackService);
20681
20754
  _toggleBtn = viewChild('toggleButton', /* @ts-ignore */
20682
20755
  ...(ngDevMode ? [{ debugName: "_toggleBtn" }] : /* istanbul ignore next */ []));
20756
+ _maskZIndex = signal(null, /* @ts-ignore */
20757
+ ...(ngDevMode ? [{ debugName: "_maskZIndex" }] : /* istanbul ignore next */ []));
20758
+ maskZIndex = this._maskZIndex.asReadonly();
20683
20759
  hostClass = computed(() => `relative inline-flex ${this.styleClass()}`, /* @ts-ignore */
20684
20760
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
20685
20761
  effectiveRadius = computed(() => this.radius() || this.model().length * 20, /* @ts-ignore */
@@ -20749,6 +20825,8 @@ class SpeedDialComponent {
20749
20825
  if (this.visible() || this.disabled())
20750
20826
  return;
20751
20827
  this.visible.set(true);
20828
+ if (this.mask())
20829
+ this._maskZIndex.set(this._overlayStack.open());
20752
20830
  this.onVisibleChange.emit(true);
20753
20831
  this.onShow.emit();
20754
20832
  }
@@ -20756,6 +20834,7 @@ class SpeedDialComponent {
20756
20834
  if (!this.visible())
20757
20835
  return;
20758
20836
  this.visible.set(false);
20837
+ this._maskZIndex.set(null);
20759
20838
  this.onVisibleChange.emit(false);
20760
20839
  this.onHide.emit();
20761
20840
  }
@@ -20818,7 +20897,8 @@ class SpeedDialComponent {
20818
20897
  </div>
20819
20898
  @if (mask() && visible()) {
20820
20899
  <div
20821
- class="fixed inset-0 z-999 bg-(--f-mask-background)"
20900
+ class="fixed inset-0 bg-(--f-mask-background)"
20901
+ [style.z-index]="maskZIndex()"
20822
20902
  (click)="hide()"
20823
20903
  ></div>
20824
20904
  }
@@ -20878,7 +20958,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
20878
20958
  </div>
20879
20959
  @if (mask() && visible()) {
20880
20960
  <div
20881
- class="fixed inset-0 z-999 bg-(--f-mask-background)"
20961
+ class="fixed inset-0 bg-(--f-mask-background)"
20962
+ [style.z-index]="maskZIndex()"
20882
20963
  (click)="hide()"
20883
20964
  ></div>
20884
20965
  }
@@ -21857,12 +21938,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
21857
21938
 
21858
21939
  class CascadeSelectComponent {
21859
21940
  _el = inject(ElementRef);
21860
- constructor() {
21861
- repositionOnScroll(() => this.open() && this.appendTo() === 'body', () => {
21862
- this.position();
21863
- this.adjustForViewport();
21864
- });
21865
- }
21866
21941
  options = input([], /* @ts-ignore */
21867
21942
  ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
21868
21943
  optionLabel = input('label', /* @ts-ignore */
@@ -21889,7 +21964,7 @@ class CascadeSelectComponent {
21889
21964
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
21890
21965
  style = input(null, /* @ts-ignore */
21891
21966
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
21892
- appendTo = input('self', /* @ts-ignore */
21967
+ appendTo = input('body', /* @ts-ignore */
21893
21968
  ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
21894
21969
  hostClass = computed(() => `block w-full ${this.styleClass()}`, /* @ts-ignore */
21895
21970
  ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
@@ -21897,42 +21972,18 @@ class CascadeSelectComponent {
21897
21972
  ...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
21898
21973
  panelRef = viewChild('panel', /* @ts-ignore */
21899
21974
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
21900
- _panelTop = signal(0, /* @ts-ignore */
21901
- ...(ngDevMode ? [{ debugName: "_panelTop" }] : /* istanbul ignore next */ []));
21902
- _panelLeft = signal(0, /* @ts-ignore */
21903
- ...(ngDevMode ? [{ debugName: "_panelLeft" }] : /* istanbul ignore next */ []));
21975
+ _placement = overlayPosition({
21976
+ active: () => this.open() && this.appendTo() === 'body',
21977
+ anchor: () => this.triggerRef()?.nativeElement,
21978
+ panel: () => this.panelRef()?.nativeElement,
21979
+ });
21904
21980
  panelClass = computed(() => {
21905
21981
  const position = this.appendTo() === 'body' ? 'fixed' : 'absolute mt-1';
21906
21982
  return `${position} z-50 flex bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay overflow-hidden`;
21907
21983
  }, /* @ts-ignore */
21908
21984
  ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
21909
- panelStyle = computed(() => {
21910
- if (this.appendTo() !== 'body')
21911
- return {};
21912
- return { top: `${this._panelTop()}px`, left: `${this._panelLeft()}px` };
21913
- }, /* @ts-ignore */
21985
+ panelStyle = computed(() => this.appendTo() === 'body' ? overlayPlacementStyle(this._placement()) : {}, /* @ts-ignore */
21914
21986
  ...(ngDevMode ? [{ debugName: "panelStyle" }] : /* istanbul ignore next */ []));
21915
- position() {
21916
- const anchorEl = this.triggerRef()?.nativeElement;
21917
- if (!anchorEl || typeof window === 'undefined')
21918
- return;
21919
- const rect = anchorEl.getBoundingClientRect();
21920
- this._panelTop.set(rect.bottom + 4);
21921
- this._panelLeft.set(Math.max(8, rect.left));
21922
- }
21923
- adjustForViewport() {
21924
- const panelEl = this.panelRef()?.nativeElement;
21925
- const anchorEl = this.triggerRef()?.nativeElement;
21926
- if (!panelEl || !anchorEl || typeof window === 'undefined')
21927
- return;
21928
- const anchorRect = anchorEl.getBoundingClientRect();
21929
- const panelRect = panelEl.getBoundingClientRect();
21930
- const gap = 4;
21931
- this._panelLeft.set(Math.max(8, Math.min(anchorRect.left, window.innerWidth - panelRect.width - 8)));
21932
- if (anchorRect.bottom + panelRect.height + gap > window.innerHeight) {
21933
- this._panelTop.set(Math.max(8, anchorRect.top - panelRect.height - gap));
21934
- }
21935
- }
21936
21987
  _open = signal(false, /* @ts-ignore */
21937
21988
  ...(ngDevMode ? [{ debugName: "_open" }] : /* istanbul ignore next */ []));
21938
21989
  open = this._open.asReadonly();
@@ -22040,10 +22091,6 @@ class CascadeSelectComponent {
22040
22091
  this._activePath.set([]);
22041
22092
  this._focusedPath.set([]);
22042
22093
  }
22043
- if (this.appendTo() === 'body') {
22044
- this.position();
22045
- setTimeout(() => this.adjustForViewport(), 0);
22046
- }
22047
22094
  }
22048
22095
  closePanel() {
22049
22096
  this._open.set(false);
@@ -22516,7 +22563,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22516
22563
  </div>
22517
22564
  `,
22518
22565
  }]
22519
- }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionChildren", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], valueRef: [{ type: i0.ContentChild, args: ['value', { isSignal: true }] }], optionRef: [{ type: i0.ContentChild, args: ['option', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
22566
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], optionChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionChildren", required: false }] }], optionGroupChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionGroupChildren", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], dropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownIcon", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], valueRef: [{ type: i0.ContentChild, args: ['value', { isSignal: true }] }], optionRef: [{ type: i0.ContentChild, args: ['option', { isSignal: true }] }], groupRef: [{ type: i0.ContentChild, args: ['group', { isSignal: true }] }], emptyRef: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], fTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FTemplateDirective), { isSignal: true }] }] } });
22520
22567
 
22521
22568
  const PRESETS = {
22522
22569
  pint: /\d/,
@@ -22570,6 +22617,7 @@ class ConfirmPopupComponent {
22570
22617
  headerId = `f-confirmpopup-header-${++ConfirmPopupComponent.idCounter}`;
22571
22618
  descId = `f-confirmpopup-desc-${ConfirmPopupComponent.idCounter}`;
22572
22619
  confirmationService = inject(ConfirmationService);
22620
+ _overlayStack = inject(OverlayStackService);
22573
22621
  key = input(undefined, /* @ts-ignore */
22574
22622
  ...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
22575
22623
  acceptLabel = input('', /* @ts-ignore */
@@ -22592,12 +22640,20 @@ class ConfirmPopupComponent {
22592
22640
  ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
22593
22641
  style = input(null, /* @ts-ignore */
22594
22642
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
22595
- _top = signal(0, /* @ts-ignore */
22596
- ...(ngDevMode ? [{ debugName: "_top" }] : /* istanbul ignore next */ []));
22597
- top = this._top.asReadonly();
22598
- _left = signal(0, /* @ts-ignore */
22599
- ...(ngDevMode ? [{ debugName: "_left" }] : /* istanbul ignore next */ []));
22600
- left = this._left.asReadonly();
22643
+ _placement = overlayPosition({
22644
+ active: () => !!this.activeConfirmation()?.target,
22645
+ anchor: () => this.activeConfirmation()?.target,
22646
+ panel: () => this.panelRef()?.nativeElement,
22647
+ // A confirm popup is short; clamping it could hide the action buttons.
22648
+ options: () => ({ gap: 8, clampHeight: false }),
22649
+ });
22650
+ top = computed(() => this._placement()?.top ?? 0, /* @ts-ignore */
22651
+ ...(ngDevMode ? [{ debugName: "top" }] : /* istanbul ignore next */ []));
22652
+ left = computed(() => this._placement()?.left ?? 0, /* @ts-ignore */
22653
+ ...(ngDevMode ? [{ debugName: "left" }] : /* istanbul ignore next */ []));
22654
+ _zIndex = signal(null, /* @ts-ignore */
22655
+ ...(ngDevMode ? [{ debugName: "_zIndex" }] : /* istanbul ignore next */ []));
22656
+ zIndex = this._zIndex.asReadonly();
22601
22657
  panelRef = viewChild('panel', /* @ts-ignore */
22602
22658
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
22603
22659
  activeConfirmation = computed(() => {
@@ -22611,10 +22667,10 @@ class ConfirmPopupComponent {
22611
22667
  effect(() => {
22612
22668
  const c = this.activeConfirmation();
22613
22669
  if (c?.target) {
22614
- this.position(c.target);
22615
- setTimeout(() => {
22616
- this.adjustForViewport(c.target);
22617
- }, 0);
22670
+ this._zIndex.set(this._overlayStack.open());
22671
+ }
22672
+ else {
22673
+ this._zIndex.set(null);
22618
22674
  }
22619
22675
  });
22620
22676
  if (typeof window !== 'undefined') {
@@ -22641,28 +22697,6 @@ class ConfirmPopupComponent {
22641
22697
  resolvedRejectIcon(c) {
22642
22698
  return c.rejectIcon || this.rejectIcon();
22643
22699
  }
22644
- position(target) {
22645
- const rect = target.getBoundingClientRect?.();
22646
- if (!rect)
22647
- return;
22648
- const gap = 8;
22649
- let left = rect.left;
22650
- if (typeof window !== 'undefined')
22651
- left = Math.min(left, window.innerWidth - 288 - 8);
22652
- this._top.set(rect.bottom + gap);
22653
- this._left.set(Math.max(8, left));
22654
- }
22655
- adjustForViewport(target) {
22656
- const panelEl = this.panelRef()?.nativeElement;
22657
- const rect = target.getBoundingClientRect?.();
22658
- if (!panelEl || !rect || typeof window === 'undefined')
22659
- return;
22660
- const gap = 8;
22661
- const panelRect = panelEl.getBoundingClientRect();
22662
- if (rect.bottom + panelRect.height + gap > window.innerHeight) {
22663
- this._top.set(Math.max(8, rect.top - panelRect.height - gap));
22664
- }
22665
- }
22666
22700
  onEscape() {
22667
22701
  const c = this.activeConfirmation();
22668
22702
  const closeOnEscape = c?.closeOnEscape ?? this.closeOnEscape();
@@ -22717,11 +22751,12 @@ class ConfirmPopupComponent {
22717
22751
  @if (c.target) {
22718
22752
  <div
22719
22753
  #panel
22720
- class="confirmpopup-panel fixed z-50 w-72 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay p-4"
22754
+ class="confirmpopup-panel fixed w-72 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay p-4"
22721
22755
  [class]="styleClass()"
22722
22756
  [style]="style()"
22723
22757
  [style.top.px]="top()"
22724
22758
  [style.left.px]="left()"
22759
+ [style.z-index]="zIndex()"
22725
22760
  role="alertdialog"
22726
22761
  [attr.aria-labelledby]="c.header ? headerId : null"
22727
22762
  [attr.aria-describedby]="c.message ? descId : null"
@@ -22778,11 +22813,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22778
22813
  @if (c.target) {
22779
22814
  <div
22780
22815
  #panel
22781
- class="confirmpopup-panel fixed z-50 w-72 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay p-4"
22816
+ class="confirmpopup-panel fixed w-72 bg-(--f-overlay-popover-background) border border-(--f-content-border-color) f-overlay p-4"
22782
22817
  [class]="styleClass()"
22783
22818
  [style]="style()"
22784
22819
  [style.top.px]="top()"
22785
22820
  [style.left.px]="left()"
22821
+ [style.z-index]="zIndex()"
22786
22822
  role="alertdialog"
22787
22823
  [attr.aria-labelledby]="c.header ? headerId : null"
22788
22824
  [attr.aria-describedby]="c.message ? descId : null"
@@ -22833,10 +22869,14 @@ class DynamicDialogRef {
22833
22869
  _closeFn;
22834
22870
  _onClose = new Subject();
22835
22871
  onClose = this._onClose.asObservable();
22872
+ _closed = false;
22836
22873
  constructor(_closeFn) {
22837
22874
  this._closeFn = _closeFn;
22838
22875
  }
22839
22876
  close(result) {
22877
+ if (this._closed)
22878
+ return;
22879
+ this._closed = true;
22840
22880
  this._onClose.next(result);
22841
22881
  this._onClose.complete();
22842
22882
  this._closeFn(result);
@@ -22846,17 +22886,24 @@ const DYNAMIC_DIALOG_DATA = new InjectionToken('DYNAMIC_DIALOG_DATA');
22846
22886
  const DYNAMIC_DIALOG_REF = new InjectionToken('DYNAMIC_DIALOG_REF');
22847
22887
  class DynamicDialogService {
22848
22888
  static idCounter = 0;
22889
+ _overlayStack = inject(OverlayStackService);
22849
22890
  _states = signal([], /* @ts-ignore */
22850
22891
  ...(ngDevMode ? [{ debugName: "_states" }] : /* istanbul ignore next */ []));
22851
22892
  states = this._states.asReadonly();
22852
22893
  open(component, config = {}) {
22853
22894
  const id = ++DynamicDialogService.idCounter;
22895
+ const zIndex = this._overlayStack.open();
22896
+ const isModal = config.modal !== false;
22897
+ if (isModal)
22898
+ this._overlayStack.lockScroll();
22854
22899
  const ref = new DynamicDialogRef(() => {
22900
+ if (isModal)
22901
+ this._overlayStack.unlockScroll();
22855
22902
  this._states.update((list) => list.filter((s) => s.id !== id));
22856
22903
  });
22857
22904
  this._states.update((list) => [
22858
22905
  ...list,
22859
- { id, component, config, ref: ref },
22906
+ { id, component, config, ref: ref, zIndex },
22860
22907
  ]);
22861
22908
  return ref;
22862
22909
  }
@@ -22874,7 +22921,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
22874
22921
  class DynamicDialogComponent {
22875
22922
  dialogService = inject(DynamicDialogService);
22876
22923
  _parentInjector = inject(Injector);
22877
- _doc = inject(DOCUMENT);
22878
22924
  injectorCache = new Map();
22879
22925
  constructor() {
22880
22926
  effect(() => {
@@ -22884,13 +22930,6 @@ class DynamicDialogComponent {
22884
22930
  this.injectorCache.delete(id);
22885
22931
  }
22886
22932
  });
22887
- effect(() => {
22888
- const anyModal = this.dialogService.states().some((s) => s.config.modal !== false);
22889
- this._doc.body.style.overflow = anyModal ? 'hidden' : '';
22890
- });
22891
- inject(DestroyRef).onDestroy(() => {
22892
- this._doc.body.style.overflow = '';
22893
- });
22894
22933
  }
22895
22934
  childInjector(state) {
22896
22935
  let injector = this.injectorCache.get(state.id);
@@ -22929,8 +22968,8 @@ class DynamicDialogComponent {
22929
22968
  }
22930
22969
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DynamicDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22931
22970
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: DynamicDialogComponent, isStandalone: true, selector: "f-dynamicdialog", host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "block" }, ngImport: i0, template: `
22932
- @for (s of dialogService.states(); track s.id; let i = $index) {
22933
- <div class="fixed inset-0 flex items-center justify-center p-4" [class.pointer-events-none]="s.config.modal === false" [style.z-index]="40 + i * 2">
22971
+ @for (s of dialogService.states(); track s.id) {
22972
+ <div class="fixed inset-0 flex items-center justify-center p-4" [class.pointer-events-none]="s.config.modal === false" [style.z-index]="s.zIndex">
22934
22973
  @if (s.config.modal !== false) {
22935
22974
  <div
22936
22975
  class="dynamicdialog-backdrop absolute inset-0 bg-black/50 backdrop-blur-[2px]"
@@ -22975,8 +23014,8 @@ class DynamicDialogComponent {
22975
23014
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: DynamicDialogComponent, decorators: [{
22976
23015
  type: Component,
22977
23016
  args: [{ selector: 'f-dynamicdialog', imports: [NgComponentOutlet, UiIconComponent], host: { class: 'block', '(document:keydown.escape)': 'onEscape()' }, template: `
22978
- @for (s of dialogService.states(); track s.id; let i = $index) {
22979
- <div class="fixed inset-0 flex items-center justify-center p-4" [class.pointer-events-none]="s.config.modal === false" [style.z-index]="40 + i * 2">
23017
+ @for (s of dialogService.states(); track s.id) {
23018
+ <div class="fixed inset-0 flex items-center justify-center p-4" [class.pointer-events-none]="s.config.modal === false" [style.z-index]="s.zIndex">
22980
23019
  @if (s.config.modal !== false) {
22981
23020
  <div
22982
23021
  class="dynamicdialog-backdrop absolute inset-0 bg-black/50 backdrop-blur-[2px]"
@@ -27138,5 +27177,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
27138
27177
  * Generated bundle index. Do not edit.
27139
27178
  */
27140
27179
 
27141
- export { AURA_PRESET, AccordionComponent, AccordionContentComponent, AccordionContext, AccordionHeaderComponent, AccordionPanelComponent, AnimateOnScrollDirective, AutoCompleteComponent, AutoFocusDirective, AvatarComponent, AvatarGroupComponent, BadgeComponent, BlockUiComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CarouselComponent, CascadeSelectComponent, ChartComponent, CheckboxComponent, ChipComponent, ColorPickerComponent, ConfirmDialog, ConfirmPopupComponent, ConfirmationService, ContextMenuComponent, DYNAMIC_DIALOG_DATA, DYNAMIC_DIALOG_REF, DataViewComponent, DatePickerComponent, DialogComponent, DividerComponent, DockComponent, DrawerComponent, DynamicDialogComponent, DynamicDialogRef, DynamicDialogService, EditorComponent, FButtonDirective, FTemplateDirective, FieldsetComponent, FileUploadComponent, FloatLabelComponent, FluidComponent, GalleriaComponent, IconFieldComponent, IftaLabelComponent, ImageCompareComponent, ImageComponent, InplaceComponent, InputGroupAddonComponent, InputGroupComponent, InputIconComponent, InputMaskDirective, InputNumberComponent, InputOtpComponent, InputPasswordDirective, InputTextDirective, KeyFilterDirective, KnobComponent, LARA_PRESET, ListboxComponent, MegaMenuComponent, MenuComponent, MenubarComponent, MessageComponent, MessageService, MeterGroupComponent, MultiSelectComponent, NOIR_PRIMARY, NORA_PRESET, NgUIConfig, OrderListComponent, OrganizationChartComponent, OverlayBadgeComponent, PRESETS$1 as PRESETS, PRESET_NAMES, PRIMARY_PALETTES, PaginatorComponent, PanelComponent, PanelMenuComponent, PasswordComponent, PickListComponent, PopoverComponent, ProgressSpinnerComponent, ProgressbarComponent, RadioButtonComponent, RatingComponent, RippleDirective, SURFACE_PALETTES, ScrollPanelComponent, ScrollTopComponent, ScrollerComponent, SelectButtonComponent, SelectComponent, SkeletonComponent, SliderComponent, SortIconComponent, SortableColumnDirective, SpeedDialComponent, SplitButtonComponent, SplitterComponent, SplitterPanelComponent, StepsComponent, StyleClassDirective, TabComponent, TabListComponent, TabPanelComponent, TabPanelsComponent, TableComponent, TabsComponent, TabsContext, TagComponent, TerminalComponent, TextareaDirective, TieredMenuComponent, TimelineComponent, ToastComponent, ToggleButtonComponent, ToggleSwitchComponent, ToolbarComponent, TooltipDirective, TreeComponent, TreeSelectComponent, TreeTableComponent, TreeTableService, TreeTableTogglerComponent, UiIconComponent, applyDarkSemantics, applyLightSemantics, applyPreset, applyPrimaryPalette, applySurfacePalette, applyTheme, buildBootstrapPreset, provideNgUI };
27180
+ export { AURA_PRESET, AccordionComponent, AccordionContentComponent, AccordionContext, AccordionHeaderComponent, AccordionPanelComponent, AnimateOnScrollDirective, AutoCompleteComponent, AutoFocusDirective, AvatarComponent, AvatarGroupComponent, BadgeComponent, BlockUiComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CardComponent, CarouselComponent, CascadeSelectComponent, ChartComponent, CheckboxComponent, ChipComponent, ColorPickerComponent, ConfirmDialog, ConfirmPopupComponent, ConfirmationService, ContextMenuComponent, DYNAMIC_DIALOG_DATA, DYNAMIC_DIALOG_REF, DataViewComponent, DatePickerComponent, DialogComponent, DividerComponent, DockComponent, DrawerComponent, DynamicDialogComponent, DynamicDialogRef, DynamicDialogService, EditorComponent, FButtonDirective, FTemplateDirective, FieldsetComponent, FileUploadComponent, FloatLabelComponent, FluidComponent, GalleriaComponent, IconFieldComponent, IftaLabelComponent, ImageCompareComponent, ImageComponent, InplaceComponent, InputGroupAddonComponent, InputGroupComponent, InputIconComponent, InputMaskDirective, InputNumberComponent, InputOtpComponent, InputPasswordDirective, InputTextDirective, KeyFilterDirective, KnobComponent, LARA_PRESET, ListboxComponent, MegaMenuComponent, MenuComponent, MenubarComponent, MessageComponent, MessageService, MeterGroupComponent, MultiSelectComponent, NOIR_PRIMARY, NORA_PRESET, NgUIConfig, OrderListComponent, OrganizationChartComponent, OverlayBadgeComponent, OverlayStackService, PRESETS$1 as PRESETS, PRESET_NAMES, PRIMARY_PALETTES, PaginatorComponent, PanelComponent, PanelMenuComponent, PasswordComponent, PickListComponent, PopoverComponent, ProgressSpinnerComponent, ProgressbarComponent, RadioButtonComponent, RatingComponent, RippleDirective, SURFACE_PALETTES, ScrollPanelComponent, ScrollTopComponent, ScrollerComponent, SelectButtonComponent, SelectComponent, SkeletonComponent, SliderComponent, SortIconComponent, SortableColumnDirective, SpeedDialComponent, SplitButtonComponent, SplitterComponent, SplitterPanelComponent, StepsComponent, StyleClassDirective, TabComponent, TabListComponent, TabPanelComponent, TabPanelsComponent, TableComponent, TabsComponent, TabsContext, TagComponent, TerminalComponent, TextareaDirective, TieredMenuComponent, TimelineComponent, ToastComponent, ToggleButtonComponent, ToggleSwitchComponent, ToolbarComponent, TooltipDirective, TreeComponent, TreeSelectComponent, TreeTableComponent, TreeTableService, TreeTableTogglerComponent, UiIconComponent, applyDarkSemantics, applyLightSemantics, applyPreset, applyPrimaryPalette, applySurfacePalette, applyTheme, attachOverlayPosition, buildBootstrapPreset, computeOverlayPlacement, overlayPlacementStyle, overlayPosition, provideNgUI };
27142
27181
  //# sourceMappingURL=flusys-ng-ui.mjs.map