@khanacademy/wonder-blocks-dropdown 2.10.2 → 2.10.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/dist/index.js DELETED
@@ -1,3502 +0,0 @@
1
- module.exports =
2
- /******/ (function(modules) { // webpackBootstrap
3
- /******/ // The module cache
4
- /******/ var installedModules = {};
5
- /******/
6
- /******/ // The require function
7
- /******/ function __webpack_require__(moduleId) {
8
- /******/
9
- /******/ // Check if module is in cache
10
- /******/ if(installedModules[moduleId]) {
11
- /******/ return installedModules[moduleId].exports;
12
- /******/ }
13
- /******/ // Create a new module (and put it into the cache)
14
- /******/ var module = installedModules[moduleId] = {
15
- /******/ i: moduleId,
16
- /******/ l: false,
17
- /******/ exports: {}
18
- /******/ };
19
- /******/
20
- /******/ // Execute the module function
21
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
22
- /******/
23
- /******/ // Flag the module as loaded
24
- /******/ module.l = true;
25
- /******/
26
- /******/ // Return the exports of the module
27
- /******/ return module.exports;
28
- /******/ }
29
- /******/
30
- /******/
31
- /******/ // expose the modules object (__webpack_modules__)
32
- /******/ __webpack_require__.m = modules;
33
- /******/
34
- /******/ // expose the module cache
35
- /******/ __webpack_require__.c = installedModules;
36
- /******/
37
- /******/ // define getter function for harmony exports
38
- /******/ __webpack_require__.d = function(exports, name, getter) {
39
- /******/ if(!__webpack_require__.o(exports, name)) {
40
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
41
- /******/ }
42
- /******/ };
43
- /******/
44
- /******/ // define __esModule on exports
45
- /******/ __webpack_require__.r = function(exports) {
46
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
47
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
48
- /******/ }
49
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
50
- /******/ };
51
- /******/
52
- /******/ // create a fake namespace object
53
- /******/ // mode & 1: value is a module id, require it
54
- /******/ // mode & 2: merge all properties of value into the ns
55
- /******/ // mode & 4: return value when already ns object
56
- /******/ // mode & 8|1: behave like require
57
- /******/ __webpack_require__.t = function(value, mode) {
58
- /******/ if(mode & 1) value = __webpack_require__(value);
59
- /******/ if(mode & 8) return value;
60
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
61
- /******/ var ns = Object.create(null);
62
- /******/ __webpack_require__.r(ns);
63
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
64
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
65
- /******/ return ns;
66
- /******/ };
67
- /******/
68
- /******/ // getDefaultExport function for compatibility with non-harmony modules
69
- /******/ __webpack_require__.n = function(module) {
70
- /******/ var getter = module && module.__esModule ?
71
- /******/ function getDefault() { return module['default']; } :
72
- /******/ function getModuleExports() { return module; };
73
- /******/ __webpack_require__.d(getter, 'a', getter);
74
- /******/ return getter;
75
- /******/ };
76
- /******/
77
- /******/ // Object.prototype.hasOwnProperty.call
78
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
79
- /******/
80
- /******/ // __webpack_public_path__
81
- /******/ __webpack_require__.p = "";
82
- /******/
83
- /******/
84
- /******/ // Load entry module and return exports
85
- /******/ return __webpack_require__(__webpack_require__.s = 36);
86
- /******/ })
87
- /************************************************************************/
88
- /******/ ([
89
- /* 0 */
90
- /***/ (function(module, exports) {
91
-
92
- module.exports = require("react");
93
-
94
- /***/ }),
95
- /* 1 */
96
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
97
-
98
- "use strict";
99
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return keyCodes; });
100
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return selectDropdownStyle; });
101
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return filterableDropdownStyle; });
102
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DROPDOWN_ITEM_HEIGHT; });
103
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return MAX_VISIBLE_ITEMS; });
104
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return SEPARATOR_ITEM_HEIGHT; });
105
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return defaultLabels; });
106
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
107
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_0__);
108
-
109
- const keyCodes = {
110
- tab: 9,
111
- enter: 13,
112
- escape: 27,
113
- space: 32,
114
- up: 38,
115
- down: 40
116
- };
117
- const selectDropdownStyle = {
118
- marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_0___default.a.xSmall_8,
119
- marginBottom: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_0___default.a.xSmall_8
120
- }; // Filterable dropdown has minimum dimensions requested from Design.
121
- // Note that these can be overridden by the provided style if needed.
122
-
123
- const filterableDropdownStyle = {
124
- minHeight: 100
125
- }; // The default item height
126
-
127
- const DROPDOWN_ITEM_HEIGHT = 40;
128
- /**
129
- * Maximum visible items inside the dropdown list. Based on the defined height
130
- * that we're using, this is the maximum number of items that can fit into the
131
- * visible portion of the dropdown's listbox.
132
- */
133
-
134
- const MAX_VISIBLE_ITEMS = 9;
135
- const SEPARATOR_ITEM_HEIGHT = 9; // The default labels that will be used by different components
136
-
137
- const defaultLabels = {
138
- clearSearch: "Clear search",
139
- filter: "Filter",
140
- noResults: "No results",
141
- selectNoneLabel: "Select none",
142
- selectAllLabel: numOptions => `Select all (${numOptions})`,
143
- noneSelected: "0 items",
144
- someSelected: numSelectedValues => `${numSelectedValues} items`,
145
- allSelected: "All items"
146
- };
147
-
148
- /***/ }),
149
- /* 2 */
150
- /***/ (function(module, exports) {
151
-
152
- module.exports = require("@khanacademy/wonder-blocks-color");
153
-
154
- /***/ }),
155
- /* 3 */
156
- /***/ (function(module, exports) {
157
-
158
- module.exports = require("@khanacademy/wonder-blocks-spacing");
159
-
160
- /***/ }),
161
- /* 4 */
162
- /***/ (function(module, exports) {
163
-
164
- module.exports = require("aphrodite");
165
-
166
- /***/ }),
167
- /* 5 */
168
- /***/ (function(module, exports) {
169
-
170
- module.exports = require("@khanacademy/wonder-blocks-core");
171
-
172
- /***/ }),
173
- /* 6 */
174
- /***/ (function(module, exports) {
175
-
176
- function _extends() {
177
- module.exports = _extends = Object.assign ? Object.assign.bind() : function (target) {
178
- for (var i = 1; i < arguments.length; i++) {
179
- var source = arguments[i];
180
- for (var key in source) {
181
- if (Object.prototype.hasOwnProperty.call(source, key)) {
182
- target[key] = source[key];
183
- }
184
- }
185
- }
186
- return target;
187
- }, module.exports.__esModule = true, module.exports["default"] = module.exports;
188
- return _extends.apply(this, arguments);
189
- }
190
- module.exports = _extends, module.exports.__esModule = true, module.exports["default"] = module.exports;
191
-
192
- /***/ }),
193
- /* 7 */
194
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
195
-
196
- "use strict";
197
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SeparatorItem; });
198
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
199
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
200
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
201
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
202
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
203
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__);
204
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
205
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3__);
206
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5);
207
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_4__);
208
- // Separator item in a dropdown, used to denote a semantic break.
209
- // Actualized as a horizontal line with surrounding whitespace. -----
210
-
211
-
212
-
213
-
214
-
215
-
216
- /**
217
- * A separator used in a dropdown menu.
218
- */
219
- class SeparatorItem extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
220
- static isClassOf(instance) {
221
- return instance && instance.type && instance.type.__IS_SEPARATOR_ITEM__;
222
- }
223
-
224
- render() {
225
- return (
226
- /*#__PURE__*/
227
- // pass optional styles from react-window (if applies)
228
- react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_4__["View"], {
229
- style: [styles.separator, this.props.style],
230
- "aria-hidden": "true"
231
- })
232
- );
233
- }
234
-
235
- }
236
- SeparatorItem.__IS_SEPARATOR_ITEM__ = true;
237
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
238
- separator: {
239
- boxShadow: `0 -1px ${_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.offBlack16}`,
240
- height: 1,
241
- minHeight: 1,
242
- marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xxxSmall_4,
243
- marginBottom: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xxxSmall_4
244
- }
245
- });
246
-
247
- /***/ }),
248
- /* 8 */
249
- /***/ (function(module, exports) {
250
-
251
- module.exports = require("react-dom");
252
-
253
- /***/ }),
254
- /* 9 */
255
- /***/ (function(module, exports) {
256
-
257
- module.exports = require("@khanacademy/wonder-blocks-icon");
258
-
259
- /***/ }),
260
- /* 10 */
261
- /***/ (function(module, exports) {
262
-
263
- module.exports = require("@khanacademy/wonder-blocks-typography");
264
-
265
- /***/ }),
266
- /* 11 */
267
- /***/ (function(module, exports) {
268
-
269
- module.exports = require("@khanacademy/wonder-blocks-clickable");
270
-
271
- /***/ }),
272
- /* 12 */
273
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
274
-
275
- "use strict";
276
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ActionItem; });
277
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
278
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
279
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
280
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
281
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
282
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_2__);
283
- /* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25);
284
- /* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_3__);
285
- /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17);
286
- /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_router__WEBPACK_IMPORTED_MODULE_4__);
287
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(2);
288
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5__);
289
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3);
290
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6__);
291
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(10);
292
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_7__);
293
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(11);
294
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_8__);
295
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5);
296
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9__);
297
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(1);
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
- const {
310
- blue,
311
- white,
312
- offBlack,
313
- offBlack32
314
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5___default.a;
315
- const StyledAnchor = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9__["addStyle"])("a");
316
- const StyledButton = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9__["addStyle"])("button");
317
- const StyledLink = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_9__["addStyle"])(react_router_dom__WEBPACK_IMPORTED_MODULE_3__["Link"]);
318
- /**
319
- * The action item trigger actions, such as navigating to a different page or
320
- * opening a modal. Supply the href and/or onClick props. Used as a child of
321
- * ActionMenu.
322
- */
323
-
324
- class ActionItem extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
325
- static isClassOf(instance) {
326
- return instance && instance.type && instance.type.__IS_ACTION_ITEM__;
327
- }
328
-
329
- renderClickableBehavior(router) {
330
- const {
331
- skipClientNav,
332
- disabled,
333
- href,
334
- target,
335
- indent,
336
- label,
337
- lang,
338
- onClick,
339
- role,
340
- style,
341
- testId
342
- } = this.props;
343
- const ClickableBehavior = Object(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_8__["getClickableBehavior"])(href, skipClientNav, router);
344
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](ClickableBehavior, {
345
- disabled: disabled,
346
- onClick: onClick,
347
- href: href,
348
- role: role,
349
- target: target
350
- }, (state, childrenProps) => {
351
- const {
352
- pressed,
353
- hovered,
354
- focused
355
- } = state;
356
- const defaultStyle = [styles.shared, disabled && styles.disabled, !disabled && (pressed ? styles.active : (hovered || focused) && styles.focus), // pass optional styles from react-window (if applies)
357
- style];
358
- const props = {
359
- "data-test-id": testId,
360
- disabled,
361
- role,
362
- style: [defaultStyle],
363
- ...childrenProps
364
- };
365
- const children = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react__WEBPACK_IMPORTED_MODULE_1__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_7__["LabelMedium"], {
366
- lang: lang,
367
- style: [indent && styles.indent, styles.label]
368
- }, label));
369
-
370
- if (href && !disabled) {
371
- return router && !skipClientNav && Object(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_8__["isClientSideUrl"])(href) ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](StyledLink, _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, props, {
372
- to: href
373
- }), children) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](StyledAnchor, _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, props, {
374
- href: href,
375
- target: target
376
- }), children);
377
- } else {
378
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](StyledButton, _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({
379
- type: "button"
380
- }, props, {
381
- disabled: disabled
382
- }), children);
383
- }
384
- });
385
- }
386
-
387
- render() {
388
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react_router__WEBPACK_IMPORTED_MODULE_4__["__RouterContext"].Consumer, null, router => this.renderClickableBehavior(router));
389
- }
390
-
391
- }
392
- ActionItem.defaultProps = {
393
- disabled: false,
394
- indent: false,
395
- role: "menuitem"
396
- };
397
- ActionItem.__IS_ACTION_ITEM__ = true;
398
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create({
399
- shared: {
400
- background: white,
401
- color: offBlack,
402
- textDecoration: "none",
403
- border: "none",
404
- outline: "none",
405
- flexDirection: "row",
406
- alignItems: "center",
407
- display: "flex",
408
- height: _util_constants_js__WEBPACK_IMPORTED_MODULE_10__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
409
- minHeight: _util_constants_js__WEBPACK_IMPORTED_MODULE_10__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
410
- paddingLeft: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6___default.a.medium_16,
411
- paddingRight: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6___default.a.medium_16,
412
- // This removes the 300ms click delay on mobile browsers by indicating that
413
- // "double-tap to zoom" shouldn't be used on this element.
414
- touchAction: "manipulation"
415
- },
416
- label: {
417
- whiteSpace: "nowrap",
418
- userSelect: "none"
419
- },
420
- indent: {
421
- marginLeft: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_6___default.a.medium_16
422
- },
423
- // hover and focus states
424
- focus: {
425
- color: white,
426
- background: blue
427
- },
428
- // active and pressed states
429
- active: {
430
- color: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5__["fade"])(blue, 0.32), white),
431
- background: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_5__["mix"])(offBlack32, blue)
432
- },
433
- // disabled state
434
- disabled: {
435
- color: offBlack32,
436
- cursor: "default"
437
- }
438
- });
439
-
440
- /***/ }),
441
- /* 13 */
442
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
443
-
444
- "use strict";
445
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return OptionItem; });
446
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
447
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
448
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
449
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
450
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
451
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_2__);
452
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2);
453
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3__);
454
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3);
455
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4__);
456
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(10);
457
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_5__);
458
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5);
459
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__);
460
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(11);
461
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_7__);
462
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1);
463
- /* harmony import */ var _check_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(26);
464
- /* harmony import */ var _checkbox_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(27);
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
- /**
478
- * For option items that can be selected in a dropdown, selection denoted either
479
- * with a check ✔️ or a checkbox ☑️. Use as children in SingleSelect or
480
- * MultiSelect.
481
- */
482
- class OptionItem extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
483
- constructor(...args) {
484
- super(...args);
485
-
486
- this.handleClick = () => {
487
- const {
488
- onClick,
489
- onToggle,
490
- value
491
- } = this.props;
492
- onToggle(value);
493
-
494
- if (onClick) {
495
- onClick();
496
- }
497
- };
498
- }
499
-
500
- static isClassOf(instance) {
501
- return instance && instance.type && instance.type.__IS_OPTION_ITEM__;
502
- }
503
-
504
- getCheckComponent() {
505
- if (this.props.variant === "check") {
506
- return _check_js__WEBPACK_IMPORTED_MODULE_9__[/* default */ "a"];
507
- } else {
508
- return _checkbox_js__WEBPACK_IMPORTED_MODULE_10__[/* default */ "a"];
509
- }
510
- }
511
-
512
- render() {
513
- const {
514
- disabled,
515
- label,
516
- role,
517
- selected,
518
- testId,
519
- style,
520
- // eslint-disable-next-line no-unused-vars
521
- value,
522
-
523
- /* eslint-disable no-unused-vars */
524
- onClick,
525
- onToggle,
526
- variant,
527
-
528
- /* eslint-enable no-unused-vars */
529
- ...sharedProps
530
- } = this.props;
531
- const ClickableBehavior = Object(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_7__["getClickableBehavior"])();
532
- const CheckComponent = this.getCheckComponent();
533
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](ClickableBehavior, {
534
- disabled: disabled,
535
- onClick: this.handleClick,
536
- role: role,
537
- tabIndex: 0
538
- }, (state, childrenProps) => {
539
- const {
540
- pressed,
541
- hovered,
542
- focused
543
- } = state;
544
- const defaultStyle = [styles.itemContainer, pressed ? styles.active : (hovered || focused) && styles.focus, disabled && styles.disabled, // pass optional styles from react-window (if applies)
545
- style];
546
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__["View"], _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, sharedProps, {
547
- testId: testId,
548
- style: defaultStyle,
549
- "aria-selected": selected ? "true" : "false",
550
- role: role
551
- }, childrenProps), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](CheckComponent, {
552
- disabled: disabled,
553
- selected: selected,
554
- pressed: pressed,
555
- hovered: hovered,
556
- focused: focused
557
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_5__["LabelMedium"], {
558
- style: styles.label
559
- }, label));
560
- });
561
- }
562
-
563
- }
564
- OptionItem.defaultProps = {
565
- disabled: false,
566
- onToggle: () => void 0,
567
- role: "option",
568
- selected: false
569
- };
570
- OptionItem.__IS_OPTION_ITEM__ = true;
571
- const {
572
- blue,
573
- white,
574
- offBlack,
575
- offBlack32
576
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3___default.a;
577
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create({
578
- itemContainer: {
579
- flexDirection: "row",
580
- background: white,
581
- color: offBlack,
582
- alignItems: "center",
583
- height: _util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
584
- minHeight: _util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
585
- border: 0,
586
- outline: 0,
587
- paddingLeft: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8,
588
- paddingRight: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.medium_16,
589
- whiteSpace: "nowrap",
590
- cursor: "default"
591
- },
592
- focus: {
593
- color: white,
594
- background: blue
595
- },
596
- active: {
597
- color: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3__["fade"])(blue, 0.32), white),
598
- background: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_3__["mix"])(offBlack32, blue)
599
- },
600
- disabled: {
601
- color: offBlack32,
602
- background: white
603
- },
604
- label: {
605
- whiteSpace: "nowrap",
606
- userSelect: "none",
607
- marginLeft: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8,
608
- // added to truncate strings that are longer than expected
609
- overflow: "hidden",
610
- textOverflow: "ellipsis"
611
- },
612
- hide: {
613
- visibility: "hidden"
614
- }
615
- });
616
-
617
- /***/ }),
618
- /* 14 */
619
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
620
-
621
- "use strict";
622
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
623
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
624
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
625
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_1__);
626
-
627
-
628
-
629
- class DropdownOpener extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
630
- constructor(...args) {
631
- super(...args);
632
-
633
- this.getTestIdFromProps = childrenProps => {
634
- return childrenProps.testId || childrenProps["data-test-id"];
635
- };
636
- }
637
-
638
- renderAnchorChildren(eventState, clickableChildrenProps) {
639
- const {
640
- disabled,
641
- testId,
642
- text
643
- } = this.props;
644
- const renderedChildren = this.props.children({ ...eventState,
645
- text
646
- });
647
- const childrenProps = renderedChildren.props;
648
- const childrenTestId = this.getTestIdFromProps(childrenProps);
649
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](renderedChildren, { ...clickableChildrenProps,
650
- disabled,
651
- onClick: childrenProps.onClick ? e => {
652
- // This is done to avoid overriding a
653
- // custom onClick handler inside the
654
- // children node
655
- childrenProps.onClick(e);
656
- clickableChildrenProps.onClick(e);
657
- } : clickableChildrenProps.onClick,
658
- // try to get the testId from the child element
659
- // If it's not set, try to fallback to the parent's testId
660
- "data-test-id": childrenTestId || testId
661
- });
662
- }
663
-
664
- render() {
665
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_1__["ClickableBehavior"], {
666
- onClick: this.props.onClick,
667
- disabled: this.props.disabled
668
- }, (eventState, handlers) => this.renderAnchorChildren(eventState, handlers));
669
- }
670
-
671
- }
672
-
673
- DropdownOpener.defaultProps = {
674
- disabled: false
675
- };
676
- /* harmony default export */ __webpack_exports__["a"] = (DropdownOpener);
677
-
678
- /***/ }),
679
- /* 15 */
680
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
681
-
682
- "use strict";
683
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
684
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
685
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
686
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
687
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
688
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_2__);
689
- /* harmony import */ var react_window__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20);
690
- /* harmony import */ var react_window__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_window__WEBPACK_IMPORTED_MODULE_3__);
691
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2);
692
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__);
693
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3);
694
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5__);
695
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5);
696
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__);
697
- /* harmony import */ var _khanacademy_wonder_blocks_search_field__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(28);
698
- /* harmony import */ var _khanacademy_wonder_blocks_search_field__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_search_field__WEBPACK_IMPORTED_MODULE_7__);
699
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(10);
700
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_8__);
701
- /* harmony import */ var _khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(18);
702
- /* harmony import */ var _khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_9__);
703
- /* harmony import */ var _dropdown_core_virtualized_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(29);
704
- /* harmony import */ var _separator_item_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(7);
705
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(1);
706
- /* harmony import */ var _dropdown_popper_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(31);
707
- /* harmony import */ var _util_helpers_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(21);
708
- /* harmony import */ var _util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(16);
709
- /* eslint-disable max-lines */
710
- // A menu that consists of action items
711
-
712
-
713
-
714
-
715
-
716
-
717
-
718
-
719
-
720
-
721
-
722
-
723
-
724
-
725
-
726
-
727
- /**
728
- * The number of options to apply the virtualized list to.
729
- *
730
- * NOTE: The threshold is defined taking into account performance
731
- * implications (e.g. process input events for users should not be longer
732
- * than 100ms).
733
- * @see https://web.dev/rail/?utm_source=devtools#goals-and-guidelines
734
- *
735
- * TODO(juan, WB-1263): Improve performance by refactoring this component.
736
- */
737
-
738
- const VIRTUALIZE_THRESHOLD = 125;
739
- const StyledSpan = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__["addStyle"])("span");
740
-
741
- /**
742
- * A core dropdown component that takes an opener and children to display as
743
- * part of the dropdown menu. Renders the dropdown as a portal to avoid clipping
744
- * in overflow: auto containers.
745
- */
746
- class DropdownCore extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
747
- // Keeps track of the index of the focused item, out of a list of focusable items
748
- // Keeps track of the index of the focused item in the context of all the
749
- // items contained by this menu, whether focusable or not, used for figuring
750
- // out focus correctly when the items have changed in terms of whether
751
- // they're focusable or not
752
- // Whether any items have been selected since the menu was opened
753
- // Keeps a reference of the virtualized list instance
754
- // Figure out if the same items are focusable. If an item has been added or
755
- // removed, this method will return false.
756
- static sameItemsFocusable(prevItems, currentItems) {
757
- if (prevItems.length !== currentItems.length) {
758
- return false;
759
- }
760
-
761
- for (let i = 0; i < prevItems.length; i++) {
762
- if (prevItems[i].focusable !== currentItems[i].focusable) {
763
- return false;
764
- }
765
- }
766
-
767
- return true;
768
- }
769
-
770
- // This is here to avoid calling React.createRef on each rerender. Instead,
771
- // we create the itemRefs only if it's the first time or if the set of items
772
- // that are focusable has changed.
773
- static getDerivedStateFromProps(props, state) {
774
- if (state.itemRefs.length === 0 && props.open || !DropdownCore.sameItemsFocusable(state.prevItems, props.items)) {
775
- const itemRefs = [];
776
-
777
- for (let i = 0; i < props.items.length; i++) {
778
- if (props.items[i].focusable) {
779
- const ref = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createRef"]();
780
- itemRefs.push({
781
- ref,
782
- originalIndex: i
783
- });
784
- }
785
- }
786
-
787
- return {
788
- itemRefs,
789
- prevItems: props.items,
790
- sameItemsFocusable: false
791
- };
792
- } else {
793
- return {
794
- prevItems: props.items,
795
- sameItemsFocusable: true
796
- };
797
- }
798
- }
799
-
800
- constructor(props) {
801
- super(props); // Apply our initial focus index
802
-
803
- this.searchFieldRef = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createRef"]();
804
-
805
- this.handleInteract = event => {
806
- const {
807
- open,
808
- onOpenChanged
809
- } = this.props;
810
- const target = event.target;
811
- const thisElement = react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.findDOMNode(this);
812
-
813
- if (open && thisElement && !thisElement.contains(target) && this.popperElement && !this.popperElement.contains(target)) {
814
- onOpenChanged(false);
815
- }
816
- };
817
-
818
- this.handleKeyDown = event => {
819
- const {
820
- enableTypeAhead,
821
- onOpenChanged,
822
- open,
823
- searchText
824
- } = this.props;
825
- const keyCode = event.which || event.keyCode; // Listen for the keydown events if we are using ASCII characters.
826
-
827
- if (enableTypeAhead && Object(_util_helpers_js__WEBPACK_IMPORTED_MODULE_14__[/* getStringForKey */ "b"])(event.key)) {
828
- event.stopPropagation();
829
- this.textSuggestion += event.key; // Trigger the filter logic only after the debounce is resolved.
830
-
831
- this.handleKeyDownDebounced(this.textSuggestion);
832
- } // If menu isn't open and user presses down, open the menu
833
-
834
-
835
- if (!open) {
836
- if (keyCode === _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].down) {
837
- event.preventDefault();
838
- onOpenChanged(true);
839
- return;
840
- }
841
-
842
- return;
843
- } // Handle all other key behavior
844
-
845
-
846
- switch (keyCode) {
847
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].tab:
848
- // When we show SearchField and that is focused and the
849
- // searchText is entered at least one character, dismiss button
850
- // is displayed. When user presses tab, we should move focus to
851
- // the dismiss button.
852
- if (this.isSearchFieldFocused() && searchText) {
853
- return;
854
- }
855
-
856
- this.restoreTabOrder();
857
- onOpenChanged(false);
858
- return;
859
-
860
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].space:
861
- // When we display SearchField and the focus is on it, we should
862
- // let the user type space.
863
- if (this.isSearchFieldFocused()) {
864
- return;
865
- } // Prevent space from scrolling down the page
866
-
867
-
868
- event.preventDefault();
869
- return;
870
-
871
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].up:
872
- event.preventDefault();
873
- this.focusPreviousItem();
874
- return;
875
-
876
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].down:
877
- event.preventDefault();
878
- this.focusNextItem();
879
- return;
880
- }
881
- };
882
-
883
- this.handleKeyUp = event => {
884
- const {
885
- onOpenChanged,
886
- open
887
- } = this.props;
888
- const keyCode = event.which || event.keyCode;
889
-
890
- switch (keyCode) {
891
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].space:
892
- // When we display SearchField and the focus is on it, we should
893
- // let the user type space.
894
- if (this.isSearchFieldFocused()) {
895
- return;
896
- } // Prevent space from scrolling down the page
897
-
898
-
899
- event.preventDefault();
900
- return;
901
-
902
- case _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* keyCodes */ "f"].escape:
903
- // Close only the dropdown, not other elements that are
904
- // listening for an escape press
905
- if (open) {
906
- event.stopPropagation();
907
- this.restoreTabOrder();
908
- onOpenChanged(false);
909
- }
910
-
911
- return;
912
- }
913
- };
914
-
915
- this.handleKeyDownDebounceResult = key => {
916
- const foundIndex = this.props.items.filter(item => item.focusable).findIndex(({
917
- component
918
- }) => {
919
- var _component$props;
920
-
921
- if (_separator_item_js__WEBPACK_IMPORTED_MODULE_11__[/* default */ "a"].isClassOf(component)) {
922
- return false;
923
- } // Flow doesn't know that the component is an OptionItem
924
- // $FlowIgnore[incompatible-use]
925
-
926
-
927
- const label = (_component$props = component.props) == null ? void 0 : _component$props.label.toLowerCase();
928
- return label.startsWith(key.toLowerCase());
929
- });
930
-
931
- if (foundIndex >= 0) {
932
- const isClosed = !this.props.open;
933
-
934
- if (isClosed) {
935
- // Open the menu to be able to focus on the item that matches
936
- // the text suggested.
937
- this.props.onOpenChanged(true);
938
- } // Update the focus reference.
939
-
940
-
941
- this.focusedIndex = foundIndex;
942
- this.scheduleToFocusCurrentItem(node => {
943
- // Force click only if the dropdown is closed and we are using
944
- // the SingleSelect component.
945
- if (this.props.selectionType === "single" && isClosed && node) {
946
- node.click();
947
- this.props.onOpenChanged(false);
948
- }
949
- });
950
- } // Otherwise, reset current text
951
-
952
-
953
- this.textSuggestion = "";
954
- };
955
-
956
- this.handleClickFocus = index => {
957
- // Turn itemsClicked on so pressing up or down would focus the
958
- // appropriate item in handleKeyDown
959
- this.itemsClicked = true;
960
- this.focusedIndex = index;
961
- this.focusedOriginalIndex = this.state.itemRefs[this.focusedIndex].originalIndex;
962
- };
963
-
964
- this.handleDropdownMouseUp = event => {
965
- // $FlowIgnore[method-unbinding]
966
- if (event.nativeEvent.stopImmediatePropagation) {
967
- event.nativeEvent.stopImmediatePropagation();
968
- } else {
969
- // Workaround for jsdom
970
- event.stopPropagation();
971
- }
972
- };
973
-
974
- this.handleItemClick = (focusIndex, item) => {
975
- this.handleClickFocus(focusIndex);
976
-
977
- if (item.component.props.onClick) {
978
- item.component.props.onClick();
979
- }
980
-
981
- if (item.populatedProps.onClick) {
982
- item.populatedProps.onClick();
983
- }
984
- };
985
-
986
- this.handleSearchTextChanged = searchText => {
987
- const {
988
- onSearchTextChanged
989
- } = this.props;
990
-
991
- if (onSearchTextChanged) {
992
- onSearchTextChanged(searchText);
993
- }
994
- };
995
-
996
- this.resetFocusedIndex();
997
- this.state = {
998
- prevItems: this.props.items,
999
- itemRefs: [],
1000
- sameItemsFocusable: false,
1001
- labels: {
1002
- noResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].noResults,
1003
- // In case we are not overriding this from the caller.
1004
- someResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].someSelected,
1005
- ...props.labels
1006
- }
1007
- };
1008
- this.virtualizedListRef = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createRef"](); // We debounce the keydown handler to get the ASCII chars because it's
1009
- // called on every keydown
1010
-
1011
- this.handleKeyDownDebounced = Object(_util_helpers_js__WEBPACK_IMPORTED_MODULE_14__[/* debounce */ "a"])(this.handleKeyDownDebounceResult, // Leaving enough time for the user to type a valid query (e.g. jul)
1012
- 500);
1013
- this.textSuggestion = "";
1014
- }
1015
-
1016
- componentDidMount() {
1017
- this.updateEventListeners();
1018
- this.maybeFocusInitialItem();
1019
- }
1020
-
1021
- componentDidUpdate(prevProps) {
1022
- const {
1023
- open
1024
- } = this.props;
1025
-
1026
- if (prevProps.open !== open) {
1027
- this.updateEventListeners();
1028
- this.maybeFocusInitialItem();
1029
- } // If the menu changed, but from open to open, figure out if we need
1030
- // to recalculate the focus somehow.
1031
- else if (open) {
1032
- const {
1033
- itemRefs,
1034
- sameItemsFocusable
1035
- } = this.state; // Check if the same items are focused by comparing the items at
1036
- // each index and seeing if the {focusable} property is the same.
1037
- // Very rarely do the set of focusable items change if the menu
1038
- // hasn't been re-opened. This is for cases like a {Select all}
1039
- // option that becomes disabled iff all the options are selected.
1040
-
1041
- if (sameItemsFocusable) {
1042
- return;
1043
- } else {
1044
- // If the set of items that was focusabled changed, it's very
1045
- // likely that the previously focused item no longer has the
1046
- // same index relative to the list of focusable items. Instead,
1047
- // use the focusedOriginalIndex to find the new index of the
1048
- // last item that was focused before this change
1049
- const newFocusableIndex = itemRefs.findIndex(ref => ref.originalIndex === this.focusedOriginalIndex);
1050
-
1051
- if (newFocusableIndex === -1) {
1052
- // Can't find the originally focused item, return focus to
1053
- // the first item that IS focusable
1054
- this.focusedIndex = 0; // Reset the knowlege that things had been clicked
1055
-
1056
- this.itemsClicked = false;
1057
- this.scheduleToFocusCurrentItem();
1058
- } else {
1059
- this.focusedIndex = newFocusableIndex;
1060
- }
1061
- }
1062
-
1063
- if (this.props.labels !== prevProps.labels) {
1064
- // eslint-disable-next-line react/no-did-update-set-state
1065
- this.setState({
1066
- labels: { ...this.state.labels,
1067
- ...this.props.labels
1068
- }
1069
- });
1070
- }
1071
- }
1072
- }
1073
-
1074
- componentWillUnmount() {
1075
- this.removeEventListeners();
1076
- }
1077
-
1078
- // Resets our initial focus index to what was passed in via the props
1079
- resetFocusedIndex() {
1080
- const {
1081
- initialFocusedIndex
1082
- } = this.props; // If we are given an initial focus index, select it. Otherwise default
1083
- // to the first item
1084
-
1085
- if (typeof initialFocusedIndex !== "undefined") {
1086
- this.focusedIndex = initialFocusedIndex;
1087
- } else {
1088
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1089
- return this.focusSearchField();
1090
- }
1091
-
1092
- this.focusedIndex = 0;
1093
- }
1094
- } // Figure out focus states for the dropdown after it has changed from open
1095
- // to closed or vice versa
1096
-
1097
-
1098
- maybeFocusInitialItem() {
1099
- const {
1100
- autoFocus,
1101
- open
1102
- } = this.props;
1103
-
1104
- if (!autoFocus) {
1105
- return;
1106
- }
1107
-
1108
- if (open) {
1109
- this.resetFocusedIndex();
1110
- this.scheduleToFocusCurrentItem();
1111
- } else if (!open) {
1112
- this.itemsClicked = false;
1113
- }
1114
- }
1115
-
1116
- updateEventListeners() {
1117
- if (this.props.open) {
1118
- this.addEventListeners();
1119
- } else {
1120
- this.removeEventListeners();
1121
- }
1122
- }
1123
-
1124
- addEventListeners() {
1125
- document.addEventListener("mouseup", this.handleInteract);
1126
- document.addEventListener("touchend", this.handleInteract);
1127
- }
1128
-
1129
- removeEventListeners() {
1130
- document.removeEventListener("mouseup", this.handleInteract);
1131
- document.removeEventListener("touchend", this.handleInteract);
1132
- }
1133
-
1134
- scheduleToFocusCurrentItem(onFocus) {
1135
- if (this.shouldVirtualizeList()) {
1136
- // wait for windowed items to be recalculated
1137
- this.props.schedule.animationFrame(() => {
1138
- this.focusCurrentItem(onFocus);
1139
- });
1140
- } else {
1141
- // immediately focus the current item if we're not virtualizing
1142
- this.focusCurrentItem(onFocus);
1143
- }
1144
- }
1145
- /**
1146
- * Focus on the current item.
1147
- * @param [onFocus] - Callback to be called when the item is focused.
1148
- */
1149
-
1150
-
1151
- focusCurrentItem(onFocus) {
1152
- const focusedItemRef = this.state.itemRefs[this.focusedIndex];
1153
-
1154
- if (focusedItemRef) {
1155
- // force react-window to scroll to ensure the focused item is visible
1156
- if (this.virtualizedListRef.current) {
1157
- // Our focused index does not include disabled items, but the
1158
- // react-window index system does include the disabled items
1159
- // in the count. So we need to use "originalIndex", which
1160
- // does account for disabled items.
1161
- this.virtualizedListRef.current.scrollToItem(focusedItemRef.originalIndex);
1162
- }
1163
-
1164
- const node = react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.findDOMNode(focusedItemRef.ref.current);
1165
-
1166
- if (node) {
1167
- node.focus(); // Keep track of the original index of the newly focused item.
1168
- // To be used if the set of focusable items in the menu changes
1169
-
1170
- this.focusedOriginalIndex = focusedItemRef.originalIndex;
1171
-
1172
- if (onFocus) {
1173
- // Call the callback with the node that was focused.
1174
- onFocus(node);
1175
- }
1176
- }
1177
- }
1178
- }
1179
-
1180
- focusSearchField() {
1181
- if (this.searchFieldRef.current) {
1182
- this.searchFieldRef.current.focus();
1183
- }
1184
- }
1185
-
1186
- hasSearchField() {
1187
- return !!this.props.isFilterable;
1188
- }
1189
-
1190
- isSearchFieldFocused() {
1191
- return this.hasSearchField() && document.activeElement === this.searchFieldRef.current;
1192
- }
1193
-
1194
- focusPreviousItem() {
1195
- if (this.focusedIndex === 0) {
1196
- // Move the focus to the search field if it is the first item.
1197
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1198
- return this.focusSearchField();
1199
- }
1200
-
1201
- this.focusedIndex = this.state.itemRefs.length - 1;
1202
- } else {
1203
- this.focusedIndex -= 1;
1204
- }
1205
-
1206
- this.scheduleToFocusCurrentItem();
1207
- }
1208
-
1209
- focusNextItem() {
1210
- if (this.focusedIndex === this.state.itemRefs.length - 1) {
1211
- // Move the focus to the search field if it is the last item.
1212
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1213
- return this.focusSearchField();
1214
- }
1215
-
1216
- this.focusedIndex = 0;
1217
- } else {
1218
- this.focusedIndex += 1;
1219
- }
1220
-
1221
- this.scheduleToFocusCurrentItem();
1222
- }
1223
-
1224
- restoreTabOrder() {
1225
- // NOTE: Because the dropdown is portalled out of its natural
1226
- // position in the DOM, we need to manually return focus to the
1227
- // opener element before we let the natural propagation of tab
1228
- // shift the focus to the next element in the tab order.
1229
- if (this.props.openerElement) {
1230
- this.props.openerElement.focus();
1231
- }
1232
- }
1233
-
1234
- getItemRole() {
1235
- const {
1236
- role
1237
- } = this.props;
1238
-
1239
- switch (role) {
1240
- case "listbox":
1241
- return "option";
1242
-
1243
- case "menu":
1244
- return "menuitem";
1245
-
1246
- default:
1247
- throw new Error(`Expected "listbox" or "menu" for role, but receieved "${role}" instead.`);
1248
- }
1249
- }
1250
-
1251
- maybeRenderNoResults() {
1252
- const {
1253
- items,
1254
- labels: {
1255
- noResults
1256
- }
1257
- } = this.props; // Verify if there are items to be rendered or not
1258
-
1259
- const numResults = items.length;
1260
-
1261
- if (numResults === 0) {
1262
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_8__["LabelMedium"], {
1263
- style: styles.noResult,
1264
- testId: "dropdown-core-no-results"
1265
- }, noResults);
1266
- }
1267
-
1268
- return null;
1269
- }
1270
- /**
1271
- * Handles click events for each item in the dropdown.
1272
- */
1273
-
1274
-
1275
- /**
1276
- * Determines which rendering strategy we are going to apply to the options
1277
- * list.
1278
- */
1279
- shouldVirtualizeList() {
1280
- // Verify if the list is long enough to be virtualized (passes the
1281
- // threshold).
1282
- return this.props.items.length > VIRTUALIZE_THRESHOLD;
1283
- }
1284
- /**
1285
- * Renders the non-virtualized list of items.
1286
- */
1287
-
1288
-
1289
- renderList() {
1290
- let focusCounter = 0;
1291
- const itemRole = this.getItemRole(); // if we don't need to virtualize, we can render the list directly
1292
-
1293
- return this.props.items.map((item, index) => {
1294
- if (_separator_item_js__WEBPACK_IMPORTED_MODULE_11__[/* default */ "a"].isClassOf(item.component)) {
1295
- return item.component;
1296
- }
1297
-
1298
- const {
1299
- component,
1300
- focusable,
1301
- populatedProps
1302
- } = item;
1303
-
1304
- if (focusable) {
1305
- focusCounter += 1;
1306
- }
1307
-
1308
- const focusIndex = focusCounter - 1; // The reference to the item is used to restore focus.
1309
-
1310
- const currentRef = this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null; // Render OptionItem and/or ActionItem elements.
1311
-
1312
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](component, { ...populatedProps,
1313
- key: index,
1314
- onClick: () => {
1315
- this.handleItemClick(focusIndex, item);
1316
- },
1317
- // Only pass the ref if the item is focusable.
1318
- ref: focusable ? currentRef : null,
1319
- role: itemRole
1320
- });
1321
- });
1322
- }
1323
- /**
1324
- * Process the items and wrap them into an array that react-window can
1325
- * interpret.
1326
- *
1327
- * NOTE: The main difference with the collection in renderList() is that we
1328
- * massage the items to be able to clone them later in
1329
- * DropdownVirtualizedItem, where as renderList() clones the items directly.
1330
- */
1331
-
1332
-
1333
- parseVirtualizedItems() {
1334
- let focusCounter = 0;
1335
- const itemRole = this.getItemRole();
1336
- return this.props.items.map((item, index) => {
1337
- if (!_separator_item_js__WEBPACK_IMPORTED_MODULE_11__[/* default */ "a"].isClassOf(item.component) && item.focusable) {
1338
- focusCounter += 1;
1339
- }
1340
-
1341
- const focusIndex = focusCounter - 1;
1342
- return { ...item,
1343
- role: itemRole,
1344
- ref: item.focusable ? this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null : null,
1345
- onClick: () => {
1346
- this.handleItemClick(focusIndex, item);
1347
- }
1348
- };
1349
- });
1350
- }
1351
- /**
1352
- * Render the items using a virtualized list
1353
- */
1354
-
1355
-
1356
- renderVirtualizedList() {
1357
- // preprocess items data to pass it to the renderer
1358
- const virtualizedItems = this.parseVirtualizedItems();
1359
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_dropdown_core_virtualized_js__WEBPACK_IMPORTED_MODULE_10__[/* default */ "a"], {
1360
- data: virtualizedItems,
1361
- listRef: this.virtualizedListRef
1362
- });
1363
- }
1364
-
1365
- renderSearchField() {
1366
- const {
1367
- searchText
1368
- } = this.props;
1369
- const {
1370
- labels
1371
- } = this.state;
1372
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_search_field__WEBPACK_IMPORTED_MODULE_7___default.a, {
1373
- clearAriaLabel: labels.clearSearch,
1374
- onChange: this.handleSearchTextChanged,
1375
- placeholder: labels.filter,
1376
- ref: this.searchFieldRef,
1377
- style: styles.searchInputStyle,
1378
- value: searchText || ""
1379
- });
1380
- }
1381
-
1382
- renderDropdownMenu(listRenderer, isReferenceHidden) {
1383
- const {
1384
- dropdownStyle,
1385
- light,
1386
- openerElement
1387
- } = this.props; // The dropdown width is at least the width of the opener.
1388
- // It's only used if the element exists in the DOM
1389
-
1390
- const openerStyle = openerElement && window.getComputedStyle(openerElement);
1391
- const minDropdownWidth = openerStyle ? openerStyle.getPropertyValue("width") : 0;
1392
- const maxDropdownHeight = Object(_util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_15__[/* getDropdownMenuHeight */ "b"])(this.props.items);
1393
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__["View"] // Stop propagation to prevent the mouseup listener on the
1394
- // document from closing the menu.
1395
- , {
1396
- onMouseUp: this.handleDropdownMouseUp,
1397
- style: [styles.dropdown, light && styles.light, isReferenceHidden && styles.hidden, dropdownStyle],
1398
- testId: "dropdown-core-container"
1399
- }, this.props.isFilterable && this.renderSearchField(), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__["View"], {
1400
- role: this.props.role,
1401
- style: [styles.listboxOrMenu, Object(_util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_15__[/* generateDropdownMenuStyles */ "a"])(minDropdownWidth, maxDropdownHeight)]
1402
- }, listRenderer), this.maybeRenderNoResults());
1403
- }
1404
-
1405
- renderDropdown() {
1406
- const {
1407
- alignment,
1408
- openerElement
1409
- } = this.props; // Preprocess the items that are used inside the Popper instance. By
1410
- // doing this, we optimize the list to be processed only one time
1411
- // instead of every time popper changes.
1412
- // NOTE: This improves the performance impact of the dropdown by
1413
- // reducing the execution time up to 2.5X.
1414
-
1415
- const listRenderer = this.shouldVirtualizeList() ? this.renderVirtualizedList() : this.renderList();
1416
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_dropdown_popper_js__WEBPACK_IMPORTED_MODULE_13__[/* default */ "a"], {
1417
- alignment: alignment,
1418
- onPopperElement: popperElement => {
1419
- this.popperElement = popperElement;
1420
- },
1421
- referenceElement: openerElement
1422
- }, isReferenceHidden => this.renderDropdownMenu(listRenderer, isReferenceHidden));
1423
- }
1424
-
1425
- renderLiveRegion() {
1426
- const {
1427
- items,
1428
- open
1429
- } = this.props;
1430
- const {
1431
- labels
1432
- } = this.state;
1433
- const totalItems = items.length;
1434
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](StyledSpan, {
1435
- "aria-live": "polite",
1436
- "aria-atomic": "true",
1437
- "aria-relevant": "additions text",
1438
- style: styles.srOnly,
1439
- "data-test-id": "dropdown-live-region"
1440
- }, open && labels.someResults(totalItems));
1441
- }
1442
-
1443
- render() {
1444
- const {
1445
- open,
1446
- opener,
1447
- style,
1448
- className
1449
- } = this.props;
1450
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_6__["View"], {
1451
- onKeyDown: this.handleKeyDown,
1452
- onKeyUp: this.handleKeyUp,
1453
- style: [styles.menuWrapper, style],
1454
- className: className
1455
- }, this.renderLiveRegion(), opener, open && this.renderDropdown());
1456
- }
1457
-
1458
- }
1459
-
1460
- DropdownCore.defaultProps = {
1461
- alignment: "left",
1462
- autoFocus: true,
1463
- enableTypeAhead: true,
1464
- labels: {
1465
- clearSearch: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].clearSearch,
1466
- filter: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].filter,
1467
- noResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].noResults,
1468
- someResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_12__[/* defaultLabels */ "d"].someSelected
1469
- },
1470
- light: false,
1471
- selectionType: "single"
1472
- };
1473
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create({
1474
- menuWrapper: {
1475
- width: "fit-content"
1476
- },
1477
- dropdown: {
1478
- backgroundColor: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a.white,
1479
- borderRadius: 4,
1480
- paddingTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default.a.xxxSmall_4,
1481
- paddingBottom: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default.a.xxxSmall_4,
1482
- border: `solid 1px ${_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a.offBlack16}`,
1483
- boxShadow: `0px 8px 8px 0px ${Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a.offBlack, 0.1)}`
1484
- },
1485
- light: {
1486
- // Pretty much just remove the border
1487
- border: "none"
1488
- },
1489
- listboxOrMenu: {
1490
- overflowY: "auto"
1491
- },
1492
- hidden: {
1493
- pointerEvents: "none",
1494
- visibility: "hidden"
1495
- },
1496
- noResult: {
1497
- color: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a.offBlack64,
1498
- alignSelf: "center",
1499
- marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default.a.xxSmall_6
1500
- },
1501
- searchInputStyle: {
1502
- margin: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default.a.xSmall_8,
1503
- marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_5___default.a.xxxSmall_4,
1504
- // Set `minHeight` to "auto" to stop the search field from having
1505
- // a height of 0 and being cut off.
1506
- minHeight: "auto"
1507
- },
1508
- srOnly: {
1509
- border: 0,
1510
- clip: "rect(0,0,0,0)",
1511
- height: 1,
1512
- margin: -1,
1513
- overflow: "hidden",
1514
- padding: 0,
1515
- position: "absolute",
1516
- width: 1
1517
- }
1518
- });
1519
- /* harmony default export */ __webpack_exports__["a"] = (Object(_khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_9__["withActionScheduler"])(DropdownCore));
1520
-
1521
- /***/ }),
1522
- /* 16 */
1523
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1524
-
1525
- "use strict";
1526
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return getDropdownMenuHeight; });
1527
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return generateDropdownMenuStyles; });
1528
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
1529
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_0__);
1530
- /* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
1531
- /* harmony import */ var _components_separator_item_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
1532
-
1533
-
1534
-
1535
-
1536
- /**
1537
- * The list height that is automatically calculated depending on the
1538
- * component's type of each item (e.g. Separator, Option, Search, etc)
1539
- *
1540
- * @param {Array<DropdownItem>} items - The list of items to calculate the height
1541
- * @param {number} initialHeight - The initial height of the list
1542
- *
1543
- * @returns {number} The list height
1544
- */
1545
- function getDropdownMenuHeight(items, initialHeight = 0) {
1546
- // calculate using the first 10 items on the array as we want to display
1547
- // this number of elements in the visible area
1548
- return items.slice(0, _constants_js__WEBPACK_IMPORTED_MODULE_1__[/* MAX_VISIBLE_ITEMS */ "b"]).reduce((sum, item) => {
1549
- if (_components_separator_item_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].isClassOf(item.component)) {
1550
- return sum + _constants_js__WEBPACK_IMPORTED_MODULE_1__[/* SEPARATOR_ITEM_HEIGHT */ "c"];
1551
- } else {
1552
- return sum + _constants_js__WEBPACK_IMPORTED_MODULE_1__[/* DROPDOWN_ITEM_HEIGHT */ "a"];
1553
- }
1554
- }, initialHeight);
1555
- }
1556
- /**
1557
- * Wraps the dynamic styles in an Aphrodite style sheet so we can properly apply
1558
- * the styles to a merged stylesheet (instead of inlining the styles).
1559
- *
1560
- * @param {StyleType} customStyles - The custom styles to apply to the dropdown
1561
- * menu.
1562
- * @returns The Aphrodite stylesheet for the dropdown menu.
1563
- */
1564
-
1565
- function generateDropdownMenuStyles(minWidth, maxHeight) {
1566
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_0__["StyleSheet"].create({
1567
- dropdownMenu: {
1568
- minWidth,
1569
- maxHeight
1570
- }
1571
- });
1572
- return styles.dropdownMenu;
1573
- }
1574
-
1575
- /***/ }),
1576
- /* 17 */
1577
- /***/ (function(module, exports) {
1578
-
1579
- module.exports = require("react-router");
1580
-
1581
- /***/ }),
1582
- /* 18 */
1583
- /***/ (function(module, exports) {
1584
-
1585
- module.exports = require("@khanacademy/wonder-blocks-timing");
1586
-
1587
- /***/ }),
1588
- /* 19 */
1589
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1590
-
1591
- "use strict";
1592
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SelectOpener; });
1593
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
1594
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
1595
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
1596
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
1597
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
1598
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_2__);
1599
- /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(17);
1600
- /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_router__WEBPACK_IMPORTED_MODULE_3__);
1601
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2);
1602
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__);
1603
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5);
1604
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__);
1605
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(11);
1606
- /* harmony import */ var _khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_6__);
1607
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9);
1608
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_7__);
1609
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(3);
1610
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_8__);
1611
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(10);
1612
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_9__);
1613
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(1);
1614
-
1615
-
1616
-
1617
-
1618
-
1619
-
1620
-
1621
-
1622
-
1623
-
1624
-
1625
- const StyledButton = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__["addStyle"])("button");
1626
- const {
1627
- blue,
1628
- white,
1629
- white50,
1630
- offBlack,
1631
- offBlack16,
1632
- offBlack32,
1633
- offBlack64
1634
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a;
1635
-
1636
- /**
1637
- * An opener that opens select boxes.
1638
- */
1639
- class SelectOpener extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
1640
- constructor(...args) {
1641
- super(...args);
1642
-
1643
- this.handleClick = e => {
1644
- const {
1645
- open
1646
- } = this.props;
1647
- this.props.onOpenChanged(!open);
1648
- };
1649
- }
1650
-
1651
- renderClickableBehavior(router) {
1652
- const {
1653
- children,
1654
- disabled,
1655
- id,
1656
- isPlaceholder,
1657
- light,
1658
- open,
1659
- testId,
1660
- // eslint-disable-next-line no-unused-vars
1661
- onOpenChanged,
1662
- ...sharedProps
1663
- } = this.props;
1664
- const ClickableBehavior = Object(_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_6__["getClickableBehavior"])(router);
1665
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](ClickableBehavior, {
1666
- disabled: disabled,
1667
- onClick: this.handleClick
1668
- }, (state, childrenProps) => {
1669
- const stateStyles = _generateStyles(light, isPlaceholder);
1670
-
1671
- const {
1672
- hovered,
1673
- focused,
1674
- pressed
1675
- } = state; // The icon colors are kind of fickle. This is just logic
1676
- // based on the zeplin design.
1677
-
1678
- const iconColor = light ? disabled || pressed ? "currentColor" : white : disabled ? offBlack32 : offBlack64;
1679
- const style = [styles.shared, stateStyles.default, disabled && stateStyles.disabled, !disabled && (pressed ? stateStyles.active : (hovered || focused) && stateStyles.focus)];
1680
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](StyledButton, _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, sharedProps, {
1681
- "aria-expanded": open ? "true" : "false",
1682
- "aria-haspopup": "listbox",
1683
- "data-test-id": testId,
1684
- disabled: disabled,
1685
- id: id,
1686
- style: style,
1687
- type: "button"
1688
- }, childrenProps), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_9__["LabelMedium"], {
1689
- style: styles.text
1690
- }, children || "\u00A0"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_7___default.a, {
1691
- icon: _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_7__["icons"].caretDown,
1692
- color: iconColor,
1693
- size: "small",
1694
- style: styles.caret,
1695
- "aria-hidden": "true"
1696
- }));
1697
- });
1698
- }
1699
-
1700
- render() {
1701
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react_router__WEBPACK_IMPORTED_MODULE_3__["__RouterContext"].Consumer, null, router => this.renderClickableBehavior(router));
1702
- }
1703
-
1704
- }
1705
- SelectOpener.defaultProps = {
1706
- disabled: false,
1707
- light: false,
1708
- isPlaceholder: false
1709
- };
1710
- const buttonRadius = 4;
1711
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create({
1712
- // TODO: Dedupe with Button styles
1713
- shared: {
1714
- position: "relative",
1715
- display: "inline-flex",
1716
- alignItems: "center",
1717
- justifyContent: "space-between",
1718
- color: offBlack,
1719
- height: _util_constants_js__WEBPACK_IMPORTED_MODULE_10__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
1720
- // This asymmetry arises from the Icon on the right side, which has
1721
- // extra padding built in. To have the component look more balanced,
1722
- // we need to take off some paddingRight here.
1723
- paddingLeft: 16,
1724
- paddingRight: 12,
1725
- borderWidth: 0,
1726
- borderRadius: buttonRadius,
1727
- borderStyle: "solid",
1728
- outline: "none",
1729
- textDecoration: "none",
1730
- boxSizing: "border-box",
1731
- whiteSpace: "nowrap",
1732
- // This removes the 300ms click delay on mobile browsers by indicating that
1733
- // "double-tap to zoom" shouldn't be used on this element.
1734
- touchAction: "manipulation"
1735
- },
1736
- text: {
1737
- marginRight: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_8___default.a.xSmall_8,
1738
- whiteSpace: "nowrap",
1739
- userSelect: "none",
1740
- overflow: "hidden",
1741
- textOverflow: "ellipsis"
1742
- },
1743
- caret: {
1744
- minWidth: 16
1745
- }
1746
- }); // These values are default padding (16 and 12) minus 1, because
1747
- // changing the borderWidth to 2 messes up the button width
1748
- // and causes it to move a couple pixels. This fixes that.
1749
-
1750
- const adjustedPaddingLeft = 16 - 1;
1751
- const adjustedPaddingRight = 12 - 1;
1752
- const stateStyles = {};
1753
-
1754
- const _generateStyles = (light, placeholder) => {
1755
- // "hash" the parameters
1756
- const styleKey = `${String(light)}-${String(placeholder)}`;
1757
-
1758
- if (stateStyles[styleKey]) {
1759
- return stateStyles[styleKey];
1760
- }
1761
-
1762
- let newStyles = {};
1763
-
1764
- if (light) {
1765
- newStyles = {
1766
- default: {
1767
- background: "transparent",
1768
- color: placeholder ? white50 : white,
1769
- borderColor: white50,
1770
- borderWidth: 1
1771
- },
1772
- focus: {
1773
- borderColor: white,
1774
- borderWidth: 2,
1775
- paddingLeft: adjustedPaddingLeft,
1776
- paddingRight: adjustedPaddingRight
1777
- },
1778
- active: {
1779
- paddingLeft: adjustedPaddingLeft,
1780
- paddingRight: adjustedPaddingRight,
1781
- borderColor: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(blue, 0.32), white),
1782
- borderWidth: 2,
1783
- color: placeholder ? Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(white, 0.32), blue) : Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(blue, 0.32), white),
1784
- backgroundColor: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(offBlack32, blue)
1785
- },
1786
- disabled: {
1787
- borderColor: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(white, 0.32), blue),
1788
- color: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(white, 0.32), blue),
1789
- cursor: "auto"
1790
- }
1791
- };
1792
- } else {
1793
- newStyles = {
1794
- default: {
1795
- background: white,
1796
- borderColor: offBlack16,
1797
- borderWidth: 1,
1798
- color: placeholder ? offBlack64 : offBlack
1799
- },
1800
- focus: {
1801
- borderColor: blue,
1802
- borderWidth: 2,
1803
- paddingLeft: adjustedPaddingLeft,
1804
- paddingRight: adjustedPaddingRight
1805
- },
1806
- active: {
1807
- background: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["fade"])(blue, 0.32), white),
1808
- borderColor: Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(offBlack32, blue),
1809
- borderWidth: 2,
1810
- paddingLeft: adjustedPaddingLeft,
1811
- paddingRight: adjustedPaddingRight
1812
- },
1813
- disabled: {
1814
- background: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a.offWhite,
1815
- borderColor: offBlack16,
1816
- color: offBlack64,
1817
- cursor: "auto"
1818
- }
1819
- };
1820
- }
1821
-
1822
- stateStyles[styleKey] = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create(newStyles);
1823
- return stateStyles[styleKey];
1824
- };
1825
-
1826
- /***/ }),
1827
- /* 20 */
1828
- /***/ (function(module, exports) {
1829
-
1830
- module.exports = require("react-window");
1831
-
1832
- /***/ }),
1833
- /* 21 */
1834
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1835
-
1836
- "use strict";
1837
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return getStringForKey; });
1838
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return debounce; });
1839
- /**
1840
- * Checks if a given key is a valid ASCII value.
1841
- *
1842
- * @param {string} key The key that is being typed in.
1843
- * @returns A valid string representation of the given key.
1844
- */
1845
- function getStringForKey(key) {
1846
- // If the key is of length 1, it is an ASCII value.
1847
- // Otherwise, if there are no ASCII characters in the key name,
1848
- // it is a Unicode character.
1849
- // See https://www.w3.org/TR/uievents-key/
1850
- if (key.length === 1 || !/^[A-Z]/i.test(key)) {
1851
- return key;
1852
- }
1853
-
1854
- return "";
1855
- }
1856
- /**
1857
- *
1858
- * @param {fn} callback The function that will be executed after the debounce is resolved.
1859
- * @param {number} wait The period of time that will be executed the debounced
1860
- * function.
1861
- * @returns The function that will be executed after the wait period is
1862
- * fulfilled.
1863
- */
1864
-
1865
- function debounce(callback, wait) {
1866
- let timeout;
1867
- return function executedFunction(...args) {
1868
- const later = () => {
1869
- clearTimeout(timeout);
1870
- callback.apply(void 0, args);
1871
- };
1872
-
1873
- clearTimeout(timeout);
1874
- timeout = setTimeout(later, wait);
1875
- };
1876
- }
1877
-
1878
- /***/ }),
1879
- /* 22 */
1880
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1881
-
1882
- "use strict";
1883
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ActionMenu; });
1884
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
1885
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
1886
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
1887
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
1888
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
1889
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
1890
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
1891
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_3__);
1892
- /* harmony import */ var _dropdown_opener_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14);
1893
- /* harmony import */ var _action_item_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(12);
1894
- /* harmony import */ var _option_item_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(13);
1895
- /* harmony import */ var _dropdown_core_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(15);
1896
- /* harmony import */ var _action_menu_opener_core_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(34);
1897
-
1898
-
1899
-
1900
-
1901
-
1902
-
1903
-
1904
-
1905
-
1906
-
1907
- /**
1908
- * A menu that consists of various types of items.
1909
- *
1910
- * ## Usage
1911
- *
1912
- * ```jsx
1913
- * import {ActionMenu, ActionItem} from "@khanacademy/wonder-blocks-dropdown";
1914
- *
1915
- * <ActionMenu menuText="Menu">
1916
- * <ActionItem href="/profile" label="Profile" />
1917
- * <ActionItem label="Settings" onClick={() => {}} />
1918
- * </ActionMenu>
1919
- * ```
1920
- */
1921
- class ActionMenu extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
1922
- constructor(...args) {
1923
- super(...args);
1924
- this.state = {
1925
- opened: false
1926
- };
1927
-
1928
- this.handleItemSelected = () => {
1929
- // close menu
1930
- this.handleOpenChanged(false); // Bring focus back to the opener element.
1931
-
1932
- if (this.openerElement) {
1933
- this.openerElement.focus();
1934
- }
1935
- };
1936
-
1937
- this.handleOpenChanged = opened => {
1938
- this.setState({
1939
- opened
1940
- });
1941
-
1942
- if (this.props.onToggle) {
1943
- this.props.onToggle(opened);
1944
- }
1945
- };
1946
-
1947
- this.handleOptionSelected = selectedValue => {
1948
- const {
1949
- onChange,
1950
- selectedValues
1951
- } = this.props; // If either of these are not defined, return.
1952
-
1953
- if (!onChange || !selectedValues) {
1954
- return;
1955
- }
1956
-
1957
- if (selectedValues.includes(selectedValue)) {
1958
- const index = selectedValues.indexOf(selectedValue);
1959
- const updatedSelection = [].concat(selectedValues.slice(0, index), selectedValues.slice(index + 1));
1960
- onChange(updatedSelection);
1961
- } else {
1962
- // Item was newly selected
1963
- onChange([].concat(selectedValues, [selectedValue]));
1964
- }
1965
-
1966
- this.handleItemSelected();
1967
- };
1968
-
1969
- this.handleOpenerRef = node => {
1970
- this.openerElement = react_dom__WEBPACK_IMPORTED_MODULE_2___default.a.findDOMNode(node);
1971
- };
1972
-
1973
- this.handleClick = e => {
1974
- this.handleOpenChanged(!this.state.opened);
1975
- };
1976
- }
1977
-
1978
- /**
1979
- * Used to sync the `opened` state when this component acts as a controlled
1980
- * component
1981
- */
1982
- static getDerivedStateFromProps(props, state) {
1983
- return {
1984
- opened: typeof props.opened === "boolean" ? props.opened : state.opened
1985
- };
1986
- }
1987
-
1988
- getMenuItems() {
1989
- const {
1990
- children,
1991
- selectedValues
1992
- } = this.props;
1993
- const allChildren = react__WEBPACK_IMPORTED_MODULE_1__["Children"].toArray(children).filter(Boolean); // verify if there's at least one OptionItem element to indent the
1994
- // possible Action items
1995
-
1996
- const isOptionItemIncluded = allChildren.some(item => _option_item_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].isClassOf(item));
1997
- return allChildren.map(item => {
1998
- const {
1999
- value,
2000
- disabled
2001
- } = item.props;
2002
- const itemObject = {
2003
- component: item,
2004
- focusable: _action_item_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"].isClassOf(item) || _option_item_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].isClassOf(item) ? !disabled : false,
2005
- populatedProps: {}
2006
- };
2007
-
2008
- if (_action_item_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"].isClassOf(item)) {
2009
- return { ...itemObject,
2010
- populatedProps: {
2011
- indent: isOptionItemIncluded,
2012
- onClick: this.handleItemSelected
2013
- }
2014
- };
2015
- } else if (_option_item_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].isClassOf(item)) {
2016
- return { ...itemObject,
2017
- populatedProps: {
2018
- onToggle: this.handleOptionSelected,
2019
- selected: selectedValues ? selectedValues.includes(value) : false,
2020
- variant: "check"
2021
- }
2022
- };
2023
- } else {
2024
- return itemObject;
2025
- }
2026
- });
2027
- }
2028
-
2029
- renderOpener(numItems) {
2030
- const {
2031
- disabled,
2032
- menuText,
2033
- opener,
2034
- testId
2035
- } = this.props;
2036
- const {
2037
- opened
2038
- } = this.state;
2039
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_opener_js__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"], {
2040
- onClick: this.handleClick,
2041
- disabled: numItems === 0 || disabled,
2042
- text: menuText,
2043
- ref: this.handleOpenerRef,
2044
- testId: opener ? undefined : testId
2045
- }, opener ? opener : openerProps => {
2046
- const {
2047
- // eslint-disable-next-line no-unused-vars
2048
- text,
2049
- ...eventState
2050
- } = openerProps;
2051
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_action_menu_opener_core_js__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"], _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, eventState, {
2052
- disabled: disabled,
2053
- opened: !!opened,
2054
- testId: testId
2055
- }), menuText);
2056
- });
2057
- }
2058
-
2059
- render() {
2060
- const {
2061
- alignment,
2062
- dropdownStyle,
2063
- style,
2064
- className
2065
- } = this.props;
2066
- const items = this.getMenuItems();
2067
- const dropdownOpener = this.renderOpener(items.length);
2068
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_core_js__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"], {
2069
- role: "menu",
2070
- style: style,
2071
- className: className,
2072
- opener: dropdownOpener,
2073
- alignment: alignment,
2074
- open: this.state.opened,
2075
- items: items,
2076
- openerElement: this.openerElement,
2077
- onOpenChanged: this.handleOpenChanged,
2078
- dropdownStyle: [styles.menuTopSpace, dropdownStyle]
2079
- });
2080
- }
2081
-
2082
- }
2083
- ActionMenu.defaultProps = {
2084
- alignment: "left",
2085
- disabled: false
2086
- };
2087
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_3__["StyleSheet"].create({
2088
- caret: {
2089
- marginLeft: 4
2090
- },
2091
- // The design calls for additional offset around the opener.
2092
- opener: {
2093
- whiteSpace: "nowrap",
2094
- userSelect: "none",
2095
- overflow: "hidden",
2096
- textOverflow: "ellipsis"
2097
- },
2098
- // This is to adjust the space between the menu and the opener.
2099
- menuTopSpace: {
2100
- top: -4
2101
- }
2102
- });
2103
-
2104
- /***/ }),
2105
- /* 23 */
2106
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2107
-
2108
- "use strict";
2109
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SingleSelect; });
2110
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
2111
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
2112
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
2113
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
2114
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
2115
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
2116
- /* harmony import */ var _dropdown_core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(15);
2117
- /* harmony import */ var _dropdown_opener_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14);
2118
- /* harmony import */ var _select_opener_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19);
2119
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1);
2120
-
2121
-
2122
-
2123
-
2124
-
2125
-
2126
-
2127
-
2128
- /**
2129
- * The single select allows the selection of one item. Clients are responsible
2130
- * for keeping track of the selected item in the select.
2131
- *
2132
- * The single select dropdown closes after the selection of an item. If the same
2133
- * item is selected, there is no callback.
2134
- *
2135
- * **NOTE:** If there are more than 125 items, the component automatically uses
2136
- * [react-window](https://github.com/bvaughn/react-window) to improve
2137
- * performance when rendering these elements and is capable of handling many
2138
- * hundreds of items without performance problems.
2139
- *
2140
- * ## Usage
2141
- *
2142
- * ```jsx
2143
- * import {OptionItem, SingleSelect} from "@khanacademy/wonder-blocks-dropdown";
2144
- *
2145
- * const [selectedValue, setSelectedValue] = useState("");
2146
- *
2147
- * <SingleSelect placeholder="Choose a fruit" onChange={setSelectedValue} selectedValue={selectedValue}>
2148
- * <OptionItem value="pear">Pear</OptionItem>
2149
- * <OptionItem value="mango">Mango</OptionItem>
2150
- * </SingleSelect>
2151
- * ```
2152
- */
2153
- class SingleSelect extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
2154
- constructor(props) {
2155
- super(props);
2156
-
2157
- this.handleOpenChanged = opened => {
2158
- this.setState({
2159
- open: opened,
2160
- searchText: ""
2161
- });
2162
-
2163
- if (this.props.onToggle) {
2164
- this.props.onToggle(opened);
2165
- }
2166
- };
2167
-
2168
- this.handleToggle = selectedValue => {
2169
- // Call callback if selection changed.
2170
- if (selectedValue !== this.props.selectedValue) {
2171
- this.props.onChange(selectedValue);
2172
- } // Bring focus back to the opener element.
2173
-
2174
-
2175
- if (this.state.open && this.state.openerElement) {
2176
- this.state.openerElement.focus();
2177
- }
2178
-
2179
- this.setState({
2180
- open: false // close the menu upon selection
2181
-
2182
- });
2183
-
2184
- if (this.props.onToggle) {
2185
- this.props.onToggle(false);
2186
- }
2187
- };
2188
-
2189
- this.mapOptionItemsToDropdownItems = children => {
2190
- // Figure out which index should receive focus when this select opens
2191
- // Needs to exclude counting items that are disabled
2192
- let indexCounter = 0;
2193
- this.selectedIndex = 0;
2194
- return children.map(option => {
2195
- const {
2196
- selectedValue
2197
- } = this.props;
2198
- const {
2199
- disabled,
2200
- value
2201
- } = option.props;
2202
- const selected = selectedValue === value;
2203
-
2204
- if (selected) {
2205
- this.selectedIndex = indexCounter;
2206
- }
2207
-
2208
- if (!disabled) {
2209
- indexCounter += 1;
2210
- }
2211
-
2212
- return {
2213
- component: option,
2214
- focusable: !disabled,
2215
- populatedProps: {
2216
- onToggle: this.handleToggle,
2217
- selected: selected,
2218
- variant: "check"
2219
- }
2220
- };
2221
- });
2222
- };
2223
-
2224
- this.handleSearchTextChanged = searchText => {
2225
- this.setState({
2226
- searchText
2227
- });
2228
- };
2229
-
2230
- this.handleOpenerRef = node => {
2231
- const openerElement = react_dom__WEBPACK_IMPORTED_MODULE_2___default.a.findDOMNode(node);
2232
- this.setState({
2233
- openerElement
2234
- });
2235
- };
2236
-
2237
- this.handleClick = e => {
2238
- this.handleOpenChanged(!this.state.open);
2239
- };
2240
-
2241
- this.selectedIndex = 0;
2242
- this.state = {
2243
- open: false,
2244
- searchText: "",
2245
- openerElement: null
2246
- };
2247
- }
2248
- /**
2249
- * Used to sync the `opened` state when this component acts as a controlled
2250
- * component
2251
- */
2252
-
2253
-
2254
- static getDerivedStateFromProps(props, state) {
2255
- return {
2256
- open: typeof props.opened === "boolean" ? props.opened : state.open
2257
- };
2258
- }
2259
-
2260
- filterChildren(children) {
2261
- const {
2262
- searchText
2263
- } = this.state;
2264
- const lowercasedSearchText = searchText.toLowerCase(); // Filter the children with the searchText if any.
2265
-
2266
- return children.filter(({
2267
- props
2268
- }) => !searchText || props.label.toLowerCase().indexOf(lowercasedSearchText) > -1);
2269
- }
2270
-
2271
- getMenuItems(children) {
2272
- const {
2273
- isFilterable
2274
- } = this.props; // If it's not filterable, no need to do any extra besides mapping the
2275
- // option items to dropdown items.
2276
-
2277
- return this.mapOptionItemsToDropdownItems(isFilterable ? this.filterChildren(children) : children);
2278
- }
2279
-
2280
- renderOpener(numItems) {
2281
- const {
2282
- children,
2283
- disabled,
2284
- id,
2285
- light,
2286
- opener,
2287
- placeholder,
2288
- selectedValue,
2289
- testId,
2290
- // the following props are being included here to avoid
2291
- // passing them down to the opener as part of sharedProps
2292
-
2293
- /* eslint-disable no-unused-vars */
2294
- alignment,
2295
- autoFocus,
2296
- dropdownStyle,
2297
- enableTypeAhead,
2298
- isFilterable,
2299
- labels,
2300
- onChange,
2301
- onToggle,
2302
- opened,
2303
- style,
2304
- className,
2305
-
2306
- /* eslint-enable no-unused-vars */
2307
- ...sharedProps
2308
- } = this.props;
2309
- const selectedItem = react__WEBPACK_IMPORTED_MODULE_1__["Children"].toArray(children).find(option => option.props.value === selectedValue); // If nothing is selected, or if the selectedValue doesn't match any
2310
- // item in the menu, use the placeholder.
2311
-
2312
- const menuText = selectedItem ? selectedItem.props.label : placeholder;
2313
- const dropdownOpener = opener ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_opener_js__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"], {
2314
- onClick: this.handleClick,
2315
- disabled: numItems === 0 || disabled,
2316
- ref: this.handleOpenerRef,
2317
- text: menuText
2318
- }, opener) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_select_opener_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"], _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, sharedProps, {
2319
- disabled: numItems === 0 || disabled,
2320
- id: id,
2321
- isPlaceholder: !selectedItem,
2322
- light: light,
2323
- onOpenChanged: this.handleOpenChanged,
2324
- open: this.state.open,
2325
- ref: this.handleOpenerRef,
2326
- testId: testId
2327
- }), menuText);
2328
- return dropdownOpener;
2329
- }
2330
-
2331
- render() {
2332
- const {
2333
- alignment,
2334
- autoFocus,
2335
- children,
2336
- className,
2337
- dropdownStyle,
2338
- enableTypeAhead,
2339
- isFilterable,
2340
- labels,
2341
- light,
2342
- style
2343
- } = this.props;
2344
- const {
2345
- searchText
2346
- } = this.state;
2347
- const allChildren = react__WEBPACK_IMPORTED_MODULE_1__["Children"].toArray(children).filter(Boolean);
2348
- const items = this.getMenuItems(allChildren);
2349
- const opener = this.renderOpener(allChildren.length);
2350
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_core_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"], {
2351
- role: "listbox",
2352
- selectionType: "single",
2353
- alignment: alignment,
2354
- autoFocus: autoFocus,
2355
- enableTypeAhead: enableTypeAhead,
2356
- dropdownStyle: [isFilterable && _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* filterableDropdownStyle */ "e"], _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* selectDropdownStyle */ "g"], dropdownStyle],
2357
- initialFocusedIndex: this.selectedIndex,
2358
- items: items,
2359
- light: light,
2360
- onOpenChanged: this.handleOpenChanged,
2361
- open: this.state.open,
2362
- opener: opener,
2363
- openerElement: this.state.openerElement,
2364
- style: style,
2365
- className: className,
2366
- isFilterable: isFilterable,
2367
- onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
2368
- searchText: isFilterable ? searchText : "",
2369
- labels: labels
2370
- });
2371
- }
2372
-
2373
- }
2374
- SingleSelect.defaultProps = {
2375
- alignment: "left",
2376
- autoFocus: true,
2377
- disabled: false,
2378
- enableTypeAhead: true,
2379
- light: false,
2380
- labels: {
2381
- clearSearch: _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* defaultLabels */ "d"].clearSearch,
2382
- filter: _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* defaultLabels */ "d"].filter,
2383
- noResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* defaultLabels */ "d"].noResults,
2384
- someResults: _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* defaultLabels */ "d"].someSelected
2385
- }
2386
- };
2387
-
2388
- /***/ }),
2389
- /* 24 */
2390
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2391
-
2392
- "use strict";
2393
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MultiSelect; });
2394
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
2395
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
2396
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
2397
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
2398
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
2399
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
2400
- /* harmony import */ var _action_item_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12);
2401
- /* harmony import */ var _dropdown_core_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(15);
2402
- /* harmony import */ var _dropdown_opener_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(14);
2403
- /* harmony import */ var _select_opener_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19);
2404
- /* harmony import */ var _separator_item_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(7);
2405
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1);
2406
-
2407
-
2408
-
2409
-
2410
-
2411
-
2412
-
2413
-
2414
-
2415
-
2416
- /**
2417
- * A dropdown that consists of multiple selection items. This select allows
2418
- * multiple options to be selected. Clients are responsible for keeping track
2419
- * of the selected items.
2420
- *
2421
- * The multi select stays open until closed by the user. The onChange callback
2422
- * happens every time there is a change in the selection of the items.
2423
- *
2424
- * ## Usage
2425
- *
2426
- * ```jsx
2427
- * import {OptionItem, MultiSelect} from "@khanacademy/wonder-blocks-dropdown";
2428
- *
2429
- * <MultiSelect onChange={setSelectedValues} selectedValues={selectedValues}>
2430
- * <OptionItem value="pear">Pear</OptionItem>
2431
- * <OptionItem value="mango">Mango</OptionItem>
2432
- * </MultiSelect>
2433
- * ```
2434
- */
2435
- class MultiSelect extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
2436
- constructor(props) {
2437
- super(props);
2438
-
2439
- this.handleOpenChanged = opened => {
2440
- this.setState({
2441
- open: opened,
2442
- searchText: "",
2443
- lastSelectedValues: this.props.selectedValues
2444
- });
2445
-
2446
- if (this.props.onToggle) {
2447
- this.props.onToggle(opened);
2448
- }
2449
- };
2450
-
2451
- this.handleToggle = selectedValue => {
2452
- const {
2453
- onChange,
2454
- selectedValues
2455
- } = this.props;
2456
-
2457
- if (selectedValues.includes(selectedValue)) {
2458
- const index = selectedValues.indexOf(selectedValue);
2459
- const updatedSelection = [].concat(selectedValues.slice(0, index), selectedValues.slice(index + 1));
2460
- onChange(updatedSelection);
2461
- } else {
2462
- // Item was newly selected
2463
- onChange([].concat(selectedValues, [selectedValue]));
2464
- }
2465
- };
2466
-
2467
- this.handleSelectAll = () => {
2468
- const {
2469
- children,
2470
- onChange
2471
- } = this.props;
2472
- const selected = react__WEBPACK_IMPORTED_MODULE_1__["Children"].toArray(children).filter(Boolean).map(option => option.props.value);
2473
- onChange(selected);
2474
- };
2475
-
2476
- this.handleSelectNone = () => {
2477
- const {
2478
- onChange
2479
- } = this.props;
2480
- onChange([]);
2481
- };
2482
-
2483
- this.mapOptionItemToDropdownItem = option => {
2484
- const {
2485
- selectedValues
2486
- } = this.props;
2487
- const {
2488
- disabled,
2489
- value
2490
- } = option.props;
2491
- return {
2492
- component: option,
2493
- focusable: !disabled,
2494
- populatedProps: {
2495
- onToggle: this.handleToggle,
2496
- selected: selectedValues.includes(value),
2497
- variant: "checkbox"
2498
- }
2499
- };
2500
- };
2501
-
2502
- this.handleOpenerRef = node => {
2503
- const openerElement = react_dom__WEBPACK_IMPORTED_MODULE_2___default.a.findDOMNode(node);
2504
- this.setState({
2505
- openerElement
2506
- });
2507
- };
2508
-
2509
- this.handleSearchTextChanged = searchText => {
2510
- this.setState({
2511
- searchText
2512
- });
2513
- };
2514
-
2515
- this.handleClick = e => {
2516
- this.handleOpenChanged(!this.state.open);
2517
- };
2518
-
2519
- this.state = {
2520
- open: false,
2521
- searchText: "",
2522
- lastSelectedValues: [],
2523
- // merge custom labels with the default ones
2524
- labels: { ..._util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* defaultLabels */ "d"],
2525
- ...props.labels
2526
- },
2527
- openerElement: null
2528
- }; // merge custom labels with the default ones
2529
-
2530
- this.labels = { ..._util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* defaultLabels */ "d"],
2531
- ...props.labels
2532
- };
2533
- }
2534
- /**
2535
- * Used to sync the `opened` state when this component acts as a controlled
2536
- * component
2537
- */
2538
-
2539
-
2540
- static getDerivedStateFromProps(props, state) {
2541
- return {
2542
- open: typeof props.opened === "boolean" ? props.opened : state.open
2543
- };
2544
- }
2545
-
2546
- componentDidUpdate(prevProps) {
2547
- if (this.props.labels !== prevProps.labels) {
2548
- // eslint-disable-next-line react/no-did-update-set-state
2549
- this.setState({
2550
- labels: { ...this.state.labels,
2551
- ...this.props.labels
2552
- }
2553
- });
2554
- }
2555
- }
2556
-
2557
- getMenuText(children) {
2558
- const {
2559
- implicitAllEnabled,
2560
- selectedValues
2561
- } = this.props;
2562
- const {
2563
- noneSelected,
2564
- someSelected,
2565
- allSelected
2566
- } = this.state.labels; // When implicit all enabled, use `labels.allSelected` when no selection
2567
- // otherwise, use the `labels.noneSelected` value
2568
-
2569
- const noSelectionText = implicitAllEnabled ? allSelected : noneSelected;
2570
-
2571
- switch (selectedValues.length) {
2572
- case 0:
2573
- return noSelectionText;
2574
-
2575
- case 1:
2576
- // If there is one item selected, we display its label. If for
2577
- // some reason we can't find the selected item, we use the
2578
- // display text for the case where nothing is selected.
2579
- const selectedItem = children.find(option => option.props.value === selectedValues[0]);
2580
- return selectedItem ? selectedItem.props.label : noSelectionText;
2581
-
2582
- case children.length:
2583
- return allSelected;
2584
-
2585
- default:
2586
- return someSelected(selectedValues.length);
2587
- }
2588
- }
2589
-
2590
- getShortcuts(numOptions) {
2591
- const {
2592
- selectedValues,
2593
- shortcuts
2594
- } = this.props;
2595
- const {
2596
- selectAllLabel,
2597
- selectNoneLabel
2598
- } = this.state.labels; // When there's search text input to filter, shortcuts should be hidden
2599
-
2600
- if (shortcuts && !this.state.searchText) {
2601
- const selectAllDisabled = numOptions === selectedValues.length;
2602
- const selectAll = {
2603
- component: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_action_item_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"], {
2604
- disabled: selectAllDisabled,
2605
- label: selectAllLabel(numOptions),
2606
- indent: true,
2607
- onClick: this.handleSelectAll
2608
- }),
2609
- focusable: !selectAllDisabled,
2610
- populatedProps: {}
2611
- };
2612
- const selectNoneDisabled = selectedValues.length === 0;
2613
- const selectNone = {
2614
- component: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_action_item_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"], {
2615
- disabled: selectNoneDisabled,
2616
- label: selectNoneLabel,
2617
- indent: true,
2618
- onClick: this.handleSelectNone
2619
- }),
2620
- focusable: !selectNoneDisabled,
2621
- populatedProps: {}
2622
- };
2623
- const separator = {
2624
- component: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_separator_item_js__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"], {
2625
- key: "shortcuts-separator"
2626
- }),
2627
- focusable: false,
2628
- populatedProps: {}
2629
- };
2630
- return [selectAll, selectNone, separator];
2631
- } else {
2632
- return [];
2633
- }
2634
- }
2635
-
2636
- getMenuItems(children) {
2637
- const {
2638
- isFilterable
2639
- } = this.props; // If it's not filterable, no need to do any extra besides mapping the
2640
- // option items to dropdown items.
2641
-
2642
- if (!isFilterable) {
2643
- return children.map(this.mapOptionItemToDropdownItem);
2644
- }
2645
-
2646
- const {
2647
- searchText,
2648
- lastSelectedValues
2649
- } = this.state;
2650
- const lowercasedSearchText = searchText.toLowerCase(); // Filter the children with the searchText if any.
2651
-
2652
- const filteredChildren = children.filter(({
2653
- props
2654
- }) => !searchText || props.label.toLowerCase().indexOf(lowercasedSearchText) > -1);
2655
- const lastSelectedChildren = [];
2656
- const restOfTheChildren = [];
2657
-
2658
- for (const child of filteredChildren) {
2659
- if (lastSelectedValues.includes(child.props.value)) {
2660
- lastSelectedChildren.push(child);
2661
- } else {
2662
- restOfTheChildren.push(child);
2663
- }
2664
- }
2665
-
2666
- const lastSelectedItems = lastSelectedChildren.map(this.mapOptionItemToDropdownItem); // We want to add SeparatorItem in between last selected items and the
2667
- // rest of the items only when both of them exists.
2668
-
2669
- if (lastSelectedChildren.length && restOfTheChildren.length) {
2670
- lastSelectedItems.push({
2671
- component: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_separator_item_js__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"], {
2672
- key: "selected-separator"
2673
- }),
2674
- focusable: false,
2675
- populatedProps: {}
2676
- });
2677
- }
2678
-
2679
- return [].concat(lastSelectedItems, restOfTheChildren.map(this.mapOptionItemToDropdownItem));
2680
- }
2681
-
2682
- renderOpener(allChildren) {
2683
- const {
2684
- disabled,
2685
- id,
2686
- light,
2687
- opener,
2688
- testId,
2689
- // the following props are being included here to avoid
2690
- // passing them down to the opener as part of sharedProps
2691
-
2692
- /* eslint-disable no-unused-vars */
2693
- alignment,
2694
- dropdownStyle,
2695
- implicitAllEnabled,
2696
- isFilterable,
2697
- labels,
2698
- onChange,
2699
- onToggle,
2700
- opened,
2701
- selectedValues,
2702
- shortcuts,
2703
- style,
2704
- className,
2705
-
2706
- /* eslint-enable no-unused-vars */
2707
- ...sharedProps
2708
- } = this.props;
2709
- const {
2710
- noneSelected
2711
- } = this.state.labels;
2712
- const menuText = this.getMenuText(allChildren);
2713
- const numOptions = allChildren.length;
2714
- const dropdownOpener = opener ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_opener_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"], {
2715
- onClick: this.handleClick,
2716
- disabled: numOptions === 0 || disabled,
2717
- ref: this.handleOpenerRef,
2718
- text: menuText
2719
- }, opener) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_select_opener_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"], _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({}, sharedProps, {
2720
- disabled: numOptions === 0 || disabled,
2721
- id: id,
2722
- isPlaceholder: menuText === noneSelected,
2723
- light: light,
2724
- onOpenChanged: this.handleOpenChanged,
2725
- open: this.state.open,
2726
- ref: this.handleOpenerRef,
2727
- testId: testId
2728
- }), menuText);
2729
- return dropdownOpener;
2730
- }
2731
-
2732
- render() {
2733
- const {
2734
- alignment,
2735
- light,
2736
- style,
2737
- className,
2738
- dropdownStyle,
2739
- children,
2740
- isFilterable
2741
- } = this.props;
2742
- const {
2743
- open,
2744
- searchText
2745
- } = this.state;
2746
- const {
2747
- clearSearch,
2748
- filter,
2749
- noResults,
2750
- someSelected
2751
- } = this.state.labels;
2752
- const allChildren = react__WEBPACK_IMPORTED_MODULE_1__["Children"].toArray(children).filter(Boolean);
2753
- const numOptions = allChildren.length;
2754
- const filteredItems = this.getMenuItems(allChildren);
2755
- const opener = this.renderOpener(allChildren);
2756
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_dropdown_core_js__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"], {
2757
- role: "listbox",
2758
- alignment: alignment,
2759
- dropdownStyle: [isFilterable && _util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* filterableDropdownStyle */ "e"], _util_constants_js__WEBPACK_IMPORTED_MODULE_8__[/* selectDropdownStyle */ "g"], dropdownStyle],
2760
- isFilterable: isFilterable,
2761
- items: [].concat(this.getShortcuts(numOptions), filteredItems),
2762
- light: light,
2763
- onOpenChanged: this.handleOpenChanged,
2764
- open: open,
2765
- opener: opener,
2766
- openerElement: this.state.openerElement,
2767
- selectionType: "multi",
2768
- style: style,
2769
- className: className,
2770
- onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : null,
2771
- searchText: isFilterable ? searchText : "",
2772
- labels: {
2773
- clearSearch,
2774
- filter,
2775
- noResults,
2776
- someResults: someSelected
2777
- }
2778
- });
2779
- }
2780
-
2781
- }
2782
- MultiSelect.defaultProps = {
2783
- alignment: "left",
2784
- disabled: false,
2785
- light: false,
2786
- shortcuts: false,
2787
- selectedValues: []
2788
- };
2789
-
2790
- /***/ }),
2791
- /* 25 */
2792
- /***/ (function(module, exports) {
2793
-
2794
- module.exports = require("react-router-dom");
2795
-
2796
- /***/ }),
2797
- /* 26 */
2798
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2799
-
2800
- "use strict";
2801
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Check; });
2802
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2803
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
2804
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
2805
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
2806
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
2807
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__);
2808
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
2809
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_3__);
2810
-
2811
-
2812
-
2813
-
2814
- const {
2815
- offBlack,
2816
- offBlack32,
2817
- white
2818
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a;
2819
- /**
2820
- * Props describing the state of the OptionItem, shared by the checkbox
2821
- * component,
2822
- */
2823
-
2824
- /**
2825
- * The check component used by OptionItem.
2826
- */
2827
- function Check(props) {
2828
- const {
2829
- disabled,
2830
- selected,
2831
- pressed,
2832
- hovered,
2833
- focused
2834
- } = props;
2835
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_3___default.a, {
2836
- icon: _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_3__["icons"].check,
2837
- size: "small",
2838
- color: disabled ? offBlack32 : pressed || hovered || focused ? white : offBlack,
2839
- style: [styles.bounds, !selected && styles.hide]
2840
- });
2841
- }
2842
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
2843
- bounds: {
2844
- // Semantically, this are the constants for a small-sized icon
2845
- minHeight: 16,
2846
- minWidth: 16
2847
- },
2848
- hide: {
2849
- visibility: "hidden"
2850
- }
2851
- });
2852
-
2853
- /***/ }),
2854
- /* 27 */
2855
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2856
-
2857
- "use strict";
2858
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Checkbox; });
2859
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2860
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
2861
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
2862
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
2863
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
2864
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__);
2865
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
2866
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__);
2867
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9);
2868
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_4__);
2869
-
2870
-
2871
-
2872
-
2873
-
2874
- // NOTE(sophie): This is a smaller check specifically for use in checkboxes.
2875
- // Please don't copy it automatically and check with designers before using.
2876
- // If the intended icon is a check without a checkbox, you should be using
2877
- // icons.check from the Wonder Blocks Icon package.
2878
- const checkboxCheck = {
2879
- small: "M11.263 4.324a1 1 0 1 1 1.474 1.352l-5.5 6a1 1 0 0 1-1.505-.036l-2.5-3a1 1 0 1 1 1.536-1.28L6.536 9.48l4.727-5.157z"
2880
- };
2881
- const {
2882
- blue,
2883
- white,
2884
- offBlack16,
2885
- offBlack32,
2886
- offBlack50,
2887
- offWhite
2888
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a;
2889
- /**
2890
- * Props describing the state of the OptionItem, shared by the check
2891
- * component,
2892
- */
2893
-
2894
- /**
2895
- * The checkbox component used by OptionItem.
2896
- */
2897
- function Checkbox(props) {
2898
- const {
2899
- disabled,
2900
- selected,
2901
- pressed,
2902
- hovered,
2903
- focused
2904
- } = props;
2905
- const activeBlue = Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__["mix"])(offBlack32, blue);
2906
- const clickInteraction = pressed || hovered || focused;
2907
- const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue : white;
2908
- const checkColor = disabled ? offBlack32 : clickInteraction ? pressed ? activeBlue : blue : white;
2909
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__["View"], {
2910
- style: [styles.checkbox, (clickInteraction || selected && !disabled) && styles.noBorder, disabled && styles.disabledCheckbox, {
2911
- backgroundColor: bgColor
2912
- }]
2913
- }, selected && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_4___default.a, {
2914
- icon: checkboxCheck,
2915
- size: "small",
2916
- color: checkColor,
2917
- style: [disabled && selected && styles.disabledCheckFormatting]
2918
- }));
2919
- }
2920
- const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
2921
- checkbox: {
2922
- // Semantically, this are the constants for a small-sized icon
2923
- minHeight: 16,
2924
- minWidth: 16,
2925
- borderRadius: 3,
2926
- borderWidth: 1,
2927
- borderStyle: "solid",
2928
- borderColor: offBlack50
2929
- },
2930
- noBorder: {
2931
- borderWidth: 0
2932
- },
2933
- disabledCheckbox: {
2934
- borderColor: offBlack16,
2935
- backgroundColor: offWhite
2936
- },
2937
- // The border of 1px on the selected, disabled checkbox pushes the check out
2938
- // of place. Move it back.
2939
- disabledCheckFormatting: {
2940
- position: "absolute",
2941
- top: -1,
2942
- left: -1
2943
- }
2944
- });
2945
-
2946
- /***/ }),
2947
- /* 28 */
2948
- /***/ (function(module, exports) {
2949
-
2950
- module.exports = require("@khanacademy/wonder-blocks-search-field");
2951
-
2952
- /***/ }),
2953
- /* 29 */
2954
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2955
-
2956
- "use strict";
2957
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2958
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
2959
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
2960
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
2961
- /* harmony import */ var react_window__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20);
2962
- /* harmony import */ var react_window__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_window__WEBPACK_IMPORTED_MODULE_2__);
2963
- /* harmony import */ var _khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18);
2964
- /* harmony import */ var _khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_3__);
2965
- /* harmony import */ var _dropdown_core_virtualized_item_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(30);
2966
- /* harmony import */ var _separator_item_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7);
2967
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1);
2968
- /* harmony import */ var _util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(16);
2969
-
2970
-
2971
-
2972
-
2973
-
2974
-
2975
-
2976
-
2977
-
2978
- /**
2979
- * A react-window's List wrapper that instantiates the virtualized list and
2980
- * dynamically calculates the item height depending on the type
2981
- */
2982
- class DropdownCoreVirtualized extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
2983
- constructor(props) {
2984
- super(props);
2985
-
2986
- this.getItemSize = index => {
2987
- // get the current item in the list
2988
- const item = this.props.data[index];
2989
-
2990
- if (_separator_item_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"].isClassOf(item.component)) {
2991
- // this is the separator's height (1px) + vertical margin (8px)
2992
- return _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* SEPARATOR_ITEM_HEIGHT */ "c"];
2993
- } else {
2994
- // default dropdown item height
2995
- return _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* DROPDOWN_ITEM_HEIGHT */ "a"];
2996
- }
2997
- };
2998
-
2999
- this.state = {
3000
- height: Object(_util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_7__[/* getDropdownMenuHeight */ "b"])(props.data),
3001
- width: props.width
3002
- };
3003
- }
3004
-
3005
- componentDidMount() {
3006
- const {
3007
- schedule
3008
- } = this.props; // Wait for styles to be applied. This way, we can get a more precise
3009
- // value of the container dimensions.
3010
-
3011
- schedule.animationFrame(() => {
3012
- this.setWidth();
3013
- });
3014
- }
3015
-
3016
- componentDidUpdate(prevProps) {
3017
- const {
3018
- data,
3019
- listRef
3020
- } = this.props; // if the items size has changed, then recalculate each item position
3021
-
3022
- if (prevProps.data.length !== data.length) {
3023
- this.setHeight();
3024
-
3025
- if (listRef && listRef.current) {
3026
- // the ref can't associate this instance method
3027
- // $FlowIgnore
3028
- listRef.current.resetAfterIndex(1);
3029
- }
3030
- }
3031
- }
3032
- /**
3033
- * Update container width
3034
- */
3035
-
3036
-
3037
- setWidth() {
3038
- const rootNode = react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.findDOMNode(this);
3039
- const parentNode = rootNode == null ? void 0 : rootNode.parentElement; // after the non-virtualized items are rendered, we get the container
3040
- // width to pass it to react-window's List
3041
-
3042
- if (parentNode) {
3043
- const width = parentNode.getBoundingClientRect().width;
3044
- this.setState({
3045
- width
3046
- });
3047
- }
3048
- }
3049
- /**
3050
- * Update container height
3051
- */
3052
-
3053
-
3054
- setHeight() {
3055
- // calculate dropdown's height depending on the type of items
3056
- const height = Object(_util_dropdown_menu_styles_js__WEBPACK_IMPORTED_MODULE_7__[/* getDropdownMenuHeight */ "b"])(this.props.data);
3057
- this.setState({
3058
- height
3059
- });
3060
- }
3061
- /**
3062
- * Calculates item height
3063
- */
3064
-
3065
-
3066
- /**
3067
- * render non virtualized items to calculate the container max-width that
3068
- * will be used by DropdownCoreVirtualized
3069
- */
3070
- renderInitialItems() {
3071
- const {
3072
- data
3073
- } = this.props;
3074
- const allComponents = data.map(e => e.component); // 1. get the children opaque data structure to sort each item by its
3075
- // label length
3076
-
3077
- const longestItems = react__WEBPACK_IMPORTED_MODULE_0__["Children"].toArray(allComponents).filter(Boolean).sort((a, b) => {
3078
- // 2. only sort elements that contain a `label` prop
3079
- if (b.props.label && a.props.label) {
3080
- return b.props.label.length - a.props.label.length;
3081
- }
3082
-
3083
- return -1;
3084
- }) // 3. only render the possible visible items to minimize layout
3085
- // jumps
3086
- .slice(0, _util_constants_js__WEBPACK_IMPORTED_MODULE_6__[/* MAX_VISIBLE_ITEMS */ "b"]); // Append longest items to calculate the container width.
3087
- // We need to hide these sorted elements to avoid any FOUC.
3088
-
3089
- return longestItems.map(item => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](item, {
3090
- style: {
3091
- visibility: "hidden"
3092
- }
3093
- }));
3094
- }
3095
-
3096
- renderVirtualizedList() {
3097
- const {
3098
- data,
3099
- listRef
3100
- } = this.props;
3101
- const {
3102
- height,
3103
- width
3104
- } = this.state;
3105
- return (
3106
- /*#__PURE__*/
3107
- // react-window has some issues for typing lists when passing refs
3108
- // $FlowIgnore
3109
- react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react_window__WEBPACK_IMPORTED_MODULE_2__["VariableSizeList"] // react-window doesn't accept maybe numbers. It wants numbers
3110
- // or strings.
3111
- // $FlowFixMe
3112
- , {
3113
- height: height,
3114
- itemCount: data.length,
3115
- itemSize: this.getItemSize,
3116
- itemData: data,
3117
- style: {
3118
- overflowX: "hidden"
3119
- } // react-window doesn't accept maybe numbers. It wants numbers
3120
- // or strings.
3121
- // $FlowFixMe
3122
- ,
3123
- width: width,
3124
- overscanCount: 5,
3125
- ref: listRef
3126
- }, _dropdown_core_virtualized_item_js__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"])
3127
- );
3128
- }
3129
-
3130
- render() {
3131
- if (this.state.width === undefined) {
3132
- // if we don't pass a fixed value, then we need to render
3133
- // non-virtualized items to calculate width
3134
- return this.renderInitialItems();
3135
- } else {
3136
- // width has been provided, then render the virtualized list
3137
- return this.renderVirtualizedList();
3138
- }
3139
- }
3140
-
3141
- }
3142
-
3143
- /* harmony default export */ __webpack_exports__["a"] = (Object(_khanacademy_wonder_blocks_timing__WEBPACK_IMPORTED_MODULE_3__["withActionScheduler"])(DropdownCoreVirtualized));
3144
-
3145
- /***/ }),
3146
- /* 30 */
3147
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
3148
-
3149
- "use strict";
3150
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
3151
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
3152
- /* harmony import */ var _separator_item_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
3153
-
3154
-
3155
-
3156
- /**
3157
- * A virtualized list item - It's created by decorating the DropdownItem
3158
- * (ActionItem, OptionItem, SeparatorItem) with custom styles to let
3159
- * react-window make its own calculations.
3160
- */
3161
- class DropdownVirtualizedItem extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
3162
- render() {
3163
- const {
3164
- data,
3165
- index,
3166
- style
3167
- } = this.props;
3168
- const item = data[index];
3169
-
3170
- if (_separator_item_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].isClassOf(item.component)) {
3171
- // add react-window style to the separator to preserve the correct
3172
- // position
3173
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](item.component, {
3174
- style
3175
- });
3176
- } else {
3177
- const {
3178
- component,
3179
- populatedProps,
3180
- onClick,
3181
- role,
3182
- ref
3183
- } = item;
3184
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](component, {
3185
- style,
3186
- ...populatedProps,
3187
- key: index,
3188
- onClick,
3189
- ref: item.focusable && ref,
3190
- role
3191
- });
3192
- }
3193
- }
3194
-
3195
- }
3196
-
3197
- /* harmony default export */ __webpack_exports__["a"] = (DropdownVirtualizedItem);
3198
-
3199
- /***/ }),
3200
- /* 31 */
3201
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
3202
-
3203
- "use strict";
3204
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DropdownPopper; });
3205
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
3206
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
3207
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
3208
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
3209
- /* harmony import */ var react_popper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(32);
3210
- /* harmony import */ var react_popper__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_popper__WEBPACK_IMPORTED_MODULE_2__);
3211
- /* harmony import */ var _khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(33);
3212
- /* harmony import */ var _khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_3__);
3213
-
3214
-
3215
-
3216
-
3217
- const modifiers = [{
3218
- name: "preventOverflow",
3219
- options: {
3220
- rootBoundary: "viewport",
3221
- // Allows to overlap the popper in case there's no more vertical
3222
- // room in the viewport.
3223
- altAxis: true,
3224
- // Also needed to make sure the Popper will be displayed correctly
3225
- // in different contexts (e.g inside a Modal)
3226
- tether: false
3227
- }
3228
- }];
3229
-
3230
- /**
3231
- * A wrapper for PopperJS that renders the children inside a portal.
3232
- */
3233
- function DropdownPopper({
3234
- children,
3235
- alignment = "left",
3236
- onPopperElement,
3237
- referenceElement
3238
- }) {
3239
- // If we are in a modal, we find where we should be portalling the menu by
3240
- // using the helper function from the modal package on the opener element.
3241
- // If we are not in a modal, we use body as the location to portal to.
3242
- const modalHost = Object(_khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_3__["maybeGetPortalMountedModalHostElement"])(referenceElement) || document.querySelector("body");
3243
-
3244
- if (!modalHost) {
3245
- return null;
3246
- }
3247
-
3248
- return /*#__PURE__*/react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.createPortal( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react_popper__WEBPACK_IMPORTED_MODULE_2__["Popper"], {
3249
- innerRef: node => {
3250
- if (node && onPopperElement) {
3251
- onPopperElement(node);
3252
- }
3253
- },
3254
- referenceElement: referenceElement,
3255
- strategy: "fixed",
3256
- placement: alignment === "left" ? "bottom-start" : "bottom-end",
3257
- modifiers: modifiers
3258
- }, ({
3259
- placement,
3260
- ref,
3261
- style,
3262
- hasPopperEscaped,
3263
- isReferenceHidden
3264
- }) => {
3265
- const shouldHidePopper = !!(hasPopperEscaped || isReferenceHidden);
3266
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("div", {
3267
- ref: ref,
3268
- style: style,
3269
- "data-test-id": "dropdown-popper",
3270
- "data-placement": placement
3271
- }, children(shouldHidePopper));
3272
- }), modalHost);
3273
- }
3274
-
3275
- /***/ }),
3276
- /* 32 */
3277
- /***/ (function(module, exports) {
3278
-
3279
- module.exports = require("react-popper");
3280
-
3281
- /***/ }),
3282
- /* 33 */
3283
- /***/ (function(module, exports) {
3284
-
3285
- module.exports = require("@khanacademy/wonder-blocks-modal");
3286
-
3287
- /***/ }),
3288
- /* 34 */
3289
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
3290
-
3291
- "use strict";
3292
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ActionMenuOpenerCore; });
3293
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
3294
- /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__);
3295
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
3296
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
3297
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
3298
- /* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_2__);
3299
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10);
3300
- /* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_3__);
3301
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2);
3302
- /* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__);
3303
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5);
3304
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__);
3305
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(9);
3306
- /* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_6__);
3307
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(3);
3308
- /* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7__);
3309
- /* harmony import */ var _khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(35);
3310
- /* harmony import */ var _khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_8__);
3311
- /* harmony import */ var _util_constants_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(1);
3312
-
3313
-
3314
-
3315
-
3316
-
3317
-
3318
-
3319
-
3320
-
3321
-
3322
- const StyledButton = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__["addStyle"])("button");
3323
- /**
3324
- * Although this component shares a lot with ButtonCore there are a couple
3325
- * of differences:
3326
- * - the down caret icon appears on the right instead of the left
3327
- * - the down caret icon is smaller that the one that would be used by ButtonCore
3328
- */
3329
-
3330
- class ActionMenuOpenerCore extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
3331
- render() {
3332
- const {
3333
- children,
3334
- disabled: disabledProp,
3335
- focused,
3336
- hovered,
3337
- pressed,
3338
- waiting: _,
3339
- testId,
3340
- opened,
3341
- "aria-label": ariaLabel,
3342
- ...restProps
3343
- } = this.props;
3344
- const buttonColor = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["SemanticColor"].controlDefault;
3345
-
3346
- const buttonStyles = _generateStyles(buttonColor);
3347
-
3348
- const disabled = disabledProp;
3349
- const defaultStyle = [sharedStyles.shared, disabled && sharedStyles.disabled, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && pressed && buttonStyles.active];
3350
- const label = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_3__["LabelLarge"], {
3351
- style: sharedStyles.text
3352
- }, children);
3353
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](StyledButton, _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0___default()({
3354
- "aria-expanded": opened ? "true" : "false",
3355
- "aria-haspopup": "menu",
3356
- "aria-label": ariaLabel,
3357
- disabled: disabled,
3358
- style: defaultStyle,
3359
- type: "button"
3360
- }, restProps, {
3361
- "data-test-id": testId
3362
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_5__["View"], {
3363
- style: !disabled && (hovered || focused) && buttonStyles.focus
3364
- }, label), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_8__["Strut"], {
3365
- size: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7___default.a.xxxSmall_4
3366
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_6___default.a, {
3367
- size: "small",
3368
- color: "currentColor",
3369
- icon: _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_6__["icons"].caretDown
3370
- }));
3371
- }
3372
-
3373
- }
3374
- const sharedStyles = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create({
3375
- shared: {
3376
- position: "relative",
3377
- display: "inline-flex",
3378
- alignItems: "center",
3379
- justifyContent: "center",
3380
- height: _util_constants_js__WEBPACK_IMPORTED_MODULE_9__[/* DROPDOWN_ITEM_HEIGHT */ "a"],
3381
- border: "none",
3382
- borderRadius: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7___default.a.xxxSmall_4,
3383
- cursor: "pointer",
3384
- outline: "none",
3385
- textDecoration: "none",
3386
- boxSizing: "border-box",
3387
- // This removes the 300ms click delay on mobile browsers by indicating that
3388
- // "double-tap to zoom" shouldn't be used on this element.
3389
- touchAction: "manipulation",
3390
- ":focus": {
3391
- // Mobile: Removes a blue highlight style shown when the user clicks a button
3392
- WebkitTapHighlightColor: "rgba(0,0,0,0)"
3393
- }
3394
- },
3395
- disabled: {
3396
- cursor: "auto"
3397
- },
3398
- small: {
3399
- height: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_7___default.a.xLarge_32
3400
- },
3401
- text: {
3402
- textAlign: "left",
3403
- display: "inline-block",
3404
- alignItems: "center",
3405
- fontWeight: "bold",
3406
- userSelect: "none",
3407
- whiteSpace: "nowrap",
3408
- overflow: "hidden",
3409
- textOverflow: "ellipsis",
3410
- pointerEvents: "none" // fix Safari bug where the browser was eating mouse events
3411
-
3412
- },
3413
- hiddenText: {
3414
- visibility: "hidden"
3415
- },
3416
- spinner: {
3417
- position: "absolute"
3418
- }
3419
- });
3420
- const styles = {};
3421
-
3422
- const _generateStyles = color => {
3423
- const buttonType = color;
3424
-
3425
- if (styles[buttonType]) {
3426
- return styles[buttonType];
3427
- }
3428
-
3429
- const {
3430
- offBlack32
3431
- } = _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default.a;
3432
- const activeColor = Object(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__["mix"])(offBlack32, color);
3433
- let newStyles = {};
3434
- newStyles = {
3435
- default: {
3436
- background: "none",
3437
- color: color
3438
- },
3439
- focus: {
3440
- ":after": {
3441
- content: "''",
3442
- position: "absolute",
3443
- height: 2,
3444
- left: 0,
3445
- right: 0,
3446
- bottom: -1,
3447
- background: "currentColor",
3448
- borderRadius: 2
3449
- }
3450
- },
3451
- active: {
3452
- color: activeColor
3453
- },
3454
- disabled: {
3455
- color: offBlack32,
3456
- cursor: "default"
3457
- }
3458
- };
3459
- styles[buttonType] = aphrodite__WEBPACK_IMPORTED_MODULE_2__["StyleSheet"].create(newStyles);
3460
- return styles[buttonType];
3461
- };
3462
-
3463
- /***/ }),
3464
- /* 35 */
3465
- /***/ (function(module, exports) {
3466
-
3467
- module.exports = require("@khanacademy/wonder-blocks-layout");
3468
-
3469
- /***/ }),
3470
- /* 36 */
3471
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
3472
-
3473
- "use strict";
3474
- __webpack_require__.r(__webpack_exports__);
3475
- /* harmony import */ var _components_action_item_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12);
3476
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ActionItem", function() { return _components_action_item_js__WEBPACK_IMPORTED_MODULE_0__["a"]; });
3477
-
3478
- /* harmony import */ var _components_option_item_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
3479
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "OptionItem", function() { return _components_option_item_js__WEBPACK_IMPORTED_MODULE_1__["a"]; });
3480
-
3481
- /* harmony import */ var _components_separator_item_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
3482
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "SeparatorItem", function() { return _components_separator_item_js__WEBPACK_IMPORTED_MODULE_2__["a"]; });
3483
-
3484
- /* harmony import */ var _components_action_menu_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(22);
3485
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ActionMenu", function() { return _components_action_menu_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
3486
-
3487
- /* harmony import */ var _components_single_select_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(23);
3488
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "SingleSelect", function() { return _components_single_select_js__WEBPACK_IMPORTED_MODULE_4__["a"]; });
3489
-
3490
- /* harmony import */ var _components_multi_select_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(24);
3491
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "MultiSelect", function() { return _components_multi_select_js__WEBPACK_IMPORTED_MODULE_5__["a"]; });
3492
-
3493
-
3494
-
3495
-
3496
-
3497
-
3498
-
3499
-
3500
-
3501
- /***/ })
3502
- /******/ ]);