UNPKG

@renderlesskit/react

Version:

Collection of headless components/hooks that are accessible, composable, customizable from low level to build your own UI & Design System powered by Reakit

158 lines (126 loc) 7.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useSegmentState = useSegmentState; var _react = require("react"); var _reakit = require("reakit"); var _i18n = require("@react-aria/i18n"); var _utils = require("../utils"); var _helpers = require("./helpers"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } 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."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } var EDITABLE_SEGMENTS = { year: true, month: true, day: true, hour: true, minute: true, second: true, dayPeriod: true }; var PAGE_STEP = { year: 5, month: 2, day: 7, hour: 2, minute: 15, second: 15 }; // Node seems to convert everything to lowercase... var TYPE_MAPPING = { dayperiod: "dayPeriod" }; function useSegmentState(props) { var _useState = (0, _react.useState)(props.value || props.defaultValue ? _objectSpread({}, EDITABLE_SEGMENTS) : {}), _useState2 = _slicedToArray(_useState, 2), validSegments = _useState2[0], setValidSegments = _useState2[1]; // https://stackoverflow.com/a/9893752/10629172 var dateFormatter = (0, _i18n.useDateFormatter)(props.formatOptions); var resolvedOptions = (0, _react.useMemo)(function () { return dateFormatter.resolvedOptions(); }, [dateFormatter]); // Determine how many editable segments there are for validation purposes. // The result is cached for performance. var numSegments = (0, _react.useMemo)(function () { return dateFormatter.formatToParts(new Date()).filter(function (seg) { return EDITABLE_SEGMENTS[seg.type]; }).length; }, [dateFormatter]); // If there is a value prop, and some segments were previously placeholders, mark them all as valid. if (props.value && Object.keys(validSegments).length < numSegments) { setValidSegments(_objectSpread({}, EDITABLE_SEGMENTS)); } // We keep track of the placeholder date separately in state so that onChange is not called // until all segments are set. If the value === null (not undefined), then assume the component // is controlled, so use the placeholder as the value until all segments are entered so it doesn't // change from uncontrolled to controlled and emit a warning. var _useState3 = (0, _react.useState)((0, _helpers.convertValue)(props.placeholderDate) || new Date(new Date().getFullYear(), 0, 1)), _useState4 = _slicedToArray(_useState3, 2), placeholderDate = _useState4[0], setPlaceholderDate = _useState4[1]; var _useControllableState = (0, _utils.useControllableState)({ value: props.value === null ? (0, _helpers.convertValue)(placeholderDate) : (0, _helpers.convertValue)(props.value), defaultValue: (0, _helpers.convertValue)(props.defaultValue), onChange: props.onChange }), _useControllableState2 = _slicedToArray(_useControllableState, 2), date = _useControllableState2[0], setDate = _useControllableState2[1]; // If all segments are valid, use the date from state, otherwise use the placeholder date. var value = Object.keys(validSegments).length >= numSegments ? date : placeholderDate; var setValue = function setValue(value) { if (Object.keys(validSegments).length >= numSegments) { setDate(value); } else { setPlaceholderDate(value); } }; var segments = dateFormatter.formatToParts(value).map(function (segment) { return _objectSpread(_objectSpread({ type: TYPE_MAPPING[segment.type] || segment.type, text: segment.value }, (0, _helpers.getSegmentLimits)(value, segment.type, resolvedOptions)), {}, { isPlaceholder: !validSegments[segment.type] }); }); var adjustSegment = function adjustSegment(type, amount) { validSegments[type] = true; setValidSegments(_objectSpread({}, validSegments)); setValue((0, _helpers.add)(value, type, amount, resolvedOptions)); }; var segmentComposite = (0, _reakit.useCompositeState)({ orientation: "horizontal" }); return _objectSpread(_objectSpread({}, segmentComposite), {}, { fieldValue: value, setFieldValue: setValue, segments: segments, dateFormatter: dateFormatter, increment: function increment(part) { adjustSegment(part, 1); }, decrement: function decrement(part) { adjustSegment(part, -1); }, incrementPage: function incrementPage(part) { adjustSegment(part, PAGE_STEP[part] || 1); }, decrementPage: function decrementPage(part) { adjustSegment(part, -(PAGE_STEP[part] || 1)); }, setSegment: function setSegment(part, v) { validSegments[part] = true; setValidSegments(_objectSpread({}, validSegments)); // @ts-ignore setValue((0, _helpers.setSegment)(value, part, v, resolvedOptions)); }, confirmPlaceholder: function confirmPlaceholder(part) { validSegments[part] = true; setValidSegments(_objectSpread({}, validSegments)); setValue(new Date(value)); } }); } //# sourceMappingURL=SegmentState.js.map