@enact/limestone 1.3.0 → 1.10.0

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 (200) hide show
  1. package/.github/workflows/ci-branch.yml +21 -0
  2. package/.github/workflows/ci-pull-request.yml +16 -0
  3. package/.github/workflows/ci-reusable.yml +73 -0
  4. package/ActionGuide/ActionGuide.d.ts +5 -4
  5. package/ActionGuide/ActionGuide.module.css +1 -1
  6. package/Alert/Alert.d.ts +13 -2
  7. package/Alert/Alert.js +39 -5
  8. package/Alert/Alert.module.css +48 -1
  9. package/Alert/tests/Alert-specs.js +91 -0
  10. package/BodyText/BodyText.d.ts +5 -4
  11. package/BodyText/BodyText.module.css +7 -7
  12. package/Button/Button.d.ts +17 -12
  13. package/Button/Button.js +1 -1
  14. package/Button/Button.module.css +195 -268
  15. package/Button/tests/Button-specs.js +26 -0
  16. package/CHANGELOG.md +254 -0
  17. package/Card/Card.d.ts +40 -12
  18. package/Card/Card.js +164 -28
  19. package/Card/Card.module.css +277 -58
  20. package/Card/tests/Card-specs.js +67 -3
  21. package/Checkbox/Checkbox.d.ts +8 -7
  22. package/Checkbox/Checkbox.js +3 -1
  23. package/Checkbox/Checkbox.module.css +213 -120
  24. package/Checkbox/tests/Checkbox-specs.js +1 -1
  25. package/CheckboxItem/CheckboxItem.d.ts +22 -7
  26. package/CheckboxItem/CheckboxItem.js +71 -4
  27. package/Chips/Chip.js +72 -13
  28. package/Chips/Chip.module.css +3 -3
  29. package/Chips/Chips.js +37 -17
  30. package/Chips/Chips.module.css +1 -1
  31. package/Chips/tests/Chip-specs.js +43 -13
  32. package/Chips/tests/Chips-specs.js +31 -21
  33. package/ColorPicker/ColorPicker.js +27 -25
  34. package/ContextualMenuDecorator/ContextualMenuDecorator.d.ts +4 -5
  35. package/ContextualPopupDecorator/ContextualPopup.module.css +34 -34
  36. package/ContextualPopupDecorator/ContextualPopupDecorator.js +567 -549
  37. package/DatePicker/DatePicker.d.ts +4 -5
  38. package/DayPicker/DayPicker.d.ts +8 -7
  39. package/DayPicker/DaySelectorDecorator.js +12 -7
  40. package/Dropdown/Dropdown.d.ts +11 -13
  41. package/Dropdown/Dropdown.module.css +13 -9
  42. package/Dropdown/DropdownList.js +80 -54
  43. package/FixedPopupPanels/FixedPopupPanels.d.ts +4 -2
  44. package/FixedPopupPanels/FixedPopupPanels.module.css +18 -18
  45. package/FlexiblePopupPanels/FlexiblePopupPanels.module.css +23 -23
  46. package/FlexiblePopupPanels/useNavButtonFocus.js +7 -10
  47. package/FormCheckboxItem/FormCheckboxItem.d.ts +5 -4
  48. package/Heading/Heading.d.ts +9 -8
  49. package/Heading/Heading.js +2 -2
  50. package/Heading/Heading.module.css +5 -5
  51. package/Icon/Icon.d.ts +15 -4
  52. package/Icon/Icon.js +49 -2
  53. package/Icon/Icon.module.css +1 -1
  54. package/Icon/IconList.js +27 -1
  55. package/IconItem/IconItem.d.ts +13 -12
  56. package/IconItem/IconItem.js +15 -0
  57. package/IconItem/IconItem.module.css +107 -1
  58. package/IconItem/tests/IconItem-specs.js +30 -1
  59. package/Image/Image.d.ts +5 -4
  60. package/Image/Image.js +6 -4
  61. package/ImageItem/ImageItem.d.ts +11 -10
  62. package/ImageItem/ImageItem.js +37 -31
  63. package/ImageItem/ImageItem.module.css +30 -30
  64. package/ImageItem/tests/ImageItem-specs.js +3 -10
  65. package/Input/Input.js +21 -3
  66. package/Input/Input.module.css +37 -8
  67. package/Input/InputField.js +79 -24
  68. package/Input/InputField.module.css +273 -41
  69. package/Input/InputFieldDecoratorIcon.js +1 -0
  70. package/Input/InputFieldSpotlightDecorator.js +257 -228
  71. package/Input/index.d.ts +120 -111
  72. package/Input/tests/Input-specs.js +26 -0
  73. package/Input/tests/InputField-specs.js +170 -3
  74. package/Input/tests/InputPopup-specs.js +1 -1
  75. package/Item/Item.d.ts +16 -9
  76. package/Item/Item.js +20 -2
  77. package/Item/Item.module.css +1 -1
  78. package/KeyGuide/KeyGuide.d.ts +8 -7
  79. package/KeyGuide/KeyGuide.js +29 -27
  80. package/KeyGuide/KeyGuide.module.css +25 -1
  81. package/Marquee/Marquee.d.ts +2 -4
  82. package/MediaOverlay/MediaOverlay.d.ts +12 -11
  83. package/MediaOverlay/MediaOverlay.js +43 -21
  84. package/MediaOverlay/MediaOverlay.module.css +114 -15
  85. package/MediaOverlay/tests/MediaOverlay-specs.js +29 -0
  86. package/MediaPlayer/MediaControls.js +195 -13
  87. package/MediaPlayer/MediaControls.module.css +3 -2
  88. package/MediaPlayer/MediaSlider.module.css +7 -20
  89. package/MediaPlayer/index.d.ts +59 -7
  90. package/MediaPlayer/tests/util-specs.js +4 -1
  91. package/PageViews/PageViews.js +232 -82
  92. package/PageViews/PageViews.module.css +3 -0
  93. package/PageViews/PageViewsRouter.js +100 -42
  94. package/PageViews/tests/PageViews-specs.js +171 -0
  95. package/Panels/Header.js +54 -34
  96. package/Panels/Header.module.css +83 -31
  97. package/Panels/Panel.module.css +1 -1
  98. package/Panels/index.d.ts +7 -8
  99. package/Picker/Picker.d.ts +4 -5
  100. package/Picker/Picker.module.css +2 -2
  101. package/Popup/Popup.js +245 -242
  102. package/Popup/Popup.module.css +24 -24
  103. package/PopupTabLayout/PopupTabLayout.d.ts +5 -7
  104. package/PopupTabLayout/PopupTabLayout.js +26 -18
  105. package/PopupTabLayout/PopupTabLayout.module.css +53 -16
  106. package/PopupTabLayout/PopupTabLayoutStateContext.js +8 -0
  107. package/ProgressBar/ProgressBar.d.ts +5 -4
  108. package/ProgressBar/ProgressBarTooltip.module.css +12 -12
  109. package/ProgressButton/ProgressButton.d.ts +4 -5
  110. package/QuickGuidePanels/QuickGuidePanels.module.css +2 -2
  111. package/RadioItem/RadioItem.d.ts +18 -5
  112. package/RadioItem/RadioItem.js +69 -2
  113. package/RadioItem/RadioItem.module.css +36 -36
  114. package/RangePicker/RangePicker.module.css +2 -2
  115. package/Scroller/EditableWrapper.js +28 -18
  116. package/Scroller/Scroller.d.ts +20 -16
  117. package/Scroller/Scroller.js +20 -13
  118. package/Scroller/Scroller.module.css +4 -4
  119. package/Scroller/useThemeScroller.js +3 -3
  120. package/Slider/Slider.d.ts +20 -14
  121. package/Slider/Slider.js +71 -14
  122. package/Slider/Slider.module.css +464 -91
  123. package/Slider/SliderBehaviorDecorator.js +16 -14
  124. package/Slider/tests/Slider-specs.js +53 -1
  125. package/Slider/utils.js +23 -7
  126. package/Spinner/Spinner.d.ts +5 -4
  127. package/Spinner/Spinner.js +10 -8
  128. package/Spinner/Spinner.module.css +9 -9
  129. package/Steps/Steps.d.ts +5 -4
  130. package/Steps/Steps.js +9 -5
  131. package/Switch/Switch.d.ts +8 -7
  132. package/Switch/Switch.module.css +100 -13
  133. package/SwitchItem/SwitchItem.d.ts +9 -6
  134. package/TabLayout/RefocusDecorator.js +26 -18
  135. package/TabLayout/TabGroup.js +3 -2
  136. package/TabLayout/TabGroup.module.css +2 -2
  137. package/TabLayout/TabLayout.d.ts +6 -0
  138. package/TabLayout/TabLayout.js +11 -1
  139. package/TabLayout/TabLayout.module.css +18 -0
  140. package/TabLayout/tests/TabGroup-specs.js +1 -1
  141. package/TabLayout/tests/TabLayout-specs.js +52 -0
  142. package/ThemeDecorator/AccessibilityDecorator.js +12 -11
  143. package/ThemeDecorator/I18nFontDecorator.js +6 -4
  144. package/ThemeDecorator/ThemeDecorator.d.ts +16 -10
  145. package/ThemeDecorator/ThemeDecorator.js +24 -9
  146. package/ThemeDecorator/fontGenerator.js +1 -1
  147. package/ThemeDecorator/screenTypes.json +1 -0
  148. package/TimePicker/TimePicker.module.css +1 -1
  149. package/TimePicker/TimePickerBase.js +5 -3
  150. package/TooltipDecorator/Tooltip.module.css +1 -2
  151. package/TooltipDecorator/TooltipDecorator.js +12 -7
  152. package/TooltipDecorator/tests/useTooltip-specs.js +5 -2
  153. package/TooltipDecorator/tests/util-specs.js +12 -0
  154. package/TooltipDecorator/useTooltip.js +1 -1
  155. package/TooltipDecorator/util.js +18 -11
  156. package/VideoPlayer/Feedback.js +3 -0
  157. package/VideoPlayer/Feedback.module.css +5 -9
  158. package/VideoPlayer/FeedbackIcons.js +1 -1
  159. package/VideoPlayer/FeedbackTooltip.module.css +55 -11
  160. package/VideoPlayer/VideoPlayer.d.ts +44 -18
  161. package/VideoPlayer/VideoPlayer.js +153 -47
  162. package/VideoPlayer/VideoPlayer.module.css +28 -11
  163. package/VirtualList/VirtualList.d.ts +9 -2
  164. package/VirtualList/VirtualList.js +51 -24
  165. package/VirtualList/tests/VirtualGridList-translate-specs.js +3 -0
  166. package/VirtualList/tests/VirtualList-specs.js +28 -1
  167. package/VirtualList/tests/VirtualList-translate-specs.js +4 -1
  168. package/VirtualList/useSpotlight.js +1 -1
  169. package/WizardPanels/WizardPanels.module.css +2 -2
  170. package/WizardPanels/index.d.ts +4 -2
  171. package/fonts/Limestone_Icons.ttf +0 -0
  172. package/internal/$L/$L.js +3 -3
  173. package/internal/AsyncRenderChildren/AsyncRenderChildren.js +9 -5
  174. package/internal/AsyncRenderChildren/tests/AsyncRenderChildren-specs.js +4 -1
  175. package/internal/DateComponentPicker/DateComponentPicker.module.css +2 -2
  176. package/internal/DateTime/DateTime.module.css +1 -0
  177. package/internal/DateTime/DateTimeDecorator.js +5 -4
  178. package/internal/Panels/PanelsRouter.js +48 -31
  179. package/internal/Panels/useAutoFocus.js +10 -6
  180. package/internal/Panels/useFocusOnTransition.js +4 -3
  181. package/internal/Picker/Picker.js +7 -5
  182. package/internal/Picker/Picker.module.css +2 -2
  183. package/internal/Picker/SpottablePicker.js +15 -13
  184. package/internal/SharedStateDecorator/SharedStateDecorator.js +78 -99
  185. package/internal/validators/validators.js +21 -2
  186. package/package.json +18 -15
  187. package/styles/colors-highcontrast.less +9 -1
  188. package/styles/colors.less +12 -7
  189. package/styles/motion-mixins.less +66 -0
  190. package/styles/motions.less +78 -0
  191. package/styles/variables.less +176 -150
  192. package/useScroll/HoverToScroll.js +23 -17
  193. package/useScroll/Scrollbar.js +14 -10
  194. package/useScroll/ScrollbarPlaceholder.js +3 -5
  195. package/useScroll/ScrollbarTrack.js +7 -5
  196. package/useScroll/ScrollbarTrack.module.css +8 -8
  197. package/useScroll/useEvent.js +14 -3
  198. package/useScroll/useScroll.js +12 -2
  199. package/useScroll/useScroll.module.css +6 -6
  200. package/.travis.yml +0 -40
@@ -35,6 +35,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default":
35
35
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
36
36
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
37
37
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
38
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
39
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
38
40
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
39
41
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
40
42
  function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
@@ -42,19 +44,7 @@ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructur
42
44
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
43
45
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
44
46
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
45
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
46
- function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
47
- function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
48
- function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
49
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
50
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
51
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
52
- function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
53
- function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
54
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
55
- function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
56
- function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
57
- function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } /* global MutationObserver ResizeObserver */ /**
47
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } /* global MutationObserver ResizeObserver */ /**
58
48
  * A higher-order component to add a Limestone styled popup to a component.
59
49
  *
60
50
  * @module limestone/ContextualPopupDecorator
@@ -106,576 +96,611 @@ var defaultConfig = {
106
96
  */
107
97
  openProp: 'selected'
108
98
  };
99
+ var contextualPopupDecoratorDefaultProps = {
100
+ 'data-webos-voice-exclusive': true,
101
+ direction: 'below center',
102
+ noAutoDismiss: false,
103
+ offset: 'small',
104
+ open: false,
105
+ scrimType: 'none',
106
+ spotlightRestrict: 'self-first'
107
+ };
109
108
  var ContextualPopupContainer = (0, _SpotlightContainerDecorator["default"])({
110
109
  enterTo: 'default-element',
111
110
  preserveId: true
112
111
  }, _ContextualPopup.ContextualPopup);
113
112
  var Decorator = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) {
114
- var _Class;
115
113
  var noArrow = config.noArrow,
116
114
  noSkin = config.noSkin,
117
115
  openProp = config.openProp;
118
116
  var WrappedWithRef = (0, _WithRef.WithRef)(Wrapped);
119
- return _Class = /*#__PURE__*/function (_Component) {
120
- function _Class(props) {
121
- var _this;
122
- _classCallCheck(this, _Class);
123
- _this = _callSuper(this, _Class, [props]);
124
- _this.generateId = function () {
125
- return Math.random().toString(36).substring(2, 10);
126
- };
127
- _this.getContainerAdjustedPosition = function () {
128
- var position = _this.adjustedDirection;
129
- var arr = _this.adjustedDirection.split(' ');
130
- var direction = null;
131
- var anchor = null;
132
- if (arr.length === 2) {
133
- var _arr = _slicedToArray(arr, 2);
134
- direction = _arr[0];
135
- anchor = _arr[1];
136
- } else {
137
- direction = position;
138
- }
139
- return {
140
- anchor: anchor,
141
- direction: direction
142
- };
117
+
118
+ // eslint-disable-next-line no-shadow
119
+ var _ContextualPopupDecorator = function ContextualPopupDecorator(props) {
120
+ (0, _util.checkPropTypes)(_ContextualPopupDecorator, props);
121
+ var componentProps = (0, _util.setDefaultProps)(props, contextualPopupDecoratorDefaultProps);
122
+ var _useState = (0, _react.useState)(null),
123
+ _useState2 = _slicedToArray(_useState, 2),
124
+ activator = _useState2[0],
125
+ setActivator = _useState2[1];
126
+ var _useState3 = (0, _react.useState)({
127
+ top: 0,
128
+ left: 0
129
+ }),
130
+ _useState4 = _slicedToArray(_useState3, 2),
131
+ arrowPosition = _useState4[0],
132
+ setArrowPosition = _useState4[1];
133
+ var _useState5 = (0, _react.useState)({
134
+ top: 0,
135
+ left: 0,
136
+ right: 0
137
+ }),
138
+ _useState6 = _slicedToArray(_useState5, 2),
139
+ containerPosition = _useState6[0],
140
+ setContainerPosition = _useState6[1];
141
+ var _useState7 = (0, _react.useState)(componentProps.direction),
142
+ _useState8 = _slicedToArray(_useState7, 2),
143
+ direction = _useState8[0],
144
+ setDirection = _useState8[1];
145
+ var _useState9 = (0, _react.useState)(null),
146
+ _useState0 = _slicedToArray(_useState9, 2),
147
+ holeBounds = _useState0[0],
148
+ setHoleBounds = _useState0[1];
149
+ var adjustedDirection = (0, _react.useRef)(componentProps.direction);
150
+ var containerNode = (0, _react.useRef)(null);
151
+ var clientSiblingRef = (0, _react.useRef)(null);
152
+ var overflow = (0, _react.useRef)({});
153
+ var mutationObserver = (0, _react.useRef)(null);
154
+ var prevProps = (0, _react.useRef)(componentProps);
155
+ var snapshot = (0, _react.useRef)(null);
156
+ var resizeObserver = (0, _react.useRef)(null);
157
+ var findClientSiblingRef = (0, _react.useRef)(null);
158
+ var keyDownRef = (0, _react.useRef)(null);
159
+ var keyUpRef = (0, _react.useRef)(null);
160
+ var containerId = (0, _react.useMemo)(function () {
161
+ return _spotlight["default"].add(componentProps.popupSpotlightId);
162
+ }, [componentProps.popupSpotlightId]);
163
+ if (componentProps.setApiProvider) {
164
+ componentProps.setApiProvider();
165
+ }
166
+ var distances = (0, _react.useCallback)(function () {
167
+ var MARGIN = _resolution["default"].scale(noArrow ? 0 : 12);
168
+ var ARROW_WIDTH = noArrow ? 0 : _resolution["default"].scale(60); // svg arrow width.
169
+ var ARROW_OFFSET = noArrow ? 0 : _resolution["default"].scale(36); // actual distance of the svg arrow displayed to offset overlaps with the container. Offset is when `noArrow` is false.
170
+ var KEEPOUT = _resolution["default"].scale(24); // keep out distance on the edge of the screen
171
+
172
+ return {
173
+ ARROW_OFFSET: ARROW_OFFSET,
174
+ ARROW_WIDTH: ARROW_WIDTH,
175
+ KEEPOUT: KEEPOUT,
176
+ MARGIN: MARGIN
143
177
  };
144
- /**
145
- * Position the popup in relation to the activator.
146
- *
147
- * Position is based on the dimensions of the popup and its activator. If the popup does not
148
- * fit in the specified direction, it will automatically flip to the opposite direction.
149
- *
150
- * @method
151
- * @memberof limestone/ContextualPopupDecorator.ContextualPopupDecorator.prototype
152
- * @public
153
- * @returns {undefined}
154
- */
155
- _this.positionContextualPopup = function () {
156
- var _this$clientSiblingRe;
157
- if (_this.containerNode && (_this$clientSiblingRe = _this.clientSiblingRef) !== null && _this$clientSiblingRe !== void 0 && _this$clientSiblingRe.current) {
158
- var containerNode = _this.containerNode.getBoundingClientRect();
159
- var _this$clientSiblingRe2 = _this.clientSiblingRef.current.getBoundingClientRect(),
160
- top = _this$clientSiblingRe2.top,
161
- left = _this$clientSiblingRe2.left,
162
- bottom = _this$clientSiblingRe2.bottom,
163
- right = _this$clientSiblingRe2.right,
164
- width = _this$clientSiblingRe2.width,
165
- height = _this$clientSiblingRe2.height;
166
- var clientNode = {
167
- top: top,
168
- left: left,
169
- bottom: bottom,
170
- right: right,
171
- width: width,
172
- height: height
173
- };
174
- clientNode.left = _this.props.rtl ? window.innerWidth - right : left;
175
- clientNode.right = _this.props.rtl ? window.innerWidth - left : right;
176
- _this.calcOverflow(containerNode, clientNode);
177
- _this.adjustDirection();
178
- var arrowPosition = _this.getArrowPosition(containerNode, clientNode),
179
- containerPosition = _this.getContainerPosition(containerNode, clientNode);
180
- if (_this.state.direction !== _this.adjustedDirection || _this.state.arrowPosition.left !== arrowPosition.left || _this.state.arrowPosition.top !== arrowPosition.top || _this.state.containerPosition.left !== containerPosition.left || _this.state.containerPosition.right !== containerPosition.right || _this.state.containerPosition.top !== containerPosition.top) {
181
- _this.setState({
182
- direction: _this.adjustedDirection,
183
- arrowPosition: arrowPosition,
184
- containerPosition: containerPosition
185
- });
186
- }
187
- }
178
+ }, []);
179
+ var generateId = (0, _react.useCallback)(function () {
180
+ return Math.random().toString(36).substring(2, 10);
181
+ }, []);
182
+ var id = (0, _react.useMemo)(function () {
183
+ return generateId();
184
+ }, [generateId]);
185
+ var adjustRTL = (0, _react.useCallback)(function (position) {
186
+ var pos = position;
187
+ if (componentProps.rtl) {
188
+ var tmpLeft = pos.left;
189
+ pos.left = pos.right;
190
+ pos.right = tmpLeft;
191
+ }
192
+ return pos;
193
+ }, [componentProps]);
194
+ var getContainerAdjustedPosition = (0, _react.useCallback)(function () {
195
+ var position = adjustedDirection.current;
196
+ var arr = adjustedDirection.current.split(' ');
197
+ var localDirection;
198
+ var anchor = null;
199
+ if (arr.length === 2) {
200
+ var _arr = _slicedToArray(arr, 2);
201
+ localDirection = _arr[0];
202
+ anchor = _arr[1];
203
+ } else {
204
+ localDirection = position;
205
+ }
206
+ return {
207
+ anchor: anchor,
208
+ localDirection: localDirection
188
209
  };
189
- _this.getContainerNode = function (node) {
190
- _this.containerNode = node;
191
- if (_this.resizeObserver) {
192
- if (node) {
193
- var _node$parentElement;
194
- // It is not easy to trigger changed position of activator,
195
- // so we chose to observe the `div` element's size that has the real size below the root of floatLayer.
196
- // This implementation is dependent on the current structure of FloatingLayer,
197
- // so if the structure have changed, below code needs to be changed accordingly.
198
- _this.resizeObserver.observe(node === null || node === void 0 || (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.parentElement);
199
- } else {
200
- _this.resizeObserver.disconnect();
201
- }
202
- }
203
- if (_this.mutationObserver) {
204
- if (node) {
205
- _this.mutationObserver.observe(document.body, {
206
- attributes: false,
207
- childList: true,
208
- subtree: true
209
- });
210
+ }, []);
211
+ var centerContainerPosition = (0, _react.useCallback)(function (localContainerNode, clientNode) {
212
+ var pos = {};
213
+ var _distances = distances(),
214
+ KEEPOUT = _distances.KEEPOUT;
215
+ var _getContainerAdjusted = getContainerAdjustedPosition(),
216
+ anchor = _getContainerAdjusted.anchor,
217
+ localDirection = _getContainerAdjusted.localDirection;
218
+ if (localDirection === 'above' || localDirection === 'below') {
219
+ if (overflow.current.isOverLeft) {
220
+ // anchor to the left of the screen
221
+ pos.left = KEEPOUT;
222
+ } else if (overflow.current.isOverRight) {
223
+ // anchor to the right of the screen
224
+ pos.left = window.innerWidth - localContainerNode.width - KEEPOUT;
225
+ } else if (anchor) {
226
+ if (anchor === 'center') {
227
+ // center horizontally
228
+ pos.left = clientNode.left + (clientNode.width - localContainerNode.width) / 2;
229
+ } else if (anchor === 'left') {
230
+ // anchor to the left side of the activator
231
+ pos.left = clientNode.left;
210
232
  } else {
211
- _this.mutationObserver.disconnect();
233
+ // anchor to the right side of the activator
234
+ pos.left = clientNode.right - localContainerNode.width;
212
235
  }
236
+ } else {
237
+ // anchor to the left side of the activator, matching its width
238
+ pos.left = clientNode.left;
239
+ pos.width = clientNode.width;
213
240
  }
214
- };
215
- _this.handle = _handle.handle.bind(_this);
216
- _this.handleKeyUp = _this.handle((0, _handle.forProp)('open', true), (0, _handle.forKey)('enter'), function () {
217
- return _spotlight["default"].getCurrent() === _this.state.activator;
218
- }, _handle.stop, (0, _handle.forwardCustom)('onClose'));
219
- _this.handleOpen = function (ev) {
220
- (0, _handle.forward)('onOpen', ev, _this.props);
221
- _this.positionContextualPopup();
222
- var current = _spotlight["default"].getCurrent();
223
- _this.updateLeaveFor(current);
224
- _this.setState({
225
- activator: current
226
- }, function () {
227
- return _this.spotPopupContent();
228
- });
229
- };
230
- _this.handleClose = function () {
231
- _this.updateLeaveFor(null);
232
- _this.setState({
233
- activator: null
234
- });
235
- };
236
- _this.handleDismiss = function () {
237
- (0, _handle.forwardCustom)('onClose')(null, _this.props);
238
- };
239
- // handle key event from outside (i.e. the activator) to the popup container
240
- _this.handleKeyDown = function (ev) {
241
- var _this$state = _this.state,
242
- activator = _this$state.activator,
243
- containerId = _this$state.containerId;
244
- var spotlightRestrict = _this.props.spotlightRestrict;
245
- var current = _spotlight["default"].getCurrent();
246
- var direction = (0, _spotlight.getDirection)(ev.keyCode);
247
- if (!direction) return;
248
- var hasSpottables = _spotlight["default"].getSpottableDescendants(containerId).length > 0;
249
- var spotlessSpotlightModal = spotlightRestrict === 'self-only' && !hasSpottables;
250
- var shouldSpotPopup = current === activator && direction === PositionToDirection[_this.adjustedDirection.split(' ')[0]] && hasSpottables;
251
- if (shouldSpotPopup || spotlessSpotlightModal) {
252
- _this.handleDirectionalKey(ev);
253
-
254
- // we guard against attempting a focus change by verifying the case where a
255
- // spotlightModal popup contains no spottable components
256
- if (!spotlessSpotlightModal && shouldSpotPopup) {
257
- _this.spotPopupContent();
258
- }
259
- }
260
- };
261
- // handle key event from contextual popup and closes the popup
262
- _this.handleContainerKeyDown = function (ev) {
263
- // Note: Container will be only rendered if `open`ed, therefore no need to check for `open`
264
- var direction = (0, _spotlight.getDirection)(ev.keyCode);
265
- if (!direction) return;
266
- _this.handleDirectionalKey(ev);
267
-
268
- // if focus moves outside the popup's container, issue the `onClose` event
269
- if (_spotlight["default"].move(direction) && !_this.containerNode.contains(_spotlight["default"].getCurrent())) {
270
- (0, _handle.forwardCustom)('onClose')(null, _this.props);
271
- }
272
- };
273
- _this.spotActivator = function (activator) {
274
- if (!_spotlight["default"].getPointerMode() && activator && activator === _spotlight["default"].getCurrent()) {
275
- activator.blur();
276
- }
277
- if (!_spotlight["default"].focus(activator)) {
278
- _spotlight["default"].focus();
241
+ } else if (localDirection === 'left' || localDirection === 'right') {
242
+ if (overflow.current.isOverTop) {
243
+ // anchor to the top of the screen
244
+ pos.top = KEEPOUT;
245
+ } else if (overflow.current.isOverBottom) {
246
+ // anchor to the bottom of the screen
247
+ pos.top = window.innerHeight - localContainerNode.height - KEEPOUT;
248
+ } else if (anchor === 'middle') {
249
+ // center vertically
250
+ pos.top = clientNode.top - (localContainerNode.height - clientNode.height) / 2;
251
+ } else if (anchor === 'top') {
252
+ // anchor to the top of the activator
253
+ pos.top = clientNode.top;
254
+ } else {
255
+ // anchor to the bottom of the activator
256
+ pos.top = clientNode.bottom - localContainerNode.height;
279
257
  }
280
- };
281
- _this.spotPopupContent = function () {
282
- var spotlightRestrict = _this.props.spotlightRestrict;
283
- var containerId = _this.state.containerId;
284
- var spottableDescendants = _spotlight["default"].getSpottableDescendants(containerId);
285
- if (spotlightRestrict === 'self-only' && spottableDescendants.length && _spotlight["default"].getCurrent()) {
286
- _spotlight["default"].getCurrent().blur();
258
+ }
259
+ return pos;
260
+ }, [distances, getContainerAdjustedPosition]);
261
+ var getContainerNodeWidth = (0, _react.useCallback)(function () {
262
+ return containerNode.current && containerNode.current.getBoundingClientRect().width || 0;
263
+ }, []);
264
+ var updateLeaveFor = (0, _react.useCallback)(function (localActivator) {
265
+ _spotlight["default"].set(containerId, {
266
+ leaveFor: {
267
+ up: localActivator,
268
+ down: localActivator,
269
+ left: localActivator,
270
+ right: localActivator
287
271
  }
288
- if (!_spotlight["default"].focus(containerId)) {
289
- _spotlight["default"].setActiveContainer(containerId);
272
+ });
273
+ }, [containerId]);
274
+ var getContainerPosition = (0, _react.useCallback)(function (localContainerNode, clientNode) {
275
+ var _distances2 = distances(),
276
+ ARROW_OFFSET = _distances2.ARROW_OFFSET,
277
+ MARGIN = _distances2.MARGIN;
278
+ var position = centerContainerPosition(localContainerNode, clientNode);
279
+ var _getContainerAdjusted2 = getContainerAdjustedPosition(),
280
+ localDirection = _getContainerAdjusted2.localDirection;
281
+ switch (localDirection) {
282
+ case 'above':
283
+ position.top = clientNode.top - ARROW_OFFSET - localContainerNode.height - MARGIN;
284
+ break;
285
+ case 'below':
286
+ position.top = clientNode.bottom + ARROW_OFFSET + MARGIN;
287
+ break;
288
+ case 'right':
289
+ position.left = componentProps.rtl ? clientNode.left - localContainerNode.width - ARROW_OFFSET - MARGIN : clientNode.right + ARROW_OFFSET + MARGIN;
290
+ break;
291
+ case 'left':
292
+ position.left = componentProps.rtl ? clientNode.right + ARROW_OFFSET + MARGIN : clientNode.left - localContainerNode.width - ARROW_OFFSET - MARGIN;
293
+ break;
294
+ }
295
+ return adjustRTL(position);
296
+ }, [adjustRTL, centerContainerPosition, componentProps, distances, getContainerAdjustedPosition]);
297
+ var getArrowPosition = (0, _react.useCallback)(function (localContainerNode, clientNode) {
298
+ var _distances3 = distances(),
299
+ ARROW_WIDTH = _distances3.ARROW_WIDTH,
300
+ KEEPOUT = _distances3.KEEPOUT,
301
+ MARGIN = _distances3.MARGIN;
302
+ var position = {};
303
+ var _getContainerAdjusted3 = getContainerAdjustedPosition(),
304
+ anchor = _getContainerAdjusted3.anchor,
305
+ localDirection = _getContainerAdjusted3.localDirection;
306
+ if (localDirection === 'above' || localDirection === 'below') {
307
+ if (overflow.current.isOverRight && !overflow.current.isOverLeft) {
308
+ position.left = window.innerWidth - (localContainerNode.width + ARROW_WIDTH) / 2 - KEEPOUT;
309
+ } else if (!overflow.current.isOverRight && overflow.current.isOverLeft) {
310
+ position.left = (localContainerNode.width - ARROW_WIDTH) / 2 + KEEPOUT;
311
+ } else if (anchor === 'left') {
312
+ position.left = clientNode.left + (localContainerNode.width - ARROW_WIDTH) / 2;
313
+ } else if (anchor === 'right') {
314
+ position.left = clientNode.right - localContainerNode.width + (localContainerNode.width - ARROW_WIDTH) / 2;
315
+ } else {
316
+ position.left = clientNode.left + (clientNode.width - ARROW_WIDTH) / 2;
290
317
  }
318
+ } else if (overflow.current.isOverBottom && !overflow.current.isOverTop) {
319
+ position.top = window.innerHeight - (localContainerNode.height + ARROW_WIDTH) / 2 - KEEPOUT;
320
+ } else if (!overflow.current.isOverBottom && overflow.current.isOverTop) {
321
+ position.top = (localContainerNode.height - ARROW_WIDTH) / 2 + KEEPOUT;
322
+ } else if (anchor === 'top') {
323
+ position.top = clientNode.top + (localContainerNode.height - ARROW_WIDTH) / 2;
324
+ } else if (anchor === 'bottom') {
325
+ position.top = clientNode.bottom - localContainerNode.height + (localContainerNode.height - ARROW_WIDTH) / 2;
326
+ } else {
327
+ position.top = clientNode.top + (clientNode.height - ARROW_WIDTH) / 2;
328
+ }
329
+ switch (localDirection) {
330
+ case 'above':
331
+ position.top = clientNode.top - ARROW_WIDTH - MARGIN;
332
+ break;
333
+ case 'below':
334
+ position.top = clientNode.bottom + MARGIN;
335
+ break;
336
+ case 'left':
337
+ position.left = componentProps.rtl ? clientNode.left + clientNode.width + MARGIN : clientNode.left - ARROW_WIDTH - MARGIN;
338
+ break;
339
+ case 'right':
340
+ position.left = componentProps.rtl ? clientNode.left - ARROW_WIDTH - MARGIN : clientNode.left + clientNode.width + MARGIN;
341
+ break;
342
+ default:
343
+ return {};
344
+ }
345
+ return adjustRTL(position);
346
+ }, [adjustRTL, componentProps, distances, getContainerAdjustedPosition]);
347
+ var adjustInlineOverflow = (0, _react.useCallback)(function (localDirection, previousOverflow, currentOverflow) {
348
+ if (currentOverflow.isOverRight && currentOverflow.isOverLeft && (localDirection === 'above' || localDirection === 'below')) {
349
+ overflow.current = previousOverflow;
350
+ } else {
351
+ overflow.current = currentOverflow;
352
+ }
353
+ }, []);
354
+ var calcOverflow = (0, _react.useCallback)(function (container, client) {
355
+ var containerHeight, containerWidth;
356
+ var _distances4 = distances(),
357
+ ARROW_OFFSET = _distances4.ARROW_OFFSET,
358
+ KEEPOUT = _distances4.KEEPOUT,
359
+ MARGIN = _distances4.MARGIN;
360
+ var _getContainerAdjusted4 = getContainerAdjustedPosition(),
361
+ anchor = _getContainerAdjusted4.anchor,
362
+ localDirection = _getContainerAdjusted4.localDirection;
363
+ if (localDirection === 'above' || localDirection === 'below') {
364
+ containerHeight = container.height;
365
+ containerWidth = anchor ? (container.width - client.width) / 2 : 0;
366
+ } else {
367
+ containerHeight = (container.height - client.height) / 2;
368
+ containerWidth = container.width;
369
+ }
370
+ var currentOverflow = {
371
+ isOverTop: anchor === 'top' && (localDirection === 'left' || localDirection === 'right') ? !(client.top > KEEPOUT) : client.top - containerHeight - ARROW_OFFSET - MARGIN - KEEPOUT < 0,
372
+ isOverBottom: anchor === 'bottom' && (localDirection === 'left' || localDirection === 'right') ? client.bottom + KEEPOUT > window.innerHeight : client.bottom + containerHeight + ARROW_OFFSET + MARGIN + KEEPOUT > window.innerHeight,
373
+ isOverLeft: anchor === 'left' && (localDirection === 'above' || localDirection === 'below') ? !(client.left > KEEPOUT) : client.left - containerWidth - ARROW_OFFSET - MARGIN - KEEPOUT < 0,
374
+ isOverRight: anchor === 'right' && (localDirection === 'above' || localDirection === 'below') ? client.right + KEEPOUT > window.innerWidth : client.right + containerWidth + ARROW_OFFSET + MARGIN + KEEPOUT > window.innerWidth
291
375
  };
292
- _this.state = {
293
- arrowPosition: {
294
- top: 0,
295
- left: 0
296
- },
297
- containerPosition: {
298
- top: 0,
299
- left: 0,
300
- right: 0
301
- },
302
- containerId: _spotlight["default"].add(_this.props.popupSpotlightId),
303
- activator: null
304
- };
305
- _this.resizeObserver = null;
306
- _this.overflow = {};
307
- _this.adjustedDirection = _this.props.direction;
308
- _this.id = _this.generateId();
309
- _this.clientSiblingRef = /*#__PURE__*/(0, _react.createRef)(null);
310
- _this.findClientSiblingRef = /*#__PURE__*/(0, _react.createRef)(null);
311
- _this.MARGIN = _resolution["default"].scale(noArrow ? 0 : 12);
312
- _this.ARROW_WIDTH = noArrow ? 0 : _resolution["default"].scale(60); // svg arrow width. used for arrow positioning
313
- _this.ARROW_OFFSET = noArrow ? 0 : _resolution["default"].scale(36); // actual distance of the svg arrow displayed to offset overlaps with the container. Offset is when `noArrow` is false.
314
- _this.KEEPOUT = _resolution["default"].scale(24); // keep out distance on the edge of the screen
315
-
316
- if (props.setApiProvider) {
317
- props.setApiProvider(_this);
376
+ adjustInlineOverflow(localDirection, overflow.current, currentOverflow);
377
+ }, [adjustInlineOverflow, distances, getContainerAdjustedPosition]);
378
+ var adjustDirection = (0, _react.useCallback)(function () {
379
+ var _getContainerAdjusted5 = getContainerAdjustedPosition(),
380
+ anchor = _getContainerAdjusted5.anchor,
381
+ localDirection = _getContainerAdjusted5.localDirection;
382
+ if (overflow.current.isOverTop && !overflow.current.isOverBottom && localDirection === 'above') {
383
+ adjustedDirection.current = anchor ? "below ".concat(anchor) : 'below';
384
+ } else if (overflow.current.isOverBottom && !overflow.current.isOverTop && localDirection === 'below') {
385
+ adjustedDirection.current = anchor ? "above ".concat(anchor) : 'above';
386
+ } else if (overflow.current.isOverLeft && !overflow.current.isOverRight && localDirection === 'left' && !componentProps.rtl) {
387
+ adjustedDirection.current = anchor ? "right ".concat(anchor) : 'right';
388
+ } else if (overflow.current.isOverRight && !overflow.current.isOverLeft && localDirection === 'right' && !componentProps.rtl) {
389
+ adjustedDirection.current = anchor ? "left ".concat(anchor) : 'left';
318
390
  }
319
- return _this;
320
- }
321
- _inherits(_Class, _Component);
322
- return _createClass(_Class, [{
323
- key: "componentDidMount",
324
- value: function componentDidMount() {
325
- var _this2 = this;
326
- if (this.props.open) {
327
- (0, _dispatcher.on)('keydown', this.handleKeyDown);
328
- (0, _dispatcher.on)('keyup', this.handleKeyUp);
391
+ }, [componentProps, getContainerAdjustedPosition]);
392
+
393
+ /**
394
+ * Position the popup in relation to the activator.
395
+ *
396
+ * Position is based on the dimensions of the popup and its activator. If the popup does not
397
+ * fit in the specified direction, it will automatically flip to the opposite direction.
398
+ *
399
+ * @method
400
+ * @memberof limestone/ContextualPopupDecorator.ContextualPopupDecorator.prototype
401
+ * @public
402
+ * @returns {undefined}
403
+ */
404
+ var positionContextualPopup = (0, _react.useCallback)(function () {
405
+ if (containerNode.current && clientSiblingRef !== null && clientSiblingRef !== void 0 && clientSiblingRef.current) {
406
+ var localContainerNode = containerNode.current.getBoundingClientRect();
407
+ var _clientSiblingRef$cur = clientSiblingRef.current.getBoundingClientRect(),
408
+ top = _clientSiblingRef$cur.top,
409
+ left = _clientSiblingRef$cur.left,
410
+ bottom = _clientSiblingRef$cur.bottom,
411
+ right = _clientSiblingRef$cur.right,
412
+ width = _clientSiblingRef$cur.width,
413
+ height = _clientSiblingRef$cur.height;
414
+ var clientNode = {
415
+ top: top,
416
+ left: left,
417
+ bottom: bottom,
418
+ right: right,
419
+ width: width,
420
+ height: height
421
+ };
422
+ clientNode.left = componentProps.rtl ? window.innerWidth - right : left;
423
+ clientNode.right = componentProps.rtl ? window.innerWidth - left : right;
424
+ calcOverflow(localContainerNode, clientNode);
425
+ adjustDirection();
426
+ var localArrowPosition = getArrowPosition(localContainerNode, clientNode),
427
+ localContainerPosition = getContainerPosition(localContainerNode, clientNode);
428
+ if (direction !== adjustedDirection.current || arrowPosition.left !== localArrowPosition.left || arrowPosition.top !== localArrowPosition.top || containerPosition.left !== localContainerPosition.left || containerPosition.right !== localContainerPosition.right || containerPosition.top !== localContainerPosition.top) {
429
+ setDirection(adjustedDirection.current);
430
+ setArrowPosition(localArrowPosition);
431
+ setContainerPosition(localContainerPosition);
329
432
  }
330
- if (typeof ResizeObserver === 'function') {
331
- this.resizeObserver = new ResizeObserver(function () {
332
- _this2.positionContextualPopup();
333
- });
433
+ }
434
+ }, [adjustDirection, arrowPosition, calcOverflow, componentProps, containerPosition, direction, getArrowPosition, getContainerPosition]);
435
+ var getContainerNode = (0, _react.useCallback)(function (node) {
436
+ containerNode.current = node;
437
+ if (resizeObserver.current) {
438
+ if (node) {
439
+ var _node$parentElement;
440
+ // It is not easy to trigger changed position of activator,
441
+ // so we chose to observe the `div` element's size that has the real size below the root of floatLayer.
442
+ // This implementation is dependent on the current structure of FloatingLayer,
443
+ // so if the structure have changed, below code needs to be changed accordingly.
444
+ resizeObserver.current.observe(node === null || node === void 0 || (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.parentElement);
445
+ } else {
446
+ resizeObserver.current.disconnect();
334
447
  }
335
- if (typeof MutationObserver === 'function') {
336
- this.mutationObserver = new MutationObserver(function () {
337
- _this2.positionContextualPopup();
448
+ }
449
+ if (mutationObserver.current) {
450
+ if (node) {
451
+ mutationObserver.current.observe(document.body, {
452
+ attributes: false,
453
+ childList: true,
454
+ subtree: true
338
455
  });
456
+ } else {
457
+ mutationObserver.current.disconnect();
339
458
  }
340
459
  }
341
- }, {
342
- key: "getSnapshotBeforeUpdate",
343
- value: function getSnapshotBeforeUpdate(prevProps, prevState) {
344
- var snapshot = {
345
- containerWidth: this.getContainerNodeWidth(),
346
- clientSiblingWidth: this.getClientSiblingNodeWidth()
347
- };
348
- if (prevProps.open && !this.props.open) {
349
- var current = _spotlight["default"].getCurrent();
350
- snapshot.shouldSpotActivator =
351
- // isn't set
352
- !current ||
353
- // is on the activator, and we want to re-spot it so a11y read out can occur
354
- current === prevState.activator ||
355
- // is within the popup
356
- this.containerNode.contains(current);
357
- }
358
- return snapshot;
460
+ }, []);
461
+ var spotPopupContent = (0, _react.useCallback)(function () {
462
+ var localSpotlightRestrict = componentProps.spotlightRestrict;
463
+ var spottableDescendants = _spotlight["default"].getSpottableDescendants(containerId);
464
+ if (localSpotlightRestrict === 'self-only' && spottableDescendants.length && _spotlight["default"].getCurrent()) {
465
+ _spotlight["default"].getCurrent().blur();
359
466
  }
360
- }, {
361
- key: "componentDidUpdate",
362
- value: function componentDidUpdate(prevProps, prevState, snapshot) {
363
- if (snapshot.clientSiblingWidth !== this.getClientSiblingNodeWidth()) {
364
- this.clientSiblingRef.current = this.findClientSiblingRef.current();
365
- }
366
- if (prevProps.direction !== this.props.direction || snapshot.containerWidth !== this.getContainerNodeWidth() || prevProps.open && this.props.open) {
367
- this.adjustedDirection = this.props.direction;
368
- // NOTE: `setState` is called and will cause re-render
369
- this.positionContextualPopup();
370
- }
371
- if (this.props.open && !prevProps.open) {
372
- (0, _dispatcher.on)('keydown', this.handleKeyDown);
373
- (0, _dispatcher.on)('keyup', this.handleKeyUp);
374
- } else if (!this.props.open && prevProps.open) {
375
- (0, _dispatcher.off)('keydown', this.handleKeyDown);
376
- (0, _dispatcher.off)('keyup', this.handleKeyUp);
377
- if (snapshot && snapshot.shouldSpotActivator) {
378
- this.spotActivator(prevState.activator);
379
- }
380
- }
467
+ if (!_spotlight["default"].focus(containerId)) {
468
+ _spotlight["default"].setActiveContainer(containerId);
381
469
  }
382
- }, {
383
- key: "componentWillUnmount",
384
- value: function componentWillUnmount() {
385
- if (this.props.open) {
386
- (0, _dispatcher.off)('keydown', this.handleKeyDown);
387
- (0, _dispatcher.off)('keyup', this.handleKeyUp);
388
- }
389
- _spotlight["default"].remove(this.state.containerId);
390
- if (this.resizeObserver) {
391
- this.resizeObserver.disconnect();
392
- this.resizeObserver = null;
393
- }
394
- if (this.mutationObserver) {
395
- this.mutationObserver.disconnect();
396
- this.mutationObserver = null;
470
+ }, [componentProps, containerId]);
471
+ var handleKeyUp = (0, _react.useCallback)(function () {
472
+ return (0, _handle.handle)((0, _handle.forProp)('open', true), (0, _handle.forKey)('enter'), function () {
473
+ return _spotlight["default"].getCurrent() === activator;
474
+ }, _handle.stop, (0, _handle.forwardCustom)('onClose'));
475
+ }, [activator]);
476
+ var handleOpen = (0, _react.useCallback)(function (ev) {
477
+ (0, _handle.forward)('onOpen', ev, componentProps);
478
+ positionContextualPopup();
479
+ var current = _spotlight["default"].getCurrent();
480
+ updateLeaveFor(current);
481
+ setTimeout(function () {
482
+ setActivator(current);
483
+ spotPopupContent();
484
+ });
485
+ }, [componentProps, positionContextualPopup, spotPopupContent, updateLeaveFor]);
486
+ var handleClose = (0, _react.useCallback)(function () {
487
+ updateLeaveFor(null);
488
+ setActivator(null);
489
+ }, [updateLeaveFor]);
490
+ var handleDismiss = (0, _react.useCallback)(function () {
491
+ (0, _handle.forwardCustom)('onClose')(null, componentProps);
492
+ }, [componentProps]);
493
+ var handleDirectionalKey = (0, _react.useCallback)(function (ev) {
494
+ // prevent default page scrolling
495
+ ev.preventDefault();
496
+ // stop propagation to prevent default spotlight behavior
497
+ ev.stopPropagation();
498
+ // set the pointer mode to false on keydown
499
+ _spotlight["default"].setPointerMode(false);
500
+ }, []);
501
+
502
+ // handle key event from outside (i.e. the activator) to the popup container
503
+ var handleKeyDown = (0, _react.useCallback)(function (ev) {
504
+ var current = _spotlight["default"].getCurrent();
505
+ var localDirection = (0, _spotlight.getDirection)(ev.keyCode);
506
+ if (!localDirection) return;
507
+ var hasSpottables = _spotlight["default"].getSpottableDescendants(containerId).length > 0;
508
+ var spotlessSpotlightModal = componentProps.spotlightRestrict === 'self-only' && !hasSpottables;
509
+ var shouldSpotPopup = current === activator && localDirection === PositionToDirection[adjustedDirection.current.split(' ')[0]] && hasSpottables;
510
+ if (shouldSpotPopup || spotlessSpotlightModal) {
511
+ handleDirectionalKey(ev);
512
+
513
+ // we guard against attempting a focus change by verifying the case where a
514
+ // spotlightModal popup contains no spottable components
515
+ if (!spotlessSpotlightModal && shouldSpotPopup) {
516
+ spotPopupContent();
397
517
  }
398
518
  }
399
- }, {
400
- key: "getContainerNodeWidth",
401
- value: function getContainerNodeWidth() {
402
- return this.containerNode && this.containerNode.getBoundingClientRect().width || 0;
519
+ }, [activator, componentProps, containerId, handleDirectionalKey, spotPopupContent]);
520
+
521
+ // handle key event from contextual popup and closes the popup
522
+ var handleContainerKeyDown = (0, _react.useCallback)(function (ev) {
523
+ // Note: Container will be only rendered if `open`ed, therefore no need to check for `open`
524
+ var localDirection = (0, _spotlight.getDirection)(ev.keyCode);
525
+ if (!localDirection) return;
526
+ handleDirectionalKey(ev);
527
+
528
+ // if focus moves outside the popup's container, issue the `onClose` event
529
+ if (_spotlight["default"].move(localDirection) && !containerNode.current.contains(_spotlight["default"].getCurrent())) {
530
+ (0, _handle.forwardCustom)('onClose')(null, componentProps);
403
531
  }
404
- }, {
405
- key: "getClientSiblingNodeWidth",
406
- value: function getClientSiblingNodeWidth() {
407
- return this.clientSiblingRef.current && this.clientSiblingRef.current.getBoundingClientRect().width || 0;
532
+ }, [componentProps, handleDirectionalKey]);
533
+ var spotActivator = (0, _react.useCallback)(function (localActivator) {
534
+ if (!_spotlight["default"].getPointerMode() && localActivator && localActivator === _spotlight["default"].getCurrent()) {
535
+ localActivator.blur();
408
536
  }
409
- }, {
410
- key: "updateLeaveFor",
411
- value: function updateLeaveFor(activator) {
412
- _spotlight["default"].set(this.state.containerId, {
413
- leaveFor: {
414
- up: activator,
415
- down: activator,
416
- left: activator,
417
- right: activator
418
- }
419
- });
537
+ if (!_spotlight["default"].focus(localActivator)) {
538
+ _spotlight["default"].focus();
420
539
  }
421
- }, {
422
- key: "getContainerPosition",
423
- value: function getContainerPosition(containerNode, clientNode) {
424
- var position = this.centerContainerPosition(containerNode, clientNode);
425
- var _this$getContainerAdj = this.getContainerAdjustedPosition(),
426
- direction = _this$getContainerAdj.direction;
427
- switch (direction) {
428
- case 'above':
429
- position.top = clientNode.top - this.ARROW_OFFSET - containerNode.height - this.MARGIN;
430
- break;
431
- case 'below':
432
- position.top = clientNode.bottom + this.ARROW_OFFSET + this.MARGIN;
433
- break;
434
- case 'right':
435
- position.left = this.props.rtl ? clientNode.left - containerNode.width - this.ARROW_OFFSET - this.MARGIN : clientNode.right + this.ARROW_OFFSET + this.MARGIN;
436
- break;
437
- case 'left':
438
- position.left = this.props.rtl ? clientNode.right + this.ARROW_OFFSET + this.MARGIN : clientNode.left - containerNode.width - this.ARROW_OFFSET - this.MARGIN;
439
- break;
440
- }
441
- return this.adjustRTL(position);
540
+ }, []);
541
+ var getClientSiblingNodeWidth = (0, _react.useCallback)(function () {
542
+ return clientSiblingRef.current && clientSiblingRef.current.getBoundingClientRect().width || 0;
543
+ }, []);
544
+ var getSnapshotBeforeUpdate = (0, _react.useCallback)(function () {
545
+ var localSnapshot = {
546
+ containerWidth: getContainerNodeWidth(),
547
+ clientSiblingWidth: getClientSiblingNodeWidth()
548
+ };
549
+ if (prevProps.current.open && !componentProps.open) {
550
+ var _containerNode$curren;
551
+ var current = _spotlight["default"].getCurrent();
552
+ localSnapshot.shouldSpotActivator =
553
+ // isn't set
554
+ !current ||
555
+ // is on the activator, and we want to re-spot it so a11y read out can occur
556
+ current === activator || (// is within the popup
557
+ (_containerNode$curren = containerNode.current) === null || _containerNode$curren === void 0 ? void 0 : _containerNode$curren.contains(current));
442
558
  }
443
- }, {
444
- key: "centerContainerPosition",
445
- value: function centerContainerPosition(containerNode, clientNode) {
446
- var pos = {};
447
- var _this$getContainerAdj2 = this.getContainerAdjustedPosition(),
448
- anchor = _this$getContainerAdj2.anchor,
449
- direction = _this$getContainerAdj2.direction;
450
- if (direction === 'above' || direction === 'below') {
451
- if (this.overflow.isOverLeft) {
452
- // anchor to the left of the screen
453
- pos.left = this.KEEPOUT;
454
- } else if (this.overflow.isOverRight) {
455
- // anchor to the right of the screen
456
- pos.left = window.innerWidth - containerNode.width - this.KEEPOUT;
457
- } else if (anchor) {
458
- if (anchor === 'center') {
459
- // center horizontally
460
- pos.left = clientNode.left + (clientNode.width - containerNode.width) / 2;
461
- } else if (anchor === 'left') {
462
- // anchor to the left side of the activator
463
- pos.left = clientNode.left;
464
- } else {
465
- // anchor to the right side of the activator
466
- pos.left = clientNode.right - containerNode.width;
467
- }
468
- } else {
469
- // anchor to the left side of the activator, matching its width
470
- pos.left = clientNode.left;
471
- pos.width = clientNode.width;
472
- }
473
- } else if (direction === 'left' || direction === 'right') {
474
- if (this.overflow.isOverTop) {
475
- // anchor to the top of the screen
476
- pos.top = this.KEEPOUT;
477
- } else if (this.overflow.isOverBottom) {
478
- // anchor to the bottom of the screen
479
- pos.top = window.innerHeight - containerNode.height - this.KEEPOUT;
480
- } else if (anchor === 'middle') {
481
- // center vertically
482
- pos.top = clientNode.top - (containerNode.height - clientNode.height) / 2;
483
- } else if (anchor === 'top') {
484
- // anchor to the top of the activator
485
- pos.top = clientNode.top;
486
- } else {
487
- // anchor to the bottom of the activator
488
- pos.top = clientNode.bottom - containerNode.height;
489
- }
559
+ return localSnapshot;
560
+ }, [activator, componentProps, getContainerNodeWidth, getClientSiblingNodeWidth]);
561
+ (0, _react.useEffect)(function () {
562
+ if (componentProps.open) {
563
+ if (handleKeyDown !== keyDownRef.current || handleKeyUp !== keyUpRef.current) {
564
+ (0, _dispatcher.off)('keydown', keyDownRef.current);
565
+ (0, _dispatcher.off)('keyup', keyUpRef.current);
566
+ keyDownRef.current = handleKeyDown;
567
+ keyUpRef.current = handleKeyUp;
568
+ (0, _dispatcher.on)('keydown', keyDownRef.current);
569
+ (0, _dispatcher.on)('keyup', keyUpRef.current);
490
570
  }
491
- return pos;
492
571
  }
493
- }, {
494
- key: "getArrowPosition",
495
- value: function getArrowPosition(containerNode, clientNode) {
496
- var position = {};
497
- var _this$getContainerAdj3 = this.getContainerAdjustedPosition(),
498
- anchor = _this$getContainerAdj3.anchor,
499
- direction = _this$getContainerAdj3.direction;
500
- if (direction === 'above' || direction === 'below') {
501
- if (this.overflow.isOverRight && !this.overflow.isOverLeft) {
502
- position.left = window.innerWidth - (containerNode.width + this.ARROW_WIDTH) / 2 - this.KEEPOUT;
503
- } else if (!this.overflow.isOverRight && this.overflow.isOverLeft) {
504
- position.left = (containerNode.width - this.ARROW_WIDTH) / 2 + this.KEEPOUT;
505
- } else if (anchor === 'left') {
506
- position.left = clientNode.left + (containerNode.width - this.ARROW_WIDTH) / 2;
507
- } else if (anchor === 'right') {
508
- position.left = clientNode.right - containerNode.width + (containerNode.width - this.ARROW_WIDTH) / 2;
509
- } else {
510
- position.left = clientNode.left + (clientNode.width - this.ARROW_WIDTH) / 2;
511
- }
512
- } else if (this.overflow.isOverBottom && !this.overflow.isOverTop) {
513
- position.top = window.innerHeight - (containerNode.height + this.ARROW_WIDTH) / 2 - this.KEEPOUT;
514
- } else if (!this.overflow.isOverBottom && this.overflow.isOverTop) {
515
- position.top = (containerNode.height - this.ARROW_WIDTH) / 2 + this.KEEPOUT;
516
- } else if (anchor === 'top') {
517
- position.top = clientNode.top + (containerNode.height - this.ARROW_WIDTH) / 2;
518
- } else if (anchor === 'bottom') {
519
- position.top = clientNode.bottom - containerNode.height + (containerNode.height - this.ARROW_WIDTH) / 2;
520
- } else {
521
- position.top = clientNode.top + (clientNode.height - this.ARROW_WIDTH) / 2;
572
+ }, [componentProps, handleKeyDown, handleKeyUp]);
573
+ (0, _react.useEffect)(function () {
574
+ var localId = containerId;
575
+ if (componentProps.open) {
576
+ (0, _dispatcher.on)('keydown', keyDownRef.current);
577
+ (0, _dispatcher.on)('keyup', keyUpRef.current);
578
+ }
579
+ if (typeof ResizeObserver === 'function') {
580
+ resizeObserver.current = new ResizeObserver(function () {
581
+ positionContextualPopup();
582
+ });
583
+ }
584
+ if (typeof MutationObserver === 'function') {
585
+ mutationObserver.current = new MutationObserver(function () {
586
+ positionContextualPopup();
587
+ });
588
+ }
589
+ return function () {
590
+ if (componentProps.open) {
591
+ (0, _dispatcher.off)('keydown', keyDownRef.current);
592
+ (0, _dispatcher.off)('keyup', keyUpRef.current);
522
593
  }
523
- switch (direction) {
524
- case 'above':
525
- position.top = clientNode.top - this.ARROW_WIDTH - this.MARGIN;
526
- break;
527
- case 'below':
528
- position.top = clientNode.bottom + this.MARGIN;
529
- break;
530
- case 'left':
531
- position.left = this.props.rtl ? clientNode.left + clientNode.width + this.MARGIN : clientNode.left - this.ARROW_WIDTH - this.MARGIN;
532
- break;
533
- case 'right':
534
- position.left = this.props.rtl ? clientNode.left - this.ARROW_WIDTH - this.MARGIN : clientNode.left + clientNode.width + this.MARGIN;
535
- break;
536
- default:
537
- return {};
594
+ _spotlight["default"].remove(localId);
595
+ if (resizeObserver.current) {
596
+ resizeObserver.current.disconnect();
597
+ resizeObserver.current = null;
538
598
  }
539
- return this.adjustRTL(position);
540
- }
541
- }, {
542
- key: "calcOverflow",
543
- value: function calcOverflow(container, client) {
544
- var containerHeight, containerWidth;
545
- var _this$getContainerAdj4 = this.getContainerAdjustedPosition(),
546
- anchor = _this$getContainerAdj4.anchor,
547
- direction = _this$getContainerAdj4.direction;
548
- if (direction === 'above' || direction === 'below') {
549
- containerHeight = container.height;
550
- containerWidth = (container.width - client.width) / 2;
551
- } else {
552
- containerHeight = (container.height - client.height) / 2;
553
- containerWidth = container.width;
599
+ if (mutationObserver.current) {
600
+ mutationObserver.current.disconnect();
601
+ mutationObserver.current = null;
554
602
  }
555
- this.overflow = {
556
- isOverTop: anchor === 'top' && (direction === 'left' || direction === 'right') ? !(client.top > this.KEEPOUT) : client.top - containerHeight - this.ARROW_OFFSET - this.MARGIN - this.KEEPOUT < 0,
557
- isOverBottom: anchor === 'bottom' && (direction === 'left' || direction === 'right') ? client.bottom + this.KEEPOUT > window.innerHeight : client.bottom + containerHeight + this.ARROW_OFFSET + this.MARGIN + this.KEEPOUT > window.innerHeight,
558
- isOverLeft: anchor === 'left' && (direction === 'above' || direction === 'below') ? !(client.left > this.KEEPOUT) : client.left - containerWidth - this.ARROW_OFFSET - this.MARGIN - this.KEEPOUT < 0,
559
- isOverRight: anchor === 'right' && (direction === 'above' || direction === 'below') ? client.right + this.KEEPOUT > window.innerWidth : client.right + containerWidth + this.ARROW_OFFSET + this.MARGIN + this.KEEPOUT > window.innerWidth
560
- };
603
+ };
604
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
605
+
606
+ (0, _react.useEffect)(function () {
607
+ snapshot.current = getSnapshotBeforeUpdate();
608
+ if (snapshot.current.clientSiblingWidth !== getClientSiblingNodeWidth()) {
609
+ clientSiblingRef.current = findClientSiblingRef.current();
561
610
  }
562
- }, {
563
- key: "adjustDirection",
564
- value: function adjustDirection() {
565
- var _this$getContainerAdj5 = this.getContainerAdjustedPosition(),
566
- anchor = _this$getContainerAdj5.anchor,
567
- direction = _this$getContainerAdj5.direction;
568
- if (this.overflow.isOverTop && !this.overflow.isOverBottom && direction === 'above') {
569
- this.adjustedDirection = anchor ? "below ".concat(anchor) : 'below';
570
- } else if (this.overflow.isOverBottom && !this.overflow.isOverTop && direction === 'below') {
571
- this.adjustedDirection = anchor ? "above ".concat(anchor) : 'above';
572
- } else if (this.overflow.isOverLeft && !this.overflow.isOverRight && direction === 'left' && !this.props.rtl) {
573
- this.adjustedDirection = anchor ? "right ".concat(anchor) : 'right';
574
- } else if (this.overflow.isOverRight && !this.overflow.isOverLeft && direction === 'right' && !this.props.rtl) {
575
- this.adjustedDirection = anchor ? "left ".concat(anchor) : 'left';
576
- }
611
+ if (prevProps.current.direction !== componentProps.direction || snapshot.current.containerWidth !== getContainerNodeWidth() || prevProps.current.open && componentProps.open) {
612
+ adjustedDirection.current = componentProps.direction;
613
+ // NOTE: `setState` is called and will cause re-render
614
+ positionContextualPopup();
577
615
  }
578
- }, {
579
- key: "adjustRTL",
580
- value: function adjustRTL(position) {
581
- var pos = position;
582
- if (this.props.rtl) {
583
- var tmpLeft = pos.left;
584
- pos.left = pos.right;
585
- pos.right = tmpLeft;
616
+ if (componentProps.open && !prevProps.current.open) {
617
+ (0, _dispatcher.on)('keydown', keyDownRef.current);
618
+ (0, _dispatcher.on)('keyup', keyUpRef.current);
619
+ } else if (!componentProps.open && prevProps.current.open) {
620
+ (0, _dispatcher.off)('keydown', keyDownRef.current);
621
+ (0, _dispatcher.off)('keyup', keyUpRef.current);
622
+ if (snapshot.current && snapshot.current.shouldSpotActivator) {
623
+ spotActivator(activator);
586
624
  }
587
- return pos;
588
- }
589
- }, {
590
- key: "handleDirectionalKey",
591
- value: function handleDirectionalKey(ev) {
592
- // prevent default page scrolling
593
- ev.preventDefault();
594
- // stop propagation to prevent default spotlight behavior
595
- ev.stopPropagation();
596
- // set the pointer mode to false on keydown
597
- _spotlight["default"].setPointerMode(false);
598
625
  }
599
- }, {
600
- key: "render",
601
- value: function render() {
602
- var _this$clientSiblingRe3;
603
- var _this$props = this.props,
604
- voiceExclusive = _this$props['data-webos-voice-exclusive'],
605
- PopupComponent = _this$props.popupComponent,
606
- popupClassName = _this$props.popupClassName,
607
- noAutoDismiss = _this$props.noAutoDismiss,
608
- open = _this$props.open,
609
- offset = _this$props.offset,
610
- popupProps = _this$props.popupProps,
611
- skin = _this$props.skin,
612
- spotlightRestrict = _this$props.spotlightRestrict,
613
- rest = _objectWithoutProperties(_this$props, _excluded);
614
- var idFloatLayer = "".concat(this.id, "_floatLayer");
615
- var scrimType = rest.scrimType;
616
- delete rest.scrimType;
626
+ prevProps.current = componentProps;
627
+ }, [activator, componentProps, getContainerNodeWidth, getClientSiblingNodeWidth, getSnapshotBeforeUpdate, positionContextualPopup, spotActivator]);
628
+ var voiceExclusive = componentProps['data-webos-voice-exclusive'],
629
+ PopupComponent = componentProps.popupComponent,
630
+ popupClassName = componentProps.popupClassName,
631
+ noAutoDismiss = componentProps.noAutoDismiss,
632
+ open = componentProps.open,
633
+ offset = componentProps.offset,
634
+ popupProps = componentProps.popupProps,
635
+ skin = componentProps.skin,
636
+ spotlightRestrict = componentProps.spotlightRestrict,
637
+ rest = _objectWithoutProperties(componentProps, _excluded);
638
+ var idFloatLayer = "".concat(id, "_floatLayer");
639
+ var scrimType = rest.scrimType;
640
+ delete rest.scrimType;
617
641
 
618
- // 'holepunch' scrimType is specific to this component, not supported by floating layer
619
- // so it must be swapped-out for one that FloatingLayer does support.
620
- var holepunchScrim = scrimType === 'holepunch';
621
- if (spotlightRestrict === 'self-only' && scrimType === 'none' || holepunchScrim) {
622
- scrimType = 'transparent';
623
- }
624
- var popupPropsRef = Object.assign({}, popupProps);
625
- var ariaProps = (0, _util.extractAriaProps)(popupPropsRef);
626
- if (!noSkin) {
627
- rest.skin = skin;
628
- }
629
- var holeBounds;
630
- if ((_this$clientSiblingRe3 = this.clientSiblingRef) !== null && _this$clientSiblingRe3 !== void 0 && _this$clientSiblingRe3.current && holepunchScrim) {
631
- holeBounds = this.clientSiblingRef.current.getBoundingClientRect();
632
- }
633
- delete rest.direction;
634
- delete rest.onClose;
635
- delete rest.onOpen;
636
- delete rest.popupSpotlightId;
637
- delete rest.rtl;
638
- delete rest.setApiProvider;
639
- if (openProp) rest[openProp] = open;
640
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
641
- "aria-owns": idFloatLayer,
642
- className: _ContextualPopupDecoratorModule["default"].contextualPopupDecorator,
643
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_FloatingLayer["default"], {
644
- id: idFloatLayer,
645
- noAutoDismiss: noAutoDismiss,
646
- onClose: this.handleClose,
647
- onDismiss: this.handleDismiss,
648
- onOpen: this.handleOpen,
649
- open: open,
650
- scrimType: scrimType,
651
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
652
- children: [holepunchScrim ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_HolePunchScrim["default"], {
653
- holeBounds: holeBounds
654
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(ContextualPopupContainer, _objectSpread(_objectSpread({}, ariaProps), {}, {
655
- className: popupClassName,
656
- onKeyDown: this.handleContainerKeyDown,
657
- direction: this.state.direction,
658
- arrowPosition: this.state.arrowPosition,
659
- containerPosition: this.state.containerPosition,
660
- containerRef: this.getContainerNode,
661
- "data-webos-voice-exclusive": voiceExclusive,
662
- offset: noArrow ? offset : 'none',
663
- showArrow: !noArrow,
664
- skin: skin,
665
- spotlightId: this.state.containerId,
666
- spotlightRestrict: spotlightRestrict,
667
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(PopupComponent, _objectSpread({}, popupPropsRef))
668
- }))]
669
- })
670
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(WrappedWithRef, _objectSpread(_objectSpread({}, rest), {}, {
671
- outermostRef: this.clientSiblingRef,
672
- findOutermostRef: this.findClientSiblingRef,
673
- referrerName: "ContextualPopup"
674
- }))]
675
- });
642
+ // 'holepunch' scrimType is specific to this component, not supported by floating layer
643
+ // so it must be swapped-out for one that FloatingLayer does support.
644
+ var holepunchScrim = scrimType === 'holepunch';
645
+ if (spotlightRestrict === 'self-only' && scrimType === 'none' || holepunchScrim) {
646
+ scrimType = 'transparent';
647
+ }
648
+ var popupPropsRef = Object.assign({}, popupProps);
649
+ var ariaProps = (0, _util.extractAriaProps)(popupPropsRef);
650
+ if (!noSkin) {
651
+ rest.skin = skin;
652
+ }
653
+ (0, _react.useEffect)(function () {
654
+ if (clientSiblingRef !== null && clientSiblingRef !== void 0 && clientSiblingRef.current && holepunchScrim) {
655
+ setHoleBounds(clientSiblingRef.current.getBoundingClientRect());
676
656
  }
677
- }]);
678
- }(_react.Component), _Class.displayName = 'ContextualPopupDecorator', _Class.propTypes = /** @lends limestone/ContextualPopupDecorator.ContextualPopupDecorator.prototype */{
657
+ }, [holepunchScrim]);
658
+ delete rest.direction;
659
+ delete rest.onClose;
660
+ delete rest.onOpen;
661
+ delete rest.popupSpotlightId;
662
+ delete rest.rtl;
663
+ delete rest.setApiProvider;
664
+ if (openProp) rest[openProp] = open;
665
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
666
+ "aria-owns": idFloatLayer,
667
+ className: _ContextualPopupDecoratorModule["default"].contextualPopupDecorator,
668
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_FloatingLayer["default"], {
669
+ id: idFloatLayer,
670
+ noAutoDismiss: noAutoDismiss,
671
+ onClose: handleClose,
672
+ onDismiss: handleDismiss,
673
+ onOpen: handleOpen,
674
+ open: open,
675
+ scrimType: scrimType,
676
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
677
+ children: [holepunchScrim ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_HolePunchScrim["default"], {
678
+ holeBounds: holeBounds
679
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(ContextualPopupContainer, _objectSpread(_objectSpread({}, ariaProps), {}, {
680
+ className: popupClassName,
681
+ onKeyDown: handleContainerKeyDown,
682
+ direction: direction,
683
+ arrowPosition: arrowPosition,
684
+ containerPosition: containerPosition,
685
+ containerRef: getContainerNode,
686
+ "data-webos-voice-exclusive": voiceExclusive,
687
+ offset: noArrow ? offset : 'none',
688
+ showArrow: !noArrow,
689
+ skin: skin,
690
+ spotlightId: containerId,
691
+ spotlightRestrict: spotlightRestrict,
692
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(PopupComponent, _objectSpread({}, popupPropsRef))
693
+ }))]
694
+ })
695
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(WrappedWithRef, _objectSpread(_objectSpread({}, rest), {}, {
696
+ outermostRef: clientSiblingRef,
697
+ findOutermostRef: findClientSiblingRef,
698
+ referrerName: "ContextualPopup"
699
+ }))]
700
+ });
701
+ };
702
+ _ContextualPopupDecorator.displayName = 'ContextualPopupDecorator';
703
+ _ContextualPopupDecorator.propTypes = /** @lends limestone/ContextualPopupDecorator.ContextualPopupDecorator.prototype */{
679
704
  /**
680
705
  * The component rendered within the
681
706
  * {@link limestone/ContextualPopupDecorator.ContextualPopup|ContextualPopup}.
@@ -824,15 +849,8 @@ var Decorator = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) {
824
849
  * @public
825
850
  */
826
851
  spotlightRestrict: _propTypes2["default"].oneOf(['none', 'self-first', 'self-only'])
827
- }, _Class.defaultProps = {
828
- 'data-webos-voice-exclusive': true,
829
- direction: 'below center',
830
- noAutoDismiss: false,
831
- offset: 'small',
832
- open: false,
833
- scrimType: 'none',
834
- spotlightRestrict: 'self-first'
835
- }, _Class;
852
+ };
853
+ return _ContextualPopupDecorator;
836
854
  });
837
855
 
838
856
  /**