@enact/limestone 1.9.3 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/.github/workflows/ci-reusable.yml +2 -2
  2. package/ActionGuide/ActionGuide.module.css +4 -0
  3. package/Alert/Alert.d.ts +9 -0
  4. package/Alert/Alert.js +35 -4
  5. package/Alert/Alert.module.css +12 -1
  6. package/Alert/tests/Alert-specs.js +91 -0
  7. package/BodyText/BodyText.module.css +21 -0
  8. package/Button/Button.module.css +72 -40
  9. package/Button/tests/Button-specs.js +26 -0
  10. package/CHANGELOG.md +74 -0
  11. package/Card/Card.d.ts +4 -4
  12. package/Card/Card.js +10 -8
  13. package/Card/Card.module.css +31 -7
  14. package/Card/tests/Card-specs.js +39 -5
  15. package/Checkbox/Checkbox.module.css +4 -0
  16. package/CheckboxItem/CheckboxItem.js +6 -4
  17. package/Chips/Chip.js +12 -6
  18. package/Chips/Chip.module.css +3 -0
  19. package/Chips/Chips.js +12 -6
  20. package/Chips/tests/Chip-specs.js +25 -5
  21. package/Chips/tests/Chips-specs.js +12 -2
  22. package/ColorPicker/ColorPicker.js +27 -25
  23. package/ContextualPopupDecorator/ContextualPopupDecorator.js +32 -22
  24. package/DayPicker/DaySelectorDecorator.js +12 -7
  25. package/Dropdown/Dropdown.module.css +4 -0
  26. package/Dropdown/DropdownList.js +74 -53
  27. package/FlexiblePopupPanels/useNavButtonFocus.js +7 -10
  28. package/Heading/Heading.d.ts +1 -1
  29. package/Heading/Heading.js +2 -2
  30. package/Heading/Heading.module.css +16 -0
  31. package/Icon/Icon.d.ts +1 -0
  32. package/Icon/Icon.js +1 -0
  33. package/Icon/Icon.module.css +12 -0
  34. package/Icon/IconList.js +2 -0
  35. package/IconItem/IconItem.module.css +19 -3
  36. package/IconItem/tests/IconItem-specs.js +30 -1
  37. package/Image/Image.js +6 -4
  38. package/ImageItem/ImageItem.module.css +17 -0
  39. package/Input/Input.js +12 -1
  40. package/Input/Input.module.css +25 -9
  41. package/Input/InputField.js +75 -24
  42. package/Input/InputField.module.css +280 -45
  43. package/Input/InputFieldDecoratorIcon.js +1 -0
  44. package/Input/InputFieldSpotlightDecorator.js +53 -8
  45. package/Input/index.d.ts +105 -93
  46. package/Input/tests/Input-specs.js +26 -0
  47. package/Input/tests/InputField-specs.js +149 -3
  48. package/Input/tests/InputPopup-specs.js +1 -1
  49. package/Item/Item.module.css +2 -1
  50. package/KeyGuide/KeyGuide.js +29 -27
  51. package/KeyGuide/KeyGuide.module.css +10 -0
  52. package/MediaOverlay/MediaOverlay.module.css +16 -4
  53. package/MediaOverlay/tests/MediaOverlay-specs.js +29 -0
  54. package/MediaPlayer/MediaControls.module.css +3 -0
  55. package/MediaPlayer/Times.module.css +4 -0
  56. package/MediaPlayer/tests/util-specs.js +4 -1
  57. package/PageViews/PageViews.js +134 -69
  58. package/PageViews/PageViews.module.css +7 -0
  59. package/PageViews/PageViewsRouter.js +91 -42
  60. package/PageViews/tests/PageViews-specs.js +87 -0
  61. package/Panels/Header.js +6 -4
  62. package/Panels/Header.module.css +37 -31
  63. package/Popup/Popup.js +5 -4
  64. package/PopupTabLayout/PopupTabLayout.js +11 -9
  65. package/PopupTabLayout/PopupTabLayout.module.css +18 -0
  66. package/RadioItem/RadioItem.js +7 -5
  67. package/RadioItem/RadioItem.module.css +5 -0
  68. package/Scroller/EditableWrapper.js +19 -15
  69. package/Scroller/Scroller.js +11 -10
  70. package/Scroller/Scroller.module.css +10 -0
  71. package/Scroller/tests/Scroller-specs.js +91 -2
  72. package/Scroller/useThemeScroller.js +6 -3
  73. package/Slider/Slider.d.ts +4 -0
  74. package/Slider/Slider.js +40 -16
  75. package/Slider/Slider.module.css +150 -3
  76. package/Slider/SliderBehaviorDecorator.js +16 -14
  77. package/Slider/tests/Slider-specs.js +51 -0
  78. package/Slider/utils.js +23 -7
  79. package/Spinner/Spinner.js +10 -8
  80. package/Steps/Steps.module.css +3 -0
  81. package/Switch/Switch.module.css +15 -1
  82. package/TabLayout/RefocusDecorator.js +14 -12
  83. package/TabLayout/TabGroup.module.css +1 -1
  84. package/TabLayout/tests/TabGroup-specs.js +1 -1
  85. package/ThemeDecorator/AccessibilityDecorator.js +12 -11
  86. package/ThemeDecorator/I18nFontDecorator.js +6 -4
  87. package/ThemeDecorator/ThemeDecorator.d.ts +7 -0
  88. package/ThemeDecorator/ThemeDecorator.js +24 -9
  89. package/TimePicker/TimePicker.module.css +3 -0
  90. package/TimePicker/TimePickerBase.js +5 -3
  91. package/TooltipDecorator/Tooltip.module.css +4 -0
  92. package/TooltipDecorator/TooltipDecorator.js +12 -7
  93. package/TooltipDecorator/tests/useTooltip-specs.js +5 -2
  94. package/VideoPlayer/Feedback.module.css +3 -0
  95. package/VideoPlayer/FeedbackTooltip.module.css +7 -0
  96. package/VideoPlayer/MediaTitle.module.css +8 -0
  97. package/VideoPlayer/VideoPlayer.js +25 -24
  98. package/VirtualList/VirtualList.js +20 -18
  99. package/VirtualList/useSpotlight.js +1 -1
  100. package/fonts/Limestone_Icons.ttf +0 -0
  101. package/internal/AsyncRenderChildren/AsyncRenderChildren.js +9 -5
  102. package/internal/AsyncRenderChildren/tests/AsyncRenderChildren-specs.js +4 -1
  103. package/internal/DateTime/DateTime.module.css +3 -0
  104. package/internal/DateTime/DateTimeDecorator.js +5 -4
  105. package/internal/Panels/PanelsRouter.js +35 -29
  106. package/internal/Panels/useAutoFocus.js +10 -6
  107. package/internal/Panels/useFocusOnTransition.js +4 -3
  108. package/internal/Picker/Picker.js +7 -5
  109. package/internal/Picker/Picker.module.css +22 -0
  110. package/internal/Picker/SpottablePicker.js +15 -13
  111. package/internal/SharedStateDecorator/SharedStateDecorator.js +6 -4
  112. package/package.json +15 -12
  113. package/styles/colors.less +1 -0
  114. package/styles/variables.less +118 -26
  115. package/useScroll/HoverToScroll.js +15 -12
  116. package/useScroll/Scrollbar.js +14 -10
  117. package/useScroll/ScrollbarPlaceholder.js +4 -1
  118. package/useScroll/ScrollbarTrack.js +7 -5
  119. package/useScroll/useEvent.js +7 -2
  120. package/useScroll/useScroll.js +10 -2
@@ -8,6 +8,7 @@ var _handle = require("@enact/core/handle");
8
8
  var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));
9
9
  var _keymap = require("@enact/core/keymap");
10
10
  var _usePublicClassNames = require("@enact/core/usePublicClassNames");
11
+ var _util = require("@enact/core/util");
11
12
  var _spotlight = _interopRequireWildcard(require("@enact/spotlight"));
12
13
  var _container = require("@enact/spotlight/src/container");
13
14
  var _target = require("@enact/spotlight/src/target");
@@ -89,21 +90,22 @@ var holdConfig = {
89
90
  * @ui
90
91
  * @public
91
92
  */
92
- var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props) {
93
+ var _EditableWrapper = exports.EditableWrapper = function EditableWrapper(props) {
93
94
  var _editable$hideIndex;
95
+ (0, _util.checkPropTypes)(_EditableWrapper, props);
94
96
  var children = props.children,
95
97
  editable = props.editable,
96
98
  scrollContainerHandle = props.scrollContainerHandle,
97
99
  scrollContainerRef = props.scrollContainerRef,
98
100
  scrollContentRef = props.scrollContentRef;
99
- var centered = (editable === null || editable === void 0 ? void 0 : editable.centered) != null ? editable.centered : true;
100
- var selectItemBy = (editable === null || editable === void 0 ? void 0 : editable.selectItemBy) || 'longPress';
101
- var customCss = (editable === null || editable === void 0 ? void 0 : editable.css) || {};
102
101
  var removeItemFuncRef = editable === null || editable === void 0 ? void 0 : editable.removeItemFuncRef;
103
102
  var hideItemFuncRef = editable === null || editable === void 0 ? void 0 : editable.hideItemFuncRef;
104
103
  var showItemFuncRef = editable === null || editable === void 0 ? void 0 : editable.showItemFuncRef;
105
104
  var focusItemFuncRef = editable === null || editable === void 0 ? void 0 : editable.focusItemFuncRef;
106
105
  var blurItemFuncRef = editable === null || editable === void 0 ? void 0 : editable.blurItemFuncRef;
106
+ var centered = (editable === null || editable === void 0 ? void 0 : editable.centered) != null ? editable.centered : true;
107
+ var selectItemBy = (editable === null || editable === void 0 ? void 0 : editable.selectItemBy) || 'longPress';
108
+ var customCss = (editable === null || editable === void 0 ? void 0 : editable.css) || {};
107
109
  var mergedCss = (0, _usePublicClassNames.usePublicClassNames)({
108
110
  componentCss: _EditableWrapperModule["default"],
109
111
  customCss: customCss,
@@ -126,7 +128,7 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
126
128
  // Indices
127
129
  fromIndex: null,
128
130
  prevToIndex: null,
129
- hideIndex: null,
131
+ hideIndex: (_editable$hideIndex = editable === null || editable === void 0 ? void 0 : editable.hideIndex) !== null && _editable$hideIndex !== void 0 ? _editable$hideIndex : dataSize,
130
132
  // Position for restoring focus after removing item
131
133
  nextSpotlightRect: null,
132
134
  // Move direction from the starting position to the current position
@@ -146,7 +148,6 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
146
148
  initialSelected: editable === null || editable === void 0 ? void 0 : editable.initialSelected
147
149
  });
148
150
  var announceRef = (0, _react.useRef)({});
149
- mutableRef.current.hideIndex = (_editable$hideIndex = editable === null || editable === void 0 ? void 0 : editable.hideIndex) !== null && _editable$hideIndex !== void 0 ? _editable$hideIndex : dataSize;
150
151
 
151
152
  // Functions
152
153
 
@@ -612,8 +613,9 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
612
613
  if (selectItemBy === 'press') {
613
614
  if ((0, _pointer.getPointerMode)()) {
614
615
  _spotlight["default"].setPointerMode(false);
616
+ _spotlight["default"].focus(focusTarget);
615
617
  }
616
- _spotlight["default"].focus(focusTarget);
618
+ if (focusTarget !== _spotlight["default"].getCurrent()) _spotlight["default"].focus(focusTarget);
617
619
  focusItem(focusTarget);
618
620
  }
619
621
  setTimeout(function () {
@@ -886,27 +888,27 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
886
888
  }, [handleMouseLeave, handleTouchMove, scrollContainerRef]);
887
889
  (0, _react.useLayoutEffect)(function () {
888
890
  if (removeItemFuncRef) {
889
- removeItemFuncRef.current = removeItem;
891
+ removeItemFuncRef.current = removeItem; // eslint-disable-line react-hooks/immutability
890
892
  }
891
893
  }, [removeItem, removeItemFuncRef]);
892
894
  (0, _react.useLayoutEffect)(function () {
893
895
  if (hideItemFuncRef) {
894
- hideItemFuncRef.current = hideItem;
896
+ hideItemFuncRef.current = hideItem; // eslint-disable-line react-hooks/immutability
895
897
  }
896
898
  }, [hideItem, hideItemFuncRef]);
897
899
  (0, _react.useLayoutEffect)(function () {
898
900
  if (showItemFuncRef) {
899
- showItemFuncRef.current = showItem;
901
+ showItemFuncRef.current = showItem; // eslint-disable-line react-hooks/immutability
900
902
  }
901
903
  }, [showItem, showItemFuncRef]);
902
904
  (0, _react.useLayoutEffect)(function () {
903
905
  if (focusItemFuncRef) {
904
- focusItemFuncRef.current = focusItem;
906
+ focusItemFuncRef.current = focusItem; // eslint-disable-line react-hooks/immutability
905
907
  }
906
908
  }, [focusItem, focusItemFuncRef]);
907
909
  (0, _react.useLayoutEffect)(function () {
908
910
  if (blurItemFuncRef) {
909
- blurItemFuncRef.current = blurItem;
911
+ blurItemFuncRef.current = blurItem; // eslint-disable-line react-hooks/immutability
910
912
  }
911
913
  }, [blurItem, blurItemFuncRef]);
912
914
  (0, _react.useEffect)(function () {
@@ -981,6 +983,8 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
981
983
 
982
984
  // We set 'data-is-hiding' for all hidden items at component mount
983
985
  (0, _react.useEffect)(function () {
986
+ var _editable$hideIndex2;
987
+ mutableRef.current.hideIndex = (_editable$hideIndex2 = editable === null || editable === void 0 ? void 0 : editable.hideIndex) !== null && _editable$hideIndex2 !== void 0 ? _editable$hideIndex2 : dataSize;
984
988
  children.map(function (child, index) {
985
989
  if (index >= mutableRef.current.hideIndex) {
986
990
  var hiddenElement = document.querySelector('[aria-label="' + child.props['aria-label'] + '"]');
@@ -1007,8 +1011,8 @@ var EditableWrapper = exports.EditableWrapper = function EditableWrapper(props)
1007
1011
  }, "editable-wrapper-announce")]
1008
1012
  });
1009
1013
  };
1010
- EditableWrapper.displayName = 'EditableWrapper';
1011
- EditableWrapper.propTypes = /** @lends limestone/Scroller.EditableWrapper.prototype */{
1014
+ _EditableWrapper.displayName = 'EditableWrapper';
1015
+ _EditableWrapper.propTypes = /** @lends limestone/Scroller.EditableWrapper.prototype */{
1012
1016
  /**
1013
1017
  * Enables editing items in the scroller.
1014
1018
  * You can specify props for editable scroller as an object.
@@ -1040,4 +1044,4 @@ EditableWrapper.propTypes = /** @lends limestone/Scroller.EditableWrapper.protot
1040
1044
  */
1041
1045
  scrollContentRef: _propTypes["default"].ref
1042
1046
  };
1043
- var _default = exports["default"] = EditableWrapper;
1047
+ var _default = exports["default"] = _EditableWrapper;
@@ -15,7 +15,7 @@ var _I18nDecorator = require("@enact/i18n/I18nDecorator");
15
15
  var _SpotlightContainerDecorator = _interopRequireDefault(require("@enact/spotlight/SpotlightContainerDecorator"));
16
16
  var _Spottable = _interopRequireDefault(require("@enact/spotlight/Spottable"));
17
17
  var _Resizable = require("@enact/ui/Resizable");
18
- var _Scroller = require("@enact/ui/Scroller");
18
+ var _Scroller2 = require("@enact/ui/Scroller");
19
19
  var _classnames = _interopRequireDefault(require("classnames"));
20
20
  var _propTypes = _interopRequireDefault(require("prop-types"));
21
21
  var _react = require("react");
@@ -97,8 +97,9 @@ var scrollerDefaultProps = {
97
97
  * @ui
98
98
  * @public
99
99
  */
100
- var Scroller = exports.Scroller = function Scroller(props) {
100
+ var _Scroller = exports.Scroller = function Scroller(props) {
101
101
  var scrollerProps = (0, _util.setDefaultProps)(props, scrollerDefaultProps);
102
+ (0, _util.checkPropTypes)(_Scroller, scrollerProps);
102
103
  if (typeof ENACT_PACK_NO_ANIMATION !== 'undefined' && ENACT_PACK_NO_ANIMATION) {
103
104
  scrollerProps.overscrollEffectOn = {
104
105
  arrowKey: false,
@@ -146,7 +147,7 @@ var Scroller = exports.Scroller = function Scroller(props) {
146
147
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Resizable.ResizeContext, _objectSpread(_objectSpread({}, resizeContextProps), {}, {
147
148
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ScrollContentWrapper, _objectSpread(_objectSpread(_objectSpread({}, scrollContainerProps), scrollContentWrapperRest), {}, {
148
149
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(ScrollBody, _objectSpread(_objectSpread({}, focusableBodyProps), {}, {
149
- children: [rest.focusableScrollbar ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollbarPlaceholder["default"], {}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroller.ScrollerBasic, _objectSpread(_objectSpread({}, themeScrollContentProps), {}, {
150
+ children: [rest.focusableScrollbar ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollbarPlaceholder["default"], {}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroller2.ScrollerBasic, _objectSpread(_objectSpread({}, themeScrollContentProps), {}, {
150
151
  "aria-label": ariaLabel,
151
152
  id: id,
152
153
  ref: scrollContentHandle,
@@ -156,8 +157,8 @@ var Scroller = exports.Scroller = function Scroller(props) {
156
157
  }))
157
158
  }));
158
159
  };
159
- Scroller.displayName = 'Scroller';
160
- Scroller.propTypes = /** @lends limestone/Scroller.Scroller.prototype */{
160
+ _Scroller.displayName = 'Scroller';
161
+ _Scroller.propTypes = /** @lends limestone/Scroller.Scroller.prototype */{
161
162
  /**
162
163
  * The "aria-label" for the Scroller.
163
164
  *
@@ -464,13 +465,13 @@ Scroller.propTypes = /** @lends limestone/Scroller.Scroller.prototype */{
464
465
  */
465
466
  verticalScrollThumbAriaLabel: _propTypes["default"].string
466
467
  };
467
- var ScrollerBase = exports.ScrollerBase = Scroller;
468
- exports.Scroller = Scroller = (0, _Skinnable["default"])((0, _SpotlightContainerDecorator["default"])({
468
+ var ScrollerBase = exports.ScrollerBase = _Scroller;
469
+ exports.Scroller = _Scroller = (0, _Skinnable["default"])((0, _SpotlightContainerDecorator["default"])({
469
470
  overflow: true,
470
471
  preserveId: true,
471
472
  restrict: 'self-first'
472
473
  }, (0, _I18nDecorator.I18nContextDecorator)({
473
474
  rtlProp: 'rtl'
474
- }, Scroller)));
475
- Scroller.defaultPropValues = scrollerDefaultProps;
476
- var _default = exports["default"] = Scroller;
475
+ }, _Scroller)));
476
+ _Scroller.defaultPropValues = scrollerDefaultProps;
477
+ var _default = exports["default"] = _Scroller;
@@ -15,6 +15,16 @@
15
15
  border-radius: var(--primitive-radius-12);
16
16
  opacity: 0;
17
17
  }
18
+ .focusableBody.hasVerticalScrollbar::before {
19
+ right: var(--scroll-scrollbar-size);
20
+ }
21
+ .focusableBody.hasHorizontalScrollbar::before {
22
+ bottom: var(--scroll-scrollbar-size);
23
+ }
24
+ :global(.enact-locale-right-to-left) .focusableBody.hasVerticalScrollbar::before {
25
+ right: 0;
26
+ left: var(--scroll-scrollbar-size);
27
+ }
18
28
  :global(.spotlight-input-key):global(.spotlight-input-key) .focusableBody:global(.spottable):focus::before,
19
29
  :global(.spotlight-input-key):global(.spotlight-input-mouse) .focusableBody:global(.spottable):focus::before {
20
30
  background-color: color(from var(--semantic-color-surface-default-focused) srgb r g b / 0.1);
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
 
3
3
  require("@testing-library/jest-dom");
4
+ var _spotlight = _interopRequireDefault(require("@enact/spotlight"));
4
5
  var _react = require("@testing-library/react");
6
+ var _react2 = require("react");
5
7
  var _Scroller = _interopRequireDefault(require("../Scroller"));
6
8
  var _jsxRuntime = require("react/jsx-runtime");
7
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
@@ -66,7 +68,7 @@ describe('Scroller', function () {
66
68
  });
67
69
  });
68
70
  describe('focusable Scrollbar', function () {
69
- test('should have focuable body and thumb when \'focusableScrollbar\' is "byEnter"', function () {
71
+ test('should have focusable body and thumb when \'focusableScrollbar\' is "byEnter"', function () {
70
72
  var id = 'scroller';
71
73
  (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroller["default"], {
72
74
  "data-testid": id,
@@ -86,7 +88,7 @@ describe('Scroller', function () {
86
88
  expect(scrollBody).toHaveClass(expected);
87
89
  expect(verticalScrollbar).toHaveClass(expected);
88
90
  });
89
- test('should have focuable scroll thumb when \'focusableScrollbar\' is true', function () {
91
+ test('should have focusable scroll thumb when \'focusableScrollbar\' is true', function () {
90
92
  var id = 'scroller';
91
93
  (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroller["default"], {
92
94
  "data-testid": id,
@@ -101,6 +103,93 @@ describe('Scroller', function () {
101
103
  expect(scrollBody).not.toHaveClass(expected);
102
104
  expect(verticalScrollbar).toHaveClass(expected);
103
105
  });
106
+ describe('ScrollbarPlaceholder focus restoration', function () {
107
+ var focusSpy, pointerModeSpy, currentSpy, pausedSpy, containerSpy;
108
+ var placeholderElement;
109
+ var renderWithFocusedPlaceholder = function renderWithFocusedPlaceholder() {
110
+ placeholderElement = null;
111
+ currentSpy.mockImplementation(function () {
112
+ return placeholderElement;
113
+ });
114
+ var onRender = function onRender(id, phase) {
115
+ if (phase === 'mount') {
116
+ placeholderElement = document.querySelector('[data-spotlight-ignore-restore]');
117
+ }
118
+ };
119
+ var view = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.Profiler, {
120
+ id: "placeholder",
121
+ onRender: onRender,
122
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scroller["default"], {
123
+ focusableScrollbar: "byEnter",
124
+ verticalScrollbar: "visible",
125
+ children: contents
126
+ })
127
+ }));
128
+ currentSpy.mockImplementation(function () {
129
+ return null;
130
+ });
131
+ focusSpy.mockClear();
132
+ return view;
133
+ };
134
+ beforeEach(function () {
135
+ jest.useFakeTimers();
136
+ focusSpy = jest.spyOn(_spotlight["default"], 'focus').mockImplementation(function () {
137
+ return true;
138
+ });
139
+ pointerModeSpy = jest.spyOn(_spotlight["default"], 'getPointerMode').mockReturnValue(false);
140
+ currentSpy = jest.spyOn(_spotlight["default"], 'getCurrent').mockReturnValue(null);
141
+ pausedSpy = jest.spyOn(_spotlight["default"], 'isPaused').mockReturnValue(false);
142
+ containerSpy = jest.spyOn(_spotlight["default"], 'getActiveContainer').mockReturnValue('active-container');
143
+ });
144
+ afterEach(function () {
145
+ focusSpy.mockRestore();
146
+ pointerModeSpy.mockRestore();
147
+ currentSpy.mockRestore();
148
+ pausedSpy.mockRestore();
149
+ containerSpy.mockRestore();
150
+ jest.useRealTimers();
151
+ });
152
+ test('should focus the active container after the placeholder disappears', function () {
153
+ renderWithFocusedPlaceholder();
154
+ (0, _react.act)(function () {
155
+ return jest.advanceTimersByTime(0);
156
+ });
157
+ expect(focusSpy).toHaveBeenCalledWith('active-container', {
158
+ toOuterContainer: true
159
+ });
160
+ });
161
+ test('should not focus when pointer mode is active', function () {
162
+ pointerModeSpy.mockReturnValue(true);
163
+ renderWithFocusedPlaceholder();
164
+ (0, _react.act)(function () {
165
+ return jest.advanceTimersByTime(0);
166
+ });
167
+ expect(focusSpy).not.toHaveBeenCalled();
168
+ });
169
+ test('should defer focus while spotlight is paused, then focus after 400ms once it unpauses', function () {
170
+ pausedSpy.mockReturnValue(true);
171
+ renderWithFocusedPlaceholder();
172
+ (0, _react.act)(function () {
173
+ return jest.advanceTimersByTime(0);
174
+ });
175
+ expect(focusSpy).not.toHaveBeenCalled();
176
+ pausedSpy.mockReturnValue(false);
177
+ (0, _react.act)(function () {
178
+ return jest.advanceTimersByTime(400);
179
+ });
180
+ expect(focusSpy).toHaveBeenCalledWith('active-container', {
181
+ toOuterContainer: true
182
+ });
183
+ });
184
+ test('should not focus after the 400ms retry if spotlight is still paused', function () {
185
+ pausedSpy.mockReturnValue(true);
186
+ renderWithFocusedPlaceholder();
187
+ (0, _react.act)(function () {
188
+ return jest.advanceTimersByTime(400);
189
+ });
190
+ expect(focusSpy).not.toHaveBeenCalled();
191
+ });
192
+ });
104
193
  });
105
194
  describe('Scrollbar accessibility', function () {
106
195
  test('should set a custom "aria-label" to the scroll thumb in the horizontal scroll bar', function () {
@@ -128,12 +128,12 @@ var useSpottable = function useSpottable(props, instances) {
128
128
  var _useEventKey = (0, _useEvent.useEventKey)(),
129
129
  addGlobalKeyDownEventListener = _useEventKey.addGlobalKeyDownEventListener,
130
130
  removeGlobalKeyDownEventListener = _useEventKey.removeGlobalKeyDownEventListener;
131
- var setContainerDisabled = (0, _react.useCallback)(function (bool) {
131
+ var setContainerDisabled = (0, _react.useCallback)(function self(bool) {
132
132
  if (scrollContainerRef.current) {
133
133
  scrollContainerRef.current.dataset.spotlightContainerDisabled = bool;
134
134
  if (bool) {
135
135
  addGlobalKeyDownEventListener(function () {
136
- setContainerDisabled(false);
136
+ self(false);
137
137
  });
138
138
  } else {
139
139
  removeGlobalKeyDownEventListener();
@@ -377,6 +377,9 @@ var useThemeScroller = exports.useThemeScroller = function useThemeScroller(prop
377
377
  var _ref3 = props.focusableScrollbar === 'byEnter' ? getFocusableBodyProps(scrollContainerRef, contentId, isScrollbarVisible) : {},
378
378
  setNavigableFilter = _ref3.setNavigableFilter,
379
379
  focusableBodyProps = _objectWithoutProperties(_ref3, _excluded2);
380
+ if (focusableBodyProps.className) {
381
+ focusableBodyProps.className = (0, _classnames["default"])(focusableBodyProps.className, isVerticalScrollbarVisible && _ScrollerModule["default"].hasVerticalScrollbar, isHorizontalScrollbarVisible && _ScrollerModule["default"].hasHorizontalScrollbar);
382
+ }
380
383
  (0, _react.useLayoutEffect)(function () {
381
384
  // Initial filter setting
382
385
  if (setNavigableFilter) {
@@ -384,7 +387,7 @@ var useThemeScroller = exports.useThemeScroller = function useThemeScroller(prop
384
387
  filterTarget: 'body'
385
388
  });
386
389
  }
387
- }, [props.focusableScrollbar, scrollContainerRef.current]); // eslint-disable-line react-hooks/exhaustive-deps
390
+ }, [props.focusableScrollbar, scrollContainerRef]); // eslint-disable-line react-hooks/exhaustive-deps
388
391
 
389
392
  scrollContentProps.setThemeScrollContentHandle({
390
393
  calculatePositionOnFocus: calculatePositionOnFocus,
@@ -24,6 +24,10 @@ input keys.
24
24
  * Sets the knob to selected state and allows it to move via 5-way controls.
25
25
  */
26
26
  active?: boolean;
27
+ /**
28
+ * Indicates if this component will be used as a colorPicker.
29
+ */
30
+ colorPicker?: boolean;
27
31
  /**
28
32
  * Customizes the component by mapping the supplied collection of CSS class names to the
29
33
  corresponding internal elements and states of this component.
package/Slider/Slider.js CHANGED
@@ -36,7 +36,7 @@ var _SliderBehaviorDecorator = _interopRequireDefault(require("./SliderBehaviorD
36
36
  var _utils = require("./utils");
37
37
  var _SliderModule = _interopRequireDefault(require("./Slider.module.css"));
38
38
  var _jsxRuntime = require("react/jsx-runtime");
39
- var _excluded = ["active", "className", "css", "disabled", "focused", "keyFrequency", "max", "min", "pressed", "showAnchor", "showMinMax"];
39
+ var _excluded = ["active", "className", "colorPicker", "css", "disabled", "focused", "keyFrequency", "max", "min", "pressed", "showAnchor", "showMinMax"];
40
40
  /**
41
41
  * Provides Limestone-themed slider components and behaviors.
42
42
  *
@@ -66,6 +66,7 @@ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t =
66
66
  var sliderDefaultProps = {
67
67
  activateOnSelect: false,
68
68
  active: false,
69
+ colorPicker: false,
69
70
  disabled: false,
70
71
  keyFrequency: [1],
71
72
  max: 100,
@@ -86,10 +87,12 @@ var sliderDefaultProps = {
86
87
  * @ui
87
88
  * @public
88
89
  */
89
- var SliderBase = exports.SliderBase = function SliderBase(props) {
90
+ var _SliderBase = exports.SliderBase = function SliderBase(props) {
90
91
  var sliderProps = (0, _util.setDefaultProps)(props, sliderDefaultProps);
92
+ (0, _util.checkPropTypes)(_SliderBase, sliderProps);
91
93
  var active = sliderProps.active,
92
94
  className = sliderProps.className,
95
+ colorPicker = sliderProps.colorPicker,
93
96
  css = sliderProps.css,
94
97
  disabled = sliderProps.disabled,
95
98
  focused = sliderProps.focused,
@@ -114,12 +117,13 @@ var SliderBase = exports.SliderBase = function SliderBase(props) {
114
117
  valueName: 'max'
115
118
  })(sliderProps);
116
119
  var tooltip = sliderProps.tooltip === true ? _ProgressBar2.ProgressBarTooltip : sliderProps.tooltip;
120
+ var context = (0, _react.useMemo)(function () {
121
+ return {
122
+ lastWheelTimeStamp: 0
123
+ };
124
+ }, []);
117
125
  var spotlightAccelerator = (0, _react.useRef)();
118
126
  var ref = (0, _react.useRef)();
119
- var _useRef = (0, _react.useRef)({
120
- lastWheelTimeStamp: 0
121
- }),
122
- context = _useRef.current;
123
127
  var handlers = (0, _useHandlers["default"])({
124
128
  onBlur: (0, _handle.handle)((0, _handle.forward)('onBlur'), (0, _handle.forProp)('active', true), (0, _handle.forward)('onActivate')),
125
129
  onKeyDown: (0, _handle.handle)((0, _handle.forProp)('disabled', false), (0, _handle.forwardWithPrevent)('onKeyDown'), (0, _anyPass["default"])([_utils.handleIncrement, _utils.handleDecrement])),
@@ -135,7 +139,7 @@ var SliderBase = exports.SliderBase = function SliderBase(props) {
135
139
  customCss: css,
136
140
  publicClassNames: true
137
141
  });
138
- var componentClassName = (0, _classnames2["default"])(_SliderModule["default"].slider, className, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, mergedCss.active, active), mergedCss.hasMinMax, showMinMax), mergedCss.pressed, pressed), mergedCss.showAnchor, showAnchor), css && css.slider);
142
+ var componentClassName = (0, _classnames2["default"])(_SliderModule["default"].slider, className, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, mergedCss.active, active), mergedCss.colorPicker, colorPicker), mergedCss.hasMinMax, showMinMax), mergedCss.pressed, pressed), mergedCss.showAnchor, showAnchor), css && css.slider);
139
143
  (0, _react.useEffect)(function () {
140
144
  spotlightAccelerator.current = new _Accelerator["default"](keyFrequency);
141
145
  }, [keyFrequency]);
@@ -161,18 +165,30 @@ var SliderBase = exports.SliderBase = function SliderBase(props) {
161
165
  delete rest.step;
162
166
  delete rest.tooltip;
163
167
  delete rest.wheelInterval;
168
+ var sliderMax = colorPicker ? 360 : max;
169
+ var sliderMin = colorPicker ? 0 : min;
170
+ var sliderStep = colorPicker ? 1 : step;
171
+ var styleObject = {
172
+ '--semantic-color-surface-default-handle': "hsla(".concat(rest.value ? rest.value : 0, ", 100%, 50%, 1)"),
173
+ '--semantic-color-surface-default-focused': "hsla(".concat(rest.value ? rest.value : 0, ", 100%, 50%, 1)")
174
+ };
164
175
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Slider["default"], _objectSpread(_objectSpread(_objectSpread({}, rest), handlers), {}, {
165
176
  "aria-disabled": disabled,
177
+ colorPicker: colorPicker,
166
178
  className: componentClassName,
167
179
  css: mergedCss,
168
180
  disabled: disabled,
169
- max: max,
170
- min: min,
181
+ max: sliderMax,
182
+ min: sliderMin,
171
183
  progressBarComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ProgressBar["default"], {
172
- css: mergedCss
184
+ css: mergedCss,
185
+ style: {
186
+ backgroundImage: colorPicker && (0, _utils.hueGradient)(rest.orientation)
187
+ }
173
188
  }),
174
189
  ref: ref,
175
- step: step,
190
+ step: sliderStep,
191
+ style: colorPicker && styleObject,
176
192
  tooltipComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ComponentOverride["default"], {
177
193
  component: tooltip,
178
194
  css: mergedCss,
@@ -181,15 +197,15 @@ var SliderBase = exports.SliderBase = function SliderBase(props) {
181
197
  minMaxComponent: showMinMax ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
182
198
  className: mergedCss.minMax,
183
199
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
184
- children: min
200
+ children: sliderMin
185
201
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
186
- children: max
202
+ children: sliderMax
187
203
  })]
188
204
  }) : null
189
205
  }));
190
206
  };
191
- SliderBase.displayName = 'Slider';
192
- SliderBase.propTypes = /** @lends limestone/Slider.SliderBase.prototype */{
207
+ _SliderBase.displayName = 'Slider';
208
+ _SliderBase.propTypes = /** @lends limestone/Slider.SliderBase.prototype */{
193
209
  /**
194
210
  * Activates the component when selected so that it may be manipulated via the directional
195
211
  * input keys.
@@ -205,6 +221,14 @@ SliderBase.propTypes = /** @lends limestone/Slider.SliderBase.prototype */{
205
221
  * @public
206
222
  */
207
223
  active: _propTypes["default"].bool,
224
+ /**
225
+ * Indicates if this component will be used as a colorPicker.
226
+ *
227
+ * @type {Boolean}
228
+ * @default false
229
+ * @public
230
+ */
231
+ colorPicker: _propTypes["default"].bool,
208
232
  /**
209
233
  * Customizes the component by mapping the supplied collection of CSS class names to the
210
234
  * corresponding internal elements and states of this component.
@@ -457,7 +481,7 @@ var SliderDecorator = exports.SliderDecorator = (0, _compose["default"])(_Pure["
457
481
  * @public
458
482
  */
459
483
 
460
- var Slider = exports.Slider = SliderDecorator(SliderBase);
484
+ var Slider = exports.Slider = SliderDecorator(_SliderBase);
461
485
  Slider.defaultPropValues = sliderDefaultProps;
462
486
 
463
487
  /**