@khanacademy/wonder-blocks-dropdown 4.0.0 → 5.0.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/CHANGELOG.md +21 -0
- package/dist/components/check.d.ts +0 -6
- package/dist/components/checkbox.d.ts +0 -6
- package/dist/components/dropdown-opener.d.ts +2 -2
- package/dist/components/option-item.d.ts +34 -2
- package/dist/components/select-opener.d.ts +2 -1
- package/dist/es/index.js +191 -116
- package/dist/index.js +189 -114
- package/dist/util/dropdown-menu-styles.d.ts +0 -10
- package/dist/util/helpers.d.ts +8 -0
- package/dist/util/popper-max-height-modifier.d.ts +17 -0
- package/dist/util/types.d.ts +11 -1
- package/package.json +10 -10
- package/src/components/__tests__/dropdown-core.test.tsx +1 -1
- package/src/components/__tests__/dropdown-popper.test.tsx +33 -3
- package/src/components/__tests__/multi-select.test.tsx +42 -1
- package/src/components/__tests__/option-item.test.tsx +86 -0
- package/src/components/__tests__/single-select.test.tsx +15 -9
- package/src/components/check.tsx +6 -19
- package/src/components/checkbox.tsx +10 -30
- package/src/components/dropdown-core.tsx +21 -17
- package/src/components/dropdown-opener.tsx +2 -2
- package/src/components/dropdown-popper.tsx +2 -0
- package/src/components/multi-select.tsx +17 -4
- package/src/components/option-item.tsx +182 -69
- package/src/components/select-opener.tsx +2 -1
- package/src/components/single-select.tsx +5 -2
- package/src/util/__tests__/{helpers.test.ts → helpers.test.tsx} +50 -1
- package/src/util/constants.ts +1 -1
- package/src/util/dropdown-menu-styles.ts +0 -26
- package/src/util/helpers.ts +27 -0
- package/src/util/popper-max-height-modifier.ts +57 -0
- package/src/util/types.ts +13 -1
- package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-dropdown
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 56a896c6: Allow custom OptionItem elements (internally using cell components)
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 70e846cb: Allow changing the popper's height to accomodate for the viewport size
|
|
12
|
+
- Updated dependencies [56a896c6]
|
|
13
|
+
- Updated dependencies [23ab9f8c]
|
|
14
|
+
- Updated dependencies [6df21f71]
|
|
15
|
+
- @khanacademy/wonder-blocks-cell@3.2.0
|
|
16
|
+
- @khanacademy/wonder-blocks-icon@4.0.1
|
|
17
|
+
- @khanacademy/wonder-blocks-core@6.3.1
|
|
18
|
+
- @khanacademy/wonder-blocks-search-field@2.1.26
|
|
19
|
+
- @khanacademy/wonder-blocks-clickable@4.0.12
|
|
20
|
+
- @khanacademy/wonder-blocks-layout@2.0.25
|
|
21
|
+
- @khanacademy/wonder-blocks-modal@4.0.39
|
|
22
|
+
- @khanacademy/wonder-blocks-typography@2.1.10
|
|
23
|
+
|
|
3
24
|
## 4.0.0
|
|
4
25
|
|
|
5
26
|
### Major Changes
|
|
@@ -8,12 +8,6 @@ type CheckProps = {
|
|
|
8
8
|
disabled: boolean;
|
|
9
9
|
/** Whether option item is selected. */
|
|
10
10
|
selected: boolean;
|
|
11
|
-
/** Whether option item is pressed. */
|
|
12
|
-
pressed: boolean;
|
|
13
|
-
/** Whether option item is hovered. */
|
|
14
|
-
hovered: boolean;
|
|
15
|
-
/** Whether option item is focused. */
|
|
16
|
-
focused: boolean;
|
|
17
11
|
};
|
|
18
12
|
/**
|
|
19
13
|
* The check component used by OptionItem.
|
|
@@ -8,12 +8,6 @@ type CheckProps = {
|
|
|
8
8
|
disabled: boolean;
|
|
9
9
|
/** Whether option item is selected. */
|
|
10
10
|
selected: boolean;
|
|
11
|
-
/** Whether option item is pressed. */
|
|
12
|
-
pressed: boolean;
|
|
13
|
-
/** Whether option item is hovered. */
|
|
14
|
-
hovered: boolean;
|
|
15
|
-
/** Whether option item is focused. */
|
|
16
|
-
focused: boolean;
|
|
17
11
|
};
|
|
18
12
|
/**
|
|
19
13
|
* The checkbox component used by OptionItem.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { AriaProps } from "@khanacademy/wonder-blocks-core";
|
|
3
3
|
import type { ChildrenProps, ClickableState } from "@khanacademy/wonder-blocks-clickable";
|
|
4
|
-
import type { OpenerProps } from "../util/types";
|
|
4
|
+
import type { OpenerProps, OptionLabel } from "../util/types";
|
|
5
5
|
type Props = Partial<Omit<AriaProps, "aria-disabled">> & {
|
|
6
6
|
/**
|
|
7
7
|
* The child function that returns the anchor the Dropdown will be activated
|
|
@@ -26,7 +26,7 @@ type Props = Partial<Omit<AriaProps, "aria-disabled">> & {
|
|
|
26
26
|
/**
|
|
27
27
|
* Text for the opener that can be passed to the child as an argument.
|
|
28
28
|
*/
|
|
29
|
-
text:
|
|
29
|
+
text: OptionLabel;
|
|
30
30
|
};
|
|
31
31
|
type DefaultProps = {
|
|
32
32
|
disabled: Props["disabled"];
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
|
|
3
3
|
import Check from "./check";
|
|
4
4
|
import Checkbox from "./checkbox";
|
|
5
|
+
import { CellProps, OptionLabel } from "../util/types";
|
|
5
6
|
type OptionProps = AriaProps & {
|
|
6
7
|
/**
|
|
7
8
|
* Display text of the option item.
|
|
8
9
|
*/
|
|
9
|
-
label:
|
|
10
|
+
label: OptionLabel;
|
|
11
|
+
/**
|
|
12
|
+
* Optional text to use as the label. If not provided, label will be used.
|
|
13
|
+
* This is useful for cases where the label is a complex component and you
|
|
14
|
+
* want to display a simpler string in the menu.
|
|
15
|
+
*/
|
|
16
|
+
labelAsText?: string;
|
|
10
17
|
/**
|
|
11
18
|
* Value of the item, used as a key of sorts for the parent to manage its
|
|
12
19
|
* items, because label/display text may be identical for some selects. This
|
|
@@ -52,9 +59,34 @@ type OptionProps = AriaProps & {
|
|
|
52
59
|
* @ignore
|
|
53
60
|
*/
|
|
54
61
|
style?: StyleType;
|
|
62
|
+
/**
|
|
63
|
+
* Inherited from WB Cell.
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* Adds a horizontal rule at the bottom of the cell that can be used to
|
|
67
|
+
* separate items within ActionMenu instances. Defaults to `none`.
|
|
68
|
+
*/
|
|
69
|
+
horizontalRule: CellProps["horizontalRule"];
|
|
70
|
+
/**
|
|
71
|
+
* Optional left accessory to display in the `OptionItem` element.
|
|
72
|
+
*/
|
|
73
|
+
leftAccessory?: CellProps["leftAccessory"];
|
|
74
|
+
/**
|
|
75
|
+
* Optional right accessory to display in the `OptionItem` element.
|
|
76
|
+
*/
|
|
77
|
+
rightAccessory?: CellProps["rightAccessory"];
|
|
78
|
+
/**
|
|
79
|
+
* Optional subtitle to display before the label.
|
|
80
|
+
*/
|
|
81
|
+
subtitle1?: CellProps["subtitle1"];
|
|
82
|
+
/**
|
|
83
|
+
* Optional subtitle to display after the label.
|
|
84
|
+
*/
|
|
85
|
+
subtitle2?: CellProps["subtitle2"];
|
|
55
86
|
};
|
|
56
87
|
type DefaultProps = {
|
|
57
88
|
disabled: OptionProps["disabled"];
|
|
89
|
+
horizontalRule: OptionProps["horizontalRule"];
|
|
58
90
|
onToggle: OptionProps["onToggle"];
|
|
59
91
|
role: OptionProps["role"];
|
|
60
92
|
selected: OptionProps["selected"];
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { AriaProps } from "@khanacademy/wonder-blocks-core";
|
|
3
|
+
import { OptionLabel } from "../util/types";
|
|
3
4
|
type SelectOpenerProps = AriaProps & {
|
|
4
5
|
/**
|
|
5
6
|
* Display text in the SelectOpener.
|
|
6
7
|
*/
|
|
7
|
-
children:
|
|
8
|
+
children: OptionLabel;
|
|
8
9
|
/**
|
|
9
10
|
* Whether the SelectOpener is disabled. If disabled, disallows interaction.
|
|
10
11
|
* Default false.
|
package/dist/es/index.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { StyleSheet } from 'aphrodite';
|
|
3
|
-
import { CompactCell } from '@khanacademy/wonder-blocks-cell';
|
|
3
|
+
import { CompactCell, DetailCell } from '@khanacademy/wonder-blocks-cell';
|
|
4
4
|
import Color, { mix, fade, SemanticColor } from '@khanacademy/wonder-blocks-color';
|
|
5
5
|
import Spacing from '@khanacademy/wonder-blocks-spacing';
|
|
6
|
-
import { LabelMedium, LabelLarge } from '@khanacademy/wonder-blocks-typography';
|
|
6
|
+
import { LabelMedium, LabelSmall, LabelLarge } from '@khanacademy/wonder-blocks-typography';
|
|
7
7
|
import { tokens } from '@khanacademy/wonder-blocks-theming';
|
|
8
8
|
import { View, addStyle } from '@khanacademy/wonder-blocks-core';
|
|
9
|
-
import {
|
|
9
|
+
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
10
10
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
11
11
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
12
12
|
import * as ReactDOM from 'react-dom';
|
|
13
|
+
import { ClickableBehavior, getClickableBehavior } from '@khanacademy/wonder-blocks-clickable';
|
|
13
14
|
import SearchField from '@khanacademy/wonder-blocks-search-field';
|
|
14
15
|
import { withActionScheduler } from '@khanacademy/wonder-blocks-timing';
|
|
15
16
|
import { VariableSizeList } from 'react-window';
|
|
16
17
|
import { Popper } from 'react-popper';
|
|
17
18
|
import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
|
|
18
|
-
import {
|
|
19
|
+
import { detectOverflow } from '@popperjs/core';
|
|
19
20
|
import caretDownIcon from '@phosphor-icons/core/bold/caret-down-bold.svg';
|
|
20
21
|
import { __RouterContext } from 'react-router';
|
|
21
22
|
|
|
@@ -59,15 +60,15 @@ const defaultLabels = {
|
|
|
59
60
|
selectNoneLabel: "Select none",
|
|
60
61
|
selectAllLabel: numOptions => `Select all (${numOptions})`,
|
|
61
62
|
noneSelected: "0 items",
|
|
62
|
-
someSelected: numSelectedValues => `${numSelectedValues} items`,
|
|
63
|
+
someSelected: numSelectedValues => numSelectedValues === 1 ? "1 item" : `${numSelectedValues} items`,
|
|
63
64
|
allSelected: "All items"
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
const {
|
|
67
|
-
blue: blue$
|
|
68
|
-
white: white$
|
|
69
|
-
offBlack: offBlack$
|
|
70
|
-
offBlack32: offBlack32$
|
|
68
|
+
blue: blue$1,
|
|
69
|
+
white: white$1,
|
|
70
|
+
offBlack: offBlack$1,
|
|
71
|
+
offBlack32: offBlack32$1
|
|
71
72
|
} = Color;
|
|
72
73
|
class ActionItem extends React.Component {
|
|
73
74
|
static isClassOf(instance) {
|
|
@@ -130,18 +131,18 @@ const styles$8 = StyleSheet.create({
|
|
|
130
131
|
outlineOffset: -Spacing.xxxxSmall_2
|
|
131
132
|
},
|
|
132
133
|
[":hover[aria-disabled=false]"]: {
|
|
133
|
-
color: white$
|
|
134
|
-
background: blue$
|
|
134
|
+
color: white$1,
|
|
135
|
+
background: blue$1
|
|
135
136
|
},
|
|
136
137
|
["@media not (hover: hover)"]: {
|
|
137
138
|
[":hover[aria-disabled=false]"]: {
|
|
138
|
-
color: white$
|
|
139
|
-
background: offBlack$
|
|
139
|
+
color: white$1,
|
|
140
|
+
background: offBlack$1
|
|
140
141
|
}
|
|
141
142
|
},
|
|
142
143
|
[":active[aria-disabled=false]"]: {
|
|
143
|
-
color: mix(fade(blue$
|
|
144
|
-
background: mix(offBlack32$
|
|
144
|
+
color: mix(fade(blue$1, 0.32), white$1),
|
|
145
|
+
background: mix(offBlack32$1, blue$1)
|
|
145
146
|
}
|
|
146
147
|
},
|
|
147
148
|
shared: {
|
|
@@ -170,30 +171,22 @@ function _objectWithoutPropertiesLoose(source, excluded) {
|
|
|
170
171
|
return target;
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
const {
|
|
174
|
-
offBlack: offBlack$1,
|
|
175
|
-
offBlack32: offBlack32$2,
|
|
176
|
-
white: white$2
|
|
177
|
-
} = Color;
|
|
178
174
|
const Check = function Check(props) {
|
|
179
175
|
const {
|
|
180
|
-
|
|
181
|
-
selected,
|
|
182
|
-
pressed,
|
|
183
|
-
hovered,
|
|
184
|
-
focused
|
|
176
|
+
selected
|
|
185
177
|
} = props;
|
|
186
178
|
return React.createElement(PhosphorIcon, {
|
|
187
179
|
icon: checkIcon,
|
|
188
180
|
size: "small",
|
|
189
|
-
color: disabled ? offBlack32$2 : pressed || hovered || focused ? white$2 : offBlack$1,
|
|
190
181
|
style: [styles$7.bounds, !selected && styles$7.hide]
|
|
191
182
|
});
|
|
192
183
|
};
|
|
193
184
|
const styles$7 = StyleSheet.create({
|
|
194
185
|
bounds: {
|
|
195
|
-
|
|
196
|
-
|
|
186
|
+
alignSelf: "center",
|
|
187
|
+
height: Spacing.medium_16,
|
|
188
|
+
minHeight: Spacing.medium_16,
|
|
189
|
+
minWidth: Spacing.medium_16
|
|
197
190
|
},
|
|
198
191
|
hide: {
|
|
199
192
|
visibility: "hidden"
|
|
@@ -201,33 +194,22 @@ const styles$7 = StyleSheet.create({
|
|
|
201
194
|
});
|
|
202
195
|
|
|
203
196
|
const {
|
|
204
|
-
blue: blue$1,
|
|
205
|
-
white: white$1,
|
|
206
197
|
offBlack16,
|
|
207
|
-
offBlack32: offBlack32$1,
|
|
208
198
|
offBlack50,
|
|
209
199
|
offWhite
|
|
210
200
|
} = Color;
|
|
211
201
|
const Checkbox = function Checkbox(props) {
|
|
212
202
|
const {
|
|
213
203
|
disabled,
|
|
214
|
-
selected
|
|
215
|
-
pressed,
|
|
216
|
-
hovered,
|
|
217
|
-
focused
|
|
204
|
+
selected
|
|
218
205
|
} = props;
|
|
219
|
-
const activeBlue = mix(offBlack32$1, blue$1);
|
|
220
|
-
const clickInteraction = pressed || hovered || focused;
|
|
221
|
-
const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue$1 : white$1;
|
|
222
|
-
const checkColor = disabled ? offBlack32$1 : clickInteraction ? pressed ? activeBlue : blue$1 : white$1;
|
|
223
206
|
return React.createElement(View, {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}]
|
|
207
|
+
className: "checkbox",
|
|
208
|
+
style: [styles$6.checkbox, selected && !disabled && styles$6.noBorder, disabled && styles$6.disabledCheckbox]
|
|
227
209
|
}, selected && React.createElement(PhosphorIcon, {
|
|
228
210
|
icon: checkIcon,
|
|
229
211
|
size: "small",
|
|
230
|
-
|
|
212
|
+
className: "check",
|
|
231
213
|
style: [{
|
|
232
214
|
width: Spacing.small_12,
|
|
233
215
|
height: Spacing.small_12,
|
|
@@ -237,8 +219,10 @@ const Checkbox = function Checkbox(props) {
|
|
|
237
219
|
};
|
|
238
220
|
const styles$6 = StyleSheet.create({
|
|
239
221
|
checkbox: {
|
|
240
|
-
|
|
241
|
-
|
|
222
|
+
alignSelf: "center",
|
|
223
|
+
minHeight: Spacing.medium_16,
|
|
224
|
+
minWidth: Spacing.medium_16,
|
|
225
|
+
height: Spacing.medium_16,
|
|
242
226
|
borderRadius: 3,
|
|
243
227
|
borderWidth: 1,
|
|
244
228
|
borderStyle: "solid",
|
|
@@ -258,7 +242,7 @@ const styles$6 = StyleSheet.create({
|
|
|
258
242
|
}
|
|
259
243
|
});
|
|
260
244
|
|
|
261
|
-
const _excluded$5 = ["disabled", "label", "role", "selected", "testId", "style", "value", "onClick", "onToggle", "variant"];
|
|
245
|
+
const _excluded$5 = ["disabled", "label", "role", "selected", "testId", "style", "leftAccessory", "horizontalRule", "rightAccessory", "subtitle1", "subtitle2", "value", "onClick", "onToggle", "variant"];
|
|
262
246
|
class OptionItem extends React.Component {
|
|
263
247
|
constructor(...args) {
|
|
264
248
|
super(...args);
|
|
@@ -292,42 +276,54 @@ class OptionItem extends React.Component {
|
|
|
292
276
|
role,
|
|
293
277
|
selected,
|
|
294
278
|
testId,
|
|
295
|
-
style
|
|
279
|
+
style,
|
|
280
|
+
leftAccessory,
|
|
281
|
+
horizontalRule,
|
|
282
|
+
rightAccessory,
|
|
283
|
+
subtitle1,
|
|
284
|
+
subtitle2
|
|
296
285
|
} = _this$props,
|
|
297
286
|
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$5);
|
|
298
|
-
const ClickableBehavior = getClickableBehavior();
|
|
299
287
|
const CheckComponent = this.getCheckComponent();
|
|
300
|
-
|
|
288
|
+
const defaultStyle = [styles$5.item, style];
|
|
289
|
+
return React.createElement(DetailCell, _extends({
|
|
301
290
|
disabled: disabled,
|
|
302
|
-
|
|
291
|
+
horizontalRule: horizontalRule,
|
|
292
|
+
rootStyle: defaultStyle,
|
|
293
|
+
style: styles$5.itemContainer,
|
|
294
|
+
"aria-selected": selected ? "true" : "false",
|
|
303
295
|
role: role,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
"aria-selected": selected ? "true" : "false",
|
|
316
|
-
role: role
|
|
317
|
-
}, childrenProps), React.createElement(CheckComponent, {
|
|
296
|
+
testId: testId,
|
|
297
|
+
leftAccessory: React.createElement(React.Fragment, null, leftAccessory ? React.createElement(View, {
|
|
298
|
+
style: {
|
|
299
|
+
flexDirection: "row"
|
|
300
|
+
}
|
|
301
|
+
}, React.createElement(CheckComponent, {
|
|
302
|
+
disabled: disabled,
|
|
303
|
+
selected: selected
|
|
304
|
+
}), React.createElement(Strut, {
|
|
305
|
+
size: Spacing.xSmall_8
|
|
306
|
+
}), leftAccessory) : React.createElement(CheckComponent, {
|
|
318
307
|
disabled: disabled,
|
|
319
|
-
selected: selected
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
308
|
+
selected: selected
|
|
309
|
+
})),
|
|
310
|
+
rightAccessory: rightAccessory,
|
|
311
|
+
subtitle1: subtitle1 ? React.createElement(LabelSmall, {
|
|
312
|
+
className: "subtitle"
|
|
313
|
+
}, subtitle1) : undefined,
|
|
314
|
+
title: React.createElement(LabelMedium, {
|
|
324
315
|
style: styles$5.label
|
|
325
|
-
}, label)
|
|
326
|
-
|
|
316
|
+
}, label),
|
|
317
|
+
subtitle2: subtitle2 ? React.createElement(LabelSmall, {
|
|
318
|
+
className: "subtitle"
|
|
319
|
+
}, subtitle2) : undefined,
|
|
320
|
+
onClick: this.handleClick
|
|
321
|
+
}, sharedProps));
|
|
327
322
|
}
|
|
328
323
|
}
|
|
329
324
|
OptionItem.defaultProps = {
|
|
330
325
|
disabled: false,
|
|
326
|
+
horizontalRule: "none",
|
|
331
327
|
onToggle: () => void 0,
|
|
332
328
|
role: "option",
|
|
333
329
|
selected: false
|
|
@@ -339,37 +335,67 @@ const {
|
|
|
339
335
|
offBlack,
|
|
340
336
|
offBlack32
|
|
341
337
|
} = Color;
|
|
338
|
+
const activeBlue = mix(offBlack32, blue);
|
|
342
339
|
const styles$5 = StyleSheet.create({
|
|
340
|
+
item: {
|
|
341
|
+
minHeight: "unset",
|
|
342
|
+
paddingBlock: Spacing.xxxxSmall_2,
|
|
343
|
+
":focus": {
|
|
344
|
+
borderRadius: Spacing.xxxSmall_4,
|
|
345
|
+
outline: `${Spacing.xxxxSmall_2}px solid ${Color.blue}`,
|
|
346
|
+
outlineOffset: -Spacing.xxxxSmall_2
|
|
347
|
+
},
|
|
348
|
+
":focus-visible": {
|
|
349
|
+
overflow: "visible"
|
|
350
|
+
},
|
|
351
|
+
[":hover[aria-disabled=false]"]: {
|
|
352
|
+
color: white,
|
|
353
|
+
background: blue
|
|
354
|
+
},
|
|
355
|
+
["@media not (hover: hover)"]: {
|
|
356
|
+
[":hover[aria-disabled=false]"]: {
|
|
357
|
+
color: white,
|
|
358
|
+
background: offBlack
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
[":active[aria-disabled=false]"]: {
|
|
362
|
+
color: mix(fade(blue, 0.32), white),
|
|
363
|
+
background: activeBlue
|
|
364
|
+
},
|
|
365
|
+
[":hover[aria-disabled=false] .checkbox"]: {
|
|
366
|
+
background: white
|
|
367
|
+
},
|
|
368
|
+
[":hover[aria-disabled=false] .check"]: {
|
|
369
|
+
color: blue
|
|
370
|
+
},
|
|
371
|
+
[":active[aria-disabled=false] .check"]: {
|
|
372
|
+
color: activeBlue
|
|
373
|
+
},
|
|
374
|
+
[":is([aria-selected=true]) .checkbox"]: {
|
|
375
|
+
background: blue
|
|
376
|
+
},
|
|
377
|
+
[":is([aria-selected=true]) .check"]: {
|
|
378
|
+
color: white
|
|
379
|
+
},
|
|
380
|
+
[":is([aria-disabled=false]) .subtitle"]: {
|
|
381
|
+
color: Color.offBlack64
|
|
382
|
+
},
|
|
383
|
+
[":hover[aria-disabled=false] .subtitle"]: {
|
|
384
|
+
color: Color.offWhite
|
|
385
|
+
},
|
|
386
|
+
[":active[aria-disabled=false] .subtitle"]: {
|
|
387
|
+
color: mix(fade(blue, 0.16), white)
|
|
388
|
+
}
|
|
389
|
+
},
|
|
343
390
|
itemContainer: {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
color: offBlack,
|
|
347
|
-
alignItems: "center",
|
|
348
|
-
height: DROPDOWN_ITEM_HEIGHT,
|
|
349
|
-
minHeight: DROPDOWN_ITEM_HEIGHT,
|
|
350
|
-
border: 0,
|
|
351
|
-
outline: 0,
|
|
352
|
-
paddingLeft: Spacing.xSmall_8,
|
|
391
|
+
minHeight: "unset",
|
|
392
|
+
padding: Spacing.xSmall_8,
|
|
353
393
|
paddingRight: Spacing.medium_16,
|
|
354
|
-
whiteSpace: "nowrap"
|
|
355
|
-
cursor: "default"
|
|
356
|
-
},
|
|
357
|
-
focus: {
|
|
358
|
-
color: white,
|
|
359
|
-
background: blue
|
|
360
|
-
},
|
|
361
|
-
active: {
|
|
362
|
-
color: mix(fade(blue, 0.32), white),
|
|
363
|
-
background: mix(offBlack32, blue)
|
|
364
|
-
},
|
|
365
|
-
disabled: {
|
|
366
|
-
color: offBlack32,
|
|
367
|
-
background: white
|
|
394
|
+
whiteSpace: "nowrap"
|
|
368
395
|
},
|
|
369
396
|
label: {
|
|
370
397
|
whiteSpace: "nowrap",
|
|
371
398
|
userSelect: "none",
|
|
372
|
-
marginLeft: Spacing.xSmall_8,
|
|
373
399
|
overflow: "hidden",
|
|
374
400
|
textOverflow: "ellipsis"
|
|
375
401
|
},
|
|
@@ -479,15 +505,6 @@ function getDropdownMenuHeight(items, initialHeight = 0) {
|
|
|
479
505
|
}
|
|
480
506
|
}, initialHeight);
|
|
481
507
|
}
|
|
482
|
-
function generateDropdownMenuStyles(minWidth, maxHeight) {
|
|
483
|
-
const styles = StyleSheet.create({
|
|
484
|
-
dropdownMenu: {
|
|
485
|
-
minWidth,
|
|
486
|
-
maxHeight
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
return styles.dropdownMenu;
|
|
490
|
-
}
|
|
491
508
|
|
|
492
509
|
class DropdownCoreVirtualized extends React.Component {
|
|
493
510
|
constructor(props) {
|
|
@@ -590,6 +607,39 @@ class DropdownCoreVirtualized extends React.Component {
|
|
|
590
607
|
}
|
|
591
608
|
var DropdownCoreVirtualized$1 = withActionScheduler(DropdownCoreVirtualized);
|
|
592
609
|
|
|
610
|
+
function modifyMaxHeight({
|
|
611
|
+
state,
|
|
612
|
+
options
|
|
613
|
+
}) {
|
|
614
|
+
const overflow = detectOverflow(state, options);
|
|
615
|
+
const {
|
|
616
|
+
y
|
|
617
|
+
} = state.modifiersData.preventOverflow || {
|
|
618
|
+
x: 0,
|
|
619
|
+
y: 0
|
|
620
|
+
};
|
|
621
|
+
const {
|
|
622
|
+
height
|
|
623
|
+
} = state.rects.popper;
|
|
624
|
+
const [basePlacement] = state.placement.split("-");
|
|
625
|
+
const heightProp = basePlacement === "top" ? "top" : "bottom";
|
|
626
|
+
const maxHeight = height - overflow[heightProp] - y;
|
|
627
|
+
state.styles.popper = _extends({}, state.styles.popper, {
|
|
628
|
+
maxHeight: `${maxHeight}px`,
|
|
629
|
+
["--popper-max-height"]: `${maxHeight}px`
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
const maxHeightModifier = {
|
|
633
|
+
name: "maxHeight",
|
|
634
|
+
enabled: true,
|
|
635
|
+
phase: "main",
|
|
636
|
+
options: {
|
|
637
|
+
padding: DROPDOWN_ITEM_HEIGHT
|
|
638
|
+
},
|
|
639
|
+
requiresIfExists: ["offset", "preventOverflow", "flip"],
|
|
640
|
+
fn: modifyMaxHeight
|
|
641
|
+
};
|
|
642
|
+
|
|
593
643
|
const modifiers = [{
|
|
594
644
|
name: "preventOverflow",
|
|
595
645
|
options: {
|
|
@@ -597,7 +647,7 @@ const modifiers = [{
|
|
|
597
647
|
altAxis: true,
|
|
598
648
|
tether: false
|
|
599
649
|
}
|
|
600
|
-
}];
|
|
650
|
+
}, maxHeightModifier];
|
|
601
651
|
const DropdownPopper = function DropdownPopper({
|
|
602
652
|
children,
|
|
603
653
|
alignment = "left",
|
|
@@ -652,6 +702,18 @@ function debounce(callback, wait) {
|
|
|
652
702
|
timeout = setTimeout(later, wait);
|
|
653
703
|
};
|
|
654
704
|
}
|
|
705
|
+
function isString(x) {
|
|
706
|
+
return typeof x === "string";
|
|
707
|
+
}
|
|
708
|
+
function getLabel(props) {
|
|
709
|
+
if (isString(props.label)) {
|
|
710
|
+
return props.label;
|
|
711
|
+
}
|
|
712
|
+
if (isString(props.labelAsText)) {
|
|
713
|
+
return props.labelAsText;
|
|
714
|
+
}
|
|
715
|
+
return "";
|
|
716
|
+
}
|
|
655
717
|
|
|
656
718
|
const VIRTUALIZE_THRESHOLD = 125;
|
|
657
719
|
const StyledSpan = addStyle("span");
|
|
@@ -783,12 +845,14 @@ class DropdownCore extends React.Component {
|
|
|
783
845
|
const foundIndex = this.props.items.filter(item => item.focusable).findIndex(({
|
|
784
846
|
component
|
|
785
847
|
}) => {
|
|
786
|
-
var _component$props;
|
|
787
848
|
if (SeparatorItem.isClassOf(component)) {
|
|
788
849
|
return false;
|
|
789
850
|
}
|
|
790
|
-
|
|
791
|
-
|
|
851
|
+
if (OptionItem.isClassOf(component)) {
|
|
852
|
+
const optionItemProps = component.props;
|
|
853
|
+
return getLabel(optionItemProps).toLowerCase().startsWith(key.toLowerCase());
|
|
854
|
+
}
|
|
855
|
+
return false;
|
|
792
856
|
});
|
|
793
857
|
if (foundIndex >= 0) {
|
|
794
858
|
const isClosed = !this.props.open;
|
|
@@ -1103,14 +1167,15 @@ class DropdownCore extends React.Component {
|
|
|
1103
1167
|
} = this.props;
|
|
1104
1168
|
const openerStyle = openerElement && window.getComputedStyle(openerElement);
|
|
1105
1169
|
const minDropdownWidth = openerStyle ? openerStyle.getPropertyValue("width") : 0;
|
|
1106
|
-
const maxDropdownHeight = getDropdownMenuHeight(this.props.items);
|
|
1107
1170
|
return React.createElement(View, {
|
|
1108
1171
|
onMouseUp: this.handleDropdownMouseUp,
|
|
1109
1172
|
style: [styles$3.dropdown, light && styles$3.light, isReferenceHidden && styles$3.hidden, dropdownStyle],
|
|
1110
1173
|
testId: "dropdown-core-container"
|
|
1111
1174
|
}, isFilterable && this.renderSearchField(), React.createElement(View, {
|
|
1112
1175
|
role: role,
|
|
1113
|
-
style: [styles$3.listboxOrMenu,
|
|
1176
|
+
style: [styles$3.listboxOrMenu, {
|
|
1177
|
+
minWidth: minDropdownWidth
|
|
1178
|
+
}],
|
|
1114
1179
|
"aria-invalid": role === "listbox" ? ariaInvalid : undefined,
|
|
1115
1180
|
"aria-required": role === "listbox" ? ariaRequired : undefined
|
|
1116
1181
|
}, listRenderer), this.maybeRenderNoResults());
|
|
@@ -1184,7 +1249,8 @@ const styles$3 = StyleSheet.create({
|
|
|
1184
1249
|
paddingTop: Spacing.xxxSmall_4,
|
|
1185
1250
|
paddingBottom: Spacing.xxxSmall_4,
|
|
1186
1251
|
border: `solid 1px ${Color.offBlack16}`,
|
|
1187
|
-
boxShadow: `0px 8px 8px 0px ${fade(Color.offBlack, 0.1)}
|
|
1252
|
+
boxShadow: `0px 8px 8px 0px ${fade(Color.offBlack, 0.1)}`,
|
|
1253
|
+
maxHeight: "var(--popper-max-height)"
|
|
1188
1254
|
},
|
|
1189
1255
|
light: {
|
|
1190
1256
|
border: "none"
|
|
@@ -1204,7 +1270,8 @@ const styles$3 = StyleSheet.create({
|
|
|
1204
1270
|
searchInputStyle: {
|
|
1205
1271
|
margin: Spacing.xSmall_8,
|
|
1206
1272
|
marginTop: Spacing.xxxSmall_4,
|
|
1207
|
-
minHeight: "auto"
|
|
1273
|
+
minHeight: "auto",
|
|
1274
|
+
position: "sticky"
|
|
1208
1275
|
},
|
|
1209
1276
|
srOnly: {
|
|
1210
1277
|
border: 0,
|
|
@@ -1757,7 +1824,7 @@ class SingleSelect extends React.Component {
|
|
|
1757
1824
|
const lowercasedSearchText = searchText.toLowerCase();
|
|
1758
1825
|
return children.filter(({
|
|
1759
1826
|
props
|
|
1760
|
-
}) => !searchText || props
|
|
1827
|
+
}) => !searchText || getLabel(props).indexOf(lowercasedSearchText) > -1);
|
|
1761
1828
|
}
|
|
1762
1829
|
getMenuItems(children) {
|
|
1763
1830
|
const {
|
|
@@ -1781,7 +1848,7 @@ class SingleSelect extends React.Component {
|
|
|
1781
1848
|
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
|
|
1782
1849
|
const items = React.Children.toArray(children);
|
|
1783
1850
|
const selectedItem = items.find(option => option.props.value === selectedValue);
|
|
1784
|
-
const menuText = selectedItem ? selectedItem.props.
|
|
1851
|
+
const menuText = selectedItem ? getLabel(selectedItem.props) || defaultLabels.someSelected(1) : placeholder;
|
|
1785
1852
|
const dropdownOpener = opener ? React.createElement(DropdownOpener, {
|
|
1786
1853
|
onClick: this.handleClick,
|
|
1787
1854
|
disabled: numItems === 0 || disabled,
|
|
@@ -1971,7 +2038,15 @@ class MultiSelect extends React.Component {
|
|
|
1971
2038
|
return noSelectionText;
|
|
1972
2039
|
case 1:
|
|
1973
2040
|
const selectedItem = children.find(option => option.props.value === selectedValues[0]);
|
|
1974
|
-
|
|
2041
|
+
if (selectedItem) {
|
|
2042
|
+
const selectedLabel = getLabel(selectedItem == null ? void 0 : selectedItem.props);
|
|
2043
|
+
if (selectedLabel) {
|
|
2044
|
+
return selectedLabel;
|
|
2045
|
+
} else {
|
|
2046
|
+
return someSelected(1);
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
return noSelectionText;
|
|
1975
2050
|
case children.length:
|
|
1976
2051
|
return allSelected;
|
|
1977
2052
|
default:
|
|
@@ -2036,7 +2111,7 @@ class MultiSelect extends React.Component {
|
|
|
2036
2111
|
const lowercasedSearchText = searchText.toLowerCase();
|
|
2037
2112
|
const filteredChildren = children.filter(({
|
|
2038
2113
|
props
|
|
2039
|
-
}) => !searchText || props.
|
|
2114
|
+
}) => !searchText || getLabel(props).toLowerCase().indexOf(lowercasedSearchText) > -1);
|
|
2040
2115
|
const lastSelectedChildren = [];
|
|
2041
2116
|
const restOfTheChildren = [];
|
|
2042
2117
|
for (const child of filteredChildren) {
|