@enact/limestone 1.3.0 → 1.9.4

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