@allxsmith/bestax-bulma 5.34.0 → 5.34.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 (42) hide show
  1. package/dist/esm/components/Dropdown.js +8 -3
  2. package/dist/esm/components/Dropdown.js.map +1 -1
  3. package/dist/esm/components/Loading.js +5 -4
  4. package/dist/esm/components/Loading.js.map +1 -1
  5. package/dist/esm/components/Modal.js +11 -4
  6. package/dist/esm/components/Modal.js.map +1 -1
  7. package/dist/esm/components/Sidebar.js +5 -4
  8. package/dist/esm/components/Sidebar.js.map +1 -1
  9. package/dist/esm/components/Toast.js +7 -5
  10. package/dist/esm/components/Toast.js.map +1 -1
  11. package/dist/esm/form/Autocomplete.js +17 -2
  12. package/dist/esm/form/Autocomplete.js.map +1 -1
  13. package/dist/esm/form/Field.js +3 -3
  14. package/dist/esm/form/Field.js.map +1 -1
  15. package/dist/esm/form/FormContext.js +2 -1
  16. package/dist/esm/form/FormContext.js.map +1 -1
  17. package/dist/esm/form/Taginput.js +40 -6
  18. package/dist/esm/form/Taginput.js.map +1 -1
  19. package/dist/esm/form/_pickerInternals/PickerPopover.js +11 -3
  20. package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
  21. package/dist/esm/form/useAutoLabelId.js.map +1 -1
  22. package/dist/index.cjs +107 -34
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/types/components/Loading.d.ts +5 -1
  25. package/dist/types/components/Modal.d.ts +4 -1
  26. package/dist/types/components/Sidebar.d.ts +5 -1
  27. package/dist/types/components/Toast.d.ts +4 -1
  28. package/dist/types/form/Autocomplete.d.ts +13 -2
  29. package/dist/types/form/Field.d.ts +5 -5
  30. package/dist/types/form/FormContext.d.ts +2 -1
  31. package/dist/types/form/Taginput.d.ts +8 -3
  32. package/dist/types/form/useAutoLabelId.d.ts +2 -2
  33. package/dist/types-cjs/components/Loading.d.ts +5 -1
  34. package/dist/types-cjs/components/Modal.d.ts +4 -1
  35. package/dist/types-cjs/components/Sidebar.d.ts +5 -1
  36. package/dist/types-cjs/components/Toast.d.ts +4 -1
  37. package/dist/types-cjs/form/Autocomplete.d.ts +13 -2
  38. package/dist/types-cjs/form/Field.d.ts +5 -5
  39. package/dist/types-cjs/form/FormContext.d.ts +2 -1
  40. package/dist/types-cjs/form/Taginput.d.ts +8 -3
  41. package/dist/types-cjs/form/useAutoLabelId.d.ts +2 -2
  42. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -2563,8 +2563,9 @@ const isBrowser$1 = (win, doc) => typeof win !== 'undefined' && typeof doc !== '
2563
2563
  * the menu, so a letter typed on the trigger does nothing. Escape closes the
2564
2564
  * menu and focuses the trigger, and Tab closes it and lets focus move on.
2565
2565
  * Anything focusable in the menu that isn't an item, such as a field, keeps
2566
- * its own keys apart from Escape and Tab. For a panel built around fields,
2567
- * use `Popover`.
2566
+ * its own keys apart from Escape and Tab, though an Escape it calls
2567
+ * `preventDefault()` on in its own `onKeyDown` stays its own and leaves the
2568
+ * menu open. For a panel built around fields, use `Popover`.
2568
2569
  *
2569
2570
  * @function
2570
2571
  * @param {DropdownProps} props - Props for the Dropdown component.
@@ -2741,8 +2742,12 @@ const DropdownComponent = React.forwardRef(function DropdownComponent({ label, c
2741
2742
  // Closing is Dropdown's: Escape and Tab close the menu from anywhere in
2742
2743
  // it, a field included, and an empty or all-disabled menu too. Moving
2743
2744
  // between the items, running them and typeahead are the hook's, which
2744
- // acts only while focus is on the menu or one of its items.
2745
+ // acts only while focus is on the menu or one of its items. An Escape
2746
+ // something in the menu already used, such as a field's own list
2747
+ // closing on it, leaves the menu open for the next one.
2745
2748
  if (e.key === 'Escape') {
2749
+ if (e.defaultPrevented)
2750
+ return;
2746
2751
  e.preventDefault();
2747
2752
  setActive(false);
2748
2753
  onActiveChange?.(false);
@@ -4056,6 +4061,9 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
4056
4061
  };
4057
4062
  }, [isModalActive]);
4058
4063
  // Escape closes; Tab cycles inside the modal. Both only for the topmost one.
4064
+ // The listener is on `window`, where a keydown arrives last, so everything
4065
+ // inside the modal has had the key first: React's handlers, and `document`
4066
+ // listeners added after this one, such as a date picker's.
4059
4067
  React.useEffect(() => {
4060
4068
  if (!isModalActive)
4061
4069
  return undefined;
@@ -4065,11 +4073,15 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
4065
4073
  return;
4066
4074
  }
4067
4075
  if (e.key === 'Escape') {
4068
- if (closeOnEscape)
4076
+ // Something inside already used this Escape, such as a popup that
4077
+ // closed on it, so the modal waits for the next one.
4078
+ if (closeOnEscape && !e.defaultPrevented)
4069
4079
  onClose?.();
4070
4080
  return;
4071
4081
  }
4072
- if (e.key !== 'Tab' || !node)
4082
+ // A trap inside the modal, such as a portaled popup's, already moved
4083
+ // focus on this Tab, so the modal leaves it where it went.
4084
+ if (e.key !== 'Tab' || !node || e.defaultPrevented)
4073
4085
  return;
4074
4086
  // Keep Tab within the modal — `aria-modal` hides the rest of the page
4075
4087
  // from assistive technology, so the keyboard order has to agree.
@@ -4094,8 +4106,8 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
4094
4106
  first.focus();
4095
4107
  }
4096
4108
  };
4097
- document.addEventListener('keydown', handleKeyDown);
4098
- return () => document.removeEventListener('keydown', handleKeyDown);
4109
+ window.addEventListener('keydown', handleKeyDown);
4110
+ return () => window.removeEventListener('keydown', handleKeyDown);
4099
4111
  }, [isModalActive, closeOnEscape, onClose]);
4100
4112
  // Move focus into the modal on open, restore it on close
4101
4113
  React.useEffect(() => {
@@ -5375,17 +5387,18 @@ const Loading = ({ active = false, isFullPage = false, size, color, canCancel =
5375
5387
  onCancel();
5376
5388
  }
5377
5389
  };
5378
- // Handle escape key
5390
+ // Handle escape key. On `window`, as in `Modal`, so a popup on the page has
5391
+ // had the key first, and an Escape it closed on doesn't cancel as well.
5379
5392
  React.useEffect(() => {
5380
5393
  if (!active || !canCancel || !onCancel)
5381
5394
  return;
5382
5395
  const handleKeyDown = (e) => {
5383
- if (e.key === 'Escape') {
5396
+ if (e.key === 'Escape' && !e.defaultPrevented) {
5384
5397
  onCancel();
5385
5398
  }
5386
5399
  };
5387
- document.addEventListener('keydown', handleKeyDown);
5388
- return () => document.removeEventListener('keydown', handleKeyDown);
5400
+ window.addEventListener('keydown', handleKeyDown);
5401
+ return () => window.removeEventListener('keydown', handleKeyDown);
5389
5402
  }, [active, canCancel, onCancel]);
5390
5403
  // Prevent body scroll when full page loading is active. Ref-counted through
5391
5404
  // the shared helper so an overlapping Modal/Dialog/Sidebar doesn't have its
@@ -7795,17 +7808,18 @@ const SidebarComponent = React.forwardRef(({ isOpen, onClose, position = 'left',
7795
7808
  handleClose();
7796
7809
  }
7797
7810
  }, [overlayClose, handleClose]);
7798
- // Handle escape key
7811
+ // Handle escape key. On `window`, as in `Modal`, so everything inside the
7812
+ // sidebar has had the key first, and an Escape it used is left to it.
7799
7813
  React.useEffect(() => {
7800
7814
  if (!isOpen || !escapeClose)
7801
7815
  return;
7802
7816
  const handleKeyDown = (e) => {
7803
- if (e.key === 'Escape') {
7817
+ if (e.key === 'Escape' && !e.defaultPrevented) {
7804
7818
  handleClose();
7805
7819
  }
7806
7820
  };
7807
- document.addEventListener('keydown', handleKeyDown);
7808
- return () => document.removeEventListener('keydown', handleKeyDown);
7821
+ window.addEventListener('keydown', handleKeyDown);
7822
+ return () => window.removeEventListener('keydown', handleKeyDown);
7809
7823
  }, [isOpen, escapeClose, handleClose]);
7810
7824
  // Prevent body scroll when sidebar is open. Ref-counted through the shared
7811
7825
  // helper so an overlapping Modal/Dialog/Loading doesn't unlock underneath.
@@ -8060,17 +8074,19 @@ const Toast = React.forwardRef(({ message, type = 'default', actionType, positio
8060
8074
  document.removeEventListener('click', handleDocumentClick);
8061
8075
  };
8062
8076
  }, [dismissible, isVisible, handleClose]);
8077
+ // On `window`, as in `Modal`, so a popup on the page has had the key
8078
+ // first, and an Escape it closed on doesn't dismiss the toast as well.
8063
8079
  React.useEffect(() => {
8064
- if (!cancelable)
8080
+ if (!cancelable || !isVisible)
8065
8081
  return undefined;
8066
8082
  const handleKeyDown = (e) => {
8067
- if (e.key === 'Escape') {
8083
+ if (e.key === 'Escape' && !e.defaultPrevented) {
8068
8084
  handleClose();
8069
8085
  }
8070
8086
  };
8071
- document.addEventListener('keydown', handleKeyDown);
8072
- return () => document.removeEventListener('keydown', handleKeyDown);
8073
- }, [cancelable, handleClose]);
8087
+ window.addEventListener('keydown', handleKeyDown);
8088
+ return () => window.removeEventListener('keydown', handleKeyDown);
8089
+ }, [cancelable, isVisible, handleClose]);
8074
8090
  const containerClasses = usePrefixedClassNames('toast-container', {
8075
8091
  [`is-${position}`]: true,
8076
8092
  });
@@ -10694,7 +10710,8 @@ const FieldLabelForContext = React.createContext({});
10694
10710
  * renders with, if it has one. An unlabeled Field passes both through
10695
10711
  * together, so a control in the inner Field of a horizontal layout can tell
10696
10712
  * the outer label names it, and point at that label by its id, as a range
10697
- * Slider's thumbs (#981) and Autocomplete's suggestion list (#998) do. The
10713
+ * Slider's thumbs (#981) and Autocomplete's and Taginput's suggestion lists
10714
+ * (#998, #1082) do. The
10698
10715
  * `htmlFor` is only ever compared with a control's own id, never adopted, so
10699
10716
  * it hands out no id for a control. It keeps the generated id after the
10700
10717
  * label drops a `for` nothing took (#1004), which no control's id matches
@@ -10949,9 +10966,9 @@ Control.displayName = 'Control';
10949
10966
  * `id`, or give the horizontal `Field` a `label` prop, which renders this
10950
10967
  * column and its `<label>` for you. A `<label>` you put here names the
10951
10968
  * control through its `htmlFor` alone: a range `Slider`'s thumbs and an
10952
- * `Autocomplete`'s suggestion list point `aria-labelledby` at a `Field`'s
10953
- * label only when its `label` prop renders it and it names the control.
10954
- * Where it would not name the control on its own, as in an inner `Field`,
10969
+ * `Autocomplete`'s or `Taginput`'s suggestion list point `aria-labelledby` at
10970
+ * a `Field`'s label only when its `label` prop renders it and it names the
10971
+ * control. Where it would not name the control on its own, as in an inner `Field`,
10955
10972
  * pass `labelProps={{ htmlFor, id }}` with a matching `id` on the control.
10956
10973
  *
10957
10974
  * @function
@@ -12654,6 +12671,11 @@ const nothingToAnnounce = [];
12654
12671
  * />
12655
12672
  */
12656
12673
  const Autocomplete = React.forwardRef(({ data = [], value: controlledValue, placeholder, field = 'label', clearable = false, openOnFocus = false, keepFirst = false, keepOpen = false, selectOnClickOutside = false, maxHeight = 200, loading = false, disabled = false, checkInfiniteScroll = false, infiniteScrollDistance = 50, color, size, onInput, onSelect, onActiveChange, onInfiniteScroll, itemTemplate, header, footer, empty, name, form, required, id,
12674
+ // Deprecated no-ops, taken here so they stay off the wrapper.
12675
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op
12676
+ selected,
12677
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op
12678
+ dropdown,
12657
12679
  // Field props
12658
12680
  label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, className, ...props }, ref) => {
12659
12681
  const insideField = useInsideField();
@@ -12806,7 +12828,10 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
12806
12828
  }
12807
12829
  break;
12808
12830
  case 'Escape':
12809
- e.preventDefault();
12831
+ // Only closing the dropdown claims the key. With it closed, the
12832
+ // key goes on to a Modal around the field.
12833
+ if (menuOpen)
12834
+ e.preventDefault();
12810
12835
  setIsActive(false);
12811
12836
  setHighlightedIndex(-1);
12812
12837
  break;
@@ -12817,7 +12842,14 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
12817
12842
  setIsActive(false);
12818
12843
  break;
12819
12844
  }
12820
- }, [disabled, isActive, highlightedIndex, filteredData, handleSelect]);
12845
+ }, [
12846
+ disabled,
12847
+ isActive,
12848
+ menuOpen,
12849
+ highlightedIndex,
12850
+ filteredData,
12851
+ handleSelect,
12852
+ ]);
12821
12853
  // Handle dropdown scroll for infinite scroll
12822
12854
  const handleDropdownScroll = React.useCallback(() => {
12823
12855
  if (!checkInfiniteScroll || !dropdownRef.current)
@@ -12960,7 +12992,7 @@ Autocomplete.displayName = 'Autocomplete';
12960
12992
  */
12961
12993
  const Taginput = React.forwardRef(({
12962
12994
  // Field props
12963
- label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, value: controlledValue, defaultValue = [], data = [], placeholder, field = 'label', allowNew = true, allowDuplicates = false, openOnFocus = false, removeOnKeys = true, confirmKeys = ['Enter', ','], closable = true, attached = false, maxTags, maxlength, disabled = false, readonly = false, rounded = false, ellipsis = false, hasCounter = true, onPasteSeparators = [','], beforeAdding, createTag, keepFirst = false, keepOpen = true, loading = false, ariaCloseLabel, icon, iconLibrary: iconLibraryProp, iconVariant, iconFeatures, color, tagColor, size, onChange, onAdd, onRemove, onTyping, tagTemplate, name, form, id, className, ...props }, ref) => {
12995
+ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, value: controlledValue, defaultValue = [], data: dataProp, placeholder, field = 'label', allowNew = true, allowDuplicates = false, openOnFocus = false, removeOnKeys = true, confirmKeys = ['Enter', ','], closable = true, attached = false, maxTags, maxlength, disabled = false, readonly = false, rounded = false, ellipsis = false, hasCounter = true, onPasteSeparators = [','], beforeAdding, createTag, keepFirst = false, keepOpen = true, loading = false, ariaCloseLabel, icon, iconLibrary: iconLibraryProp, iconVariant, iconFeatures, color, tagColor, size, onChange, onAdd, onRemove, onTyping, tagTemplate, name, form, id, className, ...props }, ref) => {
12964
12996
  const insideField = useInsideField();
12965
12997
  const insideControl = useInsideControl();
12966
12998
  const ownField = rendersOwnField('Taginput', {
@@ -12983,17 +13015,26 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
12983
13015
  const [inputValue, setInputValue] = React.useState('');
12984
13016
  const [isActive, setIsActive] = React.useState(false);
12985
13017
  const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
13018
+ const listboxId = `${React.useId()}-listbox`;
13019
+ // With `data` the input offers suggestions, so it's a combobox, even
13020
+ // while none match. Without it there's never a list, so it stays a plain
13021
+ // text field.
13022
+ const hasSuggestions = dataProp !== undefined;
13023
+ const data = dataProp ?? [];
12986
13024
  // Use controlled or internal tags
12987
13025
  const tags = controlledValue !== undefined ? controlledValue : internalTags;
12988
13026
  const isMaxReached = maxTags !== undefined && tags.length >= maxTags;
12989
13027
  // At the tag limit the text input is not rendered, so there is nothing to
12990
- // wire a label to, its own or a surrounding Field's.
12991
- const { controlId, fieldLabelProps, labelled } = useAutoLabelId({
13028
+ // wire a label to, its own or a surrounding Field's. The suggestion list
13029
+ // points `aria-labelledby` at the label that names the input, so with
13030
+ // suggestions it needs that label's id.
13031
+ const { controlId, fieldLabelProps, labelled, labelId: listLabelId, } = useAutoLabelId({
12992
13032
  label,
12993
13033
  id,
12994
13034
  labelProps,
12995
13035
  rendersLabel: ownField && !isMaxReached,
12996
13036
  hasInput: !isMaxReached,
13037
+ needsLabelId: hasSuggestions,
12997
13038
  });
12998
13039
  // Get display value from tag
12999
13040
  const getDisplayValue = (tag) => {
@@ -13013,6 +13054,7 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
13013
13054
  const hasInput = inputValue || (openOnFocus && isActive);
13014
13055
  return matchesInput && notAlreadyAdded && hasInput;
13015
13056
  });
13057
+ const listOpen = isActive && filteredData.length > 0;
13016
13058
  // keepFirst: auto-highlight first item when dropdown opens
13017
13059
  React.useEffect(() => {
13018
13060
  if (keepFirst && isActive && filteredData.length > 0) {
@@ -13181,6 +13223,10 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
13181
13223
  }
13182
13224
  break;
13183
13225
  case 'Escape':
13226
+ // Closing the suggestions claims the key, so a Modal around the
13227
+ // field stays open. With none showing, the key goes on to it.
13228
+ if (isActive && filteredData.length > 0)
13229
+ e.preventDefault();
13184
13230
  setIsActive(false);
13185
13231
  setHighlightedIndex(-1);
13186
13232
  break;
@@ -13253,15 +13299,35 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
13253
13299
  [`is-${messageColor}`]: !!messageColor,
13254
13300
  });
13255
13301
  const messageEl = message ? jsxRuntime.jsx("p", { className: helpClass, children: message }) : null;
13302
+ // The combobox controls its listbox and points at the highlighted option,
13303
+ // the way Autocomplete's does. The listbox takes its name from the label
13304
+ // that names the combobox, the one this renders or a surrounding Field's,
13305
+ // and keeps a fallback name when no label names it or the one that does
13306
+ // has no id to point at. While no suggestion matches there's no listbox,
13307
+ // so the combobox is collapsed and points at nothing. It skips a
13308
+ // highlighted suggestion that's blank once trimmed, since that one can't
13309
+ // become a tag, and the option it points at is the one marked selected.
13310
+ const optionId = (index) => `${listboxId}-${index}`;
13311
+ const activeOptionId = listOpen && filteredData[highlightedIndex]?.trim()
13312
+ ? optionId(highlightedIndex)
13313
+ : undefined;
13314
+ const comboboxProps = {
13315
+ role: 'combobox',
13316
+ 'aria-expanded': listOpen,
13317
+ 'aria-controls': listOpen ? listboxId : undefined,
13318
+ 'aria-activedescendant': activeOptionId,
13319
+ 'aria-haspopup': 'listbox',
13320
+ 'aria-autocomplete': 'list',
13321
+ };
13256
13322
  const taginputElement = (jsxRuntime.jsxs("div", { ref: containerRef, className: combinedClasses, onClick: handleContainerClick, ...rest, children: [jsxRuntime.jsxs("div", { className: containerClasses, children: [icon && (jsxRuntime.jsx(Icon, { name: icon, library: resolvedLibrary, variant: iconVariant, features: iconFeatures, containerClassName: pcn('icon', 'is-left') })), jsxRuntime.jsxs("div", { className: tagsClasses, children: [tags.map((tag, index) => {
13257
13323
  const displayVal = getDisplayValue(tag);
13258
13324
  return (jsxRuntime.jsxs("span", { className: tagClasses, children: [tagTemplate ? (tagTemplate(tag)) : ellipsis ? (jsxRuntime.jsx("span", { title: displayVal, children: displayVal })) : (displayVal), closable && !disabled && !readonly && (jsxRuntime.jsx("button", { type: "button", className: pcn('delete', 'is-small'), onClick: e => {
13259
13325
  e.stopPropagation();
13260
13326
  removeTag(index);
13261
13327
  }, "aria-label": ariaCloseLabel || `Remove ${displayVal}` }))] }, index));
13262
- }), !isMaxReached && (jsxRuntime.jsx("input", { ref: combinedRef, type: "text", className: inputClasses, id: controlId, value: inputValue, placeholder: tags.length === 0 ? placeholder : undefined, disabled: disabled, readOnly: readonly, maxLength: maxlength, onChange: handleInputChange, onFocus: handleFocus, onKeyDown: handleKeyDown, onPaste: handlePaste, "aria-label": labelled ? undefined : 'Add tag' }))] }), loading && (jsxRuntime.jsx("span", { className: iconRightClass, children: jsxRuntime.jsx("span", { className: loaderClass }) }))] }), isActive && filteredData.length > 0 && (jsxRuntime.jsx("div", { className: dropdownMenuClasses, children: jsxRuntime.jsx("div", { ref: dropdownRef, className: dropdownContentClasses, role: "listbox", children: filteredData.map((item, index) => (jsxRuntime.jsx("a", { className: pcn('dropdown-item', {
13328
+ }), !isMaxReached && (jsxRuntime.jsx("input", { ref: combinedRef, type: "text", className: inputClasses, id: controlId, value: inputValue, placeholder: tags.length === 0 ? placeholder : undefined, disabled: disabled, readOnly: readonly, maxLength: maxlength, onChange: handleInputChange, onFocus: handleFocus, onKeyDown: handleKeyDown, onPaste: handlePaste, ...(hasSuggestions && comboboxProps), "aria-label": labelled ? undefined : 'Add tag' }))] }), loading && (jsxRuntime.jsx("span", { className: iconRightClass, children: jsxRuntime.jsx("span", { className: loaderClass }) }))] }), listOpen && (jsxRuntime.jsx("div", { className: dropdownMenuClasses, children: jsxRuntime.jsx("div", { ref: dropdownRef, id: listboxId, className: dropdownContentClasses, role: "listbox", "aria-labelledby": listLabelId, "aria-label": listLabelId ? undefined : 'Suggestions', children: filteredData.map((item, index) => (jsxRuntime.jsx("a", { id: optionId(index), className: pcn('dropdown-item', {
13263
13329
  'is-active': index === highlightedIndex,
13264
- }), onClick: () => addTag(item), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: item }, index))) }) })), showCounter && jsxRuntime.jsx("small", { className: counterClasses, children: counterText }), name &&
13330
+ }), onClick: () => addTag(item), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": optionId(index) === activeOptionId, children: item }, index))) }) })), showCounter && jsxRuntime.jsx("small", { className: counterClasses, children: counterText }), name &&
13265
13331
  tags.map((tag, i) => (jsxRuntime.jsx("input", { type: "hidden", name: name, value: getDisplayValue(tag), form: form }, `tag-input-${i}`)))] }));
13266
13332
  if (ownField) {
13267
13333
  return (jsxRuntime.jsxs(Field, { label: label, labelSize: labelSize, labelProps: fieldLabelProps, horizontal: horizontal, className: fieldClassName, children: [taginputElement, messageEl] }));
@@ -15022,13 +15088,20 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
15022
15088
  return () => document.removeEventListener('pointerdown', handler);
15023
15089
  }, [isOpen, closeOnClickOutside, anchorRef, onClose]);
15024
15090
  // Escape closes it, and so does Alt+ArrowUp, the combobox's key for it,
15025
- // which the calendar and the time wheels inside leave to it.
15091
+ // which the calendar and the time wheels inside leave to it. Escape closes
15092
+ // it from anywhere, but the key is only the picker's when it was pressed in
15093
+ // the panel or the field: then it's marked used, so a Modal or Sidebar
15094
+ // around the picker stays open. From anywhere else, such as a dialog opened
15095
+ // over the picker, the key goes on to whatever has focus.
15026
15096
  React.useEffect(() => {
15027
15097
  if (!isOpen || !closeOnEscape || !isBrowser)
15028
15098
  return undefined;
15029
15099
  const handler = (e) => {
15030
15100
  if (e.key === 'Escape') {
15031
- e.stopPropagation();
15101
+ if (isEventInside(e, panelRef.current) ||
15102
+ isEventInside(e, anchorRef.current)) {
15103
+ e.preventDefault();
15104
+ }
15032
15105
  onClose();
15033
15106
  }
15034
15107
  else if (e.altKey && e.key === 'ArrowUp') {
@@ -15039,7 +15112,7 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
15039
15112
  };
15040
15113
  document.addEventListener('keydown', handler);
15041
15114
  return () => document.removeEventListener('keydown', handler);
15042
- }, [isOpen, closeOnEscape, onClose]);
15115
+ }, [isOpen, closeOnEscape, anchorRef, onClose]);
15043
15116
  useFocusTrap(panelRef, {
15044
15117
  active: isOpen && trapFocus,
15045
15118
  initialFocusRef,