@agorapulse/ui-components 22.0.31 → 22.0.33
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.
- package/agorapulse-ui-components-22.0.33.tgz +0 -0
- package/fesm2022/agorapulse-ui-components-floating.mjs +451 -0
- package/fesm2022/agorapulse-ui-components-floating.mjs.map +1 -0
- package/fesm2022/agorapulse-ui-components-popover.mjs +200 -0
- package/fesm2022/agorapulse-ui-components-popover.mjs.map +1 -0
- package/fesm2022/agorapulse-ui-components.mjs +1 -0
- package/fesm2022/agorapulse-ui-components.mjs.map +1 -1
- package/package.json +10 -1
- package/types/agorapulse-ui-components-floating.d.ts +167 -0
- package/types/agorapulse-ui-components-popover.d.ts +92 -0
- package/types/agorapulse-ui-components.d.ts +2 -0
- package/agorapulse-ui-components-22.0.31.tgz +0 -0
|
Binary file
|
|
@@ -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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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { CloseButtonComponent } from '@agorapulse/ui-components/close-button';
|
|
2
|
+
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
3
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { input, output, computed, ChangeDetectionStrategy, Component, inject, ElementRef, Directive } from '@angular/core';
|
|
6
|
+
import { createFloatingOverlay } from '@agorapulse/ui-components/floating';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The `role="dialog"` surface, its optional header and its focus trap. Instantiated by the popover
|
|
10
|
+
* directive, never by a consumer.
|
|
11
|
+
*
|
|
12
|
+
* Focus is the CDK's: `cdkTrapFocus` confines Tab, `autoCapture` focuses on open and restores the
|
|
13
|
+
* trigger on destruction. The cost is that Tab cannot leave the panel — Escape or the button do.
|
|
14
|
+
*/
|
|
15
|
+
class PopoverPanelComponent {
|
|
16
|
+
static nextId = 0;
|
|
17
|
+
/** The consumer's content. Always a template: the directive sits on the trigger, not here. */
|
|
18
|
+
content = input.required(/* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
20
|
+
/** Mirrors the popover's heading, and gives the dialog its accessible name. */
|
|
21
|
+
heading = input(/* @ts-ignore */
|
|
22
|
+
...(ngDevMode ? [undefined, { debugName: "heading" }] : /* istanbul ignore next */ []));
|
|
23
|
+
/** Mirrors the popover's input of the same name. */
|
|
24
|
+
closable = input(false, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
|
|
26
|
+
/** Mirrors the popover's backdrop, which is what makes the page genuinely inert. */
|
|
27
|
+
backdrop = input(false, /* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [{ debugName: "backdrop" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/** Mirrors the popover's, and names the dialog when there is no heading. */
|
|
30
|
+
ariaLabel = input(/* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
32
|
+
closeAriaLabel = input('Close', /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "closeAriaLabel" }] : /* istanbul ignore next */ []));
|
|
34
|
+
/** Set by the directive, which needs it for the trigger's `aria-controls`. */
|
|
35
|
+
panelId = input('', /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
37
|
+
/**
|
|
38
|
+
* The id of the element that names the dialog when nothing else does — the trigger, set by the
|
|
39
|
+
* directive. An id rather than its text, so the name is computed on the live DOM: that follows a
|
|
40
|
+
* label that changes, and reads a trigger whose own name is an `aria-label`.
|
|
41
|
+
*/
|
|
42
|
+
fallbackLabelId = input(/* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [undefined, { debugName: "fallbackLabelId" }] : /* istanbul ignore next */ []));
|
|
44
|
+
closed = output();
|
|
45
|
+
headingId = `ap-popover-heading-${PopoverPanelComponent.nextId++}`;
|
|
46
|
+
/** A dialog must be named. The heading does it, failing that the trigger. */
|
|
47
|
+
labelledBy = computed(() => {
|
|
48
|
+
if (this.heading()) {
|
|
49
|
+
return this.headingId;
|
|
50
|
+
}
|
|
51
|
+
return this.ariaLabel() ? null : (this.fallbackLabelId() ?? null);
|
|
52
|
+
}, /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
|
|
54
|
+
label = computed(() => (this.heading() ? null : (this.ariaLabel() ?? null)), /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
56
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: PopoverPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
57
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: PopoverPanelComponent, isStandalone: true, selector: "ap-popover-panel", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, backdrop: { classPropertyName: "backdrop", publicName: "backdrop", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, closeAriaLabel: { classPropertyName: "closeAriaLabel", publicName: "closeAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: false, transformFunction: null }, fallbackLabelId: { classPropertyName: "fallbackLabelId", publicName: "fallbackLabelId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<div\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\">\n <div\n class=\"ap-popover__panel\"\n role=\"dialog\"\n tabindex=\"-1\"\n cdkFocusInitial\n [id]=\"panelId()\"\n [attr.aria-modal]=\"backdrop() || null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-label]=\"label()\">\n @if (heading() || closable()) {\n <div class=\"ap-popover__header\">\n @if (heading()) {\n <h2\n class=\"ap-popover__heading\"\n [id]=\"headingId\">\n {{ heading() }}\n </h2>\n }\n @if (closable()) {\n <ap-close-button\n [ariaLabel]=\"closeAriaLabel()\"\n (closed)=\"closed.emit()\" />\n }\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"content()\" />\n </div>\n</div>\n", styles: [":host{display:block;box-sizing:border-box;background-color:var(--comp-popover-background-color);border-radius:var(--comp-popover-border-radius);box-shadow:var(--comp-popover-box-shadow);padding:var(--comp-popover-padding)}.ap-popover__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--comp-popover-header-gap);margin-bottom:var(--comp-popover-header-margin-bottom)}.ap-popover__heading{margin:0;color:var(--comp-popover-heading-color);font-family:var(--comp-popover-heading-font-family);font-size:var(--comp-popover-heading-size);font-weight:var(--comp-popover-heading-weight);line-height:var(--comp-popover-heading-line-height)}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: CloseButtonComponent, selector: "ap-close-button", inputs: ["disabled", "ariaLabel", "dataTest"], outputs: ["closed"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
58
|
+
}
|
|
59
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: PopoverPanelComponent, decorators: [{
|
|
60
|
+
type: Component,
|
|
61
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ap-popover-panel', imports: [CdkTrapFocus, CloseButtonComponent, NgTemplateOutlet], template: "<div\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\">\n <div\n class=\"ap-popover__panel\"\n role=\"dialog\"\n tabindex=\"-1\"\n cdkFocusInitial\n [id]=\"panelId()\"\n [attr.aria-modal]=\"backdrop() || null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-label]=\"label()\">\n @if (heading() || closable()) {\n <div class=\"ap-popover__header\">\n @if (heading()) {\n <h2\n class=\"ap-popover__heading\"\n [id]=\"headingId\">\n {{ heading() }}\n </h2>\n }\n @if (closable()) {\n <ap-close-button\n [ariaLabel]=\"closeAriaLabel()\"\n (closed)=\"closed.emit()\" />\n }\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"content()\" />\n </div>\n</div>\n", styles: [":host{display:block;box-sizing:border-box;background-color:var(--comp-popover-background-color);border-radius:var(--comp-popover-border-radius);box-shadow:var(--comp-popover-box-shadow);padding:var(--comp-popover-padding)}.ap-popover__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--comp-popover-header-gap);margin-bottom:var(--comp-popover-header-margin-bottom)}.ap-popover__heading{margin:0;color:var(--comp-popover-heading-color);font-family:var(--comp-popover-heading-font-family);font-size:var(--comp-popover-heading-size);font-weight:var(--comp-popover-heading-weight);line-height:var(--comp-popover-heading-line-height)}\n"] }]
|
|
62
|
+
}], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], backdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdrop", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], closeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeAriaLabel", required: false }] }], panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: false }] }], fallbackLabelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackLabelId", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A click-triggered interactive panel: `role="dialog"`, managed focus, Escape, optional backdrop.
|
|
66
|
+
* A tooltip is the opposite — descriptive, hover-triggered, and never focusable.
|
|
67
|
+
*
|
|
68
|
+
* Sits on the **trigger**, so it owns the trigger's ARIA and the content is always a `TemplateRef`.
|
|
69
|
+
* Inputs are prefixed one by one rather than bundled: an inline config object would be recreated on
|
|
70
|
+
* every change-detection cycle and thrash the overlay.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* <button [apPopover]="shareTpl" apPopoverHeading="Share">Share</button>
|
|
74
|
+
* <ng-template #shareTpl>…</ng-template>
|
|
75
|
+
*/
|
|
76
|
+
class PopoverDirective {
|
|
77
|
+
static nextId = 0;
|
|
78
|
+
instanceId = PopoverDirective.nextId++;
|
|
79
|
+
floating = createFloatingOverlay();
|
|
80
|
+
triggerElement = inject(ElementRef);
|
|
81
|
+
panelRef = null;
|
|
82
|
+
/** The panel's content. */
|
|
83
|
+
apPopover = input.required(/* @ts-ignore */
|
|
84
|
+
...(ngDevMode ? [{ debugName: "apPopover" }] : /* istanbul ignore next */ []));
|
|
85
|
+
/** Unset means derived from the anchor mode. There is no `'auto'` value. */
|
|
86
|
+
apPopoverPlacement = input(/* @ts-ignore */
|
|
87
|
+
...(ngDevMode ? [undefined, { debugName: "apPopoverPlacement" }] : /* istanbul ignore next */ []));
|
|
88
|
+
apPopoverAnchor = input('trigger', /* @ts-ignore */
|
|
89
|
+
...(ngDevMode ? [{ debugName: "apPopoverAnchor" }] : /* istanbul ignore next */ []));
|
|
90
|
+
apPopoverArrow = input(false, /* @ts-ignore */
|
|
91
|
+
...(ngDevMode ? [{ debugName: "apPopoverArrow" }] : /* istanbul ignore next */ []));
|
|
92
|
+
apPopoverArrowTarget = input('anchor', /* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [{ debugName: "apPopoverArrowTarget" }] : /* istanbul ignore next */ []));
|
|
94
|
+
/** Shows a close button — and, by doing so, makes it *the* way to close: no more outside click. */
|
|
95
|
+
apPopoverClosable = input(false, /* @ts-ignore */
|
|
96
|
+
...(ngDevMode ? [{ debugName: "apPopoverClosable" }] : /* istanbul ignore next */ []));
|
|
97
|
+
/** Blocks the page behind. Non-modal by default — that is the point of a popover. */
|
|
98
|
+
apPopoverBackdrop = input(false, /* @ts-ignore */
|
|
99
|
+
...(ngDevMode ? [{ debugName: "apPopoverBackdrop" }] : /* istanbul ignore next */ []));
|
|
100
|
+
/** Optional heading. When set, it becomes the dialog's accessible name. */
|
|
101
|
+
apPopoverHeading = input(/* @ts-ignore */
|
|
102
|
+
...(ngDevMode ? [undefined, { debugName: "apPopoverHeading" }] : /* istanbul ignore next */ []));
|
|
103
|
+
/** Accessible name used when there is no heading. */
|
|
104
|
+
apPopoverAriaLabel = input(/* @ts-ignore */
|
|
105
|
+
...(ngDevMode ? [undefined, { debugName: "apPopoverAriaLabel" }] : /* istanbul ignore next */ []));
|
|
106
|
+
/** An input rather than a hard-coded string: several of the DS's own labels read badly. */
|
|
107
|
+
apPopoverCloseAriaLabel = input('Close', /* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [{ debugName: "apPopoverCloseAriaLabel" }] : /* istanbul ignore next */ []));
|
|
109
|
+
apPopoverPanelClass = input(/* @ts-ignore */
|
|
110
|
+
...(ngDevMode ? [undefined, { debugName: "apPopoverPanelClass" }] : /* istanbul ignore next */ []));
|
|
111
|
+
isOpen = this.floating.isOpen;
|
|
112
|
+
panelId = `ap-popover-${this.instanceId}`;
|
|
113
|
+
open(event) {
|
|
114
|
+
if (this.isOpen())
|
|
115
|
+
return;
|
|
116
|
+
this.panelRef = this.floating.open(PopoverPanelComponent, this.triggerElement.nativeElement, {
|
|
117
|
+
placement: this.apPopoverPlacement(),
|
|
118
|
+
anchor: this.apPopoverAnchor(),
|
|
119
|
+
arrow: this.apPopoverArrow(),
|
|
120
|
+
arrowTarget: this.apPopoverArrowTarget(),
|
|
121
|
+
showBackdrop: this.apPopoverBackdrop(),
|
|
122
|
+
panelClass: this.apPopoverPanelClass(),
|
|
123
|
+
// Escape always closes: APG requires it of a dialog. An outside click does not.
|
|
124
|
+
onEscape: () => this.close(),
|
|
125
|
+
onOutsideClick: () => {
|
|
126
|
+
if (!this.apPopoverClosable()) {
|
|
127
|
+
this.close();
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
}, event);
|
|
131
|
+
this.panelRef?.setInput('content', this.apPopover());
|
|
132
|
+
this.panelRef?.setInput('panelId', this.panelId);
|
|
133
|
+
this.panelRef?.setInput('heading', this.apPopoverHeading());
|
|
134
|
+
this.panelRef?.setInput('closable', this.apPopoverClosable());
|
|
135
|
+
this.panelRef?.setInput('backdrop', this.apPopoverBackdrop());
|
|
136
|
+
this.panelRef?.setInput('ariaLabel', this.apPopoverAriaLabel());
|
|
137
|
+
this.panelRef?.setInput('closeAriaLabel', this.apPopoverCloseAriaLabel());
|
|
138
|
+
this.panelRef?.setInput('fallbackLabelId', this.ensureTriggerId());
|
|
139
|
+
this.panelRef?.instance.closed.subscribe(() => this.close());
|
|
140
|
+
// Render before repositioning: `attach()` measured an unevaluated template, so the first
|
|
141
|
+
// position is for an empty box and the panel jumps once the content lands.
|
|
142
|
+
this.panelRef?.changeDetectorRef.detectChanges();
|
|
143
|
+
this.floating.updatePosition();
|
|
144
|
+
}
|
|
145
|
+
/** The dialog falls back to being named by its trigger, and `aria-labelledby` needs an id to point at. */
|
|
146
|
+
ensureTriggerId() {
|
|
147
|
+
const trigger = this.triggerElement.nativeElement;
|
|
148
|
+
if (!trigger.id) {
|
|
149
|
+
trigger.id = `ap-popover-trigger-${this.instanceId}`;
|
|
150
|
+
}
|
|
151
|
+
this.warnWhenNameless(trigger);
|
|
152
|
+
return trigger.id;
|
|
153
|
+
}
|
|
154
|
+
/** The residual case the fallback cannot cover: a trigger that names nothing either. */
|
|
155
|
+
warnWhenNameless(trigger) {
|
|
156
|
+
const hasOwnName = Boolean(this.apPopoverHeading()) || Boolean(this.apPopoverAriaLabel());
|
|
157
|
+
// An icon-only trigger has no text but may carry an `aria-label`, which names it just as well.
|
|
158
|
+
const triggerNamesIt = Boolean(trigger.textContent?.trim()) || Boolean(trigger.getAttribute('aria-label'));
|
|
159
|
+
if (hasOwnName || triggerNamesIt) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
console.warn(`[Popover] The dialog opened by #${trigger.id} has no accessible name: it has neither a ` +
|
|
163
|
+
'heading nor an aria-label, and its trigger has no text. Set apPopoverHeading or apPopoverAriaLabel.');
|
|
164
|
+
}
|
|
165
|
+
close() {
|
|
166
|
+
this.panelRef = null;
|
|
167
|
+
this.floating.close();
|
|
168
|
+
}
|
|
169
|
+
toggle(event) {
|
|
170
|
+
if (this.isOpen()) {
|
|
171
|
+
this.close();
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
this.open(event);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: PopoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
178
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: PopoverDirective, isStandalone: true, selector: "[apPopover]", inputs: { apPopover: { classPropertyName: "apPopover", publicName: "apPopover", isSignal: true, isRequired: true, transformFunction: null }, apPopoverPlacement: { classPropertyName: "apPopoverPlacement", publicName: "apPopoverPlacement", isSignal: true, isRequired: false, transformFunction: null }, apPopoverAnchor: { classPropertyName: "apPopoverAnchor", publicName: "apPopoverAnchor", isSignal: true, isRequired: false, transformFunction: null }, apPopoverArrow: { classPropertyName: "apPopoverArrow", publicName: "apPopoverArrow", isSignal: true, isRequired: false, transformFunction: null }, apPopoverArrowTarget: { classPropertyName: "apPopoverArrowTarget", publicName: "apPopoverArrowTarget", isSignal: true, isRequired: false, transformFunction: null }, apPopoverClosable: { classPropertyName: "apPopoverClosable", publicName: "apPopoverClosable", isSignal: true, isRequired: false, transformFunction: null }, apPopoverBackdrop: { classPropertyName: "apPopoverBackdrop", publicName: "apPopoverBackdrop", isSignal: true, isRequired: false, transformFunction: null }, apPopoverHeading: { classPropertyName: "apPopoverHeading", publicName: "apPopoverHeading", isSignal: true, isRequired: false, transformFunction: null }, apPopoverAriaLabel: { classPropertyName: "apPopoverAriaLabel", publicName: "apPopoverAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, apPopoverCloseAriaLabel: { classPropertyName: "apPopoverCloseAriaLabel", publicName: "apPopoverCloseAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, apPopoverPanelClass: { classPropertyName: "apPopoverPanelClass", publicName: "apPopoverPanelClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "toggle($event)" }, properties: { "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "isOpen()", "attr.aria-controls": "isOpen() ? panelId : null" } }, exportAs: ["apPopover"], ngImport: i0 });
|
|
179
|
+
}
|
|
180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: PopoverDirective, decorators: [{
|
|
181
|
+
type: Directive,
|
|
182
|
+
args: [{
|
|
183
|
+
selector: '[apPopover]',
|
|
184
|
+
exportAs: 'apPopover',
|
|
185
|
+
host: {
|
|
186
|
+
'[attr.aria-haspopup]': '"dialog"',
|
|
187
|
+
'[attr.aria-expanded]': 'isOpen()',
|
|
188
|
+
// Only while open: pointing `aria-controls` at an id that does not exist yet is invalid.
|
|
189
|
+
'[attr.aria-controls]': 'isOpen() ? panelId : null',
|
|
190
|
+
'(click)': 'toggle($event)',
|
|
191
|
+
},
|
|
192
|
+
}]
|
|
193
|
+
}], propDecorators: { apPopover: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopover", required: true }] }], apPopoverPlacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverPlacement", required: false }] }], apPopoverAnchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverAnchor", required: false }] }], apPopoverArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverArrow", required: false }] }], apPopoverArrowTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverArrowTarget", required: false }] }], apPopoverClosable: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverClosable", required: false }] }], apPopoverBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverBackdrop", required: false }] }], apPopoverHeading: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverHeading", required: false }] }], apPopoverAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverAriaLabel", required: false }] }], apPopoverCloseAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverCloseAriaLabel", required: false }] }], apPopoverPanelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "apPopoverPanelClass", required: false }] }] } });
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Generated bundle index. Do not edit.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
export { PopoverDirective, PopoverPanelComponent };
|
|
200
|
+
//# sourceMappingURL=agorapulse-ui-components-popover.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agorapulse-ui-components-popover.mjs","sources":["../../../libs/ui-components/popover/src/popover-panel/popover-panel.component.ts","../../../libs/ui-components/popover/src/popover-panel/popover-panel.component.html","../../../libs/ui-components/popover/src/popover.directive.ts","../../../libs/ui-components/popover/src/agorapulse-ui-components-popover.ts"],"sourcesContent":["import { CloseButtonComponent } from '@agorapulse/ui-components/close-button';\nimport { CdkTrapFocus } from '@angular/cdk/a11y';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input, output, TemplateRef } from '@angular/core';\n\n/**\n * The `role=\"dialog\"` surface, its optional header and its focus trap. Instantiated by the popover\n * directive, never by a consumer.\n *\n * Focus is the CDK's: `cdkTrapFocus` confines Tab, `autoCapture` focuses on open and restores the\n * trigger on destruction. The cost is that Tab cannot leave the panel — Escape or the button do.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ap-popover-panel',\n imports: [CdkTrapFocus, CloseButtonComponent, NgTemplateOutlet],\n templateUrl: 'popover-panel.component.html',\n styleUrls: ['popover-panel.component.scss'],\n})\nexport class PopoverPanelComponent {\n private static nextId = 0;\n\n /** The consumer's content. Always a template: the directive sits on the trigger, not here. */\n readonly content = input.required<TemplateRef<unknown>>();\n\n /** Mirrors the popover's heading, and gives the dialog its accessible name. */\n readonly heading = input<string>();\n\n /** Mirrors the popover's input of the same name. */\n readonly closable = input<boolean>(false);\n\n /** Mirrors the popover's backdrop, which is what makes the page genuinely inert. */\n readonly backdrop = input<boolean>(false);\n\n /** Mirrors the popover's, and names the dialog when there is no heading. */\n readonly ariaLabel = input<string>();\n\n readonly closeAriaLabel = input<string>('Close');\n\n /** Set by the directive, which needs it for the trigger's `aria-controls`. */\n readonly panelId = input<string>('');\n\n /**\n * The id of the element that names the dialog when nothing else does — the trigger, set by the\n * directive. An id rather than its text, so the name is computed on the live DOM: that follows a\n * label that changes, and reads a trigger whose own name is an `aria-label`.\n */\n readonly fallbackLabelId = input<string>();\n\n readonly closed = output<void>();\n\n protected readonly headingId = `ap-popover-heading-${PopoverPanelComponent.nextId++}`;\n\n /** A dialog must be named. The heading does it, failing that the trigger. */\n protected readonly labelledBy = computed<string | null>(() => {\n if (this.heading()) {\n return this.headingId;\n }\n return this.ariaLabel() ? null : (this.fallbackLabelId() ?? null);\n });\n\n protected readonly label = computed<string | null>(() => (this.heading() ? null : (this.ariaLabel() ?? null)));\n}\n","<div\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\">\n <div\n class=\"ap-popover__panel\"\n role=\"dialog\"\n tabindex=\"-1\"\n cdkFocusInitial\n [id]=\"panelId()\"\n [attr.aria-modal]=\"backdrop() || null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-label]=\"label()\">\n @if (heading() || closable()) {\n <div class=\"ap-popover__header\">\n @if (heading()) {\n <h2\n class=\"ap-popover__heading\"\n [id]=\"headingId\">\n {{ heading() }}\n </h2>\n }\n @if (closable()) {\n <ap-close-button\n [ariaLabel]=\"closeAriaLabel()\"\n (closed)=\"closed.emit()\" />\n }\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"content()\" />\n </div>\n</div>\n","import { createFloatingOverlay, FloatingAnchorMode, FloatingPlacement } from '@agorapulse/ui-components/floating';\nimport { ComponentRef, Directive, ElementRef, inject, input, TemplateRef } from '@angular/core';\nimport { PopoverPanelComponent } from './popover-panel/popover-panel.component';\n\n/**\n * A click-triggered interactive panel: `role=\"dialog\"`, managed focus, Escape, optional backdrop.\n * A tooltip is the opposite — descriptive, hover-triggered, and never focusable.\n *\n * Sits on the **trigger**, so it owns the trigger's ARIA and the content is always a `TemplateRef`.\n * Inputs are prefixed one by one rather than bundled: an inline config object would be recreated on\n * every change-detection cycle and thrash the overlay.\n *\n * @example\n * <button [apPopover]=\"shareTpl\" apPopoverHeading=\"Share\">Share</button>\n * <ng-template #shareTpl>…</ng-template>\n */\n@Directive({\n selector: '[apPopover]',\n exportAs: 'apPopover',\n host: {\n '[attr.aria-haspopup]': '\"dialog\"',\n '[attr.aria-expanded]': 'isOpen()',\n // Only while open: pointing `aria-controls` at an id that does not exist yet is invalid.\n '[attr.aria-controls]': 'isOpen() ? panelId : null',\n '(click)': 'toggle($event)',\n },\n})\nexport class PopoverDirective {\n private static nextId = 0;\n\n private readonly instanceId = PopoverDirective.nextId++;\n private readonly floating = createFloatingOverlay();\n private readonly triggerElement = inject<ElementRef<HTMLElement>>(ElementRef);\n private panelRef: ComponentRef<PopoverPanelComponent> | null = null;\n\n /** The panel's content. */\n readonly apPopover = input.required<TemplateRef<unknown>>();\n\n /** Unset means derived from the anchor mode. There is no `'auto'` value. */\n readonly apPopoverPlacement = input<FloatingPlacement>();\n readonly apPopoverAnchor = input<FloatingAnchorMode>('trigger');\n readonly apPopoverArrow = input<boolean>(false);\n readonly apPopoverArrowTarget = input<'anchor' | 'pointer'>('anchor');\n\n /** Shows a close button — and, by doing so, makes it *the* way to close: no more outside click. */\n readonly apPopoverClosable = input<boolean>(false);\n\n /** Blocks the page behind. Non-modal by default — that is the point of a popover. */\n readonly apPopoverBackdrop = input<boolean>(false);\n\n /** Optional heading. When set, it becomes the dialog's accessible name. */\n readonly apPopoverHeading = input<string>();\n\n /** Accessible name used when there is no heading. */\n readonly apPopoverAriaLabel = input<string>();\n\n /** An input rather than a hard-coded string: several of the DS's own labels read badly. */\n readonly apPopoverCloseAriaLabel = input<string>('Close');\n\n readonly apPopoverPanelClass = input<string | string[]>();\n\n readonly isOpen = this.floating.isOpen;\n\n protected readonly panelId = `ap-popover-${this.instanceId}`;\n\n open(event?: MouseEvent): void {\n if (this.isOpen()) return;\n\n this.panelRef = this.floating.open(\n PopoverPanelComponent,\n this.triggerElement.nativeElement,\n {\n placement: this.apPopoverPlacement(),\n anchor: this.apPopoverAnchor(),\n arrow: this.apPopoverArrow(),\n arrowTarget: this.apPopoverArrowTarget(),\n showBackdrop: this.apPopoverBackdrop(),\n panelClass: this.apPopoverPanelClass(),\n // Escape always closes: APG requires it of a dialog. An outside click does not.\n onEscape: () => this.close(),\n onOutsideClick: () => {\n if (!this.apPopoverClosable()) {\n this.close();\n }\n },\n },\n event\n );\n\n this.panelRef?.setInput('content', this.apPopover());\n this.panelRef?.setInput('panelId', this.panelId);\n this.panelRef?.setInput('heading', this.apPopoverHeading());\n this.panelRef?.setInput('closable', this.apPopoverClosable());\n this.panelRef?.setInput('backdrop', this.apPopoverBackdrop());\n this.panelRef?.setInput('ariaLabel', this.apPopoverAriaLabel());\n this.panelRef?.setInput('closeAriaLabel', this.apPopoverCloseAriaLabel());\n this.panelRef?.setInput('fallbackLabelId', this.ensureTriggerId());\n this.panelRef?.instance.closed.subscribe(() => this.close());\n\n // Render before repositioning: `attach()` measured an unevaluated template, so the first\n // position is for an empty box and the panel jumps once the content lands.\n this.panelRef?.changeDetectorRef.detectChanges();\n this.floating.updatePosition();\n }\n\n /** The dialog falls back to being named by its trigger, and `aria-labelledby` needs an id to point at. */\n private ensureTriggerId(): string {\n const trigger = this.triggerElement.nativeElement;\n if (!trigger.id) {\n trigger.id = `ap-popover-trigger-${this.instanceId}`;\n }\n\n this.warnWhenNameless(trigger);\n return trigger.id;\n }\n\n /** The residual case the fallback cannot cover: a trigger that names nothing either. */\n private warnWhenNameless(trigger: HTMLElement): void {\n const hasOwnName = Boolean(this.apPopoverHeading()) || Boolean(this.apPopoverAriaLabel());\n // An icon-only trigger has no text but may carry an `aria-label`, which names it just as well.\n const triggerNamesIt = Boolean(trigger.textContent?.trim()) || Boolean(trigger.getAttribute('aria-label'));\n if (hasOwnName || triggerNamesIt) {\n return;\n }\n\n console.warn(\n `[Popover] The dialog opened by #${trigger.id} has no accessible name: it has neither a ` +\n 'heading nor an aria-label, and its trigger has no text. Set apPopoverHeading or apPopoverAriaLabel.'\n );\n }\n\n close(): void {\n this.panelRef = null;\n this.floating.close();\n }\n\n toggle(event?: MouseEvent): void {\n if (this.isOpen()) {\n this.close();\n } else {\n this.open(event);\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,7 @@ export { CustomTooltipType, TooltipDirective, TooltipExternalTriggerDirective }
|
|
|
41
41
|
import * as i0 from '@angular/core';
|
|
42
42
|
import { NgModule } from '@angular/core';
|
|
43
43
|
import { MAT_TABS_CONFIG } from '@angular/material/tabs';
|
|
44
|
+
export { PopoverDirective } from '@agorapulse/ui-components/popover';
|
|
44
45
|
export { DropdownTriggerDirective, createDropdownOverlay } from '@agorapulse/ui-components/dropdown-base';
|
|
45
46
|
export { ActionDropdownComponent, ActionDropdownTriggerDirective } from '@agorapulse/ui-components/action-dropdown';
|
|
46
47
|
export { AutocompleteComponent } from '@agorapulse/ui-components/autocomplete';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agorapulse-ui-components.mjs","sources":["../../../libs/ui-components/src/lib/agorapulse-ui-components.module.ts","../../../libs/ui-components/index.ts","../../../libs/ui-components/agorapulse-ui-components.ts"],"sourcesContent":["// Modules\nimport { AddCommentComponent } from '@agorapulse/ui-components/add-comment';\nimport { AvatarComponent } from '@agorapulse/ui-components/avatar';\nimport { ConfirmModalComponent } from '@agorapulse/ui-components/confirm-modal';\nimport { DatepickerComponent } from '@agorapulse/ui-components/datepicker';\nimport {\n AutosizeTextareaDirective,\n DefaultImageDirective,\n EllipsisDirective,\n EqualValidatorDirective,\n FrozenGifDirective,\n MultiStyleTextDirective,\n} from '@agorapulse/ui-components/directives';\nimport { DotStepperComponent } from '@agorapulse/ui-components/dot-stepper';\nimport { InfoboxComponent } from '@agorapulse/ui-components/infobox';\nimport { LabelComponent, LabelListComponent } from '@agorapulse/ui-components/labels';\nimport { LabelsSelectorComponent } from '@agorapulse/ui-components/labels-selector';\nimport { MediaDisplayOverlayDialogComponent } from '@agorapulse/ui-components/media-display-overlay';\nimport { ModalComponent } from '@agorapulse/ui-components/modal';\nimport { DayDisabledPipe, NeoDatepickerComponent } from '@agorapulse/ui-components/neo-datepicker';\nimport { NotificationComponent } from '@agorapulse/ui-components/notification';\nimport { PaginatorButtonComponent, PaginatorComponent } from '@agorapulse/ui-components/paginator';\nimport { PasswordInputComponent } from '@agorapulse/ui-components/password-input';\nimport { PopmenuModule } from '@agorapulse/ui-components/popmenu';\nimport { SlideToggleComponent } from '@agorapulse/ui-components/slide-toggle';\nimport { SnackbarsThreadComponent } from '@agorapulse/ui-components/snackbars-thread';\nimport { StepperComponent } from '@agorapulse/ui-components/stepper';\nimport { TooltipDirective } from '@agorapulse/ui-components/tooltip';\nimport { NgModule } from '@angular/core';\nimport { MAT_TABS_CONFIG } from '@angular/material/tabs';\n\n/**\n * @deprecated for better tree-shaking, use standalone component import instead\n */\n@NgModule({\n declarations: [],\n imports: [\n // Components\n AvatarComponent,\n StepperComponent,\n ConfirmModalComponent,\n DatepickerComponent,\n DotStepperComponent,\n EllipsisDirective,\n InfoboxComponent,\n LabelListComponent,\n LabelsSelectorComponent,\n NeoDatepickerComponent,\n MediaDisplayOverlayDialogComponent,\n ModalComponent,\n PasswordInputComponent,\n LabelComponent,\n NotificationComponent,\n PaginatorComponent,\n PaginatorButtonComponent,\n SlideToggleComponent,\n SnackbarsThreadComponent,\n // Directives\n DefaultImageDirective,\n FrozenGifDirective,\n EqualValidatorDirective,\n MultiStyleTextDirective,\n TooltipDirective,\n AddCommentComponent,\n AutosizeTextareaDirective,\n // Pipes\n DayDisabledPipe,\n ],\n exports: [\n // Components\n AddCommentComponent,\n AvatarComponent,\n StepperComponent,\n ConfirmModalComponent,\n DatepickerComponent,\n NeoDatepickerComponent,\n DotStepperComponent,\n EllipsisDirective,\n InfoboxComponent,\n LabelComponent,\n LabelListComponent,\n MediaDisplayOverlayDialogComponent,\n ModalComponent,\n PasswordInputComponent,\n LabelsSelectorComponent,\n NotificationComponent,\n PaginatorComponent,\n PaginatorButtonComponent,\n SlideToggleComponent,\n SnackbarsThreadComponent,\n // Pipes\n DayDisabledPipe,\n // Directives\n AutosizeTextareaDirective,\n DefaultImageDirective,\n FrozenGifDirective,\n EqualValidatorDirective,\n MultiStyleTextDirective,\n TooltipDirective,\n // Modules\n PopmenuModule,\n ],\n providers: [\n // Disable ripple effect\n // {provide: MAT_RIPPLE_GLOBAL_OPTIONS, useValue: {disabled: true}},\n // Disable tabs animation\n { provide: MAT_TABS_CONFIG, useValue: { animationDuration: '0ms' } },\n ],\n})\nexport class AgorapulseUiComponentsModule {}\n","/*\n * Public API Surface of ui\n */\n\n// Module\nexport { PopmenuModule } from '@agorapulse/ui-components/popmenu';\nexport { AgorapulseUiComponentsModule } from './src/lib/agorapulse-ui-components.module';\n\n// Directive\nexport {\n AutosizeTextareaDirective,\n CheckboxDirective,\n DefaultImageDirective,\n EllipsisDirective,\n EqualValidatorDirective,\n FrozenGifDirective,\n MultiStyleTextDirective,\n} from '@agorapulse/ui-components/directives';\nexport { PopmenuDirective } from '@agorapulse/ui-components/popmenu';\nexport { TooltipDirective, TooltipExternalTriggerDirective } from '@agorapulse/ui-components/tooltip';\n\n// Dropdown base\nexport { DropdownOverlay, DropdownTriggerDirective, createDropdownOverlay } from '@agorapulse/ui-components/dropdown-base';\n\n// Component\nexport { ActionDropdownComponent, ActionDropdownItem, ActionDropdownTriggerDirective } from '@agorapulse/ui-components/action-dropdown';\nexport { AddCommentComponent } from '@agorapulse/ui-components/add-comment';\nexport { AutocompleteComponent } from '@agorapulse/ui-components/autocomplete';\nexport { AvatarComponent, AvatarItem } from '@agorapulse/ui-components/avatar';\nexport { BadgeComponent } from '@agorapulse/ui-components/badge';\nexport { ButtonComponent } from '@agorapulse/ui-components/button';\nexport { CheckboxComponent } from '@agorapulse/ui-components/checkbox';\nexport { ConfirmModalComponent } from '@agorapulse/ui-components/confirm-modal';\nexport { CounterComponent } from '@agorapulse/ui-components/counter';\nexport { DatepickerComponent, DatepickerMode, I18nDatePicker, Period } from '@agorapulse/ui-components/datepicker';\nexport { DateRangePickerComponent, DateRangePickerPreset, defaultDateRangePickerPresets } from '@agorapulse/ui-components/date-range-picker';\nexport { DotStepperComponent } from '@agorapulse/ui-components/dot-stepper';\nexport { IconButtonComponent } from '@agorapulse/ui-components/icon-button';\nexport { InfoboxComponent } from '@agorapulse/ui-components/infobox';\nexport { LabelComponent, LabelListComponent } from '@agorapulse/ui-components/labels';\nexport { LabelsSelectorComponent } from '@agorapulse/ui-components/labels-selector';\nexport { InputComponent } from '@agorapulse/ui-components/legacy/input';\nexport { SelectComponent } from '@agorapulse/ui-components/legacy/select';\nexport { TextareaComponent } from '@agorapulse/ui-components/legacy/textarea';\nexport { MediaDisplayOverlayDialogComponent } from '@agorapulse/ui-components/media-display-overlay';\nexport { ModalComponent, ModalConfig } from '@agorapulse/ui-components/modal';\nexport { NavSelectorComponent } from '@agorapulse/ui-components/nav-selector';\nexport {\n DayDisabledPipe,\n NeoDatePickerLocale,\n NeoDatePickerMode,\n NeoDatePickerStartsOn,\n NeoDatepickerComponent,\n} from '@agorapulse/ui-components/neo-datepicker';\nexport { NotificationComponent } from '@agorapulse/ui-components/notification';\nexport { PaginatorButtonComponent, PaginatorComponent } from '@agorapulse/ui-components/paginator';\nexport { PasswordInputComponent } from '@agorapulse/ui-components/password-input';\nexport { PopmenuComponent } from '@agorapulse/ui-components/popmenu';\nexport { RadioComponent } from '@agorapulse/ui-components/radio';\nexport { RadioButtonCardComponent } from '@agorapulse/ui-components/radio-button-card';\nexport { SegmentedControlComponent, SegmentedControlOption } from '@agorapulse/ui-components/segmented-control';\nexport {\n SelectionDropdownComponent,\n SelectionDropdownItem,\n SelectionDropdownTriggerDirective,\n} from '@agorapulse/ui-components/selection-dropdown';\nexport { SlideToggleComponent } from '@agorapulse/ui-components/slide-toggle';\nexport { SnackbarsThreadComponent } from '@agorapulse/ui-components/snackbars-thread';\nexport { SocialButtonComponent } from '@agorapulse/ui-components/social-button';\nexport { StatusComponent } from '@agorapulse/ui-components/status';\nexport { StatusCardActor, StatusCardComponent } from '@agorapulse/ui-components/status-card';\nexport { StepperComponent } from '@agorapulse/ui-components/stepper';\nexport { TagComponent } from '@agorapulse/ui-components/tag';\nexport { ToggleComponent } from '@agorapulse/ui-components/toggle';\n\n// Service\nexport { SnackbarsThreadService } from '@agorapulse/ui-components/snackbars-thread';\n\n// Model\nexport { ConfirmModalTexts } from '@agorapulse/ui-components/confirm-modal';\nexport * from '@agorapulse/ui-components/filter-dropdown';\nexport {\n CodeStatus,\n SnackbarTypeValues,\n SnackbarsThreadBase,\n externalSnackbarTypeAllowed,\n generateCodeStatus,\n} from '@agorapulse/ui-components/snackbars-thread';\nexport { Step } from '@agorapulse/ui-components/stepper';\nexport { CustomTooltipAvatarItem, CustomTooltipPresentationItem, CustomTooltipType } from '@agorapulse/ui-components/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agorapulse-ui-components.mjs","sources":["../../../libs/ui-components/src/lib/agorapulse-ui-components.module.ts","../../../libs/ui-components/index.ts","../../../libs/ui-components/agorapulse-ui-components.ts"],"sourcesContent":["// Modules\nimport { AddCommentComponent } from '@agorapulse/ui-components/add-comment';\nimport { AvatarComponent } from '@agorapulse/ui-components/avatar';\nimport { ConfirmModalComponent } from '@agorapulse/ui-components/confirm-modal';\nimport { DatepickerComponent } from '@agorapulse/ui-components/datepicker';\nimport {\n AutosizeTextareaDirective,\n DefaultImageDirective,\n EllipsisDirective,\n EqualValidatorDirective,\n FrozenGifDirective,\n MultiStyleTextDirective,\n} from '@agorapulse/ui-components/directives';\nimport { DotStepperComponent } from '@agorapulse/ui-components/dot-stepper';\nimport { InfoboxComponent } from '@agorapulse/ui-components/infobox';\nimport { LabelComponent, LabelListComponent } from '@agorapulse/ui-components/labels';\nimport { LabelsSelectorComponent } from '@agorapulse/ui-components/labels-selector';\nimport { MediaDisplayOverlayDialogComponent } from '@agorapulse/ui-components/media-display-overlay';\nimport { ModalComponent } from '@agorapulse/ui-components/modal';\nimport { DayDisabledPipe, NeoDatepickerComponent } from '@agorapulse/ui-components/neo-datepicker';\nimport { NotificationComponent } from '@agorapulse/ui-components/notification';\nimport { PaginatorButtonComponent, PaginatorComponent } from '@agorapulse/ui-components/paginator';\nimport { PasswordInputComponent } from '@agorapulse/ui-components/password-input';\nimport { PopmenuModule } from '@agorapulse/ui-components/popmenu';\nimport { SlideToggleComponent } from '@agorapulse/ui-components/slide-toggle';\nimport { SnackbarsThreadComponent } from '@agorapulse/ui-components/snackbars-thread';\nimport { StepperComponent } from '@agorapulse/ui-components/stepper';\nimport { TooltipDirective } from '@agorapulse/ui-components/tooltip';\nimport { NgModule } from '@angular/core';\nimport { MAT_TABS_CONFIG } from '@angular/material/tabs';\n\n/**\n * @deprecated for better tree-shaking, use standalone component import instead\n */\n@NgModule({\n declarations: [],\n imports: [\n // Components\n AvatarComponent,\n StepperComponent,\n ConfirmModalComponent,\n DatepickerComponent,\n DotStepperComponent,\n EllipsisDirective,\n InfoboxComponent,\n LabelListComponent,\n LabelsSelectorComponent,\n NeoDatepickerComponent,\n MediaDisplayOverlayDialogComponent,\n ModalComponent,\n PasswordInputComponent,\n LabelComponent,\n NotificationComponent,\n PaginatorComponent,\n PaginatorButtonComponent,\n SlideToggleComponent,\n SnackbarsThreadComponent,\n // Directives\n DefaultImageDirective,\n FrozenGifDirective,\n EqualValidatorDirective,\n MultiStyleTextDirective,\n TooltipDirective,\n AddCommentComponent,\n AutosizeTextareaDirective,\n // Pipes\n DayDisabledPipe,\n ],\n exports: [\n // Components\n AddCommentComponent,\n AvatarComponent,\n StepperComponent,\n ConfirmModalComponent,\n DatepickerComponent,\n NeoDatepickerComponent,\n DotStepperComponent,\n EllipsisDirective,\n InfoboxComponent,\n LabelComponent,\n LabelListComponent,\n MediaDisplayOverlayDialogComponent,\n ModalComponent,\n PasswordInputComponent,\n LabelsSelectorComponent,\n NotificationComponent,\n PaginatorComponent,\n PaginatorButtonComponent,\n SlideToggleComponent,\n SnackbarsThreadComponent,\n // Pipes\n DayDisabledPipe,\n // Directives\n AutosizeTextareaDirective,\n DefaultImageDirective,\n FrozenGifDirective,\n EqualValidatorDirective,\n MultiStyleTextDirective,\n TooltipDirective,\n // Modules\n PopmenuModule,\n ],\n providers: [\n // Disable ripple effect\n // {provide: MAT_RIPPLE_GLOBAL_OPTIONS, useValue: {disabled: true}},\n // Disable tabs animation\n { provide: MAT_TABS_CONFIG, useValue: { animationDuration: '0ms' } },\n ],\n})\nexport class AgorapulseUiComponentsModule {}\n","/*\n * Public API Surface of ui\n */\n\n// Module\nexport { PopmenuModule } from '@agorapulse/ui-components/popmenu';\nexport { AgorapulseUiComponentsModule } from './src/lib/agorapulse-ui-components.module';\n\n// Directive\nexport {\n AutosizeTextareaDirective,\n CheckboxDirective,\n DefaultImageDirective,\n EllipsisDirective,\n EqualValidatorDirective,\n FrozenGifDirective,\n MultiStyleTextDirective,\n} from '@agorapulse/ui-components/directives';\nexport { PopmenuDirective } from '@agorapulse/ui-components/popmenu';\nexport { PopoverDirective } from '@agorapulse/ui-components/popover';\nexport { TooltipDirective, TooltipExternalTriggerDirective } from '@agorapulse/ui-components/tooltip';\n\n// Floating\nexport type { FloatingAnchorMode, FloatingPlacement, FloatingSide } from '@agorapulse/ui-components/floating';\n\n// Dropdown base\nexport { DropdownOverlay, DropdownTriggerDirective, createDropdownOverlay } from '@agorapulse/ui-components/dropdown-base';\n\n// Component\nexport { ActionDropdownComponent, ActionDropdownItem, ActionDropdownTriggerDirective } from '@agorapulse/ui-components/action-dropdown';\nexport { AddCommentComponent } from '@agorapulse/ui-components/add-comment';\nexport { AutocompleteComponent } from '@agorapulse/ui-components/autocomplete';\nexport { AvatarComponent, AvatarItem } from '@agorapulse/ui-components/avatar';\nexport { BadgeComponent } from '@agorapulse/ui-components/badge';\nexport { ButtonComponent } from '@agorapulse/ui-components/button';\nexport { CheckboxComponent } from '@agorapulse/ui-components/checkbox';\nexport { ConfirmModalComponent } from '@agorapulse/ui-components/confirm-modal';\nexport { CounterComponent } from '@agorapulse/ui-components/counter';\nexport {\n DateRangePickerComponent,\n DateRangePickerPreset,\n defaultDateRangePickerPresets,\n} from '@agorapulse/ui-components/date-range-picker';\nexport { DatepickerComponent, DatepickerMode, I18nDatePicker, Period } from '@agorapulse/ui-components/datepicker';\nexport { DotStepperComponent } from '@agorapulse/ui-components/dot-stepper';\nexport { IconButtonComponent } from '@agorapulse/ui-components/icon-button';\nexport { InfoboxComponent } from '@agorapulse/ui-components/infobox';\nexport { LabelComponent, LabelListComponent } from '@agorapulse/ui-components/labels';\nexport { LabelsSelectorComponent } from '@agorapulse/ui-components/labels-selector';\nexport { InputComponent } from '@agorapulse/ui-components/legacy/input';\nexport { SelectComponent } from '@agorapulse/ui-components/legacy/select';\nexport { TextareaComponent } from '@agorapulse/ui-components/legacy/textarea';\nexport { MediaDisplayOverlayDialogComponent } from '@agorapulse/ui-components/media-display-overlay';\nexport { ModalComponent, ModalConfig } from '@agorapulse/ui-components/modal';\nexport { NavSelectorComponent } from '@agorapulse/ui-components/nav-selector';\nexport {\n DayDisabledPipe,\n NeoDatePickerLocale,\n NeoDatePickerMode,\n NeoDatePickerStartsOn,\n NeoDatepickerComponent,\n} from '@agorapulse/ui-components/neo-datepicker';\nexport { NotificationComponent } from '@agorapulse/ui-components/notification';\nexport { PaginatorButtonComponent, PaginatorComponent } from '@agorapulse/ui-components/paginator';\nexport { PasswordInputComponent } from '@agorapulse/ui-components/password-input';\nexport { PopmenuComponent } from '@agorapulse/ui-components/popmenu';\nexport { RadioComponent } from '@agorapulse/ui-components/radio';\nexport { RadioButtonCardComponent } from '@agorapulse/ui-components/radio-button-card';\nexport { SegmentedControlComponent, SegmentedControlOption } from '@agorapulse/ui-components/segmented-control';\nexport {\n SelectionDropdownComponent,\n SelectionDropdownItem,\n SelectionDropdownTriggerDirective,\n} from '@agorapulse/ui-components/selection-dropdown';\nexport { SlideToggleComponent } from '@agorapulse/ui-components/slide-toggle';\nexport { SnackbarsThreadComponent } from '@agorapulse/ui-components/snackbars-thread';\nexport { SocialButtonComponent } from '@agorapulse/ui-components/social-button';\nexport { StatusComponent } from '@agorapulse/ui-components/status';\nexport { StatusCardActor, StatusCardComponent } from '@agorapulse/ui-components/status-card';\nexport { StepperComponent } from '@agorapulse/ui-components/stepper';\nexport { TagComponent } from '@agorapulse/ui-components/tag';\nexport { ToggleComponent } from '@agorapulse/ui-components/toggle';\n\n// Service\nexport { SnackbarsThreadService } from '@agorapulse/ui-components/snackbars-thread';\n\n// Model\nexport { ConfirmModalTexts } from '@agorapulse/ui-components/confirm-modal';\nexport * from '@agorapulse/ui-components/filter-dropdown';\nexport {\n CodeStatus,\n SnackbarTypeValues,\n SnackbarsThreadBase,\n externalSnackbarTypeAllowed,\n generateCodeStatus,\n} from '@agorapulse/ui-components/snackbars-thread';\nexport { Step } from '@agorapulse/ui-components/stepper';\nexport { CustomTooltipAvatarItem, CustomTooltipPresentationItem, CustomTooltipType } from '@agorapulse/ui-components/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\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.
|
|
4
|
+
"version": "22.0.33",
|
|
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"
|
|
@@ -196,6 +201,10 @@
|
|
|
196
201
|
"types": "./types/agorapulse-ui-components-popmenu.d.ts",
|
|
197
202
|
"default": "./fesm2022/agorapulse-ui-components-popmenu.mjs"
|
|
198
203
|
},
|
|
204
|
+
"./popover": {
|
|
205
|
+
"types": "./types/agorapulse-ui-components-popover.d.ts",
|
|
206
|
+
"default": "./fesm2022/agorapulse-ui-components-popover.mjs"
|
|
207
|
+
},
|
|
199
208
|
"./providers": {
|
|
200
209
|
"types": "./types/agorapulse-ui-components-providers.d.ts",
|
|
201
210
|
"default": "./fesm2022/agorapulse-ui-components-providers.mjs"
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Side, Placement, Middleware } from '@floating-ui/dom';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
import { TemplateRef, Type, ComponentRef } from '@angular/core';
|
|
4
|
+
import { OverlayRef } from '@angular/cdk/overlay';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The twelve placements, aliased from Floating UI rather than redeclared. The trade-off: this puts
|
|
8
|
+
* `@floating-ui/dom` in our **public** type surface, so its next major would move our types too.
|
|
9
|
+
*
|
|
10
|
+
* There is no `'auto'`; an unset placement is derived by `defaultPlacementFor`.
|
|
11
|
+
*/
|
|
12
|
+
type FloatingPlacement = Placement;
|
|
13
|
+
/** The four opening sides. Floating UI's `Side`, for the same reason. */
|
|
14
|
+
type FloatingSide = Side;
|
|
15
|
+
declare function sideOf(placement: FloatingPlacement): FloatingSide;
|
|
16
|
+
declare function isVertical(placement: FloatingPlacement): boolean;
|
|
17
|
+
|
|
18
|
+
/** A minimal rect — neither `DOMRect` nor any DOM dependency, so the pure units stay pure. */
|
|
19
|
+
interface FloatingRect {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** What the panel connects to. */
|
|
27
|
+
type FloatingAnchorMode = 'trigger' | 'pointer' | 'pointer-free';
|
|
28
|
+
/**
|
|
29
|
+
* The placement derived when `placement` is unset. Reads the **configured** anchor mode, not the
|
|
30
|
+
* resolved one: a keyboard opening falls back to the trigger, and if the alignment followed, the
|
|
31
|
+
* component would change shape between mouse and keyboard.
|
|
32
|
+
*/
|
|
33
|
+
declare function defaultPlacementFor(anchor: FloatingAnchorMode): FloatingPlacement;
|
|
34
|
+
/**
|
|
35
|
+
* `'pointer'` is a hybrid whose zero dimension is the **cross-axis** one; a lateral panel built
|
|
36
|
+
* from a fully point-like anchor would sit inside its own trigger. `'pointer-free'` is the point
|
|
37
|
+
* itself. Both fall back to the trigger when there is no click.
|
|
38
|
+
*
|
|
39
|
+
* @param vertical The opening axis. Invariant under the flip, which only swaps the main axis.
|
|
40
|
+
*/
|
|
41
|
+
declare function resolveAnchorRect(anchor: FloatingAnchorMode, triggerRect: FloatingRect, vertical: boolean, clickPoint?: {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
}): FloatingRect;
|
|
45
|
+
/** A point expressed as a proportion of the trigger, on each axis. */
|
|
46
|
+
interface ClickRatio {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface ApArrowOptions {
|
|
52
|
+
/** What the tip aims at — see {@link resolveArrowOffset}. */
|
|
53
|
+
targetMode: 'anchor' | 'pointer';
|
|
54
|
+
/** The configured anchor mode. Decides how the click is recovered from the reference rect. */
|
|
55
|
+
anchorMode: FloatingAnchorMode;
|
|
56
|
+
/** The clicked point as a proportion of the trigger. Absent on a keyboard opening. */
|
|
57
|
+
clickRatio?: ClickRatio;
|
|
58
|
+
}
|
|
59
|
+
/** What the middleware leaves in `middlewareData.apArrow`. */
|
|
60
|
+
interface ApArrowData {
|
|
61
|
+
/** The arrow's offset from the panel's start edge, along the cross axis. */
|
|
62
|
+
offset: number;
|
|
63
|
+
/** The side of the panel the arrow sits on — read from the **resolved** placement. */
|
|
64
|
+
side: FloatingSide;
|
|
65
|
+
/** The panel covers its **anchor** — in the POI mode the trigger may be covered on purpose. */
|
|
66
|
+
hidden: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Replaces Floating UI's `arrow`, which aims at the centre of the *reference*: on a 280px trigger
|
|
70
|
+
* with a 100px panel that centre is out of reach and the tip clamps to a corner at 80, where the
|
|
71
|
+
* intersection's centre is 42 (plate 22). {@link resolveArrowOffset} holds the rule.
|
|
72
|
+
*
|
|
73
|
+
* Must run last, after `shift`, since it reads the panel's final position.
|
|
74
|
+
*/
|
|
75
|
+
declare function apArrow(options: ApArrowOptions): Middleware;
|
|
76
|
+
|
|
77
|
+
interface ArrowOffsetInput {
|
|
78
|
+
/** The side of the panel the arrow sits on — the **resolved** side, not the wanted one. */
|
|
79
|
+
side: FloatingSide;
|
|
80
|
+
anchorRect: FloatingRect;
|
|
81
|
+
floatingRect: FloatingRect;
|
|
82
|
+
/** `'anchor'` aims at the anchor ∩ panel intersection's centre, `'pointer'` at the click. */
|
|
83
|
+
targetMode: 'anchor' | 'pointer';
|
|
84
|
+
clickPoint?: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
interface ArrowOffsetResult {
|
|
90
|
+
/** The arrow's offset from the panel's start edge, along the cross axis. */
|
|
91
|
+
offset: number;
|
|
92
|
+
clamped: boolean;
|
|
93
|
+
/** The click fell outside the panel, so the intersection centre was used instead. */
|
|
94
|
+
fellBack: boolean;
|
|
95
|
+
/** The panel is too narrow: the clamp range inverts and the arrow is centred outright. */
|
|
96
|
+
centered: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Three rules, in order:
|
|
100
|
+
*
|
|
101
|
+
* 1. Aim at the centre of the **anchor ∩ panel intersection**, never the anchor's own centre —
|
|
102
|
+
* `apArrow` documents why this diverges from Floating UI.
|
|
103
|
+
* 2. In `'pointer'` mode, aim at the click, falling back to rule 1 — discontinuously, as the
|
|
104
|
+
* plates specify — when the click lands outside the panel.
|
|
105
|
+
* 3. Clamp to leave the corner radius clear. Below `arrow + 2 × radius` = 24px the range inverts,
|
|
106
|
+
* and the arrow is centred outright.
|
|
107
|
+
*
|
|
108
|
+
* The flags say which rule applied, so the generated plate cases can assert the path taken.
|
|
109
|
+
*/
|
|
110
|
+
declare function resolveArrowOffset(input: ArrowOffsetInput): ArrowOffsetResult;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The panel edge an arrow sits on: a panel placed `bottom` hangs below its anchor, so its tip is on
|
|
114
|
+
* its top edge. Give it the **resolved** placement, or a flipped panel grows its arrow away.
|
|
115
|
+
*/
|
|
116
|
+
declare function arrowSideFor(placement: FloatingPlacement): FloatingSide;
|
|
117
|
+
/** Ready-to-use CSS values, `'auto'` for the sides that do not apply. */
|
|
118
|
+
interface ArrowPlacement {
|
|
119
|
+
top: string;
|
|
120
|
+
right: string;
|
|
121
|
+
bottom: string;
|
|
122
|
+
left: string;
|
|
123
|
+
rotate: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The insets and rotation `_floating-arrow.scss` reads off the pane. The rotation-centre
|
|
127
|
+
* compensation lives here rather than in the stylesheet, where it could not be tested.
|
|
128
|
+
*
|
|
129
|
+
* @param side The panel edge the arrow sits on — the **resolved** side, not the wanted one.
|
|
130
|
+
* @param offset The offset from the panel's start edge, along the cross axis.
|
|
131
|
+
*/
|
|
132
|
+
declare function resolveArrowPlacement(side: FloatingSide, offset: number): ArrowPlacement;
|
|
133
|
+
|
|
134
|
+
interface FloatingOverlayConfig {
|
|
135
|
+
/** Unset means derived from `anchor`. There is no `'auto'` value. */
|
|
136
|
+
placement?: FloatingPlacement;
|
|
137
|
+
anchor?: FloatingAnchorMode;
|
|
138
|
+
arrow?: boolean;
|
|
139
|
+
arrowTarget?: 'anchor' | 'pointer';
|
|
140
|
+
showBackdrop?: boolean;
|
|
141
|
+
panelClass?: string | string[];
|
|
142
|
+
/** Fallback for the two handlers below. */
|
|
143
|
+
onClose?: () => void;
|
|
144
|
+
/** Escape, which always closes. Unset means `onClose`. */
|
|
145
|
+
onEscape?: () => void;
|
|
146
|
+
/** Outside click. Unset means `onClose`. */
|
|
147
|
+
onOutsideClick?: () => void;
|
|
148
|
+
/**
|
|
149
|
+
* Elements that carry their own toggle, so a click on them is not "the outside". Read on every
|
|
150
|
+
* event, since the list may change while the floating is open.
|
|
151
|
+
*
|
|
152
|
+
* Without this, the CDK's capture-phase dispatcher closes before a secondary trigger sees the
|
|
153
|
+
* click, that trigger reopens, and the toggle never closes again.
|
|
154
|
+
*/
|
|
155
|
+
additionalTriggers?: () => readonly HTMLElement[];
|
|
156
|
+
}
|
|
157
|
+
declare function createFloatingOverlay(): {
|
|
158
|
+
readonly overlayRef: OverlayRef | null;
|
|
159
|
+
isOpen: _angular_core.Signal<boolean>;
|
|
160
|
+
open: <T = unknown>(content: TemplateRef<unknown> | Type<T>, triggerElement?: HTMLElement, config?: FloatingOverlayConfig, event?: MouseEvent) => ComponentRef<T> | null;
|
|
161
|
+
close: () => void;
|
|
162
|
+
updatePosition: () => void;
|
|
163
|
+
};
|
|
164
|
+
type FloatingOverlayInstance = ReturnType<typeof createFloatingOverlay>;
|
|
165
|
+
|
|
166
|
+
export { apArrow, arrowSideFor, createFloatingOverlay, defaultPlacementFor, isVertical, resolveAnchorRect, resolveArrowOffset, resolveArrowPlacement, sideOf };
|
|
167
|
+
export type { ApArrowData, ApArrowOptions, ArrowOffsetInput, ArrowOffsetResult, ArrowPlacement, FloatingAnchorMode, FloatingOverlayConfig, FloatingOverlayInstance, FloatingPlacement, FloatingRect, FloatingSide };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { TemplateRef } from '@angular/core';
|
|
3
|
+
import * as _floating_ui_utils from '@floating-ui/utils';
|
|
4
|
+
import { FloatingAnchorMode } from '@agorapulse/ui-components/floating';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The `role="dialog"` surface, its optional header and its focus trap. Instantiated by the popover
|
|
8
|
+
* directive, never by a consumer.
|
|
9
|
+
*
|
|
10
|
+
* Focus is the CDK's: `cdkTrapFocus` confines Tab, `autoCapture` focuses on open and restores the
|
|
11
|
+
* trigger on destruction. The cost is that Tab cannot leave the panel — Escape or the button do.
|
|
12
|
+
*/
|
|
13
|
+
declare class PopoverPanelComponent {
|
|
14
|
+
private static nextId;
|
|
15
|
+
/** The consumer's content. Always a template: the directive sits on the trigger, not here. */
|
|
16
|
+
readonly content: _angular_core.InputSignal<TemplateRef<unknown>>;
|
|
17
|
+
/** Mirrors the popover's heading, and gives the dialog its accessible name. */
|
|
18
|
+
readonly heading: _angular_core.InputSignal<string | undefined>;
|
|
19
|
+
/** Mirrors the popover's input of the same name. */
|
|
20
|
+
readonly closable: _angular_core.InputSignal<boolean>;
|
|
21
|
+
/** Mirrors the popover's backdrop, which is what makes the page genuinely inert. */
|
|
22
|
+
readonly backdrop: _angular_core.InputSignal<boolean>;
|
|
23
|
+
/** Mirrors the popover's, and names the dialog when there is no heading. */
|
|
24
|
+
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
25
|
+
readonly closeAriaLabel: _angular_core.InputSignal<string>;
|
|
26
|
+
/** Set by the directive, which needs it for the trigger's `aria-controls`. */
|
|
27
|
+
readonly panelId: _angular_core.InputSignal<string>;
|
|
28
|
+
/**
|
|
29
|
+
* The id of the element that names the dialog when nothing else does — the trigger, set by the
|
|
30
|
+
* directive. An id rather than its text, so the name is computed on the live DOM: that follows a
|
|
31
|
+
* label that changes, and reads a trigger whose own name is an `aria-label`.
|
|
32
|
+
*/
|
|
33
|
+
readonly fallbackLabelId: _angular_core.InputSignal<string | undefined>;
|
|
34
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
35
|
+
protected readonly headingId: string;
|
|
36
|
+
/** A dialog must be named. The heading does it, failing that the trigger. */
|
|
37
|
+
protected readonly labelledBy: _angular_core.Signal<string | null>;
|
|
38
|
+
protected readonly label: _angular_core.Signal<string | null>;
|
|
39
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PopoverPanelComponent, never>;
|
|
40
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PopoverPanelComponent, "ap-popover-panel", never, { "content": { "alias": "content"; "required": true; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "backdrop": { "alias": "backdrop"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "closeAriaLabel": { "alias": "closeAriaLabel"; "required": false; "isSignal": true; }; "panelId": { "alias": "panelId"; "required": false; "isSignal": true; }; "fallbackLabelId": { "alias": "fallbackLabelId"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, never, true, never>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A click-triggered interactive panel: `role="dialog"`, managed focus, Escape, optional backdrop.
|
|
45
|
+
* A tooltip is the opposite — descriptive, hover-triggered, and never focusable.
|
|
46
|
+
*
|
|
47
|
+
* Sits on the **trigger**, so it owns the trigger's ARIA and the content is always a `TemplateRef`.
|
|
48
|
+
* Inputs are prefixed one by one rather than bundled: an inline config object would be recreated on
|
|
49
|
+
* every change-detection cycle and thrash the overlay.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* <button [apPopover]="shareTpl" apPopoverHeading="Share">Share</button>
|
|
53
|
+
* <ng-template #shareTpl>…</ng-template>
|
|
54
|
+
*/
|
|
55
|
+
declare class PopoverDirective {
|
|
56
|
+
private static nextId;
|
|
57
|
+
private readonly instanceId;
|
|
58
|
+
private readonly floating;
|
|
59
|
+
private readonly triggerElement;
|
|
60
|
+
private panelRef;
|
|
61
|
+
/** The panel's content. */
|
|
62
|
+
readonly apPopover: _angular_core.InputSignal<TemplateRef<unknown>>;
|
|
63
|
+
/** Unset means derived from the anchor mode. There is no `'auto'` value. */
|
|
64
|
+
readonly apPopoverPlacement: _angular_core.InputSignal<_floating_ui_utils.Placement | undefined>;
|
|
65
|
+
readonly apPopoverAnchor: _angular_core.InputSignal<FloatingAnchorMode>;
|
|
66
|
+
readonly apPopoverArrow: _angular_core.InputSignal<boolean>;
|
|
67
|
+
readonly apPopoverArrowTarget: _angular_core.InputSignal<"anchor" | "pointer">;
|
|
68
|
+
/** Shows a close button — and, by doing so, makes it *the* way to close: no more outside click. */
|
|
69
|
+
readonly apPopoverClosable: _angular_core.InputSignal<boolean>;
|
|
70
|
+
/** Blocks the page behind. Non-modal by default — that is the point of a popover. */
|
|
71
|
+
readonly apPopoverBackdrop: _angular_core.InputSignal<boolean>;
|
|
72
|
+
/** Optional heading. When set, it becomes the dialog's accessible name. */
|
|
73
|
+
readonly apPopoverHeading: _angular_core.InputSignal<string | undefined>;
|
|
74
|
+
/** Accessible name used when there is no heading. */
|
|
75
|
+
readonly apPopoverAriaLabel: _angular_core.InputSignal<string | undefined>;
|
|
76
|
+
/** An input rather than a hard-coded string: several of the DS's own labels read badly. */
|
|
77
|
+
readonly apPopoverCloseAriaLabel: _angular_core.InputSignal<string>;
|
|
78
|
+
readonly apPopoverPanelClass: _angular_core.InputSignal<string | string[] | undefined>;
|
|
79
|
+
readonly isOpen: _angular_core.Signal<boolean>;
|
|
80
|
+
protected readonly panelId: string;
|
|
81
|
+
open(event?: MouseEvent): void;
|
|
82
|
+
/** The dialog falls back to being named by its trigger, and `aria-labelledby` needs an id to point at. */
|
|
83
|
+
private ensureTriggerId;
|
|
84
|
+
/** The residual case the fallback cannot cover: a trigger that names nothing either. */
|
|
85
|
+
private warnWhenNameless;
|
|
86
|
+
close(): void;
|
|
87
|
+
toggle(event?: MouseEvent): void;
|
|
88
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PopoverDirective, never>;
|
|
89
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<PopoverDirective, "[apPopover]", ["apPopover"], { "apPopover": { "alias": "apPopover"; "required": true; "isSignal": true; }; "apPopoverPlacement": { "alias": "apPopoverPlacement"; "required": false; "isSignal": true; }; "apPopoverAnchor": { "alias": "apPopoverAnchor"; "required": false; "isSignal": true; }; "apPopoverArrow": { "alias": "apPopoverArrow"; "required": false; "isSignal": true; }; "apPopoverArrowTarget": { "alias": "apPopoverArrowTarget"; "required": false; "isSignal": true; }; "apPopoverClosable": { "alias": "apPopoverClosable"; "required": false; "isSignal": true; }; "apPopoverBackdrop": { "alias": "apPopoverBackdrop"; "required": false; "isSignal": true; }; "apPopoverHeading": { "alias": "apPopoverHeading"; "required": false; "isSignal": true; }; "apPopoverAriaLabel": { "alias": "apPopoverAriaLabel"; "required": false; "isSignal": true; }; "apPopoverCloseAriaLabel": { "alias": "apPopoverCloseAriaLabel"; "required": false; "isSignal": true; }; "apPopoverPanelClass": { "alias": "apPopoverPanelClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { PopoverDirective, PopoverPanelComponent };
|
|
@@ -39,6 +39,8 @@ import * as i18 from '@agorapulse/ui-components/tooltip';
|
|
|
39
39
|
export { CustomTooltipAvatarItem, CustomTooltipPresentationItem, CustomTooltipType, TooltipDirective, TooltipExternalTriggerDirective } from '@agorapulse/ui-components/tooltip';
|
|
40
40
|
import * as i19 from '@agorapulse/ui-components/add-comment';
|
|
41
41
|
export { AddCommentComponent } from '@agorapulse/ui-components/add-comment';
|
|
42
|
+
export { PopoverDirective } from '@agorapulse/ui-components/popover';
|
|
43
|
+
export { FloatingAnchorMode, FloatingPlacement, FloatingSide } from '@agorapulse/ui-components/floating';
|
|
42
44
|
export { DropdownOverlay, DropdownTriggerDirective, createDropdownOverlay } from '@agorapulse/ui-components/dropdown-base';
|
|
43
45
|
export { ActionDropdownComponent, ActionDropdownItem, ActionDropdownTriggerDirective } from '@agorapulse/ui-components/action-dropdown';
|
|
44
46
|
export { AutocompleteComponent } from '@agorapulse/ui-components/autocomplete';
|
|
Binary file
|