@khanacademy/wonder-blocks-dropdown 2.6.10 → 2.7.2
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 +33 -0
- package/dist/es/index.js +36 -140
- package/dist/index.js +88 -198
- package/package.json +10 -9
- package/src/components/__tests__/dropdown-core-virtualized.test.js +0 -9
- package/src/components/__tests__/search-text-input.test.js +124 -57
- package/src/components/dropdown-core.js +12 -0
- package/src/components/search-text-input.js +34 -146
- package/src/components/single-select.stories.js +9 -2
- package/src/util/constants.js +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-dropdown
|
|
2
2
|
|
|
3
|
+
## 2.7.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [5f4a4297]
|
|
8
|
+
- Updated dependencies [2b96fd59]
|
|
9
|
+
- @khanacademy/wonder-blocks-core@4.3.2
|
|
10
|
+
- @khanacademy/wonder-blocks-button@2.11.6
|
|
11
|
+
- @khanacademy/wonder-blocks-clickable@2.2.7
|
|
12
|
+
- @khanacademy/wonder-blocks-icon@1.2.28
|
|
13
|
+
- @khanacademy/wonder-blocks-icon-button@3.4.7
|
|
14
|
+
- @khanacademy/wonder-blocks-layout@1.4.10
|
|
15
|
+
- @khanacademy/wonder-blocks-modal@2.3.2
|
|
16
|
+
- @khanacademy/wonder-blocks-search-field@1.0.5
|
|
17
|
+
- @khanacademy/wonder-blocks-typography@1.1.32
|
|
18
|
+
|
|
19
|
+
## 2.7.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 9c2580e6: Fixed the search field focus bug in dropdowns
|
|
24
|
+
|
|
25
|
+
## 2.7.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- b3960766: Replaced core elements with Wonder Blocks SearchField (added dependency to SearchField)
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Updated dependencies [b3960766]
|
|
34
|
+
- @khanacademy/wonder-blocks-search-field@1.0.4
|
|
35
|
+
|
|
3
36
|
## 2.6.10
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/extends';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { StyleSheet
|
|
3
|
+
import { StyleSheet } from 'aphrodite';
|
|
4
4
|
import { Link } from 'react-router-dom';
|
|
5
5
|
import { __RouterContext } from 'react-router';
|
|
6
6
|
import Color, { mix, fade, SemanticColor } from '@khanacademy/wonder-blocks-color';
|
|
7
7
|
import Spacing from '@khanacademy/wonder-blocks-spacing';
|
|
8
|
-
import { LabelMedium,
|
|
8
|
+
import { LabelMedium, LabelLarge } from '@khanacademy/wonder-blocks-typography';
|
|
9
9
|
import { getClickableBehavior, isClientSideUrl, ClickableBehavior } from '@khanacademy/wonder-blocks-clickable';
|
|
10
10
|
import { addStyle, View } from '@khanacademy/wonder-blocks-core';
|
|
11
11
|
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
|
|
@@ -13,7 +13,7 @@ import Icon, { icons } from '@khanacademy/wonder-blocks-icon';
|
|
|
13
13
|
import ReactDOM from 'react-dom';
|
|
14
14
|
import { VariableSizeList } from 'react-window';
|
|
15
15
|
import { withActionScheduler } from '@khanacademy/wonder-blocks-timing';
|
|
16
|
-
import
|
|
16
|
+
import SearchField from '@khanacademy/wonder-blocks-search-field';
|
|
17
17
|
import { Popper } from 'react-popper';
|
|
18
18
|
import { maybeGetPortalMountedModalHostElement } from '@khanacademy/wonder-blocks-modal';
|
|
19
19
|
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
@@ -35,7 +35,8 @@ const filterableDropdownStyle = {
|
|
|
35
35
|
};
|
|
36
36
|
const searchInputStyle = {
|
|
37
37
|
margin: Spacing.xSmall_8,
|
|
38
|
-
marginTop: Spacing.xxxSmall_4
|
|
38
|
+
marginTop: Spacing.xxxSmall_4,
|
|
39
|
+
minHeight: "auto"
|
|
39
40
|
};
|
|
40
41
|
const DROPDOWN_ITEM_HEIGHT = 40;
|
|
41
42
|
const MAX_VISIBLE_ITEMS = 9;
|
|
@@ -93,7 +94,7 @@ class ActionItem extends React.Component {
|
|
|
93
94
|
hovered,
|
|
94
95
|
focused
|
|
95
96
|
} = state;
|
|
96
|
-
const defaultStyle = [styles$
|
|
97
|
+
const defaultStyle = [styles$8.shared, disabled && styles$8.disabled, !disabled && (pressed ? styles$8.active : (hovered || focused) && styles$8.focus), style];
|
|
97
98
|
|
|
98
99
|
const props = _extends({
|
|
99
100
|
"data-test-id": testId,
|
|
@@ -104,7 +105,7 @@ class ActionItem extends React.Component {
|
|
|
104
105
|
|
|
105
106
|
const children = React.createElement(React.Fragment, null, React.createElement(LabelMedium, {
|
|
106
107
|
lang: lang,
|
|
107
|
-
style: [indent && styles$
|
|
108
|
+
style: [indent && styles$8.indent, styles$8.label]
|
|
108
109
|
}, label));
|
|
109
110
|
|
|
110
111
|
if (href && !disabled) {
|
|
@@ -135,7 +136,7 @@ ActionItem.defaultProps = {
|
|
|
135
136
|
role: "menuitem"
|
|
136
137
|
};
|
|
137
138
|
ActionItem.__IS_ACTION_ITEM__ = true;
|
|
138
|
-
const styles$
|
|
139
|
+
const styles$8 = StyleSheet.create({
|
|
139
140
|
shared: {
|
|
140
141
|
background: white$4,
|
|
141
142
|
color: offBlack$3,
|
|
@@ -189,10 +190,10 @@ function Check(props) {
|
|
|
189
190
|
icon: icons.check,
|
|
190
191
|
size: "small",
|
|
191
192
|
color: disabled ? offBlack32$3 : pressed || hovered || focused ? white$3 : offBlack$2,
|
|
192
|
-
style: [styles$
|
|
193
|
+
style: [styles$7.bounds, !selected && styles$7.hide]
|
|
193
194
|
});
|
|
194
195
|
}
|
|
195
|
-
const styles$
|
|
196
|
+
const styles$7 = StyleSheet.create({
|
|
196
197
|
bounds: {
|
|
197
198
|
minHeight: 16,
|
|
198
199
|
minWidth: 16
|
|
@@ -226,17 +227,17 @@ function Checkbox(props) {
|
|
|
226
227
|
const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue$2 : white$2;
|
|
227
228
|
const checkColor = disabled ? offBlack32$2 : clickInteraction ? pressed ? activeBlue : blue$2 : white$2;
|
|
228
229
|
return React.createElement(View, {
|
|
229
|
-
style: [styles$
|
|
230
|
+
style: [styles$6.checkbox, (clickInteraction || selected && !disabled) && styles$6.noBorder, disabled && styles$6.disabledCheckbox, {
|
|
230
231
|
backgroundColor: bgColor
|
|
231
232
|
}]
|
|
232
233
|
}, selected && React.createElement(Icon, {
|
|
233
234
|
icon: checkboxCheck,
|
|
234
235
|
size: "small",
|
|
235
236
|
color: checkColor,
|
|
236
|
-
style: [disabled && selected && styles$
|
|
237
|
+
style: [disabled && selected && styles$6.disabledCheckFormatting]
|
|
237
238
|
}));
|
|
238
239
|
}
|
|
239
|
-
const styles$
|
|
240
|
+
const styles$6 = StyleSheet.create({
|
|
240
241
|
checkbox: {
|
|
241
242
|
minHeight: 16,
|
|
242
243
|
minWidth: 16,
|
|
@@ -314,7 +315,7 @@ class OptionItem extends React.Component {
|
|
|
314
315
|
hovered,
|
|
315
316
|
focused
|
|
316
317
|
} = state;
|
|
317
|
-
const defaultStyle = [styles$
|
|
318
|
+
const defaultStyle = [styles$5.itemContainer, pressed ? styles$5.active : (hovered || focused) && styles$5.focus, disabled && styles$5.disabled, style];
|
|
318
319
|
return React.createElement(View, _extends({}, sharedProps, {
|
|
319
320
|
testId: testId,
|
|
320
321
|
style: defaultStyle,
|
|
@@ -327,7 +328,7 @@ class OptionItem extends React.Component {
|
|
|
327
328
|
hovered: hovered,
|
|
328
329
|
focused: focused
|
|
329
330
|
}), React.createElement(LabelMedium, {
|
|
330
|
-
style: styles$
|
|
331
|
+
style: styles$5.label
|
|
331
332
|
}, label));
|
|
332
333
|
});
|
|
333
334
|
}
|
|
@@ -346,7 +347,7 @@ const {
|
|
|
346
347
|
offBlack: offBlack$1,
|
|
347
348
|
offBlack32: offBlack32$1
|
|
348
349
|
} = Color;
|
|
349
|
-
const styles$
|
|
350
|
+
const styles$5 = StyleSheet.create({
|
|
350
351
|
itemContainer: {
|
|
351
352
|
flexDirection: "row",
|
|
352
353
|
background: white$1,
|
|
@@ -392,14 +393,14 @@ class SeparatorItem extends React.Component {
|
|
|
392
393
|
|
|
393
394
|
render() {
|
|
394
395
|
return React.createElement(View, {
|
|
395
|
-
style: [styles$
|
|
396
|
+
style: [styles$4.separator, this.props.style],
|
|
396
397
|
"aria-hidden": "true"
|
|
397
398
|
});
|
|
398
399
|
}
|
|
399
400
|
|
|
400
401
|
}
|
|
401
402
|
SeparatorItem.__IS_SEPARATOR_ITEM__ = true;
|
|
402
|
-
const styles$
|
|
403
|
+
const styles$4 = StyleSheet.create({
|
|
403
404
|
separator: {
|
|
404
405
|
boxShadow: `0 -1px ${Color.offBlack16}`,
|
|
405
406
|
height: 1,
|
|
@@ -487,110 +488,38 @@ class DropdownVirtualizedItem extends React.Component {
|
|
|
487
488
|
}
|
|
488
489
|
|
|
489
490
|
class SearchTextInput extends React.Component {
|
|
490
|
-
constructor(...args) {
|
|
491
|
-
super(...args);
|
|
492
|
-
this.state = {
|
|
493
|
-
focused: false,
|
|
494
|
-
labels: _extends({
|
|
495
|
-
clearSearch: defaultLabels.clearSearch,
|
|
496
|
-
filter: defaultLabels.filter
|
|
497
|
-
}, this.props.labels)
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
this.handleChange = e => {
|
|
501
|
-
e.preventDefault();
|
|
502
|
-
this.props.onChange(e.target.value);
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
this.handleDismiss = () => {
|
|
506
|
-
const {
|
|
507
|
-
onClick,
|
|
508
|
-
onChange
|
|
509
|
-
} = this.props;
|
|
510
|
-
onChange("");
|
|
511
|
-
|
|
512
|
-
if (onClick) {
|
|
513
|
-
onClick();
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
this.handleBlur = e => {
|
|
518
|
-
this.setState({
|
|
519
|
-
focused: false
|
|
520
|
-
});
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
this.handleFocus = e => {
|
|
524
|
-
this.setState({
|
|
525
|
-
focused: true
|
|
526
|
-
});
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
|
|
530
491
|
static isClassOf(instance) {
|
|
531
492
|
return instance && instance.type && instance.type.__IS_SEARCH_TEXT_INPUT__;
|
|
532
493
|
}
|
|
533
494
|
|
|
534
|
-
|
|
535
|
-
if (this.props.
|
|
536
|
-
|
|
537
|
-
labels: _extends({}, this.state.labels, this.props.labels)
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
maybeRenderDismissIconButton() {
|
|
543
|
-
const {
|
|
544
|
-
searchText
|
|
545
|
-
} = this.props;
|
|
546
|
-
const {
|
|
547
|
-
clearSearch
|
|
548
|
-
} = this.state.labels;
|
|
495
|
+
componentDidMount() {
|
|
496
|
+
if (this.props.autofocus) {
|
|
497
|
+
var _this$props$itemRef;
|
|
549
498
|
|
|
550
|
-
|
|
551
|
-
return React.createElement(IconButton, {
|
|
552
|
-
icon: icons.dismiss,
|
|
553
|
-
kind: "tertiary",
|
|
554
|
-
onClick: this.handleDismiss,
|
|
555
|
-
style: styles$4.dismissIcon,
|
|
556
|
-
"aria-label": clearSearch
|
|
557
|
-
});
|
|
499
|
+
(_this$props$itemRef = this.props.itemRef) == null ? void 0 : _this$props$itemRef.current.focus();
|
|
558
500
|
}
|
|
559
|
-
|
|
560
|
-
return null;
|
|
561
501
|
}
|
|
562
502
|
|
|
563
503
|
render() {
|
|
564
504
|
const {
|
|
505
|
+
labels,
|
|
506
|
+
onChange,
|
|
565
507
|
onClick,
|
|
566
508
|
itemRef,
|
|
567
509
|
searchText,
|
|
568
510
|
style,
|
|
569
511
|
testId
|
|
570
512
|
} = this.props;
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return React.createElement(View, {
|
|
513
|
+
return React.createElement(SearchField, {
|
|
514
|
+
clearAriaLabel: labels.clearSearch,
|
|
515
|
+
onChange: onChange,
|
|
575
516
|
onClick: onClick,
|
|
576
|
-
|
|
577
|
-
}, React.createElement(Icon, {
|
|
578
|
-
icon: icons.search,
|
|
579
|
-
size: "medium",
|
|
580
|
-
color: Color.offBlack64,
|
|
581
|
-
style: styles$4.searchIcon,
|
|
582
|
-
"aria-hidden": "true"
|
|
583
|
-
}), React.createElement("input", {
|
|
584
|
-
type: "text",
|
|
585
|
-
onChange: this.handleChange,
|
|
586
|
-
onFocus: this.handleFocus,
|
|
587
|
-
onBlur: this.handleBlur,
|
|
517
|
+
placeholder: labels.filter,
|
|
588
518
|
ref: itemRef,
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}), this.maybeRenderDismissIconButton());
|
|
519
|
+
style: style,
|
|
520
|
+
testId: testId,
|
|
521
|
+
value: searchText
|
|
522
|
+
});
|
|
594
523
|
}
|
|
595
524
|
|
|
596
525
|
}
|
|
@@ -601,41 +530,6 @@ SearchTextInput.defaultProps = {
|
|
|
601
530
|
}
|
|
602
531
|
};
|
|
603
532
|
SearchTextInput.__IS_SEARCH_TEXT_INPUT__ = true;
|
|
604
|
-
const styles$4 = StyleSheet.create({
|
|
605
|
-
inputContainer: {
|
|
606
|
-
flexDirection: "row",
|
|
607
|
-
border: `1px solid ${Color.offBlack16}`,
|
|
608
|
-
borderRadius: Spacing.xxxSmall_4,
|
|
609
|
-
alignItems: "center",
|
|
610
|
-
height: DROPDOWN_ITEM_HEIGHT,
|
|
611
|
-
minHeight: DROPDOWN_ITEM_HEIGHT
|
|
612
|
-
},
|
|
613
|
-
focused: {
|
|
614
|
-
border: `1px solid ${Color.blue}`
|
|
615
|
-
},
|
|
616
|
-
searchIcon: {
|
|
617
|
-
marginLeft: Spacing.xSmall_8,
|
|
618
|
-
marginRight: Spacing.xSmall_8
|
|
619
|
-
},
|
|
620
|
-
dismissIcon: {
|
|
621
|
-
margin: 0,
|
|
622
|
-
":hover": {
|
|
623
|
-
border: "none"
|
|
624
|
-
}
|
|
625
|
-
},
|
|
626
|
-
inputStyleReset: {
|
|
627
|
-
display: "flex",
|
|
628
|
-
flex: 1,
|
|
629
|
-
background: "inherit",
|
|
630
|
-
border: "none",
|
|
631
|
-
outline: "none",
|
|
632
|
-
"::placeholder": {
|
|
633
|
-
color: Color.offBlack64
|
|
634
|
-
},
|
|
635
|
-
width: "100%",
|
|
636
|
-
color: "inherit"
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
533
|
|
|
640
534
|
function getDropdownMenuHeight(items, initialHeight = 0) {
|
|
641
535
|
return items.slice(0, MAX_VISIBLE_ITEMS).reduce((sum, item) => {
|
|
@@ -1217,7 +1111,8 @@ class DropdownCore extends React.Component {
|
|
|
1217
1111
|
this.handleClickFocus(0);
|
|
1218
1112
|
this.focusCurrentItem();
|
|
1219
1113
|
},
|
|
1220
|
-
style: searchInputStyle
|
|
1114
|
+
style: searchInputStyle,
|
|
1115
|
+
autofocus: this.focusedIndex === 0
|
|
1221
1116
|
}));
|
|
1222
1117
|
}
|
|
1223
1118
|
|
|
@@ -1250,7 +1145,8 @@ class DropdownCore extends React.Component {
|
|
|
1250
1145
|
},
|
|
1251
1146
|
populatedProps: {
|
|
1252
1147
|
style: searchInputStyle,
|
|
1253
|
-
itemRef: this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null
|
|
1148
|
+
itemRef: this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null,
|
|
1149
|
+
autofocus: this.focusedIndex === 0
|
|
1254
1150
|
}
|
|
1255
1151
|
});
|
|
1256
1152
|
}
|