@mirohq/design-system-combobox 0.1.0-combobox.9 → 0.1.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/main.js +212 -143
- package/dist/main.js.map +1 -1
- package/dist/module.js +214 -145
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +83 -5
- package/package.json +10 -10
package/dist/module.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import React, { createContext,
|
|
2
|
+
import React, { createContext, useRef, useState, useContext, useCallback, useEffect, useMemo } from 'react';
|
|
3
3
|
import { Combobox as Combobox$1, ComboboxItem, ComboboxItemCheck, ComboboxList, Group as Group$1, GroupLabel as GroupLabel$1, ComboboxProvider as ComboboxProvider$1 } from '@ariakit/react';
|
|
4
4
|
import { useFormFieldContext, FloatingLabel } from '@mirohq/design-system-base-form';
|
|
5
|
-
import * as RadixPopover from '@radix-ui/react-popover';
|
|
6
|
-
import { Anchor, Trigger as Trigger$1, Portal as Portal$1 } from '@radix-ui/react-popover';
|
|
7
5
|
import { booleanishAttrValue, mergeRefs, booleanify } from '@mirohq/design-system-utils';
|
|
6
|
+
import * as RadixPopover from '@radix-ui/react-popover';
|
|
7
|
+
import { Trigger as Trigger$1, Anchor, Portal as Portal$1 } from '@radix-ui/react-popover';
|
|
8
8
|
import { styled, theme } from '@mirohq/design-system-stitches';
|
|
9
9
|
import { Input } from '@mirohq/design-system-input';
|
|
10
10
|
import { useControllableState } from '@radix-ui/react-use-controllable-state';
|
|
@@ -18,15 +18,10 @@ import { focus } from '@mirohq/design-system-styles';
|
|
|
18
18
|
import { createPortal } from 'react-dom';
|
|
19
19
|
import { BaseButton } from '@mirohq/design-system-base-button';
|
|
20
20
|
|
|
21
|
-
const StyledAnchor = styled(Anchor, {
|
|
22
|
-
position: "relative",
|
|
23
|
-
width: "100%"
|
|
24
|
-
});
|
|
25
21
|
const StyledInput = styled(Input, {
|
|
26
22
|
flexWrap: "wrap",
|
|
27
23
|
flexGrow: 1,
|
|
28
|
-
gap: "
|
|
29
|
-
overflowY: "scroll",
|
|
24
|
+
gap: "$50",
|
|
30
25
|
"&[data-valid], &[data-invalid]": {
|
|
31
26
|
// we don't need a bigger padding here as Input component will render its own icon
|
|
32
27
|
paddingRight: "$100"
|
|
@@ -94,6 +89,8 @@ const ComboboxProvider = ({
|
|
|
94
89
|
});
|
|
95
90
|
const [filteredItems, setFilteredItems] = useState(/* @__PURE__ */ new Set());
|
|
96
91
|
const [searchValue, setSearchValue] = useState("");
|
|
92
|
+
const [size, setSize] = useState();
|
|
93
|
+
const [placeholder, setPlaceholder] = useState();
|
|
97
94
|
const [itemValueTextMap, setItemValueTextMap] = useState(/* @__PURE__ */ new Map());
|
|
98
95
|
const { valid: formFieldValid } = useFormFieldContext();
|
|
99
96
|
return /* @__PURE__ */ jsx(
|
|
@@ -118,7 +115,11 @@ const ComboboxProvider = ({
|
|
|
118
115
|
filteredItems,
|
|
119
116
|
setFilteredItems,
|
|
120
117
|
itemValueTextMap,
|
|
121
|
-
setItemValueTextMap
|
|
118
|
+
setItemValueTextMap,
|
|
119
|
+
placeholder,
|
|
120
|
+
setPlaceholder,
|
|
121
|
+
size,
|
|
122
|
+
setSize
|
|
122
123
|
},
|
|
123
124
|
children
|
|
124
125
|
}
|
|
@@ -202,7 +203,6 @@ const Trigger = React.forwardRef(
|
|
|
202
203
|
closeActionLabel,
|
|
203
204
|
clearActionLabel,
|
|
204
205
|
onChange,
|
|
205
|
-
css,
|
|
206
206
|
...restProps
|
|
207
207
|
}, forwardRef) => {
|
|
208
208
|
const {
|
|
@@ -216,16 +216,21 @@ const Trigger = React.forwardRef(
|
|
|
216
216
|
onSearchValueChange,
|
|
217
217
|
searchValue,
|
|
218
218
|
setSearchValue,
|
|
219
|
-
setOpenState
|
|
219
|
+
setOpenState,
|
|
220
|
+
setSize,
|
|
221
|
+
setPlaceholder
|
|
220
222
|
} = useComboboxContext();
|
|
221
223
|
const {
|
|
222
224
|
formElementId,
|
|
223
225
|
ariaInvalid: formFieldAriaInvalid,
|
|
224
|
-
valid: formFieldValid
|
|
225
|
-
label,
|
|
226
|
-
isFloatingLabel,
|
|
227
|
-
focused
|
|
226
|
+
valid: formFieldValid
|
|
228
227
|
} = useFormFieldContext();
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
setSize(size);
|
|
230
|
+
}, [size, setSize]);
|
|
231
|
+
useEffect(() => {
|
|
232
|
+
setPlaceholder(placeholder);
|
|
233
|
+
}, [setPlaceholder, placeholder]);
|
|
229
234
|
const valid = formFieldValid != null ? formFieldValid : comboboxValid;
|
|
230
235
|
const inputProps = {
|
|
231
236
|
...restProps,
|
|
@@ -240,8 +245,6 @@ const Trigger = React.forwardRef(
|
|
|
240
245
|
id: id != null ? id : formElementId,
|
|
241
246
|
placeholder: value.length === 0 ? placeholder : void 0
|
|
242
247
|
};
|
|
243
|
-
const shouldUseFloatingLabel = label !== null && isFloatingLabel;
|
|
244
|
-
const isFloating = placeholder !== void 0 || value.length !== 0 || focused || searchValue !== "";
|
|
245
248
|
const scrollIntoView = (event) => {
|
|
246
249
|
var _a;
|
|
247
250
|
const trigger = triggerRef == null ? void 0 : triggerRef.current;
|
|
@@ -261,47 +264,43 @@ const Trigger = React.forwardRef(
|
|
|
261
264
|
onSearchValueChange == null ? void 0 : onSearchValueChange(e.target.value);
|
|
262
265
|
onChange == null ? void 0 : onChange(e);
|
|
263
266
|
};
|
|
264
|
-
return /* @__PURE__ */
|
|
265
|
-
|
|
267
|
+
return /* @__PURE__ */ jsx(
|
|
268
|
+
Anchor,
|
|
266
269
|
{
|
|
267
270
|
ref: mergeRefs([triggerRef, forwardRef]),
|
|
268
|
-
css,
|
|
269
271
|
onClick: () => {
|
|
270
272
|
if (!booleanify(disabled) && !booleanify(ariaDisabled) && !booleanify(readOnly)) {
|
|
271
273
|
setOpenState(true);
|
|
272
274
|
}
|
|
273
275
|
},
|
|
274
|
-
children:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
)
|
|
304
|
-
]
|
|
276
|
+
children: /* @__PURE__ */ jsx(
|
|
277
|
+
Combobox$1,
|
|
278
|
+
{
|
|
279
|
+
render: /* @__PURE__ */ jsxs(
|
|
280
|
+
StyledInput,
|
|
281
|
+
{
|
|
282
|
+
...inputProps,
|
|
283
|
+
value: searchValue,
|
|
284
|
+
size,
|
|
285
|
+
ref: inputRef,
|
|
286
|
+
onChange: onInputChange,
|
|
287
|
+
onFocus: scrollIntoView,
|
|
288
|
+
children: [
|
|
289
|
+
children,
|
|
290
|
+
/* @__PURE__ */ jsx(
|
|
291
|
+
TriggerActionButton,
|
|
292
|
+
{
|
|
293
|
+
openActionLabel,
|
|
294
|
+
closeActionLabel,
|
|
295
|
+
clearActionLabel,
|
|
296
|
+
size
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
)
|
|
305
304
|
}
|
|
306
305
|
);
|
|
307
306
|
}
|
|
@@ -372,7 +371,8 @@ const Item = React.forwardRef(
|
|
|
372
371
|
filteredItems,
|
|
373
372
|
setItemValueTextMap,
|
|
374
373
|
triggerRef,
|
|
375
|
-
inputRef
|
|
374
|
+
inputRef,
|
|
375
|
+
value: comboboxValue = []
|
|
376
376
|
} = useComboboxContext();
|
|
377
377
|
useLayoutEffect(() => {
|
|
378
378
|
const textToSet = textValue !== void 0 ? textValue : typeof children === "string" ? children : "";
|
|
@@ -398,6 +398,7 @@ const Item = React.forwardRef(
|
|
|
398
398
|
restProps.onClick(event);
|
|
399
399
|
}
|
|
400
400
|
};
|
|
401
|
+
const isSelected = comboboxValue.includes(value);
|
|
401
402
|
return /* @__PURE__ */ jsxs(
|
|
402
403
|
StyledItem,
|
|
403
404
|
{
|
|
@@ -409,10 +410,12 @@ const Item = React.forwardRef(
|
|
|
409
410
|
ref: forwardRef,
|
|
410
411
|
value,
|
|
411
412
|
onClick: scrollIntoView,
|
|
413
|
+
"aria-selected": isSelected,
|
|
412
414
|
children: [
|
|
413
415
|
/* @__PURE__ */ jsx(
|
|
414
416
|
ComboboxItemCheck,
|
|
415
417
|
{
|
|
418
|
+
checked: isSelected,
|
|
416
419
|
render: ({ style, ...props }) => (
|
|
417
420
|
// AriakitComboboxItemCheck adds its owm inline styles which we want to omit here
|
|
418
421
|
/* @__PURE__ */ jsx(StyledItemCheck, { ...props })
|
|
@@ -478,9 +481,16 @@ const isInsideRef = (element, ref) => {
|
|
|
478
481
|
};
|
|
479
482
|
const Content = React.forwardRef(
|
|
480
483
|
({
|
|
484
|
+
side = "bottom",
|
|
481
485
|
sideOffset = CONTENT_OFFSET,
|
|
486
|
+
align = "center",
|
|
487
|
+
alignOffset = 0,
|
|
488
|
+
collisionPadding = 0,
|
|
489
|
+
avoidCollisions = true,
|
|
490
|
+
sticky = "partial",
|
|
491
|
+
hideWhenDetached = true,
|
|
492
|
+
overflow = "visible",
|
|
482
493
|
maxHeight,
|
|
483
|
-
overflow,
|
|
484
494
|
children,
|
|
485
495
|
...restProps
|
|
486
496
|
}, forwardRef) => {
|
|
@@ -519,7 +529,14 @@ const Content = React.forwardRef(
|
|
|
519
529
|
asChild: true,
|
|
520
530
|
...restProps,
|
|
521
531
|
dir: direction,
|
|
532
|
+
side,
|
|
522
533
|
sideOffset,
|
|
534
|
+
align,
|
|
535
|
+
alignOffset,
|
|
536
|
+
avoidCollisions,
|
|
537
|
+
collisionPadding,
|
|
538
|
+
sticky,
|
|
539
|
+
hideWhenDetached,
|
|
523
540
|
ref: mergeRefs([forwardRef, contentRef]),
|
|
524
541
|
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
525
542
|
onInteractOutside: (event) => {
|
|
@@ -619,10 +636,6 @@ const Chip = React.forwardRef(
|
|
|
619
636
|
);
|
|
620
637
|
Chip.LeftSlot = LeftSlot;
|
|
621
638
|
|
|
622
|
-
const StyledValue = styled(Chip, {
|
|
623
|
-
marginTop: "$50"
|
|
624
|
-
});
|
|
625
|
-
|
|
626
639
|
const Value = ({ unselectAriaLabel }) => {
|
|
627
640
|
const {
|
|
628
641
|
value = [],
|
|
@@ -645,9 +658,12 @@ const Value = ({ unselectAriaLabel }) => {
|
|
|
645
658
|
return null;
|
|
646
659
|
}
|
|
647
660
|
return /* @__PURE__ */ jsx(
|
|
648
|
-
|
|
661
|
+
Chip,
|
|
649
662
|
{
|
|
650
|
-
onRemove: () =>
|
|
663
|
+
onRemove: (e) => {
|
|
664
|
+
onItemRemove(itemValue);
|
|
665
|
+
e.stopPropagation();
|
|
666
|
+
},
|
|
651
667
|
disabled: isDisabled,
|
|
652
668
|
removeAriaLabel: "".concat(unselectAriaLabel, " ").concat(textValue),
|
|
653
669
|
"data-testid": process.env.NODE_ENV === "test" ? "combobox-value-".concat(itemValue) : void 0,
|
|
@@ -676,53 +692,71 @@ const Separator = React.forwardRef((props, forwardRef) => {
|
|
|
676
692
|
return /* @__PURE__ */ jsx(StyledSeparator, { ...props, ref: forwardRef, "aria-hidden": true });
|
|
677
693
|
});
|
|
678
694
|
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
695
|
+
const StyledNativeSelect = styled(Primitive.select, {
|
|
696
|
+
// if we support autoComplete, we would have to use visually-hidden styles here
|
|
697
|
+
display: "none"
|
|
698
|
+
});
|
|
699
|
+
const StyledComboboxContent = styled(Primitive.div, {
|
|
700
|
+
position: "relative",
|
|
701
|
+
width: "100%"
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
const Root = React.forwardRef(
|
|
705
|
+
({ value: valueProp, onValueChange, name, children, ...restProps }, forwardRef) => {
|
|
706
|
+
var _a;
|
|
707
|
+
const {
|
|
708
|
+
openState,
|
|
709
|
+
setOpenState,
|
|
710
|
+
defaultValue,
|
|
711
|
+
value = [],
|
|
712
|
+
setValue,
|
|
713
|
+
required,
|
|
714
|
+
readOnly,
|
|
715
|
+
"aria-disabled": ariaDisabled,
|
|
716
|
+
disabled,
|
|
717
|
+
direction,
|
|
718
|
+
size,
|
|
719
|
+
placeholder,
|
|
720
|
+
triggerRef
|
|
721
|
+
} = useComboboxContext();
|
|
722
|
+
const {
|
|
723
|
+
setRequired,
|
|
724
|
+
setDisabled,
|
|
725
|
+
setAriaDisabled,
|
|
726
|
+
setReadOnly,
|
|
727
|
+
label,
|
|
728
|
+
isFloatingLabel,
|
|
729
|
+
focused,
|
|
730
|
+
formElementRef
|
|
731
|
+
} = useFormFieldContext();
|
|
732
|
+
useEffect(() => {
|
|
733
|
+
setRequired == null ? void 0 : setRequired(required);
|
|
734
|
+
setDisabled == null ? void 0 : setDisabled(disabled);
|
|
735
|
+
setAriaDisabled == null ? void 0 : setAriaDisabled(ariaDisabled);
|
|
736
|
+
setReadOnly == null ? void 0 : setReadOnly(readOnly);
|
|
737
|
+
}, [
|
|
738
|
+
readOnly,
|
|
739
|
+
disabled,
|
|
740
|
+
ariaDisabled,
|
|
741
|
+
required,
|
|
742
|
+
setRequired,
|
|
743
|
+
setDisabled,
|
|
744
|
+
setAriaDisabled,
|
|
745
|
+
setReadOnly
|
|
746
|
+
]);
|
|
747
|
+
const shouldUseFloatingLabel = label !== null && isFloatingLabel;
|
|
748
|
+
const isFloating = placeholder !== void 0 || value.length !== 0 || focused;
|
|
749
|
+
const onSetSelectedValue = (newValue) => {
|
|
750
|
+
setValue(typeof newValue === "string" ? [newValue] : newValue);
|
|
751
|
+
};
|
|
752
|
+
const onOpenChange = (value2) => {
|
|
753
|
+
if (!booleanify(readOnly)) {
|
|
754
|
+
setOpenState(value2);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
const isFormControl = Boolean((_a = triggerRef.current) == null ? void 0 : _a.closest("form"));
|
|
758
|
+
return /* @__PURE__ */ jsxs(RadixPopover.Root, { open: openState, onOpenChange, children: [
|
|
759
|
+
/* @__PURE__ */ jsx(
|
|
726
760
|
ComboboxProvider$1,
|
|
727
761
|
{
|
|
728
762
|
open: openState,
|
|
@@ -730,51 +764,86 @@ const Root = ({
|
|
|
730
764
|
defaultSelectedValue: defaultValue,
|
|
731
765
|
selectedValue: value,
|
|
732
766
|
setSelectedValue: onSetSelectedValue,
|
|
733
|
-
children
|
|
767
|
+
children: /* @__PURE__ */ jsxs(
|
|
768
|
+
StyledComboboxContent,
|
|
769
|
+
{
|
|
770
|
+
ref: forwardRef,
|
|
771
|
+
...restProps,
|
|
772
|
+
dir: direction,
|
|
773
|
+
"data-form-element": "select",
|
|
774
|
+
children: [
|
|
775
|
+
shouldUseFloatingLabel && /* @__PURE__ */ jsx(FloatingLabel, { floating: isFloating, size, children: label }),
|
|
776
|
+
children
|
|
777
|
+
]
|
|
778
|
+
}
|
|
779
|
+
)
|
|
780
|
+
}
|
|
781
|
+
),
|
|
782
|
+
isFormControl && /* @__PURE__ */ jsx(
|
|
783
|
+
StyledNativeSelect,
|
|
784
|
+
{
|
|
785
|
+
multiple: true,
|
|
786
|
+
autoComplete: "off",
|
|
787
|
+
name,
|
|
788
|
+
tabIndex: -1,
|
|
789
|
+
"aria-hidden": "true",
|
|
790
|
+
ref: formElementRef,
|
|
791
|
+
required,
|
|
792
|
+
disabled,
|
|
793
|
+
"aria-disabled": ariaDisabled,
|
|
794
|
+
value,
|
|
795
|
+
onChange: () => {
|
|
796
|
+
},
|
|
797
|
+
children: value.length === 0 ? /* @__PURE__ */ jsx("option", { value: "" }) : (
|
|
798
|
+
// since we don't support autoComplete we can render here only selected values
|
|
799
|
+
value.map((itemValue) => /* @__PURE__ */ jsx("option", { value: itemValue, children: itemValue }, itemValue))
|
|
800
|
+
)
|
|
734
801
|
}
|
|
735
802
|
)
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
const Combobox = (
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
valid,
|
|
744
|
-
disabled,
|
|
745
|
-
readOnly,
|
|
746
|
-
required,
|
|
747
|
-
value,
|
|
748
|
-
defaultValue,
|
|
749
|
-
onOpen,
|
|
750
|
-
onClose,
|
|
751
|
-
onSearchValueChange,
|
|
752
|
-
onValueChange,
|
|
753
|
-
direction = "ltr",
|
|
754
|
-
autoFilter = true,
|
|
755
|
-
noResultsText,
|
|
756
|
-
...restProps
|
|
757
|
-
}) => /* @__PURE__ */ jsx(
|
|
758
|
-
ComboboxProvider,
|
|
759
|
-
{
|
|
760
|
-
defaultValue,
|
|
761
|
-
value,
|
|
762
|
-
onValueChange,
|
|
763
|
-
onSearchValueChange,
|
|
764
|
-
defaultOpen,
|
|
803
|
+
] });
|
|
804
|
+
}
|
|
805
|
+
);
|
|
806
|
+
const Combobox = React.forwardRef(
|
|
807
|
+
({
|
|
808
|
+
"aria-disabled": ariaDisabled,
|
|
809
|
+
defaultOpen = false,
|
|
765
810
|
open,
|
|
766
|
-
onOpen,
|
|
767
|
-
onClose,
|
|
768
811
|
valid,
|
|
769
|
-
required,
|
|
770
812
|
disabled,
|
|
771
813
|
readOnly,
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
814
|
+
required,
|
|
815
|
+
value,
|
|
816
|
+
defaultValue,
|
|
817
|
+
onOpen,
|
|
818
|
+
onClose,
|
|
819
|
+
onSearchValueChange,
|
|
820
|
+
onValueChange,
|
|
821
|
+
direction = "ltr",
|
|
822
|
+
autoFilter = true,
|
|
775
823
|
noResultsText,
|
|
776
|
-
|
|
777
|
-
}
|
|
824
|
+
...restProps
|
|
825
|
+
}, forwardRef) => /* @__PURE__ */ jsx(
|
|
826
|
+
ComboboxProvider,
|
|
827
|
+
{
|
|
828
|
+
defaultValue,
|
|
829
|
+
value,
|
|
830
|
+
onValueChange,
|
|
831
|
+
onSearchValueChange,
|
|
832
|
+
defaultOpen,
|
|
833
|
+
open,
|
|
834
|
+
onOpen,
|
|
835
|
+
onClose,
|
|
836
|
+
valid,
|
|
837
|
+
required,
|
|
838
|
+
disabled,
|
|
839
|
+
readOnly,
|
|
840
|
+
"aria-disabled": ariaDisabled,
|
|
841
|
+
direction,
|
|
842
|
+
autoFilter,
|
|
843
|
+
noResultsText,
|
|
844
|
+
children: /* @__PURE__ */ jsx(Root, { ...restProps, value, ref: forwardRef })
|
|
845
|
+
}
|
|
846
|
+
)
|
|
778
847
|
);
|
|
779
848
|
Combobox.Portal = Portal;
|
|
780
849
|
Combobox.Trigger = Trigger;
|