@instructure/ui-drilldown 8.21.1-snapshot.10

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE.md +27 -0
  3. package/README.md +30 -0
  4. package/es/Drilldown/DrilldownGroup/index.js +56 -0
  5. package/es/Drilldown/DrilldownGroup/props.js +42 -0
  6. package/es/Drilldown/DrilldownLocator.js +144 -0
  7. package/es/Drilldown/DrilldownOption/index.js +59 -0
  8. package/es/Drilldown/DrilldownOption/props.js +46 -0
  9. package/es/Drilldown/DrilldownPage/index.js +56 -0
  10. package/es/Drilldown/DrilldownPage/props.js +41 -0
  11. package/es/Drilldown/DrilldownSeparator/index.js +52 -0
  12. package/es/Drilldown/DrilldownSeparator/props.js +30 -0
  13. package/es/Drilldown/__examples__/Drilldown.examples.js +299 -0
  14. package/es/Drilldown/index.js +1241 -0
  15. package/es/Drilldown/locator.js +26 -0
  16. package/es/Drilldown/props.js +67 -0
  17. package/es/Drilldown/styles.js +82 -0
  18. package/es/Drilldown/theme.js +43 -0
  19. package/es/index.js +24 -0
  20. package/lib/Drilldown/DrilldownGroup/index.js +42 -0
  21. package/lib/Drilldown/DrilldownGroup/props.js +56 -0
  22. package/lib/Drilldown/DrilldownLocator.js +157 -0
  23. package/lib/Drilldown/DrilldownOption/index.js +45 -0
  24. package/lib/Drilldown/DrilldownOption/props.js +57 -0
  25. package/lib/Drilldown/DrilldownPage/index.js +66 -0
  26. package/lib/Drilldown/DrilldownPage/props.js +56 -0
  27. package/lib/Drilldown/DrilldownSeparator/index.js +38 -0
  28. package/lib/Drilldown/DrilldownSeparator/props.js +41 -0
  29. package/lib/Drilldown/__examples__/Drilldown.examples.js +289 -0
  30. package/lib/Drilldown/index.js +1253 -0
  31. package/lib/Drilldown/locator.js +40 -0
  32. package/lib/Drilldown/props.js +83 -0
  33. package/lib/Drilldown/styles.js +90 -0
  34. package/lib/Drilldown/theme.js +51 -0
  35. package/lib/index.js +13 -0
  36. package/lib/package.json +1 -0
  37. package/package.json +58 -0
  38. package/src/Drilldown/DrilldownGroup/index.tsx +64 -0
  39. package/src/Drilldown/DrilldownGroup/props.ts +149 -0
  40. package/src/Drilldown/DrilldownLocator.ts +101 -0
  41. package/src/Drilldown/DrilldownOption/index.tsx +68 -0
  42. package/src/Drilldown/DrilldownOption/props.ts +224 -0
  43. package/src/Drilldown/DrilldownPage/index.tsx +58 -0
  44. package/src/Drilldown/DrilldownPage/props.ts +129 -0
  45. package/src/Drilldown/DrilldownSeparator/index.tsx +60 -0
  46. package/src/Drilldown/DrilldownSeparator/props.ts +65 -0
  47. package/src/Drilldown/README.md +1515 -0
  48. package/src/Drilldown/__examples__/Drilldown.examples.tsx +318 -0
  49. package/src/Drilldown/index.tsx +1492 -0
  50. package/src/Drilldown/locator.ts +28 -0
  51. package/src/Drilldown/props.ts +378 -0
  52. package/src/Drilldown/styles.ts +95 -0
  53. package/src/Drilldown/theme.ts +47 -0
  54. package/src/index.ts +26 -0
  55. package/tsconfig.build.json +30 -0
  56. package/tsconfig.build.tsbuildinfo +1 -0
  57. package/tsconfig.json +4 -0
  58. package/types/Drilldown/DrilldownGroup/index.d.ts +59 -0
  59. package/types/Drilldown/DrilldownGroup/index.d.ts.map +1 -0
  60. package/types/Drilldown/DrilldownGroup/props.d.ts +65 -0
  61. package/types/Drilldown/DrilldownGroup/props.d.ts.map +1 -0
  62. package/types/Drilldown/DrilldownLocator.d.ts +652 -0
  63. package/types/Drilldown/DrilldownLocator.d.ts.map +1 -0
  64. package/types/Drilldown/DrilldownOption/index.d.ts +134 -0
  65. package/types/Drilldown/DrilldownOption/index.d.ts.map +1 -0
  66. package/types/Drilldown/DrilldownOption/props.d.ts +116 -0
  67. package/types/Drilldown/DrilldownOption/props.d.ts.map +1 -0
  68. package/types/Drilldown/DrilldownPage/index.d.ts +45 -0
  69. package/types/Drilldown/DrilldownPage/index.d.ts.map +1 -0
  70. package/types/Drilldown/DrilldownPage/props.d.ts +51 -0
  71. package/types/Drilldown/DrilldownPage/props.d.ts.map +1 -0
  72. package/types/Drilldown/DrilldownSeparator/index.d.ts +27 -0
  73. package/types/Drilldown/DrilldownSeparator/index.d.ts.map +1 -0
  74. package/types/Drilldown/DrilldownSeparator/props.d.ts +18 -0
  75. package/types/Drilldown/DrilldownSeparator/props.d.ts.map +1 -0
  76. package/types/Drilldown/__examples__/Drilldown.examples.d.ts +5 -0
  77. package/types/Drilldown/__examples__/Drilldown.examples.d.ts.map +1 -0
  78. package/types/Drilldown/index.d.ts +246 -0
  79. package/types/Drilldown/index.d.ts.map +1 -0
  80. package/types/Drilldown/locator.d.ts +4 -0
  81. package/types/Drilldown/locator.d.ts.map +1 -0
  82. package/types/Drilldown/props.d.ts +189 -0
  83. package/types/Drilldown/props.d.ts.map +1 -0
  84. package/types/Drilldown/styles.d.ts +15 -0
  85. package/types/Drilldown/styles.d.ts.map +1 -0
  86. package/types/Drilldown/theme.d.ts +10 -0
  87. package/types/Drilldown/theme.d.ts.map +1 -0
  88. package/types/index.d.ts +3 -0
  89. package/types/index.d.ts.map +1 -0
@@ -0,0 +1,1253 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.default = exports.Drilldown = void 0;
11
+
12
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
+
14
+ var _react = _interopRequireWildcard(require("react"));
15
+
16
+ var _console = require("@instructure/console");
17
+
18
+ var _testable = require("@instructure/ui-testable/lib/testable.js");
19
+
20
+ var _contains = require("@instructure/ui-dom-utils/lib/contains.js");
21
+
22
+ var _containsActiveElement = require("@instructure/ui-dom-utils/lib/containsActiveElement.js");
23
+
24
+ var _callRenderProp = require("@instructure/ui-react-utils/lib/callRenderProp.js");
25
+
26
+ var _matchComponentTypes = require("@instructure/ui-react-utils/lib/matchComponentTypes.js");
27
+
28
+ var _omitProps = require("@instructure/ui-react-utils/lib/omitProps.js");
29
+
30
+ var _safeCloneElement = require("@instructure/ui-react-utils/lib/safeCloneElement.js");
31
+
32
+ var _withDeterministicId = require("@instructure/ui-react-utils/lib/DeterministicIdContext/withDeterministicId.js");
33
+
34
+ var _View = require("@instructure/ui-view/lib/View");
35
+
36
+ var _Options = require("@instructure/ui-options/lib/Options");
37
+
38
+ var _Popover = require("@instructure/ui-popover/lib/Popover");
39
+
40
+ var _Selectable = require("@instructure/ui-selectable/lib/Selectable");
41
+
42
+ var _IconArrowOpenStartSolid = require("@instructure/ui-icons/lib/IconArrowOpenStartSolid.js");
43
+
44
+ var _IconArrowOpenEndSolid = require("@instructure/ui-icons/lib/IconArrowOpenEndSolid.js");
45
+
46
+ var _IconCheckSolid = require("@instructure/ui-icons/lib/IconCheckSolid.js");
47
+
48
+ var _emotion = require("@instructure/emotion");
49
+
50
+ var _DrilldownSeparator = require("./DrilldownSeparator");
51
+
52
+ var _DrilldownOption = require("./DrilldownOption");
53
+
54
+ var _DrilldownGroup = require("./DrilldownGroup");
55
+
56
+ var _DrilldownPage = require("./DrilldownPage");
57
+
58
+ var _styles = _interopRequireDefault(require("./styles"));
59
+
60
+ var _theme = _interopRequireDefault(require("./theme"));
61
+
62
+ var _props = require("./props");
63
+
64
+ const _excluded = ["groupProps"],
65
+ _excluded2 = ["groupProps"],
66
+ _excluded3 = ["id", "themeOverride"];
67
+
68
+ var _dec, _dec2, _dec3, _class, _class2, _temp, _IconArrowOpenEndSoli, _IconArrowOpenStartSo, _Options$Separator, _Options$Separator2;
69
+
70
+ /**
71
+ ---
72
+ category: components
73
+ experimental: true
74
+ ---
75
+ @tsProps
76
+ **/
77
+ let Drilldown = (_dec = (0, _withDeterministicId.withDeterministicId)(), _dec2 = (0, _emotion.withStyle)(_styles.default, _theme.default), _dec3 = (0, _testable.testable)(), _dec(_class = _dec2(_class = _dec3(_class = (_temp = _class2 = class Drilldown extends _react.Component {
78
+ // Array of visited page ids in "breadcrumbs" fashion
79
+ // Map of the active options on the page (includes header options too)
80
+ // Map of the selected options in groups (grouped by group id)
81
+ constructor(props) {
82
+ super(props);
83
+ this._drilldownRef = null;
84
+ this._popover = null;
85
+ this._trigger = null;
86
+ this._containerElement = null;
87
+ this._id = void 0;
88
+ this._triggerId = void 0;
89
+ this._headerBackId = void 0;
90
+ this._headerTitleId = void 0;
91
+ this._headerTitleLabelId = void 0;
92
+ this._headerActionId = void 0;
93
+ this._pageHistory = void 0;
94
+ this._activeOptionsMap = {};
95
+ this._selectedGroupOptionsMap = {};
96
+ this.ref = null;
97
+
98
+ this.handleRef = el => {
99
+ // ref and elementRef have to be set together for the same element
100
+ const elementRef = this.props.elementRef;
101
+ this.ref = el;
102
+
103
+ if (typeof elementRef === 'function') {
104
+ elementRef(el);
105
+ }
106
+ };
107
+
108
+ this.handleDrilldownRef = el => {
109
+ const drilldownRef = this.props.drilldownRef;
110
+ this._drilldownRef = el;
111
+
112
+ if (typeof drilldownRef === 'function') {
113
+ drilldownRef(el);
114
+ } // setting ref for "non-popover" version, the drilldown itself
115
+ // (if a trigger is provided, the Popover sets the ref)
116
+
117
+
118
+ if (!this.props.trigger) {
119
+ this.handleRef(el);
120
+ }
121
+ };
122
+
123
+ this.show = event => {
124
+ if (this._popover) {
125
+ this._popover.show(event);
126
+
127
+ this.setState({
128
+ isShowingPopover: true
129
+ });
130
+ }
131
+ };
132
+
133
+ this.hide = event => {
134
+ if (this._popover) {
135
+ this._popover.hide(event);
136
+
137
+ this.setState({
138
+ isShowingPopover: false
139
+ });
140
+ this.reset();
141
+ }
142
+ };
143
+
144
+ this.handleOptionHighlight = (_event, _ref) => {
145
+ let id = _ref.id,
146
+ direction = _ref.direction;
147
+ const rotateFocus = this.props.rotateFocus;
148
+ const highlightedOptionId = this.state.highlightedOptionId; // if id exists, use that, or calculate from direction
149
+
150
+ let highlightId = this.getPageChildById(id) ? id : void 0;
151
+
152
+ if (!highlightId) {
153
+ if (!highlightedOptionId) {
154
+ // nothing highlighted yet, highlight first option
155
+ highlightId = this.activeOptionIds[0];
156
+ } else if (direction) {
157
+ // if it has direction, find next id based on it
158
+ const index = this.activeOptionIds.indexOf(highlightedOptionId);
159
+ const newIndex = index + direction;
160
+ highlightId = index > -1 ? this.activeOptionIds[newIndex] : void 0;
161
+
162
+ if (rotateFocus) {
163
+ const lastOptionsIndex = this.activeOptionIds.length - 1;
164
+
165
+ if (newIndex < 0) {
166
+ highlightId = this.activeOptionIds[lastOptionsIndex];
167
+ }
168
+
169
+ if (newIndex > lastOptionsIndex) {
170
+ highlightId = this.activeOptionIds[0];
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ if (highlightId) {
177
+ // only highlight if id exists as a valid option
178
+ this.setState({
179
+ highlightedOptionId: highlightId
180
+ }, () => {
181
+ this.focusOption(highlightId);
182
+ });
183
+ }
184
+ };
185
+
186
+ this.goToPage = newPageId => {
187
+ var _this$pageMap;
188
+
189
+ if (!newPageId) {
190
+ (0, _console.warn)(false, `Cannot go to page because there was no page id provided.`);
191
+ return void 0;
192
+ } // TS complains that it cannot be true, but since it is an exposed method,
193
+ // it is better if we provide a warning for this case too
194
+
195
+
196
+ if (typeof newPageId !== 'string') {
197
+ (0, _console.warn)(false, `Cannot go to page because parameter newPageId has to be string (valid page id). Current newPageId is "${typeof newPageId}".`);
198
+ return void 0;
199
+ }
200
+
201
+ if (!((_this$pageMap = this.pageMap) !== null && _this$pageMap !== void 0 && _this$pageMap[newPageId])) {
202
+ (0, _console.warn)(false, `Cannot go to page because page with id: "${newPageId}" doesn't exist.`);
203
+ return void 0;
204
+ } // the last page id in the history is the current one,
205
+ // it will become the "prevPage"
206
+
207
+
208
+ const prevPageId = this._pageHistory[this._pageHistory.length - 1];
209
+
210
+ const idxInHistory = this._pageHistory.indexOf(newPageId);
211
+
212
+ if (idxInHistory < 0) {
213
+ // if it is not in the page history, we have to add it
214
+ this._pageHistory.push(newPageId);
215
+ } else {
216
+ // if it was already in the history, we go back to that page,
217
+ // and clear the rest from the history
218
+ this._pageHistory.splice(idxInHistory + 1, this._pageHistory.length - 1);
219
+ }
220
+
221
+ this.setState({
222
+ activePageId: newPageId,
223
+ highlightedOptionId: void 0
224
+ });
225
+ return {
226
+ prevPageId,
227
+ newPageId
228
+ };
229
+ };
230
+
231
+ this.goToPreviousPage = () => {
232
+ if (!this.previousPage) {
233
+ (0, _console.warn)(false, `There is no previous page to go to. The current page history is: [${this._pageHistory.join(', ')}].`);
234
+ return void 0;
235
+ } // If there is a previous page, goToPage will succeed and return the data
236
+
237
+
238
+ const _ref2 = this.goToPage(this.previousPage.id),
239
+ newPageId = _ref2.newPageId,
240
+ prevPageId = _ref2.prevPageId;
241
+
242
+ return {
243
+ newPageId,
244
+ prevPageId
245
+ };
246
+ };
247
+
248
+ this.handleBackButtonClick = () => {
249
+ const _ref3 = this.currentPage,
250
+ onBackButtonClicked = _ref3.onBackButtonClicked; // we only display the back button when there is a page to go back to
251
+
252
+ const _ref4 = this.goToPreviousPage(),
253
+ newPageId = _ref4.newPageId,
254
+ prevPageId = _ref4.prevPageId;
255
+
256
+ if (typeof onBackButtonClicked === 'function') {
257
+ onBackButtonClicked(newPageId, prevPageId);
258
+ }
259
+ };
260
+
261
+ this.handleOptionSelect = (event, _ref5) => {
262
+ let id = _ref5.id;
263
+ const selectedOption = this.getPageChildById(id);
264
+
265
+ if (!id || !selectedOption || selectedOption.props.disabled || event.target.getAttribute('disabled') || event.target.getAttribute('aria-disabled')) {
266
+ event.preventDefault();
267
+ event.stopPropagation();
268
+ return;
269
+ }
270
+
271
+ const _this$props = this.props,
272
+ shouldHideOnSelect = _this$props.shouldHideOnSelect,
273
+ onSelect = _this$props.onSelect;
274
+ const groupProps = selectedOption.groupProps,
275
+ selectedOptionChild = (0, _objectWithoutProperties2.default)(selectedOption, _excluded);
276
+ const _selectedOptionChild$ = selectedOptionChild.props,
277
+ subPageId = _selectedOptionChild$.subPageId,
278
+ href = _selectedOptionChild$.href,
279
+ value = _selectedOptionChild$.value,
280
+ onOptionClick = _selectedOptionChild$.onOptionClick;
281
+
282
+ if (typeof onOptionClick === 'function') {
283
+ onOptionClick(event, {
284
+ optionId: id,
285
+ drilldown: this,
286
+ ...this.exposedNavigationProps
287
+ });
288
+ }
289
+
290
+ if (subPageId) {
291
+ this.goToPage(subPageId);
292
+ }
293
+
294
+ if (href) {
295
+ var _this$_drilldownRef;
296
+
297
+ const optionEl = (_this$_drilldownRef = this._drilldownRef) === null || _this$_drilldownRef === void 0 ? void 0 : _this$_drilldownRef.querySelector(`#${id}`);
298
+ const isLink = optionEl.tagName.toLowerCase() === 'a'; // we need this check because in some cases
299
+ // we ignore href prop in renderOption()
300
+
301
+ if (isLink && optionEl !== null && optionEl !== void 0 && optionEl.href) {
302
+ optionEl.click();
303
+ }
304
+ }
305
+
306
+ if (groupProps !== null && groupProps !== void 0 && groupProps.selectableType) {
307
+ this.handleGroupOptionSelected(event, selectedOption);
308
+ } else {
309
+ if (typeof onSelect === 'function') {
310
+ onSelect(event, {
311
+ value,
312
+ isSelected: true,
313
+ selectedOption: selectedOptionChild,
314
+ drilldown: this
315
+ });
316
+ }
317
+ } // should prevent closing on page navigation
318
+
319
+
320
+ if (shouldHideOnSelect && !subPageId && id !== this._headerBackId) {
321
+ this.hide(event);
322
+ }
323
+ };
324
+
325
+ this.handleKeyDown = event => {
326
+ const id = event.target.id;
327
+ const option = this.getPageChildById(id); // On Space...
328
+
329
+ if ([' ', 'space', 'Space'].includes(event.key)) {
330
+ // we need to preventDefault so the page doesn't scroll on Space
331
+ event.preventDefault();
332
+ event.stopPropagation(); // for options, Space it has to work as Enter (get selected)
333
+
334
+ if (option) {
335
+ this.handleOptionSelect(event, {
336
+ id
337
+ });
338
+ }
339
+ } // On Right arrow...
340
+
341
+
342
+ if (event.key === 'ArrowRight') {
343
+ // if the option has subpage, we open it
344
+ if (option !== null && option !== void 0 && option.props.subPageId) {
345
+ this.handleOptionSelect(event, {
346
+ id
347
+ });
348
+ }
349
+ } // On Left arrow...
350
+
351
+
352
+ if (event.key === 'ArrowLeft') {
353
+ var _this$_popover;
354
+
355
+ // if it is possible, we go a level up in the history
356
+ if (this._pageHistory.length > 1) {
357
+ this.goToPreviousPage();
358
+ } // if on root page and popover is open, we close it
359
+
360
+
361
+ if (this.isOnRootPage && (_this$_popover = this._popover) !== null && _this$_popover !== void 0 && _this$_popover.shown) {
362
+ this._popover.hide(event);
363
+ }
364
+ }
365
+ };
366
+
367
+ this.handleToggle = (event, shown) => {
368
+ const onToggle = this.props.onToggle;
369
+ this.setState({
370
+ isShowingPopover: shown
371
+ });
372
+
373
+ if (typeof onToggle === 'function') {
374
+ onToggle(event, {
375
+ shown,
376
+ drilldown: this,
377
+ ...this.exposedNavigationProps
378
+ });
379
+ }
380
+ };
381
+
382
+ this.state = {
383
+ isShowingPopover: props.trigger ? !!props.show : false,
384
+ activePageId: props.rootPageId,
385
+ highlightedOptionId: void 0,
386
+ lastSelectedId: void 0
387
+ };
388
+ this._pageHistory = [props.rootPageId];
389
+ this.setDefaultSelected();
390
+ this._id = props.id || props.deterministicId();
391
+ this._triggerId = props.deterministicId('Drilldown-Trigger');
392
+ this._headerBackId = props.deterministicId('DrilldownHeader-Back');
393
+ this._headerTitleId = props.deterministicId('DrilldownHeader-Title');
394
+ this._headerTitleLabelId = props.deterministicId('DrilldownHeader-Title-Label');
395
+ this._headerActionId = props.deterministicId('DrilldownHeader-Action');
396
+ }
397
+
398
+ componentDidMount() {
399
+ var _this$props$makeStyle, _this$props2;
400
+
401
+ (_this$props$makeStyle = (_this$props2 = this.props).makeStyles) === null || _this$props$makeStyle === void 0 ? void 0 : _this$props$makeStyle.call(_this$props2, this.makeStylesVariables);
402
+ }
403
+
404
+ componentDidUpdate(_prevProps, prevState) {
405
+ var _this$props$makeStyle2, _this$props3;
406
+
407
+ (_this$props$makeStyle2 = (_this$props3 = this.props).makeStyles) === null || _this$props$makeStyle2 === void 0 ? void 0 : _this$props$makeStyle2.call(_this$props3, this.makeStylesVariables);
408
+
409
+ if (prevState.activePageId !== this.state.activePageId) {
410
+ // on page change with mouse navigation, some option can get rendered
411
+ // under the cursor and get focused, so we need to wait a tick to see
412
+ // if anything gets focused, otherwise we focus the whole drilldown
413
+ setTimeout(() => {
414
+ if (!this.focused()) {
415
+ this.focus();
416
+ }
417
+ }, 0);
418
+ } // if the current page was removed
419
+
420
+
421
+ if (!this.currentPage) {
422
+ if (this.previousPage) {
423
+ this.goToPreviousPage();
424
+ } else {
425
+ this.goToPage(this.props.rootPageId);
426
+ }
427
+ }
428
+
429
+ if (this.state.highlightedOptionId && !this.getPageChildById(this.state.highlightedOptionId)) {
430
+ this.setState({
431
+ highlightedOptionId: void 0
432
+ });
433
+ }
434
+ }
435
+
436
+ get makeStylesVariables() {
437
+ return {
438
+ hasHighlightedOption: !!this.state.highlightedOptionId
439
+ };
440
+ }
441
+
442
+ get activeOptionIds() {
443
+ return Object.keys(this._activeOptionsMap);
444
+ }
445
+
446
+ get activeOptions() {
447
+ return Object.values(this._activeOptionsMap);
448
+ }
449
+
450
+ get pages() {
451
+ const children = this.props.children;
452
+ return _react.default.Children.toArray(children || []);
453
+ }
454
+
455
+ get pageMap() {
456
+ const children = this.props.children;
457
+
458
+ if (!children) {
459
+ return void 0;
460
+ }
461
+
462
+ const map = {};
463
+ this.pages.forEach(page => {
464
+ const props = page.props;
465
+ const children = props.children;
466
+ map[props.id] = { ...props,
467
+ children: _react.default.Children.toArray(children || [])
468
+ };
469
+ });
470
+ return map;
471
+ }
472
+
473
+ get isOnRootPage() {
474
+ return this.state.activePageId === this.props.rootPageId;
475
+ }
476
+
477
+ get currentPage() {
478
+ return this.getPageById(this.state.activePageId);
479
+ }
480
+
481
+ get previousPage() {
482
+ const previousPageId = this._pageHistory[this._pageHistory.length - 2];
483
+ return this.getPageById(previousPageId);
484
+ } // Returns the navigation methods and the page history.
485
+ // These are used in some callbacks to expose the navigation logic.
486
+
487
+
488
+ get exposedNavigationProps() {
489
+ const goToPage = this.goToPage,
490
+ goToPreviousPage = this.goToPreviousPage; // we make a copy of the array so the original history
491
+ // cannot be modified from the outside
492
+
493
+ const pageHistory = [...this._pageHistory];
494
+ return {
495
+ pageHistory,
496
+ goToPage,
497
+ goToPreviousPage
498
+ };
499
+ }
500
+
501
+ get currentPageAriaLabel() {
502
+ var _this$currentPage;
503
+
504
+ // return, if explicitly set
505
+ if (this.props['aria-labelledby']) {
506
+ return this.props['aria-labelledby'];
507
+ } // if it has title, point to the title label content
508
+
509
+
510
+ if ((_this$currentPage = this.currentPage) !== null && _this$currentPage !== void 0 && _this$currentPage.renderTitle) {
511
+ return this._headerTitleLabelId;
512
+ } // if root page has no title, try the trigger, if exists
513
+
514
+
515
+ if (this.isOnRootPage && this.props.trigger) {
516
+ return this._triggerId;
517
+ }
518
+
519
+ return void 0;
520
+ }
521
+
522
+ getChildrenArray(children) {
523
+ if (!children) {
524
+ return [];
525
+ }
526
+
527
+ return Array.isArray(children) ? children : [children];
528
+ }
529
+
530
+ getPageById(id) {
531
+ return this.pageMap && id ? this.pageMap[id] : void 0;
532
+ }
533
+
534
+ getPageChildById(id) {
535
+ return id ? this._activeOptionsMap[id] : void 0;
536
+ }
537
+
538
+ setDefaultSelected() {
539
+ this.pages.forEach(page => {
540
+ const children = page.props.children;
541
+ this.getChildrenArray(children).forEach(child => {
542
+ if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownGroup.DrilldownGroup])) {
543
+ var _this$getChildrenArra;
544
+
545
+ const _child$props = child.props,
546
+ groupId = _child$props.id,
547
+ selectableType = _child$props.selectableType,
548
+ _child$props$defaultS = _child$props.defaultSelected,
549
+ groupDefaultSelected = _child$props$defaultS === void 0 ? [] : _child$props$defaultS,
550
+ groupChildren = _child$props.children;
551
+
552
+ if (!selectableType) {
553
+ return;
554
+ }
555
+
556
+ if (selectableType === 'single' && groupDefaultSelected.length > 1) {
557
+ (0, _console.error)(false, `Radio type selectable groups can have only one item selected! Group with id "${groupId}" cannot select multiple items: [${groupDefaultSelected.join(', ')}]!`);
558
+ return;
559
+ }
560
+
561
+ this._selectedGroupOptionsMap[groupId] = new Map();
562
+ (_this$getChildrenArra = this.getChildrenArray(groupChildren)) === null || _this$getChildrenArra === void 0 ? void 0 : _this$getChildrenArra.forEach(groupChild => {
563
+ if ((0, _matchComponentTypes.matchComponentTypes)(groupChild, [_DrilldownOption.DrilldownOption])) {
564
+ const _groupChild$props = groupChild.props,
565
+ optionId = _groupChild$props.id,
566
+ optionValue = _groupChild$props.value,
567
+ optionDefaultSelected = _groupChild$props.defaultSelected; // if explicitly set to false, it should override the group's
568
+
569
+ if (optionDefaultSelected === false) {
570
+ return;
571
+ }
572
+
573
+ const isGroupDefaultSelected = typeof optionValue !== 'undefined' && groupDefaultSelected.filter(value => typeof value !== 'undefined').includes(optionValue);
574
+
575
+ if (optionDefaultSelected || isGroupDefaultSelected) {
576
+ this._selectedGroupOptionsMap[groupId].set(optionId, optionValue);
577
+ }
578
+ }
579
+ });
580
+ }
581
+ });
582
+ });
583
+ }
584
+
585
+ get selectedGroupOptionIdsArray() {
586
+ return Object.values(this._selectedGroupOptionsMap).map(groupIdMap => Array.from(groupIdMap.keys())).flat();
587
+ }
588
+
589
+ get headerChildren() {
590
+ const currentPage = this.currentPage;
591
+ const _this$props4 = this.props,
592
+ styles = _this$props4.styles,
593
+ deterministicId = _this$props4.deterministicId;
594
+ const headerChildren = [];
595
+
596
+ if (!currentPage) {
597
+ return headerChildren;
598
+ }
599
+
600
+ const children = currentPage.children,
601
+ renderBackButtonLabel = currentPage.renderBackButtonLabel,
602
+ renderTitle = currentPage.renderTitle,
603
+ renderActionLabel = currentPage.renderActionLabel,
604
+ onHeaderActionClicked = currentPage.onHeaderActionClicked,
605
+ withoutHeaderSeparator = currentPage.withoutHeaderSeparator; // Back navigation option
606
+
607
+ if (this.previousPage) {
608
+ const prevPageTitle = (0, _callRenderProp.callRenderProp)(this.previousPage.renderTitle);
609
+ const backButtonLabel = (0, _callRenderProp.callRenderProp)(renderBackButtonLabel, prevPageTitle);
610
+ headerChildren.push((0, _emotion.jsx)(_DrilldownOption.DrilldownOption, {
611
+ id: this._headerBackId,
612
+ onOptionClick: this.handleBackButtonClick
613
+ }, (0, _emotion.jsx)("div", {
614
+ css: styles === null || styles === void 0 ? void 0 : styles.headerBack,
615
+ role: "presentation"
616
+ }, backButtonLabel)));
617
+ } // Header title
618
+
619
+
620
+ if (renderTitle) {
621
+ const title = (0, _callRenderProp.callRenderProp)(renderTitle);
622
+
623
+ if (title) {
624
+ headerChildren.push((0, _emotion.jsx)(_DrilldownOption.DrilldownOption, {
625
+ id: this._headerTitleId,
626
+ role: "presentation",
627
+ "aria-hidden": "true"
628
+ }, (0, _emotion.jsx)("div", {
629
+ css: styles === null || styles === void 0 ? void 0 : styles.headerTitle,
630
+ id: this._headerTitleLabelId
631
+ }, title)));
632
+ }
633
+ } // Action label
634
+
635
+
636
+ if (renderActionLabel) {
637
+ const actionLabel = (0, _callRenderProp.callRenderProp)(renderActionLabel);
638
+
639
+ if (actionLabel) {
640
+ headerChildren.push((0, _emotion.jsx)(_DrilldownOption.DrilldownOption, {
641
+ id: this._headerActionId,
642
+ themeOverride: {
643
+ color: styles === null || styles === void 0 ? void 0 : styles.headerActionColor
644
+ },
645
+ onOptionClick: event => {
646
+ if (typeof onHeaderActionClicked === 'function') {
647
+ onHeaderActionClicked(event);
648
+ }
649
+ }
650
+ }, actionLabel));
651
+ }
652
+ } // header separator
653
+
654
+
655
+ if (headerChildren.length > 0 && children.length > 0 && !withoutHeaderSeparator) {
656
+ headerChildren.push((0, _emotion.jsx)(_DrilldownSeparator.DrilldownSeparator, {
657
+ id: deterministicId('DrilldownHeader-Separator')
658
+ }));
659
+ }
660
+
661
+ return headerChildren;
662
+ }
663
+
664
+ get shown() {
665
+ return this.props.trigger ? this.state.isShowingPopover : true;
666
+ }
667
+
668
+ reset() {
669
+ this._activeOptionsMap = {};
670
+ this.setState({
671
+ highlightedOptionId: void 0
672
+ });
673
+ }
674
+
675
+ focus() {
676
+ if (this.shown) {
677
+ var _this$_drilldownRef2, _this$_drilldownRef3;
678
+
679
+ (0, _console.error)(!!((_this$_drilldownRef2 = this._drilldownRef) !== null && _this$_drilldownRef2 !== void 0 && _this$_drilldownRef2.focus), '[Drilldown] Could not focus the drilldown.');
680
+ (_this$_drilldownRef3 = this._drilldownRef) === null || _this$_drilldownRef3 === void 0 ? void 0 : _this$_drilldownRef3.focus();
681
+ } else {
682
+ var _this$_trigger;
683
+
684
+ (0, _console.error)(!!((_this$_trigger = this._trigger) !== null && _this$_trigger !== void 0 && _this$_trigger.focus), '[Drilldown] Could not focus the trigger.');
685
+
686
+ this._trigger.focus();
687
+ }
688
+ }
689
+
690
+ focused() {
691
+ if (this.shown) {
692
+ return (0, _containsActiveElement.containsActiveElement)(this._drilldownRef);
693
+ } else {
694
+ return (0, _containsActiveElement.containsActiveElement)(this._trigger);
695
+ }
696
+ }
697
+
698
+ focusOption(id) {
699
+ const container = this._containerElement;
700
+ const optionElement = container === null || container === void 0 ? void 0 : container.querySelector(`[id="${id}"]`);
701
+ optionElement === null || optionElement === void 0 ? void 0 : optionElement.focus();
702
+ }
703
+
704
+ handleGroupOptionSelected(event, selectedOption) {
705
+ const _selectedOption$props = selectedOption.props,
706
+ optionId = _selectedOption$props.id,
707
+ value = _selectedOption$props.value;
708
+ const _ref6 = selectedOption.groupProps,
709
+ groupId = _ref6.id,
710
+ selectableType = _ref6.selectableType,
711
+ groupOnSelect = _ref6.onSelect;
712
+ const onSelect = this.props.onSelect;
713
+
714
+ if (this._selectedGroupOptionsMap[groupId].has(optionId)) {
715
+ // toggle off, if already selected
716
+ this._selectedGroupOptionsMap[groupId].delete(optionId);
717
+ } else {
718
+ if (selectableType === 'multiple') {
719
+ // "checkbox"
720
+ this._selectedGroupOptionsMap[groupId].set(optionId, value);
721
+ } else if (selectableType === 'single') {
722
+ // "radio"
723
+ this._selectedGroupOptionsMap[groupId] = new Map();
724
+
725
+ this._selectedGroupOptionsMap[groupId].set(optionId, value);
726
+ }
727
+ } // needed for rerender
728
+
729
+
730
+ this.setState({
731
+ lastSelectedId: optionId
732
+ });
733
+ const groupProps = selectedOption.groupProps,
734
+ option = (0, _objectWithoutProperties2.default)(selectedOption, _excluded2);
735
+ const selectedOptionValuesInGroup = Array.from(this._selectedGroupOptionsMap[groupId].values());
736
+
737
+ if (typeof groupOnSelect === 'function') {
738
+ groupOnSelect(event, {
739
+ value: selectedOptionValuesInGroup,
740
+ isSelected: this._selectedGroupOptionsMap[groupId].has(optionId),
741
+ selectedOption: option,
742
+ drilldown: this
743
+ });
744
+ }
745
+
746
+ if (typeof onSelect === 'function') {
747
+ onSelect(event, {
748
+ value: selectedOptionValuesInGroup,
749
+ isSelected: this._selectedGroupOptionsMap[groupId].has(optionId),
750
+ selectedOption: option,
751
+ drilldown: this
752
+ });
753
+ }
754
+ }
755
+
756
+ renderList(getOptionProps, getDisabledOptionProps) {
757
+ const currentPage = this.currentPage,
758
+ headerChildren = this.headerChildren;
759
+
760
+ if (!currentPage) {
761
+ return null;
762
+ }
763
+
764
+ const pageChildren = [...headerChildren, ...currentPage.children]; // for tracking if the last item was a Separator or not
765
+
766
+ let lastItemWasSeparator = false;
767
+ return pageChildren.map((child, index) => {
768
+ /**
769
+ * --- RENDER GROUP ---
770
+ */
771
+ if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownGroup.DrilldownGroup])) {
772
+ const isFirstChild = index === 0;
773
+ const isLastChild = index === pageChildren.length - 1;
774
+ const afterSeparator = lastItemWasSeparator;
775
+ const needsFirstSeparator = !child.props.withoutSeparators && !isFirstChild && !afterSeparator;
776
+ const needsLastSeparator = !child.props.withoutSeparators && !isLastChild;
777
+ lastItemWasSeparator = needsLastSeparator;
778
+ return this.renderGroup(child, getOptionProps, getDisabledOptionProps, // for rendering separators appropriately
779
+ needsFirstSeparator, needsLastSeparator);
780
+ /**
781
+ * --- RENDER SEPARATOR ---
782
+ */
783
+ } else if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownSeparator.DrilldownSeparator])) {
784
+ // if the last item was separator, we don't want to duplicate it
785
+ if (lastItemWasSeparator) {
786
+ return null;
787
+ }
788
+
789
+ lastItemWasSeparator = true;
790
+ return this.renderSeparator(child);
791
+ /**
792
+ * --- RENDER OPTION ---
793
+ */
794
+ } else if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownOption.DrilldownOption])) {
795
+ lastItemWasSeparator = false;
796
+ return this.renderOption(child, getOptionProps, getDisabledOptionProps);
797
+ } else {
798
+ return null;
799
+ }
800
+ });
801
+ }
802
+
803
+ renderSeparator(separator) {
804
+ const _separator$props = separator.props,
805
+ id = _separator$props.id,
806
+ themeOverride = _separator$props.themeOverride,
807
+ props = (0, _objectWithoutProperties2.default)(_separator$props, _excluded3);
808
+ return (0, _emotion.jsx)(_Options.Options.Separator, Object.assign({}, props, {
809
+ id: id,
810
+ key: id,
811
+ role: "separator" // we pass the themeOverride to Options.Separator
812
+ ,
813
+ themeOverride: themeOverride
814
+ }));
815
+ }
816
+
817
+ renderOption(option, getOptionProps, getDisabledOptionProps, groupProps) {
818
+ var _this$currentPage2, _optionProps$renderBe, _optionProps$renderBe2, _optionProps$renderAf, _optionProps$renderAf2;
819
+
820
+ const styles = this.props.styles;
821
+ let isSelected = false;
822
+ const _option$props = option.props,
823
+ id = _option$props.id,
824
+ children = _option$props.children,
825
+ href = _option$props.href,
826
+ as = _option$props.as,
827
+ role = _option$props.role,
828
+ subPageId = _option$props.subPageId,
829
+ disabled = _option$props.disabled,
830
+ renderLabelInfo = _option$props.renderLabelInfo,
831
+ renderBeforeLabel = _option$props.renderBeforeLabel,
832
+ renderAfterLabel = _option$props.renderAfterLabel,
833
+ beforeLabelContentVAlign = _option$props.beforeLabelContentVAlign,
834
+ afterLabelContentVAlign = _option$props.afterLabelContentVAlign,
835
+ description = _option$props.description,
836
+ descriptionRole = _option$props.descriptionRole,
837
+ elementRef = _option$props.elementRef,
838
+ themeOverride = _option$props.themeOverride;
839
+
840
+ if (!id) {
841
+ (0, _console.warn)(false, `Drilldown.Option without id won't be rendered. It is needed to internally track the options.`);
842
+ return null;
843
+ }
844
+
845
+ if (this.getPageChildById(id)) {
846
+ (0, _console.warn)(false, `Duplicate id: "${id}"! Make sure all options have unique ids, otherwise they won't be rendered.`);
847
+ return null;
848
+ } // Props passed to the Option.Item
849
+
850
+
851
+ let optionProps = { // passthrough props
852
+ ...(0, _omitProps.omitProps)(option.props, [..._DrilldownOption.DrilldownOption.allowedProps, ..._Options.Options.Item.allowedProps]),
853
+ // props from selectable
854
+ ...getOptionProps({
855
+ id,
856
+ // aria-selected is only valid for these roles, otherwise we need to unset it
857
+ ...(role && !['gridcell', 'option', 'row', 'tab', 'columnheader', 'rowheader', 'treeitem'].includes(role) && {
858
+ 'aria-selected': void 0
859
+ })
860
+ }),
861
+ // we pass the themeOverride to Options.Item
862
+ themeOverride,
863
+ // directly passed props
864
+ renderBeforeLabel,
865
+ renderAfterLabel,
866
+ beforeLabelContentVAlign,
867
+ afterLabelContentVAlign,
868
+ description,
869
+ descriptionRole,
870
+ as,
871
+ role,
872
+ elementRef,
873
+ variant: 'default',
874
+ tabIndex: -1
875
+ }; // extra data we need track on the option,
876
+ // but don't want to expose as props
877
+
878
+ const optionData = {
879
+ groupProps: groupProps
880
+ };
881
+ const isOptionDisabled = id !== this._headerBackId && ( // Back nav is never disabled
882
+ this.props.disabled || ((_this$currentPage2 = this.currentPage) === null || _this$currentPage2 === void 0 ? void 0 : _this$currentPage2.disabled) || (groupProps === null || groupProps === void 0 ? void 0 : groupProps.disabled) || disabled); // display option as disabled
883
+
884
+ if (isOptionDisabled) {
885
+ optionProps.variant = 'disabled';
886
+ optionProps = { ...optionProps,
887
+ ...getDisabledOptionProps()
888
+ };
889
+ } // track as valid active option if not the title
890
+
891
+
892
+ if (id !== this._headerTitleId) {
893
+ this._activeOptionsMap[id] = { ...option,
894
+ ...optionData
895
+ };
896
+ }
897
+
898
+ const customRole = role !== _DrilldownOption.DrilldownOption.defaultProps.role ? role : void 0; // BEFORE/AFTER elements:
899
+ // we set a few manually on Options.Item,
900
+ // the rest are passed directly
901
+
902
+ if (subPageId) {
903
+ optionProps.renderAfterLabel = _IconArrowOpenEndSoli || (_IconArrowOpenEndSoli = (0, _emotion.jsx)(_IconArrowOpenEndSolid.IconArrowOpenEndSolid, null));
904
+ optionProps['aria-haspopup'] = true;
905
+ optionProps.role = customRole || 'button';
906
+ (0, _console.warn)(!renderAfterLabel, `The prop "renderAfterLabel" is reserved on item with id: "${id}". When it has "subPageId" provided, a navigation arrow will render after the label.`);
907
+ }
908
+
909
+ if (id === this._headerBackId) {
910
+ optionProps.renderBeforeLabel = _IconArrowOpenStartSo || (_IconArrowOpenStartSo = (0, _emotion.jsx)(_IconArrowOpenStartSolid.IconArrowOpenStartSolid, null));
911
+ }
912
+
913
+ if (groupProps !== null && groupProps !== void 0 && groupProps.selectableType) {
914
+ isSelected = this._selectedGroupOptionsMap[groupProps.id].has(id);
915
+ optionProps['aria-checked'] = isSelected;
916
+ optionProps.renderBeforeLabel = (0, _emotion.jsx)(_IconCheckSolid.IconCheckSolid, {
917
+ style: {
918
+ opacity: isSelected ? 1 : 0
919
+ }
920
+ });
921
+ (0, _console.warn)(!renderBeforeLabel, `The prop "renderBeforeLabel" is reserved on item with id: "${id}". When this option is a selectable member of a Drilldown.Group, selection indicator will render before the label.`); // setting aria roles and attributes for selectable group items
922
+
923
+ if (groupProps.selectableType === 'single') {
924
+ optionProps.role = customRole || 'menuitemradio';
925
+ }
926
+
927
+ if (groupProps.selectableType === 'multiple') {
928
+ optionProps.role = customRole || 'menuitemcheckbox';
929
+ }
930
+ } // display option as highlighted
931
+
932
+
933
+ if (id === this.state.highlightedOptionId) {
934
+ optionProps.variant = 'highlighted';
935
+
936
+ if (isOptionDisabled) {
937
+ optionProps.variant = 'highlighted-disabled';
938
+ }
939
+ }
940
+
941
+ if (href) {
942
+ if (subPageId) {
943
+ (0, _console.warn)(false, `Drilldown.Option with id "${id}" has subPageId, so it will ignore the "href" property.`);
944
+ } else if (groupProps !== null && groupProps !== void 0 && groupProps.selectableType) {
945
+ (0, _console.warn)(false, `Drilldown.Option with id "${id}" is in a selectable group, so it will ignore the "href" property.`);
946
+ } else {
947
+ optionProps.href = href;
948
+ }
949
+ }
950
+
951
+ const optionLabel = (0, _callRenderProp.callRenderProp)(children, {
952
+ id,
953
+ variant: optionProps.variant,
954
+ isSelected
955
+ });
956
+
957
+ if (!optionLabel) {
958
+ (0, _console.warn)(false, `There are no "children" prop provided for option with id: "${id}", so it won't be rendered.`);
959
+ return null;
960
+ }
961
+
962
+ const renderLabelProps = {
963
+ variant: optionProps.variant,
964
+ vAlign: afterLabelContentVAlign,
965
+ as,
966
+ role: optionProps.role,
967
+ isSelected
968
+ }; // we need to bind our own option props the render functions
969
+
970
+ if (typeof optionProps.renderBeforeLabel === 'function' && !((_optionProps$renderBe = optionProps.renderBeforeLabel) !== null && _optionProps$renderBe !== void 0 && (_optionProps$renderBe2 = _optionProps$renderBe.prototype) !== null && _optionProps$renderBe2 !== void 0 && _optionProps$renderBe2.isReactComponent)) {
971
+ optionProps.renderBeforeLabel = optionProps.renderBeforeLabel.bind(null, renderLabelProps);
972
+ }
973
+
974
+ if (typeof optionProps.renderAfterLabel === 'function' && !((_optionProps$renderAf = optionProps.renderAfterLabel) !== null && _optionProps$renderAf !== void 0 && (_optionProps$renderAf2 = _optionProps$renderAf.prototype) !== null && _optionProps$renderAf2 !== void 0 && _optionProps$renderAf2.isReactComponent)) {
975
+ optionProps.renderAfterLabel = optionProps.renderAfterLabel.bind(null, renderLabelProps);
976
+ }
977
+
978
+ const labelInfo = renderLabelInfo && (0, _callRenderProp.callRenderProp)(renderLabelInfo, renderLabelProps);
979
+ const vAlignMap = {
980
+ start: 'flex-start',
981
+ center: 'center',
982
+ end: 'flex-end'
983
+ };
984
+ const labelAriaId = `${id}__label`;
985
+ const infoAriaId = `${id}__info`;
986
+ const labelledby = option.props['aria-labelledby'] || labelAriaId;
987
+ const describedby = option.props['aria-describedby'] || (labelInfo ? infoAriaId : void 0);
988
+ return (0, _emotion.jsx)(_Options.Options.Item, Object.assign({}, optionProps, {
989
+ key: id,
990
+ "aria-labelledby": labelledby,
991
+ "aria-describedby": describedby
992
+ }), (0, _emotion.jsx)("div", {
993
+ css: styles === null || styles === void 0 ? void 0 : styles.optionContainer,
994
+ role: "none"
995
+ }, (0, _emotion.jsx)("span", {
996
+ css: styles === null || styles === void 0 ? void 0 : styles.optionContent,
997
+ role: "none",
998
+ id: labelAriaId
999
+ }, optionLabel), labelInfo ? (0, _emotion.jsx)("span", {
1000
+ css: styles === null || styles === void 0 ? void 0 : styles.optionLabelInfo,
1001
+ role: "presentation",
1002
+ style: {
1003
+ alignSelf: vAlignMap[afterLabelContentVAlign]
1004
+ }
1005
+ }, (0, _emotion.jsx)("span", {
1006
+ role: "note",
1007
+ id: infoAriaId
1008
+ }, labelInfo)) : null));
1009
+ }
1010
+
1011
+ renderGroup(group, getOptionProps, getDisabledOptionProps, needsFirstSeparator, needsLastSeparator) {
1012
+ const _group$props = group.props,
1013
+ id = _group$props.id,
1014
+ children = _group$props.children,
1015
+ renderGroupTitle = _group$props.renderGroupTitle,
1016
+ themeOverride = _group$props.themeOverride,
1017
+ selectableType = _group$props.selectableType,
1018
+ role = _group$props.role,
1019
+ as = _group$props.as,
1020
+ elementRef = _group$props.elementRef;
1021
+
1022
+ if (!children) {
1023
+ return null;
1024
+ }
1025
+
1026
+ const groupChildren = []; // add a separator above
1027
+
1028
+ if (needsFirstSeparator) {
1029
+ groupChildren.push(_Options$Separator || (_Options$Separator = (0, _emotion.jsx)(_Options.Options.Separator, null)));
1030
+ }
1031
+
1032
+ if (selectableType && !this._selectedGroupOptionsMap[id]) {
1033
+ this._selectedGroupOptionsMap[id] = new Map();
1034
+ } // create a sublist as a group
1035
+ // (a wrapping list item will be created by Options)
1036
+
1037
+
1038
+ groupChildren.push((0, _emotion.jsx)(_Options.Options, {
1039
+ id: id,
1040
+ key: id,
1041
+ role: role,
1042
+ as: as || this.props.as,
1043
+ renderLabel: renderGroupTitle,
1044
+ elementRef: elementRef // we pass the themeOverride to Options
1045
+ ,
1046
+ themeOverride: themeOverride
1047
+ }, this.getChildrenArray(children).map(child => {
1048
+ if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownSeparator.DrilldownSeparator])) {
1049
+ return this.renderSeparator(child);
1050
+ } else if ((0, _matchComponentTypes.matchComponentTypes)(child, [_DrilldownOption.DrilldownOption])) {
1051
+ return this.renderOption(child, getOptionProps, getDisabledOptionProps, group.props);
1052
+ } else {
1053
+ return null;
1054
+ }
1055
+ }))); // add a separator below
1056
+
1057
+ if (needsLastSeparator) {
1058
+ groupChildren.push(_Options$Separator2 || (_Options$Separator2 = (0, _emotion.jsx)(_Options.Options.Separator, null)));
1059
+ }
1060
+
1061
+ return groupChildren;
1062
+ }
1063
+
1064
+ renderPage() {
1065
+ const _this$props5 = this.props,
1066
+ styles = _this$props5.styles,
1067
+ overflowY = _this$props5.overflowY,
1068
+ overflowX = _this$props5.overflowX,
1069
+ height = _this$props5.height,
1070
+ width = _this$props5.width,
1071
+ maxHeight = _this$props5.maxHeight,
1072
+ maxWidth = _this$props5.maxWidth,
1073
+ role = _this$props5.role,
1074
+ as = _this$props5.as,
1075
+ label = _this$props5.label;
1076
+
1077
+ if (!this.currentPage) {
1078
+ return null;
1079
+ }
1080
+
1081
+ return (0, _emotion.jsx)(_Selectable.Selectable, {
1082
+ isShowingOptions: this.shown,
1083
+ highlightedOptionId: this.state.highlightedOptionId,
1084
+ selectedOptionId: this.selectedGroupOptionIdsArray,
1085
+ onRequestShowOptions: this.show,
1086
+ onRequestHideOptions: this.hide,
1087
+ onRequestSelectOption: this.handleOptionSelect,
1088
+ onRequestHighlightOption: this.handleOptionHighlight,
1089
+ onRequestHighlightFirstOption: event => {
1090
+ const firstOptionId = this.activeOptionIds[0];
1091
+ this.handleOptionHighlight(event, {
1092
+ id: firstOptionId
1093
+ });
1094
+ },
1095
+ onRequestHighlightLastOption: event => {
1096
+ const lastOptionId = this.activeOptionIds[this.activeOptionIds.length - 1];
1097
+ this.handleOptionHighlight(event, {
1098
+ id: lastOptionId
1099
+ });
1100
+ }
1101
+ }, _ref7 => {
1102
+ let getTriggerProps = _ref7.getTriggerProps,
1103
+ getListProps = _ref7.getListProps,
1104
+ getOptionProps = _ref7.getOptionProps,
1105
+ getDisabledOptionProps = _ref7.getDisabledOptionProps;
1106
+ return (0, _emotion.jsx)(_View.View, Object.assign({
1107
+ as: "div",
1108
+ elementRef: this.handleDrilldownRef,
1109
+ tabIndex: 0,
1110
+ css: styles === null || styles === void 0 ? void 0 : styles.drilldown,
1111
+ position: "relative",
1112
+ borderRadius: "small",
1113
+ width: width,
1114
+ maxWidth: maxWidth,
1115
+ role: role,
1116
+ "aria-label": label,
1117
+ "aria-labelledby": this.currentPageAriaLabel
1118
+ }, getTriggerProps({
1119
+ id: this._id,
1120
+ // We need to override these aria attributes added by Selectable,
1121
+ // since Drilldown is not a combobox and has no popup
1122
+ 'aria-haspopup': false,
1123
+ 'aria-expanded': void 0,
1124
+ onKeyDown: this.handleKeyDown,
1125
+ onBlur: event => {
1126
+ const target = event.currentTarget;
1127
+ const related = event.relatedTarget;
1128
+ const containsRelated = (0, _contains.contains)(target, related);
1129
+
1130
+ if (!related || related === this._drilldownRef || related !== target && !containsRelated) {
1131
+ this.setState({
1132
+ highlightedOptionId: void 0
1133
+ });
1134
+ }
1135
+ },
1136
+ onMouseLeave: () => {
1137
+ this.setState({
1138
+ highlightedOptionId: void 0
1139
+ });
1140
+ }
1141
+ })), (0, _emotion.jsx)(_View.View, {
1142
+ as: "div",
1143
+ overflowY: overflowY,
1144
+ overflowX: overflowX,
1145
+ height: height,
1146
+ width: width,
1147
+ maxHeight: maxHeight,
1148
+ maxWidth: maxWidth,
1149
+ css: styles === null || styles === void 0 ? void 0 : styles.container,
1150
+ borderRadius: "small",
1151
+ role: "presentation",
1152
+ elementRef: element => {
1153
+ this._containerElement = element;
1154
+ }
1155
+ }, (0, _emotion.jsx)(_Options.Options, Object.assign({}, getListProps(), {
1156
+ role: "presentation",
1157
+ as: as
1158
+ }), this.renderList(getOptionProps, getDisabledOptionProps))));
1159
+ });
1160
+ }
1161
+
1162
+ render() {
1163
+ // clear temporary option store
1164
+ this._activeOptionsMap = {};
1165
+ const _this$props6 = this.props,
1166
+ show = _this$props6.show,
1167
+ defaultShow = _this$props6.defaultShow,
1168
+ placement = _this$props6.placement,
1169
+ withArrow = _this$props6.withArrow,
1170
+ shouldContainFocus = _this$props6.shouldContainFocus,
1171
+ shouldReturnFocus = _this$props6.shouldReturnFocus,
1172
+ trigger = _this$props6.trigger,
1173
+ mountNode = _this$props6.mountNode,
1174
+ constrain = _this$props6.constrain,
1175
+ positionTarget = _this$props6.positionTarget,
1176
+ popoverRef = _this$props6.popoverRef,
1177
+ disabled = _this$props6.disabled,
1178
+ onDismiss = _this$props6.onDismiss,
1179
+ onFocus = _this$props6.onFocus,
1180
+ onMouseOver = _this$props6.onMouseOver,
1181
+ offsetX = _this$props6.offsetX,
1182
+ offsetY = _this$props6.offsetY;
1183
+ return trigger ? (0, _emotion.jsx)(_Popover.Popover, {
1184
+ isShowingContent: show,
1185
+ defaultIsShowingContent: defaultShow,
1186
+ shouldCloseOnDocumentClick: true,
1187
+ onHideContent: (event, _ref8) => {
1188
+ let documentClick = _ref8.documentClick;
1189
+
1190
+ if (typeof onDismiss === 'function') {
1191
+ onDismiss(event, documentClick);
1192
+ }
1193
+
1194
+ this.reset();
1195
+ this.handleToggle(event, false);
1196
+ },
1197
+ onShowContent: event => this.handleToggle(event, true),
1198
+ mountNode: mountNode,
1199
+ placement: placement,
1200
+ withArrow: withArrow,
1201
+ positionTarget: positionTarget,
1202
+ constrain: constrain,
1203
+ shouldContainFocus: shouldContainFocus,
1204
+ shouldReturnFocus: shouldReturnFocus,
1205
+ id: this._id,
1206
+ on: ['click'],
1207
+ onFocus: onFocus,
1208
+ onMouseOver: onMouseOver,
1209
+ offsetX: offsetX,
1210
+ offsetY: offsetY,
1211
+ elementRef: element => {
1212
+ // setting ref for "Popover" version, the popover root
1213
+ // (if there is no trigger, we set it in handleDrilldownRef)
1214
+ this.handleRef(element);
1215
+ },
1216
+ ref: el => {
1217
+ this._popover = el;
1218
+
1219
+ if (typeof popoverRef === 'function') {
1220
+ popoverRef(el);
1221
+ }
1222
+ },
1223
+ renderTrigger: (0, _safeCloneElement.safeCloneElement)(trigger, {
1224
+ ref: el => {
1225
+ this._trigger = el;
1226
+ },
1227
+ 'aria-haspopup': this.props.role,
1228
+ id: this._triggerId,
1229
+ disabled: !!(trigger.props.disabled || disabled),
1230
+ 'aria-disabled': trigger.props.disabled || disabled ? 'true' : void 0
1231
+ })
1232
+ }, this.renderPage()) : this.renderPage();
1233
+ }
1234
+
1235
+ }, _class2.displayName = "Drilldown", _class2.componentId = 'Drilldown', _class2.propTypes = _props.propTypes, _class2.allowedProps = _props.allowedProps, _class2.defaultProps = {
1236
+ disabled: false,
1237
+ rotateFocus: true,
1238
+ as: 'ul',
1239
+ role: 'menu',
1240
+ overflowX: 'auto',
1241
+ overflowY: 'auto',
1242
+ placement: 'bottom center',
1243
+ defaultShow: false,
1244
+ shouldHideOnSelect: true,
1245
+ shouldContainFocus: false,
1246
+ shouldReturnFocus: true,
1247
+ withArrow: true,
1248
+ offsetX: 0,
1249
+ offsetY: 0
1250
+ }, _class2.Group = _DrilldownGroup.DrilldownGroup, _class2.Option = _DrilldownOption.DrilldownOption, _class2.Page = _DrilldownPage.DrilldownPage, _class2.Separator = _DrilldownSeparator.DrilldownSeparator, _temp)) || _class) || _class) || _class);
1251
+ exports.Drilldown = Drilldown;
1252
+ var _default = Drilldown;
1253
+ exports.default = _default;