@workday/canvas-kit-popup-stack 7.1.4 → 7.2.0-427-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,6 +42,24 @@ interface Stack {
42
42
  };
43
43
  _adapter: Partial<typeof PopupStack>;
44
44
  }
45
+ /**
46
+ * The `PopupStack` is a framework agnostic first-in-last-out (FILO) stack that tracks all popups
47
+ * ("floating UI" or any UI that renders on top of other content). It contains methods that interact
48
+ * with the stack to support all coordinating behaviors of all popups on the page. The `PopupStack`
49
+ * helps:
50
+ *
51
+ * - Render popups in the right order on the page
52
+ * - Helps accessibility with the Escape key (topmost popup is closed)
53
+ * - Handles transition to [Full
54
+ * Screen](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
55
+ *
56
+ * The `PopupStack` supports adapters to work with existing popup systems. {@link createAdapter} is
57
+ * exported to accept an adapter. Only a single adapter should be used per page.
58
+ *
59
+ * The `PopupStack` is designed to handle multiple versions of `PopupStack` on the page at once
60
+ * while the internal FILO stack is shared between instances. You should not attempt to use the
61
+ * internal FILO stack. If an adapter is used, the internal FILO stack may be empty.
62
+ */
45
63
  export declare const PopupStack: {
46
64
  /**
47
65
  * Create a HTMLElement as the container for the popup stack item. The returned element reference
@@ -139,6 +157,10 @@ export declare const PopupStack: {
139
157
  */
140
158
  export declare function resetStack(): void;
141
159
  /**
160
+ * An adapter is a custom implementation of the {@link PopupStack}. There is only ever a single
161
+ * instance of an adapter on the page. It allows an adapter to intercept any `PopupStack` method.
162
+ * This could bypass the internal FILO stack of the `PopupStack` and allows the FILO stack to be
163
+ * handled by something else.
142
164
  *
143
165
  * @param adapter The parts of the PopupStack that we want to override
144
166
  */
@@ -1 +1 @@
1
- {"version":3,"file":"PopupStack.d.ts","sourceRoot":"","sources":["../../../lib/PopupStack.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AASD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO9D;AAyDD,UAAU,KAAK;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,WAAW,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAC;CACtC;AAwFD,eAAO,MAAM,UAAU;IACrB;;;;;OAKG;uBACgB,WAAW;IAS9B;;;;;OAKG;cACO,cAAc,GAAG,IAAI;IAY/B;;;;;;OAMG;oBACa,WAAW,GAAG,IAAI;IAkBlC;;;;OAIG;uBACgB,WAAW,GAAG,OAAO;IAaxC;;;;OAIG;oDACiC,WAAW,EAAE;IAQjD;;;;;;;;;;;OAWG;wBACiB,WAAW,GAAG,IAAI;IA6BtC;;;;;;;;;;OAUG;sBACe,WAAW,eAAe,WAAW,GAAG,OAAO;IA2BjE;;;;;;OAMG;gCACyB,WAAW,GAAG,IAAI;IAoB9C;;;;OAIG;+BACwB,WAAW,GAAG,IAAI;IAY7C;;;;;;;;;;;;;;OAcG;mCAC4B,cAAc,GAAG,IAAI;CAqBrD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,SAEzB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,YAAa,QAAQ,iBAAiB,CAAC,SAEhE,CAAC"}
1
+ {"version":3,"file":"PopupStack.d.ts","sourceRoot":"","sources":["../../../lib/PopupStack.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AASD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO9D;AA2CD,UAAU,KAAK;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,WAAW,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAC;CACtC;AAwFD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU;IACrB;;;;;OAKG;uBACgB,WAAW;IAS9B;;;;;OAKG;cACO,cAAc,GAAG,IAAI;IAY/B;;;;;;OAMG;oBACa,WAAW,GAAG,IAAI;IAelC;;;;OAIG;uBACgB,WAAW,GAAG,OAAO;IAaxC;;;;OAIG;oDACiC,WAAW,EAAE;IAQjD;;;;;;;;;;;OAWG;wBACiB,WAAW,GAAG,IAAI;IA6BtC;;;;;;;;;;OAUG;sBACe,WAAW,eAAe,WAAW,GAAG,OAAO;IA2BjE;;;;;;OAMG;gCACyB,WAAW,GAAG,IAAI;IAoB9C;;;;OAIG;+BACwB,WAAW,GAAG,IAAI;IAY7C;;;;;;;;;;;;;;OAcG;mCAC4B,cAAc,GAAG,IAAI;CAqBrD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,SAEzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,YAAa,QAAQ,iBAAiB,CAAC,SAEhE,CAAC"}
@@ -1,17 +1,10 @@
1
1
  "use strict";
2
- var __spreadArrays = (this && this.__spreadArrays) || function () {
3
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
4
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
5
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
6
- r[k] = a[j];
7
- return r;
8
- };
9
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
10
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
11
4
  };
12
5
  Object.defineProperty(exports, "__esModule", { value: true });
13
6
  exports.createAdapter = exports.resetStack = exports.PopupStack = exports.getValue = void 0;
14
- var screenfull_1 = __importDefault(require("screenfull"));
7
+ const screenfull_1 = __importDefault(require("screenfull"));
15
8
  function getLast(items) {
16
9
  if (items.length) {
17
10
  return items[items.length - 1];
@@ -25,30 +18,20 @@ function getLast(items) {
25
18
  * popups.
26
19
  */
27
20
  function getValue(index, length) {
28
- var _a = stack.zIndex, min = _a.min, max = _a.max;
21
+ const { min, max } = stack.zIndex;
29
22
  if (length <= max - min) {
30
23
  return index + min;
31
24
  }
32
25
  return Math.max(min, max - (length - index) + 1);
33
26
  }
34
27
  exports.getValue = getValue;
35
- // IE11 doesn't support Array.prototype.find, so we'll polyfill here
36
- function find(items, predicate) {
37
- var length = items.length;
38
- for (var i = 0; i < length; i++) {
39
- if (predicate(items[i], i, items)) {
40
- return items[i];
41
- }
42
- }
43
- return;
44
- }
45
28
  /**
46
29
  * Sets the z-index value of all elements in the stack according to the `getValue` function. This
47
30
  * will be run any time the stack changes.
48
31
  */
49
32
  function setZIndexOfElements(elements) {
50
- var length = elements.length;
51
- elements.forEach(function (element, index) {
33
+ const length = elements.length;
34
+ elements.forEach((element, index) => {
52
35
  element.style.zIndex = String(getValue(index, length));
53
36
  });
54
37
  }
@@ -57,9 +40,9 @@ function setZIndexOfElements(elements) {
57
40
  * to the stack.
58
41
  */
59
42
  function getOwnerPopup(element, items) {
60
- var parentEl = element;
43
+ let parentEl = element;
61
44
  do {
62
- var owner = find(items, function (el) { return el.element === parentEl; });
45
+ const owner = items.find(el => el.element === parentEl);
63
46
  if (owner) {
64
47
  return owner.element;
65
48
  }
@@ -72,10 +55,10 @@ function getOwnerPopup(element, items) {
72
55
  * hierarchy.
73
56
  */
74
57
  function getChildPopups(item, items) {
75
- var owners = items
76
- .filter(function (i) { return i.owner; })
77
- .map(function (i) { return ({ element: i.element, parent: getOwnerPopup(i.owner, items) }); })
78
- .filter(function (i) { return i.parent === item.element; });
58
+ const owners = items
59
+ .filter(i => i.owner)
60
+ .map(i => ({ element: i.element, parent: getOwnerPopup(i.owner, items) }))
61
+ .filter(i => i.parent === item.element);
79
62
  return owners;
80
63
  }
81
64
  /**
@@ -85,8 +68,8 @@ function getChildPopups(item, items) {
85
68
  * @param path dot-notation path of a deep property
86
69
  */
87
70
  function get(obj, path) {
88
- var parts = path.split('.');
89
- var first = parts.splice(0, 1)[0];
71
+ const parts = path.split('.');
72
+ const first = parts.splice(0, 1)[0];
90
73
  if (parts.length && obj[first]) {
91
74
  return get(obj[first], parts.join('.'));
92
75
  }
@@ -101,8 +84,8 @@ function get(obj, path) {
101
84
  * @param value Any value
102
85
  */
103
86
  function set(obj, path, value) {
104
- var parts = path.split('.');
105
- var first = parts.splice(0, 1)[0];
87
+ const parts = path.split('.');
88
+ const first = parts.splice(0, 1)[0];
106
89
  if (parts.length) {
107
90
  if (obj[first] === undefined) {
108
91
  obj[first] = {};
@@ -123,7 +106,7 @@ if (typeof window !== 'undefined') {
123
106
  * environments without a `window` object, so it is safe to use in server-side rendering.
124
107
  * @param path Any dot-notation path
125
108
  */
126
- var getFromWindow = function (path) {
109
+ const getFromWindow = (path) => {
127
110
  if (typeof window !== 'undefined') {
128
111
  return get(window, path);
129
112
  }
@@ -135,7 +118,7 @@ var getFromWindow = function (path) {
135
118
  * @param path dot-notation path of a deep property
136
119
  * @param value Any value
137
120
  */
138
- var setToWindow = function (path, value) {
121
+ const setToWindow = (path, value) => {
139
122
  if (typeof window !== 'undefined') {
140
123
  set(window, path, value);
141
124
  }
@@ -143,20 +126,38 @@ var setToWindow = function (path, value) {
143
126
  // We need to make sure only one stack is ever in use on the page - ever. If a stack is already
144
127
  // defined on the page, we need to use that one. Never, ever, ever change this variable name on
145
128
  // window
146
- var stack = getFromWindow('workday.__popupStack') || {
129
+ const stack = getFromWindow('workday.__popupStack') || {
147
130
  description: 'Global popup stack from @workday/canvas-kit/popup-stack',
148
- container: function () { return document.body; },
131
+ container: () => document.body,
149
132
  items: [],
150
133
  zIndex: { min: 30, max: 50, getValue: getValue },
151
134
  _adapter: {},
152
135
  };
153
136
  setToWindow('workday.__popupStack', stack);
154
- var stacks = getFromWindow('workday.__popupStackOfStacks') || [stack];
137
+ const stacks = getFromWindow('workday.__popupStackOfStacks') || [stack];
155
138
  stacks.description = 'Global stack of popup stacks from @workday/canvas-kit/popup-stack';
156
139
  setToWindow('workday.__popupStackOfStacks', stacks);
157
140
  function getTopStack() {
158
141
  return stacks[stacks.length - 1];
159
142
  }
143
+ /**
144
+ * The `PopupStack` is a framework agnostic first-in-last-out (FILO) stack that tracks all popups
145
+ * ("floating UI" or any UI that renders on top of other content). It contains methods that interact
146
+ * with the stack to support all coordinating behaviors of all popups on the page. The `PopupStack`
147
+ * helps:
148
+ *
149
+ * - Render popups in the right order on the page
150
+ * - Helps accessibility with the Escape key (topmost popup is closed)
151
+ * - Handles transition to [Full
152
+ * Screen](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
153
+ *
154
+ * The `PopupStack` supports adapters to work with existing popup systems. {@link createAdapter} is
155
+ * exported to accept an adapter. Only a single adapter should be used per page.
156
+ *
157
+ * The `PopupStack` is designed to handle multiple versions of `PopupStack` on the page at once
158
+ * while the internal FILO stack is shared between instances. You should not attempt to use the
159
+ * internal FILO stack. If an adapter is used, the internal FILO stack may be empty.
160
+ */
160
161
  exports.PopupStack = {
161
162
  /**
162
163
  * Create a HTMLElement as the container for the popup stack item. The returned element reference
@@ -164,13 +165,13 @@ exports.PopupStack = {
164
165
  * element is added and removed from the DOM as well as the `z-index` style property. Your content
165
166
  * should be added to this element.
166
167
  */
167
- createContainer: function () {
168
+ createContainer() {
168
169
  var _a;
169
- var stack = getTopStack();
170
+ const stack = getTopStack();
170
171
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.createContainer) {
171
172
  return stack._adapter.createContainer();
172
173
  }
173
- var div = document.createElement('div');
174
+ const div = document.createElement('div');
174
175
  div.style.position = 'relative'; // z-index only works on _positioned_ elements
175
176
  return div;
176
177
  },
@@ -180,9 +181,9 @@ exports.PopupStack = {
180
181
  * popups to be registered initially, but rendered when the user triggers some event, call this
181
182
  * method when the event triggers.
182
183
  */
183
- add: function (item) {
184
+ add(item) {
184
185
  var _a, _b;
185
- var stack = getTopStack();
186
+ const stack = getTopStack();
186
187
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.add) {
187
188
  stack._adapter.add(item);
188
189
  return;
@@ -198,16 +199,16 @@ exports.PopupStack = {
198
199
  * called when the element is removed from the DOM. This method will reset z-index values of the
199
200
  * stack.
200
201
  */
201
- remove: function (element) {
202
+ remove(element) {
202
203
  var _a, _b;
203
204
  // Find the stack the popup belongs to.
204
- var stack = find(stacks, function (stack) { return !!find(exports.PopupStack.getElements(stack), function (el) { return el === element; }); });
205
+ const stack = stacks.find(stack => !!exports.PopupStack.getElements(stack).find(el => el === element));
205
206
  if (stack) {
206
207
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.remove) {
207
208
  stack._adapter.remove(element);
208
209
  return;
209
210
  }
210
- stack.items = stack.items.filter(function (item) { return item.element !== element; });
211
+ stack.items = stack.items.filter(item => item.element !== element);
211
212
  (((_b = stack.container) === null || _b === void 0 ? void 0 : _b.call(stack)) || document.body).removeChild(element);
212
213
  setZIndexOfElements(exports.PopupStack.getElements(stack));
213
214
  }
@@ -217,13 +218,13 @@ exports.PopupStack = {
217
218
  * is not the top of the stack or is not found in the stack. The `element` should be the same
218
219
  * reference that was passed to `add`
219
220
  */
220
- isTopmost: function (element) {
221
+ isTopmost(element) {
221
222
  var _a;
222
- var stack = getTopStack();
223
+ const stack = getTopStack();
223
224
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.isTopmost) {
224
225
  return stack._adapter.isTopmost(element);
225
226
  }
226
- var last = getLast(stack.items);
227
+ const last = getLast(stack.items);
227
228
  if (last) {
228
229
  return last.element === element;
229
230
  }
@@ -234,13 +235,13 @@ exports.PopupStack = {
234
235
  * elements in the order of lowest z-index to highest z-index. Some popup behaviors will need to
235
236
  * make decisions based on z-index order.
236
237
  */
237
- getElements: function (stackOverride) {
238
+ getElements(stackOverride) {
238
239
  var _a;
239
- var stack = stackOverride || getTopStack();
240
+ const stack = stackOverride || getTopStack();
240
241
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.getElements) {
241
242
  return stack._adapter.getElements();
242
243
  }
243
- return stack.items.map(function (i) { return i.element; });
244
+ return stack.items.map(i => i.element);
244
245
  },
245
246
  /**
246
247
  * Bring the element to the top of the stack. This is useful for persistent popups to place them
@@ -254,30 +255,30 @@ exports.PopupStack = {
254
255
  * This does not need to be called when a popup is added since added popups are already place on
255
256
  * the top of the stack.
256
257
  */
257
- bringToTop: function (element) {
258
+ bringToTop(element) {
258
259
  var _a;
259
- var stack = getTopStack();
260
+ const stack = getTopStack();
260
261
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.bringToTop) {
261
262
  stack._adapter.bringToTop(element);
262
263
  return;
263
264
  }
264
- var item = find(stack.items, function (i) { return i.element === element; });
265
+ const item = stack.items.find(i => i.element === element);
265
266
  if (item) {
266
- stack.items = __spreadArrays(stack.items.filter(function (i) { return i !== item; }), [item]);
267
+ stack.items = [...stack.items.filter(i => i !== item), item];
267
268
  // Also bring children to top. There are a few cases where stacking might break otherwise:
268
269
  // - Clicking a Popup calls `bringToTop`, but mouse is over a Tooltip so that Tooltip is now
269
270
  // under the Popup
270
271
  // - Clicking a button opens a new Popup, but that click bubbles up to a `bringToTop` call
271
272
  // putting the new popup under an existing one
272
273
  // Example: https://user-images.githubusercontent.com/338257/83924476-031af580-a742-11ea-8f68-0edabdf0fd6a.gif
273
- getChildPopups(item, stack.items).forEach(function (popup) {
274
+ getChildPopups(item, stack.items).forEach(popup => {
274
275
  exports.PopupStack.bringToTop(popup.element);
275
276
  });
276
277
  setZIndexOfElements(exports.PopupStack.getElements());
277
278
  }
278
279
  else {
279
280
  // not found
280
- var e = new Error();
281
+ const e = new Error();
281
282
  console.warn('Could not find item', e.stack);
282
283
  }
283
284
  },
@@ -292,22 +293,24 @@ exports.PopupStack = {
292
293
  * opt-in to toggling. Otherwise there is no way to opt-out of toggle behavior (because the target
293
294
  * is not inside `element`).
294
295
  */
295
- contains: function (element, eventTarget) {
296
+ contains(element, eventTarget) {
296
297
  var _a, _b;
297
- var stack = getTopStack();
298
+ const stack = getTopStack();
298
299
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.contains) {
299
300
  return stack._adapter.contains(element, eventTarget);
300
301
  }
301
- var item = find(stack.items, function (i) { return i.element === element; });
302
- var containsOwnerOfAnotherPopupTargeted = stack.items.some(function (currentItem) {
302
+ const item = stack.items.find(i => i.element === element);
303
+ const containsOwnerOfAnotherPopupTargeted = stack.items.some(currentItem => {
303
304
  var _a;
304
305
  return ((item === null || item === void 0 ? void 0 : item.element.contains(currentItem.owner || null)) &&
305
- (eventTarget === currentItem.owner || ((_a = currentItem.owner) === null || _a === void 0 ? void 0 : _a.contains(eventTarget)) ||
306
+ (eventTarget === currentItem.owner ||
307
+ ((_a = currentItem.owner) === null || _a === void 0 ? void 0 : _a.contains(eventTarget)) ||
306
308
  currentItem.element.contains(eventTarget)));
307
309
  });
308
310
  if (item) {
309
311
  return (containsOwnerOfAnotherPopupTargeted ||
310
- eventTarget === item.owner || ((_b = item.owner) === null || _b === void 0 ? void 0 : _b.contains(eventTarget)) ||
312
+ eventTarget === item.owner ||
313
+ ((_b = item.owner) === null || _b === void 0 ? void 0 : _b.contains(eventTarget)) ||
311
314
  element.contains(eventTarget));
312
315
  }
313
316
  return false;
@@ -319,9 +322,9 @@ exports.PopupStack = {
319
322
  * pushing the same element which is very difficult to ensure only one stack is used. To mitigate,
320
323
  * this method filters out multiple calls to push the same element as a new stack context.
321
324
  */
322
- pushStackContext: function (container) {
325
+ pushStackContext(container) {
323
326
  var _a, _b;
324
- var stack = getTopStack();
327
+ const stack = getTopStack();
325
328
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.pushStackContext) {
326
329
  return stack._adapter.pushStackContext(container);
327
330
  }
@@ -329,10 +332,10 @@ exports.PopupStack = {
329
332
  if (((_b = stack.container) === null || _b === void 0 ? void 0 : _b.call(stack)) === container) {
330
333
  return;
331
334
  }
332
- var newStack = {
335
+ const newStack = {
333
336
  items: [],
334
337
  zIndex: stack.zIndex,
335
- container: function () { return container; },
338
+ container: () => container,
336
339
  _adapter: {},
337
340
  };
338
341
  stacks.push(newStack);
@@ -342,9 +345,9 @@ exports.PopupStack = {
342
345
  * context container element matches to guard against accidental remove of other stack contexts
343
346
  * you don't own.
344
347
  */
345
- popStackContext: function (container) {
348
+ popStackContext(container) {
346
349
  var _a, _b;
347
- var stack = getTopStack();
350
+ const stack = getTopStack();
348
351
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.popStackContext) {
349
352
  return stack._adapter.popStackContext(container);
350
353
  }
@@ -367,19 +370,19 @@ exports.PopupStack = {
367
370
  * members of different popup stack contexts which will cause unspecified results (like the escape
368
371
  * key will choose the wrong popup as the "topmost").
369
372
  */
370
- transferToCurrentContext: function (item) {
373
+ transferToCurrentContext(item) {
371
374
  var _a;
372
- var stack = getTopStack();
375
+ const stack = getTopStack();
373
376
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.transferToCurrentContext) {
374
377
  return stack._adapter.transferToCurrentContext(item);
375
378
  }
376
- if (find(stack.items, function (i) { return i.element === item.element; })) {
379
+ if (stack.items.find(i => i.element === item.element)) {
377
380
  // The element is already in the stack, don't do anything
378
381
  return;
379
382
  }
380
383
  // Try to find the element in existing stacks. If it exists, we need to first remove from that
381
384
  // stack context
382
- var oldStack = find(stacks, function (stack) { return !!find(stack.items, function (i) { return i.element === item.element; }); });
385
+ const oldStack = stacks.find(stack => !!stack.items.find(i => i.element === item.element));
383
386
  if (oldStack) {
384
387
  exports.PopupStack.remove(item.element);
385
388
  }
@@ -395,21 +398,25 @@ function resetStack() {
395
398
  }
396
399
  exports.resetStack = resetStack;
397
400
  /**
401
+ * An adapter is a custom implementation of the {@link PopupStack}. There is only ever a single
402
+ * instance of an adapter on the page. It allows an adapter to intercept any `PopupStack` method.
403
+ * This could bypass the internal FILO stack of the `PopupStack` and allows the FILO stack to be
404
+ * handled by something else.
398
405
  *
399
406
  * @param adapter The parts of the PopupStack that we want to override
400
407
  */
401
- var createAdapter = function (adapter) {
408
+ const createAdapter = (adapter) => {
402
409
  stack._adapter = adapter;
403
410
  };
404
411
  exports.createAdapter = createAdapter;
405
412
  // keep track of the element ourselves to avoid accidentally popping off someone else's stack
406
413
  // context
407
- var element = null;
414
+ let element = null;
408
415
  // Where should this go? Each version of `PopupStack` on a page will add a listener. The
409
416
  // `PopupStack` should guard against multiple handlers like this simultaneously and there is no
410
417
  // lifecycle here.
411
418
  if (screenfull_1.default.isEnabled) {
412
- screenfull_1.default.on('change', function () {
419
+ screenfull_1.default.on('change', () => {
413
420
  if (screenfull_1.default.isFullscreen) {
414
421
  if (screenfull_1.default.element) {
415
422
  element = screenfull_1.default.element;
@@ -42,6 +42,24 @@ interface Stack {
42
42
  };
43
43
  _adapter: Partial<typeof PopupStack>;
44
44
  }
45
+ /**
46
+ * The `PopupStack` is a framework agnostic first-in-last-out (FILO) stack that tracks all popups
47
+ * ("floating UI" or any UI that renders on top of other content). It contains methods that interact
48
+ * with the stack to support all coordinating behaviors of all popups on the page. The `PopupStack`
49
+ * helps:
50
+ *
51
+ * - Render popups in the right order on the page
52
+ * - Helps accessibility with the Escape key (topmost popup is closed)
53
+ * - Handles transition to [Full
54
+ * Screen](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
55
+ *
56
+ * The `PopupStack` supports adapters to work with existing popup systems. {@link createAdapter} is
57
+ * exported to accept an adapter. Only a single adapter should be used per page.
58
+ *
59
+ * The `PopupStack` is designed to handle multiple versions of `PopupStack` on the page at once
60
+ * while the internal FILO stack is shared between instances. You should not attempt to use the
61
+ * internal FILO stack. If an adapter is used, the internal FILO stack may be empty.
62
+ */
45
63
  export declare const PopupStack: {
46
64
  /**
47
65
  * Create a HTMLElement as the container for the popup stack item. The returned element reference
@@ -139,6 +157,10 @@ export declare const PopupStack: {
139
157
  */
140
158
  export declare function resetStack(): void;
141
159
  /**
160
+ * An adapter is a custom implementation of the {@link PopupStack}. There is only ever a single
161
+ * instance of an adapter on the page. It allows an adapter to intercept any `PopupStack` method.
162
+ * This could bypass the internal FILO stack of the `PopupStack` and allows the FILO stack to be
163
+ * handled by something else.
142
164
  *
143
165
  * @param adapter The parts of the PopupStack that we want to override
144
166
  */
@@ -1 +1 @@
1
- {"version":3,"file":"PopupStack.d.ts","sourceRoot":"","sources":["../../../lib/PopupStack.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AASD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO9D;AAyDD,UAAU,KAAK;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,WAAW,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAC;CACtC;AAwFD,eAAO,MAAM,UAAU;IACrB;;;;;OAKG;uBACgB,WAAW;IAS9B;;;;;OAKG;cACO,cAAc,GAAG,IAAI;IAY/B;;;;;;OAMG;oBACa,WAAW,GAAG,IAAI;IAkBlC;;;;OAIG;uBACgB,WAAW,GAAG,OAAO;IAaxC;;;;OAIG;oDACiC,WAAW,EAAE;IAQjD;;;;;;;;;;;OAWG;wBACiB,WAAW,GAAG,IAAI;IA6BtC;;;;;;;;;;OAUG;sBACe,WAAW,eAAe,WAAW,GAAG,OAAO;IA2BjE;;;;;;OAMG;gCACyB,WAAW,GAAG,IAAI;IAoB9C;;;;OAIG;+BACwB,WAAW,GAAG,IAAI;IAY7C;;;;;;;;;;;;;;OAcG;mCAC4B,cAAc,GAAG,IAAI;CAqBrD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,SAEzB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,YAAa,QAAQ,iBAAiB,CAAC,SAEhE,CAAC"}
1
+ {"version":3,"file":"PopupStack.d.ts","sourceRoot":"","sources":["../../../lib/PopupStack.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AASD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO9D;AA2CD,UAAU,KAAK;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,WAAW,CAAC;IAC9B,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,OAAO,QAAQ,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAC;CACtC;AAwFD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU;IACrB;;;;;OAKG;uBACgB,WAAW;IAS9B;;;;;OAKG;cACO,cAAc,GAAG,IAAI;IAY/B;;;;;;OAMG;oBACa,WAAW,GAAG,IAAI;IAelC;;;;OAIG;uBACgB,WAAW,GAAG,OAAO;IAaxC;;;;OAIG;oDACiC,WAAW,EAAE;IAQjD;;;;;;;;;;;OAWG;wBACiB,WAAW,GAAG,IAAI;IA6BtC;;;;;;;;;;OAUG;sBACe,WAAW,eAAe,WAAW,GAAG,OAAO;IA2BjE;;;;;;OAMG;gCACyB,WAAW,GAAG,IAAI;IAoB9C;;;;OAIG;+BACwB,WAAW,GAAG,IAAI;IAY7C;;;;;;;;;;;;;;OAcG;mCAC4B,cAAc,GAAG,IAAI;CAqBrD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,UAAU,SAEzB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,YAAa,QAAQ,iBAAiB,CAAC,SAEhE,CAAC"}
@@ -1,10 +1,3 @@
1
- var __spreadArrays = (this && this.__spreadArrays) || function () {
2
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
3
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
4
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
5
- r[k] = a[j];
6
- return r;
7
- };
8
1
  import screenfull from 'screenfull';
9
2
  function getLast(items) {
10
3
  if (items.length) {
@@ -19,29 +12,19 @@ function getLast(items) {
19
12
  * popups.
20
13
  */
21
14
  export function getValue(index, length) {
22
- var _a = stack.zIndex, min = _a.min, max = _a.max;
15
+ const { min, max } = stack.zIndex;
23
16
  if (length <= max - min) {
24
17
  return index + min;
25
18
  }
26
19
  return Math.max(min, max - (length - index) + 1);
27
20
  }
28
- // IE11 doesn't support Array.prototype.find, so we'll polyfill here
29
- function find(items, predicate) {
30
- var length = items.length;
31
- for (var i = 0; i < length; i++) {
32
- if (predicate(items[i], i, items)) {
33
- return items[i];
34
- }
35
- }
36
- return;
37
- }
38
21
  /**
39
22
  * Sets the z-index value of all elements in the stack according to the `getValue` function. This
40
23
  * will be run any time the stack changes.
41
24
  */
42
25
  function setZIndexOfElements(elements) {
43
- var length = elements.length;
44
- elements.forEach(function (element, index) {
26
+ const length = elements.length;
27
+ elements.forEach((element, index) => {
45
28
  element.style.zIndex = String(getValue(index, length));
46
29
  });
47
30
  }
@@ -50,9 +33,9 @@ function setZIndexOfElements(elements) {
50
33
  * to the stack.
51
34
  */
52
35
  function getOwnerPopup(element, items) {
53
- var parentEl = element;
36
+ let parentEl = element;
54
37
  do {
55
- var owner = find(items, function (el) { return el.element === parentEl; });
38
+ const owner = items.find(el => el.element === parentEl);
56
39
  if (owner) {
57
40
  return owner.element;
58
41
  }
@@ -65,10 +48,10 @@ function getOwnerPopup(element, items) {
65
48
  * hierarchy.
66
49
  */
67
50
  function getChildPopups(item, items) {
68
- var owners = items
69
- .filter(function (i) { return i.owner; })
70
- .map(function (i) { return ({ element: i.element, parent: getOwnerPopup(i.owner, items) }); })
71
- .filter(function (i) { return i.parent === item.element; });
51
+ const owners = items
52
+ .filter(i => i.owner)
53
+ .map(i => ({ element: i.element, parent: getOwnerPopup(i.owner, items) }))
54
+ .filter(i => i.parent === item.element);
72
55
  return owners;
73
56
  }
74
57
  /**
@@ -78,8 +61,8 @@ function getChildPopups(item, items) {
78
61
  * @param path dot-notation path of a deep property
79
62
  */
80
63
  function get(obj, path) {
81
- var parts = path.split('.');
82
- var first = parts.splice(0, 1)[0];
64
+ const parts = path.split('.');
65
+ const first = parts.splice(0, 1)[0];
83
66
  if (parts.length && obj[first]) {
84
67
  return get(obj[first], parts.join('.'));
85
68
  }
@@ -94,8 +77,8 @@ function get(obj, path) {
94
77
  * @param value Any value
95
78
  */
96
79
  function set(obj, path, value) {
97
- var parts = path.split('.');
98
- var first = parts.splice(0, 1)[0];
80
+ const parts = path.split('.');
81
+ const first = parts.splice(0, 1)[0];
99
82
  if (parts.length) {
100
83
  if (obj[first] === undefined) {
101
84
  obj[first] = {};
@@ -116,7 +99,7 @@ if (typeof window !== 'undefined') {
116
99
  * environments without a `window` object, so it is safe to use in server-side rendering.
117
100
  * @param path Any dot-notation path
118
101
  */
119
- var getFromWindow = function (path) {
102
+ const getFromWindow = (path) => {
120
103
  if (typeof window !== 'undefined') {
121
104
  return get(window, path);
122
105
  }
@@ -128,7 +111,7 @@ var getFromWindow = function (path) {
128
111
  * @param path dot-notation path of a deep property
129
112
  * @param value Any value
130
113
  */
131
- var setToWindow = function (path, value) {
114
+ const setToWindow = (path, value) => {
132
115
  if (typeof window !== 'undefined') {
133
116
  set(window, path, value);
134
117
  }
@@ -136,34 +119,52 @@ var setToWindow = function (path, value) {
136
119
  // We need to make sure only one stack is ever in use on the page - ever. If a stack is already
137
120
  // defined on the page, we need to use that one. Never, ever, ever change this variable name on
138
121
  // window
139
- var stack = getFromWindow('workday.__popupStack') || {
122
+ const stack = getFromWindow('workday.__popupStack') || {
140
123
  description: 'Global popup stack from @workday/canvas-kit/popup-stack',
141
- container: function () { return document.body; },
124
+ container: () => document.body,
142
125
  items: [],
143
126
  zIndex: { min: 30, max: 50, getValue: getValue },
144
127
  _adapter: {},
145
128
  };
146
129
  setToWindow('workday.__popupStack', stack);
147
- var stacks = getFromWindow('workday.__popupStackOfStacks') || [stack];
130
+ const stacks = getFromWindow('workday.__popupStackOfStacks') || [stack];
148
131
  stacks.description = 'Global stack of popup stacks from @workday/canvas-kit/popup-stack';
149
132
  setToWindow('workday.__popupStackOfStacks', stacks);
150
133
  function getTopStack() {
151
134
  return stacks[stacks.length - 1];
152
135
  }
153
- export var PopupStack = {
136
+ /**
137
+ * The `PopupStack` is a framework agnostic first-in-last-out (FILO) stack that tracks all popups
138
+ * ("floating UI" or any UI that renders on top of other content). It contains methods that interact
139
+ * with the stack to support all coordinating behaviors of all popups on the page. The `PopupStack`
140
+ * helps:
141
+ *
142
+ * - Render popups in the right order on the page
143
+ * - Helps accessibility with the Escape key (topmost popup is closed)
144
+ * - Handles transition to [Full
145
+ * Screen](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
146
+ *
147
+ * The `PopupStack` supports adapters to work with existing popup systems. {@link createAdapter} is
148
+ * exported to accept an adapter. Only a single adapter should be used per page.
149
+ *
150
+ * The `PopupStack` is designed to handle multiple versions of `PopupStack` on the page at once
151
+ * while the internal FILO stack is shared between instances. You should not attempt to use the
152
+ * internal FILO stack. If an adapter is used, the internal FILO stack may be empty.
153
+ */
154
+ export const PopupStack = {
154
155
  /**
155
156
  * Create a HTMLElement as the container for the popup stack item. The returned element reference
156
157
  * will be the reference to be passed to all other methods. The Popup Stack will control when this
157
158
  * element is added and removed from the DOM as well as the `z-index` style property. Your content
158
159
  * should be added to this element.
159
160
  */
160
- createContainer: function () {
161
+ createContainer() {
161
162
  var _a;
162
- var stack = getTopStack();
163
+ const stack = getTopStack();
163
164
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.createContainer) {
164
165
  return stack._adapter.createContainer();
165
166
  }
166
- var div = document.createElement('div');
167
+ const div = document.createElement('div');
167
168
  div.style.position = 'relative'; // z-index only works on _positioned_ elements
168
169
  return div;
169
170
  },
@@ -173,9 +174,9 @@ export var PopupStack = {
173
174
  * popups to be registered initially, but rendered when the user triggers some event, call this
174
175
  * method when the event triggers.
175
176
  */
176
- add: function (item) {
177
+ add(item) {
177
178
  var _a, _b;
178
- var stack = getTopStack();
179
+ const stack = getTopStack();
179
180
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.add) {
180
181
  stack._adapter.add(item);
181
182
  return;
@@ -191,16 +192,16 @@ export var PopupStack = {
191
192
  * called when the element is removed from the DOM. This method will reset z-index values of the
192
193
  * stack.
193
194
  */
194
- remove: function (element) {
195
+ remove(element) {
195
196
  var _a, _b;
196
197
  // Find the stack the popup belongs to.
197
- var stack = find(stacks, function (stack) { return !!find(PopupStack.getElements(stack), function (el) { return el === element; }); });
198
+ const stack = stacks.find(stack => !!PopupStack.getElements(stack).find(el => el === element));
198
199
  if (stack) {
199
200
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.remove) {
200
201
  stack._adapter.remove(element);
201
202
  return;
202
203
  }
203
- stack.items = stack.items.filter(function (item) { return item.element !== element; });
204
+ stack.items = stack.items.filter(item => item.element !== element);
204
205
  (((_b = stack.container) === null || _b === void 0 ? void 0 : _b.call(stack)) || document.body).removeChild(element);
205
206
  setZIndexOfElements(PopupStack.getElements(stack));
206
207
  }
@@ -210,13 +211,13 @@ export var PopupStack = {
210
211
  * is not the top of the stack or is not found in the stack. The `element` should be the same
211
212
  * reference that was passed to `add`
212
213
  */
213
- isTopmost: function (element) {
214
+ isTopmost(element) {
214
215
  var _a;
215
- var stack = getTopStack();
216
+ const stack = getTopStack();
216
217
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.isTopmost) {
217
218
  return stack._adapter.isTopmost(element);
218
219
  }
219
- var last = getLast(stack.items);
220
+ const last = getLast(stack.items);
220
221
  if (last) {
221
222
  return last.element === element;
222
223
  }
@@ -227,13 +228,13 @@ export var PopupStack = {
227
228
  * elements in the order of lowest z-index to highest z-index. Some popup behaviors will need to
228
229
  * make decisions based on z-index order.
229
230
  */
230
- getElements: function (stackOverride) {
231
+ getElements(stackOverride) {
231
232
  var _a;
232
- var stack = stackOverride || getTopStack();
233
+ const stack = stackOverride || getTopStack();
233
234
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.getElements) {
234
235
  return stack._adapter.getElements();
235
236
  }
236
- return stack.items.map(function (i) { return i.element; });
237
+ return stack.items.map(i => i.element);
237
238
  },
238
239
  /**
239
240
  * Bring the element to the top of the stack. This is useful for persistent popups to place them
@@ -247,30 +248,30 @@ export var PopupStack = {
247
248
  * This does not need to be called when a popup is added since added popups are already place on
248
249
  * the top of the stack.
249
250
  */
250
- bringToTop: function (element) {
251
+ bringToTop(element) {
251
252
  var _a;
252
- var stack = getTopStack();
253
+ const stack = getTopStack();
253
254
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.bringToTop) {
254
255
  stack._adapter.bringToTop(element);
255
256
  return;
256
257
  }
257
- var item = find(stack.items, function (i) { return i.element === element; });
258
+ const item = stack.items.find(i => i.element === element);
258
259
  if (item) {
259
- stack.items = __spreadArrays(stack.items.filter(function (i) { return i !== item; }), [item]);
260
+ stack.items = [...stack.items.filter(i => i !== item), item];
260
261
  // Also bring children to top. There are a few cases where stacking might break otherwise:
261
262
  // - Clicking a Popup calls `bringToTop`, but mouse is over a Tooltip so that Tooltip is now
262
263
  // under the Popup
263
264
  // - Clicking a button opens a new Popup, but that click bubbles up to a `bringToTop` call
264
265
  // putting the new popup under an existing one
265
266
  // Example: https://user-images.githubusercontent.com/338257/83924476-031af580-a742-11ea-8f68-0edabdf0fd6a.gif
266
- getChildPopups(item, stack.items).forEach(function (popup) {
267
+ getChildPopups(item, stack.items).forEach(popup => {
267
268
  PopupStack.bringToTop(popup.element);
268
269
  });
269
270
  setZIndexOfElements(PopupStack.getElements());
270
271
  }
271
272
  else {
272
273
  // not found
273
- var e = new Error();
274
+ const e = new Error();
274
275
  console.warn('Could not find item', e.stack);
275
276
  }
276
277
  },
@@ -285,22 +286,24 @@ export var PopupStack = {
285
286
  * opt-in to toggling. Otherwise there is no way to opt-out of toggle behavior (because the target
286
287
  * is not inside `element`).
287
288
  */
288
- contains: function (element, eventTarget) {
289
+ contains(element, eventTarget) {
289
290
  var _a, _b;
290
- var stack = getTopStack();
291
+ const stack = getTopStack();
291
292
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.contains) {
292
293
  return stack._adapter.contains(element, eventTarget);
293
294
  }
294
- var item = find(stack.items, function (i) { return i.element === element; });
295
- var containsOwnerOfAnotherPopupTargeted = stack.items.some(function (currentItem) {
295
+ const item = stack.items.find(i => i.element === element);
296
+ const containsOwnerOfAnotherPopupTargeted = stack.items.some(currentItem => {
296
297
  var _a;
297
298
  return ((item === null || item === void 0 ? void 0 : item.element.contains(currentItem.owner || null)) &&
298
- (eventTarget === currentItem.owner || ((_a = currentItem.owner) === null || _a === void 0 ? void 0 : _a.contains(eventTarget)) ||
299
+ (eventTarget === currentItem.owner ||
300
+ ((_a = currentItem.owner) === null || _a === void 0 ? void 0 : _a.contains(eventTarget)) ||
299
301
  currentItem.element.contains(eventTarget)));
300
302
  });
301
303
  if (item) {
302
304
  return (containsOwnerOfAnotherPopupTargeted ||
303
- eventTarget === item.owner || ((_b = item.owner) === null || _b === void 0 ? void 0 : _b.contains(eventTarget)) ||
305
+ eventTarget === item.owner ||
306
+ ((_b = item.owner) === null || _b === void 0 ? void 0 : _b.contains(eventTarget)) ||
304
307
  element.contains(eventTarget));
305
308
  }
306
309
  return false;
@@ -312,9 +315,9 @@ export var PopupStack = {
312
315
  * pushing the same element which is very difficult to ensure only one stack is used. To mitigate,
313
316
  * this method filters out multiple calls to push the same element as a new stack context.
314
317
  */
315
- pushStackContext: function (container) {
318
+ pushStackContext(container) {
316
319
  var _a, _b;
317
- var stack = getTopStack();
320
+ const stack = getTopStack();
318
321
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.pushStackContext) {
319
322
  return stack._adapter.pushStackContext(container);
320
323
  }
@@ -322,10 +325,10 @@ export var PopupStack = {
322
325
  if (((_b = stack.container) === null || _b === void 0 ? void 0 : _b.call(stack)) === container) {
323
326
  return;
324
327
  }
325
- var newStack = {
328
+ const newStack = {
326
329
  items: [],
327
330
  zIndex: stack.zIndex,
328
- container: function () { return container; },
331
+ container: () => container,
329
332
  _adapter: {},
330
333
  };
331
334
  stacks.push(newStack);
@@ -335,9 +338,9 @@ export var PopupStack = {
335
338
  * context container element matches to guard against accidental remove of other stack contexts
336
339
  * you don't own.
337
340
  */
338
- popStackContext: function (container) {
341
+ popStackContext(container) {
339
342
  var _a, _b;
340
- var stack = getTopStack();
343
+ const stack = getTopStack();
341
344
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.popStackContext) {
342
345
  return stack._adapter.popStackContext(container);
343
346
  }
@@ -360,19 +363,19 @@ export var PopupStack = {
360
363
  * members of different popup stack contexts which will cause unspecified results (like the escape
361
364
  * key will choose the wrong popup as the "topmost").
362
365
  */
363
- transferToCurrentContext: function (item) {
366
+ transferToCurrentContext(item) {
364
367
  var _a;
365
- var stack = getTopStack();
368
+ const stack = getTopStack();
366
369
  if ((_a = stack._adapter) === null || _a === void 0 ? void 0 : _a.transferToCurrentContext) {
367
370
  return stack._adapter.transferToCurrentContext(item);
368
371
  }
369
- if (find(stack.items, function (i) { return i.element === item.element; })) {
372
+ if (stack.items.find(i => i.element === item.element)) {
370
373
  // The element is already in the stack, don't do anything
371
374
  return;
372
375
  }
373
376
  // Try to find the element in existing stacks. If it exists, we need to first remove from that
374
377
  // stack context
375
- var oldStack = find(stacks, function (stack) { return !!find(stack.items, function (i) { return i.element === item.element; }); });
378
+ const oldStack = stacks.find(stack => !!stack.items.find(i => i.element === item.element));
376
379
  if (oldStack) {
377
380
  PopupStack.remove(item.element);
378
381
  }
@@ -387,20 +390,24 @@ export function resetStack() {
387
390
  stack.items = [];
388
391
  }
389
392
  /**
393
+ * An adapter is a custom implementation of the {@link PopupStack}. There is only ever a single
394
+ * instance of an adapter on the page. It allows an adapter to intercept any `PopupStack` method.
395
+ * This could bypass the internal FILO stack of the `PopupStack` and allows the FILO stack to be
396
+ * handled by something else.
390
397
  *
391
398
  * @param adapter The parts of the PopupStack that we want to override
392
399
  */
393
- export var createAdapter = function (adapter) {
400
+ export const createAdapter = (adapter) => {
394
401
  stack._adapter = adapter;
395
402
  };
396
403
  // keep track of the element ourselves to avoid accidentally popping off someone else's stack
397
404
  // context
398
- var element = null;
405
+ let element = null;
399
406
  // Where should this go? Each version of `PopupStack` on a page will add a listener. The
400
407
  // `PopupStack` should guard against multiple handlers like this simultaneously and there is no
401
408
  // lifecycle here.
402
409
  if (screenfull.isEnabled) {
403
- screenfull.on('change', function () {
410
+ screenfull.on('change', () => {
404
411
  if (screenfull.isFullscreen) {
405
412
  if (screenfull.element) {
406
413
  element = screenfull.element;
package/lib/PopupStack.ts CHANGED
@@ -50,20 +50,6 @@ export function getValue(index: number, length: number): number {
50
50
  return Math.max(min, max - (length - index) + 1);
51
51
  }
52
52
 
53
- // IE11 doesn't support Array.prototype.find, so we'll polyfill here
54
- function find<T>(
55
- items: T[],
56
- predicate: (value: T, index: number, obj: T[]) => boolean
57
- ): T | undefined {
58
- const length = items.length;
59
- for (let i = 0; i < length; i++) {
60
- if (predicate(items[i], i, items)) {
61
- return items[i];
62
- }
63
- }
64
- return;
65
- }
66
-
67
53
  /**
68
54
  * Sets the z-index value of all elements in the stack according to the `getValue` function. This
69
55
  * will be run any time the stack changes.
@@ -82,7 +68,7 @@ function setZIndexOfElements(elements: HTMLElement[]): void {
82
68
  function getOwnerPopup(element: HTMLElement, items: PopupStackItem[]): HTMLElement | undefined {
83
69
  let parentEl: HTMLElement | null = element;
84
70
  do {
85
- const owner = find(items, el => el.element === parentEl);
71
+ const owner = items.find(el => el.element === parentEl);
86
72
  if (owner) {
87
73
  return owner.element;
88
74
  }
@@ -202,6 +188,24 @@ function getTopStack() {
202
188
  return stacks[stacks.length - 1];
203
189
  }
204
190
 
191
+ /**
192
+ * The `PopupStack` is a framework agnostic first-in-last-out (FILO) stack that tracks all popups
193
+ * ("floating UI" or any UI that renders on top of other content). It contains methods that interact
194
+ * with the stack to support all coordinating behaviors of all popups on the page. The `PopupStack`
195
+ * helps:
196
+ *
197
+ * - Render popups in the right order on the page
198
+ * - Helps accessibility with the Escape key (topmost popup is closed)
199
+ * - Handles transition to [Full
200
+ * Screen](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API)
201
+ *
202
+ * The `PopupStack` supports adapters to work with existing popup systems. {@link createAdapter} is
203
+ * exported to accept an adapter. Only a single adapter should be used per page.
204
+ *
205
+ * The `PopupStack` is designed to handle multiple versions of `PopupStack` on the page at once
206
+ * while the internal FILO stack is shared between instances. You should not attempt to use the
207
+ * internal FILO stack. If an adapter is used, the internal FILO stack may be empty.
208
+ */
205
209
  export const PopupStack = {
206
210
  /**
207
211
  * Create a HTMLElement as the container for the popup stack item. The returned element reference
@@ -245,10 +249,7 @@ export const PopupStack = {
245
249
  */
246
250
  remove(element: HTMLElement): void {
247
251
  // Find the stack the popup belongs to.
248
- const stack = find(
249
- stacks,
250
- stack => !!find(PopupStack.getElements(stack), el => el === element)
251
- );
252
+ const stack = stacks.find(stack => !!PopupStack.getElements(stack).find(el => el === element));
252
253
  if (stack) {
253
254
  if (stack._adapter?.remove) {
254
255
  stack._adapter.remove(element);
@@ -310,7 +311,7 @@ export const PopupStack = {
310
311
  stack._adapter.bringToTop(element);
311
312
  return;
312
313
  }
313
- const item = find(stack.items, i => i.element === element);
314
+ const item = stack.items.find(i => i.element === element);
314
315
 
315
316
  if (item) {
316
317
  stack.items = [...stack.items.filter(i => i !== item), item];
@@ -349,7 +350,7 @@ export const PopupStack = {
349
350
  if (stack._adapter?.contains) {
350
351
  return stack._adapter.contains(element, eventTarget);
351
352
  }
352
- const item = find(stack.items, i => i.element === element);
353
+ const item = stack.items.find(i => i.element === element);
353
354
 
354
355
  const containsOwnerOfAnotherPopupTargeted = stack.items.some(currentItem => {
355
356
  return (
@@ -437,14 +438,14 @@ export const PopupStack = {
437
438
  return stack._adapter.transferToCurrentContext(item);
438
439
  }
439
440
 
440
- if (find(stack.items, i => i.element === item.element)) {
441
+ if (stack.items.find(i => i.element === item.element)) {
441
442
  // The element is already in the stack, don't do anything
442
443
  return;
443
444
  }
444
445
 
445
446
  // Try to find the element in existing stacks. If it exists, we need to first remove from that
446
447
  // stack context
447
- const oldStack = find(stacks, stack => !!find(stack.items, i => i.element === item.element));
448
+ const oldStack = stacks.find(stack => !!stack.items.find(i => i.element === item.element));
448
449
  if (oldStack) {
449
450
  PopupStack.remove(item.element);
450
451
  }
@@ -462,6 +463,10 @@ export function resetStack() {
462
463
  }
463
464
 
464
465
  /**
466
+ * An adapter is a custom implementation of the {@link PopupStack}. There is only ever a single
467
+ * instance of an adapter on the page. It allows an adapter to intercept any `PopupStack` method.
468
+ * This could bypass the internal FILO stack of the `PopupStack` and allows the FILO stack to be
469
+ * handled by something else.
465
470
  *
466
471
  * @param adapter The parts of the PopupStack that we want to override
467
472
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workday/canvas-kit-popup-stack",
3
- "version": "7.1.4",
3
+ "version": "7.2.0-427-next.2+2c79134a",
4
4
  "description": "Stack for managing popup UIs to coordinate global concerns like escape key handling and rendering order",
5
5
  "author": "Workday, Inc. (https://www.workday.com)",
6
6
  "license": "Apache-2.0",
@@ -37,5 +37,5 @@
37
37
  "dependencies": {
38
38
  "screenfull": "^5.2.0"
39
39
  },
40
- "gitHead": "6c20e6b9755afa86a865f4e90c24a4a52ea9e481"
40
+ "gitHead": "2c79134aa48ef0efde9cdf883b529b8157337a28"
41
41
  }