@purpurds/autocomplete 5.14.0 → 5.15.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/styles.css CHANGED
@@ -1 +1 @@
1
- ._purpur-autocomplete_1u8x6_1{position:relative}._purpur-autocomplete__listbox_1u8x6_4{position:absolute;z-index:1;top:calc(100% + var(--purpur-spacing-100))}._purpur-autocomplete__chevron-button_1u8x6_9{padding:0;border:0;background:none;cursor:pointer}._purpur-autocomplete_1u8x6_1 ._purpur-autocomplete__chevron-icon_1u8x6_15{display:block;transition:transform var(--purpur-motion-duration-200) var(--purpur-motion-easing-ease-in-out)}._purpur-autocomplete_1u8x6_1 ._purpur-autocomplete__chevron-icon--up_1u8x6_19{transform:rotate(180deg)}._purpur-listbox_qhoi7_1{padding:0;margin:0;list-style-type:none;border:var(--purpur-border-width-xs) solid var(--purpur-color-border-interactive-subtle);border-radius:var(--purpur-border-radius-sm);color:var(--purpur-color-brand-off-black);width:100%;background-color:var(--purpur-color-brand-white);max-height:calc(2 * var(--purpur-spacing-1200));overflow-y:scroll;box-sizing:border-box}._purpur-listbox-item_qhoi7_15{list-style:none;padding:var(--purpur-spacing-150);border:var(--purpur-border-width-xs) solid transparent;cursor:pointer;max-width:100%;word-break:break-word;transition:background var(--purpur-motion-duration-150) ease;display:flex;justify-content:space-between;align-items:center;gap:var(--purpur-spacing-100)}@media (hover: hover) and (pointer: fine){._purpur-listbox-item--hovered_qhoi7_29{background:var(--purpur-color-background-interactive-transparent-hover)}}._purpur-listbox-item--highlighted_qhoi7_37{outline:var(--purpur-border-width-sm) solid var(--purpur-color-border-interactive-focus);outline-offset:calc(-1 * var(--purpur-border-width-sm))}._purpur-listbox-item_qhoi7_15:active:not(._purpur-listbox-item--noninteractive_qhoi7_41){background:var(--purpur-color-background-interactive-transparent-active)}._purpur-listbox-item--disabled_qhoi7_44{color:var(--purpur-color-text-weak);cursor:default}._purpur-listbox-item--noninteractive_qhoi7_41{cursor:default}._purpur-listbox-item__icon_qhoi7_51{color:var(--purpur-color-text-interactive-selected)}
1
+ ._purpur-autocomplete_1u8x6_1{position:relative}._purpur-autocomplete__listbox_1u8x6_4{position:absolute;z-index:1;top:calc(100% + var(--purpur-spacing-100))}._purpur-autocomplete__chevron-button_1u8x6_9{padding:0;border:0;background:none;cursor:pointer}._purpur-autocomplete_1u8x6_1 ._purpur-autocomplete__chevron-icon_1u8x6_15{display:block;transition:transform var(--purpur-motion-duration-200) var(--purpur-motion-easing-ease-in-out)}._purpur-autocomplete_1u8x6_1 ._purpur-autocomplete__chevron-icon--up_1u8x6_19{transform:rotate(180deg)}
@@ -1,5 +1,5 @@
1
- import { ListboxItemProps, ListboxProps } from './listbox';
2
1
  import { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import { ListboxItemProps, ListboxProps } from '@purpurds/listbox';
3
3
 
4
4
  export type Option = {
5
5
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../src/useAutocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGhE,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,MAAM,IAAI;IAIrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAI/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAI3B,UAAU,CAAC,EAAE,MAAM,CAAC;IAIpB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IAItE,EAAE,EAAE,MAAM,CAAC;IAIX,YAAY,EAAE,MAAM,CAAC;IAIrB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAInC,aAAa,CAAC,EAAE,SAAS,CAAC;IAI1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAIxC,WAAW,CAAC,EAAE,OAAO,CAAC;IAItB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IAI3C,OAAO,EAAE,CAAC,EAAE,CAAC;IAIb,cAAc,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,mOAgB7C,sBAAsB,CAAC,CAAC,CAAC;;;;;;;;kCA4KW,CAAC,SAAS,MAAM,KAAG,gBAAgB;;CAqDzE,CAAC"}
1
+ {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../src/useAutocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIxE,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,MAAM,IAAI;IAIrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAI/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAI3B,UAAU,CAAC,EAAE,MAAM,CAAC;IAIpB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IAItE,EAAE,EAAE,MAAM,CAAC;IAIX,YAAY,EAAE,MAAM,CAAC;IAIrB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAInC,aAAa,CAAC,EAAE,SAAS,CAAC;IAI1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAIxC,WAAW,CAAC,EAAE,OAAO,CAAC;IAItB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IAI3C,OAAO,EAAE,CAAC,EAAE,CAAC;IAIb,cAAc,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,mOAgB7C,sBAAsB,CAAC,CAAC,CAAC;;;;;;;;kCAqLW,CAAC,SAAS,MAAM,KAAG,gBAAgB;;CAqDzE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/autocomplete",
3
- "version": "5.14.0",
3
+ "version": "5.15.1",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/autocomplete.cjs.js",
6
6
  "types": "./dist/autocomplete.d.ts",
@@ -15,10 +15,11 @@
15
15
  "source": "src/autocomplete.tsx",
16
16
  "dependencies": {
17
17
  "classnames": "~2.5.0",
18
- "@purpurds/icon": "5.14.0",
19
- "@purpurds/text-field": "5.14.0",
20
- "@purpurds/tokens": "5.14.0",
21
- "@purpurds/paragraph": "5.14.0"
18
+ "@purpurds/listbox": "5.15.1",
19
+ "@purpurds/icon": "5.15.1",
20
+ "@purpurds/paragraph": "5.15.1",
21
+ "@purpurds/tokens": "5.15.1",
22
+ "@purpurds/text-field": "5.15.1"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@rushstack/eslint-patch": "~1.10.0",
@@ -44,10 +45,10 @@
44
45
  "typescript": "^5.5.4",
45
46
  "vite": "5.3.4",
46
47
  "vitest": "~1.5.0",
47
- "@purpurds/button": "5.14.0",
48
- "@purpurds/icon": "5.14.0",
49
- "@purpurds/search-field": "5.14.0",
50
- "@purpurds/component-rig": "1.0.0"
48
+ "@purpurds/button": "5.15.1",
49
+ "@purpurds/component-rig": "1.0.0",
50
+ "@purpurds/search-field": "5.15.1",
51
+ "@purpurds/icon": "5.15.1"
51
52
  },
52
53
  "scripts": {
53
54
  "build:dev": "vite",
@@ -7,6 +7,7 @@ import type { Meta, StoryObj } from "@storybook/react";
7
7
 
8
8
  import "@purpurds/icon/styles";
9
9
  import "@purpurds/button/styles";
10
+ import "@purpurds/listbox/styles";
10
11
  import "@purpurds/search-field/styles";
11
12
  import "@purpurds/text-field/styles";
12
13
  import { Autocomplete } from "./autocomplete";
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { TextField } from "@purpurds/text-field";
3
3
  import * as matchers from "@testing-library/jest-dom/matchers";
4
- import { cleanup, fireEvent, render, screen } from "@testing-library/react";
4
+ import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
5
5
  import { afterEach, describe, expect, it, vi } from "vitest";
6
6
 
7
7
  import { Autocomplete } from "./autocomplete";
@@ -593,7 +593,7 @@ describe("B2xAutocomplete", () => {
593
593
  expect(input.value).toEqual("random text");
594
594
  });
595
595
 
596
- it("should reset input value on blur for combobox with no selected option", () => {
596
+ it("should reset input value on blur for combobox with no selected option", async () => {
597
597
  const onSelectMock = vi.fn();
598
598
  render(
599
599
  <Autocomplete
@@ -613,10 +613,12 @@ describe("B2xAutocomplete", () => {
613
613
  fireEvent.change(input, { target: { value: "random text" } });
614
614
  expect(input.value).toEqual("random text");
615
615
  fireEvent.blur(input);
616
- expect(input.value).toEqual("");
616
+ await waitFor(() => {
617
+ expect(input.value).toEqual("");
618
+ });
617
619
  });
618
620
 
619
- it("should reset input value on blur for combobox with selected option", () => {
621
+ it("should reset input value on blur for combobox with selected option", async () => {
620
622
  const onSelectMock = vi.fn();
621
623
  render(
622
624
  <Autocomplete
@@ -637,6 +639,8 @@ describe("B2xAutocomplete", () => {
637
639
  fireEvent.change(input, { target: { value: "random text" } });
638
640
  expect(input.value).toEqual("random text");
639
641
  fireEvent.blur(input);
640
- expect(input.value).toEqual(options[0].label);
642
+ await waitFor(() => {
643
+ expect(input.value).toEqual(options[0].label);
644
+ });
641
645
  });
642
646
  });
@@ -1,11 +1,11 @@
1
1
  import type { ComponentPropsWithRef, ForwardedRef, ReactNode } from "react";
2
2
  import React, { cloneElement, forwardRef } from "react";
3
3
  import { IconChevronDown } from "@purpurds/icon";
4
+ import { Listbox } from "@purpurds/listbox";
4
5
  import { isTextField } from "@purpurds/text-field";
5
6
  import c from "classnames/bind";
6
7
 
7
8
  import styles from "./autocomplete.module.scss";
8
- import * as ListBox from "./listbox";
9
9
  import type { Option, UseAutocompleteOptions } from "./useAutocomplete";
10
10
  import { useAutocomplete } from "./useAutocomplete";
11
11
  import type { Prettify } from "./utils";
@@ -48,9 +48,9 @@ const AutocompleteComponent = <T extends Option>(
48
48
  const { key, ...listboxItemProps } = getListBoxItemProps(option, index);
49
49
 
50
50
  return (
51
- <ListBox.Item key={key} {...listboxItemProps}>
51
+ <Listbox.Item key={key} {...listboxItemProps}>
52
52
  {renderOption ? renderOption?.(option) : option.label}
53
- </ListBox.Item>
53
+ </Listbox.Item>
54
54
  );
55
55
  };
56
56
 
@@ -101,13 +101,13 @@ const AutocompleteComponent = <T extends Option>(
101
101
  <div id={id} ref={setRootRef} className={cx([className, rootClassName])}>
102
102
  {getInputComponent()}
103
103
  {showListbox && (
104
- <ListBox.Root {...listboxProps} className={cx(`${rootClassName}__listbox`)}>
104
+ <Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>
105
105
  {!optionsToShow.length ? (
106
- <ListBox.Item noninteractive>{noOptionsText}</ListBox.Item>
106
+ <Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>
107
107
  ) : (
108
108
  optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)
109
109
  )}
110
- </ListBox.Root>
110
+ </Listbox>
111
111
  )}
112
112
  </div>
113
113
  );
@@ -1,7 +1,7 @@
1
1
  import type { ComponentPropsWithRef, CSSProperties, ReactNode } from "react";
2
2
  import { useRef, useState } from "react";
3
+ import type { ListboxItemProps, ListboxProps } from "@purpurds/listbox";
3
4
 
4
- import type { ListboxItemProps, ListboxProps } from "./listbox";
5
5
  import { useMutableRefObject, useOnClickOutside } from "./utils";
6
6
 
7
7
  export type Option = {
@@ -245,7 +245,16 @@ export const useAutocomplete = <T extends Option>({
245
245
 
246
246
  const handleOnBlur = () => {
247
247
  if (combobox) {
248
- populateInputField(selectedOption?.label ?? "");
248
+ // Use a timeout to allow click events on the listbox to fire before this check
249
+ setTimeout(() => {
250
+ // If the blur happened due to a click inside the listbox, don't reset the value
251
+ if (
252
+ !inputRef.current?.contains(document.activeElement) &&
253
+ !listboxRef.current?.contains(document.activeElement)
254
+ ) {
255
+ populateInputField(selectedOption ? selectedOption.label : "");
256
+ }
257
+ });
249
258
  }
250
259
  };
251
260
 
package/dist/listbox.d.ts DELETED
@@ -1,22 +0,0 @@
1
- import { ComponentPropsWithRef, default as React } from 'react';
2
-
3
- export * from './useAutocomplete';
4
- type ListboxProps = Omit<ComponentPropsWithRef<"ul">, "role"> & {
5
- "data-testid"?: string;
6
- "aria-label": NonNullable<ComponentPropsWithRef<"ul">["aria-label"]>;
7
- "aria-expanded": NonNullable<ComponentPropsWithRef<"ul">["aria-expanded"]>;
8
- };
9
- type ListboxItemProps = Omit<ComponentPropsWithRef<"li">, "role"> & {
10
- "data-testid"?: string;
11
- highlighted?: boolean;
12
- hovered?: boolean;
13
- key?: string;
14
- selected?: boolean;
15
- disabled?: boolean;
16
- noninteractive?: boolean;
17
- };
18
- declare const Root: React.ForwardRefExoticComponent<Omit<ListboxProps, "ref"> & React.RefAttributes<HTMLUListElement>>;
19
- declare const Item: React.ForwardRefExoticComponent<Omit<ListboxItemProps, "ref"> & React.RefAttributes<HTMLLIElement>>;
20
- export { Item, Root };
21
- export type { ListboxItemProps, ListboxProps };
22
- //# sourceMappingURL=listbox.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"listbox.d.ts","sourceRoot":"","sources":["../src/listbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EAKtB,MAAM,OAAO,CAAC;AACf,OAAO,KAA+C,MAAM,OAAO,CAAC;AAOpE,cAAc,mBAAmB,CAAC;AAKlC,KAAK,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACrE,eAAe,EAAE,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;CAC5E,CAAC;AAgBF,KAAK,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AA0CF,QAAA,MAAM,IAAI,oGAAU,CAAC;AACrB,QAAA,MAAM,IAAI,qGAAc,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC"}
@@ -1,60 +0,0 @@
1
- .purpur-listbox {
2
- padding: 0;
3
- margin: 0;
4
- width: 100%;
5
- list-style-type: none;
6
- border: var(--purpur-border-width-xs) solid var(--purpur-color-border-interactive-subtle);
7
- border-radius: var(--purpur-border-radius-sm);
8
- color: var(--purpur-color-brand-off-black);
9
- width: 100%;
10
- background-color: var(--purpur-color-brand-white);
11
- max-height: calc(2 * var(--purpur-spacing-1200));
12
- overflow-y: scroll;
13
- box-sizing: border-box;
14
-
15
- &-item {
16
- $listboxItemRoot: &;
17
-
18
- cursor: pointer;
19
- list-style: none;
20
- padding: var(--purpur-spacing-150);
21
- border: var(--purpur-border-width-xs) solid transparent;
22
- cursor: pointer;
23
- max-width: 100%;
24
- word-break: break-word;
25
- transition: background var(--purpur-motion-duration-150) ease;
26
- display: flex;
27
- justify-content: space-between;
28
- align-items: center;
29
- gap: var(--purpur-spacing-100);
30
-
31
- &--hovered {
32
- /* Enable only on non-touch devices */
33
- @media (hover: hover) and (pointer: fine) {
34
- background: var(--purpur-color-background-interactive-transparent-hover);
35
- }
36
- }
37
-
38
- &--highlighted {
39
- outline: var(--purpur-border-width-sm) solid var(--purpur-color-border-interactive-focus);
40
- outline-offset: calc(-1 * var(--purpur-border-width-sm));
41
- }
42
-
43
- &:active:not(#{$listboxItemRoot}--noninteractive) {
44
- background: var(--purpur-color-background-interactive-transparent-active);
45
- }
46
-
47
- &--disabled {
48
- color: var(--purpur-color-text-weak);
49
- cursor: default;
50
- }
51
-
52
- &--noninteractive {
53
- cursor: default;
54
- }
55
-
56
- &__icon {
57
- color: var(--purpur-color-text-interactive-selected);
58
- }
59
- }
60
- }
package/src/listbox.tsx DELETED
@@ -1,94 +0,0 @@
1
- import type {
2
- ComponentPropsWithRef,
3
- ForwardedRef,
4
- ReactElement,
5
- ReactNode,
6
- ReactPortal,
7
- } from "react";
8
- import React, { Children, forwardRef, isValidElement } from "react";
9
- import { checkmark, Icon } from "@purpurds/icon";
10
- import { Paragraph } from "@purpurds/paragraph";
11
- import c from "classnames/bind";
12
-
13
- import styles from "./listbox.module.scss";
14
-
15
- export * from "./useAutocomplete";
16
- const cx = c.bind(styles);
17
-
18
- const rootClassName = "purpur-listbox";
19
-
20
- type ListboxProps = Omit<ComponentPropsWithRef<"ul">, "role"> & {
21
- "data-testid"?: string;
22
- "aria-label": NonNullable<ComponentPropsWithRef<"ul">["aria-label"]>;
23
- "aria-expanded": NonNullable<ComponentPropsWithRef<"ul">["aria-expanded"]>;
24
- };
25
-
26
- const Listbox = forwardRef(
27
- ({ children, ...listboxProps }: ListboxProps, ref: ForwardedRef<HTMLUListElement>) => (
28
- <ul
29
- {...listboxProps}
30
- ref={ref}
31
- className={cx(rootClassName, listboxProps.className)}
32
- role="listbox"
33
- >
34
- {Children.toArray(children).filter(isListboxItem)}
35
- </ul>
36
- )
37
- );
38
- Listbox.displayName = "ListBox";
39
-
40
- type ListboxItemProps = Omit<ComponentPropsWithRef<"li">, "role"> & {
41
- "data-testid"?: string;
42
- highlighted?: boolean;
43
- hovered?: boolean;
44
- key?: string;
45
- selected?: boolean;
46
- disabled?: boolean;
47
- noninteractive?: boolean;
48
- };
49
-
50
- const ListboxItem = forwardRef((props: ListboxItemProps, ref: ForwardedRef<HTMLLIElement>) => {
51
- const { disabled, highlighted, hovered, selected, children, noninteractive, ...liProps } = props;
52
- const className = cx(`${rootClassName}-item`, liProps.className, {
53
- [`${rootClassName}-item--highlighted`]: highlighted,
54
- [`${rootClassName}-item--selected`]: selected,
55
- [`${rootClassName}-item--hovered`]: hovered,
56
- [`${rootClassName}-item--disabled`]: disabled,
57
- [`${rootClassName}-item--noninteractive`]: noninteractive,
58
- });
59
-
60
- return (
61
- <li
62
- {...liProps}
63
- ref={ref}
64
- className={className}
65
- aria-selected={!!selected}
66
- role="option"
67
- aria-disabled={!!disabled}
68
- >
69
- {typeof children === "string" ? <Paragraph>{children}</Paragraph> : children}
70
- {selected && <Icon svg={checkmark} size="xs" className={cx(`${rootClassName}-item__icon`)} />}
71
- </li>
72
- );
73
- });
74
- ListboxItem.displayName = "ListBoxItem";
75
-
76
- function isListboxItem(
77
- child:
78
- | ReactElement
79
- | Iterable<ReactNode>
80
- | ReactPortal
81
- | string
82
- | number
83
- | boolean
84
- | null
85
- | undefined
86
- ): child is ReactElement<ListboxItemProps> {
87
- return isValidElement<ListboxItemProps>(child) && child?.type === ListboxItem;
88
- }
89
-
90
- const Root = Listbox;
91
- const Item = ListboxItem;
92
-
93
- export { Item, Root };
94
- export type { ListboxItemProps, ListboxProps };