@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
JavaScript
;
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