@aurodesignsystem/auro-library 5.7.0 → 5.9.0
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Semantic Release Automated Changelog
|
|
2
2
|
|
|
3
|
+
# [5.9.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.8.0...v5.9.0) (2026-01-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* move popover positioner to library ([6d69131](https://github.com/AlaskaAirlines/auro-library/commit/6d69131a3ade2922cde25169d2dec6543264d11b))
|
|
9
|
+
|
|
10
|
+
# [5.8.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.7.0...v5.8.0) (2026-01-22)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* add StringBoolean lit converter for supporting string boolean attributes ([025cde2](https://github.com/AlaskaAirlines/auro-library/commit/025cde2fad3b12fa113c11a123268a816de4c009))
|
|
16
|
+
|
|
3
17
|
# [5.7.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.6.0...v5.7.0) (2026-01-22)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurodesignsystem/auro-library",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "This repository holds shared scripts, utilities, and workflows utilized across repositories along the Auro Design System.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"generateDocs": "./bin/generateDocs.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@floating-ui/dom": "^1.6.11",
|
|
19
18
|
"handlebars": "^4.7.8",
|
|
20
|
-
"markdown-magic": "^2.6.1"
|
|
19
|
+
"markdown-magic": "^2.6.1",
|
|
20
|
+
"@floating-ui/dom": "^1.7.4"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@aurodesignsystem/auro-cli": "^3.5.1",
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {
|
|
2
|
+
arrow,
|
|
3
|
+
autoPlacement,
|
|
4
|
+
autoUpdate,
|
|
5
|
+
computePosition,
|
|
6
|
+
flip,
|
|
7
|
+
hide,
|
|
8
|
+
inline,
|
|
9
|
+
offset,
|
|
10
|
+
} from "@floating-ui/dom";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Positions a popover element relative to a target element using Floating UI.
|
|
14
|
+
* @param {Object} config
|
|
15
|
+
* @param {HTMLElement} config.target - The reference element (trigger)
|
|
16
|
+
* @param {HTMLElement} config.popover - The floating element (dropdown)
|
|
17
|
+
* @param {Object} config.options - Configuration options
|
|
18
|
+
* @param {string} [config.options.placement='bottom-start'] - Positioning placement of the floating element
|
|
19
|
+
* @param {number} [config.options.offset=0] - Distance in pixels from the reference element
|
|
20
|
+
* @param {boolean} [config.options.autoStart=true] - Whether to start auto-updating the position immediately
|
|
21
|
+
* @param {HTMLElement} [config.options.arrowEl=null] - Optional arrow element to position (e.g., <div class="arrow"></div>)
|
|
22
|
+
* @param {boolean} [config.options.useAutoPlacement=true] - Whether to use auto placement to find optimal position
|
|
23
|
+
* @param {boolean} [config.options.useFlip=true] - Whether to flip the floating element if it doesn't fit
|
|
24
|
+
* @param {boolean} [config.options.useHide=true] - Whether to hide the floating element if it doesn't fit
|
|
25
|
+
* @param {string} [config.options.strategy='absolute'] - Positioning strategy ('absolute' or 'fixed')
|
|
26
|
+
* @param {boolean} [config.options.inline=false] - Whether to position inline (needed for hyperlinks and inline elements)
|
|
27
|
+
*/
|
|
28
|
+
export class PopoverPositioner {
|
|
29
|
+
#currentPlacement;
|
|
30
|
+
#currentSide;
|
|
31
|
+
#currentArrowSide;
|
|
32
|
+
#currentArrowDirection;
|
|
33
|
+
|
|
34
|
+
#referenceEl;
|
|
35
|
+
#floatingEl;
|
|
36
|
+
#options;
|
|
37
|
+
#onPlacementChange;
|
|
38
|
+
#cleanup;
|
|
39
|
+
|
|
40
|
+
constructor({
|
|
41
|
+
target,
|
|
42
|
+
popover,
|
|
43
|
+
options = {},
|
|
44
|
+
onPlacementChange = () => {},
|
|
45
|
+
} = {}) {
|
|
46
|
+
this.#referenceEl = target;
|
|
47
|
+
this.#floatingEl = popover;
|
|
48
|
+
this.#options = options;
|
|
49
|
+
this.#onPlacementChange = onPlacementChange;
|
|
50
|
+
this.#setInitialFloatingElementStyles();
|
|
51
|
+
this.#cleanup = this.#options.autoStart !== false ? this.start() : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Start auto-updating the position
|
|
56
|
+
* @returns {Function} Cleanup function
|
|
57
|
+
*/
|
|
58
|
+
start() {
|
|
59
|
+
if (this.cleanup) {
|
|
60
|
+
this.#cleanup();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const cleanup = autoUpdate(
|
|
64
|
+
this.#referenceEl,
|
|
65
|
+
this.#floatingEl,
|
|
66
|
+
this.#updatePosition.bind(this),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return cleanup;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Stop auto-updating the position
|
|
74
|
+
*/
|
|
75
|
+
stop() {
|
|
76
|
+
if (this.#cleanup) {
|
|
77
|
+
this.#cleanup();
|
|
78
|
+
this.#cleanup = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Destroy the instance and clean up
|
|
84
|
+
*/
|
|
85
|
+
disconnect() {
|
|
86
|
+
this.stop();
|
|
87
|
+
this.referenceEl = null;
|
|
88
|
+
this.floatingEl = null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Builds the list of Floating UI middleware used to position the popover. This configures how the popover behaves in response to space, visibility, and arrow requirements.
|
|
93
|
+
* @returns {Array} An array of middleware instances that control offset, flipping, auto placement, hiding, inline behavior, and arrow positioning.
|
|
94
|
+
*/
|
|
95
|
+
get #middleware() {
|
|
96
|
+
return [].concat(
|
|
97
|
+
this.#options.offset && this.#options.offset !== 0
|
|
98
|
+
? offset(this.#options.offset)
|
|
99
|
+
: [],
|
|
100
|
+
this.#options.useFlip ? flip() : [],
|
|
101
|
+
this.#options.useAutoPlacement ? autoPlacement() : [],
|
|
102
|
+
this.#options.useHide ? hide() : [],
|
|
103
|
+
this.#options.inline ? inline() : [],
|
|
104
|
+
this.#options.arrowEl ? arrow({ element: this.#options.arrowEl }) : [],
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Prepares the arguments used when calling Floating UI to compute the popover position. This encapsulates the reference, floating element, and core configuration in a single structure.
|
|
110
|
+
* @returns {Array} An ordered array containing the reference element, floating element, and configuration object for Floating UI.
|
|
111
|
+
*/
|
|
112
|
+
get #floatingUiArgs() {
|
|
113
|
+
return [
|
|
114
|
+
this.#referenceEl,
|
|
115
|
+
this.#floatingEl,
|
|
116
|
+
{
|
|
117
|
+
strategy: this.#options.strategy || "absolute",
|
|
118
|
+
placement: this.#options.placement || "bottom-start",
|
|
119
|
+
middleware: this.#middleware,
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Primary callback for FloatingUI updates
|
|
126
|
+
* Recomputes and applies the current popover and arrow position. This keeps the popover layout in sync with its reference element as the page or viewport changes.
|
|
127
|
+
*/
|
|
128
|
+
#updatePosition() {
|
|
129
|
+
if (!this.#referenceEl || !this.#floatingEl) return;
|
|
130
|
+
|
|
131
|
+
computePosition(...this.#floatingUiArgs).then(
|
|
132
|
+
({ x, y, middlewareData, placement }) => {
|
|
133
|
+
// Handle the new placement and get the direction the arrow should point
|
|
134
|
+
const { arrowSide } = this.#handlePlacementChange({ placement });
|
|
135
|
+
|
|
136
|
+
// Upload the position of the floating element
|
|
137
|
+
this.#updateFloatingElPosition({ x, y, middlewareData });
|
|
138
|
+
|
|
139
|
+
// Update the position of the arrow element
|
|
140
|
+
this.#updateArrowPosition({
|
|
141
|
+
arrowData: middlewareData.arrow,
|
|
142
|
+
arrowSide,
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Applies the base positioning styles to the floating element before any calculations run. This ensures the popover is ready to be positioned consistently by Floating UI.
|
|
150
|
+
*/
|
|
151
|
+
#setInitialFloatingElementStyles() {
|
|
152
|
+
if (!this.#floatingEl) return;
|
|
153
|
+
const strategy = this.#options.strategy || "absolute";
|
|
154
|
+
const defaultStyles = {
|
|
155
|
+
position: strategy,
|
|
156
|
+
margin: "0",
|
|
157
|
+
};
|
|
158
|
+
Object.assign(this.#floatingEl.style, defaultStyles);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Derives normalized placement information from the raw Floating UI placement value. This determines how the popover and its arrow should be oriented relative to the reference element.
|
|
163
|
+
* @param {Object} params
|
|
164
|
+
* @param {string} params.placement - The full placement value reported by Floating UI (e.g., "bottom-start").
|
|
165
|
+
* @returns {{placement: string, side: string, arrowDirection: string, arrowSide: string}} Normalized placement data including side and arrow orientation.
|
|
166
|
+
*/
|
|
167
|
+
#handlePlacementChange({ placement }) {
|
|
168
|
+
// Get the side of the placement (top, right, bottom, left)
|
|
169
|
+
const placementSide = placement.split("-")[0];
|
|
170
|
+
const arrowSide = {
|
|
171
|
+
top: "bottom",
|
|
172
|
+
right: "left",
|
|
173
|
+
bottom: "top",
|
|
174
|
+
left: "right",
|
|
175
|
+
}[placementSide];
|
|
176
|
+
|
|
177
|
+
// Get the direction the arrow is pointing
|
|
178
|
+
const arrowDirection = {
|
|
179
|
+
top: "down",
|
|
180
|
+
right: "left",
|
|
181
|
+
bottom: "up",
|
|
182
|
+
left: "right",
|
|
183
|
+
}[placementSide];
|
|
184
|
+
|
|
185
|
+
this.#updateInternalState({
|
|
186
|
+
placement,
|
|
187
|
+
arrowDirection,
|
|
188
|
+
arrowSide: arrowSide,
|
|
189
|
+
side: placementSide,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return { placement, side: placementSide, arrowDirection, arrowSide };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Caches the latest placement state and triggers any placement change callback. This keeps consumers informed when the popover or its arrow orientation changes.
|
|
197
|
+
* @param {Object} params
|
|
198
|
+
* @param {string} params.placement - The current full placement string (e.g., "bottom-start").
|
|
199
|
+
* @param {string} params.side - The side of the reference element where the popover is placed.
|
|
200
|
+
* @param {string} params.arrowDirection - The direction the arrow visually points.
|
|
201
|
+
* @param {string} params.arrowSide - The side of the popover where the arrow is anchored.
|
|
202
|
+
*/
|
|
203
|
+
#updateInternalState({ placement, side, arrowDirection, arrowSide }) {
|
|
204
|
+
if (
|
|
205
|
+
this.#currentPlacement !== placement ||
|
|
206
|
+
this.#currentArrowDirection !== arrowDirection ||
|
|
207
|
+
this.#currentArrowSide !== arrowSide ||
|
|
208
|
+
this.#currentSide !== side
|
|
209
|
+
) {
|
|
210
|
+
this.#currentPlacement = placement;
|
|
211
|
+
this.#currentArrowDirection = arrowDirection;
|
|
212
|
+
this.#currentArrowSide = arrowSide;
|
|
213
|
+
this.#currentSide = side;
|
|
214
|
+
this.#onPlacementChange?.({ placement, arrowDirection, arrowSide, side });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Applies the latest computed position to the floating element. This keeps the popover visually aligned with the reference element and updates its visibility state.
|
|
220
|
+
* @param {Object} params
|
|
221
|
+
* @param {number} params.x - The horizontal position in pixels for the floating element.
|
|
222
|
+
* @param {number} params.y - The vertical position in pixels for the floating element.
|
|
223
|
+
* @param {Object} params.middlewareData - Data returned from Floating UI middleware, including visibility information.
|
|
224
|
+
*/
|
|
225
|
+
#updateFloatingElPosition({ x, y, middlewareData }) {
|
|
226
|
+
if (!this.#floatingEl) return;
|
|
227
|
+
Object.assign(this.#floatingEl.style, {
|
|
228
|
+
visibility: middlewareData.hide?.referenceHidden ? "hidden" : "visible",
|
|
229
|
+
left: `${x}px`,
|
|
230
|
+
top: `${y}px`,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Updates the visual position of the arrow element relative to the popover. This keeps the arrow aligned with the reference element and clears any stale positioning styles.
|
|
236
|
+
* @param {Object} params
|
|
237
|
+
* @param {{x: number|null, y: number|null}|null} params.arrowData - The computed arrow coordinates from Floating UI, or null if no arrow data is available.
|
|
238
|
+
* @param {string} params.arrowSide - The side of the popover where the arrow should be anchored (top, right, bottom, or left).
|
|
239
|
+
*/
|
|
240
|
+
#updateArrowPosition({ arrowData, arrowSide }) {
|
|
241
|
+
// Update the styles for the arrow element
|
|
242
|
+
if (arrowData && this.#options.arrowEl) {
|
|
243
|
+
// Get current arrow styles
|
|
244
|
+
const arrowStyle = this.#options.arrowEl?.style;
|
|
245
|
+
|
|
246
|
+
// Reset arrow style properties modified by this middleware below to clean up old styles before applying new ones
|
|
247
|
+
const propsToReset = [
|
|
248
|
+
"top",
|
|
249
|
+
"bottom",
|
|
250
|
+
"left",
|
|
251
|
+
"right",
|
|
252
|
+
...(arrowData ? [] : ["position"]),
|
|
253
|
+
];
|
|
254
|
+
propsToReset.forEach((prop) => {
|
|
255
|
+
arrowStyle[prop] = "";
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Update the arrow position
|
|
259
|
+
const { x, y } = arrowData;
|
|
260
|
+
Object.assign(arrowStyle ?? {}, {
|
|
261
|
+
left: x != null ? `${x}px` : "",
|
|
262
|
+
top: y != null ? `${y}px` : "",
|
|
263
|
+
[arrowSide]: `${-this.#options.arrowEl.offsetWidth}px`,
|
|
264
|
+
position: "absolute",
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|