@enact/limestone 1.3.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.github/workflows/ci-branch.yml +21 -0
  2. package/.github/workflows/ci-pull-request.yml +16 -0
  3. package/.github/workflows/ci-reusable.yml +73 -0
  4. package/ActionGuide/ActionGuide.d.ts +5 -4
  5. package/ActionGuide/ActionGuide.module.css +1 -1
  6. package/Alert/Alert.d.ts +13 -2
  7. package/Alert/Alert.js +39 -5
  8. package/Alert/Alert.module.css +48 -1
  9. package/Alert/tests/Alert-specs.js +91 -0
  10. package/BodyText/BodyText.d.ts +5 -4
  11. package/BodyText/BodyText.module.css +7 -7
  12. package/Button/Button.d.ts +17 -12
  13. package/Button/Button.js +1 -1
  14. package/Button/Button.module.css +195 -268
  15. package/Button/tests/Button-specs.js +26 -0
  16. package/CHANGELOG.md +254 -0
  17. package/Card/Card.d.ts +40 -12
  18. package/Card/Card.js +164 -28
  19. package/Card/Card.module.css +277 -58
  20. package/Card/tests/Card-specs.js +67 -3
  21. package/Checkbox/Checkbox.d.ts +8 -7
  22. package/Checkbox/Checkbox.js +3 -1
  23. package/Checkbox/Checkbox.module.css +213 -120
  24. package/Checkbox/tests/Checkbox-specs.js +1 -1
  25. package/CheckboxItem/CheckboxItem.d.ts +22 -7
  26. package/CheckboxItem/CheckboxItem.js +71 -4
  27. package/Chips/Chip.js +72 -13
  28. package/Chips/Chip.module.css +3 -3
  29. package/Chips/Chips.js +37 -17
  30. package/Chips/Chips.module.css +1 -1
  31. package/Chips/tests/Chip-specs.js +43 -13
  32. package/Chips/tests/Chips-specs.js +31 -21
  33. package/ColorPicker/ColorPicker.js +27 -25
  34. package/ContextualMenuDecorator/ContextualMenuDecorator.d.ts +4 -5
  35. package/ContextualPopupDecorator/ContextualPopup.module.css +34 -34
  36. package/ContextualPopupDecorator/ContextualPopupDecorator.js +567 -549
  37. package/DatePicker/DatePicker.d.ts +4 -5
  38. package/DayPicker/DayPicker.d.ts +8 -7
  39. package/DayPicker/DaySelectorDecorator.js +12 -7
  40. package/Dropdown/Dropdown.d.ts +11 -13
  41. package/Dropdown/Dropdown.module.css +13 -9
  42. package/Dropdown/DropdownList.js +80 -54
  43. package/FixedPopupPanels/FixedPopupPanels.d.ts +4 -2
  44. package/FixedPopupPanels/FixedPopupPanels.module.css +18 -18
  45. package/FlexiblePopupPanels/FlexiblePopupPanels.module.css +23 -23
  46. package/FlexiblePopupPanels/useNavButtonFocus.js +7 -10
  47. package/FormCheckboxItem/FormCheckboxItem.d.ts +5 -4
  48. package/Heading/Heading.d.ts +9 -8
  49. package/Heading/Heading.js +2 -2
  50. package/Heading/Heading.module.css +5 -5
  51. package/Icon/Icon.d.ts +15 -4
  52. package/Icon/Icon.js +49 -2
  53. package/Icon/Icon.module.css +1 -1
  54. package/Icon/IconList.js +27 -1
  55. package/IconItem/IconItem.d.ts +13 -12
  56. package/IconItem/IconItem.js +15 -0
  57. package/IconItem/IconItem.module.css +107 -1
  58. package/IconItem/tests/IconItem-specs.js +30 -1
  59. package/Image/Image.d.ts +5 -4
  60. package/Image/Image.js +6 -4
  61. package/ImageItem/ImageItem.d.ts +11 -10
  62. package/ImageItem/ImageItem.js +37 -31
  63. package/ImageItem/ImageItem.module.css +30 -30
  64. package/ImageItem/tests/ImageItem-specs.js +3 -10
  65. package/Input/Input.js +21 -3
  66. package/Input/Input.module.css +37 -8
  67. package/Input/InputField.js +79 -24
  68. package/Input/InputField.module.css +273 -41
  69. package/Input/InputFieldDecoratorIcon.js +1 -0
  70. package/Input/InputFieldSpotlightDecorator.js +257 -228
  71. package/Input/index.d.ts +120 -111
  72. package/Input/tests/Input-specs.js +26 -0
  73. package/Input/tests/InputField-specs.js +170 -3
  74. package/Input/tests/InputPopup-specs.js +1 -1
  75. package/Item/Item.d.ts +16 -9
  76. package/Item/Item.js +20 -2
  77. package/Item/Item.module.css +1 -1
  78. package/KeyGuide/KeyGuide.d.ts +8 -7
  79. package/KeyGuide/KeyGuide.js +29 -27
  80. package/KeyGuide/KeyGuide.module.css +25 -1
  81. package/Marquee/Marquee.d.ts +2 -4
  82. package/MediaOverlay/MediaOverlay.d.ts +12 -11
  83. package/MediaOverlay/MediaOverlay.js +43 -21
  84. package/MediaOverlay/MediaOverlay.module.css +114 -15
  85. package/MediaOverlay/tests/MediaOverlay-specs.js +29 -0
  86. package/MediaPlayer/MediaControls.js +195 -13
  87. package/MediaPlayer/MediaControls.module.css +3 -2
  88. package/MediaPlayer/MediaSlider.module.css +7 -20
  89. package/MediaPlayer/index.d.ts +59 -7
  90. package/MediaPlayer/tests/util-specs.js +4 -1
  91. package/PageViews/PageViews.js +232 -82
  92. package/PageViews/PageViews.module.css +3 -0
  93. package/PageViews/PageViewsRouter.js +100 -42
  94. package/PageViews/tests/PageViews-specs.js +171 -0
  95. package/Panels/Header.js +54 -34
  96. package/Panels/Header.module.css +83 -31
  97. package/Panels/Panel.module.css +1 -1
  98. package/Panels/index.d.ts +7 -8
  99. package/Picker/Picker.d.ts +4 -5
  100. package/Picker/Picker.module.css +2 -2
  101. package/Popup/Popup.js +245 -242
  102. package/Popup/Popup.module.css +24 -24
  103. package/PopupTabLayout/PopupTabLayout.d.ts +5 -7
  104. package/PopupTabLayout/PopupTabLayout.js +26 -18
  105. package/PopupTabLayout/PopupTabLayout.module.css +53 -16
  106. package/PopupTabLayout/PopupTabLayoutStateContext.js +8 -0
  107. package/ProgressBar/ProgressBar.d.ts +5 -4
  108. package/ProgressBar/ProgressBarTooltip.module.css +12 -12
  109. package/ProgressButton/ProgressButton.d.ts +4 -5
  110. package/QuickGuidePanels/QuickGuidePanels.module.css +2 -2
  111. package/RadioItem/RadioItem.d.ts +18 -5
  112. package/RadioItem/RadioItem.js +69 -2
  113. package/RadioItem/RadioItem.module.css +36 -36
  114. package/RangePicker/RangePicker.module.css +2 -2
  115. package/Scroller/EditableWrapper.js +28 -18
  116. package/Scroller/Scroller.d.ts +20 -16
  117. package/Scroller/Scroller.js +20 -13
  118. package/Scroller/Scroller.module.css +4 -4
  119. package/Scroller/useThemeScroller.js +3 -3
  120. package/Slider/Slider.d.ts +20 -14
  121. package/Slider/Slider.js +71 -14
  122. package/Slider/Slider.module.css +464 -91
  123. package/Slider/SliderBehaviorDecorator.js +16 -14
  124. package/Slider/tests/Slider-specs.js +53 -1
  125. package/Slider/utils.js +23 -7
  126. package/Spinner/Spinner.d.ts +5 -4
  127. package/Spinner/Spinner.js +10 -8
  128. package/Spinner/Spinner.module.css +9 -9
  129. package/Steps/Steps.d.ts +5 -4
  130. package/Steps/Steps.js +9 -5
  131. package/Switch/Switch.d.ts +8 -7
  132. package/Switch/Switch.module.css +100 -13
  133. package/SwitchItem/SwitchItem.d.ts +9 -6
  134. package/TabLayout/RefocusDecorator.js +26 -18
  135. package/TabLayout/TabGroup.js +3 -2
  136. package/TabLayout/TabGroup.module.css +2 -2
  137. package/TabLayout/TabLayout.d.ts +6 -0
  138. package/TabLayout/TabLayout.js +11 -1
  139. package/TabLayout/TabLayout.module.css +18 -0
  140. package/TabLayout/tests/TabGroup-specs.js +1 -1
  141. package/TabLayout/tests/TabLayout-specs.js +52 -0
  142. package/ThemeDecorator/AccessibilityDecorator.js +12 -11
  143. package/ThemeDecorator/I18nFontDecorator.js +6 -4
  144. package/ThemeDecorator/ThemeDecorator.d.ts +16 -10
  145. package/ThemeDecorator/ThemeDecorator.js +24 -9
  146. package/ThemeDecorator/fontGenerator.js +1 -1
  147. package/ThemeDecorator/screenTypes.json +1 -0
  148. package/TimePicker/TimePicker.module.css +1 -1
  149. package/TimePicker/TimePickerBase.js +5 -3
  150. package/TooltipDecorator/Tooltip.module.css +1 -2
  151. package/TooltipDecorator/TooltipDecorator.js +12 -7
  152. package/TooltipDecorator/tests/useTooltip-specs.js +5 -2
  153. package/TooltipDecorator/tests/util-specs.js +12 -0
  154. package/TooltipDecorator/useTooltip.js +1 -1
  155. package/TooltipDecorator/util.js +18 -11
  156. package/VideoPlayer/Feedback.js +3 -0
  157. package/VideoPlayer/Feedback.module.css +5 -9
  158. package/VideoPlayer/FeedbackIcons.js +1 -1
  159. package/VideoPlayer/FeedbackTooltip.module.css +55 -11
  160. package/VideoPlayer/VideoPlayer.d.ts +44 -18
  161. package/VideoPlayer/VideoPlayer.js +153 -47
  162. package/VideoPlayer/VideoPlayer.module.css +28 -11
  163. package/VirtualList/VirtualList.d.ts +9 -2
  164. package/VirtualList/VirtualList.js +51 -24
  165. package/VirtualList/tests/VirtualGridList-translate-specs.js +3 -0
  166. package/VirtualList/tests/VirtualList-specs.js +28 -1
  167. package/VirtualList/tests/VirtualList-translate-specs.js +4 -1
  168. package/VirtualList/useSpotlight.js +1 -1
  169. package/WizardPanels/WizardPanels.module.css +2 -2
  170. package/WizardPanels/index.d.ts +4 -2
  171. package/fonts/Limestone_Icons.ttf +0 -0
  172. package/internal/$L/$L.js +3 -3
  173. package/internal/AsyncRenderChildren/AsyncRenderChildren.js +9 -5
  174. package/internal/AsyncRenderChildren/tests/AsyncRenderChildren-specs.js +4 -1
  175. package/internal/DateComponentPicker/DateComponentPicker.module.css +2 -2
  176. package/internal/DateTime/DateTime.module.css +1 -0
  177. package/internal/DateTime/DateTimeDecorator.js +5 -4
  178. package/internal/Panels/PanelsRouter.js +48 -31
  179. package/internal/Panels/useAutoFocus.js +10 -6
  180. package/internal/Panels/useFocusOnTransition.js +4 -3
  181. package/internal/Picker/Picker.js +7 -5
  182. package/internal/Picker/Picker.module.css +2 -2
  183. package/internal/Picker/SpottablePicker.js +15 -13
  184. package/internal/SharedStateDecorator/SharedStateDecorator.js +78 -99
  185. package/internal/validators/validators.js +21 -2
  186. package/package.json +18 -15
  187. package/styles/colors-highcontrast.less +9 -1
  188. package/styles/colors.less +12 -7
  189. package/styles/motion-mixins.less +66 -0
  190. package/styles/motions.less +78 -0
  191. package/styles/variables.less +176 -150
  192. package/useScroll/HoverToScroll.js +23 -17
  193. package/useScroll/Scrollbar.js +14 -10
  194. package/useScroll/ScrollbarPlaceholder.js +3 -5
  195. package/useScroll/ScrollbarTrack.js +7 -5
  196. package/useScroll/ScrollbarTrack.module.css +8 -8
  197. package/useScroll/useEvent.js +14 -3
  198. package/useScroll/useScroll.js +12 -2
  199. package/useScroll/useScroll.module.css +6 -6
  200. package/.travis.yml +0 -40
@@ -7,6 +7,7 @@ exports["default"] = exports.InputSpotlightDecorator = void 0;
7
7
  var _handle = require("@enact/core/handle");
8
8
  var _hoc = _interopRequireDefault(require("@enact/core/hoc"));
9
9
  var _keymap = require("@enact/core/keymap");
10
+ var _util = require("@enact/core/util");
10
11
  var _spotlight = require("@enact/spotlight");
11
12
  var _Pause = _interopRequireDefault(require("@enact/spotlight/Pause"));
12
13
  var _Spottable = _interopRequireDefault(require("@enact/spotlight/Spottable"));
@@ -18,18 +19,15 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default":
18
19
  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; }
19
20
  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; }
20
21
  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; }
21
- function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
22
- 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); } }
23
- function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
24
22
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
25
23
  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); }
26
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
27
- 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); }
28
- function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
29
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
30
- function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
31
- 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); }
32
- function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
24
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
25
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
26
+ 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; } }
27
+ 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; }
28
+ 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; } }
29
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
30
+ function _objectDestructuringEmpty(t) { if (null == t) throw new TypeError("Cannot destructure " + t); }
33
31
  var isBubbling = function isBubbling(ev) {
34
32
  return ev.currentTarget !== ev.target;
35
33
  };
@@ -43,7 +41,6 @@ var isSelectionAtLocation = function isSelectionAtLocation(target, location) {
43
41
  return true;
44
42
  }
45
43
  };
46
- var handleKeyDown = (0, _handle.handle)((0, _handle.forwardWithPrevent)('onKeyDown'), (0, _handle.call)('onKeyDown'));
47
44
 
48
45
  /**
49
46
  * Default config for {@link limestone/Input.InputSpotlightDecorator|InputSpotlightDecorator}
@@ -58,7 +55,7 @@ var defaultConfig = {
58
55
  * @type {Boolean}
59
56
  * @default false
60
57
  * @memberof limestone/Input/InputSpotlightDecorator.InputSpotlightDecorator.defaultConfig
61
- */
58
+ */
62
59
  noLockPointer: false
63
60
  };
64
61
 
@@ -72,7 +69,6 @@ var defaultConfig = {
72
69
  * @private
73
70
  */
74
71
  var InputSpotlightDecorator = exports.InputSpotlightDecorator = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) {
75
- var _Class;
76
72
  var noLockPointer = config.noLockPointer;
77
73
  var Component = (0, _Spottable["default"])({
78
74
  emulateMouse: false
@@ -80,245 +76,269 @@ var InputSpotlightDecorator = exports.InputSpotlightDecorator = (0, _hoc["defaul
80
76
  var forwardBlur = (0, _handle.forward)('onBlur');
81
77
  var forwardMouseDown = (0, _handle.forward)('onMouseDown');
82
78
  var forwardFocus = (0, _handle.forward)('onFocus');
79
+ var forwardKeyDown = (0, _handle.forwardWithPrevent)('onKeyDown');
83
80
  var forwardKeyUp = (0, _handle.forward)('onKeyUp');
84
- return _Class = /*#__PURE__*/function (_ReactComponent) {
85
- function _Class(props) {
86
- var _this;
87
- _classCallCheck(this, _Class);
88
- _this = _callSuper(this, _Class, [props]);
89
- _this.updateFocus = function () {
90
- // focus node if `InputSpotlightDecorator` is pausing Spotlight or if Spotlight is paused
91
- if (_this.node && _spotlight.Spotlight.getCurrent() !== _this.node && (_this.paused.isPaused() || !_spotlight.Spotlight.isPaused())) {
92
- if (_this.fromMouse) {
93
- _this.node.focus({
94
- preventScroll: true
95
- });
96
- } else {
97
- _this.node.focus();
98
- }
81
+
82
+ // eslint-disable-next-line no-shadow
83
+ var _InputSpotlightDecorator = function InputSpotlightDecorator(_ref) {
84
+ var props = Object.assign({}, (_objectDestructuringEmpty(_ref), _ref));
85
+ (0, _util.checkPropTypes)(_InputSpotlightDecorator, props);
86
+ var _props$caretToEndOnFo = props.caretToEndOnFocus,
87
+ caretToEndOnFocus = _props$caretToEndOnFo === void 0 ? false : _props$caretToEndOnFo;
88
+ var downTarget = (0, _react.useRef)(null);
89
+ var focused = (0, _react.useRef)(null);
90
+ var node = (0, _react.useRef)(null);
91
+ var fromMouse = (0, _react.useRef)(false);
92
+ var prevStatus = (0, _react.useRef)({
93
+ focused: null,
94
+ node: null
95
+ });
96
+ var paused = (0, _react.useMemo)(function () {
97
+ return new _Pause["default"]('InputSpotlightDecorator');
98
+ }, []);
99
+ var _useState = (0, _react.useState)(false),
100
+ _useState2 = _slicedToArray(_useState, 2),
101
+ active = _useState2[0],
102
+ setActive = _useState2[1];
103
+ var setDownTarget = (0, _react.useCallback)(function (ev) {
104
+ var repeat = ev.repeat,
105
+ target = ev.target;
106
+ if (!repeat) {
107
+ downTarget.current = target;
108
+ }
109
+ }, []);
110
+ var moveCaretToEnd = (0, _react.useCallback)(function (inputNode) {
111
+ if (caretToEndOnFocus && inputNode && SELECTABLE_TYPES.test(inputNode.type)) {
112
+ var length = inputNode.value.length;
113
+ inputNode.setSelectionRange(length, length);
114
+ inputNode.scrollLeft = inputNode.dir === 'rtl' ? 0 : inputNode.scrollWidth;
115
+ }
116
+ }, [caretToEndOnFocus]);
117
+ var updateFocus = (0, _react.useCallback)(function () {
118
+ // focus node if `InputSpotlightDecorator` is pausing Spotlight or if Spotlight is paused
119
+ if (node.current && _spotlight.Spotlight.getCurrent() !== node.current && (paused.isPaused() || !_spotlight.Spotlight.isPaused())) {
120
+ if (fromMouse.current) {
121
+ node.current.focus({
122
+ preventScroll: true
123
+ });
124
+ } else {
125
+ node.current.focus();
99
126
  }
100
- var focusChanged = _this.focused !== _this.prevStatus.focused;
101
- if (focusChanged) {
102
- if (_this.focused === 'input') {
103
- (0, _handle.forwardCustom)('onActivate')(null, _this.props);
104
- if (!noLockPointer) {
105
- (0, _pointer.lockPointer)(_this.node);
106
- }
107
- _this.paused.pause();
108
- } else if (_this.prevStatus.focused === 'input') {
109
- (0, _handle.forwardCustom)('onDeactivate')(null, _this.props);
110
- if (!noLockPointer) {
111
- (0, _pointer.releasePointer)(_this.prevStatus.node);
112
- }
113
- _this.paused.resume();
127
+
128
+ // Move caret to end if caretToEndOnFocus is enabled and we're focusing an input
129
+ if (focused.current === 'input') {
130
+ if (fromMouse.current) {
131
+ setTimeout(function () {
132
+ moveCaretToEnd(node.current);
133
+ }, 0);
134
+ } else {
135
+ moveCaretToEnd(node.current);
114
136
  }
115
137
  }
116
- _this.prevStatus.focused = _this.focused;
117
- _this.prevStatus.node = _this.node;
118
- };
119
- _this.focus = function (focused, node, fromMouse) {
120
- _this.focused = focused;
121
- _this.node = node;
122
- _this.fromMouse = fromMouse;
123
- _this.updateFocus();
124
- };
125
- _this.blur = function () {
126
- if (_this.focused || _this.node) {
127
- _this.focused = null;
128
- _this.node = null;
129
- _this.updateFocus();
130
- }
131
- };
132
- _this.focusDecorator = function (decorator) {
133
- _this.focus('decorator', decorator, false);
134
- };
135
- _this.focusInput = function (decorator, fromMouse) {
136
- _this.focus('input', decorator.querySelector('input'), fromMouse);
137
- };
138
- _this.onBlur = function (ev) {
139
- if (!_this.props.autoFocus) {
140
- if (isBubbling(ev)) {
141
- if (_spotlight.Spotlight.getPointerMode()) {
142
- _this.blur();
143
- forwardBlur(ev, _this.props);
144
- } else {
145
- _this.focused = 'decorator';
146
- _this.node = ev.currentTarget;
147
- _this.fromMouse = false;
148
- ev.stopPropagation();
149
- }
150
- } else if (!ev.currentTarget.contains(ev.relatedTarget)) {
151
- // Blurring decorator but not focusing input
152
- forwardBlur(ev, _this.props);
153
- _this.blur();
138
+ }
139
+ var focusChanged = focused.current !== prevStatus.current.focused;
140
+ if (focusChanged) {
141
+ if (focused.current === 'input') {
142
+ setActive(true);
143
+ (0, _handle.forwardCustom)('onActivate')(null, props);
144
+ if (!noLockPointer) {
145
+ (0, _pointer.lockPointer)(node.current);
154
146
  }
155
- } else if (isBubbling(ev)) {
156
- if (_this.focused === 'input' && _this.node === ev.target && ev.currentTarget !== ev.relatedTarget) {
157
- _this.blur();
158
- forwardBlur(ev, _this.props);
159
- } else {
160
- _this.focusDecorator(ev.currentTarget);
161
- ev.stopPropagation();
162
- _this.blur();
147
+ paused.pause();
148
+ } else if (prevStatus.current.focused === 'input') {
149
+ setActive(false);
150
+ (0, _handle.forwardCustom)('onDeactivate')(null, props);
151
+ if (!noLockPointer) {
152
+ (0, _pointer.releasePointer)(prevStatus.current.node);
163
153
  }
154
+ paused.resume();
164
155
  }
156
+ }
157
+ prevStatus.current = {
158
+ focused: focused.current,
159
+ node: node.current
165
160
  };
166
- _this.onMouseDown = function (ev) {
167
- var _this$props = _this.props,
168
- disabled = _this$props.disabled,
169
- spotlightDisabled = _this$props.spotlightDisabled;
170
- _this.setDownTarget(ev);
171
- // focus the <input> whenever clicking on any part of the component to ensure both that
172
- // the <input> has focus and Spotlight is paused.
173
- if (!disabled && !spotlightDisabled) {
174
- _this.focusInput(ev.currentTarget, true);
175
- }
176
- forwardMouseDown(ev, _this.props);
177
- };
178
- _this.onFocus = function (ev) {
179
- forwardFocus(ev, _this.props);
161
+ }, [moveCaretToEnd, paused, props]);
162
+ var blur = (0, _react.useCallback)(function () {
163
+ if (focused.current || node.current) {
164
+ focused.current = null;
165
+ node.current = null;
166
+ updateFocus();
167
+ }
168
+ }, [updateFocus]);
169
+ var focus = (0, _react.useCallback)(function (focusedProp, nodeProp, fromMouseProp) {
170
+ focused.current = focusedProp;
171
+ node.current = nodeProp;
172
+ fromMouse.current = fromMouseProp;
173
+ updateFocus();
174
+ }, [updateFocus]);
175
+ var focusDecorator = (0, _react.useCallback)(function (decorator) {
176
+ focus('decorator', decorator, false);
177
+ }, [focus]);
178
+ var onKeyDown = (0, _react.useCallback)(function (ev) {
179
+ forwardKeyDown(ev, props);
180
+ var currentTarget = ev.currentTarget,
181
+ keyCode = ev.keyCode,
182
+ target = ev.target;
180
183
 
181
- // when in autoFocus mode, focusing the decorator directly will cause it to
182
- // forward the focus onto the <input>
183
- if (!isBubbling(ev) && _this.props.autoFocus && _this.focused === null && !_spotlight.Spotlight.getPointerMode()) {
184
- _this.focusInput(ev.currentTarget, false);
185
- ev.stopPropagation();
184
+ // cache the target if this is the first keyDown event to ensure the component had focus
185
+ // when the key interaction started
186
+ setDownTarget(ev);
187
+ if (focused.current === 'input') {
188
+ var isDown = (0, _keymap.is)('down', keyCode);
189
+ var isLeft = (0, _keymap.is)('left', keyCode);
190
+ var isRight = (0, _keymap.is)('right', keyCode);
191
+ var isUp = (0, _keymap.is)('up', keyCode);
192
+
193
+ // move spotlight
194
+ var shouldSpotlightMove =
195
+ // No value exists! (Can happen when disabled)
196
+ target.value == null ||
197
+ // on left + at beginning of selection
198
+ isLeft && isSelectionAtLocation(target, 0) ||
199
+ // on right + at end of selection (note: fails on non-selectable types usually)
200
+ isRight && isSelectionAtLocation(target, target.value.length) ||
201
+ // on up
202
+ isUp ||
203
+ // on down
204
+ isDown;
205
+
206
+ // prevent modifying the value via 5-way for numeric fields
207
+ if ((isUp || isDown) && target.type === 'number') {
208
+ ev.preventDefault();
186
209
  }
187
- };
188
- _this.onKeyUp = function (ev) {
189
- var dismissOnEnter = _this.props.dismissOnEnter;
190
- var currentTarget = ev.currentTarget,
191
- keyCode = ev.keyCode,
192
- target = ev.target;
210
+ if (shouldSpotlightMove) {
211
+ var direction = (0, _spotlight.getDirection)(keyCode);
212
+ var getPointerMode = _spotlight.Spotlight.getPointerMode,
213
+ move = _spotlight.Spotlight.move,
214
+ resetKeyHoldState = _spotlight.Spotlight.resetKeyHoldState,
215
+ setPointerMode = _spotlight.Spotlight.setPointerMode;
216
+ if (getPointerMode()) {
217
+ setPointerMode(false);
218
+ }
219
+ (0, _handle.stopImmediate)(ev);
220
+ paused.resume();
193
221
 
194
- // verify that we have a matching pair of key down/up events to avoid adjusting focus
195
- // when the component received focus mid-press
196
- if (target === _this.downTarget) {
197
- _this.downTarget = null;
198
- if (!_this.props.disabled) {
199
- if (_this.focused === 'input' && dismissOnEnter && (0, _keymap.is)('enter', keyCode)) {
200
- _this.focusDecorator(currentTarget);
201
- // prevent Enter onKeyPress which triggers an onMouseDown via Spotlight
202
- ev.preventDefault();
203
- } else if (_this.focused !== 'input' && (0, _keymap.is)('enter', keyCode)) {
204
- _this.focusInput(currentTarget, false);
205
- }
222
+ // Move spotlight in the keypress direction
223
+ if (move(direction)) {
224
+ // if successful, reset the internal state
225
+ blur();
226
+ resetKeyHoldState();
227
+ } else {
228
+ // if there is no other spottable elements, focus `InputDecorator` instead
229
+ focusDecorator(currentTarget);
206
230
  }
231
+ } else if (isLeft || isRight) {
232
+ // prevent 5-way nav for left/right keys within the <input>
233
+ (0, _handle.stopImmediate)(ev);
207
234
  }
208
- forwardKeyUp(ev, _this.props);
209
- };
210
- _this.focused = null;
211
- _this.node = null;
212
- _this.fromMouse = false;
213
- _this.paused = new _Pause["default"]('InputSpotlightDecorator');
214
- _this.handleKeyDown = handleKeyDown.bind(_this);
215
- _this.prevStatus = {
216
- focused: null,
217
- node: null
218
- };
219
- return _this;
220
- }
221
- _inherits(_Class, _ReactComponent);
222
- return _createClass(_Class, [{
223
- key: "componentWillUnmount",
224
- value: function componentWillUnmount() {
225
- this.paused.resume();
226
- if (this.focused === 'input') {
227
- var onSpotlightDisappear = this.props.onSpotlightDisappear;
235
+ }
236
+ }, [blur, focusDecorator, paused, props, setDownTarget]);
237
+ (0, _react.useEffect)(function () {
238
+ return function () {
239
+ paused.resume();
240
+ if (focused.current === 'input') {
241
+ var onSpotlightDisappear = props.onSpotlightDisappear;
228
242
  if (onSpotlightDisappear) {
229
243
  onSpotlightDisappear();
230
244
  }
231
245
  if (!noLockPointer) {
232
- (0, _pointer.releasePointer)(this.node);
246
+ (0, _pointer.releasePointer)(node.current);
233
247
  }
234
248
  }
235
- }
236
- }, {
237
- key: "onKeyDown",
238
- value: function onKeyDown(ev) {
239
- var currentTarget = ev.currentTarget,
240
- keyCode = ev.keyCode,
241
- target = ev.target;
242
-
243
- // cache the target if this is the first keyDown event to ensure the component had focus
244
- // when the key interaction started
245
- this.setDownTarget(ev);
246
- if (this.focused === 'input') {
247
- var isDown = (0, _keymap.is)('down', keyCode);
248
- var isLeft = (0, _keymap.is)('left', keyCode);
249
- var isRight = (0, _keymap.is)('right', keyCode);
250
- var isUp = (0, _keymap.is)('up', keyCode);
251
-
252
- // move spotlight
253
- var shouldSpotlightMove =
254
- // No value exists! (Can happen when disabled)
255
- target.value == null ||
256
- // on left + at beginning of selection
257
- isLeft && isSelectionAtLocation(target, 0) ||
258
- // on right + at end of selection (note: fails on non-selectable types usually)
259
- isRight && isSelectionAtLocation(target, target.value.length) ||
260
- // on up
261
- isUp ||
262
- // on down
263
- isDown;
264
-
265
- // prevent modifying the value via 5-way for numeric fields
266
- if ((isUp || isDown) && target.type === 'number') {
267
- ev.preventDefault();
268
- }
269
- if (shouldSpotlightMove) {
270
- var direction = (0, _spotlight.getDirection)(keyCode);
271
- var getPointerMode = _spotlight.Spotlight.getPointerMode,
272
- move = _spotlight.Spotlight.move,
273
- resetKeyHoldState = _spotlight.Spotlight.resetKeyHoldState,
274
- setPointerMode = _spotlight.Spotlight.setPointerMode;
275
- if (getPointerMode()) {
276
- setPointerMode(false);
277
- }
278
- (0, _handle.stopImmediate)(ev);
279
- this.paused.resume();
249
+ };
250
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
280
251
 
281
- // Move spotlight in the keypress direction
282
- if (move(direction)) {
283
- // if successful, reset the internal state
284
- this.blur();
285
- resetKeyHoldState();
286
- } else {
287
- // if there is no other spottable elements, focus `InputDecorator` instead
288
- this.focusDecorator(currentTarget);
289
- }
290
- } else if (isLeft || isRight) {
291
- // prevent 5-way nav for left/right keys within the <input>
292
- (0, _handle.stopImmediate)(ev);
252
+ var focusInput = (0, _react.useCallback)(function (decorator, fromMouseProp) {
253
+ focus('input', decorator.querySelector('input'), fromMouseProp);
254
+ }, [focus]);
255
+ var onBlur = (0, _react.useCallback)(function (ev) {
256
+ if (!props.autoFocus) {
257
+ if (isBubbling(ev)) {
258
+ if (_spotlight.Spotlight.getPointerMode()) {
259
+ blur();
260
+ forwardBlur(ev, props);
261
+ } else {
262
+ focused.current = 'decorator';
263
+ node.current = ev.currentTarget;
264
+ fromMouse.current = false;
265
+ ev.stopPropagation();
293
266
  }
267
+ } else if (!ev.currentTarget.contains(ev.relatedTarget)) {
268
+ // Blurring decorator but not focusing input
269
+ forwardBlur(ev, props);
270
+ blur();
294
271
  }
295
- }
296
- }, {
297
- key: "setDownTarget",
298
- value: function setDownTarget(ev) {
299
- var repeat = ev.repeat,
300
- target = ev.target;
301
- if (!repeat) {
302
- this.downTarget = target;
272
+ } else if (isBubbling(ev)) {
273
+ if (focused.current === 'input' && node.current === ev.target && ev.currentTarget !== ev.relatedTarget) {
274
+ blur();
275
+ forwardBlur(ev, props);
276
+ } else {
277
+ focusDecorator(ev.currentTarget);
278
+ ev.stopPropagation();
279
+ blur();
303
280
  }
304
281
  }
305
- }, {
306
- key: "render",
307
- value: function render() {
308
- var props = Object.assign({}, this.props);
309
- delete props.autoFocus;
310
- delete props.onActivate;
311
- delete props.onDeactivate;
312
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, _objectSpread(_objectSpread({}, props), {}, {
313
- onBlur: this.onBlur,
314
- onMouseDown: this.onMouseDown,
315
- onFocus: this.onFocus,
316
- onKeyDown: this.handleKeyDown,
317
- onKeyUp: this.onKeyUp
318
- }));
282
+ }, [blur, focusDecorator, props]);
283
+ var onMouseDown = (0, _react.useCallback)(function (ev) {
284
+ var disabled = props.disabled,
285
+ spotlightDisabled = props.spotlightDisabled;
286
+ setDownTarget(ev);
287
+ // focus the <input> whenever clicking on any part of the component to ensure both that
288
+ // the <input> has focus and Spotlight is paused. Skip when the target is a decorative
289
+ // icon so it doesn't activate the input.
290
+ if (!disabled && !spotlightDisabled && !ev.target.closest('[data-input-icon]')) {
291
+ focusInput(ev.currentTarget, true);
292
+ }
293
+ forwardMouseDown(ev, props);
294
+ }, [focusInput, props, setDownTarget]);
295
+ var onFocus = (0, _react.useCallback)(function (ev) {
296
+ forwardFocus(ev, props);
297
+ // when in autoFocus mode, focusing the decorator directly will cause it to
298
+ // forward the focus onto the <input>
299
+ if (!isBubbling(ev) && props.autoFocus && focused.current === null && !_spotlight.Spotlight.getPointerMode()) {
300
+ focusInput(ev.currentTarget, false);
301
+ ev.stopPropagation();
302
+ }
303
+ }, [focusInput, props]);
304
+ var onKeyUp = (0, _react.useCallback)(function (ev) {
305
+ var dismissOnEnter = props.dismissOnEnter;
306
+ var currentTarget = ev.currentTarget,
307
+ keyCode = ev.keyCode,
308
+ target = ev.target;
309
+
310
+ // verify that we have a matching pair of key down/up events to avoid adjusting focus
311
+ // when the component received focus mid-press
312
+ if (target === downTarget.current) {
313
+ downTarget.current = null;
314
+ if (!props.disabled) {
315
+ if (focused.current === 'input' && dismissOnEnter && (0, _keymap.is)('enter', keyCode)) {
316
+ focusDecorator(currentTarget);
317
+ // prevent Enter onKeyPress which triggers an onMouseDown via Spotlight
318
+ ev.preventDefault();
319
+ } else if (focused.current !== 'input' && (0, _keymap.is)('enter', keyCode)) {
320
+ focusInput(currentTarget, false);
321
+ }
322
+ }
319
323
  }
320
- }]);
321
- }(_react.Component), _Class.displayName = 'InputSpotlightDecorator', _Class.propTypes = /** @lends limestone/Input/InputSpotlightDecorator.InputSpotlightDecorator.prototype */{
324
+ forwardKeyUp(ev, props);
325
+ }, [focusDecorator, focusInput, props]);
326
+ var componentProps = Object.assign({}, props);
327
+ delete componentProps.autoFocus;
328
+ delete componentProps.caretToEndOnFocus;
329
+ delete componentProps.onActivate;
330
+ delete componentProps.onDeactivate;
331
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, _objectSpread(_objectSpread({}, componentProps), {}, {
332
+ active: active,
333
+ onBlur: onBlur,
334
+ onFocus: onFocus,
335
+ onKeyDown: onKeyDown,
336
+ onKeyUp: onKeyUp,
337
+ onMouseDown: onMouseDown
338
+ }));
339
+ };
340
+ _InputSpotlightDecorator.displayName = 'InputSpotlightDecorator';
341
+ _InputSpotlightDecorator.propTypes = /** @lends limestone/Input/InputSpotlightDecorator.InputSpotlightDecorator.prototype */{
322
342
  /**
323
343
  * Focuses the <input> when the decorator is focused via 5-way.
324
344
  *
@@ -327,6 +347,14 @@ var InputSpotlightDecorator = exports.InputSpotlightDecorator = (0, _hoc["defaul
327
347
  * @public
328
348
  */
329
349
  autoFocus: _propTypes["default"].bool,
350
+ /**
351
+ * Moves the caret to the end of the text when the input receives focus.
352
+ *
353
+ * @type {Boolean}
354
+ * @default false
355
+ * @public
356
+ */
357
+ caretToEndOnFocus: _propTypes["default"].bool,
330
358
  /**
331
359
  * Applies a disabled style and the control becomes non-interactive.
332
360
  *
@@ -375,6 +403,7 @@ var InputSpotlightDecorator = exports.InputSpotlightDecorator = (0, _hoc["defaul
375
403
  * @public
376
404
  */
377
405
  spotlightDisabled: _propTypes["default"].bool
378
- }, _Class;
406
+ };
407
+ return _InputSpotlightDecorator;
379
408
  });
380
409
  var _default = exports["default"] = InputSpotlightDecorator;