@enact/sandstone
Version:
Large-screen/TV support library for Enact, containing a variety of UI components.
390 lines (387 loc) • 16.2 kB
JavaScript
;
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;