@amaui/ui-react
Version:
UI for React
348 lines (347 loc) • 15.3 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.STATUS = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const utils_1 = require("@amaui/utils");
const subscription_1 = __importDefault(require("@amaui/subscription"));
const style_react_1 = require("@amaui/style-react");
const Context_1 = __importDefault(require("./Context"));
const utils_2 = require("../utils");
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_) => {
const theme = (0, style_react_1.useAmauiTheme)();
const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiTransition) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]);
const { in: inProp_, 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_1.default.useState(false);
const [inProp, setInProp] = react_1.default.useState(inProp_);
const [status, setStatus] = react_1.default.useState(() => {
let statusNew = '';
if (inProp) {
statusNew = add_ ? exports.STATUS.add : exports.STATUS.entered;
if (enterOnAdd)
statusNew = exports.STATUS.enter;
}
else {
statusNew = (enterOnAdd || removeOnExited) ? exports.STATUS.removed : exports.STATUS.exited;
if (exitOnAdd)
statusNew = exports.STATUS.exit;
}
if (append)
statusNew = 'appended';
return statusNew;
});
const subs = react_1.default.useRef({
status: new subscription_1.default()
});
const refs = {
root: react_1.default.useRef(undefined),
status: react_1.default.useRef(undefined),
inProp: react_1.default.useRef(undefined),
prefix: react_1.default.useRef(undefined)
};
refs.status.current = status;
refs.inProp.current = inProp;
refs.prefix.current = prefix;
react_1.default.useEffect(() => {
let statusNew;
if (status === 'appended') {
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, 'appended');
if ((0, utils_1.is)('function', onAppended))
onAppended(refs.root.current);
}
if (inProp) {
statusNew = add_ ? exports.STATUS.add : exports.STATUS.entered;
if (enterOnAdd)
statusNew = exports.STATUS.enter;
}
else {
statusNew = (enterOnAdd || removeOnExited) ? exports.STATUS.removed : exports.STATUS.exited;
if (exitOnAdd)
statusNew = exports.STATUS.exit;
}
if ((0, utils_1.is)('function', onInit))
onInit(refs.root.current);
// Update
update(statusNew);
setInit(true);
}, []);
react_1.default.useEffect(() => {
var _a, _b, _c;
if (init) {
let statusNew;
if (inProp) {
if ([exports.STATUS.enter, exports.STATUS.entered].indexOf(status) === -1)
statusNew = exports.STATUS.enter;
}
else {
if ([exports.STATUS.exit, exports.STATUS.exited].indexOf(status) === -1)
statusNew = exports.STATUS.exit;
}
// Added
const classNameValue = ((_b = (_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.className) === null || _b === void 0 ? void 0 : _b.baseVal) || ((_c = refs.root.current) === null || _c === void 0 ? void 0 : _c.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), preEnterAppendTimeout);
}
else
update(statusNew);
}
}, [inProp]);
react_1.default.useEffect(() => {
if (status === exports.STATUS.exited && removeOnExited) {
updateStatus('removed');
// Subscriptions
subs.current.status.emit('removed');
}
}, [status]);
react_1.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 = (item) => {
if (item === 'exited') {
setInProp(inProp_);
subs.current.status.unsubscribe(sub);
}
};
subs.current.status.subscribe(sub);
}
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_1.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 = react_1.default.useCallback(async (status_) => {
let value = delay_;
if ((0, utils_1.is)('string', value) &&
theme.transitions.duration[value] !== undefined)
value = theme.transitions.duration[value];
if ((0, utils_1.is)('object', value))
value = value[status_] !== undefined ? value[status_] : value.default;
if (!((0, utils_1.is)('number', value) && value > 0))
return;
await (0, utils_1.wait)(value);
}, [delay_, theme]);
const duration = react_1.default.useCallback(async (status_) => {
let value = duration_;
if ((0, utils_1.is)('string', value) &&
theme.transitions.duration[value] !== undefined)
value = theme.transitions.duration[value];
if ((0, utils_1.is)('object', value))
value = value[status_] !== undefined ? value[status_] : value.default;
if (!(0, utils_1.is)('number', value))
value = theme.transitions.duration.rg;
if (!((0, utils_1.is)('number', value) && value > 0))
return;
await (0, utils_1.wait)(value);
}, [duration_, theme]);
const add = async (status_) => {
if (!add_ ||
(refs.status.current !== status_))
return;
updateStatus('add');
// Reflow
(0, utils_2.reflow)(refs.root.current);
await delay('add');
// Prevent update batches
await (0, utils_1.wait)(14);
updateStatus('adding');
// await duration('add');
if (refs.status.current === status_)
updateStatus('added');
};
const enter = async (status_) => {
var _a;
if (!enter_ ||
(status_ !== 'appended' &&
(refs.status.current !== status_ || !refs.inProp.current)))
return;
updateStatus('enter');
// Reflow
(0, utils_2.reflow)(refs.root.current);
await delay('enter');
// Prevent update batches
await (0, utils_1.wait)(14);
updateStatus('entering');
await duration('enter');
if (((_a = refs.status.current) === null || _a === void 0 ? void 0 : _a.indexOf('exit')) === -1)
updateStatus('entered');
};
const exit = async (status_) => {
var _a;
if (!exit_ ||
(refs.status.current !== status_ || refs.inProp.current))
return;
updateStatus('exit');
// Reflow
(0, utils_2.reflow)(refs.root.current);
await delay('exit');
// Prevent update batches
await (0, utils_1.wait)(14);
updateStatus('exiting');
await duration('exit');
if (((_a = refs.status.current) === null || _a === void 0 ? void 0 : _a.indexOf('enter')) === -1)
updateStatus('exited');
};
const onEntered = (element) => {
if ((0, utils_1.is)('function', onEntered_))
onEntered_(element);
if (run && inProp)
setInProp(false);
};
const updateStatus = (status_) => {
var _a, _b, _c;
setStatus(status_);
// Subscriptions
subs.current.status.emit(status_);
switch (status_) {
case 'appended':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onAppended))
onAppended(refs.root.current);
break;
case 'add':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onAdd))
onAdd(refs.root.current);
break;
case 'adding':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onAdding))
onAdding(refs.root.current);
break;
case 'added':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onAdded))
onAdded(refs.root.current);
break;
case 'enter':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onEnter))
onEnter(refs.root.current);
break;
case 'entering':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onEntering))
onEntering(refs.root.current);
break;
case 'entered':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onEntered))
onEntered(refs.root.current);
break;
case 'exit':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onExit))
onExit(refs.root.current);
break;
case 'exiting':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onExiting))
onExiting(refs.root.current);
break;
case 'exited':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onExited))
onExited(refs.root.current);
break;
case 'removed':
if ((0, utils_1.is)('function', onTransition))
onTransition(refs.root.current, status_);
if ((0, utils_1.is)('function', onRemoved))
onRemoved(refs.root.current);
break;
default:
break;
}
// Add className
if (className && (0, utils_1.is)('element', refs.root.current)) {
let className_ = (0, style_react_1.classNames)([(_b = (((_a = refs.root.current.className) === null || _a === void 0 ? void 0 : _a.baseVal) || refs.root.current.className)) === null || _b === void 0 ? void 0 : _b.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_}`;
className_ = className_.replace(/ +/g, ' ').trim();
if ((_c = refs.root.current.className) === null || _c === void 0 ? void 0 : _c.baseVal)
refs.root.current.className.baseVal = className_;
else
refs.root.current.className = className_;
}
};
if (status === 'removed')
return null;
const value_ = {
status
};
return ((0, jsx_runtime_1.jsx)(Context_1.default.Provider, Object.assign({ value: value_ }, { children: (0, utils_1.is)('function', children) ?
children(status, refs.root) :
react_1.default.cloneElement(children, {
ref: (item) => {
if (ref) {
if ((0, utils_1.is)('function', ref))
ref(item);
else
ref.current = item;
}
refs.root.current = item;
}
}) })));
};
Transition.displayName = 'amaui-Transition';
exports.default = Transition;
;