@khanacademy/wonder-blocks-popover 1.1.0 → 1.1.1
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 +897 -821
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ module.exports =
|
|
|
82
82
|
/******/
|
|
83
83
|
/******/
|
|
84
84
|
/******/ // Load entry module and return exports
|
|
85
|
-
/******/ return __webpack_require__(__webpack_require__.s =
|
|
85
|
+
/******/ return __webpack_require__(__webpack_require__.s = 22);
|
|
86
86
|
/******/ })
|
|
87
87
|
/************************************************************************/
|
|
88
88
|
/******/ ([
|
|
@@ -117,100 +117,11 @@ module.exports = require("@khanacademy/wonder-blocks-color");
|
|
|
117
117
|
|
|
118
118
|
/***/ }),
|
|
119
119
|
/* 5 */
|
|
120
|
-
/***/ (function(module, exports) {
|
|
121
|
-
|
|
122
|
-
module.exports = require("aphrodite");
|
|
123
|
-
|
|
124
|
-
/***/ }),
|
|
125
|
-
/* 6 */
|
|
126
|
-
/***/ (function(module, exports) {
|
|
127
|
-
|
|
128
|
-
function _extends() {
|
|
129
|
-
module.exports = _extends = Object.assign || function (target) {
|
|
130
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
131
|
-
var source = arguments[i];
|
|
132
|
-
|
|
133
|
-
for (var key in source) {
|
|
134
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
135
|
-
target[key] = source[key];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return target;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
|
144
|
-
return _extends.apply(this, arguments);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
module.exports = _extends;
|
|
148
|
-
module.exports["default"] = module.exports, module.exports.__esModule = true;
|
|
149
|
-
|
|
150
|
-
/***/ }),
|
|
151
|
-
/* 7 */
|
|
152
|
-
/***/ (function(module, exports) {
|
|
153
|
-
|
|
154
|
-
module.exports = require("@khanacademy/wonder-blocks-tooltip");
|
|
155
|
-
|
|
156
|
-
/***/ }),
|
|
157
|
-
/* 8 */
|
|
158
|
-
/***/ (function(module, exports) {
|
|
159
|
-
|
|
160
|
-
module.exports = require("@khanacademy/wonder-blocks-typography");
|
|
161
|
-
|
|
162
|
-
/***/ }),
|
|
163
|
-
/* 9 */
|
|
164
|
-
/***/ (function(module, exports) {
|
|
165
|
-
|
|
166
|
-
module.exports = require("@khanacademy/wonder-blocks-modal");
|
|
167
|
-
|
|
168
|
-
/***/ }),
|
|
169
|
-
/* 10 */
|
|
170
|
-
/***/ (function(module, exports) {
|
|
171
|
-
|
|
172
|
-
module.exports = require("@khanacademy/wonder-blocks-icon");
|
|
173
|
-
|
|
174
|
-
/***/ }),
|
|
175
|
-
/* 11 */
|
|
176
|
-
/***/ (function(module, exports) {
|
|
177
|
-
|
|
178
|
-
module.exports = require("@khanacademy/wonder-blocks-icon-button");
|
|
179
|
-
|
|
180
|
-
/***/ }),
|
|
181
|
-
/* 12 */
|
|
182
120
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
183
121
|
|
|
184
122
|
"use strict";
|
|
185
|
-
|
|
186
|
-
__webpack_require__.
|
|
187
|
-
|
|
188
|
-
// EXPORTS
|
|
189
|
-
__webpack_require__.d(__webpack_exports__, "Popover", function() { return /* reexport */ popover_Popover; });
|
|
190
|
-
__webpack_require__.d(__webpack_exports__, "PopoverContent", function() { return /* reexport */ popover_content_PopoverContent; });
|
|
191
|
-
__webpack_require__.d(__webpack_exports__, "PopoverContentCore", function() { return /* reexport */ popover_content_core_PopoverContentCore; });
|
|
192
|
-
|
|
193
|
-
// EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/extends.js
|
|
194
|
-
var helpers_extends = __webpack_require__(6);
|
|
195
|
-
var extends_default = /*#__PURE__*/__webpack_require__.n(helpers_extends);
|
|
196
|
-
|
|
197
|
-
// EXTERNAL MODULE: external "react"
|
|
198
|
-
var external_react_ = __webpack_require__(0);
|
|
199
|
-
|
|
200
|
-
// EXTERNAL MODULE: external "react-dom"
|
|
201
|
-
var external_react_dom_ = __webpack_require__(3);
|
|
202
|
-
var external_react_dom_default = /*#__PURE__*/__webpack_require__.n(external_react_dom_);
|
|
203
|
-
|
|
204
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-core"
|
|
205
|
-
var wonder_blocks_core_ = __webpack_require__(2);
|
|
206
|
-
|
|
207
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-tooltip"
|
|
208
|
-
var wonder_blocks_tooltip_ = __webpack_require__(7);
|
|
209
|
-
|
|
210
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-modal"
|
|
211
|
-
var wonder_blocks_modal_ = __webpack_require__(9);
|
|
212
|
-
|
|
213
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-context.js
|
|
123
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
124
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
214
125
|
|
|
215
126
|
const defaultContext = {
|
|
216
127
|
close: undefined,
|
|
@@ -227,70 +138,47 @@ const defaultContext = {
|
|
|
227
138
|
* of the following values: "top", "bottom", "left" or "right".
|
|
228
139
|
*/
|
|
229
140
|
|
|
230
|
-
/* harmony default export */
|
|
231
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-anchor.js
|
|
141
|
+
/* harmony default export */ __webpack_exports__["a"] = (/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](defaultContext));
|
|
232
142
|
|
|
143
|
+
/***/ }),
|
|
144
|
+
/* 6 */
|
|
145
|
+
/***/ (function(module, exports) {
|
|
233
146
|
|
|
147
|
+
module.exports = require("aphrodite");
|
|
234
148
|
|
|
149
|
+
/***/ }),
|
|
150
|
+
/* 7 */
|
|
151
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
235
152
|
|
|
153
|
+
"use strict";
|
|
154
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return findFocusableNodes; });
|
|
236
155
|
/**
|
|
237
|
-
*
|
|
238
|
-
*
|
|
156
|
+
* List of elements that can be focused
|
|
157
|
+
* @see https://www.w3.org/TR/html5/editing.html#can-be-focused
|
|
239
158
|
*/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (anchorNode) {
|
|
245
|
-
this.props.anchorRef(anchorNode);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
render() {
|
|
250
|
-
const {
|
|
251
|
-
children,
|
|
252
|
-
id,
|
|
253
|
-
onClick,
|
|
254
|
-
"aria-controls": ariaControls,
|
|
255
|
-
"aria-expanded": ariaExpanded
|
|
256
|
-
} = this.props; // props that will be injected to both children versions
|
|
257
|
-
|
|
258
|
-
const sharedProps = {
|
|
259
|
-
id: id,
|
|
260
|
-
"aria-controls": ariaControls,
|
|
261
|
-
"aria-expanded": ariaExpanded
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
if (typeof children === "function") {
|
|
265
|
-
const renderedChildren = children({
|
|
266
|
-
open: onClick
|
|
267
|
-
}); // we clone it to allow injecting the sharedProps defined before
|
|
268
|
-
|
|
269
|
-
return /*#__PURE__*/external_react_["cloneElement"](renderedChildren, sharedProps);
|
|
270
|
-
} else {
|
|
271
|
-
// add onClick handler to automatically open the dialog after
|
|
272
|
-
// clicking on this anchor element
|
|
273
|
-
return /*#__PURE__*/external_react_["cloneElement"](children, extends_default()({}, children.props, sharedProps, {
|
|
274
|
-
onClick: children.props.onClick ? e => {
|
|
275
|
-
e.stopPropagation(); // This is done to avoid overriding a custom onClick
|
|
276
|
-
// handler inside the children node
|
|
277
|
-
|
|
278
|
-
children.props.onClick();
|
|
279
|
-
onClick();
|
|
280
|
-
} : onClick
|
|
281
|
-
}));
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
159
|
+
const FOCUSABLE_ELEMENTS = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
160
|
+
function findFocusableNodes(root) {
|
|
161
|
+
return Array.from(root.querySelectorAll(FOCUSABLE_ELEMENTS));
|
|
285
162
|
}
|
|
286
|
-
// EXTERNAL MODULE: external "aphrodite"
|
|
287
|
-
var external_aphrodite_ = __webpack_require__(5);
|
|
288
163
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
164
|
+
/***/ }),
|
|
165
|
+
/* 8 */
|
|
166
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
167
|
+
|
|
168
|
+
"use strict";
|
|
169
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PopoverContentCore; });
|
|
170
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
171
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
172
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
|
|
173
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
|
|
174
|
+
/* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
|
|
175
|
+
/* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2__);
|
|
176
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2);
|
|
177
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__);
|
|
178
|
+
/* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1);
|
|
179
|
+
/* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4__);
|
|
180
|
+
/* harmony import */ var _close_button_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19);
|
|
292
181
|
|
|
293
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-dialog.js
|
|
294
182
|
|
|
295
183
|
|
|
296
184
|
|
|
@@ -298,903 +186,1091 @@ var wonder_blocks_color_default = /*#__PURE__*/__webpack_require__.n(wonder_bloc
|
|
|
298
186
|
|
|
299
187
|
|
|
300
188
|
/**
|
|
301
|
-
* This is
|
|
302
|
-
*
|
|
303
|
-
* that can be of type [PopoverContent](#PopoverContent) or
|
|
304
|
-
* [PopoverContentCore](#PopoverContentCore), and the
|
|
305
|
-
* [TooltipTail](#TooltipTail).
|
|
306
|
-
*
|
|
307
|
-
* The main difference with [TooltipBubble](#TooltipBubble) is that bubble
|
|
308
|
-
* handles hover states and PopoverDialog doesn't need to handle any states at
|
|
309
|
-
* all (for now). Also, PopoverDialog needs to coordinate different background
|
|
310
|
-
* colors for the content and tail components.
|
|
311
|
-
*
|
|
312
|
-
* Note that without explicit positioning, the tail will not be centered.
|
|
189
|
+
* This is the base popover container. It’s used internally by all the variants.
|
|
190
|
+
* Also, it can be used to create flexible popovers.
|
|
313
191
|
*/
|
|
314
|
-
class
|
|
315
|
-
componentDidUpdate(prevProps) {
|
|
316
|
-
// if the placement has changed, then we need to notify this to the
|
|
317
|
-
// parent component (`Popover`). This way, the context will update its
|
|
318
|
-
// `placement` value.
|
|
319
|
-
if (prevProps.placement !== this.props.placement) {
|
|
320
|
-
this.props.onUpdate(this.props.placement);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
192
|
+
class PopoverContentCore extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
324
193
|
render() {
|
|
325
194
|
const {
|
|
326
|
-
placement,
|
|
327
195
|
children,
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
tailOffset,
|
|
196
|
+
closeButtonLight,
|
|
197
|
+
closeButtonLabel,
|
|
198
|
+
closeButtonVisible,
|
|
199
|
+
color,
|
|
333
200
|
style,
|
|
334
|
-
|
|
201
|
+
testId
|
|
335
202
|
} = this.props;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
"aria-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
style: [isReferenceHidden && styles.hide, styles[`content-${placement}`], style]
|
|
346
|
-
}, children, /*#__PURE__*/external_react_["createElement"](wonder_blocks_tooltip_["TooltipTail"], {
|
|
347
|
-
color: color,
|
|
348
|
-
updateRef: updateTailRef,
|
|
349
|
-
placement: placement,
|
|
350
|
-
offset: tailOffset
|
|
351
|
-
})));
|
|
203
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_3__["View"], {
|
|
204
|
+
"data-test-id": testId,
|
|
205
|
+
style: [styles.content, color !== "white" && styles[color], style]
|
|
206
|
+
}, closeButtonVisible && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_close_button_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"], {
|
|
207
|
+
"aria-label": closeButtonLabel,
|
|
208
|
+
light: closeButtonLight || color !== "white",
|
|
209
|
+
style: styles.closeButton,
|
|
210
|
+
testId: `${testId || "popover"}-close-btn`
|
|
211
|
+
}), children);
|
|
352
212
|
}
|
|
353
213
|
|
|
354
214
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
215
|
+
PopoverContentCore.defaultProps = {
|
|
216
|
+
color: "white",
|
|
217
|
+
closeButtonLight: false,
|
|
218
|
+
closeButtonVisible: false
|
|
219
|
+
};
|
|
220
|
+
const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
|
|
221
|
+
content: {
|
|
222
|
+
borderRadius: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xxxSmall_4,
|
|
223
|
+
border: `solid 1px ${_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.offBlack16}`,
|
|
224
|
+
backgroundColor: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.white,
|
|
225
|
+
boxShadow: `0 ${_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8}px ${_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8}px 0 ${_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.offBlack8}`,
|
|
226
|
+
margin: 0,
|
|
227
|
+
maxWidth: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.medium_16 * 18,
|
|
228
|
+
// 288px
|
|
229
|
+
padding: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.large_24,
|
|
230
|
+
overflow: "hidden",
|
|
231
|
+
justifyContent: "center"
|
|
367
232
|
},
|
|
368
233
|
|
|
369
234
|
/**
|
|
370
|
-
*
|
|
235
|
+
* Theming
|
|
371
236
|
*/
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
"content-right": {
|
|
376
|
-
flexDirection: "row-reverse"
|
|
237
|
+
blue: {
|
|
238
|
+
backgroundColor: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.blue,
|
|
239
|
+
color: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.white
|
|
377
240
|
},
|
|
378
|
-
|
|
379
|
-
|
|
241
|
+
darkBlue: {
|
|
242
|
+
backgroundColor: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.darkBlue,
|
|
243
|
+
color: _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_2___default.a.white
|
|
380
244
|
},
|
|
381
|
-
|
|
382
|
-
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* elements
|
|
248
|
+
*/
|
|
249
|
+
closeButton: {
|
|
250
|
+
position: "absolute",
|
|
251
|
+
right: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8,
|
|
252
|
+
top: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8,
|
|
253
|
+
// Allows the button to be above the title and/or custom content
|
|
254
|
+
zIndex: 1
|
|
383
255
|
}
|
|
384
256
|
});
|
|
385
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/util/util.js
|
|
386
|
-
/**
|
|
387
|
-
* List of elements that can be focused
|
|
388
|
-
* @see https://www.w3.org/TR/html5/editing.html#can-be-focused
|
|
389
|
-
*/
|
|
390
|
-
const FOCUSABLE_ELEMENTS = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
391
|
-
function findFocusableNodes(root) {
|
|
392
|
-
return Array.from(root.querySelectorAll(FOCUSABLE_ELEMENTS));
|
|
393
|
-
}
|
|
394
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/initial-focus.js
|
|
395
257
|
|
|
258
|
+
/***/ }),
|
|
259
|
+
/* 9 */
|
|
260
|
+
/***/ (function(module, exports) {
|
|
396
261
|
|
|
262
|
+
module.exports = require("@khanacademy/wonder-blocks-tooltip");
|
|
397
263
|
|
|
264
|
+
/***/ }),
|
|
265
|
+
/* 10 */
|
|
266
|
+
/***/ (function(module, exports) {
|
|
398
267
|
|
|
399
|
-
|
|
400
|
-
* This component finds which element (from within the children) needs to
|
|
401
|
-
* receive focus. After that, the children is rendered with the focus assigned.
|
|
402
|
-
*/
|
|
403
|
-
class initial_focus_InitialFocus extends external_react_["Component"] {
|
|
404
|
-
constructor(...args) {
|
|
405
|
-
super(...args);
|
|
268
|
+
module.exports = require("@khanacademy/wonder-blocks-typography");
|
|
406
269
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
// 3. If no focusable elements are found, get the container itself
|
|
411
|
-
const firstFocusableElement = this.maybeGetInitialFocusElement(node) || this.maybeGetFirstFocusableElement(node) || node;
|
|
270
|
+
/***/ }),
|
|
271
|
+
/* 11 */
|
|
272
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
412
273
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
274
|
+
"use strict";
|
|
275
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Popover; });
|
|
276
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
277
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
278
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
279
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
|
|
280
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
|
|
281
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__);
|
|
282
|
+
/* harmony import */ var _khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
|
|
283
|
+
/* harmony import */ var _khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__);
|
|
284
|
+
/* harmony import */ var _khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(13);
|
|
285
|
+
/* harmony import */ var _khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_4__);
|
|
286
|
+
/* harmony import */ var _popover_context_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5);
|
|
287
|
+
/* harmony import */ var _popover_anchor_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(14);
|
|
288
|
+
/* harmony import */ var _popover_dialog_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(15);
|
|
289
|
+
/* harmony import */ var _focus_manager_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(16);
|
|
290
|
+
/* harmony import */ var _popover_event_listener_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(18);
|
|
291
|
+
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
417
292
|
|
|
418
293
|
|
|
419
|
-
setTimeout(() => {
|
|
420
|
-
firstFocusableElement.focus();
|
|
421
|
-
}, 0);
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
294
|
|
|
425
|
-
componentDidMount() {
|
|
426
|
-
const node = external_react_dom_["findDOMNode"](this);
|
|
427
295
|
|
|
428
|
-
if (!node) {
|
|
429
|
-
return;
|
|
430
|
-
} // try to focus on the first focussable element
|
|
431
296
|
|
|
432
297
|
|
|
433
|
-
this.setInitialFocusableElement(node);
|
|
434
|
-
}
|
|
435
|
-
/**
|
|
436
|
-
* Gets the focusable element and applies focus to it
|
|
437
|
-
*/
|
|
438
298
|
|
|
439
299
|
|
|
440
|
-
/**
|
|
441
|
-
* Returns an element specified by the user
|
|
442
|
-
*/
|
|
443
|
-
maybeGetInitialFocusElement(node) {
|
|
444
|
-
const {
|
|
445
|
-
initialFocusId
|
|
446
|
-
} = this.props;
|
|
447
300
|
|
|
448
|
-
if (!initialFocusId) {
|
|
449
|
-
return null;
|
|
450
|
-
}
|
|
451
301
|
|
|
452
|
-
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Popovers provide additional information that is related to a particular
|
|
306
|
+
* element and/or content. They can include text, links, icons and
|
|
307
|
+
* illustrations. The main difference with `Tooltip` is that they must be
|
|
308
|
+
* dismissed by clicking an element.
|
|
309
|
+
*
|
|
310
|
+
* This component uses the `PopoverPopper` component to position the
|
|
311
|
+
* `PopoverContentCore` component according to the children it is wrapping.
|
|
312
|
+
*/
|
|
313
|
+
class Popover extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
314
|
+
constructor(...args) {
|
|
315
|
+
super(...args);
|
|
316
|
+
this.state = {
|
|
317
|
+
opened: !!this.props.opened,
|
|
318
|
+
anchorElement: null,
|
|
319
|
+
placement: this.props.placement
|
|
320
|
+
};
|
|
321
|
+
this.contentRef = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createRef"]();
|
|
322
|
+
|
|
323
|
+
this.handleClose = () => {
|
|
324
|
+
this.setState({
|
|
325
|
+
opened: false
|
|
326
|
+
}, () => {
|
|
327
|
+
this.props.onClose && this.props.onClose();
|
|
328
|
+
});
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
this.handleOpen = () => {
|
|
332
|
+
if (this.props.dismissEnabled && this.state.opened) {
|
|
333
|
+
this.setState({
|
|
334
|
+
opened: false
|
|
335
|
+
});
|
|
336
|
+
} else {
|
|
337
|
+
this.setState({
|
|
338
|
+
opened: true
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
this.updateRef = ref => {
|
|
344
|
+
const actualRef = ref && react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.findDOMNode(ref);
|
|
345
|
+
|
|
346
|
+
if (actualRef && this.state.anchorElement !== actualRef) {
|
|
347
|
+
this.setState({
|
|
348
|
+
anchorElement: actualRef
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
};
|
|
453
352
|
}
|
|
353
|
+
|
|
454
354
|
/**
|
|
455
|
-
*
|
|
355
|
+
* Used to sync the `opened` state when Popover acts as a controlled
|
|
356
|
+
* component
|
|
456
357
|
*/
|
|
358
|
+
static getDerivedStateFromProps(props, state) {
|
|
359
|
+
return {
|
|
360
|
+
opened: typeof props.opened === "boolean" ? props.opened : state.opened
|
|
361
|
+
};
|
|
362
|
+
}
|
|
457
363
|
|
|
364
|
+
renderContent() {
|
|
365
|
+
const {
|
|
366
|
+
content
|
|
367
|
+
} = this.props;
|
|
368
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](typeof content === "function" ? content({
|
|
369
|
+
close: this.handleClose
|
|
370
|
+
}) : content, {
|
|
371
|
+
ref: this.contentRef
|
|
372
|
+
});
|
|
373
|
+
}
|
|
458
374
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
375
|
+
renderPopper(uniqueId) {
|
|
376
|
+
const {
|
|
377
|
+
initialFocusId,
|
|
378
|
+
placement
|
|
379
|
+
} = this.props;
|
|
380
|
+
const {
|
|
381
|
+
anchorElement
|
|
382
|
+
} = this.state;
|
|
383
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_focus_manager_js__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"], {
|
|
384
|
+
anchorElement: anchorElement,
|
|
385
|
+
initialFocusId: initialFocusId
|
|
386
|
+
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__["TooltipPopper"], {
|
|
387
|
+
anchorElement: anchorElement,
|
|
388
|
+
placement: placement
|
|
389
|
+
}, props => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_dialog_js__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"], _extends({}, props, {
|
|
390
|
+
"aria-describedby": `${uniqueId}-anchor`,
|
|
391
|
+
id: uniqueId,
|
|
392
|
+
onUpdate: placement => this.setState({
|
|
393
|
+
placement
|
|
394
|
+
})
|
|
395
|
+
}), this.renderContent())));
|
|
396
|
+
}
|
|
467
397
|
|
|
468
|
-
|
|
398
|
+
getHost() {
|
|
399
|
+
// If we are in a modal, we find where we should be portalling the
|
|
400
|
+
// popover by using the helper function from the modal package on the
|
|
401
|
+
// trigger element. If we are not in a modal, we use body as the
|
|
402
|
+
// location to portal to.
|
|
403
|
+
return Object(_khanacademy_wonder_blocks_modal__WEBPACK_IMPORTED_MODULE_4__["maybeGetPortalMountedModalHostElement"])(this.state.anchorElement) || document.body;
|
|
469
404
|
}
|
|
470
405
|
|
|
471
406
|
render() {
|
|
472
|
-
|
|
407
|
+
const {
|
|
408
|
+
children,
|
|
409
|
+
dismissEnabled,
|
|
410
|
+
id
|
|
411
|
+
} = this.props;
|
|
412
|
+
const {
|
|
413
|
+
opened,
|
|
414
|
+
placement
|
|
415
|
+
} = this.state;
|
|
416
|
+
const popperHost = this.getHost();
|
|
417
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_context_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"].Provider, {
|
|
418
|
+
value: {
|
|
419
|
+
close: this.handleClose,
|
|
420
|
+
placement: placement
|
|
421
|
+
}
|
|
422
|
+
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["IDProvider"], {
|
|
423
|
+
id: id,
|
|
424
|
+
scope: "popover"
|
|
425
|
+
}, uniqueId => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_anchor_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"], {
|
|
426
|
+
anchorRef: this.updateRef,
|
|
427
|
+
id: `${uniqueId}-anchor`,
|
|
428
|
+
"aria-controls": uniqueId,
|
|
429
|
+
"aria-expanded": opened ? "true" : "false",
|
|
430
|
+
onClick: this.handleOpen
|
|
431
|
+
}, children), popperHost && opened && /*#__PURE__*/react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.createPortal(this.renderPopper(uniqueId), popperHost))), dismissEnabled && opened && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_event_listener_js__WEBPACK_IMPORTED_MODULE_9__[/* default */ "a"], {
|
|
432
|
+
onClose: this.handleClose,
|
|
433
|
+
contentRef: this.contentRef
|
|
434
|
+
}));
|
|
473
435
|
}
|
|
474
436
|
|
|
475
437
|
}
|
|
476
|
-
|
|
438
|
+
Popover.defaultProps = {
|
|
439
|
+
placement: "top"
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
/***/ }),
|
|
443
|
+
/* 12 */
|
|
444
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
445
|
+
|
|
446
|
+
"use strict";
|
|
447
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PopoverContent; });
|
|
448
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
449
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
450
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
|
|
451
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
|
|
452
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
|
|
453
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__);
|
|
454
|
+
/* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1);
|
|
455
|
+
/* harmony import */ var _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3__);
|
|
456
|
+
/* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10);
|
|
457
|
+
/* harmony import */ var _khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_4__);
|
|
458
|
+
/* harmony import */ var _popover_content_core_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8);
|
|
459
|
+
/* harmony import */ var _popover_context_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5);
|
|
460
|
+
|
|
477
461
|
|
|
478
462
|
|
|
479
463
|
|
|
480
464
|
|
|
481
465
|
|
|
466
|
+
|
|
467
|
+
// Created to add custom styles to the icon or image elements
|
|
468
|
+
const StyledImage = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["addStyle"])("img");
|
|
482
469
|
/**
|
|
483
|
-
* This
|
|
484
|
-
*
|
|
485
|
-
* Inside the popover:
|
|
486
|
-
* - `tab`: Moves focus to the next focusable element.
|
|
487
|
-
* - `shift + tab`: Moves focus to the previous focusable element.
|
|
488
|
-
*
|
|
489
|
-
* After the focus reaches the start/end of the popover, then we handle two
|
|
490
|
-
* different scenarios:
|
|
491
|
-
*
|
|
492
|
-
* 1. If the focus has reached the last focusable element inside the popover,
|
|
493
|
-
* the next tab will set focus on the next focusable element that exists
|
|
494
|
-
* after the PopoverAnchor.
|
|
495
|
-
* 2. If the focus is set to the first focusable element inside the popover, the
|
|
496
|
-
* next shift + tab will set focus on the PopoverAnchor element.
|
|
497
|
-
*
|
|
470
|
+
* This is the container that is consumed by all the predefined variations. Its
|
|
471
|
+
* main responsibility is populate the contents depending on the variation used.
|
|
498
472
|
*/
|
|
499
|
-
|
|
473
|
+
|
|
474
|
+
class PopoverContent extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
500
475
|
constructor(...args) {
|
|
501
476
|
super(...args);
|
|
502
|
-
this.focusableElementsInPopover = [];
|
|
503
477
|
|
|
504
|
-
this.
|
|
478
|
+
this.maybeRenderImage = ({
|
|
479
|
+
placement
|
|
480
|
+
}) => {
|
|
505
481
|
const {
|
|
506
|
-
|
|
482
|
+
image
|
|
507
483
|
} = this.props;
|
|
508
484
|
|
|
509
|
-
if (
|
|
510
|
-
|
|
511
|
-
} // tries to get the next focusable element outside of the popover
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
this.nextElementAfterPopover = this.getNextFocusableElement();
|
|
515
|
-
|
|
516
|
-
if (this.nextElementAfterPopover) {
|
|
517
|
-
this.nextElementAfterPopover.addEventListener("keydown", this.handleKeydownNextFocusableElement, true);
|
|
485
|
+
if (!image) {
|
|
486
|
+
return null;
|
|
518
487
|
}
|
|
488
|
+
|
|
489
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
490
|
+
style: [styles.image, placement === "bottom" && styles.imageToBottom]
|
|
491
|
+
}, image);
|
|
519
492
|
};
|
|
520
493
|
|
|
521
|
-
this.
|
|
494
|
+
this.maybeRenderIcon = () => {
|
|
522
495
|
const {
|
|
523
|
-
|
|
496
|
+
icon
|
|
524
497
|
} = this.props;
|
|
525
498
|
|
|
526
|
-
if (!
|
|
527
|
-
return;
|
|
528
|
-
} // get the total list of focusable elements within the document
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const focusableElements = findFocusableNodes(document); // get anchor element index
|
|
532
|
-
|
|
533
|
-
const anchorIndex = focusableElements.indexOf(anchorElement);
|
|
534
|
-
|
|
535
|
-
if (anchorIndex >= 0) {
|
|
536
|
-
// guess next focusable element index
|
|
537
|
-
const nextElementIndex = anchorIndex < focusableElements.length - 1 ? anchorIndex + 1 : 0; // get next element's DOM reference
|
|
538
|
-
|
|
539
|
-
return focusableElements[nextElementIndex];
|
|
499
|
+
if (!icon) {
|
|
500
|
+
return null;
|
|
540
501
|
}
|
|
541
502
|
|
|
542
|
-
return
|
|
503
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
504
|
+
style: styles.iconContainer
|
|
505
|
+
}, typeof icon !== "string" ? icon : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](StyledImage, {
|
|
506
|
+
src: icon,
|
|
507
|
+
style: styles.icon
|
|
508
|
+
}));
|
|
543
509
|
};
|
|
544
510
|
|
|
545
|
-
this.
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
const rootNode = external_react_dom_["findDOMNode"](node);
|
|
511
|
+
this.maybeRenderActions = close => {
|
|
512
|
+
const {
|
|
513
|
+
actions
|
|
514
|
+
} = this.props;
|
|
552
515
|
|
|
553
|
-
if (!
|
|
554
|
-
|
|
516
|
+
if (!actions) {
|
|
517
|
+
return null;
|
|
555
518
|
}
|
|
556
519
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
520
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
521
|
+
style: styles.actions
|
|
522
|
+
}, typeof actions === "function" ? actions({
|
|
523
|
+
close: close
|
|
524
|
+
}) : actions);
|
|
560
525
|
};
|
|
526
|
+
}
|
|
561
527
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
};
|
|
528
|
+
componentDidMount() {
|
|
529
|
+
const {
|
|
530
|
+
icon,
|
|
531
|
+
image
|
|
532
|
+
} = this.props; // this runtime check is added to support <svg> and <img> elements
|
|
533
|
+
// inside the image prop
|
|
567
534
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
535
|
+
if (image && icon) {
|
|
536
|
+
throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Runtime validation in case we try to use an invalid shape
|
|
541
|
+
*/
|
|
573
542
|
|
|
574
|
-
this.handleKeydownPreviousFocusableElement = e => {
|
|
575
|
-
// It will try focus only if the user is pressing `tab`
|
|
576
|
-
if (e.key === "Tab" && !e.shiftKey) {
|
|
577
|
-
e.preventDefault();
|
|
578
|
-
this.focusableElementsInPopover[0].focus();
|
|
579
|
-
}
|
|
580
|
-
};
|
|
581
543
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
544
|
+
validateProps({
|
|
545
|
+
placement
|
|
546
|
+
}) {
|
|
547
|
+
// illustration popover can't be placed horizontally
|
|
548
|
+
if (this.props.image && (placement === "left" || placement === "right")) {
|
|
549
|
+
throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.");
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
render() {
|
|
554
|
+
const {
|
|
555
|
+
closeButtonLabel,
|
|
556
|
+
closeButtonVisible,
|
|
557
|
+
content,
|
|
558
|
+
emphasized = undefined,
|
|
559
|
+
icon,
|
|
560
|
+
image,
|
|
561
|
+
style,
|
|
562
|
+
title,
|
|
563
|
+
testId
|
|
564
|
+
} = this.props;
|
|
565
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_context_js__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].Consumer, null, ({
|
|
566
|
+
close,
|
|
567
|
+
placement
|
|
568
|
+
}) => {
|
|
569
|
+
// verify if the props are correct
|
|
570
|
+
this.validateProps({
|
|
571
|
+
close,
|
|
572
|
+
placement
|
|
573
|
+
});
|
|
574
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_content_core_js__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"], {
|
|
575
|
+
color: emphasized ? "blue" : "white",
|
|
576
|
+
closeButtonLight: image && placement === "top",
|
|
577
|
+
closeButtonLabel: closeButtonLabel,
|
|
578
|
+
closeButtonVisible: closeButtonVisible,
|
|
579
|
+
style: style,
|
|
580
|
+
testId: testId
|
|
581
|
+
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
582
|
+
style: !!icon && styles.withIcon
|
|
583
|
+
}, this.maybeRenderImage({
|
|
584
|
+
placement
|
|
585
|
+
}), this.maybeRenderIcon(), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
586
|
+
style: styles.text
|
|
587
|
+
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_4__["HeadingSmall"], {
|
|
588
|
+
style: styles.title
|
|
589
|
+
}, title), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_typography__WEBPACK_IMPORTED_MODULE_4__["Body"], null, content))), this.maybeRenderActions(close));
|
|
590
|
+
});
|
|
590
591
|
}
|
|
591
592
|
|
|
593
|
+
}
|
|
594
|
+
PopoverContent.defaultProps = {
|
|
595
|
+
closeButtonVisible: false
|
|
596
|
+
};
|
|
597
|
+
const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
|
|
592
598
|
/**
|
|
593
|
-
*
|
|
599
|
+
* Shared styles
|
|
594
600
|
*/
|
|
601
|
+
actions: {
|
|
602
|
+
marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
603
|
+
flexDirection: "row",
|
|
604
|
+
alignItems: "center",
|
|
605
|
+
justifyContent: "flex-end"
|
|
606
|
+
},
|
|
607
|
+
text: {
|
|
608
|
+
justifyContent: "center"
|
|
609
|
+
},
|
|
610
|
+
title: {
|
|
611
|
+
marginBottom: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xSmall_8
|
|
612
|
+
},
|
|
595
613
|
|
|
596
614
|
/**
|
|
597
|
-
*
|
|
615
|
+
* Icon styles
|
|
598
616
|
*/
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
617
|
+
iconContainer: {
|
|
618
|
+
alignItems: "center",
|
|
619
|
+
justifyContent: "center",
|
|
620
|
+
height: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xxxLarge_64,
|
|
621
|
+
width: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xxxLarge_64,
|
|
622
|
+
minWidth: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.xxxLarge_64,
|
|
623
|
+
marginRight: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.medium_16,
|
|
624
|
+
overflow: "hidden"
|
|
625
|
+
},
|
|
626
|
+
icon: {
|
|
627
|
+
width: "100%"
|
|
628
|
+
},
|
|
629
|
+
withIcon: {
|
|
630
|
+
flexDirection: "row"
|
|
631
|
+
},
|
|
602
632
|
|
|
603
|
-
componentDidUpdate() {
|
|
604
|
-
this.addEventListeners();
|
|
605
|
-
}
|
|
606
633
|
/**
|
|
607
|
-
*
|
|
634
|
+
* Illustration styles
|
|
608
635
|
*/
|
|
636
|
+
image: {
|
|
637
|
+
marginBottom: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
638
|
+
marginLeft: -_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
639
|
+
marginRight: -_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
640
|
+
marginTop: -_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
641
|
+
width: `calc(100% + ${_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24 * 2}px)`
|
|
642
|
+
},
|
|
643
|
+
imageToBottom: {
|
|
644
|
+
marginBottom: -_khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
645
|
+
marginTop: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_3___default.a.large_24,
|
|
646
|
+
order: 1
|
|
647
|
+
}
|
|
648
|
+
});
|
|
609
649
|
|
|
650
|
+
/***/ }),
|
|
651
|
+
/* 13 */
|
|
652
|
+
/***/ (function(module, exports) {
|
|
610
653
|
|
|
611
|
-
|
|
612
|
-
const {
|
|
613
|
-
anchorElement
|
|
614
|
-
} = this.props;
|
|
654
|
+
module.exports = require("@khanacademy/wonder-blocks-modal");
|
|
615
655
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
anchorElement.removeEventListener("keydown", this.handleKeydownPreviousFocusableElement, true);
|
|
620
|
-
}
|
|
656
|
+
/***/ }),
|
|
657
|
+
/* 14 */
|
|
658
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
621
659
|
|
|
622
|
-
|
|
623
|
-
|
|
660
|
+
"use strict";
|
|
661
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PopoverAnchor; });
|
|
662
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
663
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
664
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
665
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* The element that triggers the popover dialog. This is also used as reference
|
|
671
|
+
* to position the dialog itself.
|
|
672
|
+
*/
|
|
673
|
+
class PopoverAnchor extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
674
|
+
componentDidMount() {
|
|
675
|
+
const anchorNode = react_dom__WEBPACK_IMPORTED_MODULE_1__["findDOMNode"](this);
|
|
676
|
+
|
|
677
|
+
if (anchorNode) {
|
|
678
|
+
this.props.anchorRef(anchorNode);
|
|
624
679
|
}
|
|
625
680
|
}
|
|
626
|
-
/**
|
|
627
|
-
* List of focusable elements within the popover content
|
|
628
|
-
*/
|
|
629
|
-
|
|
630
681
|
|
|
631
682
|
render() {
|
|
632
683
|
const {
|
|
633
|
-
children
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
684
|
+
children,
|
|
685
|
+
id,
|
|
686
|
+
onClick,
|
|
687
|
+
"aria-controls": ariaControls,
|
|
688
|
+
"aria-expanded": ariaExpanded
|
|
689
|
+
} = this.props; // props that will be injected to both children versions
|
|
690
|
+
|
|
691
|
+
const sharedProps = {
|
|
692
|
+
id: id,
|
|
693
|
+
"aria-controls": ariaControls,
|
|
694
|
+
"aria-expanded": ariaExpanded
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
if (typeof children === "function") {
|
|
698
|
+
const renderedChildren = children({
|
|
699
|
+
open: onClick
|
|
700
|
+
}); // we clone it to allow injecting the sharedProps defined before
|
|
701
|
+
|
|
702
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](renderedChildren, sharedProps);
|
|
703
|
+
} else {
|
|
704
|
+
// add onClick handler to automatically open the dialog after
|
|
705
|
+
// clicking on this anchor element
|
|
706
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"](children, { ...children.props,
|
|
707
|
+
...sharedProps,
|
|
708
|
+
onClick: children.props.onClick ? e => {
|
|
709
|
+
e.stopPropagation(); // This is done to avoid overriding a custom onClick
|
|
710
|
+
// handler inside the children node
|
|
711
|
+
|
|
712
|
+
children.props.onClick();
|
|
713
|
+
onClick();
|
|
714
|
+
} : onClick
|
|
715
|
+
});
|
|
716
|
+
}
|
|
652
717
|
}
|
|
653
718
|
|
|
654
719
|
}
|
|
655
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-event-listener.js
|
|
656
720
|
|
|
721
|
+
/***/ }),
|
|
722
|
+
/* 15 */
|
|
723
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
657
724
|
|
|
725
|
+
"use strict";
|
|
726
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PopoverDialog; });
|
|
727
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
728
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
729
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
|
|
730
|
+
/* harmony import */ var aphrodite__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aphrodite__WEBPACK_IMPORTED_MODULE_1__);
|
|
731
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
|
|
732
|
+
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__);
|
|
733
|
+
/* harmony import */ var _khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
|
|
734
|
+
/* harmony import */ var _khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__);
|
|
735
|
+
/* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4);
|
|
736
|
+
/* harmony import */ var _khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_color__WEBPACK_IMPORTED_MODULE_4__);
|
|
658
737
|
|
|
659
|
-
/**
|
|
660
|
-
* A component that, when mounted, calls `onClose` when certain events occur.
|
|
661
|
-
* This includes when pressing Escape or clicking outside the Popover.
|
|
662
|
-
* @see @khanacademy/wonder-blocks-modal/components/modal-launcher.js
|
|
663
|
-
*/
|
|
664
|
-
class popover_event_listener_PopoverEventListener extends external_react_["Component"] {
|
|
665
|
-
constructor(...args) {
|
|
666
|
-
super(...args);
|
|
667
|
-
this.state = {
|
|
668
|
-
isFirstClick: true
|
|
669
|
-
};
|
|
670
738
|
|
|
671
|
-
this._handleKeyup = e => {
|
|
672
|
-
// We check the key as that's keyboard layout agnostic and also avoids
|
|
673
|
-
// the minefield of deprecated number type properties like keyCode and
|
|
674
|
-
// which, with the replacement code, which uses a string instead.
|
|
675
|
-
if (e.key === "Escape") {
|
|
676
|
-
// Stop the event going any further.
|
|
677
|
-
// For cancellation events, like the Escape key, we generally should
|
|
678
|
-
// air on the side of caution and only allow it to cancel one thing.
|
|
679
|
-
// So, it's polite for us to stop propagation of the event.
|
|
680
|
-
// Otherwise, we end up with UX where one Escape key press
|
|
681
|
-
// unexpectedly cancels multiple things.
|
|
682
|
-
e.preventDefault();
|
|
683
|
-
e.stopPropagation();
|
|
684
|
-
this.props.onClose();
|
|
685
|
-
}
|
|
686
|
-
};
|
|
687
739
|
|
|
688
|
-
this._handleClick = e => {
|
|
689
|
-
var _this$props$contentRe;
|
|
690
740
|
|
|
691
|
-
// Prevents the problem where clicking the trigger button
|
|
692
|
-
// triggers a click event and immediately closes the popover.
|
|
693
|
-
if (this.state.isFirstClick) {
|
|
694
|
-
this.setState({
|
|
695
|
-
isFirstClick: false
|
|
696
|
-
});
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
741
|
|
|
700
|
-
const node = external_react_dom_default.a.findDOMNode((_this$props$contentRe = this.props.contentRef) == null ? void 0 : _this$props$contentRe.current);
|
|
701
742
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
743
|
+
/**
|
|
744
|
+
* This is an internal component that we use to render the stuff that appears
|
|
745
|
+
* when a popover shows. It's composed by two elements: The popover content,
|
|
746
|
+
* that can be of type [PopoverContent](#PopoverContent) or
|
|
747
|
+
* [PopoverContentCore](#PopoverContentCore), and the
|
|
748
|
+
* [TooltipTail](#TooltipTail).
|
|
749
|
+
*
|
|
750
|
+
* The main difference with [TooltipBubble](#TooltipBubble) is that bubble
|
|
751
|
+
* handles hover states and PopoverDialog doesn't need to handle any states at
|
|
752
|
+
* all (for now). Also, PopoverDialog needs to coordinate different background
|
|
753
|
+
* colors for the content and tail components.
|
|
754
|
+
*
|
|
755
|
+
* Note that without explicit positioning, the tail will not be centered.
|
|
756
|
+
*/
|
|
757
|
+
class PopoverDialog extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
758
|
+
componentDidUpdate(prevProps) {
|
|
759
|
+
// if the placement has changed, then we need to notify this to the
|
|
760
|
+
// parent component (`Popover`). This way, the context will update its
|
|
761
|
+
// `placement` value.
|
|
762
|
+
if (prevProps.placement !== this.props.placement) {
|
|
763
|
+
this.props.onUpdate(this.props.placement);
|
|
764
|
+
}
|
|
710
765
|
}
|
|
711
766
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
767
|
+
render() {
|
|
768
|
+
const {
|
|
769
|
+
placement,
|
|
770
|
+
children,
|
|
771
|
+
id,
|
|
772
|
+
isReferenceHidden,
|
|
773
|
+
updateBubbleRef,
|
|
774
|
+
updateTailRef,
|
|
775
|
+
tailOffset,
|
|
776
|
+
style,
|
|
777
|
+
"aria-describedby": ariaDescribedby
|
|
778
|
+
} = this.props;
|
|
779
|
+
const contentProps = children.props; // extract the background color from the popover content
|
|
716
780
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
781
|
+
const color = contentProps.emphasized ? "blue" : contentProps.color;
|
|
782
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
|
|
783
|
+
"aria-describedby": ariaDescribedby,
|
|
784
|
+
id: id,
|
|
785
|
+
role: "dialog",
|
|
786
|
+
ref: updateBubbleRef,
|
|
787
|
+
"data-placement": placement,
|
|
788
|
+
style: [isReferenceHidden && styles.hide, styles[`content-${placement}`], style]
|
|
789
|
+
}, children, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_tooltip__WEBPACK_IMPORTED_MODULE_3__["TooltipTail"], {
|
|
790
|
+
color: color,
|
|
791
|
+
updateRef: updateTailRef,
|
|
792
|
+
placement: placement,
|
|
793
|
+
offset: tailOffset
|
|
794
|
+
})));
|
|
720
795
|
}
|
|
721
796
|
|
|
722
|
-
|
|
723
|
-
|
|
797
|
+
}
|
|
798
|
+
const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
|
|
799
|
+
/**
|
|
800
|
+
* The hide style ensures that the bounds of the popover stay unchanged.
|
|
801
|
+
* This is because popper.js calculates the bubble position based off its
|
|
802
|
+
* bounds and if we stopped rendering it entirely, it wouldn't know where to
|
|
803
|
+
* place it when it reappeared.
|
|
804
|
+
*/
|
|
805
|
+
hide: {
|
|
806
|
+
pointerEvents: "none",
|
|
807
|
+
opacity: 0,
|
|
808
|
+
backgroundColor: "transparent",
|
|
809
|
+
color: "transparent"
|
|
810
|
+
},
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Ensure the content and tail are properly arranged.
|
|
814
|
+
*/
|
|
815
|
+
"content-top": {
|
|
816
|
+
flexDirection: "column"
|
|
817
|
+
},
|
|
818
|
+
"content-right": {
|
|
819
|
+
flexDirection: "row-reverse"
|
|
820
|
+
},
|
|
821
|
+
"content-bottom": {
|
|
822
|
+
flexDirection: "column-reverse"
|
|
823
|
+
},
|
|
824
|
+
"content-left": {
|
|
825
|
+
flexDirection: "row"
|
|
724
826
|
}
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
/***/ }),
|
|
830
|
+
/* 16 */
|
|
831
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
832
|
+
|
|
833
|
+
"use strict";
|
|
834
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return FocusManager; });
|
|
835
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
836
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
837
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
838
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
|
|
839
|
+
/* harmony import */ var _util_util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
|
|
840
|
+
/* harmony import */ var _initial_focus_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(17);
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* This component ensures that focus flows correctly when the popover is open.
|
|
848
|
+
*
|
|
849
|
+
* Inside the popover:
|
|
850
|
+
* - `tab`: Moves focus to the next focusable element.
|
|
851
|
+
* - `shift + tab`: Moves focus to the previous focusable element.
|
|
852
|
+
*
|
|
853
|
+
* After the focus reaches the start/end of the popover, then we handle two
|
|
854
|
+
* different scenarios:
|
|
855
|
+
*
|
|
856
|
+
* 1. If the focus has reached the last focusable element inside the popover,
|
|
857
|
+
* the next tab will set focus on the next focusable element that exists
|
|
858
|
+
* after the PopoverAnchor.
|
|
859
|
+
* 2. If the focus is set to the first focusable element inside the popover, the
|
|
860
|
+
* next shift + tab will set focus on the PopoverAnchor element.
|
|
861
|
+
*
|
|
862
|
+
*/
|
|
863
|
+
class FocusManager extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
864
|
+
constructor(...args) {
|
|
865
|
+
super(...args);
|
|
866
|
+
this.focusableElementsInPopover = [];
|
|
867
|
+
|
|
868
|
+
this.addEventListeners = () => {
|
|
869
|
+
const {
|
|
870
|
+
anchorElement
|
|
871
|
+
} = this.props;
|
|
872
|
+
|
|
873
|
+
if (anchorElement) {
|
|
874
|
+
anchorElement.addEventListener("keydown", this.handleKeydownPreviousFocusableElement, true);
|
|
875
|
+
} // tries to get the next focusable element outside of the popover
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
this.nextElementAfterPopover = this.getNextFocusableElement();
|
|
725
879
|
|
|
726
|
-
|
|
727
|
-
|
|
880
|
+
if (this.nextElementAfterPopover) {
|
|
881
|
+
this.nextElementAfterPopover.addEventListener("keydown", this.handleKeydownNextFocusableElement, true);
|
|
882
|
+
}
|
|
883
|
+
};
|
|
728
884
|
|
|
885
|
+
this.getNextFocusableElement = () => {
|
|
886
|
+
const {
|
|
887
|
+
anchorElement
|
|
888
|
+
} = this.props;
|
|
729
889
|
|
|
890
|
+
if (!anchorElement || this.nextElementAfterPopover) {
|
|
891
|
+
return;
|
|
892
|
+
} // get the total list of focusable elements within the document
|
|
730
893
|
|
|
731
894
|
|
|
895
|
+
const focusableElements = Object(_util_util_js__WEBPACK_IMPORTED_MODULE_2__[/* findFocusableNodes */ "a"])(document); // get anchor element index
|
|
732
896
|
|
|
897
|
+
const anchorIndex = focusableElements.indexOf(anchorElement);
|
|
733
898
|
|
|
899
|
+
if (anchorIndex >= 0) {
|
|
900
|
+
// guess next focusable element index
|
|
901
|
+
const nextElementIndex = anchorIndex < focusableElements.length - 1 ? anchorIndex + 1 : 0; // get next element's DOM reference
|
|
734
902
|
|
|
903
|
+
return focusableElements[nextElementIndex];
|
|
904
|
+
}
|
|
735
905
|
|
|
906
|
+
return;
|
|
907
|
+
};
|
|
736
908
|
|
|
909
|
+
this.getComponentRootNode = node => {
|
|
910
|
+
if (!node) {
|
|
911
|
+
// The component is being umounted
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
737
914
|
|
|
915
|
+
const rootNode = react_dom__WEBPACK_IMPORTED_MODULE_1__["findDOMNode"](node);
|
|
738
916
|
|
|
917
|
+
if (!rootNode) {
|
|
918
|
+
throw new Error("Assertion error: root node should exist after mount");
|
|
919
|
+
}
|
|
739
920
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
* illustrations. The main difference with `Tooltip` is that they must be
|
|
744
|
-
* dismissed by clicking an element.
|
|
745
|
-
*
|
|
746
|
-
* This component uses the `PopoverPopper` component to position the
|
|
747
|
-
* `PopoverContentCore` component according to the children it is wrapping.
|
|
748
|
-
*/
|
|
749
|
-
class popover_Popover extends external_react_["Component"] {
|
|
750
|
-
constructor(...args) {
|
|
751
|
-
super(...args);
|
|
752
|
-
this.state = {
|
|
753
|
-
opened: !!this.props.opened,
|
|
754
|
-
anchorElement: null,
|
|
755
|
-
placement: this.props.placement
|
|
921
|
+
this.rootNode = rootNode; // store the list of possible focusable elements inside the popover
|
|
922
|
+
|
|
923
|
+
this.focusableElementsInPopover = Object(_util_util_js__WEBPACK_IMPORTED_MODULE_2__[/* findFocusableNodes */ "a"])(this.rootNode);
|
|
756
924
|
};
|
|
757
|
-
this.contentRef = /*#__PURE__*/external_react_["createRef"]();
|
|
758
925
|
|
|
759
|
-
this.
|
|
760
|
-
this.
|
|
761
|
-
|
|
762
|
-
}
|
|
763
|
-
this.props.onClose && this.props.onClose();
|
|
764
|
-
});
|
|
926
|
+
this.handleFocusPreviousFocusableElement = () => {
|
|
927
|
+
if (this.props.anchorElement) {
|
|
928
|
+
this.props.anchorElement.focus();
|
|
929
|
+
}
|
|
765
930
|
};
|
|
766
931
|
|
|
767
|
-
this.
|
|
768
|
-
if (this.
|
|
769
|
-
this.
|
|
770
|
-
opened: false
|
|
771
|
-
});
|
|
772
|
-
} else {
|
|
773
|
-
this.setState({
|
|
774
|
-
opened: true
|
|
775
|
-
});
|
|
932
|
+
this.handleFocusNextFocusableElement = () => {
|
|
933
|
+
if (this.nextElementAfterPopover) {
|
|
934
|
+
this.nextElementAfterPopover.focus();
|
|
776
935
|
}
|
|
777
936
|
};
|
|
778
937
|
|
|
779
|
-
this.
|
|
780
|
-
|
|
938
|
+
this.handleKeydownPreviousFocusableElement = e => {
|
|
939
|
+
// It will try focus only if the user is pressing `tab`
|
|
940
|
+
if (e.key === "Tab" && !e.shiftKey) {
|
|
941
|
+
e.preventDefault();
|
|
942
|
+
this.focusableElementsInPopover[0].focus();
|
|
943
|
+
}
|
|
944
|
+
};
|
|
781
945
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
946
|
+
this.handleKeydownNextFocusableElement = e => {
|
|
947
|
+
// It will try focus only if the user is pressing `Shift+tab`
|
|
948
|
+
if (e.key === "Tab" && e.shiftKey) {
|
|
949
|
+
e.preventDefault();
|
|
950
|
+
const lastElementIndex = this.focusableElementsInPopover.length - 1;
|
|
951
|
+
this.focusableElementsInPopover[lastElementIndex].focus();
|
|
786
952
|
}
|
|
787
953
|
};
|
|
788
954
|
}
|
|
789
955
|
|
|
790
956
|
/**
|
|
791
|
-
*
|
|
792
|
-
* component
|
|
957
|
+
* The focusable element that is positioned after the trigger element
|
|
793
958
|
*/
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Tabbing is restricted to descendents of this element.
|
|
962
|
+
*/
|
|
963
|
+
componentDidMount() {
|
|
964
|
+
this.addEventListeners();
|
|
798
965
|
}
|
|
799
966
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
content
|
|
803
|
-
} = this.props;
|
|
804
|
-
return /*#__PURE__*/external_react_["cloneElement"](typeof content === "function" ? content({
|
|
805
|
-
close: this.handleClose
|
|
806
|
-
}) : content, {
|
|
807
|
-
ref: this.contentRef
|
|
808
|
-
});
|
|
967
|
+
componentDidUpdate() {
|
|
968
|
+
this.addEventListeners();
|
|
809
969
|
}
|
|
970
|
+
/**
|
|
971
|
+
* Remove keydown listeners
|
|
972
|
+
*/
|
|
810
973
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
initialFocusId,
|
|
814
|
-
placement
|
|
815
|
-
} = this.props;
|
|
974
|
+
|
|
975
|
+
componentWillUnmount() {
|
|
816
976
|
const {
|
|
817
977
|
anchorElement
|
|
818
|
-
} = this.
|
|
819
|
-
return /*#__PURE__*/external_react_["createElement"](focus_manager_FocusManager, {
|
|
820
|
-
anchorElement: anchorElement,
|
|
821
|
-
initialFocusId: initialFocusId
|
|
822
|
-
}, /*#__PURE__*/external_react_["createElement"](wonder_blocks_tooltip_["TooltipPopper"], {
|
|
823
|
-
anchorElement: anchorElement,
|
|
824
|
-
placement: placement
|
|
825
|
-
}, props => /*#__PURE__*/external_react_["createElement"](popover_dialog_PopoverDialog, extends_default()({}, props, {
|
|
826
|
-
"aria-describedby": `${uniqueId}-anchor`,
|
|
827
|
-
id: uniqueId,
|
|
828
|
-
onUpdate: placement => this.setState({
|
|
829
|
-
placement
|
|
830
|
-
})
|
|
831
|
-
}), this.renderContent())));
|
|
832
|
-
}
|
|
978
|
+
} = this.props;
|
|
833
979
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
980
|
+
if (anchorElement) {
|
|
981
|
+
// wait for styles to applied, then return the focus to the anchor
|
|
982
|
+
setTimeout(() => anchorElement.focus(), 0);
|
|
983
|
+
anchorElement.removeEventListener("keydown", this.handleKeydownPreviousFocusableElement, true);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (this.nextElementAfterPopover) {
|
|
987
|
+
this.nextElementAfterPopover.removeEventListener("keydown", this.handleKeydownNextFocusableElement, true);
|
|
988
|
+
}
|
|
840
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* List of focusable elements within the popover content
|
|
992
|
+
*/
|
|
993
|
+
|
|
841
994
|
|
|
842
995
|
render() {
|
|
843
996
|
const {
|
|
844
|
-
children
|
|
845
|
-
dismissEnabled,
|
|
846
|
-
id
|
|
997
|
+
children
|
|
847
998
|
} = this.props;
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
999
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](react__WEBPACK_IMPORTED_MODULE_0__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("div", {
|
|
1000
|
+
tabIndex: "0",
|
|
1001
|
+
onFocus: this.handleFocusPreviousFocusableElement,
|
|
1002
|
+
style: {
|
|
1003
|
+
position: "fixed"
|
|
1004
|
+
}
|
|
1005
|
+
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("div", {
|
|
1006
|
+
ref: this.getComponentRootNode
|
|
1007
|
+
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_initial_focus_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"], {
|
|
1008
|
+
initialFocusId: this.props.initialFocusId
|
|
1009
|
+
}, children)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"]("div", {
|
|
1010
|
+
tabIndex: "0",
|
|
1011
|
+
onFocus: this.handleFocusNextFocusableElement,
|
|
1012
|
+
style: {
|
|
1013
|
+
position: "fixed"
|
|
857
1014
|
}
|
|
858
|
-
}, /*#__PURE__*/external_react_["createElement"](wonder_blocks_core_["IDProvider"], {
|
|
859
|
-
id: id,
|
|
860
|
-
scope: "popover"
|
|
861
|
-
}, uniqueId => /*#__PURE__*/external_react_["createElement"](external_react_["Fragment"], null, /*#__PURE__*/external_react_["createElement"](popover_anchor_PopoverAnchor, {
|
|
862
|
-
anchorRef: this.updateRef,
|
|
863
|
-
id: `${uniqueId}-anchor`,
|
|
864
|
-
"aria-controls": uniqueId,
|
|
865
|
-
"aria-expanded": opened ? "true" : "false",
|
|
866
|
-
onClick: this.handleOpen
|
|
867
|
-
}, children), popperHost && opened && /*#__PURE__*/external_react_dom_default.a.createPortal(this.renderPopper(uniqueId), popperHost))), dismissEnabled && opened && /*#__PURE__*/external_react_["createElement"](popover_event_listener_PopoverEventListener, {
|
|
868
|
-
onClose: this.handleClose,
|
|
869
|
-
contentRef: this.contentRef
|
|
870
1015
|
}));
|
|
871
1016
|
}
|
|
872
1017
|
|
|
873
1018
|
}
|
|
874
|
-
popover_Popover.defaultProps = {
|
|
875
|
-
placement: "top"
|
|
876
|
-
};
|
|
877
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-spacing"
|
|
878
|
-
var wonder_blocks_spacing_ = __webpack_require__(1);
|
|
879
|
-
var wonder_blocks_spacing_default = /*#__PURE__*/__webpack_require__.n(wonder_blocks_spacing_);
|
|
880
|
-
|
|
881
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-typography"
|
|
882
|
-
var wonder_blocks_typography_ = __webpack_require__(8);
|
|
883
1019
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
// EXTERNAL MODULE: external "@khanacademy/wonder-blocks-icon-button"
|
|
888
|
-
var wonder_blocks_icon_button_ = __webpack_require__(11);
|
|
889
|
-
var wonder_blocks_icon_button_default = /*#__PURE__*/__webpack_require__.n(wonder_blocks_icon_button_);
|
|
890
|
-
|
|
891
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/close-button.js
|
|
1020
|
+
/***/ }),
|
|
1021
|
+
/* 17 */
|
|
1022
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
892
1023
|
|
|
1024
|
+
"use strict";
|
|
1025
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InitialFocus; });
|
|
1026
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
1027
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
1028
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
1029
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
|
|
1030
|
+
/* harmony import */ var _util_util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
|
|
893
1031
|
|
|
894
1032
|
|
|
895
1033
|
|
|
896
1034
|
|
|
897
1035
|
/**
|
|
898
|
-
* This
|
|
899
|
-
*
|
|
900
|
-
* true.
|
|
1036
|
+
* This component finds which element (from within the children) needs to
|
|
1037
|
+
* receive focus. After that, the children is rendered with the focus assigned.
|
|
901
1038
|
*/
|
|
902
|
-
class
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
light,
|
|
906
|
-
"aria-label": ariaLabel,
|
|
907
|
-
style,
|
|
908
|
-
testId
|
|
909
|
-
} = this.props;
|
|
910
|
-
return /*#__PURE__*/external_react_["createElement"](popover_context.Consumer, null, ({
|
|
911
|
-
close
|
|
912
|
-
}) => {
|
|
913
|
-
return /*#__PURE__*/external_react_["createElement"](wonder_blocks_icon_button_default.a, {
|
|
914
|
-
icon: wonder_blocks_icon_["icons"].dismiss,
|
|
915
|
-
"aria-label": ariaLabel,
|
|
916
|
-
onClick: close,
|
|
917
|
-
kind: light ? "primary" : "tertiary",
|
|
918
|
-
light: light,
|
|
919
|
-
style: style,
|
|
920
|
-
testId: testId
|
|
921
|
-
});
|
|
922
|
-
});
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
}
|
|
926
|
-
close_button_CloseButton.defaultProps = {
|
|
927
|
-
light: true,
|
|
928
|
-
"aria-label": "Close Popover"
|
|
929
|
-
};
|
|
930
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-content-core.js
|
|
931
|
-
|
|
1039
|
+
class InitialFocus extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
1040
|
+
constructor(...args) {
|
|
1041
|
+
super(...args);
|
|
932
1042
|
|
|
1043
|
+
this.setInitialFocusableElement = node => {
|
|
1044
|
+
// 1. try to get element specified by the user
|
|
1045
|
+
// 2. get first occurence from list of focusable elements
|
|
1046
|
+
// 3. If no focusable elements are found, get the container itself
|
|
1047
|
+
const firstFocusableElement = this.maybeGetInitialFocusElement(node) || this.maybeGetFirstFocusableElement(node) || node;
|
|
933
1048
|
|
|
1049
|
+
if (firstFocusableElement === node) {
|
|
1050
|
+
// add tabIndex to make the container focusable
|
|
1051
|
+
node.tabIndex = -1;
|
|
1052
|
+
} // using timeout to prevent page jumps when focusing on this element
|
|
934
1053
|
|
|
935
1054
|
|
|
1055
|
+
setTimeout(() => {
|
|
1056
|
+
firstFocusableElement.focus();
|
|
1057
|
+
}, 0);
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
936
1060
|
|
|
1061
|
+
componentDidMount() {
|
|
1062
|
+
const node = react_dom__WEBPACK_IMPORTED_MODULE_1__["findDOMNode"](this);
|
|
937
1063
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
const {
|
|
945
|
-
children,
|
|
946
|
-
closeButtonLight,
|
|
947
|
-
closeButtonLabel,
|
|
948
|
-
closeButtonVisible,
|
|
949
|
-
color,
|
|
950
|
-
style,
|
|
951
|
-
testId
|
|
952
|
-
} = this.props;
|
|
953
|
-
return /*#__PURE__*/external_react_["createElement"](wonder_blocks_core_["View"], {
|
|
954
|
-
"data-test-id": testId,
|
|
955
|
-
style: [popover_content_core_styles.content, color !== "white" && popover_content_core_styles[color], style]
|
|
956
|
-
}, closeButtonVisible && /*#__PURE__*/external_react_["createElement"](close_button_CloseButton, {
|
|
957
|
-
"aria-label": closeButtonLabel,
|
|
958
|
-
light: closeButtonLight || color !== "white",
|
|
959
|
-
style: popover_content_core_styles.closeButton,
|
|
960
|
-
testId: `${testId || "popover"}-close-btn`
|
|
961
|
-
}), children);
|
|
1064
|
+
if (!node) {
|
|
1065
|
+
return;
|
|
1066
|
+
} // try to focus on the first focussable element
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
this.setInitialFocusableElement(node);
|
|
962
1070
|
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Gets the focusable element and applies focus to it
|
|
1073
|
+
*/
|
|
963
1074
|
|
|
964
|
-
}
|
|
965
|
-
popover_content_core_PopoverContentCore.defaultProps = {
|
|
966
|
-
color: "white",
|
|
967
|
-
closeButtonLight: false,
|
|
968
|
-
closeButtonVisible: false
|
|
969
|
-
};
|
|
970
|
-
const popover_content_core_styles = external_aphrodite_["StyleSheet"].create({
|
|
971
|
-
content: {
|
|
972
|
-
borderRadius: wonder_blocks_spacing_default.a.xxxSmall_4,
|
|
973
|
-
border: `solid 1px ${wonder_blocks_color_default.a.offBlack16}`,
|
|
974
|
-
backgroundColor: wonder_blocks_color_default.a.white,
|
|
975
|
-
boxShadow: `0 ${wonder_blocks_spacing_default.a.xSmall_8}px ${wonder_blocks_spacing_default.a.xSmall_8}px 0 ${wonder_blocks_color_default.a.offBlack8}`,
|
|
976
|
-
margin: 0,
|
|
977
|
-
maxWidth: wonder_blocks_spacing_default.a.medium_16 * 18,
|
|
978
|
-
// 288px
|
|
979
|
-
padding: wonder_blocks_spacing_default.a.large_24,
|
|
980
|
-
overflow: "hidden",
|
|
981
|
-
justifyContent: "center"
|
|
982
|
-
},
|
|
983
1075
|
|
|
984
1076
|
/**
|
|
985
|
-
*
|
|
1077
|
+
* Returns an element specified by the user
|
|
986
1078
|
*/
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1079
|
+
maybeGetInitialFocusElement(node) {
|
|
1080
|
+
const {
|
|
1081
|
+
initialFocusId
|
|
1082
|
+
} = this.props;
|
|
1083
|
+
|
|
1084
|
+
if (!initialFocusId) {
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
995
1087
|
|
|
1088
|
+
return node.querySelector(`#${initialFocusId}`);
|
|
1089
|
+
}
|
|
996
1090
|
/**
|
|
997
|
-
*
|
|
1091
|
+
* Returns the first focusable element found inside the children
|
|
998
1092
|
*/
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
maybeGetFirstFocusableElement(node) {
|
|
1096
|
+
// get a collection of elements that can be focused
|
|
1097
|
+
const focusableElements = Object(_util_util_js__WEBPACK_IMPORTED_MODULE_2__[/* findFocusableNodes */ "a"])(node);
|
|
1098
|
+
|
|
1099
|
+
if (!focusableElements.length) {
|
|
1100
|
+
return null;
|
|
1101
|
+
} // if found, return the first focusable element
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
return focusableElements[0];
|
|
1005
1105
|
}
|
|
1006
|
-
});
|
|
1007
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/components/popover-content.js
|
|
1008
1106
|
|
|
1107
|
+
render() {
|
|
1108
|
+
return this.props.children;
|
|
1109
|
+
}
|
|
1009
1110
|
|
|
1111
|
+
}
|
|
1010
1112
|
|
|
1113
|
+
/***/ }),
|
|
1114
|
+
/* 18 */
|
|
1115
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1011
1116
|
|
|
1117
|
+
"use strict";
|
|
1118
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return PopoverEventListener; });
|
|
1119
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
1120
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
1121
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
1122
|
+
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
|
|
1012
1123
|
|
|
1013
1124
|
|
|
1014
1125
|
|
|
1015
|
-
// Created to add custom styles to the icon or image elements
|
|
1016
|
-
const StyledImage = Object(wonder_blocks_core_["addStyle"])("img");
|
|
1017
1126
|
/**
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1127
|
+
* A component that, when mounted, calls `onClose` when certain events occur.
|
|
1128
|
+
* This includes when pressing Escape or clicking outside the Popover.
|
|
1129
|
+
* @see @khanacademy/wonder-blocks-modal/components/modal-launcher.js
|
|
1020
1130
|
*/
|
|
1021
|
-
|
|
1022
|
-
class popover_content_PopoverContent extends external_react_["Component"] {
|
|
1131
|
+
class PopoverEventListener extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
1023
1132
|
constructor(...args) {
|
|
1024
1133
|
super(...args);
|
|
1134
|
+
this.state = {
|
|
1135
|
+
isFirstClick: true
|
|
1136
|
+
};
|
|
1025
1137
|
|
|
1026
|
-
this.
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1138
|
+
this._handleKeyup = e => {
|
|
1139
|
+
// We check the key as that's keyboard layout agnostic and also avoids
|
|
1140
|
+
// the minefield of deprecated number type properties like keyCode and
|
|
1141
|
+
// which, with the replacement code, which uses a string instead.
|
|
1142
|
+
if (e.key === "Escape") {
|
|
1143
|
+
// Stop the event going any further.
|
|
1144
|
+
// For cancellation events, like the Escape key, we generally should
|
|
1145
|
+
// air on the side of caution and only allow it to cancel one thing.
|
|
1146
|
+
// So, it's polite for us to stop propagation of the event.
|
|
1147
|
+
// Otherwise, we end up with UX where one Escape key press
|
|
1148
|
+
// unexpectedly cancels multiple things.
|
|
1149
|
+
e.preventDefault();
|
|
1150
|
+
e.stopPropagation();
|
|
1151
|
+
this.props.onClose();
|
|
1035
1152
|
}
|
|
1036
|
-
|
|
1037
|
-
return /*#__PURE__*/external_react_["createElement"](wonder_blocks_core_["View"], {
|
|
1038
|
-
style: [popover_content_styles.image, placement === "bottom" && popover_content_styles.imageToBottom]
|
|
1039
|
-
}, image);
|
|
1040
1153
|
};
|
|
1041
1154
|
|
|
1042
|
-
this.
|
|
1043
|
-
|
|
1044
|
-
icon
|
|
1045
|
-
} = this.props;
|
|
1155
|
+
this._handleClick = e => {
|
|
1156
|
+
var _this$props$contentRe;
|
|
1046
1157
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1158
|
+
// Prevents the problem where clicking the trigger button
|
|
1159
|
+
// triggers a click event and immediately closes the popover.
|
|
1160
|
+
if (this.state.isFirstClick) {
|
|
1161
|
+
this.setState({
|
|
1162
|
+
isFirstClick: false
|
|
1163
|
+
});
|
|
1164
|
+
return;
|
|
1049
1165
|
}
|
|
1050
1166
|
|
|
1051
|
-
|
|
1052
|
-
style: popover_content_styles.iconContainer
|
|
1053
|
-
}, typeof icon !== "string" ? icon : /*#__PURE__*/external_react_["createElement"](StyledImage, {
|
|
1054
|
-
src: icon,
|
|
1055
|
-
style: popover_content_styles.icon
|
|
1056
|
-
}));
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
|
-
this.maybeRenderActions = close => {
|
|
1060
|
-
const {
|
|
1061
|
-
actions
|
|
1062
|
-
} = this.props;
|
|
1167
|
+
const node = react_dom__WEBPACK_IMPORTED_MODULE_1___default.a.findDOMNode((_this$props$contentRe = this.props.contentRef) == null ? void 0 : _this$props$contentRe.current);
|
|
1063
1168
|
|
|
1064
|
-
if (!
|
|
1065
|
-
|
|
1169
|
+
if (node && !node.contains(e.target)) {
|
|
1170
|
+
// Stop the event going any further.
|
|
1171
|
+
// Only allow click to cancel one thing at a time.
|
|
1172
|
+
e.preventDefault();
|
|
1173
|
+
e.stopPropagation();
|
|
1174
|
+
this.props.onClose();
|
|
1066
1175
|
}
|
|
1067
|
-
|
|
1068
|
-
return /*#__PURE__*/external_react_["createElement"](wonder_blocks_core_["View"], {
|
|
1069
|
-
style: popover_content_styles.actions
|
|
1070
|
-
}, typeof actions === "function" ? actions({
|
|
1071
|
-
close: close
|
|
1072
|
-
}) : actions);
|
|
1073
1176
|
};
|
|
1074
1177
|
}
|
|
1075
1178
|
|
|
1076
1179
|
componentDidMount() {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
image
|
|
1080
|
-
} = this.props; // this runtime check is added to support <svg> and <img> elements
|
|
1081
|
-
// inside the image prop
|
|
1082
|
-
|
|
1083
|
-
if (image && icon) {
|
|
1084
|
-
throw new Error("'image' and 'icon' cannot be used at the same time. You can fix this by either removing 'image' or 'icon' from your instance.");
|
|
1085
|
-
}
|
|
1180
|
+
window.addEventListener("keyup", this._handleKeyup);
|
|
1181
|
+
window.addEventListener("click", this._handleClick);
|
|
1086
1182
|
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Runtime validation in case we try to use an invalid shape
|
|
1089
|
-
*/
|
|
1090
1183
|
|
|
1184
|
+
componentWillUnmount() {
|
|
1185
|
+
window.removeEventListener("keyup", this._handleKeyup);
|
|
1186
|
+
window.removeEventListener("click", this._handleClick);
|
|
1187
|
+
}
|
|
1091
1188
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
}) {
|
|
1095
|
-
// illustration popover can't be placed horizontally
|
|
1096
|
-
if (this.props.image && (placement === "left" || placement === "right")) {
|
|
1097
|
-
throw new Error("'image' can only be vertically placed. You can fix this by either changing `placement` to `top` or `bottom` or removing the `image` prop inside `content`.");
|
|
1098
|
-
}
|
|
1189
|
+
render() {
|
|
1190
|
+
return null;
|
|
1099
1191
|
}
|
|
1100
1192
|
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
/***/ }),
|
|
1196
|
+
/* 19 */
|
|
1197
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1198
|
+
|
|
1199
|
+
"use strict";
|
|
1200
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return CloseButton; });
|
|
1201
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
1202
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
1203
|
+
/* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20);
|
|
1204
|
+
/* harmony import */ var _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_1__);
|
|
1205
|
+
/* harmony import */ var _khanacademy_wonder_blocks_icon_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21);
|
|
1206
|
+
/* harmony import */ var _khanacademy_wonder_blocks_icon_button__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_icon_button__WEBPACK_IMPORTED_MODULE_2__);
|
|
1207
|
+
/* harmony import */ var _popover_context_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* This is the visual component rendering the close button that is rendered
|
|
1215
|
+
* inside the PopoverContentCore. It’s rendered if closeButtonVisible is set
|
|
1216
|
+
* true.
|
|
1217
|
+
*/
|
|
1218
|
+
class CloseButton extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
1101
1219
|
render() {
|
|
1102
1220
|
const {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
content,
|
|
1106
|
-
emphasized = undefined,
|
|
1107
|
-
icon,
|
|
1108
|
-
image,
|
|
1221
|
+
light,
|
|
1222
|
+
"aria-label": ariaLabel,
|
|
1109
1223
|
style,
|
|
1110
|
-
title,
|
|
1111
1224
|
testId
|
|
1112
1225
|
} = this.props;
|
|
1113
|
-
return /*#__PURE__*/
|
|
1114
|
-
close
|
|
1115
|
-
placement
|
|
1226
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_popover_context_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].Consumer, null, ({
|
|
1227
|
+
close
|
|
1116
1228
|
}) => {
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
color: emphasized ? "blue" : "white",
|
|
1124
|
-
closeButtonLight: image && placement === "top",
|
|
1125
|
-
closeButtonLabel: closeButtonLabel,
|
|
1126
|
-
closeButtonVisible: closeButtonVisible,
|
|
1229
|
+
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_icon_button__WEBPACK_IMPORTED_MODULE_2___default.a, {
|
|
1230
|
+
icon: _khanacademy_wonder_blocks_icon__WEBPACK_IMPORTED_MODULE_1__["icons"].dismiss,
|
|
1231
|
+
"aria-label": ariaLabel,
|
|
1232
|
+
onClick: close,
|
|
1233
|
+
kind: light ? "primary" : "tertiary",
|
|
1234
|
+
light: light,
|
|
1127
1235
|
style: style,
|
|
1128
1236
|
testId: testId
|
|
1129
|
-
}
|
|
1130
|
-
style: !!icon && popover_content_styles.withIcon
|
|
1131
|
-
}, this.maybeRenderImage({
|
|
1132
|
-
placement
|
|
1133
|
-
}), this.maybeRenderIcon(), /*#__PURE__*/external_react_["createElement"](wonder_blocks_core_["View"], {
|
|
1134
|
-
style: popover_content_styles.text
|
|
1135
|
-
}, /*#__PURE__*/external_react_["createElement"](wonder_blocks_typography_["HeadingSmall"], {
|
|
1136
|
-
style: popover_content_styles.title
|
|
1137
|
-
}, title), /*#__PURE__*/external_react_["createElement"](wonder_blocks_typography_["Body"], null, content))), this.maybeRenderActions(close));
|
|
1237
|
+
});
|
|
1138
1238
|
});
|
|
1139
1239
|
}
|
|
1140
1240
|
|
|
1141
1241
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1242
|
+
CloseButton.defaultProps = {
|
|
1243
|
+
light: true,
|
|
1244
|
+
"aria-label": "Close Popover"
|
|
1144
1245
|
};
|
|
1145
|
-
const popover_content_styles = external_aphrodite_["StyleSheet"].create({
|
|
1146
|
-
/**
|
|
1147
|
-
* Shared styles
|
|
1148
|
-
*/
|
|
1149
|
-
actions: {
|
|
1150
|
-
marginTop: wonder_blocks_spacing_default.a.large_24,
|
|
1151
|
-
flexDirection: "row",
|
|
1152
|
-
alignItems: "center",
|
|
1153
|
-
justifyContent: "flex-end"
|
|
1154
|
-
},
|
|
1155
|
-
text: {
|
|
1156
|
-
justifyContent: "center"
|
|
1157
|
-
},
|
|
1158
|
-
title: {
|
|
1159
|
-
marginBottom: wonder_blocks_spacing_default.a.xSmall_8
|
|
1160
|
-
},
|
|
1161
1246
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1247
|
+
/***/ }),
|
|
1248
|
+
/* 20 */
|
|
1249
|
+
/***/ (function(module, exports) {
|
|
1250
|
+
|
|
1251
|
+
module.exports = require("@khanacademy/wonder-blocks-icon");
|
|
1252
|
+
|
|
1253
|
+
/***/ }),
|
|
1254
|
+
/* 21 */
|
|
1255
|
+
/***/ (function(module, exports) {
|
|
1256
|
+
|
|
1257
|
+
module.exports = require("@khanacademy/wonder-blocks-icon-button");
|
|
1258
|
+
|
|
1259
|
+
/***/ }),
|
|
1260
|
+
/* 22 */
|
|
1261
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1262
|
+
|
|
1263
|
+
"use strict";
|
|
1264
|
+
__webpack_require__.r(__webpack_exports__);
|
|
1265
|
+
/* harmony import */ var _components_popover_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11);
|
|
1266
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Popover", function() { return _components_popover_js__WEBPACK_IMPORTED_MODULE_0__["a"]; });
|
|
1267
|
+
|
|
1268
|
+
/* harmony import */ var _components_popover_content_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12);
|
|
1269
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "PopoverContent", function() { return _components_popover_content_js__WEBPACK_IMPORTED_MODULE_1__["a"]; });
|
|
1270
|
+
|
|
1271
|
+
/* harmony import */ var _components_popover_content_core_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
|
|
1272
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "PopoverContentCore", function() { return _components_popover_content_core_js__WEBPACK_IMPORTED_MODULE_2__["a"]; });
|
|
1180
1273
|
|
|
1181
|
-
/**
|
|
1182
|
-
* Illustration styles
|
|
1183
|
-
*/
|
|
1184
|
-
image: {
|
|
1185
|
-
marginBottom: wonder_blocks_spacing_default.a.large_24,
|
|
1186
|
-
marginLeft: -wonder_blocks_spacing_default.a.large_24,
|
|
1187
|
-
marginRight: -wonder_blocks_spacing_default.a.large_24,
|
|
1188
|
-
marginTop: -wonder_blocks_spacing_default.a.large_24,
|
|
1189
|
-
width: `calc(100% + ${wonder_blocks_spacing_default.a.large_24 * 2}px)`
|
|
1190
|
-
},
|
|
1191
|
-
imageToBottom: {
|
|
1192
|
-
marginBottom: -wonder_blocks_spacing_default.a.large_24,
|
|
1193
|
-
marginTop: wonder_blocks_spacing_default.a.large_24,
|
|
1194
|
-
order: 1
|
|
1195
|
-
}
|
|
1196
|
-
});
|
|
1197
|
-
// CONCATENATED MODULE: ./packages/wonder-blocks-popover/src/index.js
|
|
1198
1274
|
|
|
1199
1275
|
|
|
1200
1276
|
|