@onesy/ui-react
Version:
UI for React
324 lines (309 loc) • 14.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.STATUS = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _utils = require("@onesy/utils");
var _subscription = _interopRequireDefault(require("@onesy/subscription"));
var _styleReact = require("@onesy/style-react");
var _Context = _interopRequireDefault(require("./Context"));
var _utils2 = require("../utils");
var _jsxRuntime = require("react/jsx-runtime");
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) { (0, _defineProperty2.default)(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; }
const STATUS = exports.STATUS = {
appended: 'appended',
add: 'add',
added: 'added',
adding: 'adding',
enter: 'enter',
entering: 'entering',
entered: 'entered',
exit: 'exit',
exiting: 'exiting',
exited: 'exited',
removed: 'removed'
};
const Transition = props_ => {
var _theme$ui, _theme$ui2;
const theme = (0, _styleReact.useOnesyTheme)();
const props = _objectSpread(_objectSpread(_objectSpread({}, theme === null || theme === void 0 || (_theme$ui = theme.ui) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.elements) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.all) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.props) === null || _theme$ui === void 0 ? void 0 : _theme$ui.default), theme === null || theme === void 0 || (_theme$ui2 = theme.ui) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.elements) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.onesyTransition) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.props) === null || _theme$ui2 === void 0 ? void 0 : _theme$ui2.default), props_);
const {
in: inProp_,
// @ts-ignore
name,
prefix,
run,
append,
add: add_,
enter: enter_ = true,
exit: exit_ = true,
enterOnAdd = props.add || props.enter,
exitOnAdd,
noAbruption,
removeOnExited,
preEnterAppendTimeout = 14,
delay: delay_,
duration: duration_,
// An all in one method
onTransition,
onInit,
onAppended,
onAdd,
onAdding,
onAdded,
onEnter,
onEntering,
onEntered: onEntered_,
onExit,
onExiting,
onExited,
onRemoved,
className,
children,
ref
} = props;
const [init, setInit] = _react.default.useState(false);
const [inProp, setInProp] = _react.default.useState(inProp_);
const [status, setStatus] = _react.default.useState(() => {
let statusNew = '';
if (inProp) {
statusNew = add_ ? STATUS.add : STATUS.entered;
if (enterOnAdd) statusNew = STATUS.enter;
} else {
statusNew = enterOnAdd || removeOnExited ? STATUS.removed : STATUS.exited;
if (exitOnAdd) statusNew = STATUS.exit;
}
if (append) statusNew = 'appended';
return statusNew;
});
const subs = _react.default.useRef({
status: new _subscription.default()
});
const refs = {
root: _react.default.useRef(undefined),
status: _react.default.useRef(undefined),
inProp: _react.default.useRef(undefined),
prefix: _react.default.useRef(undefined)
};
refs.status.current = status;
refs.inProp.current = inProp;
refs.prefix.current = prefix;
_react.default.useEffect(() => {
let statusNew_0;
if (status === 'appended') {
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, 'appended');
if ((0, _utils.is)('function', onAppended)) onAppended(refs.root.current);
}
if (inProp) {
statusNew_0 = add_ ? STATUS.add : STATUS.entered;
if (enterOnAdd) statusNew_0 = STATUS.enter;
} else {
statusNew_0 = enterOnAdd || removeOnExited ? STATUS.removed : STATUS.exited;
if (exitOnAdd) statusNew_0 = STATUS.exit;
}
if ((0, _utils.is)('function', onInit)) onInit(refs.root.current);
// Update
update(statusNew_0);
setInit(true);
}, []);
_react.default.useEffect(() => {
if (init) {
var _refs$root$current, _refs$root$current2;
let statusNew_1;
if (inProp) {
if ([STATUS.enter, STATUS.entered].indexOf(status) === -1) statusNew_1 = STATUS.enter;
} else {
if ([STATUS.exit, STATUS.exited].indexOf(status) === -1) statusNew_1 = STATUS.exit;
}
// Added
const classNameValue = ((_refs$root$current = refs.root.current) === null || _refs$root$current === void 0 || (_refs$root$current = _refs$root$current.className) === null || _refs$root$current === void 0 ? void 0 : _refs$root$current.baseVal) || ((_refs$root$current2 = refs.root.current) === null || _refs$root$current2 === void 0 ? void 0 : _refs$root$current2.className);
if (inProp && (!refs.root.current || (classNameValue === null || classNameValue === void 0 ? void 0 : classNameValue.indexOf('removed')) > -1)) {
// We add the element and get the ref value
// for update below to use it for enter
update('appended');
// Prevent update batches
setTimeout(() => update(statusNew_1), preEnterAppendTimeout);
} else update(statusNew_1);
}
}, [inProp]);
_react.default.useEffect(() => {
if (status === STATUS.exited && removeOnExited) {
updateStatus('removed');
// Subscriptions
subs.current.status.emit('removed');
}
}, [status]);
_react.default.useEffect(() => {
if (!inProp_ && noAbruption && ['enter', 'entering'].indexOf(subs.current.status.value) > -1) {
const sub = item => {
if (item === 'entered') {
setInProp(inProp_);
subs.current.status.unsubscribe(sub);
}
};
subs.current.status.subscribe(sub);
} else if (inProp_ && noAbruption && ['exit', 'exiting'].indexOf(subs.current.status.value) > -1) {
const sub_0 = item_0 => {
if (item_0 === 'exited') {
setInProp(inProp_);
subs.current.status.unsubscribe(sub_0);
}
};
subs.current.status.subscribe(sub_0);
} else if (!inProp_ && noAbruption && subs.current.status.value === 'entered' || inProp_ && noAbruption && subs.current.status.value === 'exited' || inProp_ !== inProp) setInProp(inProp_);
}, [inProp_]);
const update = async (status_, pause) => {
if (pause !== undefined) await (0, _utils.wait)(pause);
refs.status.current = status_;
switch (status_) {
case 'add':
return await add(status_);
case 'enter':
return await enter(status_);
case 'exit':
return await exit(status_);
case 'exited':
return updateStatus(status_);
default:
return updateStatus(status_);
}
};
const delay = async status__0 => {
let value = delay_;
if ((0, _utils.is)('string', value) && theme.transitions.duration[value] !== undefined) value = theme.transitions.duration[value];
if ((0, _utils.is)('object', value)) value = value[status__0] !== undefined ? value[status__0] : value.default;
if (!((0, _utils.is)('number', value) && value > 0)) return;
await (0, _utils.wait)(value);
};
const duration = async status__1 => {
let value_0 = duration_;
if ((0, _utils.is)('string', value_0) && theme.transitions.duration[value_0] !== undefined) value_0 = theme.transitions.duration[value_0];
if ((0, _utils.is)('object', value_0)) value_0 = value_0[status__1] !== undefined ? value_0[status__1] : value_0.default;
if (!(0, _utils.is)('number', value_0)) value_0 = theme.transitions.duration.rg;
if (!((0, _utils.is)('number', value_0) && value_0 > 0)) return;
await (0, _utils.wait)(value_0);
};
const add = async status__2 => {
if (!add_ || refs.status.current !== status__2) return;
updateStatus('add');
await delay('add');
// Prevent update batches
await (0, _utils.wait)(14);
updateStatus('adding');
// await duration('add');
if (refs.status.current === status__2) updateStatus('added');
};
const enter = async status__3 => {
var _refs$status$current;
if (!enter_ || status__3 !== 'appended' && (refs.status.current !== status__3 || !refs.inProp.current)) return;
updateStatus('enter');
await delay('enter');
// Prevent update batches
await (0, _utils.wait)(14);
updateStatus('entering');
await duration('enter');
if (((_refs$status$current = refs.status.current) === null || _refs$status$current === void 0 ? void 0 : _refs$status$current.indexOf('exit')) === -1) updateStatus('entered');
};
const exit = async status__4 => {
var _refs$status$current2;
if (!exit_ || refs.status.current !== status__4 || refs.inProp.current) return;
updateStatus('exit');
await delay('exit');
// Prevent update batches
await (0, _utils.wait)(14);
updateStatus('exiting');
await duration('exit');
if (((_refs$status$current2 = refs.status.current) === null || _refs$status$current2 === void 0 ? void 0 : _refs$status$current2.indexOf('enter')) === -1) updateStatus('exited');
};
const onEntered = element => {
if ((0, _utils.is)('function', onEntered_)) onEntered_(element);
if (run && inProp) setInProp(false);
};
const updateStatus = status__5 => {
setStatus(status__5);
// Subscriptions
subs.current.status.emit(status__5);
switch (status__5) {
case 'appended':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onAppended)) onAppended(refs.root.current);
break;
case 'add':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onAdd)) onAdd(refs.root.current);
break;
case 'adding':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onAdding)) onAdding(refs.root.current);
break;
case 'added':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onAdded)) onAdded(refs.root.current);
break;
case 'enter':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onEnter)) onEnter(refs.root.current);
break;
case 'entering':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onEntering)) onEntering(refs.root.current);
break;
case 'entered':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onEntered)) onEntered(refs.root.current);
break;
case 'exit':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onExit)) onExit(refs.root.current);
break;
case 'exiting':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onExiting)) onExiting(refs.root.current);
break;
case 'exited':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onExited)) onExited(refs.root.current);
break;
case 'removed':
if ((0, _utils.is)('function', onTransition)) onTransition(refs.root.current, status__5);
if ((0, _utils.is)('function', onRemoved)) onRemoved(refs.root.current);
break;
default:
break;
}
// Add className
if (className && (0, _utils.is)('element', refs.root.current)) {
var _ref, _refs$root$current$cl, _refs$root$current$cl2;
let className_ = (0, _styleReact.classNames)([(_ref = ((_refs$root$current$cl = refs.root.current.className) === null || _refs$root$current$cl === void 0 ? void 0 : _refs$root$current$cl.baseVal) || refs.root.current.className) === null || _ref === void 0 ? void 0 : _ref.split(' ')]);
// Remove all previous classes
className_ = className_.replace(new RegExp(`(^| )${refs.prefix.current || ''}(add|enter|exit)(ed|ing)?($| )`, 'g'), ' ');
// Add
className_ += ` ${refs.prefix.current || ''}${status__5}`;
className_ = className_.replace(/ +/g, ' ').trim();
if ((_refs$root$current$cl2 = refs.root.current.className) !== null && _refs$root$current$cl2 !== void 0 && _refs$root$current$cl2.baseVal) refs.root.current.className.baseVal = className_;else refs.root.current.className = className_;
}
// reflow
(0, _utils2.reflow)(refs.root.current);
};
if (status === 'removed') return null;
const value_ = {
status
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Context.default.Provider, {
value: value_,
children: (0, _utils.is)('function', children) ? children(status, refs.root) : /*#__PURE__*/_react.default.cloneElement(children, {
ref: item_1 => {
if (ref) {
if ((0, _utils.is)('function', ref)) ref(item_1);else ref.current = item_1;
}
refs.root.current = item_1;
}
})
});
};
Transition.displayName = 'onesy-Transition';
var _default = exports.default = Transition;