@agorapulse/ui-components 22.0.30 → 22.0.32

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.
@@ -0,0 +1,451 @@
1
+ import { Overlay } from '@angular/cdk/overlay';
2
+ import { TemplatePortal, ComponentPortal } from '@angular/cdk/portal';
3
+ import { inject, ElementRef, ViewContainerRef, signal, DestroyRef, TemplateRef } from '@angular/core';
4
+ import { offset, flip, shift, computePosition, autoUpdate } from '@floating-ui/dom';
5
+ import { filter, take } from 'rxjs/operators';
6
+
7
+ /**
8
+ * The placement derived when `placement` is unset. Reads the **configured** anchor mode, not the
9
+ * resolved one: a keyboard opening falls back to the trigger, and if the alignment followed, the
10
+ * component would change shape between mouse and keyboard.
11
+ */
12
+ function defaultPlacementFor(anchor) {
13
+ return anchor === 'trigger' ? 'bottom-start' : 'bottom';
14
+ }
15
+ /**
16
+ * `'pointer'` is a hybrid whose zero dimension is the **cross-axis** one; a lateral panel built
17
+ * from a fully point-like anchor would sit inside its own trigger. `'pointer-free'` is the point
18
+ * itself. Both fall back to the trigger when there is no click.
19
+ *
20
+ * @param vertical The opening axis. Invariant under the flip, which only swaps the main axis.
21
+ */
22
+ function resolveAnchorRect(anchor, triggerRect, vertical, clickPoint) {
23
+ if (anchor === 'trigger' || !clickPoint) {
24
+ return triggerRect;
25
+ }
26
+ if (anchor === 'pointer-free') {
27
+ return { x: clickPoint.x, y: clickPoint.y, width: 0, height: 0 };
28
+ }
29
+ return vertical
30
+ ? { x: clickPoint.x, y: triggerRect.y, width: 0, height: triggerRect.height }
31
+ : { x: triggerRect.x, y: clickPoint.y, width: triggerRect.width, height: 0 };
32
+ }
33
+ /**
34
+ * A keyboard-synthesised click carries `detail: 0` and `clientX: 0`, which without this guard puts
35
+ * the pointer anchor in the screen's top-left corner.
36
+ */
37
+ function clickPointOf(event) {
38
+ return event && event.detail > 0 ? { x: event.clientX, y: event.clientY } : undefined;
39
+ }
40
+ /**
41
+ * A ratio names a place on the trigger where a viewport coordinate names a place in the window,
42
+ * which is what makes a pointer anchor survive scrolling, resizing and shifting. `undefined` for a
43
+ * trigger with no area, so the anchor falls back to the element rather than divide by zero.
44
+ */
45
+ function resolveClickRatio(triggerRect, clickPoint) {
46
+ if (!clickPoint || triggerRect.width <= 0 || triggerRect.height <= 0) {
47
+ return undefined;
48
+ }
49
+ return {
50
+ x: (clickPoint.x - triggerRect.x) / triggerRect.width,
51
+ y: (clickPoint.y - triggerRect.y) / triggerRect.height,
52
+ };
53
+ }
54
+ /** The inverse: the viewport point this ratio names within a **fresh** trigger rect. */
55
+ function pointFromRatio(triggerRect, ratio) {
56
+ if (!ratio) {
57
+ return undefined;
58
+ }
59
+ return {
60
+ x: triggerRect.x + ratio.x * triggerRect.width,
61
+ y: triggerRect.y + ratio.y * triggerRect.height,
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Whole pixels, to match the panel's rounded translate and to stop the hiding test flickering on
67
+ * sub-pixel noise.
68
+ */
69
+ function roundRect(rect) {
70
+ return {
71
+ x: Math.round(rect.x),
72
+ y: Math.round(rect.y),
73
+ width: Math.round(rect.width),
74
+ height: Math.round(rect.height),
75
+ };
76
+ }
77
+ function overlaps(a, b) {
78
+ return a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;
79
+ }
80
+
81
+ function sideOf(placement) {
82
+ return placement.split('-')[0];
83
+ }
84
+ function isVertical(placement) {
85
+ const side = sideOf(placement);
86
+ return side === 'top' || side === 'bottom';
87
+ }
88
+
89
+ /**
90
+ * The arrow drawing's dimensions, shared by the offset computation, the CSS insets and the
91
+ * stylesheet. The mask's `path` in `_floating-arrow.scss` encodes them too and cannot follow a
92
+ * variable, so changing either number here means redrawing that SVG.
93
+ */
94
+ const ARROW_WIDTH = 16;
95
+ const ARROW_HEIGHT = 8;
96
+
97
+ /** The surface's own corner radius, which the tip must not encroach on. */
98
+ const RADIUS = 4;
99
+ /**
100
+ * Three rules, in order:
101
+ *
102
+ * 1. Aim at the centre of the **anchor ∩ panel intersection**, never the anchor's own centre —
103
+ * `apArrow` documents why this diverges from Floating UI.
104
+ * 2. In `'pointer'` mode, aim at the click, falling back to rule 1 — discontinuously, as the
105
+ * plates specify — when the click lands outside the panel.
106
+ * 3. Clamp to leave the corner radius clear. Below `arrow + 2 × radius` = 24px the range inverts,
107
+ * and the arrow is centred outright.
108
+ *
109
+ * The flags say which rule applied, so the generated plate cases can assert the path taken.
110
+ */
111
+ function resolveArrowOffset(input) {
112
+ const vertical = isVertical(input.side);
113
+ const panel = input.floatingRect;
114
+ const anchor = input.anchorRect;
115
+ const panelStart = vertical ? panel.x : panel.y;
116
+ const panelEnd = panelStart + (vertical ? panel.width : panel.height);
117
+ const size = vertical ? panel.width : panel.height;
118
+ const anchorStart = vertical ? anchor.x : anchor.y;
119
+ const anchorEnd = anchorStart + (vertical ? anchor.width : anchor.height);
120
+ const click = input.clickPoint ? (vertical ? input.clickPoint.x : input.clickPoint.y) : undefined;
121
+ const aimsAtPointer = input.targetMode === 'pointer' && click !== undefined && click >= panelStart && click <= panelEnd;
122
+ let target;
123
+ let fellBack = false;
124
+ if (aimsAtPointer && click !== undefined) {
125
+ target = click;
126
+ }
127
+ else {
128
+ fellBack = input.targetMode === 'pointer';
129
+ const from = Math.max(panelStart, anchorStart);
130
+ const to = Math.min(panelEnd, anchorEnd);
131
+ target = to >= from ? (from + to) / 2 : (panelStart + panelEnd) / 2;
132
+ }
133
+ const raw = target - panelStart - ARROW_WIDTH / 2;
134
+ const low = RADIUS;
135
+ const high = size - ARROW_WIDTH - RADIUS;
136
+ if (high < low) {
137
+ return { offset: (size - ARROW_WIDTH) / 2, clamped: false, fellBack, centered: true };
138
+ }
139
+ const offset = Math.max(low, Math.min(high, raw));
140
+ return { offset, clamped: Math.abs(offset - raw) > 0.5, fellBack, centered: false };
141
+ }
142
+
143
+ const OPPOSITE = {
144
+ top: 'bottom',
145
+ bottom: 'top',
146
+ left: 'right',
147
+ right: 'left',
148
+ };
149
+ /**
150
+ * The panel edge an arrow sits on: a panel placed `bottom` hangs below its anchor, so its tip is on
151
+ * its top edge. Give it the **resolved** placement, or a flipped panel grows its arrow away.
152
+ */
153
+ function arrowSideFor(placement) {
154
+ return OPPOSITE[sideOf(placement)];
155
+ }
156
+ /** One pixel of overlap, or a sub-pixel seam opens at the joint. */
157
+ const OVERLAP = 1;
158
+ /** How far it stands out on the main axis, measured from the panel's edge. */
159
+ const MAIN_INSET = ARROW_HEIGHT - OVERLAP;
160
+ /**
161
+ * The same laterally. A ±90° rotation turns about the box's centre, so the unrotated box is pushed
162
+ * out by half its width less the half height it gains back, for the footprint to clear by `MAIN_INSET`.
163
+ */
164
+ const SIDE_INSET = ARROW_WIDTH / 2 + ARROW_HEIGHT / 2 - OVERLAP;
165
+ /** Compensation for that same rotation centre, on the cross axis. */
166
+ const CROSS_SHIFT = (ARROW_WIDTH - ARROW_HEIGHT) / 2;
167
+ /**
168
+ * The insets and rotation `_floating-arrow.scss` reads off the pane. The rotation-centre
169
+ * compensation lives here rather than in the stylesheet, where it could not be tested.
170
+ *
171
+ * @param side The panel edge the arrow sits on — the **resolved** side, not the wanted one.
172
+ * @param offset The offset from the panel's start edge, along the cross axis.
173
+ */
174
+ function resolveArrowPlacement(side, offset) {
175
+ const auto = 'auto';
176
+ if (side === 'top') {
177
+ return { top: `${-MAIN_INSET}px`, right: auto, bottom: auto, left: `${offset}px`, rotate: '0deg' };
178
+ }
179
+ if (side === 'bottom') {
180
+ return { top: auto, right: auto, bottom: `${-MAIN_INSET}px`, left: `${offset}px`, rotate: '180deg' };
181
+ }
182
+ const cross = `${offset + CROSS_SHIFT}px`;
183
+ return side === 'left'
184
+ ? { top: cross, right: auto, bottom: auto, left: `${-SIDE_INSET}px`, rotate: '-90deg' }
185
+ : { top: cross, right: `${-SIDE_INSET}px`, bottom: auto, left: auto, rotate: '90deg' };
186
+ }
187
+
188
+ const AP_ARROW = 'apArrow';
189
+ /**
190
+ * Replaces Floating UI's `arrow`, which aims at the centre of the *reference*: on a 280px trigger
191
+ * with a 100px panel that centre is out of reach and the tip clamps to a corner at 80, where the
192
+ * intersection's centre is 42 (plate 22). {@link resolveArrowOffset} holds the rule.
193
+ *
194
+ * Must run last, after `shift`, since it reads the panel's final position.
195
+ */
196
+ function apArrow(options) {
197
+ return {
198
+ name: AP_ARROW,
199
+ options,
200
+ fn(state) {
201
+ // Both rects come from Floating UI, in one space. Measuring the pane here would not.
202
+ const anchorRect = roundRect(state.rects.reference);
203
+ const floatingRect = roundRect({
204
+ x: state.x,
205
+ y: state.y,
206
+ width: state.rects.floating.width,
207
+ height: state.rects.floating.height,
208
+ });
209
+ const { offset } = resolveArrowOffset({
210
+ side: arrowSideFor(state.placement),
211
+ anchorRect,
212
+ floatingRect,
213
+ targetMode: options.targetMode,
214
+ clickPoint: clickPointIn(anchorRect, options),
215
+ });
216
+ const data = {
217
+ offset,
218
+ side: arrowSideFor(state.placement),
219
+ hidden: overlaps(floatingRect, anchorRect),
220
+ };
221
+ return { data };
222
+ },
223
+ };
224
+ }
225
+ /**
226
+ * In the pointer modes the reference **is** the click, so its origin is the point. Its coordinate
227
+ * on the main axis is the trigger's and goes unread: the offset only ever reads the cross axis.
228
+ */
229
+ function clickPointIn(anchorRect, { anchorMode, clickRatio }) {
230
+ if (!clickRatio) {
231
+ return undefined;
232
+ }
233
+ if (anchorMode !== 'trigger') {
234
+ return { x: anchorRect.x, y: anchorRect.y };
235
+ }
236
+ return {
237
+ x: anchorRect.x + clickRatio.x * anchorRect.width,
238
+ y: anchorRect.y + clickRatio.y * anchorRect.height,
239
+ };
240
+ }
241
+
242
+ /**
243
+ * Set on the pane when an arrow is asked for. The drawing is global CSS because the pane belongs to
244
+ * no component's DOM, so no encapsulated stylesheet can reach it.
245
+ */
246
+ const ARROW_CLASS = 'ap-floating-arrow';
247
+ /**
248
+ * Written on the first computation only: `getComputedStyle` forces a style recalculation, and the
249
+ * update cycle runs on every scroll of every scrollable ancestor.
250
+ *
251
+ * **A contract for panels that ask for an arrow**: the pane's first element child must be the
252
+ * styled surface, not a wrapper around it. The arrow's colour is lifted off that element, and the
253
+ * stylesheet neutralises its shadow — a wrapper yields a transparent tip and two shadows at the
254
+ * joint.
255
+ *
256
+ * Only CSS knows which element carries a background, so this is checked in a browser, never in a
257
+ * unit test.
258
+ *
259
+ * @returns whether the surface was there to read, so the caller can retry on the next pass.
260
+ */
261
+ function writeArrowInvariants(pane) {
262
+ pane.style.setProperty('--ap-floating-arrow-width', `${ARROW_WIDTH}px`);
263
+ pane.style.setProperty('--ap-floating-arrow-height', `${ARROW_HEIGHT}px`);
264
+ const surface = pane.firstElementChild;
265
+ if (!surface) {
266
+ return false;
267
+ }
268
+ pane.style.setProperty('--ap-arrow-background', getComputedStyle(surface).backgroundColor);
269
+ return true;
270
+ }
271
+ /** The half that moves with the panel. */
272
+ function writeArrowStyles(pane, arrow) {
273
+ const placement = resolveArrowPlacement(arrow.side, arrow.offset);
274
+ pane.style.setProperty('--ap-arrow-top', placement.top);
275
+ pane.style.setProperty('--ap-arrow-right', placement.right);
276
+ pane.style.setProperty('--ap-arrow-bottom', placement.bottom);
277
+ pane.style.setProperty('--ap-arrow-left', placement.left);
278
+ pane.style.setProperty('--ap-arrow-rotate', placement.rotate);
279
+ pane.style.setProperty('--ap-arrow-visibility', arrow.hidden ? 'hidden' : 'visible');
280
+ }
281
+
282
+ /** gap (4) + arrow length (8). */
283
+ const MAIN_OFFSET = 12;
284
+ const VIEWPORT_MARGIN = 8;
285
+ function toRect(source) {
286
+ const rect = source.getBoundingClientRect();
287
+ return roundRect({ x: rect.left, y: rect.top, width: rect.width, height: rect.height });
288
+ }
289
+ function createFloatingOverlay() {
290
+ const elementRef = inject(ElementRef);
291
+ const overlay = inject(Overlay);
292
+ const viewContainerRef = inject(ViewContainerRef);
293
+ let _overlayRef = null;
294
+ let stopAutoUpdate = null;
295
+ let reposition = null;
296
+ let anchorState = null;
297
+ const isOpen = signal(false, /* @ts-ignore */
298
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
299
+ inject(DestroyRef).onDestroy(() => close());
300
+ /**
301
+ * Opens the floating on a `TemplateRef`, attached as is, or on a component whose `ComponentRef`
302
+ * is handed back, typed on the component, so the caller can set its inputs.
303
+ *
304
+ * The position keeps itself current, so inputs set after this returns need no refresh.
305
+ */
306
+ function open(content, triggerElement, config, event) {
307
+ if (isOpen())
308
+ return null;
309
+ const target = triggerElement ?? elementRef.nativeElement;
310
+ const mode = config?.anchor ?? 'trigger';
311
+ const placement = config?.placement ?? defaultPlacementFor(mode);
312
+ anchorState = captureAnchor(target, mode, placement, event);
313
+ disposeOverlay();
314
+ _overlayRef = createOverlay(config);
315
+ const pane = _overlayRef.overlayElement;
316
+ // Floating UI's coordinates are viewport-relative; the CDK's `absolute` would misread them.
317
+ pane.style.position = 'fixed';
318
+ pane.style.left = '0';
319
+ pane.style.top = '0';
320
+ const panelRef = attachContent(content);
321
+ isOpen.set(true);
322
+ if (config?.arrow === true) {
323
+ // On opening, so the pane carries the single silhouette's shadow before the first frame.
324
+ pane.classList.add(ARROW_CLASS);
325
+ }
326
+ watchPosition(pane, placement, config);
327
+ watchDismissal(target, config);
328
+ return panelRef;
329
+ }
330
+ function captureAnchor(target, mode, placement, event) {
331
+ return { target, mode, vertical: isVertical(placement), ratio: resolveClickRatio(toRect(target), clickPointOf(event)) };
332
+ }
333
+ /**
334
+ * The reference **is** the anchor in all three modes, which is what lets the arrow read
335
+ * `rects.reference` rather than rebuild it. `contextElement` is load-bearing: without it
336
+ * `autoUpdate` cannot find the scrollable ancestors of an anchor that has no DOM node.
337
+ */
338
+ function toReference(state) {
339
+ if (state.mode === 'trigger' || !state.ratio) {
340
+ return state.target;
341
+ }
342
+ return {
343
+ contextElement: state.target,
344
+ getBoundingClientRect: () => {
345
+ const trigger = toRect(state.target);
346
+ const rect = resolveAnchorRect(state.mode, trigger, state.vertical, pointFromRatio(trigger, state.ratio));
347
+ return new DOMRect(rect.x, rect.y, rect.width, rect.height);
348
+ },
349
+ };
350
+ }
351
+ function createOverlay(config) {
352
+ return overlay.create({
353
+ hasBackdrop: config?.showBackdrop ?? false,
354
+ backdropClass: '',
355
+ panelClass: config?.panelClass ?? '',
356
+ // No scroll strategy: `autoUpdate` owns the update cycle, and the CDK's default is a no-op.
357
+ usePopover: false,
358
+ });
359
+ }
360
+ function attachContent(content) {
361
+ if (!_overlayRef)
362
+ return null;
363
+ if (content instanceof TemplateRef) {
364
+ _overlayRef.attach(new TemplatePortal(content, viewContainerRef));
365
+ return null;
366
+ }
367
+ return _overlayRef.attach(new ComponentPortal(content, viewContainerRef));
368
+ }
369
+ /**
370
+ * `autoUpdate` is the whole update cycle: scrollable ancestors of both boxes, the viewport,
371
+ * both boxes' own resizing, and layout shifts. Nothing else here watches anything.
372
+ */
373
+ function watchPosition(pane, placement, config) {
374
+ const state = anchorState;
375
+ if (!state)
376
+ return;
377
+ const reference = toReference(state);
378
+ const middleware = [
379
+ offset(MAIN_OFFSET),
380
+ flip({ crossAxis: false, flipAlignment: false, padding: VIEWPORT_MARGIN }),
381
+ shift({ padding: VIEWPORT_MARGIN }),
382
+ ];
383
+ if (config?.arrow === true) {
384
+ middleware.push(apArrow({ targetMode: config.arrowTarget ?? 'anchor', anchorMode: state.mode, clickRatio: state.ratio }));
385
+ }
386
+ let invariantsWritten = false;
387
+ reposition = () => {
388
+ void computePosition(reference, pane, { strategy: 'fixed', placement, middleware }).then(position => {
389
+ // Whole pixels: a fractional translate blurs text on a non-retina screen.
390
+ pane.style.transform = `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`;
391
+ const arrow = position.middlewareData[AP_ARROW];
392
+ if (arrow) {
393
+ invariantsWritten = invariantsWritten || writeArrowInvariants(pane);
394
+ writeArrowStyles(pane, arrow);
395
+ }
396
+ });
397
+ };
398
+ stopAutoUpdate = autoUpdate(reference, pane, reposition);
399
+ }
400
+ function watchDismissal(target, config) {
401
+ if (!_overlayRef)
402
+ return;
403
+ const closeHandler = config?.onClose ?? (() => close());
404
+ const outsideHandler = config?.onOutsideClick ?? closeHandler;
405
+ const escapeHandler = config?.onEscape ?? closeHandler;
406
+ const ownsGesture = (node) => target.contains(node) || (config?.additionalTriggers?.() ?? []).some(element => element.contains(node));
407
+ _overlayRef
408
+ .outsidePointerEvents()
409
+ .pipe(filter(pointerEvent => !(pointerEvent.target instanceof Node && ownsGesture(pointerEvent.target))), take(1))
410
+ .subscribe(() => outsideHandler());
411
+ _overlayRef
412
+ .keydownEvents()
413
+ .pipe(filter(keyEvent => keyEvent.key === 'Escape'), take(1))
414
+ .subscribe(() => escapeHandler());
415
+ }
416
+ /** The observers never outlive their overlay: they would reposition it after its destruction. */
417
+ function disposeOverlay() {
418
+ stopAutoUpdate?.();
419
+ stopAutoUpdate = null;
420
+ reposition = null;
421
+ _overlayRef?.dispose();
422
+ _overlayRef = null;
423
+ }
424
+ function close() {
425
+ if (!isOpen())
426
+ return;
427
+ anchorState = null;
428
+ disposeOverlay();
429
+ isOpen.set(false);
430
+ }
431
+ /** Recomputes now. For a caller that knows the geometry changed before any observer can see it. */
432
+ function updatePosition() {
433
+ reposition?.();
434
+ }
435
+ return {
436
+ get overlayRef() {
437
+ return _overlayRef;
438
+ },
439
+ isOpen: isOpen.asReadonly(),
440
+ open,
441
+ close,
442
+ updatePosition,
443
+ };
444
+ }
445
+
446
+ /**
447
+ * Generated bundle index. Do not edit.
448
+ */
449
+
450
+ export { apArrow, arrowSideFor, createFloatingOverlay, defaultPlacementFor, isVertical, resolveAnchorRect, resolveArrowOffset, resolveArrowPlacement, sideOf };
451
+ //# sourceMappingURL=agorapulse-ui-components-floating.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agorapulse-ui-components-floating.mjs","sources":["../../../libs/ui-components/floating/src/anchor.ts","../../../libs/ui-components/floating/src/rect.ts","../../../libs/ui-components/floating/src/placement.ts","../../../libs/ui-components/floating/src/arrow/arrow-geometry.ts","../../../libs/ui-components/floating/src/arrow/arrow-offset.ts","../../../libs/ui-components/floating/src/arrow/arrow-placement.ts","../../../libs/ui-components/floating/src/arrow/ap-arrow.middleware.ts","../../../libs/ui-components/floating/src/arrow/arrow-styles.ts","../../../libs/ui-components/floating/src/floating-overlay.helper.ts","../../../libs/ui-components/floating/src/agorapulse-ui-components-floating.ts"],"sourcesContent":["import { FloatingPlacement } from './placement';\nimport { FloatingRect } from './rect';\n\n/** What the panel connects to. */\nexport type FloatingAnchorMode = 'trigger' | 'pointer' | 'pointer-free';\n\n/**\n * The placement derived when `placement` is unset. Reads the **configured** anchor mode, not the\n * resolved one: a keyboard opening falls back to the trigger, and if the alignment followed, the\n * component would change shape between mouse and keyboard.\n */\nexport function defaultPlacementFor(anchor: FloatingAnchorMode): FloatingPlacement {\n return anchor === 'trigger' ? 'bottom-start' : 'bottom';\n}\n\n/**\n * `'pointer'` is a hybrid whose zero dimension is the **cross-axis** one; a lateral panel built\n * from a fully point-like anchor would sit inside its own trigger. `'pointer-free'` is the point\n * itself. Both fall back to the trigger when there is no click.\n *\n * @param vertical The opening axis. Invariant under the flip, which only swaps the main axis.\n */\nexport function resolveAnchorRect(\n anchor: FloatingAnchorMode,\n triggerRect: FloatingRect,\n vertical: boolean,\n clickPoint?: { x: number; y: number }\n): FloatingRect {\n if (anchor === 'trigger' || !clickPoint) {\n return triggerRect;\n }\n\n if (anchor === 'pointer-free') {\n return { x: clickPoint.x, y: clickPoint.y, width: 0, height: 0 };\n }\n\n return vertical\n ? { x: clickPoint.x, y: triggerRect.y, width: 0, height: triggerRect.height }\n : { x: triggerRect.x, y: clickPoint.y, width: triggerRect.width, height: 0 };\n}\n\n/**\n * A keyboard-synthesised click carries `detail: 0` and `clientX: 0`, which without this guard puts\n * the pointer anchor in the screen's top-left corner.\n */\nexport function clickPointOf(event?: MouseEvent): { x: number; y: number } | undefined {\n return event && event.detail > 0 ? { x: event.clientX, y: event.clientY } : undefined;\n}\n\n/** A point expressed as a proportion of the trigger, on each axis. */\nexport interface ClickRatio {\n x: number;\n y: number;\n}\n\n/**\n * A ratio names a place on the trigger where a viewport coordinate names a place in the window,\n * which is what makes a pointer anchor survive scrolling, resizing and shifting. `undefined` for a\n * trigger with no area, so the anchor falls back to the element rather than divide by zero.\n */\nexport function resolveClickRatio(triggerRect: FloatingRect, clickPoint?: { x: number; y: number }): ClickRatio | undefined {\n if (!clickPoint || triggerRect.width <= 0 || triggerRect.height <= 0) {\n return undefined;\n }\n\n return {\n x: (clickPoint.x - triggerRect.x) / triggerRect.width,\n y: (clickPoint.y - triggerRect.y) / triggerRect.height,\n };\n}\n\n/** The inverse: the viewport point this ratio names within a **fresh** trigger rect. */\nexport function pointFromRatio(triggerRect: FloatingRect, ratio?: ClickRatio): { x: number; y: number } | undefined {\n if (!ratio) {\n return undefined;\n }\n\n return {\n x: triggerRect.x + ratio.x * triggerRect.width,\n y: triggerRect.y + ratio.y * triggerRect.height,\n };\n}\n","/** A minimal rect — neither `DOMRect` nor any DOM dependency, so the pure units stay pure. */\nexport interface FloatingRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Whole pixels, to match the panel's rounded translate and to stop the hiding test flickering on\n * sub-pixel noise.\n */\nexport function roundRect(rect: FloatingRect): FloatingRect {\n return {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n}\n\nexport function overlaps(a: FloatingRect, b: FloatingRect): boolean {\n return a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;\n}\n","import { Placement, Side } from '@floating-ui/dom';\n\n/**\n * The twelve placements, aliased from Floating UI rather than redeclared. The trade-off: this puts\n * `@floating-ui/dom` in our **public** type surface, so its next major would move our types too.\n *\n * There is no `'auto'`; an unset placement is derived by `defaultPlacementFor`.\n */\nexport type FloatingPlacement = Placement;\n\n/** The four opening sides. Floating UI's `Side`, for the same reason. */\nexport type FloatingSide = Side;\n\nexport function sideOf(placement: FloatingPlacement): FloatingSide {\n return placement.split('-')[0] as FloatingSide;\n}\n\nexport function isVertical(placement: FloatingPlacement): boolean {\n const side = sideOf(placement);\n return side === 'top' || side === 'bottom';\n}\n","/**\n * The arrow drawing's dimensions, shared by the offset computation, the CSS insets and the\n * stylesheet. The mask's `path` in `_floating-arrow.scss` encodes them too and cannot follow a\n * variable, so changing either number here means redrawing that SVG.\n */\nexport const ARROW_WIDTH = 16;\nexport const ARROW_HEIGHT = 8;\n","import { FloatingSide, isVertical } from '../placement';\nimport { FloatingRect } from '../rect';\nimport { ARROW_WIDTH } from './arrow-geometry';\n\nexport interface ArrowOffsetInput {\n /** The side of the panel the arrow sits on — the **resolved** side, not the wanted one. */\n side: FloatingSide;\n anchorRect: FloatingRect;\n floatingRect: FloatingRect;\n /** `'anchor'` aims at the anchor ∩ panel intersection's centre, `'pointer'` at the click. */\n targetMode: 'anchor' | 'pointer';\n clickPoint?: { x: number; y: number };\n}\n\nexport interface ArrowOffsetResult {\n /** The arrow's offset from the panel's start edge, along the cross axis. */\n offset: number;\n clamped: boolean;\n /** The click fell outside the panel, so the intersection centre was used instead. */\n fellBack: boolean;\n /** The panel is too narrow: the clamp range inverts and the arrow is centred outright. */\n centered: boolean;\n}\n\n/** The surface's own corner radius, which the tip must not encroach on. */\nconst RADIUS = 4;\n\n/**\n * Three rules, in order:\n *\n * 1. Aim at the centre of the **anchor ∩ panel intersection**, never the anchor's own centre —\n * `apArrow` documents why this diverges from Floating UI.\n * 2. In `'pointer'` mode, aim at the click, falling back to rule 1 — discontinuously, as the\n * plates specify — when the click lands outside the panel.\n * 3. Clamp to leave the corner radius clear. Below `arrow + 2 × radius` = 24px the range inverts,\n * and the arrow is centred outright.\n *\n * The flags say which rule applied, so the generated plate cases can assert the path taken.\n */\nexport function resolveArrowOffset(input: ArrowOffsetInput): ArrowOffsetResult {\n const vertical = isVertical(input.side);\n const panel = input.floatingRect;\n const anchor = input.anchorRect;\n\n const panelStart = vertical ? panel.x : panel.y;\n const panelEnd = panelStart + (vertical ? panel.width : panel.height);\n const size = vertical ? panel.width : panel.height;\n const anchorStart = vertical ? anchor.x : anchor.y;\n const anchorEnd = anchorStart + (vertical ? anchor.width : anchor.height);\n const click = input.clickPoint ? (vertical ? input.clickPoint.x : input.clickPoint.y) : undefined;\n\n const aimsAtPointer = input.targetMode === 'pointer' && click !== undefined && click >= panelStart && click <= panelEnd;\n\n let target: number;\n let fellBack = false;\n if (aimsAtPointer && click !== undefined) {\n target = click;\n } else {\n fellBack = input.targetMode === 'pointer';\n const from = Math.max(panelStart, anchorStart);\n const to = Math.min(panelEnd, anchorEnd);\n target = to >= from ? (from + to) / 2 : (panelStart + panelEnd) / 2;\n }\n\n const raw = target - panelStart - ARROW_WIDTH / 2;\n const low = RADIUS;\n const high = size - ARROW_WIDTH - RADIUS;\n\n if (high < low) {\n return { offset: (size - ARROW_WIDTH) / 2, clamped: false, fellBack, centered: true };\n }\n\n const offset = Math.max(low, Math.min(high, raw));\n return { offset, clamped: Math.abs(offset - raw) > 0.5, fellBack, centered: false };\n}\n","import { FloatingPlacement, FloatingSide, sideOf } from '../placement';\nimport { ARROW_HEIGHT, ARROW_WIDTH } from './arrow-geometry';\n\nconst OPPOSITE: Record<FloatingSide, FloatingSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\n/**\n * The panel edge an arrow sits on: a panel placed `bottom` hangs below its anchor, so its tip is on\n * its top edge. Give it the **resolved** placement, or a flipped panel grows its arrow away.\n */\nexport function arrowSideFor(placement: FloatingPlacement): FloatingSide {\n return OPPOSITE[sideOf(placement)];\n}\n\n/** Ready-to-use CSS values, `'auto'` for the sides that do not apply. */\nexport interface ArrowPlacement {\n top: string;\n right: string;\n bottom: string;\n left: string;\n rotate: string;\n}\n\n/** One pixel of overlap, or a sub-pixel seam opens at the joint. */\nconst OVERLAP = 1;\n\n/** How far it stands out on the main axis, measured from the panel's edge. */\nconst MAIN_INSET = ARROW_HEIGHT - OVERLAP;\n\n/**\n * The same laterally. A ±90° rotation turns about the box's centre, so the unrotated box is pushed\n * out by half its width less the half height it gains back, for the footprint to clear by `MAIN_INSET`.\n */\nconst SIDE_INSET = ARROW_WIDTH / 2 + ARROW_HEIGHT / 2 - OVERLAP;\n\n/** Compensation for that same rotation centre, on the cross axis. */\nconst CROSS_SHIFT = (ARROW_WIDTH - ARROW_HEIGHT) / 2;\n\n/**\n * The insets and rotation `_floating-arrow.scss` reads off the pane. The rotation-centre\n * compensation lives here rather than in the stylesheet, where it could not be tested.\n *\n * @param side The panel edge the arrow sits on — the **resolved** side, not the wanted one.\n * @param offset The offset from the panel's start edge, along the cross axis.\n */\nexport function resolveArrowPlacement(side: FloatingSide, offset: number): ArrowPlacement {\n const auto = 'auto';\n\n if (side === 'top') {\n return { top: `${-MAIN_INSET}px`, right: auto, bottom: auto, left: `${offset}px`, rotate: '0deg' };\n }\n\n if (side === 'bottom') {\n return { top: auto, right: auto, bottom: `${-MAIN_INSET}px`, left: `${offset}px`, rotate: '180deg' };\n }\n\n const cross = `${offset + CROSS_SHIFT}px`;\n\n return side === 'left'\n ? { top: cross, right: auto, bottom: auto, left: `${-SIDE_INSET}px`, rotate: '-90deg' }\n : { top: cross, right: `${-SIDE_INSET}px`, bottom: auto, left: auto, rotate: '90deg' };\n}\n","import { Middleware, MiddlewareState } from '@floating-ui/dom';\nimport { ClickRatio, FloatingAnchorMode } from '../anchor';\nimport { FloatingSide } from '../placement';\nimport { FloatingRect, overlaps, roundRect } from '../rect';\nimport { resolveArrowOffset } from './arrow-offset';\nimport { arrowSideFor } from './arrow-placement';\n\nexport interface ApArrowOptions {\n /** What the tip aims at — see {@link resolveArrowOffset}. */\n targetMode: 'anchor' | 'pointer';\n /** The configured anchor mode. Decides how the click is recovered from the reference rect. */\n anchorMode: FloatingAnchorMode;\n /** The clicked point as a proportion of the trigger. Absent on a keyboard opening. */\n clickRatio?: ClickRatio;\n}\n\n/** What the middleware leaves in `middlewareData.apArrow`. */\nexport interface ApArrowData {\n /** The arrow's offset from the panel's start edge, along the cross axis. */\n offset: number;\n /** The side of the panel the arrow sits on — read from the **resolved** placement. */\n side: FloatingSide;\n /** The panel covers its **anchor** — in the POI mode the trigger may be covered on purpose. */\n hidden: boolean;\n}\n\nexport const AP_ARROW = 'apArrow';\n\n/**\n * Replaces Floating UI's `arrow`, which aims at the centre of the *reference*: on a 280px trigger\n * with a 100px panel that centre is out of reach and the tip clamps to a corner at 80, where the\n * intersection's centre is 42 (plate 22). {@link resolveArrowOffset} holds the rule.\n *\n * Must run last, after `shift`, since it reads the panel's final position.\n */\nexport function apArrow(options: ApArrowOptions): Middleware {\n return {\n name: AP_ARROW,\n options,\n fn(state: MiddlewareState) {\n // Both rects come from Floating UI, in one space. Measuring the pane here would not.\n const anchorRect = roundRect(state.rects.reference);\n const floatingRect = roundRect({\n x: state.x,\n y: state.y,\n width: state.rects.floating.width,\n height: state.rects.floating.height,\n });\n\n const { offset } = resolveArrowOffset({\n side: arrowSideFor(state.placement),\n anchorRect,\n floatingRect,\n targetMode: options.targetMode,\n clickPoint: clickPointIn(anchorRect, options),\n });\n\n const data: ApArrowData = {\n offset,\n side: arrowSideFor(state.placement),\n hidden: overlaps(floatingRect, anchorRect),\n };\n return { data };\n },\n };\n}\n\n/**\n * In the pointer modes the reference **is** the click, so its origin is the point. Its coordinate\n * on the main axis is the trigger's and goes unread: the offset only ever reads the cross axis.\n */\nfunction clickPointIn(anchorRect: FloatingRect, { anchorMode, clickRatio }: ApArrowOptions): { x: number; y: number } | undefined {\n if (!clickRatio) {\n return undefined;\n }\n if (anchorMode !== 'trigger') {\n return { x: anchorRect.x, y: anchorRect.y };\n }\n return {\n x: anchorRect.x + clickRatio.x * anchorRect.width,\n y: anchorRect.y + clickRatio.y * anchorRect.height,\n };\n}\n","import { ApArrowData } from './ap-arrow.middleware';\nimport { ARROW_HEIGHT, ARROW_WIDTH } from './arrow-geometry';\nimport { resolveArrowPlacement } from './arrow-placement';\n\n/**\n * Set on the pane when an arrow is asked for. The drawing is global CSS because the pane belongs to\n * no component's DOM, so no encapsulated stylesheet can reach it.\n */\nexport const ARROW_CLASS = 'ap-floating-arrow';\n\n/**\n * Written on the first computation only: `getComputedStyle` forces a style recalculation, and the\n * update cycle runs on every scroll of every scrollable ancestor.\n *\n * **A contract for panels that ask for an arrow**: the pane's first element child must be the\n * styled surface, not a wrapper around it. The arrow's colour is lifted off that element, and the\n * stylesheet neutralises its shadow — a wrapper yields a transparent tip and two shadows at the\n * joint.\n *\n * Only CSS knows which element carries a background, so this is checked in a browser, never in a\n * unit test.\n *\n * @returns whether the surface was there to read, so the caller can retry on the next pass.\n */\nexport function writeArrowInvariants(pane: HTMLElement): boolean {\n pane.style.setProperty('--ap-floating-arrow-width', `${ARROW_WIDTH}px`);\n pane.style.setProperty('--ap-floating-arrow-height', `${ARROW_HEIGHT}px`);\n\n const surface = pane.firstElementChild;\n if (!surface) {\n return false;\n }\n\n pane.style.setProperty('--ap-arrow-background', getComputedStyle(surface).backgroundColor);\n return true;\n}\n\n/** The half that moves with the panel. */\nexport function writeArrowStyles(pane: HTMLElement, arrow: ApArrowData): void {\n const placement = resolveArrowPlacement(arrow.side, arrow.offset);\n\n pane.style.setProperty('--ap-arrow-top', placement.top);\n pane.style.setProperty('--ap-arrow-right', placement.right);\n pane.style.setProperty('--ap-arrow-bottom', placement.bottom);\n pane.style.setProperty('--ap-arrow-left', placement.left);\n pane.style.setProperty('--ap-arrow-rotate', placement.rotate);\n pane.style.setProperty('--ap-arrow-visibility', arrow.hidden ? 'hidden' : 'visible');\n}\n","import { Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';\nimport { ComponentRef, DestroyRef, ElementRef, inject, signal, TemplateRef, Type, ViewContainerRef } from '@angular/core';\nimport { autoUpdate, computePosition, flip, offset, shift, VirtualElement } from '@floating-ui/dom';\nimport { filter, take } from 'rxjs/operators';\nimport {\n clickPointOf,\n ClickRatio,\n defaultPlacementFor,\n FloatingAnchorMode,\n pointFromRatio,\n resolveAnchorRect,\n resolveClickRatio,\n} from './anchor';\nimport { AP_ARROW, apArrow, ApArrowData } from './arrow/ap-arrow.middleware';\nimport { ARROW_CLASS, writeArrowInvariants, writeArrowStyles } from './arrow/arrow-styles';\nimport { FloatingPlacement, isVertical } from './placement';\nimport { FloatingRect, roundRect } from './rect';\n\nexport interface FloatingOverlayConfig {\n /** Unset means derived from `anchor`. There is no `'auto'` value. */\n placement?: FloatingPlacement;\n anchor?: FloatingAnchorMode;\n arrow?: boolean;\n arrowTarget?: 'anchor' | 'pointer';\n showBackdrop?: boolean;\n panelClass?: string | string[];\n /** Fallback for the two handlers below. */\n onClose?: () => void;\n /** Escape, which always closes. Unset means `onClose`. */\n onEscape?: () => void;\n /** Outside click. Unset means `onClose`. */\n onOutsideClick?: () => void;\n /**\n * Elements that carry their own toggle, so a click on them is not \"the outside\". Read on every\n * event, since the list may change while the floating is open.\n *\n * Without this, the CDK's capture-phase dispatcher closes before a secondary trigger sees the\n * click, that trigger reopens, and the toggle never closes again.\n */\n additionalTriggers?: () => readonly HTMLElement[];\n}\n\n/** gap (4) + arrow length (8). */\nconst MAIN_OFFSET = 12;\n\nconst VIEWPORT_MARGIN = 8;\n\ninterface Measurable {\n getBoundingClientRect: () => { left: number; top: number; width: number; height: number };\n}\n\nfunction toRect(source: Measurable): FloatingRect {\n const rect = source.getBoundingClientRect();\n return roundRect({ x: rect.left, y: rect.top, width: rect.width, height: rect.height });\n}\n\ninterface AnchorState {\n target: HTMLElement;\n mode: FloatingAnchorMode;\n /** The opening axis. Invariant under the flip, which only swaps the main axis. */\n vertical: boolean;\n /** The click as a proportion of the trigger, so it survives scrolling, resizing and shifting. */\n ratio?: ClickRatio;\n}\n\nexport function createFloatingOverlay() {\n const elementRef = inject(ElementRef);\n const overlay = inject(Overlay);\n const viewContainerRef = inject(ViewContainerRef);\n\n let _overlayRef: OverlayRef | null = null;\n let stopAutoUpdate: (() => void) | null = null;\n let reposition: (() => void) | null = null;\n let anchorState: AnchorState | null = null;\n const isOpen = signal(false);\n\n inject(DestroyRef).onDestroy(() => close());\n\n /**\n * Opens the floating on a `TemplateRef`, attached as is, or on a component whose `ComponentRef`\n * is handed back, typed on the component, so the caller can set its inputs.\n *\n * The position keeps itself current, so inputs set after this returns need no refresh.\n */\n function open<T = unknown>(\n content: TemplateRef<unknown> | Type<T>,\n triggerElement?: HTMLElement,\n config?: FloatingOverlayConfig,\n event?: MouseEvent\n ): ComponentRef<T> | null {\n if (isOpen()) return null;\n\n const target = triggerElement ?? elementRef.nativeElement;\n const mode = config?.anchor ?? 'trigger';\n const placement = config?.placement ?? defaultPlacementFor(mode);\n\n anchorState = captureAnchor(target, mode, placement, event);\n\n disposeOverlay();\n _overlayRef = createOverlay(config);\n const pane = _overlayRef.overlayElement;\n // Floating UI's coordinates are viewport-relative; the CDK's `absolute` would misread them.\n pane.style.position = 'fixed';\n pane.style.left = '0';\n pane.style.top = '0';\n\n const panelRef = attachContent(content);\n isOpen.set(true);\n\n if (config?.arrow === true) {\n // On opening, so the pane carries the single silhouette's shadow before the first frame.\n pane.classList.add(ARROW_CLASS);\n }\n\n watchPosition(pane, placement, config);\n watchDismissal(target, config);\n\n return panelRef;\n }\n\n function captureAnchor(target: HTMLElement, mode: FloatingAnchorMode, placement: FloatingPlacement, event?: MouseEvent): AnchorState {\n return { target, mode, vertical: isVertical(placement), ratio: resolveClickRatio(toRect(target), clickPointOf(event)) };\n }\n\n /**\n * The reference **is** the anchor in all three modes, which is what lets the arrow read\n * `rects.reference` rather than rebuild it. `contextElement` is load-bearing: without it\n * `autoUpdate` cannot find the scrollable ancestors of an anchor that has no DOM node.\n */\n function toReference(state: AnchorState): HTMLElement | VirtualElement {\n if (state.mode === 'trigger' || !state.ratio) {\n return state.target;\n }\n\n return {\n contextElement: state.target,\n getBoundingClientRect: () => {\n const trigger = toRect(state.target);\n const rect = resolveAnchorRect(state.mode, trigger, state.vertical, pointFromRatio(trigger, state.ratio));\n return new DOMRect(rect.x, rect.y, rect.width, rect.height);\n },\n };\n }\n\n function createOverlay(config?: FloatingOverlayConfig): OverlayRef {\n return overlay.create({\n hasBackdrop: config?.showBackdrop ?? false,\n backdropClass: '',\n panelClass: config?.panelClass ?? '',\n // No scroll strategy: `autoUpdate` owns the update cycle, and the CDK's default is a no-op.\n usePopover: false,\n });\n }\n\n function attachContent<T>(content: TemplateRef<unknown> | Type<T>): ComponentRef<T> | null {\n if (!_overlayRef) return null;\n if (content instanceof TemplateRef) {\n _overlayRef.attach(new TemplatePortal(content, viewContainerRef));\n return null;\n }\n return _overlayRef.attach(new ComponentPortal(content, viewContainerRef));\n }\n\n /**\n * `autoUpdate` is the whole update cycle: scrollable ancestors of both boxes, the viewport,\n * both boxes' own resizing, and layout shifts. Nothing else here watches anything.\n */\n function watchPosition(pane: HTMLElement, placement: FloatingPlacement, config?: FloatingOverlayConfig): void {\n const state = anchorState;\n if (!state) return;\n const reference = toReference(state);\n\n const middleware = [\n offset(MAIN_OFFSET),\n flip({ crossAxis: false, flipAlignment: false, padding: VIEWPORT_MARGIN }),\n shift({ padding: VIEWPORT_MARGIN }),\n ];\n if (config?.arrow === true) {\n middleware.push(apArrow({ targetMode: config.arrowTarget ?? 'anchor', anchorMode: state.mode, clickRatio: state.ratio }));\n }\n\n let invariantsWritten = false;\n\n reposition = () => {\n void computePosition(reference, pane, { strategy: 'fixed', placement, middleware }).then(position => {\n // Whole pixels: a fractional translate blurs text on a non-retina screen.\n pane.style.transform = `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`;\n const arrow: ApArrowData | undefined = position.middlewareData[AP_ARROW];\n if (arrow) {\n invariantsWritten = invariantsWritten || writeArrowInvariants(pane);\n writeArrowStyles(pane, arrow);\n }\n });\n };\n\n stopAutoUpdate = autoUpdate(reference, pane, reposition);\n }\n\n function watchDismissal(target: HTMLElement, config?: FloatingOverlayConfig): void {\n if (!_overlayRef) return;\n\n const closeHandler = config?.onClose ?? (() => close());\n const outsideHandler = config?.onOutsideClick ?? closeHandler;\n const escapeHandler = config?.onEscape ?? closeHandler;\n\n const ownsGesture = (node: Node): boolean =>\n target.contains(node) || (config?.additionalTriggers?.() ?? []).some(element => element.contains(node));\n\n _overlayRef\n .outsidePointerEvents()\n .pipe(\n filter(pointerEvent => !(pointerEvent.target instanceof Node && ownsGesture(pointerEvent.target))),\n take(1)\n )\n .subscribe(() => outsideHandler());\n\n _overlayRef\n .keydownEvents()\n .pipe(\n filter(keyEvent => keyEvent.key === 'Escape'),\n take(1)\n )\n .subscribe(() => escapeHandler());\n }\n\n /** The observers never outlive their overlay: they would reposition it after its destruction. */\n function disposeOverlay(): void {\n stopAutoUpdate?.();\n stopAutoUpdate = null;\n reposition = null;\n _overlayRef?.dispose();\n _overlayRef = null;\n }\n\n function close(): void {\n if (!isOpen()) return;\n\n anchorState = null;\n disposeOverlay();\n isOpen.set(false);\n }\n\n /** Recomputes now. For a caller that knows the geometry changed before any observer can see it. */\n function updatePosition(): void {\n reposition?.();\n }\n\n return {\n get overlayRef() {\n return _overlayRef;\n },\n isOpen: isOpen.asReadonly(),\n open,\n close,\n updatePosition,\n };\n}\n\nexport type FloatingOverlayInstance = ReturnType<typeof createFloatingOverlay>;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agorapulse/ui-components",
3
3
  "description": "Agorapulse UI Components Library",
4
- "version": "22.0.30",
4
+ "version": "22.0.32",
5
5
  "author": "Benoit Hediard",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,6 +20,7 @@
20
20
  "@angular/core": "^22.0.0",
21
21
  "@angular/material": "^22.0.0",
22
22
  "@angular/animations": "^22.0.0",
23
+ "@floating-ui/dom": "^1.8.0",
23
24
  "@ng-select/ng-select": "^23.0.0",
24
25
  "@agorapulse/ngx-daterangepicker-material": "^6.0.5",
25
26
  "dayjs": "^1.11.6",
@@ -108,6 +109,10 @@
108
109
  "types": "./types/agorapulse-ui-components-filter-dropdown.d.ts",
109
110
  "default": "./fesm2022/agorapulse-ui-components-filter-dropdown.mjs"
110
111
  },
112
+ "./floating": {
113
+ "types": "./types/agorapulse-ui-components-floating.d.ts",
114
+ "default": "./fesm2022/agorapulse-ui-components-floating.mjs"
115
+ },
111
116
  "./form-field": {
112
117
  "types": "./types/agorapulse-ui-components-form-field.d.ts",
113
118
  "default": "./fesm2022/agorapulse-ui-components-form-field.mjs"
@@ -189,6 +189,8 @@ declare class FilterState {
189
189
  readonly draft: _angular_core.Signal<FilterDropdownOutput>;
190
190
  readonly expanded: _angular_core.Signal<Record<string, boolean>>;
191
191
  readonly activeFilterCount: _angular_core.Signal<number>;
192
+ /** What the consumer last applied, which is what the trigger advertises while the panel edits the draft. */
193
+ readonly appliedFilterCount: _angular_core.Signal<number>;
192
194
  readonly isFilterCountActive: _angular_core.Signal<boolean>;
193
195
  readonly hasChanges: _angular_core.Signal<boolean>;
194
196
  /** Save / Update / Reset / Apply are gated on dirty state. */
@@ -197,6 +199,7 @@ declare class FilterState {
197
199
  readonly clearDisabled: _angular_core.Signal<boolean>;
198
200
  /** Whether a leaf has a panel of its own showing: the dropdown must not close under it. */
199
201
  readonly nestedPanelOpen: _angular_core.Signal<boolean>;
202
+ private countSelections;
200
203
  /** Refresh the structural schema and reconcile the value keyspace (add empty / drop removed). */
201
204
  setSchema(groups: FilterDropdownGroup[]): void;
202
205
  /** Seed the draft from an external value, projected onto the current keyspace. Echo-gated, silent. */
@@ -317,6 +320,9 @@ declare class FilterDropdownComponent implements DropdownOverlay {
317
320
  /** Event emitted when a group with locked feature is clicked */
318
321
  filterDropdownGroupLockedClicked: _angular_core.OutputEmitterRef<FilterDropdownGroup>;
319
322
  readonly isOpen: _angular_core.Signal<boolean>;
323
+ /** What the trigger badge counts: the applied value when an Apply step gates it, the live draft otherwise. */
324
+ readonly triggerFilterCount: _angular_core.Signal<number>;
325
+ readonly triggerFilterCountActive: _angular_core.Signal<boolean>;
320
326
  private panelOpenAtGestureStart;
321
327
  savePresetsDropdownItems: _angular_core.Signal<ActionDropdownItem[]>;
322
328
  /** Opens the dropdown menu at the specified trigger element */