@mirohq/design-system-combobox 0.1.0-combobox.9 → 0.1.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/main.js CHANGED
@@ -6,8 +6,8 @@ var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
7
  var react = require('@ariakit/react');
8
8
  var designSystemBaseForm = require('@mirohq/design-system-base-form');
9
- var RadixPopover = require('@radix-ui/react-popover');
10
9
  var designSystemUtils = require('@mirohq/design-system-utils');
10
+ var RadixPopover = require('@radix-ui/react-popover');
11
11
  var designSystemStitches = require('@mirohq/design-system-stitches');
12
12
  var designSystemInput = require('@mirohq/design-system-input');
13
13
  var reactUseControllableState = require('@radix-ui/react-use-controllable-state');
@@ -44,14 +44,10 @@ function _interopNamespace(e) {
44
44
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
45
45
  var RadixPopover__namespace = /*#__PURE__*/_interopNamespace(RadixPopover);
46
46
 
47
- const StyledAnchor = designSystemStitches.styled(RadixPopover.Anchor, {
48
- position: "relative",
49
- width: "100%"
50
- });
51
47
  const StyledInput = designSystemStitches.styled(designSystemInput.Input, {
52
48
  flexWrap: "wrap",
53
49
  flexGrow: 1,
54
- gap: "0 $50",
50
+ gap: "$50",
55
51
  overflowY: "scroll",
56
52
  "&[data-valid], &[data-invalid]": {
57
53
  // we don't need a bigger padding here as Input component will render its own icon
@@ -120,6 +116,8 @@ const ComboboxProvider = ({
120
116
  });
121
117
  const [filteredItems, setFilteredItems] = React.useState(/* @__PURE__ */ new Set());
122
118
  const [searchValue, setSearchValue] = React.useState("");
119
+ const [size, setSize] = React.useState();
120
+ const [placeholder, setPlaceholder] = React.useState();
123
121
  const [itemValueTextMap, setItemValueTextMap] = React.useState(/* @__PURE__ */ new Map());
124
122
  const { valid: formFieldValid } = designSystemBaseForm.useFormFieldContext();
125
123
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -144,7 +142,11 @@ const ComboboxProvider = ({
144
142
  filteredItems,
145
143
  setFilteredItems,
146
144
  itemValueTextMap,
147
- setItemValueTextMap
145
+ setItemValueTextMap,
146
+ placeholder,
147
+ setPlaceholder,
148
+ size,
149
+ setSize
148
150
  },
149
151
  children
150
152
  }
@@ -228,7 +230,6 @@ const Trigger = React__default["default"].forwardRef(
228
230
  closeActionLabel,
229
231
  clearActionLabel,
230
232
  onChange,
231
- css,
232
233
  ...restProps
233
234
  }, forwardRef) => {
234
235
  const {
@@ -242,16 +243,21 @@ const Trigger = React__default["default"].forwardRef(
242
243
  onSearchValueChange,
243
244
  searchValue,
244
245
  setSearchValue,
245
- setOpenState
246
+ setOpenState,
247
+ setSize,
248
+ setPlaceholder
246
249
  } = useComboboxContext();
247
250
  const {
248
251
  formElementId,
249
252
  ariaInvalid: formFieldAriaInvalid,
250
- valid: formFieldValid,
251
- label,
252
- isFloatingLabel,
253
- focused
253
+ valid: formFieldValid
254
254
  } = designSystemBaseForm.useFormFieldContext();
255
+ React.useEffect(() => {
256
+ setSize(size);
257
+ }, [size, setSize]);
258
+ React.useEffect(() => {
259
+ setPlaceholder(placeholder);
260
+ }, [setPlaceholder, placeholder]);
255
261
  const valid = formFieldValid != null ? formFieldValid : comboboxValid;
256
262
  const inputProps = {
257
263
  ...restProps,
@@ -266,8 +272,6 @@ const Trigger = React__default["default"].forwardRef(
266
272
  id: id != null ? id : formElementId,
267
273
  placeholder: value.length === 0 ? placeholder : void 0
268
274
  };
269
- const shouldUseFloatingLabel = label !== null && isFloatingLabel;
270
- const isFloating = placeholder !== void 0 || value.length !== 0 || focused || searchValue !== "";
271
275
  const scrollIntoView = (event) => {
272
276
  var _a;
273
277
  const trigger = triggerRef == null ? void 0 : triggerRef.current;
@@ -287,47 +291,43 @@ const Trigger = React__default["default"].forwardRef(
287
291
  onSearchValueChange == null ? void 0 : onSearchValueChange(e.target.value);
288
292
  onChange == null ? void 0 : onChange(e);
289
293
  };
290
- return /* @__PURE__ */ jsxRuntime.jsxs(
291
- StyledAnchor,
294
+ return /* @__PURE__ */ jsxRuntime.jsx(
295
+ RadixPopover.Anchor,
292
296
  {
293
297
  ref: designSystemUtils.mergeRefs([triggerRef, forwardRef]),
294
- css,
295
298
  onClick: () => {
296
299
  if (!designSystemUtils.booleanify(disabled) && !designSystemUtils.booleanify(ariaDisabled) && !designSystemUtils.booleanify(readOnly)) {
297
300
  setOpenState(true);
298
301
  }
299
302
  },
300
- children: [
301
- shouldUseFloatingLabel && /* @__PURE__ */ jsxRuntime.jsx(designSystemBaseForm.FloatingLabel, { floating: isFloating, size, children: label }),
302
- /* @__PURE__ */ jsxRuntime.jsx(
303
- react.Combobox,
304
- {
305
- render: /* @__PURE__ */ jsxRuntime.jsxs(
306
- StyledInput,
307
- {
308
- ...inputProps,
309
- value: searchValue,
310
- size,
311
- ref: inputRef,
312
- onChange: onInputChange,
313
- onFocus: scrollIntoView,
314
- children: [
315
- children,
316
- /* @__PURE__ */ jsxRuntime.jsx(
317
- TriggerActionButton,
318
- {
319
- openActionLabel,
320
- closeActionLabel,
321
- clearActionLabel,
322
- size
323
- }
324
- )
325
- ]
326
- }
327
- )
328
- }
329
- )
330
- ]
303
+ children: /* @__PURE__ */ jsxRuntime.jsx(
304
+ react.Combobox,
305
+ {
306
+ render: /* @__PURE__ */ jsxRuntime.jsxs(
307
+ StyledInput,
308
+ {
309
+ ...inputProps,
310
+ value: searchValue,
311
+ size,
312
+ ref: inputRef,
313
+ onChange: onInputChange,
314
+ onFocus: scrollIntoView,
315
+ children: [
316
+ children,
317
+ /* @__PURE__ */ jsxRuntime.jsx(
318
+ TriggerActionButton,
319
+ {
320
+ openActionLabel,
321
+ closeActionLabel,
322
+ clearActionLabel,
323
+ size
324
+ }
325
+ )
326
+ ]
327
+ }
328
+ )
329
+ }
330
+ )
331
331
  }
332
332
  );
333
333
  }
@@ -398,7 +398,8 @@ const Item = React__default["default"].forwardRef(
398
398
  filteredItems,
399
399
  setItemValueTextMap,
400
400
  triggerRef,
401
- inputRef
401
+ inputRef,
402
+ value: comboboxValue = []
402
403
  } = useComboboxContext();
403
404
  designSystemUseLayoutEffect.useLayoutEffect(() => {
404
405
  const textToSet = textValue !== void 0 ? textValue : typeof children === "string" ? children : "";
@@ -424,6 +425,7 @@ const Item = React__default["default"].forwardRef(
424
425
  restProps.onClick(event);
425
426
  }
426
427
  };
428
+ const isSelected = comboboxValue.includes(value);
427
429
  return /* @__PURE__ */ jsxRuntime.jsxs(
428
430
  StyledItem,
429
431
  {
@@ -435,10 +437,12 @@ const Item = React__default["default"].forwardRef(
435
437
  ref: forwardRef,
436
438
  value,
437
439
  onClick: scrollIntoView,
440
+ "aria-selected": isSelected,
438
441
  children: [
439
442
  /* @__PURE__ */ jsxRuntime.jsx(
440
443
  react.ComboboxItemCheck,
441
444
  {
445
+ checked: isSelected,
442
446
  render: ({ style, ...props }) => (
443
447
  // AriakitComboboxItemCheck adds its owm inline styles which we want to omit here
444
448
  /* @__PURE__ */ jsxRuntime.jsx(StyledItemCheck, { ...props })
@@ -504,9 +508,16 @@ const isInsideRef = (element, ref) => {
504
508
  };
505
509
  const Content = React__default["default"].forwardRef(
506
510
  ({
511
+ side = "bottom",
507
512
  sideOffset = CONTENT_OFFSET,
513
+ align = "center",
514
+ alignOffset = 0,
515
+ collisionPadding = 0,
516
+ avoidCollisions = true,
517
+ sticky = "partial",
518
+ hideWhenDetached = true,
519
+ overflow = "visible",
508
520
  maxHeight,
509
- overflow,
510
521
  children,
511
522
  ...restProps
512
523
  }, forwardRef) => {
@@ -545,7 +556,14 @@ const Content = React__default["default"].forwardRef(
545
556
  asChild: true,
546
557
  ...restProps,
547
558
  dir: direction,
559
+ side,
548
560
  sideOffset,
561
+ align,
562
+ alignOffset,
563
+ avoidCollisions,
564
+ collisionPadding,
565
+ sticky,
566
+ hideWhenDetached,
549
567
  ref: designSystemUtils.mergeRefs([forwardRef, contentRef]),
550
568
  onOpenAutoFocus: (event) => event.preventDefault(),
551
569
  onInteractOutside: (event) => {
@@ -645,10 +663,6 @@ const Chip = React__default["default"].forwardRef(
645
663
  );
646
664
  Chip.LeftSlot = LeftSlot;
647
665
 
648
- const StyledValue = designSystemStitches.styled(Chip, {
649
- marginTop: "$50"
650
- });
651
-
652
666
  const Value = ({ unselectAriaLabel }) => {
653
667
  const {
654
668
  value = [],
@@ -671,9 +685,12 @@ const Value = ({ unselectAriaLabel }) => {
671
685
  return null;
672
686
  }
673
687
  return /* @__PURE__ */ jsxRuntime.jsx(
674
- StyledValue,
688
+ Chip,
675
689
  {
676
- onRemove: () => onItemRemove(itemValue),
690
+ onRemove: (e) => {
691
+ onItemRemove(itemValue);
692
+ e.stopPropagation();
693
+ },
677
694
  disabled: isDisabled,
678
695
  removeAriaLabel: "".concat(unselectAriaLabel, " ").concat(textValue),
679
696
  "data-testid": process.env.NODE_ENV === "test" ? "combobox-value-".concat(itemValue) : void 0,
@@ -702,53 +719,71 @@ const Separator = React__default["default"].forwardRef((props, forwardRef) => {
702
719
  return /* @__PURE__ */ jsxRuntime.jsx(StyledSeparator, { ...props, ref: forwardRef, "aria-hidden": true });
703
720
  });
704
721
 
705
- const Root = ({
706
- value: valueProp,
707
- children,
708
- ...restProps
709
- }) => {
710
- const {
711
- openState,
712
- setOpenState,
713
- defaultValue,
714
- value,
715
- setValue,
716
- required,
717
- readOnly,
718
- "aria-disabled": ariaDisabled,
719
- disabled
720
- } = useComboboxContext();
721
- const { setRequired, setDisabled, setAriaDisabled, setReadOnly } = designSystemBaseForm.useFormFieldContext();
722
- React.useEffect(() => {
723
- setRequired == null ? void 0 : setRequired(required);
724
- setDisabled == null ? void 0 : setDisabled(disabled);
725
- setAriaDisabled == null ? void 0 : setAriaDisabled(ariaDisabled);
726
- setReadOnly == null ? void 0 : setReadOnly(readOnly);
727
- }, [
728
- readOnly,
729
- disabled,
730
- ariaDisabled,
731
- required,
732
- setRequired,
733
- setDisabled,
734
- setAriaDisabled,
735
- setReadOnly
736
- ]);
737
- const onSetSelectedValue = (newValue) => {
738
- setValue(typeof newValue === "string" ? [newValue] : newValue);
739
- };
740
- const onOpenChange = (value2) => {
741
- if (!designSystemUtils.booleanify(readOnly)) {
742
- setOpenState(value2);
743
- }
744
- };
745
- return /* @__PURE__ */ jsxRuntime.jsx(
746
- RadixPopover__namespace.Root,
747
- {
748
- open: openState,
749
- onOpenChange,
750
- ...restProps,
751
- children: /* @__PURE__ */ jsxRuntime.jsx(
722
+ const StyledNativeSelect = designSystemStitches.styled(designSystemPrimitive.Primitive.select, {
723
+ // if we support autoComplete, we would have to use visually-hidden styles here
724
+ display: "none"
725
+ });
726
+ const StyledComboboxContent = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
727
+ position: "relative",
728
+ width: "100%"
729
+ });
730
+
731
+ const Root = React__default["default"].forwardRef(
732
+ ({ value: valueProp, onValueChange, name, children, ...restProps }, forwardRef) => {
733
+ var _a;
734
+ const {
735
+ openState,
736
+ setOpenState,
737
+ defaultValue,
738
+ value = [],
739
+ setValue,
740
+ required,
741
+ readOnly,
742
+ "aria-disabled": ariaDisabled,
743
+ disabled,
744
+ direction,
745
+ size,
746
+ placeholder,
747
+ triggerRef
748
+ } = useComboboxContext();
749
+ const {
750
+ setRequired,
751
+ setDisabled,
752
+ setAriaDisabled,
753
+ setReadOnly,
754
+ label,
755
+ isFloatingLabel,
756
+ focused,
757
+ formElementRef
758
+ } = designSystemBaseForm.useFormFieldContext();
759
+ React.useEffect(() => {
760
+ setRequired == null ? void 0 : setRequired(required);
761
+ setDisabled == null ? void 0 : setDisabled(disabled);
762
+ setAriaDisabled == null ? void 0 : setAriaDisabled(ariaDisabled);
763
+ setReadOnly == null ? void 0 : setReadOnly(readOnly);
764
+ }, [
765
+ readOnly,
766
+ disabled,
767
+ ariaDisabled,
768
+ required,
769
+ setRequired,
770
+ setDisabled,
771
+ setAriaDisabled,
772
+ setReadOnly
773
+ ]);
774
+ const shouldUseFloatingLabel = label !== null && isFloatingLabel;
775
+ const isFloating = placeholder !== void 0 || value.length !== 0 || focused;
776
+ const onSetSelectedValue = (newValue) => {
777
+ setValue(typeof newValue === "string" ? [newValue] : newValue);
778
+ };
779
+ const onOpenChange = (value2) => {
780
+ if (!designSystemUtils.booleanify(readOnly)) {
781
+ setOpenState(value2);
782
+ }
783
+ };
784
+ const isFormControl = Boolean((_a = triggerRef.current) == null ? void 0 : _a.closest("form"));
785
+ return /* @__PURE__ */ jsxRuntime.jsxs(RadixPopover__namespace.Root, { open: openState, onOpenChange, children: [
786
+ /* @__PURE__ */ jsxRuntime.jsx(
752
787
  react.ComboboxProvider,
753
788
  {
754
789
  open: openState,
@@ -756,51 +791,86 @@ const Root = ({
756
791
  defaultSelectedValue: defaultValue,
757
792
  selectedValue: value,
758
793
  setSelectedValue: onSetSelectedValue,
759
- children
794
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
795
+ StyledComboboxContent,
796
+ {
797
+ ref: forwardRef,
798
+ ...restProps,
799
+ dir: direction,
800
+ "data-form-element": "select",
801
+ children: [
802
+ shouldUseFloatingLabel && /* @__PURE__ */ jsxRuntime.jsx(designSystemBaseForm.FloatingLabel, { floating: isFloating, size, children: label }),
803
+ children
804
+ ]
805
+ }
806
+ )
807
+ }
808
+ ),
809
+ isFormControl && /* @__PURE__ */ jsxRuntime.jsx(
810
+ StyledNativeSelect,
811
+ {
812
+ multiple: true,
813
+ autoComplete: "off",
814
+ name,
815
+ tabIndex: -1,
816
+ "aria-hidden": "true",
817
+ ref: formElementRef,
818
+ required,
819
+ disabled,
820
+ "aria-disabled": ariaDisabled,
821
+ value,
822
+ onChange: () => {
823
+ },
824
+ children: value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "" }) : (
825
+ // since we don't support autoComplete we can render here only selected values
826
+ value.map((itemValue) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: itemValue, children: itemValue }, itemValue))
827
+ )
760
828
  }
761
829
  )
762
- }
763
- );
764
- };
765
- const Combobox = ({
766
- "aria-disabled": ariaDisabled,
767
- defaultOpen = false,
768
- open,
769
- valid,
770
- disabled,
771
- readOnly,
772
- required,
773
- value,
774
- defaultValue,
775
- onOpen,
776
- onClose,
777
- onSearchValueChange,
778
- onValueChange,
779
- direction = "ltr",
780
- autoFilter = true,
781
- noResultsText,
782
- ...restProps
783
- }) => /* @__PURE__ */ jsxRuntime.jsx(
784
- ComboboxProvider,
785
- {
786
- defaultValue,
787
- value,
788
- onValueChange,
789
- onSearchValueChange,
790
- defaultOpen,
830
+ ] });
831
+ }
832
+ );
833
+ const Combobox = React__default["default"].forwardRef(
834
+ ({
835
+ "aria-disabled": ariaDisabled,
836
+ defaultOpen = false,
791
837
  open,
792
- onOpen,
793
- onClose,
794
838
  valid,
795
- required,
796
839
  disabled,
797
840
  readOnly,
798
- "aria-disabled": ariaDisabled,
799
- direction,
800
- autoFilter,
841
+ required,
842
+ value,
843
+ defaultValue,
844
+ onOpen,
845
+ onClose,
846
+ onSearchValueChange,
847
+ onValueChange,
848
+ direction = "ltr",
849
+ autoFilter = true,
801
850
  noResultsText,
802
- children: /* @__PURE__ */ jsxRuntime.jsx(Root, { ...restProps, value })
803
- }
851
+ ...restProps
852
+ }, forwardRef) => /* @__PURE__ */ jsxRuntime.jsx(
853
+ ComboboxProvider,
854
+ {
855
+ defaultValue,
856
+ value,
857
+ onValueChange,
858
+ onSearchValueChange,
859
+ defaultOpen,
860
+ open,
861
+ onOpen,
862
+ onClose,
863
+ valid,
864
+ required,
865
+ disabled,
866
+ readOnly,
867
+ "aria-disabled": ariaDisabled,
868
+ direction,
869
+ autoFilter,
870
+ noResultsText,
871
+ children: /* @__PURE__ */ jsxRuntime.jsx(Root, { ...restProps, value, ref: forwardRef })
872
+ }
873
+ )
804
874
  );
805
875
  Combobox.Portal = Portal;
806
876
  Combobox.Trigger = Trigger;