@planningcenter/topbar 12.3.0-qa-952.0 → 12.3.0-qa-953.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/dist/topbar.js CHANGED
@@ -3390,6 +3390,45 @@ function saveLastProduct(slug) {
3390
3390
  }
3391
3391
  }
3392
3392
 
3393
+ // Products open modals from many libraries, not all of which mark themselves
3394
+ // with roles, so a modal is recognized by what it does: cover the page.
3395
+ function isModalOpen() {
3396
+ const {
3397
+ clientHeight,
3398
+ clientWidth
3399
+ } = document.documentElement;
3400
+ const element = document.elementFromPoint(clientWidth / 2, clientHeight / 2);
3401
+ return element !== null && (isInNativeDialog(element) || hasBackdrop(element, clientWidth, clientHeight));
3402
+ }
3403
+ // A native modal's backdrop is drawn by the browser rather than being an
3404
+ // element; hit-testing it lands on the dialog itself.
3405
+ function isInNativeDialog(element) {
3406
+ return element.closest("dialog[open]") !== null;
3407
+ }
3408
+ function hasBackdrop(element, width, height) {
3409
+ let current = element;
3410
+ while (current && !isBackdrop(current, width, height)) {
3411
+ current = current.parentElement;
3412
+ }
3413
+ return current !== null;
3414
+ }
3415
+ // Some backdrops start below the topbar rather than at the top of the screen,
3416
+ // so the layer only has to span the width and reach from the center to the
3417
+ // bottom. Its own box has to reach the center: a bar along the bottom can
3418
+ // hold a panel that pops up over the center, like Services' media player.
3419
+ // react-aria leaves a closed modal's backdrop up while it fades out, search's
3420
+ // own included, so one that's on its way out doesn't count.
3421
+ function isBackdrop(element, width, height) {
3422
+ const rect = element.getBoundingClientRect();
3423
+ return !element.matches("[data-exiting]") && getComputedStyle(element).position === "fixed" && rect.width >= width - SCROLLBAR_SLACK && rect.top <= height / 2 && rect.bottom >= height - ROUNDING_SLACK;
3424
+ }
3425
+ // react-aria keeps a classic scrollbar's gutter reserved while its modals lock
3426
+ // scrolling, so their backdrops stop short of the right edge by its width.
3427
+ const SCROLLBAR_SLACK = 24;
3428
+ // Rects are fractional at non-100% zoom, but clientWidth and clientHeight are
3429
+ // rounded to whole pixels.
3430
+ const ROUNDING_SLACK = 1;
3431
+
3393
3432
  var styles$e = {"visuallyHidden":"visuallyHidden-C28ju","searchButton":"searchButton-YAeJ1","modal":"modal-NR3TO","header":"header-c3SLe","input":"input-DkZNI","clearButton":"clearButton-t5hFs"};
3394
3433
 
3395
3434
  var styles$d = {"icon":"icon-XKLvN","squircle":"squircle-JCHr6"};
@@ -4623,13 +4662,15 @@ function SearchButtonAndDialog({
4623
4662
  const [open, setOpen] = React.useState(false);
4624
4663
  React.useEffect(() => {
4625
4664
  // Rich text editors like Trix bind ⌘K to "insert link"; capturing at the
4626
- // window and stopping propagation keeps them from ever seeing it.
4665
+ // window and stopping propagation keeps them from ever seeing it. Under a
4666
+ // product's modal, search stays shut rather than stacking a second modal,
4667
+ // and the keystroke goes on to the product.
4627
4668
  const handleKeyDown = event => {
4628
- if (isSearchShortcut(event)) {
4669
+ if (open && isSearchShortcut(event)) {
4629
4670
  event.preventDefault();
4630
4671
  event.stopPropagation();
4631
- setOpen(wasOpen => !wasOpen);
4632
- } else if (isLegacySearchShortcut(event)) {
4672
+ setOpen(false);
4673
+ } else if (!open && (isSearchShortcut(event) || isLegacySearchShortcut(event)) && !isModalOpen()) {
4633
4674
  event.preventDefault();
4634
4675
  event.stopPropagation();
4635
4676
  setOpen(true);
@@ -4641,7 +4682,7 @@ function SearchButtonAndDialog({
4641
4682
  return () => window.removeEventListener("keydown", handleKeyDown, {
4642
4683
  capture: true
4643
4684
  });
4644
- }, []);
4685
+ }, [open]);
4645
4686
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
4646
4687
  "aria-keyshortcuts": `${isMac() ? "Meta+K" : "Control+K"} /`,
4647
4688
  "aria-label": "Search",