@khanacademy/wonder-blocks-dropdown 2.3.20 → 2.4.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-dropdown",
3
- "version": "2.3.20",
3
+ "version": "2.4.3",
4
4
  "design": "v1",
5
5
  "description": "Dropdown variants for Wonder Blocks.",
6
6
  "main": "dist/index.js",
@@ -15,30 +15,31 @@
15
15
  "access": "public"
16
16
  },
17
17
  "dependencies": {
18
- "@khanacademy/wonder-blocks-button": "^2.9.12",
19
- "@khanacademy/wonder-blocks-clickable": "^2.1.1",
20
- "@khanacademy/wonder-blocks-color": "^1.1.17",
21
- "@khanacademy/wonder-blocks-core": "^3.1.3",
22
- "@khanacademy/wonder-blocks-icon": "^1.2.20",
23
- "@khanacademy/wonder-blocks-icon-button": "^3.3.12",
24
- "@khanacademy/wonder-blocks-layout": "^1.4.2",
25
- "@khanacademy/wonder-blocks-modal": "^2.1.41",
26
- "@khanacademy/wonder-blocks-spacing": "^3.0.2",
27
- "@khanacademy/wonder-blocks-timing": "^1.2.2",
28
- "@khanacademy/wonder-blocks-typography": "^1.1.24"
18
+ "@babel/runtime": "^7.13.10",
19
+ "@khanacademy/wonder-blocks-button": "^2.9.14",
20
+ "@khanacademy/wonder-blocks-clickable": "^2.1.3",
21
+ "@khanacademy/wonder-blocks-color": "^1.1.19",
22
+ "@khanacademy/wonder-blocks-core": "^3.1.5",
23
+ "@khanacademy/wonder-blocks-icon": "^1.2.22",
24
+ "@khanacademy/wonder-blocks-icon-button": "^3.3.14",
25
+ "@khanacademy/wonder-blocks-layout": "^1.4.4",
26
+ "@khanacademy/wonder-blocks-modal": "^2.1.43",
27
+ "@khanacademy/wonder-blocks-spacing": "^3.0.4",
28
+ "@khanacademy/wonder-blocks-timing": "^2.0.1",
29
+ "@khanacademy/wonder-blocks-typography": "^1.1.26"
29
30
  },
30
31
  "peerDependencies": {
32
+ "@popperjs/core": "^2.10.1",
31
33
  "aphrodite": "^1.2.5",
32
- "popper.js": "^1.14.1",
33
34
  "prop-types": "^15.6.2",
34
35
  "react": "^16.4.1",
35
36
  "react-dom": "^16.4.1",
36
- "react-popper": "^1.0.0",
37
+ "react-popper": "^2.0.0",
37
38
  "react-router-dom": "^4.2.2",
38
39
  "react-window": "^1.8.5"
39
40
  },
40
41
  "devDependencies": {
41
- "wb-dev-build-settings": "^0.0.4"
42
+ "wb-dev-build-settings": "^0.1.2"
42
43
  },
43
- "gitHead": "1e01eef4683b2be90d822eace58bb60ef6e28092"
44
+ "gitHead": "2a21f4ec19e5611fe716237c21f45c9164b65710"
44
45
  }
@@ -662,7 +662,9 @@ describe("DropdownCore", () => {
662
662
  });
663
663
 
664
664
  // Assert
665
- expect(dropdown.find("InnerPopper").text()).toContain("No results");
665
+ expect(dropdown).toContainMatchingElement(
666
+ `[data-test-id="dropdown-core-no-results"]`,
667
+ );
666
668
  });
667
669
 
668
670
  it("When SearchTextInput has input and focused, tab key should not close the select", () => {
@@ -19,11 +19,6 @@ import type {
19
19
  WithActionSchedulerProps,
20
20
  WithoutActionScheduler,
21
21
  } from "@khanacademy/wonder-blocks-timing";
22
- // NOTE(jeff): Here we share some code for use with PopperJS. Long term,
23
- // we should either contribute this code to the PopperJS component, or its
24
- // own non-wonder-blocks package.
25
- // $FlowIgnore
26
- import visibilityModifierDefaultConfig from "../../../../shared-unpackaged/visibility-modifier.js"; // eslint-disable-line import/no-restricted-paths
27
22
  import DropdownCoreVirtualized from "./dropdown-core-virtualized.js";
28
23
  import SeparatorItem from "./separator-item.js";
29
24
  import SearchTextInput from "./search-text-input.js";
@@ -639,7 +634,7 @@ class DropdownCore extends React.Component<Props, State> {
639
634
  });
640
635
  }
641
636
 
642
- renderItems(outOfBoundaries: ?boolean): React.Node {
637
+ renderItems(isReferenceHidden: ?boolean): React.Node {
643
638
  const {dropdownStyle, light, openerElement} = this.props;
644
639
 
645
640
  // The dropdown width is at least the width of the opener.
@@ -662,7 +657,7 @@ class DropdownCore extends React.Component<Props, State> {
662
657
  style={[
663
658
  styles.dropdown,
664
659
  light && styles.light,
665
- outOfBoundaries && styles.hidden,
660
+ isReferenceHidden && styles.hidden,
666
661
  {minWidth: minDropdownWidth},
667
662
  dropdownStyle,
668
663
  ]}
@@ -690,24 +685,39 @@ class DropdownCore extends React.Component<Props, State> {
690
685
  if (modalHost) {
691
686
  return ReactDOM.createPortal(
692
687
  <Popper
693
- innerRef={(node) => {
688
+ innerRef={(node: ?HTMLElement) => {
694
689
  if (node) {
695
690
  this.popperElement = node;
696
691
  }
697
692
  }}
698
693
  referenceElement={this.props.openerElement}
694
+ strategy="fixed"
699
695
  placement={
700
696
  alignment === "left" ? "bottom-start" : "bottom-end"
701
697
  }
702
- modifiers={{
703
- wbVisibility: visibilityModifierDefaultConfig,
704
- preventOverflow: {
705
- boundariesElement: "viewport",
706
- escapeWithReference: true,
698
+ modifiers={[
699
+ {
700
+ name: "preventOverflow",
701
+ options: {
702
+ rootBoundary: "viewport",
703
+ // Allows to overlap the popper in case there's
704
+ // no more vertical room in the viewport.
705
+ altAxis: true,
706
+ // Also needed to make sure the Popper will be
707
+ // displayed correctly in different contexts
708
+ // (e.g inside a Modal)
709
+ tether: false,
710
+ },
707
711
  },
708
- }}
712
+ ]}
709
713
  >
710
- {({placement, ref, style, outOfBoundaries}) => {
714
+ {({
715
+ placement,
716
+ ref,
717
+ style,
718
+ hasPopperEscaped,
719
+ isReferenceHidden,
720
+ }) => {
711
721
  // For some reason react-popper includes `pointerEvents: "none"`
712
722
  // in the `style` it passes to us, but only when running the tests.
713
723
  const {pointerEvents: _, ...restStyle} = style;
@@ -717,7 +727,9 @@ class DropdownCore extends React.Component<Props, State> {
717
727
  style={restStyle}
718
728
  data-placement={placement}
719
729
  >
720
- {this.renderItems(outOfBoundaries)}
730
+ {this.renderItems(
731
+ hasPopperEscaped || isReferenceHidden,
732
+ )}
721
733
  </div>
722
734
  );
723
735
  }}
@@ -767,6 +779,7 @@ const styles = StyleSheet.create({
767
779
  },
768
780
 
769
781
  hidden: {
782
+ pointerEvents: "none",
770
783
  visibility: "hidden",
771
784
  },
772
785
 
@@ -2,8 +2,13 @@
2
2
  import * as React from "react";
3
3
  import {StyleSheet} from "aphrodite";
4
4
 
5
+ import Button from "@khanacademy/wonder-blocks-button";
5
6
  import {View} from "@khanacademy/wonder-blocks-core";
6
7
  import {SingleSelect, OptionItem} from "@khanacademy/wonder-blocks-dropdown";
8
+ import {Strut} from "@khanacademy/wonder-blocks-layout";
9
+ import {OnePaneDialog, ModalLauncher} from "@khanacademy/wonder-blocks-modal";
10
+ import Spacing from "@khanacademy/wonder-blocks-spacing";
11
+ import {Body} from "@khanacademy/wonder-blocks-typography";
7
12
 
8
13
  import type {StoryComponentType} from "@storybook/react";
9
14
 
@@ -89,6 +94,14 @@ const styles = StyleSheet.create({
89
94
  height: "800px",
90
95
  width: "1200px",
91
96
  },
97
+ centered: {
98
+ alignItems: "center",
99
+ justifyContent: "center",
100
+ height: `calc(100vh - 16px)`,
101
+ },
102
+ scrollableArea: {
103
+ height: "200vh",
104
+ },
92
105
  });
93
106
 
94
107
  export const WithFilter: StoryComponentType = () => <SingleSelectWithFilter />;
@@ -105,3 +118,58 @@ WithFilter.story = {
105
118
  export const WithFilterOpened: StoryComponentType = () => (
106
119
  <SingleSelectWithFilter opened={true} />
107
120
  );
121
+
122
+ export const DropdownInModal: StoryComponentType = () => {
123
+ const [value, setValue] = React.useState(null);
124
+ const [opened, setOpened] = React.useState(true);
125
+
126
+ const modalContent = (
127
+ <View style={styles.scrollableArea}>
128
+ <View>
129
+ <Body>
130
+ Sometimes we want to include Dropdowns inside a Modal, and
131
+ these controls can be accessed only by scrolling down. This
132
+ example help us to demonstrate that SingleSelect components
133
+ can correctly be displayed within the visible scrolling
134
+ area.
135
+ </Body>
136
+ <Strut size={Spacing.large_24} />
137
+ <SingleSelect
138
+ onChange={(selected) => setValue(selected)}
139
+ isFilterable={true}
140
+ opened={opened}
141
+ onToggle={(opened) => setOpened(opened)}
142
+ placeholder="Select a fruit"
143
+ selectedValue={value}
144
+ >
145
+ {optionItems}
146
+ </SingleSelect>
147
+ </View>
148
+ </View>
149
+ );
150
+
151
+ const modal = (
152
+ <OnePaneDialog title="Dropdown in a Modal" content={modalContent} />
153
+ );
154
+
155
+ return (
156
+ <View style={styles.centered}>
157
+ <ModalLauncher modal={modal}>
158
+ {({openModal}) => (
159
+ <Button onClick={openModal}>Click here!</Button>
160
+ )}
161
+ </ModalLauncher>
162
+ </View>
163
+ );
164
+ };
165
+
166
+ DropdownInModal.story = {
167
+ name: "Dropdown in a modal",
168
+ parameters: {
169
+ chromatic: {
170
+ // We don't need screenshots because this story can be tested after
171
+ // the modal is opened.
172
+ disable: true,
173
+ },
174
+ },
175
+ };
@@ -1,23 +0,0 @@
1
- // @flow
2
-
3
- describe("@khanacademy/wonder-blocks-dropdown", () => {
4
- test("package exports default", async () => {
5
- // Arrange
6
- const importedModule = import("../index.js");
7
-
8
- // Act
9
- const result = await importedModule;
10
-
11
- // Assert
12
- expect(Object.keys(result).sort()).toEqual(
13
- [
14
- "ActionItem",
15
- "ActionMenu",
16
- "MultiSelect",
17
- "OptionItem",
18
- "SeparatorItem",
19
- "SingleSelect",
20
- ].sort(),
21
- );
22
- });
23
- });