@amaui/ui-react
Version:
UI for React
183 lines (171 loc) • 6.49 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
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; }
import React from 'react';
import { is, wait } from '@amaui/utils';
import AmauiSubscription from '@amaui/subscription';
import { classNames, useAmauiTheme } from '@amaui/style-react';
import KeyframesContext from './Context';
import { reflow } from '../utils';
const Keyframes = props_ => {
const theme = useAmauiTheme();
const props = React.useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.amauiKeyframes?.props?.default), props_), [props_]);
const {
ref,
append,
update,
timeout: timeout_,
appendStatusPost,
add: add_,
runOnEnter,
removeOnEnd,
keyframes,
prefix,
onKeyframes,
onAppended,
onAdd,
onAdding,
onAdded,
onRemoved,
className,
children
} = props;
const [init, setInit] = React.useState(false);
const [status, setStatus] = React.useState(() => {
let statusNew = '';
if (append) statusNew = 'appended';
return statusNew;
});
const subs = React.useRef({
status: new AmauiSubscription()
});
const refs = {
root: React.useRef(undefined),
status: React.useRef(status)
};
React.useEffect(() => {
initMethod();
}, []);
// Anytime update updates
// keyframes are ran
// meaning you can update
// keyframes between reruns
// and have any version of
// animation based on those points
// ie. Switch ui on and off animation
React.useEffect(() => {
if (init) run();
}, [update]);
const initMethod = async () => {
// Appended
if (status === 'appended') updateStatus(appendStatusPost);
// Add
if (add_ || status === 'add') await add();
// Run the method
// to run the keyframes
if (runOnEnter) await run();
// Init
setInit(true);
};
const run = async () => {
// Run all keyframes
if (is('array', keyframes)) for (const keyframe of keyframes) await runKeyframe(keyframe);
if (removeOnEnd) {
// So exited status has
// enough time to apply some value
setStatus('removed');
// Subscriptions
subs.current.status.emit('removed');
}
};
const runKeyframe = async value_ => {
if (value_) {
const {
name,
timeout: timeout__
} = value_;
updateStatus(name);
await wait(timeout__ || 0);
}
};
const timeout = async status_ => {
let duration = timeout_;
if (is('string', timeout_) && theme.transitions.duration[timeout_] !== undefined) duration = theme.transitions.duration[timeout_];
if (is('object', timeout_)) duration = timeout_[status_] !== undefined ? timeout_[status_] : timeout_.default;
if (!is('number', duration)) duration = theme.transitions.duration.rg;
await wait(duration);
};
const add = async () => {
updateStatus('add');
// Reflow
reflow(refs.root.current);
// Add adding class for animation
setTimeout(() => updateStatus('adding'));
await timeout('add');
updateStatus('added');
await wait(0);
};
const updateStatus = function () {
let status_ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : status;
// Update
setStatus(status_);
// Subscriptions
subs.current.status.emit(status_);
switch (status_) {
case 'appended':
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
if (is('function', onAppended)) onAppended(refs.root.current);
break;
case 'add':
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
if (is('function', onAdd)) onAdd(refs.root.current);
break;
case 'adding':
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
if (is('function', onAdding)) onAdding(refs.root.current);
break;
case 'added':
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
if (is('function', onAdded)) onAdded(refs.root.current);
break;
case 'removed':
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
if (is('function', onRemoved)) onRemoved(refs.root.current);
break;
default:
if (is('function', onKeyframes)) onKeyframes(refs.root.current, status_);
break;
}
// Add className
if (className && is('element', refs.root.current)) {
let className_ = classNames([refs.root.current.className.split(' ')]);
// Remove all previous state classes
className_ = className_.replace(new RegExp(`${prefix || ''}(add)(ed|ing)?`, 'g'), '');
// Remove all previous keyframes classes
if (is('array', keyframes)) {
const regex = new RegExp(`${keyframes.reduce((result, item, index) => result += `${index !== 0 ? '|' : ''}${item}`, '')}`, 'g');
className_ = className_.replace(regex, '');
}
// Add
className_ += ` ${prefix || ''}${status_}`;
className_ = className_.replace(/ +/g, ' ').trim();
refs.root.current.className = className_;
}
};
if (status === 'removed') return null;
const value = {
status
};
return /*#__PURE__*/React.createElement(KeyframesContext.Provider, {
value: value
}, is('function', children) ? children(status, refs.root) : /*#__PURE__*/React.cloneElement(children, {
ref: item => {
if (ref) {
if (is('function', ref)) ref(item);else ref.current = item;
}
refs.root.current = item;
}
}));
};
Keyframes.displayName = 'amaui-Keyframes';
export default Keyframes;