@purpurds/autocomplete 5.14.0 → 5.15.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/LICENSE.txt +10 -10
- package/dist/autocomplete.cjs.js +21 -13
- package/dist/autocomplete.cjs.js.map +1 -1
- package/dist/autocomplete.d.ts +6 -6
- package/dist/autocomplete.d.ts.map +1 -1
- package/dist/autocomplete.es.js +536 -419
- package/dist/autocomplete.es.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/useAutocomplete.d.ts +1 -1
- package/dist/useAutocomplete.d.ts.map +1 -1
- package/package.json +10 -9
- package/src/autocomplete.stories.tsx +1 -0
- package/src/autocomplete.tsx +6 -6
- package/src/useAutocomplete.ts +1 -1
- package/dist/listbox.d.ts +0 -22
- package/dist/listbox.d.ts.map +0 -1
- package/src/listbox.module.scss +0 -60
- package/src/listbox.tsx +0 -94
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)}
|
|
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 +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;
|
|
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;;;;;;;;kCA4KW,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.
|
|
3
|
+
"version": "5.15.0",
|
|
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.
|
|
19
|
-
"@purpurds/
|
|
20
|
-
"@purpurds/
|
|
21
|
-
"@purpurds/
|
|
18
|
+
"@purpurds/icon": "5.15.0",
|
|
19
|
+
"@purpurds/listbox": "5.15.0",
|
|
20
|
+
"@purpurds/paragraph": "5.15.0",
|
|
21
|
+
"@purpurds/text-field": "5.15.0",
|
|
22
|
+
"@purpurds/tokens": "5.15.0"
|
|
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.
|
|
48
|
-
"@purpurds/
|
|
49
|
-
"@purpurds/
|
|
50
|
-
"@purpurds/
|
|
48
|
+
"@purpurds/button": "5.15.0",
|
|
49
|
+
"@purpurds/component-rig": "1.0.0",
|
|
50
|
+
"@purpurds/icon": "5.15.0",
|
|
51
|
+
"@purpurds/search-field": "5.15.0"
|
|
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";
|
package/src/autocomplete.tsx
CHANGED
|
@@ -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
|
-
<
|
|
51
|
+
<Listbox.Item key={key} {...listboxItemProps}>
|
|
52
52
|
{renderOption ? renderOption?.(option) : option.label}
|
|
53
|
-
</
|
|
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
|
-
<
|
|
104
|
+
<Listbox {...listboxProps} className={cx(`${rootClassName}__listbox`)}>
|
|
105
105
|
{!optionsToShow.length ? (
|
|
106
|
-
<
|
|
106
|
+
<Listbox.Item noninteractive>{noOptionsText}</Listbox.Item>
|
|
107
107
|
) : (
|
|
108
108
|
optionsToShow.filter((option): option is T => !!option).map(renderListboxItem)
|
|
109
109
|
)}
|
|
110
|
-
</
|
|
110
|
+
</Listbox>
|
|
111
111
|
)}
|
|
112
112
|
</div>
|
|
113
113
|
);
|
package/src/useAutocomplete.ts
CHANGED
|
@@ -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 = {
|
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
|
package/dist/listbox.d.ts.map
DELETED
|
@@ -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"}
|
package/src/listbox.module.scss
DELETED
|
@@ -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 };
|