@launchpad-ui/filter 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/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # @launchpad-ui/filter
2
+
3
+ > filter a list of results
4
+
5
+ [![See it on NPM!](https://img.shields.io/npm/v/@launchpad-ui/filter?style=for-the-badge)](https://www.npmjs.com/package/@launchpad-ui/filter)
6
+ [![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@launchpad-ui/filter?style=for-the-badge)](https://bundlephobia.com/result?p=@launchpad-ui/filter)
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ $ yarn add @launchpad-ui/filter
12
+ # or
13
+ $ npm install @launchpad-ui/filter
14
+ ```
@@ -0,0 +1,25 @@
1
+ import type { FilterOption } from './FilterMenu';
2
+ import type { ReactNode } from 'react';
3
+ declare type AppliedFilterProps = {
4
+ searchValue?: string;
5
+ onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;
6
+ onClearFilter?(): void;
7
+ searchPlaceholder?: string;
8
+ name?: ReactNode;
9
+ description: ReactNode;
10
+ options: FilterOption[];
11
+ className?: string;
12
+ onStateChange?({ isOpen }: {
13
+ isOpen?: boolean;
14
+ }): void;
15
+ isSelected?: boolean;
16
+ onSelect?(item: FilterOption): void;
17
+ isEmpty?: boolean;
18
+ isLoading?: boolean;
19
+ onClickFilterButton?(): void;
20
+ searchAriaLabel?: string;
21
+ };
22
+ declare const AppliedFilter: ({ searchValue, onSearchChange, searchPlaceholder, name, description, options, className, isEmpty, isLoading, onClickFilterButton, onClearFilter, searchAriaLabel, ...props }: AppliedFilterProps) => JSX.Element;
23
+ export type { AppliedFilterProps };
24
+ export { AppliedFilter };
25
+ //# sourceMappingURL=AppliedFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppliedFilter.d.ts","sourceRoot":"","sources":["../src/AppliedFilter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,aAAK,kBAAkB,GAAG;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAClE,aAAa,CAAC,IAAI,IAAI,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,IAAI,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,QAAA,MAAM,aAAa,iLAchB,kBAAkB,gBA4BpB,CAAC;AAEF,YAAY,EAAE,kBAAkB,EAAE,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ import './styles/Filter.css';
3
+ declare type AppliedFilterButtonProps = {
4
+ name?: ReactNode;
5
+ className?: string;
6
+ isSelected?: boolean;
7
+ children: ReactNode;
8
+ onClickFilterButton?(): void;
9
+ };
10
+ declare const AppliedFilterButton: import("react").ForwardRefExoticComponent<AppliedFilterButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
11
+ export type { AppliedFilterButtonProps };
12
+ export { AppliedFilterButton };
13
+ //# sourceMappingURL=AppliedFilterButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppliedFilterButton.d.ts","sourceRoot":"","sources":["../src/AppliedFilterButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,qBAAqB,CAAC;AAE7B,aAAK,wBAAwB,GAAG;IAC9B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,mBAAmB,CAAC,IAAI,IAAI,CAAC;CAC9B,CAAC;AAIF,QAAA,MAAM,mBAAmB,wHA8BvB,CAAC;AAIH,YAAY,EAAE,wBAAwB,EAAE,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { FilterOption } from './FilterMenu';
2
+ import type { MenuProps } from '@launchpad-ui/menu';
3
+ import type { ReactNode } from 'react';
4
+ declare type FilterProps = Pick<MenuProps<string>, 'size' | 'enableVirtualization'> & {
5
+ searchValue?: string;
6
+ onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;
7
+ searchPlaceholder?: string;
8
+ searchAriaLabel?: string;
9
+ name: ReactNode;
10
+ hideName?: boolean;
11
+ description: ReactNode;
12
+ options: FilterOption[];
13
+ isClearable?: boolean;
14
+ onClear?(): void;
15
+ className?: string;
16
+ onStateChange?({ isOpen }: {
17
+ isOpen?: boolean;
18
+ }): void;
19
+ isSelected?: boolean;
20
+ onSelect?(item: FilterOption): void;
21
+ isEmpty?: boolean;
22
+ isLoading?: boolean;
23
+ onClickFilterButton?(): void;
24
+ disabledOptionTooltip?: string;
25
+ testId?: string;
26
+ };
27
+ declare const Filter: ({ searchValue, onSearchChange, searchPlaceholder, searchAriaLabel, name, hideName, description, options, isClearable, onClear, isSelected, className, isEmpty, isLoading, onClickFilterButton, disabledOptionTooltip, testId, size, enableVirtualization, ...props }: FilterProps) => JSX.Element;
28
+ export { Filter };
29
+ export type { FilterProps };
30
+ //# sourceMappingURL=Filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Filter.d.ts","sourceRoot":"","sources":["../src/Filter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAUvD,aAAK,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,sBAAsB,CAAC,GAAG;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,IAAI,IAAI,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,QAAA,MAAM,MAAM,yQAqBT,WAAW,gBAsCb,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ReactNode, SyntheticEvent } from 'react';
2
+ import './styles/Filter.css';
3
+ declare type FilterButtonProps = {
4
+ name: ReactNode;
5
+ hideName?: boolean;
6
+ isClearable?: boolean;
7
+ onClear?(event: SyntheticEvent): void;
8
+ className?: string;
9
+ isSelected?: boolean;
10
+ clearTooltip?: string | JSX.Element;
11
+ children?: ReactNode;
12
+ onClickFilterButton?(): void;
13
+ testId?: string;
14
+ };
15
+ declare const FilterButton: import("react").ForwardRefExoticComponent<FilterButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
16
+ export { FilterButton };
17
+ export type { FilterButtonProps };
18
+ //# sourceMappingURL=FilterButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterButton.d.ts","sourceRoot":"","sources":["../src/FilterButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAUvD,OAAO,qBAAqB,CAAC;AAE7B,aAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,mBAAmB,CAAC,IAAI,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,QAAA,MAAM,YAAY,iHA+DhB,CAAC;AAQH,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { MenuProps } from '@launchpad-ui/menu';
2
+ import type { ReactNode } from 'react';
3
+ declare type FilterOption<T = any> = {
4
+ name?: ReactNode;
5
+ isDisabled?: boolean;
6
+ isDivider?: boolean;
7
+ isChecked?: boolean;
8
+ value: T | null;
9
+ projKey?: string;
10
+ nested?: boolean;
11
+ groupHeader?: boolean;
12
+ };
13
+ declare type FilterMenuProps = Pick<MenuProps<string>, 'enableVirtualization' | 'size'> & {
14
+ options: FilterOption[];
15
+ onClearFilter?(): void;
16
+ enableSearch?: boolean;
17
+ searchValue?: string;
18
+ searchPlaceholder?: string;
19
+ searchAriaLabel?: string;
20
+ onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;
21
+ onSelect?(): void;
22
+ isLoading?: boolean;
23
+ disabledOptionTooltip?: string;
24
+ };
25
+ declare const FilterMenu: ({ options, onClearFilter, enableSearch, searchValue, searchPlaceholder, searchAriaLabel, onSelect, onSearchChange, isLoading, disabledOptionTooltip, enableVirtualization, size, }: FilterMenuProps) => JSX.Element;
26
+ export { FilterMenu };
27
+ export type { FilterOption, FilterMenuProps };
28
+ //# sourceMappingURL=FilterMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterMenu.d.ts","sourceRoot":"","sources":["../src/FilterMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,aAAK,YAAY,CAAC,CAAC,GAAG,GAAG,IAAI;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,aAAK,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC,GAAG;IAChF,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,CAAC,IAAI,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAClE,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,QAAA,MAAM,UAAU,uLAab,eAAe,gBA+CjB,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type { AppliedFilterProps } from './AppliedFilter';
2
+ export type { FilterProps } from './Filter';
3
+ export type { FilterButtonProps } from './FilterButton';
4
+ export type { FilterOption } from './FilterMenu';
5
+ export { AppliedFilter } from './AppliedFilter';
6
+ export { Filter } from './Filter';
7
+ export { FilterButton } from './FilterButton';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,259 @@
1
+ // ../../scripts/react-shim.js
2
+ import * as React from "react";
3
+
4
+ // src/AppliedFilter.tsx
5
+ import { Dropdown } from "@launchpad-ui/dropdown";
6
+ import cx2 from "clsx";
7
+
8
+ // src/AppliedFilterButton.tsx
9
+ import { ExpandMore, IconSize } from "@launchpad-ui/icons";
10
+ import cx from "clsx";
11
+ import { Children, forwardRef } from "react";
12
+ import "./styles/Filter.css";
13
+ var AppliedFilterButton = forwardRef((props, ref) => {
14
+ const { name, className, isSelected, children, onClickFilterButton } = props;
15
+ const hasDescription = Children.count(children) !== 0;
16
+ return /* @__PURE__ */ React.createElement("div", {
17
+ className: "AppliedFilter-buttonContainer"
18
+ }, /* @__PURE__ */ React.createElement("button", {
19
+ "aria-haspopup": true,
20
+ className: cx("AppliedFilter-button", {
21
+ isSelected
22
+ }, className),
23
+ ref,
24
+ onClick: onClickFilterButton
25
+ }, name && /* @__PURE__ */ React.createElement("span", {
26
+ className: "AppliedFilter-name"
27
+ }, name, hasDescription && ":"), hasDescription && /* @__PURE__ */ React.createElement("span", {
28
+ className: "AppliedFilter-description"
29
+ }, children), /* @__PURE__ */ React.createElement(ExpandMore, {
30
+ size: IconSize.SMALL
31
+ })));
32
+ });
33
+ AppliedFilterButton.displayName = "AppliedFilterButton";
34
+
35
+ // src/FilterMenu.tsx
36
+ import { Button, ButtonKind } from "@launchpad-ui/button";
37
+ import { Check } from "@launchpad-ui/icons";
38
+ import { Menu, MenuDivider, MenuItem, MenuSearch } from "@launchpad-ui/menu";
39
+ var FilterMenu = ({
40
+ options,
41
+ onClearFilter,
42
+ enableSearch,
43
+ searchValue,
44
+ searchPlaceholder,
45
+ searchAriaLabel,
46
+ onSelect,
47
+ onSearchChange,
48
+ isLoading = false,
49
+ disabledOptionTooltip,
50
+ enableVirtualization,
51
+ size
52
+ }) => {
53
+ const filterOptions = isLoading ? [{ name: "loading...", value: "loading...", isDisabled: true }] : options;
54
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, onClearFilter && /* @__PURE__ */ React.createElement(Button, {
55
+ tabIndex: 0,
56
+ className: "Menu-clear",
57
+ onClick: onClearFilter,
58
+ kind: ButtonKind.LINK
59
+ }, "CLEAR FILTER"), /* @__PURE__ */ React.createElement(Menu, {
60
+ enableVirtualization,
61
+ size,
62
+ onSelect
63
+ }, enableSearch && /* @__PURE__ */ React.createElement(MenuSearch, {
64
+ value: searchValue,
65
+ placeholder: searchPlaceholder,
66
+ onChange: onSearchChange,
67
+ ariaLabel: searchAriaLabel
68
+ }), filterOptions.map((option, index) => {
69
+ if (option.isDivider) {
70
+ return /* @__PURE__ */ React.createElement(MenuDivider, {
71
+ key: `divider-${index}`
72
+ });
73
+ }
74
+ return /* @__PURE__ */ React.createElement(MenuItem, {
75
+ item: option,
76
+ disabled: option.isDisabled,
77
+ icon: option.isChecked ? Check : null,
78
+ key: option.value,
79
+ role: "menuitemradio",
80
+ "aria-checked": option.isChecked ? "true" : void 0,
81
+ nested: option.nested,
82
+ groupHeader: option.groupHeader,
83
+ tooltip: option.isDisabled && disabledOptionTooltip ? disabledOptionTooltip : void 0,
84
+ tooltipPlacement: "right"
85
+ }, option.name);
86
+ })));
87
+ };
88
+
89
+ // src/AppliedFilter.tsx
90
+ var SEARCH_INPUT_THRESHOLD = 4;
91
+ var AppliedFilter = ({
92
+ searchValue,
93
+ onSearchChange,
94
+ searchPlaceholder,
95
+ name,
96
+ description,
97
+ options,
98
+ className,
99
+ isEmpty,
100
+ isLoading,
101
+ onClickFilterButton,
102
+ onClearFilter,
103
+ searchAriaLabel,
104
+ ...props
105
+ }) => {
106
+ const enableSearch = onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);
107
+ const dropdownClasses = cx2("Filter-target", className);
108
+ return /* @__PURE__ */ React.createElement(Dropdown, {
109
+ targetClassName: dropdownClasses,
110
+ placement: "bottom-start",
111
+ enableArrow: false,
112
+ ...props
113
+ }, /* @__PURE__ */ React.createElement(AppliedFilterButton, {
114
+ name,
115
+ onClickFilterButton
116
+ }, description), /* @__PURE__ */ React.createElement(FilterMenu, {
117
+ options,
118
+ searchValue,
119
+ searchPlaceholder,
120
+ enableSearch,
121
+ searchAriaLabel,
122
+ onSearchChange,
123
+ onClearFilter,
124
+ isLoading
125
+ }));
126
+ };
127
+
128
+ // src/Filter.tsx
129
+ import { Dropdown as Dropdown2 } from "@launchpad-ui/dropdown";
130
+ import cx4 from "clsx";
131
+
132
+ // src/FilterButton.tsx
133
+ import { Button as Button2, ButtonSize, ButtonType } from "@launchpad-ui/button";
134
+ import { Close, ExpandMore as ExpandMore2, IconSize as IconSize2 } from "@launchpad-ui/icons";
135
+ import { Tooltip } from "@launchpad-ui/tooltip";
136
+ import { useId } from "@react-aria/utils";
137
+ import { VisuallyHidden } from "@react-aria/visually-hidden";
138
+ import cx3 from "clsx";
139
+ import { Children as Children2, forwardRef as forwardRef2 } from "react";
140
+ import "./styles/Filter.css";
141
+ var FilterButton = forwardRef2((props, ref) => {
142
+ const {
143
+ children,
144
+ name,
145
+ hideName,
146
+ isClearable,
147
+ clearTooltip,
148
+ onClear,
149
+ isSelected,
150
+ onClickFilterButton,
151
+ className,
152
+ testId,
153
+ ...rest
154
+ } = props;
155
+ const nameId = useId();
156
+ const descriptionId = useId();
157
+ const hasDescription = Children2.count(children) !== 0;
158
+ const nameElement = /* @__PURE__ */ React.createElement("span", {
159
+ className: "Filter-name"
160
+ }, name, hasDescription && ":");
161
+ return /* @__PURE__ */ React.createElement("div", {
162
+ className: "Filter-buttonContainer",
163
+ "data-test-id": testId
164
+ }, /* @__PURE__ */ React.createElement("button", {
165
+ ...rest,
166
+ "aria-labelledby": `${nameId} ${hasDescription ? descriptionId : ""}`,
167
+ "aria-haspopup": true,
168
+ className: cx3("Filter-button", className, {
169
+ "is-clearable": isClearable || isSelected
170
+ }),
171
+ ref,
172
+ onClick: onClickFilterButton
173
+ }, hideName ? /* @__PURE__ */ React.createElement(VisuallyHidden, {
174
+ id: nameId
175
+ }, nameElement) : /* @__PURE__ */ React.createElement("span", {
176
+ id: nameId
177
+ }, nameElement), hasDescription && /* @__PURE__ */ React.createElement("span", {
178
+ id: descriptionId,
179
+ className: "Filter-description"
180
+ }, children), !isClearable && /* @__PURE__ */ React.createElement(ExpandMore2, {
181
+ size: IconSize2.SMALL
182
+ })), isClearable && /* @__PURE__ */ React.createElement(Tooltip, {
183
+ targetClassName: "Filter-clearTooltip",
184
+ content: clearTooltip
185
+ }, /* @__PURE__ */ React.createElement(Button2, {
186
+ className: "Filter-clear",
187
+ size: ButtonSize.SMALL,
188
+ type: ButtonType.ICON,
189
+ icon: /* @__PURE__ */ React.createElement(Close, {
190
+ size: IconSize2.TINY
191
+ }),
192
+ onClick: onClear
193
+ })));
194
+ });
195
+ FilterButton.defaultProps = {
196
+ clearTooltip: "Clear filter"
197
+ };
198
+ FilterButton.displayName = "FilterButton";
199
+
200
+ // src/Filter.tsx
201
+ var SEARCH_INPUT_THRESHOLD2 = 4;
202
+ var Filter = ({
203
+ searchValue,
204
+ onSearchChange,
205
+ searchPlaceholder,
206
+ searchAriaLabel,
207
+ name,
208
+ hideName,
209
+ description,
210
+ options,
211
+ isClearable,
212
+ onClear,
213
+ isSelected,
214
+ className,
215
+ isEmpty,
216
+ isLoading,
217
+ onClickFilterButton,
218
+ disabledOptionTooltip,
219
+ testId,
220
+ size,
221
+ enableVirtualization,
222
+ ...props
223
+ }) => {
224
+ const enableSearch = onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD2 || !isEmpty);
225
+ const dropdownClasses = cx4("Filter", "Filter-target", className);
226
+ const handleClear = (event) => {
227
+ event.preventDefault();
228
+ onClear?.();
229
+ };
230
+ return /* @__PURE__ */ React.createElement(Dropdown2, {
231
+ targetClassName: dropdownClasses,
232
+ ...props
233
+ }, /* @__PURE__ */ React.createElement(FilterButton, {
234
+ isClearable,
235
+ onClear: handleClear,
236
+ name,
237
+ hideName,
238
+ isSelected,
239
+ onClickFilterButton,
240
+ testId
241
+ }, description), /* @__PURE__ */ React.createElement(FilterMenu, {
242
+ options,
243
+ searchValue,
244
+ searchPlaceholder,
245
+ searchAriaLabel,
246
+ enableSearch,
247
+ onSearchChange,
248
+ isLoading,
249
+ disabledOptionTooltip,
250
+ size,
251
+ enableVirtualization
252
+ }));
253
+ };
254
+ export {
255
+ AppliedFilter,
256
+ Filter,
257
+ FilterButton
258
+ };
259
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../scripts/react-shim.js", "../src/AppliedFilter.tsx", "../src/AppliedFilterButton.tsx", "../src/FilterMenu.tsx", "../src/Filter.tsx", "../src/FilterButton.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { FilterOption } from './FilterMenu';\nimport type { ReactNode } from 'react';\n\nimport { Dropdown } from '@launchpad-ui/dropdown';\nimport cx from 'clsx';\n\nimport { AppliedFilterButton } from './AppliedFilterButton';\nimport { FilterMenu } from './FilterMenu';\n\nconst SEARCH_INPUT_THRESHOLD = 4;\n\ntype AppliedFilterProps = {\n searchValue?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n onClearFilter?(): void;\n searchPlaceholder?: string;\n name?: ReactNode;\n description: ReactNode;\n options: FilterOption[];\n className?: string;\n onStateChange?({ isOpen }: { isOpen?: boolean }): void;\n isSelected?: boolean;\n onSelect?(item: FilterOption): void;\n isEmpty?: boolean;\n isLoading?: boolean;\n onClickFilterButton?(): void;\n searchAriaLabel?: string;\n};\n\nconst AppliedFilter = ({\n searchValue,\n onSearchChange,\n searchPlaceholder,\n name,\n description,\n options,\n className,\n isEmpty,\n isLoading,\n onClickFilterButton,\n onClearFilter,\n searchAriaLabel,\n ...props\n}: AppliedFilterProps) => {\n const enableSearch =\n onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);\n\n const dropdownClasses = cx('Filter-target', className);\n return (\n <Dropdown\n targetClassName={dropdownClasses}\n placement=\"bottom-start\"\n enableArrow={false}\n {...props}\n >\n <AppliedFilterButton name={name} onClickFilterButton={onClickFilterButton}>\n {description}\n </AppliedFilterButton>\n\n <FilterMenu\n options={options}\n searchValue={searchValue}\n searchPlaceholder={searchPlaceholder}\n enableSearch={enableSearch}\n searchAriaLabel={searchAriaLabel}\n onSearchChange={onSearchChange}\n onClearFilter={onClearFilter}\n isLoading={isLoading}\n />\n </Dropdown>\n );\n};\n\nexport type { AppliedFilterProps };\nexport { AppliedFilter };\n", "import type { ReactNode } from 'react';\n\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport cx from 'clsx';\nimport { Children, forwardRef } from 'react';\n\nimport './styles/Filter.css';\n\ntype AppliedFilterButtonProps = {\n name?: ReactNode;\n className?: string;\n isSelected?: boolean;\n children: ReactNode;\n onClickFilterButton?(): void;\n};\n\ntype Ref = HTMLButtonElement;\n\nconst AppliedFilterButton = forwardRef<Ref, AppliedFilterButtonProps>((props, ref) => {\n const { name, className, isSelected, children, onClickFilterButton } = props;\n\n const hasDescription = Children.count(children) !== 0;\n\n return (\n <div className=\"AppliedFilter-buttonContainer\">\n <button\n aria-haspopup\n className={cx(\n 'AppliedFilter-button',\n {\n isSelected,\n },\n className\n )}\n ref={ref}\n onClick={onClickFilterButton}\n >\n {name && (\n <span className=\"AppliedFilter-name\">\n {name}\n {hasDescription && ':'}\n </span>\n )}\n {hasDescription && <span className=\"AppliedFilter-description\">{children}</span>}\n <ExpandMore size={IconSize.SMALL} />\n </button>\n </div>\n );\n});\n\nAppliedFilterButton.displayName = 'AppliedFilterButton';\n\nexport type { AppliedFilterButtonProps };\nexport { AppliedFilterButton };\n", "import type { MenuProps } from '@launchpad-ui/menu';\nimport type { ReactNode } from 'react';\n\nimport { Button, ButtonKind } from '@launchpad-ui/button';\nimport { Check } from '@launchpad-ui/icons';\nimport { Menu, MenuDivider, MenuItem, MenuSearch } from '@launchpad-ui/menu';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype FilterOption<T = any> = {\n name?: ReactNode;\n isDisabled?: boolean;\n isDivider?: boolean;\n isChecked?: boolean;\n value: T | null;\n projKey?: string;\n nested?: boolean;\n groupHeader?: boolean;\n};\n\ntype FilterMenuProps = Pick<MenuProps<string>, 'enableVirtualization' | 'size'> & {\n options: FilterOption[];\n onClearFilter?(): void;\n enableSearch?: boolean;\n searchValue?: string;\n searchPlaceholder?: string;\n searchAriaLabel?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n onSelect?(): void;\n isLoading?: boolean;\n disabledOptionTooltip?: string;\n};\n\nconst FilterMenu = ({\n options,\n onClearFilter,\n enableSearch,\n searchValue,\n searchPlaceholder,\n searchAriaLabel,\n onSelect,\n onSearchChange,\n isLoading = false,\n disabledOptionTooltip,\n enableVirtualization,\n size,\n}: FilterMenuProps) => {\n const filterOptions = isLoading\n ? [{ name: 'loading...', value: 'loading...', isDisabled: true }]\n : options;\n\n return (\n <>\n {onClearFilter && (\n <Button tabIndex={0} className=\"Menu-clear\" onClick={onClearFilter} kind={ButtonKind.LINK}>\n CLEAR FILTER\n </Button>\n )}\n <Menu enableVirtualization={enableVirtualization} size={size} onSelect={onSelect}>\n {enableSearch && (\n <MenuSearch\n value={searchValue}\n placeholder={searchPlaceholder}\n onChange={onSearchChange}\n ariaLabel={searchAriaLabel}\n />\n )}\n {filterOptions.map((option, index) => {\n if (option.isDivider) {\n return <MenuDivider key={`divider-${index}`} />;\n }\n return (\n <MenuItem\n item={option}\n disabled={option.isDisabled}\n icon={option.isChecked ? Check : null}\n key={option.value}\n role=\"menuitemradio\"\n aria-checked={option.isChecked ? 'true' : undefined}\n nested={option.nested}\n groupHeader={option.groupHeader}\n tooltip={\n option.isDisabled && disabledOptionTooltip ? disabledOptionTooltip : undefined\n }\n tooltipPlacement=\"right\"\n >\n {option.name}\n </MenuItem>\n );\n })}\n </Menu>\n </>\n );\n};\n\nexport { FilterMenu };\nexport type { FilterOption, FilterMenuProps };\n", "import type { FilterOption } from './FilterMenu';\nimport type { MenuProps } from '@launchpad-ui/menu';\nimport type { ReactNode, SyntheticEvent } from 'react';\n\nimport { Dropdown } from '@launchpad-ui/dropdown';\nimport cx from 'clsx';\n\nimport { FilterButton } from './FilterButton';\nimport { FilterMenu } from './FilterMenu';\n\nconst SEARCH_INPUT_THRESHOLD = 4;\n\ntype FilterProps = Pick<MenuProps<string>, 'size' | 'enableVirtualization'> & {\n searchValue?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n searchPlaceholder?: string;\n searchAriaLabel?: string;\n name: ReactNode;\n hideName?: boolean;\n description: ReactNode;\n options: FilterOption[];\n isClearable?: boolean;\n onClear?(): void;\n className?: string;\n onStateChange?({ isOpen }: { isOpen?: boolean }): void;\n isSelected?: boolean;\n onSelect?(item: FilterOption): void;\n isEmpty?: boolean;\n isLoading?: boolean;\n onClickFilterButton?(): void;\n disabledOptionTooltip?: string;\n testId?: string;\n};\n\nconst Filter = ({\n searchValue,\n onSearchChange,\n searchPlaceholder,\n searchAriaLabel,\n name,\n hideName,\n description,\n options,\n isClearable,\n onClear,\n isSelected,\n className,\n isEmpty,\n isLoading,\n onClickFilterButton,\n disabledOptionTooltip,\n testId,\n size,\n enableVirtualization,\n ...props\n}: FilterProps) => {\n const enableSearch =\n onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);\n\n const dropdownClasses = cx('Filter', 'Filter-target', className);\n\n const handleClear = (event: SyntheticEvent) => {\n event.preventDefault();\n onClear?.();\n };\n\n return (\n <Dropdown targetClassName={dropdownClasses} {...props}>\n <FilterButton\n isClearable={isClearable}\n onClear={handleClear}\n name={name}\n hideName={hideName}\n isSelected={isSelected}\n onClickFilterButton={onClickFilterButton}\n testId={testId}\n >\n {description}\n </FilterButton>\n <FilterMenu\n options={options}\n searchValue={searchValue}\n searchPlaceholder={searchPlaceholder}\n searchAriaLabel={searchAriaLabel}\n enableSearch={enableSearch}\n onSearchChange={onSearchChange}\n isLoading={isLoading}\n disabledOptionTooltip={disabledOptionTooltip}\n size={size}\n enableVirtualization={enableVirtualization}\n />\n </Dropdown>\n );\n};\n\nexport { Filter };\nexport type { FilterProps };\n", "import type { ReactNode, SyntheticEvent } from 'react';\n\nimport { Button, ButtonSize, ButtonType } from '@launchpad-ui/button';\nimport { Close, ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { useId } from '@react-aria/utils';\nimport { VisuallyHidden } from '@react-aria/visually-hidden';\nimport cx from 'clsx';\nimport { Children, forwardRef } from 'react';\n\nimport './styles/Filter.css';\n\ntype FilterButtonProps = {\n name: ReactNode;\n hideName?: boolean;\n isClearable?: boolean;\n onClear?(event: SyntheticEvent): void;\n className?: string;\n isSelected?: boolean;\n clearTooltip?: string | JSX.Element;\n children?: ReactNode;\n onClickFilterButton?(): void;\n testId?: string;\n};\n\ntype Ref = HTMLButtonElement;\n\nconst FilterButton = forwardRef<Ref, FilterButtonProps>((props, ref) => {\n const {\n children,\n name,\n hideName,\n isClearable,\n clearTooltip,\n onClear,\n isSelected,\n onClickFilterButton,\n className,\n testId,\n ...rest\n } = props;\n const nameId = useId();\n const descriptionId = useId();\n\n const hasDescription = Children.count(children) !== 0;\n\n const nameElement = (\n <span className=\"Filter-name\">\n {name}\n {hasDescription && ':'}\n </span>\n );\n\n return (\n <div className=\"Filter-buttonContainer\" data-test-id={testId}>\n <button\n {...rest}\n aria-labelledby={`${nameId} ${hasDescription ? descriptionId : ''}`}\n aria-haspopup\n className={cx('Filter-button', className, {\n 'is-clearable': isClearable || isSelected,\n })}\n ref={ref}\n onClick={onClickFilterButton}\n >\n {hideName ? (\n <VisuallyHidden id={nameId}>{nameElement}</VisuallyHidden>\n ) : (\n <span id={nameId}>{nameElement}</span>\n )}\n {hasDescription && (\n <span id={descriptionId} className=\"Filter-description\">\n {children}\n </span>\n )}\n {!isClearable && <ExpandMore size={IconSize.SMALL} />}\n </button>\n {isClearable && (\n <Tooltip targetClassName=\"Filter-clearTooltip\" content={clearTooltip}>\n <Button\n className=\"Filter-clear\"\n size={ButtonSize.SMALL}\n type={ButtonType.ICON}\n icon={<Close size={IconSize.TINY} />}\n onClick={onClear}\n />\n </Tooltip>\n )}\n </div>\n );\n});\n\nFilterButton.defaultProps = {\n clearTooltip: 'Clear filter',\n};\n\nFilterButton.displayName = 'FilterButton';\n\nexport { FilterButton };\nexport type { FilterButtonProps };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.js ADDED
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/index.ts
24
+ var src_exports = {};
25
+ __export(src_exports, {
26
+ AppliedFilter: () => AppliedFilter,
27
+ Filter: () => Filter,
28
+ FilterButton: () => FilterButton
29
+ });
30
+ module.exports = __toCommonJS(src_exports);
31
+
32
+ // ../../scripts/react-shim.js
33
+ var React = __toESM(require("react"));
34
+
35
+ // src/AppliedFilter.tsx
36
+ var import_dropdown = require("@launchpad-ui/dropdown");
37
+ var import_clsx2 = __toESM(require("clsx"));
38
+
39
+ // src/AppliedFilterButton.tsx
40
+ var import_icons = require("@launchpad-ui/icons");
41
+ var import_clsx = __toESM(require("clsx"));
42
+ var import_react = require("react");
43
+ var import_Filter = require("./styles/Filter.css");
44
+ var AppliedFilterButton = (0, import_react.forwardRef)((props, ref) => {
45
+ const { name, className, isSelected, children, onClickFilterButton } = props;
46
+ const hasDescription = import_react.Children.count(children) !== 0;
47
+ return /* @__PURE__ */ React.createElement("div", {
48
+ className: "AppliedFilter-buttonContainer"
49
+ }, /* @__PURE__ */ React.createElement("button", {
50
+ "aria-haspopup": true,
51
+ className: (0, import_clsx.default)("AppliedFilter-button", {
52
+ isSelected
53
+ }, className),
54
+ ref,
55
+ onClick: onClickFilterButton
56
+ }, name && /* @__PURE__ */ React.createElement("span", {
57
+ className: "AppliedFilter-name"
58
+ }, name, hasDescription && ":"), hasDescription && /* @__PURE__ */ React.createElement("span", {
59
+ className: "AppliedFilter-description"
60
+ }, children), /* @__PURE__ */ React.createElement(import_icons.ExpandMore, {
61
+ size: import_icons.IconSize.SMALL
62
+ })));
63
+ });
64
+ AppliedFilterButton.displayName = "AppliedFilterButton";
65
+
66
+ // src/FilterMenu.tsx
67
+ var import_button = require("@launchpad-ui/button");
68
+ var import_icons2 = require("@launchpad-ui/icons");
69
+ var import_menu = require("@launchpad-ui/menu");
70
+ var FilterMenu = ({
71
+ options,
72
+ onClearFilter,
73
+ enableSearch,
74
+ searchValue,
75
+ searchPlaceholder,
76
+ searchAriaLabel,
77
+ onSelect,
78
+ onSearchChange,
79
+ isLoading = false,
80
+ disabledOptionTooltip,
81
+ enableVirtualization,
82
+ size
83
+ }) => {
84
+ const filterOptions = isLoading ? [{ name: "loading...", value: "loading...", isDisabled: true }] : options;
85
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, onClearFilter && /* @__PURE__ */ React.createElement(import_button.Button, {
86
+ tabIndex: 0,
87
+ className: "Menu-clear",
88
+ onClick: onClearFilter,
89
+ kind: import_button.ButtonKind.LINK
90
+ }, "CLEAR FILTER"), /* @__PURE__ */ React.createElement(import_menu.Menu, {
91
+ enableVirtualization,
92
+ size,
93
+ onSelect
94
+ }, enableSearch && /* @__PURE__ */ React.createElement(import_menu.MenuSearch, {
95
+ value: searchValue,
96
+ placeholder: searchPlaceholder,
97
+ onChange: onSearchChange,
98
+ ariaLabel: searchAriaLabel
99
+ }), filterOptions.map((option, index) => {
100
+ if (option.isDivider) {
101
+ return /* @__PURE__ */ React.createElement(import_menu.MenuDivider, {
102
+ key: `divider-${index}`
103
+ });
104
+ }
105
+ return /* @__PURE__ */ React.createElement(import_menu.MenuItem, {
106
+ item: option,
107
+ disabled: option.isDisabled,
108
+ icon: option.isChecked ? import_icons2.Check : null,
109
+ key: option.value,
110
+ role: "menuitemradio",
111
+ "aria-checked": option.isChecked ? "true" : void 0,
112
+ nested: option.nested,
113
+ groupHeader: option.groupHeader,
114
+ tooltip: option.isDisabled && disabledOptionTooltip ? disabledOptionTooltip : void 0,
115
+ tooltipPlacement: "right"
116
+ }, option.name);
117
+ })));
118
+ };
119
+
120
+ // src/AppliedFilter.tsx
121
+ var SEARCH_INPUT_THRESHOLD = 4;
122
+ var AppliedFilter = ({
123
+ searchValue,
124
+ onSearchChange,
125
+ searchPlaceholder,
126
+ name,
127
+ description,
128
+ options,
129
+ className,
130
+ isEmpty,
131
+ isLoading,
132
+ onClickFilterButton,
133
+ onClearFilter,
134
+ searchAriaLabel,
135
+ ...props
136
+ }) => {
137
+ const enableSearch = onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);
138
+ const dropdownClasses = (0, import_clsx2.default)("Filter-target", className);
139
+ return /* @__PURE__ */ React.createElement(import_dropdown.Dropdown, {
140
+ targetClassName: dropdownClasses,
141
+ placement: "bottom-start",
142
+ enableArrow: false,
143
+ ...props
144
+ }, /* @__PURE__ */ React.createElement(AppliedFilterButton, {
145
+ name,
146
+ onClickFilterButton
147
+ }, description), /* @__PURE__ */ React.createElement(FilterMenu, {
148
+ options,
149
+ searchValue,
150
+ searchPlaceholder,
151
+ enableSearch,
152
+ searchAriaLabel,
153
+ onSearchChange,
154
+ onClearFilter,
155
+ isLoading
156
+ }));
157
+ };
158
+
159
+ // src/Filter.tsx
160
+ var import_dropdown2 = require("@launchpad-ui/dropdown");
161
+ var import_clsx4 = __toESM(require("clsx"));
162
+
163
+ // src/FilterButton.tsx
164
+ var import_button2 = require("@launchpad-ui/button");
165
+ var import_icons3 = require("@launchpad-ui/icons");
166
+ var import_tooltip = require("@launchpad-ui/tooltip");
167
+ var import_utils = require("@react-aria/utils");
168
+ var import_visually_hidden = require("@react-aria/visually-hidden");
169
+ var import_clsx3 = __toESM(require("clsx"));
170
+ var import_react2 = require("react");
171
+ var import_Filter2 = require("./styles/Filter.css");
172
+ var FilterButton = (0, import_react2.forwardRef)((props, ref) => {
173
+ const {
174
+ children,
175
+ name,
176
+ hideName,
177
+ isClearable,
178
+ clearTooltip,
179
+ onClear,
180
+ isSelected,
181
+ onClickFilterButton,
182
+ className,
183
+ testId,
184
+ ...rest
185
+ } = props;
186
+ const nameId = (0, import_utils.useId)();
187
+ const descriptionId = (0, import_utils.useId)();
188
+ const hasDescription = import_react2.Children.count(children) !== 0;
189
+ const nameElement = /* @__PURE__ */ React.createElement("span", {
190
+ className: "Filter-name"
191
+ }, name, hasDescription && ":");
192
+ return /* @__PURE__ */ React.createElement("div", {
193
+ className: "Filter-buttonContainer",
194
+ "data-test-id": testId
195
+ }, /* @__PURE__ */ React.createElement("button", {
196
+ ...rest,
197
+ "aria-labelledby": `${nameId} ${hasDescription ? descriptionId : ""}`,
198
+ "aria-haspopup": true,
199
+ className: (0, import_clsx3.default)("Filter-button", className, {
200
+ "is-clearable": isClearable || isSelected
201
+ }),
202
+ ref,
203
+ onClick: onClickFilterButton
204
+ }, hideName ? /* @__PURE__ */ React.createElement(import_visually_hidden.VisuallyHidden, {
205
+ id: nameId
206
+ }, nameElement) : /* @__PURE__ */ React.createElement("span", {
207
+ id: nameId
208
+ }, nameElement), hasDescription && /* @__PURE__ */ React.createElement("span", {
209
+ id: descriptionId,
210
+ className: "Filter-description"
211
+ }, children), !isClearable && /* @__PURE__ */ React.createElement(import_icons3.ExpandMore, {
212
+ size: import_icons3.IconSize.SMALL
213
+ })), isClearable && /* @__PURE__ */ React.createElement(import_tooltip.Tooltip, {
214
+ targetClassName: "Filter-clearTooltip",
215
+ content: clearTooltip
216
+ }, /* @__PURE__ */ React.createElement(import_button2.Button, {
217
+ className: "Filter-clear",
218
+ size: import_button2.ButtonSize.SMALL,
219
+ type: import_button2.ButtonType.ICON,
220
+ icon: /* @__PURE__ */ React.createElement(import_icons3.Close, {
221
+ size: import_icons3.IconSize.TINY
222
+ }),
223
+ onClick: onClear
224
+ })));
225
+ });
226
+ FilterButton.defaultProps = {
227
+ clearTooltip: "Clear filter"
228
+ };
229
+ FilterButton.displayName = "FilterButton";
230
+
231
+ // src/Filter.tsx
232
+ var SEARCH_INPUT_THRESHOLD2 = 4;
233
+ var Filter = ({
234
+ searchValue,
235
+ onSearchChange,
236
+ searchPlaceholder,
237
+ searchAriaLabel,
238
+ name,
239
+ hideName,
240
+ description,
241
+ options,
242
+ isClearable,
243
+ onClear,
244
+ isSelected,
245
+ className,
246
+ isEmpty,
247
+ isLoading,
248
+ onClickFilterButton,
249
+ disabledOptionTooltip,
250
+ testId,
251
+ size,
252
+ enableVirtualization,
253
+ ...props
254
+ }) => {
255
+ const enableSearch = onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD2 || !isEmpty);
256
+ const dropdownClasses = (0, import_clsx4.default)("Filter", "Filter-target", className);
257
+ const handleClear = (event) => {
258
+ event.preventDefault();
259
+ onClear?.();
260
+ };
261
+ return /* @__PURE__ */ React.createElement(import_dropdown2.Dropdown, {
262
+ targetClassName: dropdownClasses,
263
+ ...props
264
+ }, /* @__PURE__ */ React.createElement(FilterButton, {
265
+ isClearable,
266
+ onClear: handleClear,
267
+ name,
268
+ hideName,
269
+ isSelected,
270
+ onClickFilterButton,
271
+ testId
272
+ }, description), /* @__PURE__ */ React.createElement(FilterMenu, {
273
+ options,
274
+ searchValue,
275
+ searchPlaceholder,
276
+ searchAriaLabel,
277
+ enableSearch,
278
+ onSearchChange,
279
+ isLoading,
280
+ disabledOptionTooltip,
281
+ size,
282
+ enableVirtualization
283
+ }));
284
+ };
285
+ // Annotate the CommonJS export names for ESM import in node:
286
+ 0 && (module.exports = {
287
+ AppliedFilter,
288
+ Filter,
289
+ FilterButton
290
+ });
291
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../../../scripts/react-shim.js", "../src/AppliedFilter.tsx", "../src/AppliedFilterButton.tsx", "../src/FilterMenu.tsx", "../src/Filter.tsx", "../src/FilterButton.tsx"],
4
+ "sourcesContent": ["export type { AppliedFilterProps } from './AppliedFilter';\nexport type { FilterProps } from './Filter';\nexport type { FilterButtonProps } from './FilterButton';\nexport type { FilterOption } from './FilterMenu';\nexport { AppliedFilter } from './AppliedFilter';\nexport { Filter } from './Filter';\nexport { FilterButton } from './FilterButton';\n", "import * as React from 'react';\nexport { React };\n", "import type { FilterOption } from './FilterMenu';\nimport type { ReactNode } from 'react';\n\nimport { Dropdown } from '@launchpad-ui/dropdown';\nimport cx from 'clsx';\n\nimport { AppliedFilterButton } from './AppliedFilterButton';\nimport { FilterMenu } from './FilterMenu';\n\nconst SEARCH_INPUT_THRESHOLD = 4;\n\ntype AppliedFilterProps = {\n searchValue?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n onClearFilter?(): void;\n searchPlaceholder?: string;\n name?: ReactNode;\n description: ReactNode;\n options: FilterOption[];\n className?: string;\n onStateChange?({ isOpen }: { isOpen?: boolean }): void;\n isSelected?: boolean;\n onSelect?(item: FilterOption): void;\n isEmpty?: boolean;\n isLoading?: boolean;\n onClickFilterButton?(): void;\n searchAriaLabel?: string;\n};\n\nconst AppliedFilter = ({\n searchValue,\n onSearchChange,\n searchPlaceholder,\n name,\n description,\n options,\n className,\n isEmpty,\n isLoading,\n onClickFilterButton,\n onClearFilter,\n searchAriaLabel,\n ...props\n}: AppliedFilterProps) => {\n const enableSearch =\n onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);\n\n const dropdownClasses = cx('Filter-target', className);\n return (\n <Dropdown\n targetClassName={dropdownClasses}\n placement=\"bottom-start\"\n enableArrow={false}\n {...props}\n >\n <AppliedFilterButton name={name} onClickFilterButton={onClickFilterButton}>\n {description}\n </AppliedFilterButton>\n\n <FilterMenu\n options={options}\n searchValue={searchValue}\n searchPlaceholder={searchPlaceholder}\n enableSearch={enableSearch}\n searchAriaLabel={searchAriaLabel}\n onSearchChange={onSearchChange}\n onClearFilter={onClearFilter}\n isLoading={isLoading}\n />\n </Dropdown>\n );\n};\n\nexport type { AppliedFilterProps };\nexport { AppliedFilter };\n", "import type { ReactNode } from 'react';\n\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport cx from 'clsx';\nimport { Children, forwardRef } from 'react';\n\nimport './styles/Filter.css';\n\ntype AppliedFilterButtonProps = {\n name?: ReactNode;\n className?: string;\n isSelected?: boolean;\n children: ReactNode;\n onClickFilterButton?(): void;\n};\n\ntype Ref = HTMLButtonElement;\n\nconst AppliedFilterButton = forwardRef<Ref, AppliedFilterButtonProps>((props, ref) => {\n const { name, className, isSelected, children, onClickFilterButton } = props;\n\n const hasDescription = Children.count(children) !== 0;\n\n return (\n <div className=\"AppliedFilter-buttonContainer\">\n <button\n aria-haspopup\n className={cx(\n 'AppliedFilter-button',\n {\n isSelected,\n },\n className\n )}\n ref={ref}\n onClick={onClickFilterButton}\n >\n {name && (\n <span className=\"AppliedFilter-name\">\n {name}\n {hasDescription && ':'}\n </span>\n )}\n {hasDescription && <span className=\"AppliedFilter-description\">{children}</span>}\n <ExpandMore size={IconSize.SMALL} />\n </button>\n </div>\n );\n});\n\nAppliedFilterButton.displayName = 'AppliedFilterButton';\n\nexport type { AppliedFilterButtonProps };\nexport { AppliedFilterButton };\n", "import type { MenuProps } from '@launchpad-ui/menu';\nimport type { ReactNode } from 'react';\n\nimport { Button, ButtonKind } from '@launchpad-ui/button';\nimport { Check } from '@launchpad-ui/icons';\nimport { Menu, MenuDivider, MenuItem, MenuSearch } from '@launchpad-ui/menu';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype FilterOption<T = any> = {\n name?: ReactNode;\n isDisabled?: boolean;\n isDivider?: boolean;\n isChecked?: boolean;\n value: T | null;\n projKey?: string;\n nested?: boolean;\n groupHeader?: boolean;\n};\n\ntype FilterMenuProps = Pick<MenuProps<string>, 'enableVirtualization' | 'size'> & {\n options: FilterOption[];\n onClearFilter?(): void;\n enableSearch?: boolean;\n searchValue?: string;\n searchPlaceholder?: string;\n searchAriaLabel?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n onSelect?(): void;\n isLoading?: boolean;\n disabledOptionTooltip?: string;\n};\n\nconst FilterMenu = ({\n options,\n onClearFilter,\n enableSearch,\n searchValue,\n searchPlaceholder,\n searchAriaLabel,\n onSelect,\n onSearchChange,\n isLoading = false,\n disabledOptionTooltip,\n enableVirtualization,\n size,\n}: FilterMenuProps) => {\n const filterOptions = isLoading\n ? [{ name: 'loading...', value: 'loading...', isDisabled: true }]\n : options;\n\n return (\n <>\n {onClearFilter && (\n <Button tabIndex={0} className=\"Menu-clear\" onClick={onClearFilter} kind={ButtonKind.LINK}>\n CLEAR FILTER\n </Button>\n )}\n <Menu enableVirtualization={enableVirtualization} size={size} onSelect={onSelect}>\n {enableSearch && (\n <MenuSearch\n value={searchValue}\n placeholder={searchPlaceholder}\n onChange={onSearchChange}\n ariaLabel={searchAriaLabel}\n />\n )}\n {filterOptions.map((option, index) => {\n if (option.isDivider) {\n return <MenuDivider key={`divider-${index}`} />;\n }\n return (\n <MenuItem\n item={option}\n disabled={option.isDisabled}\n icon={option.isChecked ? Check : null}\n key={option.value}\n role=\"menuitemradio\"\n aria-checked={option.isChecked ? 'true' : undefined}\n nested={option.nested}\n groupHeader={option.groupHeader}\n tooltip={\n option.isDisabled && disabledOptionTooltip ? disabledOptionTooltip : undefined\n }\n tooltipPlacement=\"right\"\n >\n {option.name}\n </MenuItem>\n );\n })}\n </Menu>\n </>\n );\n};\n\nexport { FilterMenu };\nexport type { FilterOption, FilterMenuProps };\n", "import type { FilterOption } from './FilterMenu';\nimport type { MenuProps } from '@launchpad-ui/menu';\nimport type { ReactNode, SyntheticEvent } from 'react';\n\nimport { Dropdown } from '@launchpad-ui/dropdown';\nimport cx from 'clsx';\n\nimport { FilterButton } from './FilterButton';\nimport { FilterMenu } from './FilterMenu';\n\nconst SEARCH_INPUT_THRESHOLD = 4;\n\ntype FilterProps = Pick<MenuProps<string>, 'size' | 'enableVirtualization'> & {\n searchValue?: string;\n onSearchChange?(event: React.ChangeEvent<HTMLInputElement>): void;\n searchPlaceholder?: string;\n searchAriaLabel?: string;\n name: ReactNode;\n hideName?: boolean;\n description: ReactNode;\n options: FilterOption[];\n isClearable?: boolean;\n onClear?(): void;\n className?: string;\n onStateChange?({ isOpen }: { isOpen?: boolean }): void;\n isSelected?: boolean;\n onSelect?(item: FilterOption): void;\n isEmpty?: boolean;\n isLoading?: boolean;\n onClickFilterButton?(): void;\n disabledOptionTooltip?: string;\n testId?: string;\n};\n\nconst Filter = ({\n searchValue,\n onSearchChange,\n searchPlaceholder,\n searchAriaLabel,\n name,\n hideName,\n description,\n options,\n isClearable,\n onClear,\n isSelected,\n className,\n isEmpty,\n isLoading,\n onClickFilterButton,\n disabledOptionTooltip,\n testId,\n size,\n enableVirtualization,\n ...props\n}: FilterProps) => {\n const enableSearch =\n onSearchChange && (!!searchValue || options.length > SEARCH_INPUT_THRESHOLD || !isEmpty);\n\n const dropdownClasses = cx('Filter', 'Filter-target', className);\n\n const handleClear = (event: SyntheticEvent) => {\n event.preventDefault();\n onClear?.();\n };\n\n return (\n <Dropdown targetClassName={dropdownClasses} {...props}>\n <FilterButton\n isClearable={isClearable}\n onClear={handleClear}\n name={name}\n hideName={hideName}\n isSelected={isSelected}\n onClickFilterButton={onClickFilterButton}\n testId={testId}\n >\n {description}\n </FilterButton>\n <FilterMenu\n options={options}\n searchValue={searchValue}\n searchPlaceholder={searchPlaceholder}\n searchAriaLabel={searchAriaLabel}\n enableSearch={enableSearch}\n onSearchChange={onSearchChange}\n isLoading={isLoading}\n disabledOptionTooltip={disabledOptionTooltip}\n size={size}\n enableVirtualization={enableVirtualization}\n />\n </Dropdown>\n );\n};\n\nexport { Filter };\nexport type { FilterProps };\n", "import type { ReactNode, SyntheticEvent } from 'react';\n\nimport { Button, ButtonSize, ButtonType } from '@launchpad-ui/button';\nimport { Close, ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { useId } from '@react-aria/utils';\nimport { VisuallyHidden } from '@react-aria/visually-hidden';\nimport cx from 'clsx';\nimport { Children, forwardRef } from 'react';\n\nimport './styles/Filter.css';\n\ntype FilterButtonProps = {\n name: ReactNode;\n hideName?: boolean;\n isClearable?: boolean;\n onClear?(event: SyntheticEvent): void;\n className?: string;\n isSelected?: boolean;\n clearTooltip?: string | JSX.Element;\n children?: ReactNode;\n onClickFilterButton?(): void;\n testId?: string;\n};\n\ntype Ref = HTMLButtonElement;\n\nconst FilterButton = forwardRef<Ref, FilterButtonProps>((props, ref) => {\n const {\n children,\n name,\n hideName,\n isClearable,\n clearTooltip,\n onClear,\n isSelected,\n onClickFilterButton,\n className,\n testId,\n ...rest\n } = props;\n const nameId = useId();\n const descriptionId = useId();\n\n const hasDescription = Children.count(children) !== 0;\n\n const nameElement = (\n <span className=\"Filter-name\">\n {name}\n {hasDescription && ':'}\n </span>\n );\n\n return (\n <div className=\"Filter-buttonContainer\" data-test-id={testId}>\n <button\n {...rest}\n aria-labelledby={`${nameId} ${hasDescription ? descriptionId : ''}`}\n aria-haspopup\n className={cx('Filter-button', className, {\n 'is-clearable': isClearable || isSelected,\n })}\n ref={ref}\n onClick={onClickFilterButton}\n >\n {hideName ? (\n <VisuallyHidden id={nameId}>{nameElement}</VisuallyHidden>\n ) : (\n <span id={nameId}>{nameElement}</span>\n )}\n {hasDescription && (\n <span id={descriptionId} className=\"Filter-description\">\n {children}\n </span>\n )}\n {!isClearable && <ExpandMore size={IconSize.SMALL} />}\n </button>\n {isClearable && (\n <Tooltip targetClassName=\"Filter-clearTooltip\" content={clearTooltip}>\n <Button\n className=\"Filter-clear\"\n size={ButtonSize.SMALL}\n type={ButtonType.ICON}\n icon={<Close size={IconSize.TINY} />}\n onClick={onClear}\n />\n </Tooltip>\n )}\n </div>\n );\n});\n\nFilterButton.defaultProps = {\n clearTooltip: 'Clear filter',\n};\n\nFilterButton.displayName = 'FilterButton';\n\nexport { FilterButton };\nexport type { FilterButtonProps };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ .Filter{font-family:var(--font-family-base)}.Filter-buttonContainer{cursor:pointer;align-items:center;display:inline-flex;position:relative}.Filter-button{cursor:pointer;border-radius:var(--border-radius);color:var(--color-text);background-color:var(--color-white);align-items:center;margin:0;padding-top:0;padding-bottom:0;line-height:3.2rem;display:flex}.AppliedFilter-button{color:var(--color-text);height:2rem;background-color:var(--color-gray-100);border-radius:.2rem;padding:.2rem .6rem;display:flex}.Filter-button,.AppliedFilter-button{cursor:pointer;border-style:solid;border-width:1px;border-color:var(--color-white);font-family:inherit;font-size:1.3rem}:is(.Filter-button,.AppliedFilter-button):hover{background-color:var(--color-background-hover);border-color:var(--color-border)}:is(.Filter-button,.AppliedFilter-button):focus{box-shadow:0 0 0 2px var(--color-white),0 0 0 4px var(--color-focus);border-color:var(--color-border);outline:none}:is(.Filter-button,.AppliedFilter-button):focus:not(:focus-visible){box-shadow:unset;border-color:var(--color-white)}.is-clearable{background-color:var(--color-blue-200);padding-right:3.1rem}.Filter-name{font-weight:var(--font-weight-medium);margin-right:.5rem}.AppliedFilter-name{margin-right:.3rem}.Filter-description{color:var(--color-text);font-weight:var(--font-weight-medium)}.Filter-button .Filter-description,.AppliedFilter-button .AppliedFilter-description{max-width:16rem;text-overflow:ellipsis;white-space:nowrap;margin-right:.5rem;overflow:hidden}.Filter-description .Gravatar:first-child{margin-right:.5rem}.Filter-clear{cursor:pointer;padding:.3rem}.Filter-target--usage{border:1px solid var(--color-text-subtle-secondary)}.Filter-button.is-clearable{background-color:var(--color-blue-200);padding-right:3.1rem}.Filter-button.is-clearable:focus,.Filter-button.is-clearable:hover,.Filter-button.is-clearable:active{background-color:var(--color-blue-300)}.Filter-button.is-clearable:focus:not(:focus-visible){background-color:unset}.Filter-button.is-clearable:focus:not(:focus-visible):hover{background-color:var(--color-blue-300)}.Filter-button:hover:not(.is-clearable),.Filter-button:focus:not(.is-clearable),.Popover-target--active .Filter-button:not(.is-clearable){background-color:var(--color-background-hover);border-color:var(--color-text-subtle-secondary)}.Filter-button:focus:not(:focus-visible):not(.is-clearable):hover{background-color:var(--color-background-hover)}.Filter-clearTooltip{line-height:1;position:absolute;right:.7rem}
2
+ /*# sourceMappingURL=Filter.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":null,"mappings":"AAAA,4CAIA,gGAOA,wNAaA,sJASA,6JASE,gIAKA,mKAMA,qHAMF,0EAKA,sEAKA,uCAIA,kFAKA,iLASA,6DAIA,2CAKA,0EAIA,wFAIE,8IAOF,6EAGE,mGAKF,yOAQE,iHAKF","sources":["src/styles/Filter.css"],"sourcesContent":[".Filter {\n font-family: var(--font-family-base);\n}\n\n.Filter-buttonContainer {\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n position: relative;\n}\n\n.Filter-button {\n cursor: pointer;\n border-radius: var(--border-radius);\n padding-top: 0;\n padding-bottom: 0;\n line-height: 3.2rem;\n display: flex;\n align-items: center;\n margin: 0;\n color: var(--color-text);\n background-color: var(--color-white);\n}\n\n.AppliedFilter-button {\n color: var(--color-text);\n height: 2rem;\n background-color: var(--color-gray-100);\n padding: 0.2rem 0.6rem;\n border-radius: 0.2rem;\n display: flex;\n}\n\n.Filter-button,\n.AppliedFilter-button {\n font-family: inherit;\n font-size: 1.3rem;\n cursor: pointer;\n border-width: 1px;\n border-style: solid;\n border-color: var(--color-white);\n\n &:hover {\n background-color: var(--color-background-hover);\n border-color: var(--color-border);\n }\n\n &:focus {\n box-shadow: 0 0 0 2px var(--color-white), 0 0 0 4px var(--color-focus);\n border-color: var(--color-border);\n outline: none;\n }\n\n &:focus:not(:focus-visible) {\n box-shadow: unset;\n border-color: var(--color-white);\n }\n}\n\n.is-clearable {\n background-color: var(--color-blue-200);\n padding-right: 3.1rem;\n}\n\n.Filter-name {\n margin-right: 0.5rem;\n font-weight: var(--font-weight-medium);\n}\n\n.AppliedFilter-name {\n margin-right: 0.3rem;\n}\n\n.Filter-description {\n color: var(--color-text);\n font-weight: var(--font-weight-medium);\n}\n\n.Filter-button .Filter-description,\n.AppliedFilter-button .AppliedFilter-description {\n margin-right: 0.5rem;\n max-width: 16rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.Filter-description .Gravatar:first-child {\n margin-right: 0.5rem;\n}\n\n.Filter-clear {\n cursor: pointer;\n padding: 0.3rem;\n}\n\n.Filter-target--usage {\n border: 1px solid var(--color-text-subtle-secondary);\n}\n\n.Filter-button.is-clearable {\n background-color: var(--color-blue-200);\n padding-right: 3.1rem;\n\n &:focus,\n &:hover,\n &:active {\n background-color: var(--color-blue-300);\n }\n}\n\n.Filter-button.is-clearable:focus:not(:focus-visible) {\n background-color: unset;\n\n &:hover {\n background-color: var(--color-blue-300);\n }\n}\n\n.Filter-button:hover:not(.is-clearable),\n.Filter-button:focus:not(.is-clearable),\n.Popover-target--active .Filter-button:not(.is-clearable) {\n background-color: var(--color-background-hover);\n border-color: var(--color-text-subtle-secondary);\n}\n\n.Filter-button:focus:not(:focus-visible):not(.is-clearable) {\n &:hover {\n background-color: var(--color-background-hover);\n }\n}\n\n.Filter-clearTooltip {\n line-height: 1;\n position: absolute;\n right: 0.7rem;\n}\n"],"names":[]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@launchpad-ui/filter",
3
+ "version": "0.1.0",
4
+ "status": "beta",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "description": "filter a list of results",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "main": "dist/index.js",
13
+ "module": "dist/index.es.js",
14
+ "types": "dist/index.d.ts",
15
+ "sideEffects": [
16
+ "**/*.css"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.es.js",
22
+ "require": "./dist/index.js"
23
+ },
24
+ "./package.json": "./package.json",
25
+ "./styles/*": "./dist/styles/*"
26
+ },
27
+ "source": "src/index.ts",
28
+ "dependencies": {
29
+ "@launchpad-ui/button": "~0.3.2",
30
+ "@launchpad-ui/dropdown": "~0.2.8",
31
+ "@launchpad-ui/icons": "~0.2.4",
32
+ "@launchpad-ui/menu": "~0.3.6",
33
+ "@launchpad-ui/tokens": "~0.1.5",
34
+ "@launchpad-ui/tooltip": "~0.3.8",
35
+ "@react-aria/utils": "^3.13.1",
36
+ "@react-aria/visually-hidden": "^3.4.0",
37
+ "clsx": "^1.2.0"
38
+ },
39
+ "peerDependencies": {
40
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
41
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "react": "^18.2.0",
45
+ "react-dom": "^18.2.0"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc --project tsconfig.build.json && node ../../scripts/build.js",
49
+ "clean": "rm -rf dist",
50
+ "e2e": "playwright test --config=../../playwright.config.ct.ts",
51
+ "lint": "eslint '**/*.{ts,tsx,js}' && stylelint '**/*.css' --ignore-path ../../.stylelintignore",
52
+ "test": "vitest run --coverage"
53
+ }
54
+ }