@mirohq/design-system-combobox 1.6.1-reactdismissablelayer.1 → 1.7.0-filter-chip.1

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/module.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import React, { createContext, useContext, useRef, useState, useMemo, useCallback, useEffect } from 'react';
3
- import { Combobox as Combobox$1, useComboboxContext as useComboboxContext$1, ComboboxList, ComboboxItem, ComboboxItemCheck, Group as Group$1, GroupLabel as GroupLabel$1, CompositeItem as CompositeItem$1, useCompositeContext, ComboboxProvider as ComboboxProvider$1 } from '@ariakit/react';
3
+ import { Combobox as Combobox$1, ComboboxList, useComboboxContext as useComboboxContext$1, ComboboxItem, ComboboxItemCheck, Group as Group$1, GroupLabel as GroupLabel$1, CompositeItem as CompositeItem$1, useCompositeContext, ComboboxProvider as ComboboxProvider$1 } from '@ariakit/react';
4
4
  import { useFormFieldContext } from '@mirohq/design-system-base-form';
5
5
  import { stringAttrValue, mergeRefs, booleanify } from '@mirohq/design-system-utils';
6
6
  import * as RadixPopover from '@radix-ui/react-popover';
@@ -50,7 +50,7 @@ const ComboboxProvider = ({
50
50
  prop: openProp,
51
51
  defaultProp: defaultOpen,
52
52
  onChange: (state) => {
53
- if (state === true) {
53
+ if (state) {
54
54
  externalOpenedRef.current = true;
55
55
  onOpen == null ? void 0 : onOpen();
56
56
  } else {
@@ -59,25 +59,15 @@ const ComboboxProvider = ({
59
59
  }
60
60
  }
61
61
  });
62
- const [value, setValue] = useControllableState(
63
- {
64
- prop: valueProp,
65
- defaultProp: defaultValueProp,
66
- // Only the initial state can be undefined — nothing selects "no value" —
67
- // so the public handler never has to widen its parameter.
68
- onChange: (state) => {
69
- if (state !== void 0) {
70
- onValueChange == null ? void 0 : onValueChange(state);
71
- }
72
- }
73
- }
74
- );
62
+ const [value, setValue] = useControllableState({
63
+ prop: valueProp,
64
+ defaultProp: defaultValueProp,
65
+ onChange: onValueChange
66
+ });
75
67
  const [searchValue = "", setSearchValue] = useControllableState({
76
68
  prop: searchValueProp,
77
69
  defaultProp: "",
78
- // Clearing through the setter reads as undefined, which the search is
79
- // free to treat as empty — so the public handler stays on plain strings.
80
- onChange: (state) => onSearchValueChange == null ? void 0 : onSearchValueChange(state != null ? state : "")
70
+ onChange: onSearchValueChange
81
71
  });
82
72
  const [size, setSize] = useState();
83
73
  const [placeholder, setPlaceholder] = useState();
@@ -380,6 +370,12 @@ const StyledContent = styled(RadixPopover.Content, {
380
370
  boxSizing: "border-box"
381
371
  });
382
372
 
373
+ const List = ({ children }) => (
374
+ // Role must be set explicitly; Radix Content can overwrite Ariakit's default.
375
+ /* @__PURE__ */ jsx(ComboboxList, { role: "listbox", children: /* @__PURE__ */ jsx(StyledItemsContainer, { children }) })
376
+ );
377
+ List.displayName = "Combobox.List";
378
+
383
379
  const useDocumentFragment = () => {
384
380
  const [fragment, setFragment] = React.useState();
385
381
  useLayoutEffect(() => {
@@ -402,6 +398,11 @@ const isInsideRef = (element, ref) => {
402
398
  var _a, _b;
403
399
  return (_b = element != null && ((_a = ref.current) == null ? void 0 : _a.contains(element))) != null ? _b : false;
404
400
  };
401
+ const isComboboxList = (child) => {
402
+ var _a;
403
+ return React.isValidElement(child) && ((_a = child.type) == null ? void 0 : _a.displayName) === "Combobox.List";
404
+ };
405
+ const hasComboboxList = (children) => React.Children.toArray(children).some(isComboboxList);
405
406
  const Content = React.forwardRef(
406
407
  ({
407
408
  side = "bottom",
@@ -411,7 +412,7 @@ const Content = React.forwardRef(
411
412
  collisionPadding = 0,
412
413
  avoidCollisions = true,
413
414
  sticky = "partial",
414
- hideWhenDetached = process.env.NODE_ENV !== "test",
415
+ hideWhenDetached = true,
415
416
  overflow = "visible",
416
417
  maxHeight,
417
418
  children,
@@ -424,7 +425,22 @@ const Content = React.forwardRef(
424
425
  if (!openState) {
425
426
  return getInvisibleContent(children);
426
427
  }
427
- const content = /* @__PURE__ */ jsx(StyledItemsContainer, { children });
428
+ const listContent = hasComboboxList(children) ? children : /* @__PURE__ */ jsx(List, { children });
429
+ let content = listContent;
430
+ if (overflow === "auto") {
431
+ content = /* @__PURE__ */ jsxs(ScrollArea, { type: "always", dir: direction, children: [
432
+ /* @__PURE__ */ jsx(
433
+ ScrollArea.Viewport,
434
+ {
435
+ css: {
436
+ maxHeight: maxHeight !== void 0 ? "min(".concat(RADIX_CONTENT_AVAILABLE_HEIGHT, ", ").concat(typeof maxHeight === "number" ? "".concat(maxHeight, "px") : maxHeight, ")") : RADIX_CONTENT_AVAILABLE_HEIGHT
437
+ },
438
+ children: listContent
439
+ }
440
+ ),
441
+ /* @__PURE__ */ jsx(ScrollArea.Scrollbar, { orientation: "vertical", children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {}) })
442
+ ] });
443
+ }
428
444
  return /* @__PURE__ */ jsx(
429
445
  StyledContent,
430
446
  {
@@ -439,6 +455,7 @@ const Content = React.forwardRef(
439
455
  sticky,
440
456
  hideWhenDetached,
441
457
  onOpenAutoFocus: (event) => {
458
+ var _a;
442
459
  if (onOpenAutoFocus != null) {
443
460
  onOpenAutoFocus(event);
444
461
  return;
@@ -446,6 +463,13 @@ const Content = React.forwardRef(
446
463
  event == null ? void 0 : event.preventDefault();
447
464
  if (externalOpenedRef.current !== true) return;
448
465
  const baseElement = ariakitStore == null ? void 0 : ariakitStore.getState().baseElement;
466
+ if (!(baseElement instanceof HTMLInputElement)) {
467
+ const searchInput = (_a = contentRef.current) == null ? void 0 : _a.querySelector("input");
468
+ if (searchInput != null) {
469
+ searchInput.focus();
470
+ return;
471
+ }
472
+ }
449
473
  baseElement == null ? void 0 : baseElement.focus();
450
474
  },
451
475
  ref: mergeRefs([forwardRef, contentRef]),
@@ -457,18 +481,7 @@ const Content = React.forwardRef(
457
481
  event.preventDefault();
458
482
  }
459
483
  },
460
- children: /* @__PURE__ */ jsx(ComboboxList, { role: "listbox", children: overflow === "auto" ? /* @__PURE__ */ jsxs(ScrollArea, { type: "always", dir: direction, children: [
461
- /* @__PURE__ */ jsx(
462
- ScrollArea.Viewport,
463
- {
464
- css: {
465
- maxHeight: maxHeight !== void 0 ? "min(".concat(RADIX_CONTENT_AVAILABLE_HEIGHT, ", ").concat(typeof maxHeight === "number" ? "".concat(maxHeight, "px") : maxHeight, ")") : RADIX_CONTENT_AVAILABLE_HEIGHT
466
- },
467
- children: content
468
- }
469
- ),
470
- /* @__PURE__ */ jsx(ScrollArea.Scrollbar, { orientation: "vertical", children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {}) })
471
- ] }) : content })
484
+ children: content
472
485
  }
473
486
  );
474
487
  }
@@ -688,39 +701,71 @@ const StyledInputSearch = styled(InputSearch, {
688
701
  "&&": {
689
702
  border: "1px solid $border-neutrals",
690
703
  backgroundColor: "$background-control"
704
+ },
705
+ variants: {
706
+ // Lay selected chips (passed as children, typically `<Combobox.Value />`)
707
+ // out inside the field alongside the text input, matching the multiselect
708
+ // trigger. The leading magnifier is pulled ahead of the chips so the field
709
+ // still reads as a search.
710
+ inlineChips: {
711
+ true: {
712
+ "&&": {
713
+ flexWrap: "wrap",
714
+ height: "auto",
715
+ minHeight: "$10",
716
+ paddingBlock: "$50",
717
+ gap: "$50"
718
+ },
719
+ // The magnifier icon slot (the only direct child that wraps a bare svg)
720
+ // leads the field, before the chips.
721
+ "& > div:has(> svg)": {
722
+ order: -1
723
+ },
724
+ "& input": {
725
+ width: "auto",
726
+ flexGrow: 1,
727
+ flexBasis: "$8",
728
+ minWidth: "$8"
729
+ }
730
+ }
731
+ }
691
732
  }
692
733
  });
693
- const SearchInput = React.forwardRef((props, ref) => {
694
- const { setSearchValue, contentRef } = useComboboxContext();
695
- const handleSearchChange = useCallback(
696
- (event) => {
734
+ const SearchInput = React.forwardRef(
735
+ ({ children, onChange, onKeyDown, inlineChips = false, ...rest }, ref) => {
736
+ const { setSearchValue, contentRef } = useComboboxContext();
737
+ const handleSearchChange = useCallback(
738
+ (event) => {
739
+ setSearchValue(event.target.value);
740
+ onChange == null ? void 0 : onChange(event);
741
+ },
742
+ [onChange, setSearchValue]
743
+ );
744
+ const handleKeyDown = (event) => {
697
745
  var _a;
698
- setSearchValue(event.target.value);
699
- (_a = props.onChange) == null ? void 0 : _a.call(props, event);
700
- },
701
- [props, setSearchValue]
702
- );
703
- const handleKeyDown = (event) => {
704
- var _a, _b;
705
- if (event.key === "ArrowDown") {
706
- event.preventDefault();
707
- const firstItem = (_a = contentRef.current) == null ? void 0 : _a.querySelector(
708
- '[role="option"]:not([aria-disabled="true"])'
709
- );
710
- firstItem == null ? void 0 : firstItem.focus();
711
- }
712
- (_b = props.onKeyDown) == null ? void 0 : _b.call(props, event);
713
- };
714
- return /* @__PURE__ */ jsx(
715
- StyledInputSearch,
716
- {
717
- ...props,
718
- ref,
719
- onKeyDown: handleKeyDown,
720
- onChange: handleSearchChange
721
- }
722
- );
723
- });
746
+ if (event.key === "ArrowDown") {
747
+ event.preventDefault();
748
+ const firstItem = (_a = contentRef.current) == null ? void 0 : _a.querySelector(
749
+ '[role="option"]:not([aria-disabled="true"])'
750
+ );
751
+ firstItem == null ? void 0 : firstItem.focus();
752
+ }
753
+ onKeyDown == null ? void 0 : onKeyDown(event);
754
+ };
755
+ return /* @__PURE__ */ jsx(
756
+ StyledInputSearch,
757
+ {
758
+ ...rest,
759
+ ref,
760
+ inlineChips,
761
+ onKeyDown: handleKeyDown,
762
+ onChange: handleSearchChange,
763
+ children
764
+ }
765
+ );
766
+ }
767
+ );
768
+ SearchInput.displayName = "Combobox.SearchInput";
724
769
 
725
770
  const StyledCompositeItem = styled(CompositeItem$1, {
726
771
  ...itemStyles,
@@ -730,7 +775,7 @@ const StyledCompositeItem = styled(CompositeItem$1, {
730
775
 
731
776
  const CompositeItem = ({
732
777
  asChild = true,
733
- role = "menuitem",
778
+ role,
734
779
  textValue,
735
780
  disabled = false,
736
781
  tabbable,
@@ -949,6 +994,7 @@ Combobox.Portal = Portal;
949
994
  Combobox.Trigger = Trigger;
950
995
  Combobox.Input = Input;
951
996
  Combobox.Content = Content;
997
+ Combobox.List = List;
952
998
  Combobox.Item = Item;
953
999
  Combobox.CompositeItem = CompositeItem;
954
1000
  Combobox.Group = Group;