UNPKG

@enact/sandstone

Version:

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

485 lines (473 loc) 17.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.InputFieldDecorator = exports.InputFieldBase = exports.InputField = void 0; var _handle = require("@enact/core/handle"); var _kind = _interopRequireDefault(require("@enact/core/kind")); var _platform = _interopRequireDefault(require("@enact/core/platform")); var _I18nDecorator = require("@enact/i18n/I18nDecorator"); var _util = require("@enact/i18n/util"); var _AnnounceDecorator = require("@enact/ui/AnnounceDecorator"); var _Changeable = _interopRequireDefault(require("@enact/ui/Changeable")); var _Pure = _interopRequireDefault(require("@enact/ui/internal/Pure")); var _speech = require("@enact/webos/speech"); var _classnames2 = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); var _compose = _interopRequireDefault(require("ramda/src/compose")); var _react = require("react"); var _$L = _interopRequireDefault(require("../internal/$L")); var _Skinnable = _interopRequireDefault(require("../Skinnable")); var _Tooltip = _interopRequireDefault(require("../TooltipDecorator/Tooltip")); var _util2 = require("../internal/util"); var _InputFieldDecoratorIcon = _interopRequireDefault(require("./InputFieldDecoratorIcon")); var _InputFieldSpotlightDecorator = _interopRequireDefault(require("./InputFieldSpotlightDecorator")); var _util3 = require("./util"); var _InputFieldModule = _interopRequireDefault(require("./InputField.module.css")); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["css", "dir", "disabled", "iconAfter", "iconBefore", "invalidTooltip", "onChange", "placeholder", "size", "type", "value"]; /** * A Sandstone styled input component. * * It supports start and end icons but it does not support Spotlight. Apps should use * {@link sandstone/Input.InputField}. * * @class InputFieldBase * @memberof sandstone/Input * @ui * @public */ 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 InputFieldBase = exports.InputFieldBase = (0, _kind["default"])({ name: 'InputField', propTypes: /** @lends sandstone/Input.InputFieldBase.prototype */{ /** * Passed by AnnounceDecorator for accessibility. * * @type {Function} * @public */ announce: _propTypes["default"].func, /** * 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: * * * `inputField` - The root class name * * `input` - The <input> class name * * `inputHighlight` - The class used to make input text appear highlighted when `.inputField` has focus, but not `.input` * * `tooltip` - The "invalid" tooltip * * `tooltipLabel` - The "invalid" tooltip's label * * @type {Object} * @private */ css: _propTypes["default"].object, // TODO: Document voice control props and make public 'data-webos-voice-group-label': _propTypes["default"].string, 'data-webos-voice-intent': _propTypes["default"].string, 'data-webos-voice-label': _propTypes["default"].string, /** * Disables InputField and becomes non-interactive. * * @type {Boolean} * @default false * @public */ disabled: _propTypes["default"].bool, /** * Blurs the input when the "enter" key is pressed. * * @type {Boolean} * @default false * @public */ dismissOnEnter: _propTypes["default"].bool, /** * The icon to be placed at the end of the input. * * @see {@link sandstone/Icon.Icon} * @type {String} * @public */ iconAfter: _propTypes["default"].string, /** * The icon to be placed at the beginning of the input. * * @see {@link sandstone/Icon.Icon} * @type {String} * @public */ iconBefore: _propTypes["default"].string, /** * Indicates {@link sandstone/Input.InputFieldBase.value|value} is invalid and shows * {@link sandstone/Input.InputFieldBase.invalidMessage|invalidMessage}, if set. * * @type {Boolean} * @default false * @public */ invalid: _propTypes["default"].bool, /** * The tooltip text to be displayed when the input is * {@link sandstone/Input.InputFieldBase.invalid|invalid}. * * If this value is *falsy*, the tooltip will be shown with the default message. * * @type {String} * @default 'Please enter a valid value.' * @public */ invalidMessage: _propTypes["default"].string, /** * Called before the input value is changed. * * The change can be prevented by calling `preventDefault` on the event. * * @type {Function} * @public */ onBeforeChange: _propTypes["default"].func, /** * Called when blurred. * * @type {Function} * @param {Object} event * @public */ onBlur: _propTypes["default"].func, /** * Called when the input value is changed. * * The event payload includes the current `value` as well as a `stopPropagation()` method * which may be called to stop the original `onChange` event from the `<input>` from * bubbling. * * @type {Function} * @param {Object} event * @public */ onChange: _propTypes["default"].func, /** * Called when clicked. * * @type {Function} * @param {Object} event * @public */ onClick: _propTypes["default"].func, /** * Called when focused. * * @type {Function} * @param {Object} event * @public */ onFocus: _propTypes["default"].func, /** * Called when a key is pressed down. * * @type {Function} * @param {Object} event * @public */ onKeyDown: _propTypes["default"].func, /** * Text to display when {@link sandstone/Input.InputFieldBase.value|value} is not set. * * @type {String} * @default '' * @public */ placeholder: _propTypes["default"].string, /** * Indicates the content's text direction is right-to-left. * * @type {Boolean} * @private */ rtl: _propTypes["default"].bool, /** * The size of the input field. * * @type {('large'|'small')} * @default 'small' * @public */ size: _propTypes["default"].oneOf(['small', 'large']), /** * The type of input. * * Accepted values correspond to the standard HTML5 input types. * * @type {String} * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types|MDN input types doc} * @default 'text' * @public */ type: _propTypes["default"].string, /** * The value of the input. * * @type {String|Number} * @public */ value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]) }, defaultProps: { disabled: false, dismissOnEnter: false, invalid: false, placeholder: '', size: 'small', type: 'text' }, styles: { css: _InputFieldModule["default"], className: 'inputField', publicClassNames: ['inputField', 'input', 'inputHighlight', 'tooltip', 'tooltipLabel'] }, handlers: { onChange: (0, _handle.handle)((0, _handle.forwardCustomWithPrevent)('onBeforeChange', function (ev) { return { value: ev.target.value }; }), (0, _handle.returnsTrue)(function (ev, _ref) { var announce = _ref.announce, type = _ref.type; if (type === 'passwordtel') { if (_platform["default"].type === 'webos') { (0, _speech.readAlert)((0, _$L["default"])('hidden')); } else { announce((0, _$L["default"])('hidden')); } } }), (0, _handle.forwardCustom)('onChange', function (ev) { return { value: ev.target.value }; })) }, computed: { 'aria-label': function ariaLabel(_ref2) { var placeholder = _ref2.placeholder, type = _ref2.type, value = _ref2.value; var title = value == null || value === '' ? placeholder : ''; return (0, _util3.calcAriaLabel)(title, type, value); }, className: function className(_ref3) { var invalid = _ref3.invalid, size = _ref3.size, styler = _ref3.styler; return styler.append({ invalid: invalid }, size); }, dir: function dir(_ref4) { var value = _ref4.value, placeholder = _ref4.placeholder; return (0, _util.isRtlText)(value || placeholder) ? 'rtl' : 'ltr'; }, invalidTooltip: function invalidTooltip(_ref5) { var css = _ref5.css, invalid = _ref5.invalid, _ref5$invalidMessage = _ref5.invalidMessage, invalidMessage = _ref5$invalidMessage === void 0 ? (0, _$L["default"])('Please enter a valid value.') : _ref5$invalidMessage; if (invalid && invalidMessage) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip["default"], { css: css, marquee: true, relative: true, type: "transparent", children: invalidMessage }); } }, // ensure we have a value so the internal <input> is always controlled value: function value(_ref6) { var _value = _ref6.value; return typeof _value === 'number' ? _value : _value || ''; } }, render: function render(_ref7) { var css = _ref7.css, dir = _ref7.dir, disabled = _ref7.disabled, iconAfter = _ref7.iconAfter, iconBefore = _ref7.iconBefore, invalidTooltip = _ref7.invalidTooltip, onChange = _ref7.onChange, placeholder = _ref7.placeholder, size = _ref7.size, type = _ref7.type, value = _ref7.value, rest = _objectWithoutProperties(_ref7, _excluded); var inputProps = (0, _util3.extractInputProps)(rest); var voiceProps = (0, _util2.extractVoiceProps)(rest); var isPasswordtel = type === 'passwordtel'; if (type === 'password' || type === 'passwordtel') { inputProps.spellCheck = false; } delete rest.announce; delete rest.dismissOnEnter; delete rest.invalid; delete rest.invalidMessage; delete rest.onBeforeChange; delete rest.rtl; return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", _objectSpread(_objectSpread({}, rest), {}, { "aria-disabled": disabled, disabled: disabled, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: css.bg }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputFieldDecoratorIcon["default"], { position: "before", size: size, children: iconBefore }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", { className: css.inputHighlight, children: value ? value : placeholder }), /*#__PURE__*/(0, _jsxRuntime.jsx)("input", _objectSpread(_objectSpread(_objectSpread({}, inputProps), voiceProps), {}, { "aria-hidden": isPasswordtel, className: (0, _classnames2["default"])(css.input, _defineProperty({}, css.passwordtel, isPasswordtel)), dir: dir, disabled: disabled, onChange: onChange, placeholder: placeholder, tabIndex: -1, type: isPasswordtel ? 'tel' : type, value: value })), /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputFieldDecoratorIcon["default"], { position: "after", size: size, children: iconAfter }), invalidTooltip] })); } }); // eslint-disable-next-line no-shadow var AnnounceDecorator = function AnnounceDecorator(Wrapped) { return function AnnounceDecorator(props) { var _useAnnounce = (0, _AnnounceDecorator.useAnnounce)(), announce = _useAnnounce.announce, children = _useAnnounce.children; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapped, _objectSpread(_objectSpread({}, props), {}, { announce: announce })), children] }); }; }; /** * Sandstone specific item behaviors to apply to {@link sandstone/Input.InputFieldBase|InputField}. * * @class InputFieldDecorator * @hoc * @memberof sandstone/Input * @mixes ui/Changeable.Changeable * @mixes sandstone/Skinnable.Skinnable * @public */ var InputFieldDecorator = exports.InputFieldDecorator = (0, _compose["default"])(_Pure["default"], (0, _I18nDecorator.I18nContextDecorator)({ rtlProp: 'rtl' }), _Changeable["default"], _InputFieldSpotlightDecorator["default"], AnnounceDecorator, _Skinnable["default"]); /** * A Spottable, Sandstone styled input component with embedded icon support. * * By default, `InputField` 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 InputField * @memberof sandstone/Input * @extends sandstone/Input.InputFieldBase * @mixes ui/Changeable.Changeable * @mixes spotlight/Spottable.Spottable * @mixes sandstone/Skinnable.Skinnable * @ui * @public */ var InputField = exports.InputField = InputFieldDecorator(InputFieldBase); /** * Focuses the internal input when the component gains 5-way focus. * * By default, the internal input is not editable when the component is focused via 5-way and must * be selected to become interactive. In pointer mode, the input will be editable when clicked. * * @name autoFocus * @memberof sandstone/Input.InputField.prototype * @type {Boolean} * @default false * @public */ /** * Applies a disabled style and prevents interacting with the component. * * @name disabled * @memberof sandstone/Input.InputField.prototype * @type {Boolean} * @default false * @public */ /** * Sets the initial value. * * @name defaultValue * @memberof sandstone/Input.InputField.prototype * @type {String} * @public */ /** * Blurs the input when the "enter" key is pressed. * * @name dismissOnEnter * @memberof sandstone/Input.InputField.prototype * @type {Boolean} * @default false * @public */ /** * Called when the internal input is focused. * * @name onActivate * @memberof sandstone/Input.InputField.prototype * @type {Function} * @param {Object} event * @public */ /** * Called when the internal input loses focus. * * @name onDeactivate * @memberof sandstone/Input.InputField.prototype * @type {Function} * @param {Object} event * @public */ /** * Called when the component is removed when it had focus. * * @name onSpotlightDisappear * @memberof sandstone/Input.InputField.prototype * @type {Function} * @param {Object} event * @public */ /** * Disables spotlight navigation into the component. * * @name spotlightDisabled * @memberof sandstone/Input.InputField.prototype * @type {Boolean} * @default false * @public */ var _default = exports["default"] = InputField;