@aurodesignsystem/auro-formkit 6.2.1 → 6.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/components/bibtemplate/dist/index.js +9 -7
  3. package/components/bibtemplate/dist/registered.js +9 -7
  4. package/components/checkbox/demo/customize.min.js +8 -4
  5. package/components/checkbox/demo/demo-support.min.js +1303 -643
  6. package/components/checkbox/demo/getting-started.min.js +8 -4
  7. package/components/checkbox/demo/index.min.js +8 -4
  8. package/components/checkbox/dist/index.js +7 -3
  9. package/components/checkbox/dist/registered.js +7 -3
  10. package/components/combobox/demo/customize.min.js +516 -193
  11. package/components/combobox/demo/demo-support.min.js +1303 -643
  12. package/components/combobox/demo/getting-started.min.js +516 -193
  13. package/components/combobox/demo/index.min.js +516 -193
  14. package/components/combobox/dist/auro-combobox.d.ts +14 -0
  15. package/components/combobox/dist/index.js +421 -178
  16. package/components/combobox/dist/registered.js +421 -178
  17. package/components/counter/demo/api.md +0 -1
  18. package/components/counter/demo/customize.md +4 -4
  19. package/components/counter/demo/customize.min.js +341 -182
  20. package/components/counter/demo/demo-support.min.js +1303 -643
  21. package/components/counter/demo/getting-started.min.js +341 -182
  22. package/components/counter/demo/index.min.js +341 -182
  23. package/components/counter/dist/auro-counter-group.d.ts +0 -7
  24. package/components/counter/dist/index.js +339 -180
  25. package/components/counter/dist/registered.js +339 -180
  26. package/components/datepicker/demo/customize.min.js +425 -192
  27. package/components/datepicker/demo/demo-support.min.js +1303 -643
  28. package/components/datepicker/demo/getting-started.min.js +425 -192
  29. package/components/datepicker/demo/index.min.js +425 -192
  30. package/components/datepicker/dist/index.js +423 -190
  31. package/components/datepicker/dist/registered.js +423 -190
  32. package/components/dropdown/demo/customize.min.js +313 -154
  33. package/components/dropdown/demo/demo-support.min.js +1303 -643
  34. package/components/dropdown/demo/getting-started.min.js +375 -168
  35. package/components/dropdown/demo/index.min.js +313 -154
  36. package/components/dropdown/dist/index.js +311 -152
  37. package/components/dropdown/dist/registered.js +311 -152
  38. package/components/form/demo/customize.min.js +1702 -763
  39. package/components/form/demo/demo-support.min.js +1303 -643
  40. package/components/form/demo/getting-started.min.js +1702 -763
  41. package/components/form/demo/index.min.js +1702 -763
  42. package/components/form/demo/registerDemoDeps.min.js +1702 -763
  43. package/components/input/demo/customize.min.js +64 -16
  44. package/components/input/demo/demo-support.min.js +1303 -643
  45. package/components/input/demo/getting-started.min.js +64 -16
  46. package/components/input/demo/index.min.js +64 -16
  47. package/components/input/dist/auro-input.d.ts +14 -0
  48. package/components/input/dist/index.js +62 -14
  49. package/components/input/dist/registered.js +62 -14
  50. package/components/menu/demo/api.md +1 -1
  51. package/components/menu/demo/demo-support.min.js +1303 -643
  52. package/components/menu/demo/index.min.js +93 -13
  53. package/components/menu/dist/auro-menu-utils.d.ts +15 -2
  54. package/components/menu/dist/auro-menu.d.ts +1 -1
  55. package/components/menu/dist/index.js +92 -12
  56. package/components/menu/dist/registered.js +92 -12
  57. package/components/radio/demo/customize.min.js +8 -4
  58. package/components/radio/demo/demo-support.min.js +1303 -643
  59. package/components/radio/demo/getting-started.min.js +8 -4
  60. package/components/radio/demo/index.min.js +8 -4
  61. package/components/radio/dist/index.js +7 -3
  62. package/components/radio/dist/registered.js +7 -3
  63. package/components/select/demo/customize.min.js +433 -187
  64. package/components/select/demo/demo-support.min.js +1303 -643
  65. package/components/select/demo/getting-started.min.js +433 -187
  66. package/components/select/demo/index.min.js +433 -187
  67. package/components/select/dist/index.js +339 -173
  68. package/components/select/dist/registered.js +339 -173
  69. package/custom-elements.json +7551 -7498
  70. package/package.json +56 -56
@@ -189,12 +189,12 @@ function getOppositePlacement(placement) {
189
189
  return oppositeSideMap[side] + placement.slice(side.length);
190
190
  }
191
191
  function expandPaddingObject(padding) {
192
+ var _padding$top, _padding$right, _padding$bottom, _padding$left;
192
193
  return {
193
- top: 0,
194
- right: 0,
195
- bottom: 0,
196
- left: 0,
197
- ...padding
194
+ top: (_padding$top = padding.top) != null ? _padding$top : 0,
195
+ right: (_padding$right = padding.right) != null ? _padding$right : 0,
196
+ bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0,
197
+ left: (_padding$left = padding.left) != null ? _padding$left : 0
198
198
  };
199
199
  }
200
200
  function getPaddingObject(padding) {
@@ -269,13 +269,9 @@ function computeCoordsFromPlacement(_ref, placement, rtl) {
269
269
  y: reference.y
270
270
  };
271
271
  }
272
- switch (getAlignment(placement)) {
273
- case 'start':
274
- coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
275
- break;
276
- case 'end':
277
- coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
278
- break;
272
+ const alignment = getAlignment(placement);
273
+ if (alignment) {
274
+ coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);
279
275
  }
280
276
  return coords;
281
277
  }
@@ -324,10 +320,7 @@ async function detectOverflow(state, options) {
324
320
  height: rects.floating.height
325
321
  } : rects.reference;
326
322
  const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
327
- const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
328
- x: 1,
329
- y: 1
330
- } : {
323
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
331
324
  x: 1,
332
325
  y: 1
333
326
  };
@@ -482,13 +475,11 @@ const autoPlacement$1 = function (options) {
482
475
  ...detectOverflowOptions
483
476
  } = evaluate(options, state);
484
477
  const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;
485
- const overflow = await platform.detectOverflow(state, detectOverflowOptions);
486
478
  const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;
487
479
  const currentPlacement = placements$1[currentIndex];
488
480
  if (currentPlacement == null) {
489
481
  return {};
490
482
  }
491
- const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
492
483
 
493
484
  // Make `computeCoords` start from the right place.
494
485
  if (placement !== currentPlacement) {
@@ -498,6 +489,8 @@ const autoPlacement$1 = function (options) {
498
489
  }
499
490
  };
500
491
  }
492
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
493
+ const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
501
494
  const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];
502
495
  const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {
503
496
  placement: currentPlacement,
@@ -805,23 +798,16 @@ const shift$1 = function (options) {
805
798
  y
806
799
  };
807
800
  const overflow = await platform.detectOverflow(state, detectOverflowOptions);
808
- const crossAxis = getSideAxis(getSide(placement));
801
+ const crossAxis = getSideAxis(placement);
809
802
  const mainAxis = getOppositeAxis(crossAxis);
810
803
  let mainAxisCoord = coords[mainAxis];
811
804
  let crossAxisCoord = coords[crossAxis];
805
+ const clampCoord = (axis, coord) => clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);
812
806
  if (checkMainAxis) {
813
- const minSide = mainAxis === 'y' ? 'top' : 'left';
814
- const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
815
- const min = mainAxisCoord + overflow[minSide];
816
- const max = mainAxisCoord - overflow[maxSide];
817
- mainAxisCoord = clamp(min, mainAxisCoord, max);
807
+ mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);
818
808
  }
819
809
  if (checkCrossAxis) {
820
- const minSide = crossAxis === 'y' ? 'top' : 'left';
821
- const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
822
- const min = crossAxisCoord + overflow[minSide];
823
- const max = crossAxisCoord - overflow[maxSide];
824
- crossAxisCoord = clamp(min, crossAxisCoord, max);
810
+ crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);
825
811
  }
826
812
  const limitedCoords = limiter.fn({
827
813
  ...state,
@@ -978,7 +964,7 @@ function getParentNode(node) {
978
964
  function getNearestOverflowAncestor(node) {
979
965
  const parentNode = getParentNode(node);
980
966
  if (isLastTraversableNode(parentNode)) {
981
- return node.ownerDocument ? node.ownerDocument.body : node.body;
967
+ return (node.ownerDocument || node).body;
982
968
  }
983
969
  if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
984
970
  return parentNode;
@@ -1075,10 +1061,7 @@ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
1075
1061
  if (isFixed === void 0) {
1076
1062
  isFixed = false;
1077
1063
  }
1078
- if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
1079
- return false;
1080
- }
1081
- return isFixed;
1064
+ return !!floatingOffsetParent && isFixed && floatingOffsetParent === getWindow(element);
1082
1065
  }
1083
1066
 
1084
1067
  function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
@@ -1105,12 +1088,12 @@ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetPar
1105
1088
  let y = (clientRect.top + visualOffsets.y) / scale.y;
1106
1089
  let width = clientRect.width / scale.x;
1107
1090
  let height = clientRect.height / scale.y;
1108
- if (domElement) {
1091
+ if (domElement && offsetParent) {
1109
1092
  const win = getWindow(domElement);
1110
- const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
1093
+ const offsetWin = isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
1111
1094
  let currentWin = win;
1112
1095
  let currentIFrame = getFrameElement(currentWin);
1113
- while (currentIFrame && offsetParent && offsetWin !== currentWin) {
1096
+ while (currentIFrame && offsetWin !== currentWin) {
1114
1097
  const iframeScale = getScale(currentIFrame);
1115
1098
  const iframeRect = currentIFrame.getBoundingClientRect();
1116
1099
  const css = getComputedStyle$1(currentIFrame);
@@ -1174,7 +1157,7 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
1174
1157
  let scale = createCoords(1);
1175
1158
  const offsets = createCoords(0);
1176
1159
  const isOffsetParentAnElement = isHTMLElement(offsetParent);
1177
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
1160
+ if (isOffsetParentAnElement || !isFixed) {
1178
1161
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
1179
1162
  scroll = getNodeScroll(offsetParent);
1180
1163
  }
@@ -1195,18 +1178,17 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
1195
1178
  }
1196
1179
 
1197
1180
  function getClientRects(element) {
1198
- return Array.from(element.getClientRects());
1181
+ return element.getClientRects ? Array.from(element.getClientRects()) : [];
1199
1182
  }
1200
1183
 
1201
1184
  // Gets the entire size of the scrollable document area, even extending outside
1202
1185
  // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
1203
- function getDocumentRect(element) {
1204
- const html = getDocumentElement(element);
1205
- const scroll = getNodeScroll(element);
1206
- const body = element.ownerDocument.body;
1186
+ function getDocumentRect(html) {
1187
+ const scroll = getNodeScroll(html);
1188
+ const body = html.ownerDocument.body;
1207
1189
  const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
1208
1190
  const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
1209
- let x = -scroll.scrollLeft + getWindowScrollBarX(element);
1191
+ let x = -scroll.scrollLeft + getWindowScrollBarX(html);
1210
1192
  const y = -scroll.scrollTop;
1211
1193
  if (getComputedStyle$1(body).direction === 'rtl') {
1212
1194
  x += max(html.clientWidth, body.clientWidth) - width;
@@ -1223,7 +1205,11 @@ function getDocumentRect(element) {
1223
1205
  // calculation is affected by unusual styles.
1224
1206
  // Most scrollbars leave 15-18px of space.
1225
1207
  const SCROLLBAR_MAX = 25;
1226
- function getViewportRect(element, strategy) {
1208
+ function getViewportRect(element, strategy, rootBoundary) {
1209
+ if (rootBoundary === void 0) {
1210
+ rootBoundary = 'viewport';
1211
+ }
1212
+ const isLayoutViewport = rootBoundary === 'layoutViewport';
1227
1213
  const win = getWindow(element);
1228
1214
  const html = getDocumentElement(element);
1229
1215
  const visualViewport = win.visualViewport;
@@ -1232,31 +1218,42 @@ function getViewportRect(element, strategy) {
1232
1218
  let x = 0;
1233
1219
  let y = 0;
1234
1220
  if (visualViewport) {
1235
- width = visualViewport.width;
1236
- height = visualViewport.height;
1237
- const visualViewportBased = isWebKit();
1238
- if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
1239
- x = visualViewport.offsetLeft;
1240
- y = visualViewport.offsetTop;
1221
+ // Client coordinates are relative to the layout viewport, except in
1222
+ // WebKit with an `absolute` strategy, where they are relative to the
1223
+ // visual viewport.
1224
+ const layoutRelativeClientCoords = !isWebKit() || strategy === 'fixed';
1225
+ if (isLayoutViewport) {
1226
+ if (!layoutRelativeClientCoords) {
1227
+ x = -visualViewport.offsetLeft;
1228
+ y = -visualViewport.offsetTop;
1229
+ }
1230
+ } else {
1231
+ width = visualViewport.width;
1232
+ height = visualViewport.height;
1233
+ if (layoutRelativeClientCoords) {
1234
+ x = visualViewport.offsetLeft;
1235
+ y = visualViewport.offsetTop;
1236
+ }
1241
1237
  }
1242
1238
  }
1243
1239
  const windowScrollbarX = getWindowScrollBarX(html);
1244
- // <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the
1245
- // visual width of the <html> but this is not considered in the size
1246
- // of `html.clientWidth`.
1240
+ // `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks
1241
+ // the visual width but isn't reflected in `html.clientWidth`, so subtract it.
1242
+ // Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also
1243
+ // reserves an empty inline-start gutter that clips nothing, so exclude just
1244
+ // the one scrollbar-side gutter — halve the measured (two-gutter) total. A
1245
+ // left-side scrollbar (`windowScrollbarX > 0`) is already handled by
1246
+ // `getHTMLOffset`/`visualViewport.width`; skip it here.
1247
1247
  if (windowScrollbarX <= 0) {
1248
1248
  const doc = html.ownerDocument;
1249
1249
  const body = doc.body;
1250
1250
  const bodyStyles = getComputedStyle(body);
1251
1251
  const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
1252
- const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
1253
- if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
1254
- width -= clippingStableScrollbarWidth;
1252
+ const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
1253
+ const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;
1254
+ if (gutter <= SCROLLBAR_MAX) {
1255
+ width -= gutter;
1255
1256
  }
1256
- } else if (windowScrollbarX <= SCROLLBAR_MAX) {
1257
- // If the <body> scrollbar is on the left, the width needs to be extended
1258
- // by the scrollbar amount so there isn't extra space on the right.
1259
- width += windowScrollbarX;
1260
1257
  }
1261
1258
  return {
1262
1259
  width,
@@ -1271,7 +1268,7 @@ function getInnerBoundingClientRect(element, strategy) {
1271
1268
  const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
1272
1269
  const top = clientRect.top + element.clientTop;
1273
1270
  const left = clientRect.left + element.clientLeft;
1274
- const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
1271
+ const scale = getScale(element);
1275
1272
  const width = element.clientWidth * scale.x;
1276
1273
  const height = element.clientHeight * scale.y;
1277
1274
  const x = left * scale.x;
@@ -1285,8 +1282,8 @@ function getInnerBoundingClientRect(element, strategy) {
1285
1282
  }
1286
1283
  function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
1287
1284
  let rect;
1288
- if (clippingAncestor === 'viewport') {
1289
- rect = getViewportRect(element, strategy);
1285
+ if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {
1286
+ rect = getViewportRect(element, strategy, clippingAncestor);
1290
1287
  } else if (clippingAncestor === 'document') {
1291
1288
  rect = getDocumentRect(getDocumentElement(element));
1292
1289
  } else if (isElement(clippingAncestor)) {
@@ -1302,13 +1299,6 @@ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy)
1302
1299
  }
1303
1300
  return rectToClientRect(rect);
1304
1301
  }
1305
- function hasFixedPositionAncestor(element, stopNode) {
1306
- const parentNode = getParentNode(element);
1307
- if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
1308
- return false;
1309
- }
1310
- return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
1311
- }
1312
1302
 
1313
1303
  // A "clipping ancestor" is an `overflow` element with the characteristic of
1314
1304
  // clipping (or hiding) child elements. This returns all clipping ancestors
@@ -1319,7 +1309,7 @@ function getClippingElementAncestors(element, cache) {
1319
1309
  return cachedResult;
1320
1310
  }
1321
1311
  let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
1322
- let currentContainingBlockComputedStyle = null;
1312
+ let lastKeptComputedStyle = null;
1323
1313
  const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
1324
1314
  let currentNode = elementIsFixed ? getParentNode(element) : element;
1325
1315
 
@@ -1327,16 +1317,20 @@ function getClippingElementAncestors(element, cache) {
1327
1317
  while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
1328
1318
  const computedStyle = getComputedStyle$1(currentNode);
1329
1319
  const currentNodeIsContaining = isContainingBlock(currentNode);
1330
- if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
1331
- currentContainingBlockComputedStyle = null;
1332
- }
1333
- const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === 'absolute' || currentContainingBlockComputedStyle.position === 'fixed') || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
1320
+ // Position of the containing block chain below the current node. A fixed
1321
+ // element whose containing block hasn't been found yet is a fixed chain.
1322
+ const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';
1323
+
1324
+ // A non-containing ancestor does not clip the element when the chain
1325
+ // below it escapes it: a fixed chain escapes all ancestors up to the
1326
+ // next containing block, an absolute chain escapes static ancestors.
1327
+ const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');
1334
1328
  if (shouldDropCurrentNode) {
1335
1329
  // Drop non-containing blocks.
1336
1330
  result = result.filter(ancestor => ancestor !== currentNode);
1337
1331
  } else {
1338
- // Record last containing block for next iteration.
1339
- currentContainingBlockComputedStyle = computedStyle;
1332
+ // The kept node carries the chain position for the next iteration.
1333
+ lastKeptComputedStyle = computedStyle;
1340
1334
  }
1341
1335
  currentNode = getParentNode(currentNode);
1342
1336
  }
@@ -1396,13 +1390,7 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
1396
1390
  scrollTop: 0
1397
1391
  };
1398
1392
  const offsets = createCoords(0);
1399
-
1400
- // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
1401
- // Firefox with layout.scrollbar.side = 3 in about:config to test this.
1402
- function setLeftRTLScrollbarOffset() {
1403
- offsets.x = getWindowScrollBarX(documentElement);
1404
- }
1405
- if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
1393
+ if (isOffsetParentAnElement || !isFixed) {
1406
1394
  if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
1407
1395
  scroll = getNodeScroll(offsetParent);
1408
1396
  }
@@ -1410,12 +1398,13 @@ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
1410
1398
  const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
1411
1399
  offsets.x = offsetRect.x + offsetParent.clientLeft;
1412
1400
  offsets.y = offsetRect.y + offsetParent.clientTop;
1413
- } else if (documentElement) {
1414
- setLeftRTLScrollbarOffset();
1415
1401
  }
1416
1402
  }
1417
- if (isFixed && !isOffsetParentAnElement && documentElement) {
1418
- setLeftRTLScrollbarOffset();
1403
+
1404
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
1405
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
1406
+ if (!isOffsetParentAnElement && documentElement) {
1407
+ offsets.x = getWindowScrollBarX(documentElement);
1419
1408
  }
1420
1409
  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
1421
1410
  const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
@@ -1515,7 +1504,7 @@ function rectsAreEqual(a, b) {
1515
1504
  }
1516
1505
 
1517
1506
  // https://samthor.au/2021/observing-dom/
1518
- function observeMove(element, onMove) {
1507
+ function observeMove(element, onMove, ancestorResize) {
1519
1508
  let io = null;
1520
1509
  let timeoutId;
1521
1510
  const root = getDocumentElement(element);
@@ -1558,13 +1547,22 @@ function observeMove(element, onMove) {
1558
1547
  let isFirstUpdate = true;
1559
1548
  function handleObserve(entries) {
1560
1549
  const ratio = entries[0].intersectionRatio;
1550
+
1551
+ // The entry is a snapshot, so the reference may have moved since the
1552
+ // intersection was computed (under performance constraints, or between
1553
+ // consecutive frames of a multi-frame layout shift). The reported ratio
1554
+ // and the observed area are stale in that case and cannot be trusted to
1555
+ // detect subsequent movement, so refresh regardless of the ratio.
1556
+ if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
1557
+ return refresh();
1558
+ }
1561
1559
  if (ratio !== threshold) {
1562
1560
  if (!isFirstUpdate) {
1563
1561
  return refresh();
1564
1562
  }
1565
1563
  if (!ratio) {
1566
- // If the reference is clipped, the ratio is 0. Throttle the refresh
1567
- // to prevent an infinite loop of updates.
1564
+ // If the reference is clipped in place, the ratio is 0. Throttle
1565
+ // the refresh to prevent an infinite loop of updates.
1568
1566
  timeoutId = setTimeout(() => {
1569
1567
  refresh(false, 1e-7);
1570
1568
  }, 1000);
@@ -1572,16 +1570,6 @@ function observeMove(element, onMove) {
1572
1570
  refresh(false, ratio);
1573
1571
  }
1574
1572
  }
1575
- if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
1576
- // It's possible that even though the ratio is reported as 1, the
1577
- // element is not actually fully within the IntersectionObserver's root
1578
- // area anymore. This can happen under performance constraints. This may
1579
- // be a bug in the browser's IntersectionObserver implementation. To
1580
- // work around this, we compare the element's bounding rect now with
1581
- // what it was at the time we created the IntersectionObserver. If they
1582
- // are not equal then the element moved, so we refresh.
1583
- refresh();
1584
- }
1585
1573
  isFirstUpdate = false;
1586
1574
  }
1587
1575
 
@@ -1598,8 +1586,18 @@ function observeMove(element, onMove) {
1598
1586
  }
1599
1587
  io.observe(element);
1600
1588
  }
1589
+ const win = getWindow(element);
1590
+ // The window is a resize ancestor, so when `ancestorResize` is enabled its
1591
+ // listener already runs the update on resize. Here we only need to rebuild
1592
+ // the `IntersectionObserver` for the new root size, skipping a redundant
1593
+ // update. When `ancestorResize` is disabled, this becomes the sole update.
1594
+ const handleResize = () => refresh(ancestorResize);
1595
+ win.addEventListener('resize', handleResize);
1601
1596
  refresh(true);
1602
- return cleanup;
1597
+ return () => {
1598
+ win.removeEventListener('resize', handleResize);
1599
+ cleanup();
1600
+ };
1603
1601
  }
1604
1602
 
1605
1603
  /**
@@ -1624,12 +1622,10 @@ function autoUpdate(reference, floating, update, options) {
1624
1622
  const referenceEl = unwrapElement(reference);
1625
1623
  const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];
1626
1624
  ancestors.forEach(ancestor => {
1627
- ancestorScroll && ancestor.addEventListener('scroll', update, {
1628
- passive: true
1629
- });
1625
+ ancestorScroll && ancestor.addEventListener('scroll', update);
1630
1626
  ancestorResize && ancestor.addEventListener('resize', update);
1631
1627
  });
1632
- const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
1628
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;
1633
1629
  let reobserveFrame = -1;
1634
1630
  let resizeObserver = null;
1635
1631
  if (elementResize) {
@@ -1724,11 +1720,9 @@ const computePosition = (reference, floating, options) => {
1724
1720
  // multiple lifecycle resets re-use the same result. It only lives for a
1725
1721
  // single call. If other functions become expensive, we can add them as well.
1726
1722
  const cache = new Map();
1727
- const mergedOptions = {
1728
- platform,
1729
- ...options
1730
- };
1723
+ const mergedOptions = options != null ? options : {};
1731
1724
  const platformWithCache = {
1725
+ ...platform,
1732
1726
  ...mergedOptions.platform,
1733
1727
  _c: cache
1734
1728
  };
@@ -2067,30 +2061,61 @@ class AuroFloatingUI {
2067
2061
 
2068
2062
  /**
2069
2063
  * @private
2070
- * Controls whether to lock the scrolling for the document's body.
2071
- * @param {Boolean} lock - If true, locks the body's scrolling functionlity; otherwise, unlock.
2064
+ * Mirrors `aria-modal` onto the `<dialog>` inside the bib, tracking the page
2065
+ * scroll lock: an overlay that holds the page hides it from assistive tech.
2066
+ *
2067
+ * The removal is called only from inside lockScroll()'s ownership guard: run
2068
+ * outside it, it fired on every autoUpdate tick of every NON-owning instance,
2069
+ * and a repositioning dropdown stripped `aria-modal` off an open modal dialog
2070
+ * it had nothing to do with. The write is unguarded by design — see the call
2071
+ * site — but is skipped when the attribute already reads correctly, so the
2072
+ * repeat costs no mutation record.
2073
+ * @param {Boolean} modal - True to mark the dialog modal; false to unmark it.
2072
2074
  */
2073
- lockScroll(lock = true) {
2075
+ mirrorAriaModal(modal) {
2074
2076
  const element = this.element;
2077
+ const dialog = element?.bib
2078
+ ? (element.bib?.shadowRoot || element.bib || element).querySelector(
2079
+ "dialog",
2080
+ )
2081
+ : undefined;
2075
2082
 
2076
- if (!element?.bib) {
2083
+ if (!dialog) {
2077
2084
  return;
2078
2085
  }
2079
2086
 
2080
- const dialog = (
2081
- element.bib?.shadowRoot ||
2082
- element.bib ||
2083
- element
2084
- ).querySelector("dialog");
2085
- if (dialog) {
2086
- if (lock) {
2087
+ if (modal) {
2088
+ if (dialog.getAttribute("aria-modal") !== "true") {
2087
2089
  dialog.setAttribute("aria-modal", "true");
2088
- } else {
2089
- dialog.removeAttribute("aria-modal");
2090
2090
  }
2091
+ } else {
2092
+ dialog.removeAttribute("aria-modal");
2093
+ }
2094
+ }
2095
+
2096
+ /**
2097
+ * @private
2098
+ * Controls whether to lock the scrolling for the document's body.
2099
+ * @param {Boolean} lock - If true, locks the body's scrolling functionlity; otherwise, unlock.
2100
+ */
2101
+ lockScroll(lock = true) {
2102
+ const element = this.element;
2103
+
2104
+ // Locking needs a bib to lock around; unlocking must not, or a bib that has
2105
+ // already been detached would leave the page frozen with no way back.
2106
+ if (lock && !element?.bib) {
2107
+ return;
2091
2108
  }
2092
2109
 
2093
2110
  if (lock) {
2111
+ // Re-asserted on every lock call rather than only on the unlocked ->
2112
+ // locked transition. If the bib's inner <dialog> is replaced while this
2113
+ // instance still holds the lock, the replacement would otherwise go
2114
+ // unmarked until a full unlock/lock cycle. Safe to repeat: it targets
2115
+ // this instance's own element, so it cannot reach another overlay's
2116
+ // dialog, and mirrorAriaModal() skips the write when already correct.
2117
+ this.mirrorAriaModal(true);
2118
+
2094
2119
  if (!this._scrollLocked) {
2095
2120
  this._scrollLocked = true;
2096
2121
  this._savedScrollY = window.scrollY;
@@ -2148,6 +2173,8 @@ class AuroFloatingUI {
2148
2173
  }
2149
2174
  } else {
2150
2175
  if (this._scrollLocked) {
2176
+ this.mirrorAriaModal(false);
2177
+
2151
2178
  if (this._viewportHandler && window.visualViewport) {
2152
2179
  window.visualViewport.removeEventListener(
2153
2180
  "resize",
@@ -2260,15 +2287,47 @@ class AuroFloatingUI {
2260
2287
  } else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
2261
2288
  this.configureTrial += 1;
2262
2289
 
2263
- setTimeout(() => {
2290
+ // The id is retained so disconnect() can cancel it. A retry that fires
2291
+ // after teardown re-enters this method with isPopoverVisible still true
2292
+ // — nothing clears it on the teardown path — and takes the page scroll
2293
+ // lock back, with no owner left to release it.
2294
+ //
2295
+ // This is not the rare timing race it reads as: the lookup above wants
2296
+ // a `.container` inside the BIB's own shadow root, which only a bib
2297
+ // that is itself a custom element has. A consumer whose bib is a plain
2298
+ // element (auro-dialog's `#bib` is a div, with its `.container` a
2299
+ // sibling in the host's shadow root) can never satisfy it, so it
2300
+ // retries the full MAX_CONFIGURATION_COUNT every time. Correcting the
2301
+ // lookup would change bib sizing for those consumers and is tracked
2302
+ // separately; cancelling the timer is what keeps it from freezing the
2303
+ // page.
2304
+ this._configureRetryId = setTimeout(() => {
2305
+ this._configureRetryId = undefined;
2264
2306
  this.configureBibStrategy(value);
2265
2307
  }, 0);
2266
2308
  }
2267
2309
 
2268
2310
  if (element.isPopoverVisible) {
2269
- this.lockScroll(value === "fullscreen");
2311
+ // Positioning strategy is not scroll ownership. Both "fullscreen" and
2312
+ // "dialog" lay the bib over the page and trap focus inside it, so both
2313
+ // must freeze the page behind them (AB#1647843). Gating this on
2314
+ // "fullscreen" alone left dismissible desktop dialogs and drawers
2315
+ // scrollable, and actively released the lock on every reposition
2316
+ // (AB#1625424, AB#1625435). The nested "cover" strategy takes the else
2317
+ // branch and stays scrollable by design — it sits inside its parent
2318
+ // rather than over the page.
2319
+ this.lockScroll(true);
2270
2320
  }
2271
2321
  } else {
2322
+ // The mirror of the lock above: a strategy that does not own the page must
2323
+ // hand the lock back, not merely decline to take it. autoUpdate re-runs
2324
+ // this method on every resize tick, and getPositioningStrategy() flips
2325
+ // "fullscreen" -> "floating" across the breakpoint for dropdown behavior —
2326
+ // so an overlay that locked while narrow can land here while still open.
2327
+ // Without this, the page stays frozen behind a small floating bib until
2328
+ // hideBib() happens to run.
2329
+ this.lockScroll(false);
2330
+
2272
2331
  element.bib.style.position = "";
2273
2332
  element.bib.removeAttribute("isfullscreen");
2274
2333
  element.isBibFullscreen = false;
@@ -2378,6 +2437,46 @@ class AuroFloatingUI {
2378
2437
  this.hideBib("focusloss");
2379
2438
  }
2380
2439
 
2440
+ /**
2441
+ * @private
2442
+ * Installs the handlers that dismiss an open overlay.
2443
+ *
2444
+ * Shared by showBib(), which opens the overlay, and configure(), which has to
2445
+ * put these back after a rewire tore them down under an overlay that is still
2446
+ * open. A non-modal overlay dismisses on outside click, focus loss and
2447
+ * Escape; a modal one instead swallows Escape so the native dialog's
2448
+ * CloseWatcher never sees it (AB#1613688).
2449
+ */
2450
+ setupDismissHandlers() {
2451
+ const element = this.element;
2452
+ if (!element) {
2453
+ return;
2454
+ }
2455
+
2456
+ if (!element.modal) {
2457
+ this.setupHideHandlers();
2458
+ return;
2459
+ }
2460
+
2461
+ if (this.keyDownHandler) {
2462
+ document.removeEventListener("keydown", this.keyDownHandler);
2463
+ }
2464
+ this.keyDownHandler = (evt) => {
2465
+ if (evt.key === "Escape" && element.isPopoverVisible) {
2466
+ // Intercept at keydown so CloseWatcher never sees the keystroke.
2467
+ // Canceling `cancel` alone is insufficient — a second Esc with no
2468
+ // intervening user activation triggers the anti-trap and fires `close`
2469
+ // directly, bypassing any `cancel` preventDefault (AB#1613688).
2470
+ // stopImmediatePropagation is intentional: it prevents other document
2471
+ // keydown handlers (e.g. consumer code, auro-dialog) from also acting
2472
+ // on Escape while the modal owns the key.
2473
+ evt.preventDefault();
2474
+ evt.stopImmediatePropagation();
2475
+ }
2476
+ };
2477
+ document.addEventListener("keydown", this.keyDownHandler);
2478
+ }
2479
+
2381
2480
  setupHideHandlers() {
2382
2481
  const element = this.element;
2383
2482
  if (!element) {
@@ -2550,27 +2649,7 @@ class AuroFloatingUI {
2550
2649
 
2551
2650
  // prevent double showing: isPopovervisible gets first and showBib gets called later
2552
2651
  if (!this.showing) {
2553
- if (!element.modal) {
2554
- this.setupHideHandlers();
2555
- } else {
2556
- if (this.keyDownHandler) {
2557
- document.removeEventListener("keydown", this.keyDownHandler);
2558
- }
2559
- this.keyDownHandler = (evt) => {
2560
- if (evt.key === "Escape" && element.isPopoverVisible) {
2561
- // Intercept at keydown so CloseWatcher never sees the keystroke.
2562
- // Canceling `cancel` alone is insufficient — a second Esc with no
2563
- // intervening user activation triggers the anti-trap and fires `close`
2564
- // directly, bypassing any `cancel` preventDefault (AB#1613688).
2565
- // stopImmediatePropagation is intentional: it prevents other document
2566
- // keydown handlers (e.g. consumer code, auro-dialog) from also acting
2567
- // on Escape while the modal owns the key.
2568
- evt.preventDefault();
2569
- evt.stopImmediatePropagation();
2570
- }
2571
- };
2572
- document.addEventListener("keydown", this.keyDownHandler);
2573
- }
2652
+ this.setupDismissHandlers();
2574
2653
  this.showing = true;
2575
2654
  element.isPopoverVisible = true;
2576
2655
  this.position();
@@ -2810,7 +2889,35 @@ class AuroFloatingUI {
2810
2889
  this.enableKeyboardHandling = enableKeyboardHandling;
2811
2890
 
2812
2891
  this.eventPrefix = eventPrefix;
2813
- if (this.element !== elem) {
2892
+
2893
+ // A retained scroll lock's saved body styles were captured for whichever
2894
+ // element held it, so only a same-element rewire may keep it. An actual
2895
+ // element swap has to take the full teardown, or this instance is left
2896
+ // holding a lock that no longer describes the page it points at — with no
2897
+ // owner able to release it (AB#1647843).
2898
+ const rewiringSameElement = this.element === elem;
2899
+
2900
+ if (!rewiringSameElement) {
2901
+ // Tear down against the outgoing element, before this.element is
2902
+ // repointed. Everything disconnect() releases is element-scoped:
2903
+ // aria-modal on that element's inner dialog, the bib transform saved for
2904
+ // it, its autoUpdate loop and its trigger listeners. Repointing first
2905
+ // aimed all of it at the incoming element — the outgoing dialog kept
2906
+ // aria-modal="true" for good, its bib stayed transformed, and the
2907
+ // incoming bib had the outgoing element's saved transform written onto
2908
+ // it. The trigger gate below read the incoming element's trigger, which
2909
+ // is not assigned until later in this method, so on a swap teardown was
2910
+ // usually skipped outright and the page stayed locked with no owner.
2911
+ if (this.element?.trigger) {
2912
+ this.disconnect({ teardown: true });
2913
+ }
2914
+
2915
+ // disconnect() does not clear this.showing, and the rewire block at the
2916
+ // end of this method only runs for a same-element rewire. Left true, the
2917
+ // incoming element's first showBib() is silently dropped by its
2918
+ // `!this.showing` guard and the overlay never opens.
2919
+ this.showing = false;
2920
+
2814
2921
  this.element = elem;
2815
2922
  }
2816
2923
 
@@ -2823,8 +2930,10 @@ class AuroFloatingUI {
2823
2930
  this.behavior = element.behavior;
2824
2931
  }
2825
2932
 
2826
- if (element.trigger) {
2827
- this.disconnect();
2933
+ if (rewiringSameElement && element.trigger) {
2934
+ // Rewiring, not tearing down — an overlay that is open right now keeps
2935
+ // its page scroll lock across a trigger change.
2936
+ this.disconnect({ teardown: false });
2828
2937
  }
2829
2938
  element.trigger =
2830
2939
  element.triggerElement ||
@@ -2853,11 +2962,61 @@ class AuroFloatingUI {
2853
2962
  element.trigger.addEventListener("focus", this.handleEvent);
2854
2963
  element.trigger.addEventListener("blur", this.handleEvent);
2855
2964
  }
2965
+
2966
+ // disconnect() above stripped the dismissal handlers and killed the
2967
+ // autoUpdate loop; the trigger listeners re-registered here replace
2968
+ // neither. An overlay that is open right now would otherwise be left on
2969
+ // screen with outside-click, focus-loss and Escape all dead and its
2970
+ // position frozen — and, since the lock is deliberately retained, holding
2971
+ // the page with only its original trigger able to give it back.
2972
+ if (rewiringSameElement && this.showing) {
2973
+ this.setupDismissHandlers();
2974
+
2975
+ if (element.bib && (element.trigger || element.parentNode)) {
2976
+ element.cleanup = autoUpdate(
2977
+ element.trigger || element.parentNode,
2978
+ element.bib,
2979
+ () => {
2980
+ this.position();
2981
+ },
2982
+ );
2983
+ }
2984
+ }
2856
2985
  }
2857
2986
 
2858
- disconnect() {
2987
+ /**
2988
+ * Tears the floater's connections down.
2989
+ *
2990
+ * Two callers with different intent share this: a real teardown, which must
2991
+ * release the page scroll lock, and configure(), which re-runs it purely to
2992
+ * rewire a changed trigger and must leave an open overlay's lock alone.
2993
+ * @param {Object} [options] - Teardown options.
2994
+ * @param {Boolean} [options.teardown] - False when only rewiring; keeps the
2995
+ * page scroll lock held for an overlay that is still open.
2996
+ * @returns {void}
2997
+ */
2998
+ disconnect({ teardown = true } = {}) {
2859
2999
  this.cleanupHideHandlers();
2860
3000
 
3001
+ // Cancel any pending configureBibStrategy() retry. It would otherwise fire
3002
+ // a macrotask after the unlock below, re-lock the page, and leave it frozen
3003
+ // with the floater already gone. Cancelled on a rewire too: configure()
3004
+ // re-runs position() itself, so a stale retry has nothing to contribute.
3005
+ if (this._configureRetryId !== undefined) {
3006
+ clearTimeout(this._configureRetryId);
3007
+ this._configureRetryId = undefined;
3008
+ }
3009
+
3010
+ // Tearing down while the bib is still open would otherwise strand
3011
+ // body{position:fixed} and leave the page permanently unscrollable —
3012
+ // hideBib() is the only other unlock, and it never runs in this path.
3013
+ // Skipped when merely rewiring: configure() routes through here on every
3014
+ // triggerElement change, and releasing the lock there would unlock the page
3015
+ // behind an overlay that is still open (AB#1625424, AB#1625435).
3016
+ if (teardown) {
3017
+ this.lockScroll(false);
3018
+ }
3019
+
2861
3020
  const element = this.element;
2862
3021
  if (!element) {
2863
3022
  return;
@@ -3843,7 +4002,7 @@ class AuroHelpText extends LitElement {
3843
4002
  }
3844
4003
  }
3845
4004
 
3846
- var formkitVersion = '202609242008';
4005
+ var formkitVersion = '202610081824';
3847
4006
 
3848
4007
  /**
3849
4008
  * AuroElement is the shared base class for layout-aware Auro form components.