@enact/limestone 1.10.0 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  2. package/ActionGuide/ActionGuide.d.ts +1 -1
  3. package/ActionGuide/ActionGuide.module.css +7 -0
  4. package/Alert/Alert.d.ts +9 -0
  5. package/Alert/Alert.js +63 -21
  6. package/Alert/Alert.module.css +41 -9
  7. package/Alert/AlertImage.module.css +5 -1
  8. package/Alert/tests/Alert-specs.js +6 -2
  9. package/BodyText/BodyText.d.ts +1 -1
  10. package/BodyText/BodyText.js +14 -9
  11. package/BodyText/BodyText.module.css +22 -1
  12. package/Button/Button.d.ts +3 -3
  13. package/Button/Button.module.css +81 -63
  14. package/CHANGELOG.md +87 -0
  15. package/Card/Card.d.ts +81 -9
  16. package/Card/Card.js +324 -84
  17. package/Card/Card.module.css +200 -25
  18. package/Card/tests/Card-specs.js +100 -0
  19. package/Checkbox/Checkbox.d.ts +2 -2
  20. package/Checkbox/Checkbox.module.css +2 -5
  21. package/CheckboxItem/CheckboxItem.d.ts +8 -1
  22. package/CheckboxItem/CheckboxItem.js +39 -12
  23. package/CheckboxItem/CheckboxItem.module.css +228 -4
  24. package/Chips/Chip.module.css +5 -2
  25. package/ContextualMenuDecorator/ContextualMenuDecorator.d.ts +2 -2
  26. package/ContextualPopupDecorator/ContextualPopup.module.css +1 -1
  27. package/ContextualPopupDecorator/ContextualPopupDecorator.js +2 -4
  28. package/ContextualPopupDecorator/tests/ContextualPopupDecorator-specs.js +39 -2
  29. package/Dropdown/Dropdown.d.ts +2 -2
  30. package/Dropdown/Dropdown.module.css +7 -7
  31. package/FixedPopupPanels/FixedPopupPanels.d.ts +2 -2
  32. package/FlexiblePopupPanels/FlexiblePopupPanels.module.css +15 -3
  33. package/FlexiblePopupPanels/index.d.ts +2 -2
  34. package/FormCheckboxItem/FormCheckboxItem.d.ts +1 -1
  35. package/FormCheckboxItem/FormCheckboxItem.js +1 -0
  36. package/FormCheckboxItem/FormCheckboxItem.module.css +1 -1
  37. package/Heading/Heading.d.ts +2 -2
  38. package/Heading/Heading.module.css +16 -0
  39. package/Icon/Icon.d.ts +22 -1
  40. package/Icon/Icon.js +21 -0
  41. package/Icon/Icon.module.css +12 -0
  42. package/Icon/IconList.js +43 -1
  43. package/IconItem/IconItem.d.ts +2 -2
  44. package/IconItem/IconItem.module.css +27 -14
  45. package/Image/Image.d.ts +1 -1
  46. package/Image/Image.module.css +1 -1
  47. package/ImageItem/ImageItem.d.ts +2 -2
  48. package/ImageItem/ImageItem.js +3 -16
  49. package/ImageItem/ImageItem.module.css +122 -97
  50. package/ImageItem/tests/ImageItem-specs.js +6 -5
  51. package/Input/Input.module.css +33 -16
  52. package/Input/InputField.module.css +22 -4
  53. package/Input/index.d.ts +1 -1
  54. package/Input/tests/Input-specs.js +2 -2
  55. package/Input/tests/InputField-specs.js +1 -1
  56. package/Item/Item.d.ts +2 -2
  57. package/Item/Item.module.css +29 -16
  58. package/KeyGuide/KeyGuide.d.ts +2 -2
  59. package/KeyGuide/KeyGuide.module.css +10 -0
  60. package/MediaOverlay/MediaOverlay.d.ts +2 -2
  61. package/MediaOverlay/MediaOverlay.module.css +18 -9
  62. package/MediaPlayer/MediaControls.module.css +3 -0
  63. package/MediaPlayer/MediaSlider.module.css +1 -0
  64. package/MediaPlayer/Times.module.css +5 -1
  65. package/MediaPlayer/index.d.ts +2 -2
  66. package/PageViews/PageViews.module.css +6 -1
  67. package/Panels/Header.module.css +74 -56
  68. package/Panels/Panel.module.css +1 -1
  69. package/Panels/index.d.ts +1 -1
  70. package/Picker/Picker.d.ts +1 -1
  71. package/Popup/Popup.module.css +4 -1
  72. package/PopupTabLayout/PopupTabLayout.d.ts +6 -6
  73. package/PopupTabLayout/PopupTabLayout.module.css +24 -6
  74. package/ProgressBar/ProgressBar.d.ts +1 -1
  75. package/ProgressBar/ProgressBar.module.css +12 -12
  76. package/ProgressBar/ProgressBarTooltip.module.css +7 -7
  77. package/ProgressButton/ProgressButton.d.ts +2 -2
  78. package/QuickGuidePanels/QuickGuidePanels.module.css +1 -1
  79. package/RadioItem/RadioItem.d.ts +1 -1
  80. package/RadioItem/RadioItem.module.css +21 -18
  81. package/Scroller/EditableWrapper.js +2 -1
  82. package/Scroller/Scroller.d.ts +12 -0
  83. package/Scroller/Scroller.js +15 -0
  84. package/Scroller/Scroller.module.css +10 -0
  85. package/Scroller/tests/Scroller-specs.js +120 -2
  86. package/Scroller/useThemeScroller.js +25 -2
  87. package/Slider/Slider.d.ts +1 -1
  88. package/Slider/Slider.module.css +539 -303
  89. package/Spinner/Spinner.d.ts +1 -1
  90. package/Spinner/Spinner.module.css +2 -2
  91. package/Steps/Steps.d.ts +1 -1
  92. package/Steps/Steps.js +12 -6
  93. package/Steps/Steps.module.css +19 -2
  94. package/Switch/Switch.module.css +17 -6
  95. package/SwitchItem/SwitchItem.d.ts +1 -1
  96. package/TabLayout/RefocusDecorator.js +1 -1
  97. package/TabLayout/TabGroup.module.css +13 -7
  98. package/TabLayout/TabLayout.js +4 -0
  99. package/ThemeDecorator/ThemeDecorator.d.ts +1 -1
  100. package/ThemeDecorator/ThemeDecorator.module.css +22 -1
  101. package/TimePicker/TimePicker.module.css +3 -0
  102. package/TooltipDecorator/Tooltip.js +68 -7
  103. package/TooltipDecorator/Tooltip.module.css +44 -23
  104. package/TooltipDecorator/TooltipDecorator.d.ts +52 -0
  105. package/TooltipDecorator/TooltipDecorator.js +42 -0
  106. package/TooltipDecorator/TooltipLabel.js +67 -14
  107. package/TooltipDecorator/tests/TooltipDecorator-specs.js +46 -0
  108. package/TooltipDecorator/useTooltip.js +14 -2
  109. package/VideoPlayer/Feedback.module.css +3 -0
  110. package/VideoPlayer/FeedbackTooltip.module.css +7 -0
  111. package/VideoPlayer/MediaTitle.module.css +9 -1
  112. package/VirtualList/VirtualList.d.ts +24 -0
  113. package/VirtualList/VirtualList.js +30 -0
  114. package/VirtualList/tests/stickTo-specs.js +115 -0
  115. package/VirtualList/tests/useEvent-specs.js +39 -0
  116. package/VirtualList/useEvent.js +45 -10
  117. package/VirtualList/useThemeVirtualList.js +20 -2
  118. package/WizardPanels/WizardPanels.module.css +1 -1
  119. package/fonts/Limestone_Icons.ttf +0 -0
  120. package/internal/DateComponentPicker/DateComponentPicker.module.css +3 -3
  121. package/internal/DateTime/DateTime.module.css +3 -0
  122. package/internal/Picker/Picker.js +8 -10
  123. package/internal/Picker/Picker.module.css +92 -137
  124. package/package.json +14 -17
  125. package/styles/color-mixins.less +4 -60
  126. package/styles/colors-game.less +5 -5
  127. package/styles/colors.less +9 -10
  128. package/styles/mixins.less +0 -46
  129. package/styles/motion-mixins.less +16 -7
  130. package/styles/motions.less +2 -2
  131. package/styles/variables.less +186 -69
  132. package/useScroll/ScrollbarPlaceholder.js +8 -3
  133. package/useScroll/useScroll.js +3 -1
@@ -456,6 +456,21 @@ _VirtualList.propTypes = /** @lends limestone/VirtualList.VirtualList.prototype
456
456
  * @public
457
457
  */
458
458
  spotlightId: _propTypes["default"].string,
459
+ /**
460
+ * Anchors the focused item to a fixed "focus position" at the start edge while the list scrolls
461
+ * beneath it.
462
+ *
463
+ * When set to `'start'`, moving focus with 5-way keys keeps the focus indicator at a fixed slot
464
+ * at the start of the list (top for vertical, leading edge for horizontal) and scrolls so the
465
+ * newly focused item lands in that slot. At the end of the list, the list scrolls only to its
466
+ * last position so the focused item stays visible.
467
+ *
468
+ * This is ignored when `snapToCenter` is set.
469
+ *
470
+ * @type {('start')}
471
+ * @public
472
+ */
473
+ stickTo: _propTypes["default"].oneOf(['start']),
459
474
  /**
460
475
  * Specifies how to show vertical scrollbar.
461
476
  *
@@ -908,6 +923,21 @@ _VirtualGridList.propTypes = /** @lends limestone/VirtualList.VirtualGridList.pr
908
923
  * @public
909
924
  */
910
925
  spotlightId: _propTypes["default"].string,
926
+ /**
927
+ * Anchors the focused item to a fixed "focus position" at the start edge while the list scrolls
928
+ * beneath it.
929
+ *
930
+ * When set to `'start'`, moving focus with 5-way keys keeps the focus indicator at a fixed slot
931
+ * at the start of the list (top for vertical, leading edge for horizontal) and scrolls so the
932
+ * newly focused item lands in that slot. At the end of the list, the list scrolls only to its
933
+ * last position so the focused item stays visible.
934
+ *
935
+ * This is ignored when `snapToCenter` is set.
936
+ *
937
+ * @type {('start')}
938
+ * @public
939
+ */
940
+ stickTo: _propTypes["default"].oneOf(['start']),
911
941
  /**
912
942
  * Specifies how to show vertical scrollbar.
913
943
  *
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+
3
+ require("@testing-library/jest-dom");
4
+ var _spotlight = _interopRequireDefault(require("@enact/spotlight"));
5
+ var _react = require("@testing-library/react");
6
+ var _Item = _interopRequireDefault(require("../../Item"));
7
+ var _VirtualList = _interopRequireDefault(require("../VirtualList"));
8
+ var _jsxRuntime = require("react/jsx-runtime");
9
+ var _excluded = ["index"]; // These tests exercise the `stickTo="start"` scroll behavior added to `useThemeVirtualList`. They
10
+ // live in their own file because they depend on a clean Spotlight instance.
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ 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; }
13
+ 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; }
14
+ 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; }
15
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
16
+ 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); }
17
+ 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; }
18
+ 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; }
19
+ var focus = function focus(elm) {
20
+ return _react.fireEvent.focus(elm);
21
+ };
22
+ var keyDownUp = function keyDownUp(keyCode) {
23
+ return function (elm) {
24
+ _react.fireEvent.keyDown(elm, {
25
+ keyCode: keyCode
26
+ });
27
+ return _react.fireEvent.keyUp(elm, {
28
+ keyCode: keyCode
29
+ });
30
+ };
31
+ };
32
+ var pressDownKey = keyDownUp(40);
33
+ describe('VirtualList stickTo="start"', function () {
34
+ var clientSize, currentFocusIndex, dataSize, handlerOnFocus, items, itemSize, renderItem;
35
+ beforeEach(function () {
36
+ clientSize = {
37
+ clientWidth: 1280,
38
+ clientHeight: 720
39
+ };
40
+ currentFocusIndex = -1;
41
+ dataSize = 200;
42
+ items = [];
43
+ itemSize = 60;
44
+ handlerOnFocus = function handlerOnFocus(index) {
45
+ return function () {
46
+ currentFocusIndex = index;
47
+ };
48
+ };
49
+ renderItem = function renderItem(_ref) {
50
+ var index = _ref.index,
51
+ rest = _objectWithoutProperties(_ref, _excluded);
52
+ // eslint-disable-line enact/display-name
53
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Item["default"], _objectSpread(_objectSpread({}, rest), {}, {
54
+ onFocus: handlerOnFocus(index),
55
+ children: items[index].name
56
+ }));
57
+ };
58
+ for (var i = 0; i < dataSize; i++) {
59
+ items.push({
60
+ name: 'Account ' + i
61
+ });
62
+ }
63
+ });
64
+ afterEach(function () {
65
+ clientSize = null;
66
+ dataSize = null;
67
+ handlerOnFocus = null;
68
+ items = null;
69
+ itemSize = null;
70
+ renderItem = null;
71
+ });
72
+ test('should scroll to anchor the focused item at the start slot on 5-way navigation', function () {
73
+ var spy = jest.fn(function () {});
74
+ var scrollToFn = global.Element.prototype.scrollTo;
75
+ global.Element.prototype.scrollTo = spy;
76
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_VirtualList["default"], {
77
+ clientSize: clientSize,
78
+ dataSize: dataSize,
79
+ itemRenderer: renderItem,
80
+ itemSize: itemSize,
81
+ stickTo: "start"
82
+ }));
83
+ var list = _react.screen.getByRole('list');
84
+ var item13 = list.children.item(13).children.item(0);
85
+ focus(item13);
86
+ expect(currentFocusIndex).toBe(13);
87
+ pressDownKey(item13);
88
+ expect(currentFocusIndex).toBe(14);
89
+ expect(spy).toHaveBeenCalled();
90
+ global.Element.prototype.scrollTo = scrollToFn;
91
+ });
92
+ test('should scroll a focused item to the start slot', function () {
93
+ var spy = jest.fn(function () {});
94
+ var scrollToFn = global.Element.prototype.scrollTo;
95
+ global.Element.prototype.scrollTo = spy;
96
+ var pointerSpy = jest.spyOn(_spotlight["default"], 'getPointerMode').mockReturnValue(false);
97
+ var currentSpy = jest.spyOn(_spotlight["default"], 'getCurrent');
98
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_VirtualList["default"], {
99
+ clientSize: clientSize,
100
+ dataSize: dataSize,
101
+ direction: "horizontal",
102
+ itemRenderer: renderItem,
103
+ itemSize: itemSize,
104
+ stickTo: "start"
105
+ }));
106
+ var list = _react.screen.getByRole('list');
107
+ var node = list.querySelector('[data-index="13"]');
108
+ currentSpy.mockReturnValue(node);
109
+ _react.fireEvent.focusIn(node);
110
+ expect(spy).toHaveBeenCalled();
111
+ currentSpy.mockRestore();
112
+ pointerSpy.mockRestore();
113
+ global.Element.prototype.scrollTo = scrollToFn;
114
+ });
115
+ });
@@ -27,6 +27,14 @@ var keyDownUp = function keyDownUp(keyCode) {
27
27
  });
28
28
  };
29
29
  };
30
+ var keyDownRepeat = function keyDownRepeat(keyCode) {
31
+ return function (elm) {
32
+ return _react.fireEvent.keyDown(elm, {
33
+ keyCode: keyCode,
34
+ repeat: true
35
+ });
36
+ };
37
+ };
30
38
  var pressLeftKey = keyDownUp(37);
31
39
  var pressRightKey = keyDownUp(39);
32
40
  var pressUpKey = keyDownUp(38);
@@ -148,6 +156,37 @@ describe('VirtualList useEvent', function () {
148
156
  expect(spy).toHaveBeenCalled();
149
157
  global.Element.prototype.scrollTo = scrollToFn;
150
158
  });
159
+ test('should handle repeat keydown on first VirtualList entry without error', function () {
160
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_VirtualList["default"], {
161
+ clientSize: clientSize,
162
+ dataSize: dataSize,
163
+ itemRenderer: renderItem,
164
+ itemSize: itemSize
165
+ }));
166
+ var list = _react.screen.getByRole('list');
167
+ var item0 = list.children.item(0).children.item(0);
168
+ focus(item0);
169
+ expect(currentFocusIndex).toBe(0);
170
+ keyDownRepeat(40)(item0);
171
+ expect(currentFocusIndex).toBe(0);
172
+ });
173
+ test('should handle repeat keydown when data-index jumps unexpectedly without error', function () {
174
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_VirtualList["default"], {
175
+ clientSize: clientSize,
176
+ dataSize: dataSize,
177
+ itemRenderer: renderItem,
178
+ itemSize: itemSize
179
+ }));
180
+ var list = _react.screen.getByRole('list');
181
+ var item0 = list.children.item(0).children.item(0);
182
+ var item1 = list.children.item(1).children.item(0);
183
+ focus(item0);
184
+ pressDownKey(item0);
185
+ expect(currentFocusIndex).toBe(1);
186
+ item1.dataset.index = '20';
187
+ keyDownRepeat(40)(item1);
188
+ expect(currentFocusIndex).toBe(1);
189
+ });
151
190
  test('should scroll by page-down key', function () {
152
191
  var spy = jest.fn(function () {});
153
192
  var scrollToFn = global.Element.prototype.scrollTo;
@@ -28,13 +28,14 @@ var isDown = (0, _keymap.is)('down'),
28
28
  // should return -1 if index is not a number or a negative value
29
29
  return number >= 0 ? number : -1;
30
30
  };
31
- var prevKeyDownIndex = -1;
32
31
  var useEventKey = exports.useEventKey = function useEventKey(props, instances, context) {
33
32
  // Mutable value
34
33
 
35
34
  var mutableRef = (0, _react.useRef)({
36
35
  fn: null
37
36
  });
37
+ var prevKeyDownIndexRef = (0, _react.useRef)(-1);
38
+ var hasProcessedKeyDownRef = (0, _react.useRef)(false);
38
39
 
39
40
  // Functions
40
41
 
@@ -121,6 +122,7 @@ var useEventKey = exports.useEventKey = function useEventKey(props, instances, c
121
122
  var handle5WayKeyUp = context.handle5WayKeyUp,
122
123
  handleDirectionKeyDown = context.handleDirectionKeyDown,
123
124
  handlePageUpDownKeyDown = context.handlePageUpDownKeyDown,
125
+ resetAccelerator = context.resetAccelerator,
124
126
  spotlightAcceleratorProcessKey = context.spotlightAcceleratorProcessKey;
125
127
  function handleKeyDown(ev) {
126
128
  var keyCode = ev.keyCode,
@@ -163,15 +165,50 @@ var useEventKey = exports.useEventKey = function useEventKey(props, instances, c
163
165
  isRightMovement = _getNextIndex.isRightMovement,
164
166
  isWrapped = _getNextIndex.isWrapped,
165
167
  nextIndex = _getNextIndex.nextIndex;
168
+ var _scrollContentHandle$2 = scrollContentHandle.current,
169
+ dimensionToExtent = _scrollContentHandle$2.dimensionToExtent,
170
+ isPrimaryDirectionVertical = _scrollContentHandle$2.isPrimaryDirectionVertical;
171
+
172
+ // VirtualList recycles DOM nodes during scroll. If a node gets reused for a different index
173
+ // while browser focus stays on it, target.dataset.index reflects the new (wrong) index.
174
+ // Detect this by checking if the index jumped unnaturally during key repeat.
175
+ var isForwardKey = isPrimaryDirectionVertical ? isDownKey : isRightMovement;
176
+ var isBackwardKey = isPrimaryDirectionVertical ? isUpKey : isLeftMovement;
177
+ var isOutdatedIndex = repeat && prevKeyDownIndexRef.current !== -1 && (isForwardKey && (prevKeyDownIndexRef.current > index || index > prevKeyDownIndexRef.current + dimensionToExtent) || isBackwardKey && (prevKeyDownIndexRef.current < index || index < prevKeyDownIndexRef.current - dimensionToExtent));
178
+
179
+ // Block the first repeat event when entering VirtualList from outside with acceleration.
180
+ // prevKeyDownIndexRef is -1 only on first entry; a repeat here means key was held before entering.
181
+ var isFirstEntryRepeat = repeat && !hasProcessedKeyDownRef.current;
182
+ if (isFirstEntryRepeat) {
183
+ ev.preventDefault();
184
+ ev.stopPropagation();
185
+ resetAccelerator();
186
+ return;
187
+ }
188
+ if (isOutdatedIndex) {
189
+ ev.preventDefault();
190
+ ev.stopPropagation();
191
+ resetAccelerator();
192
+ var correctedNextIndex = isForwardKey ? prevKeyDownIndexRef.current + dimensionToExtent : prevKeyDownIndexRef.current - dimensionToExtent;
193
+ if (correctedNextIndex >= 0 && correctedNextIndex < props.dataSize) {
194
+ var currentItemNode = instances.itemRefs.current[prevKeyDownIndexRef.current % scrollContentHandle.current.state.numOfItems];
195
+ var correctedTarget = currentItemNode && parseInt(currentItemNode.dataset.index) === prevKeyDownIndexRef.current ? currentItemNode : target;
196
+ handleDirectionKeyDown(ev, 'acceleratedKeyDown', {
197
+ isWrapped: false,
198
+ keyCode: keyCode,
199
+ nextIndex: correctedNextIndex,
200
+ repeat: repeat,
201
+ target: correctedTarget
202
+ });
203
+ prevKeyDownIndexRef.current = correctedNextIndex;
204
+ }
205
+ // At list boundary: keep prevKeyDownIndexRef.current unchanged so next event stays recoverable
206
+ return;
207
+ }
166
208
  if (nextIndex >= 0) {
167
209
  // if the candidate is another item
168
210
  ev.preventDefault();
169
211
  ev.stopPropagation();
170
- if (repeat && prevKeyDownIndex !== -1 && (isDownKey && prevKeyDownIndex > index || isUpKey && prevKeyDownIndex < index)) {
171
- // Ignore keyEvent from item with wrong data-index (Workaround for data-index bug)
172
- // Sometimes keyDown event occurs before the data-index updated, it causes reverse focus change
173
- return;
174
- }
175
212
  if (props.scrollContainerHandle && props.scrollContainerHandle.current) {
176
213
  props.scrollContainerHandle.current.lastInputType = 'arrowKey';
177
214
  }
@@ -188,9 +225,6 @@ var useEventKey = exports.useEventKey = function useEventKey(props, instances, c
188
225
  focusableScrollbar = props.focusableScrollbar,
189
226
  isHorizontalScrollbarVisible = props.isHorizontalScrollbarVisible,
190
227
  isVerticalScrollbarVisible = props.isVerticalScrollbarVisible;
191
- var _scrollContentHandle$2 = scrollContentHandle.current,
192
- dimensionToExtent = _scrollContentHandle$2.dimensionToExtent,
193
- isPrimaryDirectionVertical = _scrollContentHandle$2.isPrimaryDirectionVertical;
194
228
  var column = index % dimensionToExtent;
195
229
  var row = (index - column) % dataSize / dimensionToExtent;
196
230
  var directions = {};
@@ -236,7 +270,8 @@ var useEventKey = exports.useEventKey = function useEventKey(props, instances, c
236
270
  }
237
271
  }
238
272
  }
239
- prevKeyDownIndex = index;
273
+ prevKeyDownIndexRef.current = index;
274
+ hasProcessedKeyDownRef.current = true;
240
275
  if (isLeaving) {
241
276
  handleDirectionKeyDown(ev, 'keyLeave');
242
277
  }
@@ -99,6 +99,9 @@ var useSpottable = function useSpottable(props, instances) {
99
99
  handle5WayKeyUp: function handle5WayKeyUp() {
100
100
  SpotlightAccelerator.reset();
101
101
  },
102
+ resetAccelerator: function resetAccelerator() {
103
+ SpotlightAccelerator.reset();
104
+ },
102
105
  spotlightAcceleratorProcessKey: function spotlightAcceleratorProcessKey(ev) {
103
106
  return SpotlightAccelerator.processKey(ev, nop);
104
107
  }
@@ -192,6 +195,10 @@ var useSpottable = function useSpottable(props, instances) {
192
195
  var index = getNumberValue(target.dataset.index);
193
196
  var direction = (0, _spotlight.getDirection)(keyCode);
194
197
  var allowAffordance = !(noAffordance || orientation === 'horizontal');
198
+ // When anchoring focus to the start slot, always scroll the newly focused item to that slot
199
+ // rather than leaving it in place when it happens to be already visible. `snapToCenter` is a
200
+ // more specific mode and keeps precedence.
201
+ var stickToStart = props.stickTo === 'start' && !snapToCenter;
195
202
  var shouldMove = snapToCenter ? nextIndex > 0 && nextIndex < dataSize - 1 && index > 0 : nextIndex >= 0 && index >= 0;
196
203
  mutableRef.current.isScrolledBy5way = false;
197
204
  mutableRef.current.isScrolledByJump = false;
@@ -203,7 +210,7 @@ var useSpottable = function useSpottable(props, instances) {
203
210
  startBoundary = scrollMode === 'native' ? scrollPosition : scrollPositionTarget,
204
211
  endBoundary = startBoundary + clientSize - (!allowAffordance ? 0 : _resolution["default"].scale(_useScroll.affordanceSize));
205
212
  mutableRef.current.lastFocusedIndex = nextIndex;
206
- if (start >= startBoundary && end <= endBoundary) {
213
+ if (!stickToStart && start >= startBoundary && end <= endBoundary) {
207
214
  // The next item could be still out of viewport. So we need to prevent scrolling into view with `isScrolledBy5way` flag.
208
215
  mutableRef.current.isScrolledBy5way = true;
209
216
  focusByIndex(nextIndex, direction);
@@ -213,6 +220,9 @@ var useSpottable = function useSpottable(props, instances) {
213
220
  } else if (!snapToCenter || !mutableRef.current.isScrollingBySnapToCenter) {
214
221
  var itemNode = getItemNode(nextIndex);
215
222
  var stickTo = Math.abs(endBoundary - end) < Math.abs(startBoundary - start) ? 'end' : 'start';
223
+ if (stickToStart) {
224
+ stickTo = 'start';
225
+ }
216
226
  stickTo = snapToCenter ? 'center' : stickTo;
217
227
  mutableRef.current.isScrolledBy5way = true;
218
228
  mutableRef.current.isWrappedBy5way = isWrapped;
@@ -286,6 +296,7 @@ var useSpottable = function useSpottable(props, instances) {
286
296
  var offsetToClientEnd = Math.max(0, primary.clientSize - (snapToCenter ? primary.gridSize : primary.itemSize) - (!allowAffordance ? 0 : _resolution["default"].scale(_useScroll.affordanceSize)));
287
297
  var focusedIndex = getNumberValue(item.getAttribute(_useScroll.dataIndexAttribute));
288
298
  var offsetToCenter = snapToCenter ? primary.clientSize / 2 - primary.gridSize / 2 : 0;
299
+ var stickToStart = props.stickTo === 'start' && !snapToCenter;
289
300
  if (focusedIndex >= 0) {
290
301
  var gridPosition = scrollContentHandle.current.getGridPosition(focusedIndex);
291
302
  if (numOfItems > 0 && focusedIndex % numOfItems !== mutableRef.current.lastFocusedIndex % numOfItems) {
@@ -296,7 +307,13 @@ var useSpottable = function useSpottable(props, instances) {
296
307
  }
297
308
  mutableRef.current.lastFocusedIndex = focusedIndex;
298
309
  if (primary.clientSize >= primary.itemSize) {
299
- if (gridPosition.primaryPosition > scrollPosition + offsetToClientEnd) {
310
+ if (stickToStart) {
311
+ // anchor to the start slot
312
+ // Clamp to the scroll bounds so that at the end of the list, the list stops at its
313
+ // last position while keeping the focused item visible.
314
+ var maxPos = scrollContentHandle.current.isPrimaryDirectionVertical ? scrollContentHandle.current.scrollBounds.maxTop : scrollContentHandle.current.scrollBounds.maxLeft;
315
+ gridPosition.primaryPosition = Math.max(0, Math.min(gridPosition.primaryPosition, maxPos));
316
+ } else if (gridPosition.primaryPosition > scrollPosition + offsetToClientEnd) {
300
317
  // forward over
301
318
  gridPosition.primaryPosition -= pageScroll ? 0 : offsetToClientEnd - offsetToCenter;
302
319
  } else if (gridPosition.primaryPosition >= scrollPosition) {
@@ -431,6 +448,7 @@ var useThemeVirtualList = exports.useThemeVirtualList = function useThemeVirtual
431
448
  delete rest.scrollContentHandle;
432
449
  delete rest.snapToCenter;
433
450
  delete rest.spotlightId;
451
+ delete rest.stickTo;
434
452
  delete rest.wrap;
435
453
  return _objectSpread(_objectSpread({}, rest), {}, {
436
454
  containerProps: {
@@ -7,7 +7,7 @@
7
7
  margin-top: calc(var(--primitive-spacing-84) * -1);
8
8
  }
9
9
  .wizardPanels .content {
10
- margin: var(--primitive-spacing-60) NaNrem - NaNrem - var(--primitive-spacing-36)));
10
+ margin: var(--primitive-spacing-60) calc(324px - calc(132px - var(--primitive-spacing-36)));
11
11
  }
12
12
  .wizardPanels .footer {
13
13
  text-align: center;
Binary file
@@ -5,14 +5,14 @@
5
5
  vertical-align: inherit;
6
6
  }
7
7
  .dateComponentPicker .label {
8
+ text-align: center;
9
+ white-space: nowrap;
8
10
  font-weight: var(--primitive-font-weight-regular);
9
11
  font-size: var(--primitive-font-size-60);
10
12
  font-style: normal;
11
13
  font-family: "Limestone";
12
- line-height: 1.4em;
13
- text-align: center;
14
+ line-height: 1.34em;
14
15
  padding: 0.75rem 1rem;
15
- white-space: nowrap;
16
16
  }
17
17
  :global(.enact-locale-non-latin) .dateComponentPicker .label {
18
18
  font-family: "Limestone";
@@ -19,6 +19,9 @@
19
19
  .dateTime .pickers > *:nth-last-child(2) {
20
20
  margin-inline-end: 0;
21
21
  }
22
+ .dateTime:global(.largeText) .heading {
23
+ font-size: var(--primitive-font-size-80);
24
+ }
22
25
  .dateTime:global(.neutral) .heading {
23
26
  color: var(--semantic-color-on-background-main);
24
27
  }
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "PickerItem", {
11
11
  }
12
12
  });
13
13
  exports["default"] = void 0;
14
- var _classnames3 = _interopRequireDefault(require("classnames"));
14
+ var _classnames2 = _interopRequireDefault(require("classnames"));
15
15
  var _handle = require("@enact/core/handle");
16
16
  var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));
17
17
  var _keymap = require("@enact/core/keymap");
@@ -27,6 +27,7 @@ var _spotlight = _interopRequireWildcard(require("@enact/spotlight"));
27
27
  var _propTypes2 = _interopRequireDefault(require("prop-types"));
28
28
  var _react = require("react");
29
29
  var _Skinnable = _interopRequireDefault(require("../../Skinnable"));
30
+ var _Steps = _interopRequireDefault(require("../../Steps"));
30
31
  var _$L = _interopRequireDefault(require("../$L"));
31
32
  var _validators = require("../validators");
32
33
  var _util2 = require("../util");
@@ -418,7 +419,7 @@ var _PickerBase = function PickerBase(props) {
418
419
  }, [hasReachedBound, orientation, props, step]);
419
420
  var determineClasses = (0, _react.useCallback)(function (cssProps, decrementerDisabledProp, incrementerDisabledProp) {
420
421
  var classNameVariable = props.className;
421
- return (0, _classnames3["default"])(cssProps.picker, cssProps[changedBy], cssProps[orientation], cssProps[width], _defineProperty(_defineProperty(_defineProperty({}, cssProps.joined, joined), cssProps.decrementing, !decrementerDisabledProp && pressed === -1), cssProps.incrementing, !incrementerDisabledProp && pressed === 1), classNameVariable);
422
+ return (0, _classnames2["default"])(cssProps.picker, cssProps[changedBy], cssProps[orientation], cssProps[width], _defineProperty(_defineProperty(_defineProperty({}, cssProps.joined, joined), cssProps.decrementing, !decrementerDisabledProp && pressed === -1), cssProps.incrementing, !incrementerDisabledProp && pressed === 1), classNameVariable);
422
423
  }, [changedBy, joined, orientation, pressed, props, width]);
423
424
  var calcValueText = (0, _react.useCallback)(function () {
424
425
  var _props$accessibilityH = props.accessibilityHint,
@@ -580,14 +581,11 @@ var _PickerBase = function PickerBase(props) {
580
581
  noAnimation: noAnimation,
581
582
  reverseTransition: reverseTransition.current,
582
583
  children: children
583
- }), showIndicators && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", _objectSpread(_objectSpread({
584
- className: css.indicatorContainer
585
- }, voiceProps), {}, {
586
- children: children.map(function (c, indicator) {
587
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
588
- className: (0, _classnames3["default"])(css.indicator, _defineProperty({}, css.active, index === indicator))
589
- }, "indicator".concat(indicator));
590
- })
584
+ }), showIndicators && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Steps["default"], _objectSpread(_objectSpread({}, voiceProps), {}, {
585
+ css: css,
586
+ highlightCurrentOnly: true,
587
+ current: index + 1,
588
+ total: children.length
591
589
  }))]
592
590
  }), isHorizontalJoinedEnter ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Layout.Cell, _objectSpread(_objectSpread({}, voiceProps), {}, {
593
591
  align: joined ? 'stretch' : null,