UNPKG

@enact/sandstone

Version:

Large-screen/TV support library for Enact, containing a variety of UI components.

390 lines (387 loc) 16.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.PickerBase = exports.Picker = void 0; var _classnames2 = _interopRequireDefault(require("classnames")); var _kind = _interopRequireDefault(require("@enact/core/kind")); var _util = require("@enact/core/util"); var _Changeable = _interopRequireDefault(require("@enact/ui/Changeable")); var _Pure = _interopRequireDefault(require("@enact/ui/internal/Pure")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = require("react"); var _Heading = _interopRequireDefault(require("../Heading")); var _Picker = _interopRequireWildcard(require("../internal/Picker")); var _validators = require("../internal/validators"); var _Marquee = require("../Marquee"); var _PickerModule = _interopRequireDefault(require("./Picker.module.css")); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["children", "css", "inlineTitle", "max", "title", "value", "voiceLabel"]; /** * A component for selecting values from a list of values. * * @example * <Picker> * {['A', 'B', 'C']} * </Picker> * * @module sandstone/Picker * @exports Picker * @exports PickerBase */ /** * The base `Picker` component. * * This version is not {@link spotlight/Spottable.Spottable|spottable}. * * @class PickerBase * @memberof sandstone/Picker * @ui * @public */ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 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; } 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; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); } 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); } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var PickerBase = exports.PickerBase = (0, _kind["default"])({ name: 'Picker', propTypes: /** @lends sandstone/Picker.PickerBase.prototype */{ /** * Picker value list. * * @type {Node} * @required * @public */ children: _propTypes["default"].node.isRequired, /** * The `aria-valuetext` for the picker. * * By default, `aria-valuetext` is set to the current selected child text. * * @type {String} * @memberof sandstone/Picker.PickerBase.prototype * @public */ 'aria-valuetext': _propTypes["default"].string, /** * Determines which key to adjust the picker's value for the joined horizontal one. * * * `'enter'` allows the user to use the enter key to adjust the picker's value * * `'arrow'` allows the user to use the left or right keys to adjust the picker's value. * * The default value for joined horizontal picker is `'enter'`. * If {@link sandstone/Picker.PickerBase.orientation|orientation} is `'vertical'` or * {@link sandstone/Picker.PickerBase.joined|joined} is undefined or is `false`, this prop is ignored. * * @type {('enter'|'arrow')} * @public */ changedBy: _propTypes["default"].oneOf(['enter', 'arrow']), /** * Customizes the component by mapping the supplied collection of CSS class names to the * corresponding internal elements and states of this component. * * The following classes are supported: * * * `title` - The title component class * * `inlineTitle` - The title component class when `inlineTitle` is true * * @type {Object} * @public */ css: _propTypes["default"].object, /** * The voice control labels for the `children`. * * By default, `data-webos-voice-labels-ext` is generated from `children`. However, if * `children` is not an array of numbers or strings, `data-webos-voice-labels-ext` should be * set to an array of labels. * * @type {Number[]|String[]} * @memberof sandstone/Picker.PickerBase.prototype * @public */ 'data-webos-voice-labels-ext': _propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].number), _propTypes["default"].arrayOf(_propTypes["default"].string)]), /** * A custom icon for the decrementer. * * All strings supported by {@link sandstone/Icon.Icon|Icon} are supported. Without a * custom icon, the default is used, and is automatically changed when the * {@link sandstone/Picker.PickerBase.orientation|orientation} is changed. * * @type {String} * @public */ decrementIcon: _propTypes["default"].string, /** * Disables the picker. * * @type {Boolean} * @public */ disabled: _propTypes["default"].bool, /** * A custom icon for the incrementer. * * All strings supported by {@link sandstone/Icon.Icon|Icon} are supported. Without a * custom icon, the default is used, and is automatically changed when the * {@link sandstone/Picker.PickerBase.orientation|orientation} is changed. * * @type {String} * @public */ incrementIcon: _propTypes["default"].string, /** * Applies inline styling to the title. * * @type {Boolean} * @public */ inlineTitle: _propTypes["default"].bool, /** * Allows the user to use the arrow keys or enter key to adjust the picker's value. * * Key presses are captured in the directions of the increment and decrement buttons but * others are unaffected. A non-joined Picker allows navigation in any direction, but * requires individual ENTER presses on the incrementer and decrementer buttons. Pointer * interaction is the same for both formats. * * @type {Boolean} * @public */ joined: _propTypes["default"].bool, /** * Disables marqueeing of items. * * By default, each picker item is wrapped by a * {@link sandstone/Marquee.Marquee|Marquee}. When this is set, the items will * not be wrapped. * * @type {Boolean} * @public */ marqueeDisabled: _propTypes["default"].bool, /** * Disables transition animation. * * @type {Boolean} * @public */ noAnimation: _propTypes["default"].bool, /** * Called when the `value` changes. * * @type {Function} * @public */ onChange: _propTypes["default"].func, /** * Orientation of the picker. * * Controls whether the buttons are arranged horizontally or vertically around the value. * * @type {('horizontal'|'vertical')} * @public */ orientation: _propTypes["default"].oneOf(['horizontal', 'vertical']), /** * When `true`, the picker buttons operate in the reverse direction such that pressing * up/left decrements the value and down/right increments the value. This is more natural * for vertical lists of text options where "up" implies a spatial change rather than * incrementing the value. * * If this prop is omitted, it will be determined by `orientation`. * For example, if `orientation` is `vertical`, `reverse` is `true`. * Conversely, if `orientation` is `horizontal`, `reverse` is `false`. * * @type {Boolean} * @public */ reverse: _propTypes["default"].bool, /** * The primary text of the `Picker`. * * The screen readers read out the title text when the `joined` prop is false * * @type {String} * @public */ title: _propTypes["default"].string, /** * The type of picker. It determines the aria-label for the next and previous buttons. * * Depending on the `type`, `joined`, `decrementAriaLabel`, and `incrementAriaLabel`, * the screen readers read out differently when Spotlight is on the next button, the previous button, * or the picker itself. * * For example, if Spotlight is on the next button, the `joined` prop is false, * and aria label props(`decrementAriaLabel` and `incrementAriaLabel`) are not defined, * then the screen readers read out as follows. * `'string'` type: `'next item'` * `'number'` type: `'press ok button to increase the value'` * * @type {('number'|'string')} * @default 'string' * @public */ type: _propTypes["default"].oneOf(['number', 'string']), /** * Index of the selected child. * * @type {Number} * @default 0 * @public */ value: _propTypes["default"].number, /** * The width of the picker. * * A number can be used to set the minimum number of characters to be shown. Setting a * number to less than the number of characters in the longest value will cause the width to * grow for the longer values. * * A string can be used to select from pre-defined widths: * * `'small'` - numeric values * * `'medium'` - single or short words * * `'large'` - maximum-sized pickers taking full width of its parent * * By default, the picker will size according to the longest valid value. * * @type {('small'|'medium'|'large'|Number)} * @public */ width: _propTypes["default"].oneOfType([_propTypes["default"].oneOf([null, 'small', 'medium', 'large']), _propTypes["default"].number]), /** * Allows picker to continue from the start of the list after it reaches the end and * vice-versa. * * @type {Boolean} * @public */ wrap: _propTypes["default"].bool }, defaultProps: { type: 'string', value: 0 }, styles: { css: _PickerModule["default"], publicClassNames: ['inlineTitle', 'title'] }, computed: { max: function max(_ref) { var children = _ref.children; return children && children.length ? children.length - 1 : 0; }, reverse: function reverse(_ref2) { var orientation = _ref2.orientation, _reverse = _ref2.reverse; return typeof _reverse === 'boolean' ? _reverse : orientation === 'vertical'; }, children: function children(_ref3) { var _children = _ref3.children, disabled = _ref3.disabled, joined = _ref3.joined, marqueeDisabled = _ref3.marqueeDisabled; return _react.Children.map(_children, function (child) { var focusOrHover = !disabled && joined ? 'focus' : 'hover'; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Picker.PickerItem, { marqueeDisabled: marqueeDisabled, marqueeOn: focusOrHover, children: child }); }); }, disabled: function disabled(_ref4) { var children = _ref4.children, _disabled = _ref4.disabled; return _react.Children.count(children) > 1 ? _disabled : true; }, value: function value(_ref5) { var _value = _ref5.value, children = _ref5.children; var max = children && children.length ? children.length - 1 : 0; if (process.env.NODE_ENV !== "production") { (0, _validators.validateRange)(_value, 0, max, 'Picker', 'value', 'min', 'max index'); } return (0, _util.clamp)(0, max, _value); }, voiceLabel: function voiceLabel(_ref6) { var children = _ref6.children, voiceLabelsExt = _ref6['data-webos-voice-labels-ext']; var voiceLabel; if (voiceLabelsExt) { voiceLabel = voiceLabelsExt; } else { voiceLabel = _react.Children.map(children, function (child) { return typeof child === 'number' || typeof child === 'string' ? child : ''; }); } return JSON.stringify(voiceLabel); } }, render: function render(_ref7) { var children = _ref7.children, css = _ref7.css, inlineTitle = _ref7.inlineTitle, max = _ref7.max, title = _ref7.title, value = _ref7.value, voiceLabel = _ref7.voiceLabel, rest = _objectWithoutProperties(_ref7, _excluded); delete rest.marqueeDisabled; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [title ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Heading["default"], { className: (0, _classnames2["default"])(css.title, _defineProperty({}, css.inlineTitle, inlineTitle)), marqueeOn: "hover", size: "tiny", children: title }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Picker["default"], _objectSpread(_objectSpread({}, rest), {}, { "data-webos-voice-labels-ext": voiceLabel, min: 0, max: max, index: value, step: 1, title: title, value: value, children: children }))] }); } }); /** * A Picker component that allows selecting values from a list of values. * * By default, `Picker` maintains the state of its `value` property. Supply the `defaultValue` * property to control its initial value. If you wish to directly control updates to the component, * supply a value to `value` at creation time and update it in response to `onChange` events. * * @class Picker * @memberof sandstone/Picker * @extends sandstone/Picker.PickerBase * @mixes ui/Changeable.Changeable * @mixes sandstone/Marquee.MarqueeController * @ui * @public */ var Picker = exports.Picker = (0, _Pure["default"])((0, _Changeable["default"])((0, _Marquee.MarqueeController)({ marqueeOnFocus: true }, PickerBase))); /** * Default index of the selected child. * * *Note*: Changing `defaultValue` after initial render has no effect. * * @name defaultValue * @memberof sandstone/Picker.Picker.prototype * @type {Number} * @public */ var _default = exports["default"] = Picker;