UNPKG

@amaui/ui-react

Version:
183 lines (171 loc) 6.49 kB
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;