<commit_before>// @flow

import type { Children } from 'react';

import React from 'react';
import * as yubaba from 'yubaba-core';

const nodeStore = {};

function readFromStore (pairName) {
  return nodeStore[pairName];
}

function addToStore (pairName, nodeOrFunc) {
  nodeStore[pairName] = nodeOrFunc;
}

// function removeFromStore (pairName) {
//   delete nodeStore[pairName];
// }

export type TransitionOptions = {
  transition: 'move' | 'expand',
};

export default class Transition extends React.Component {
  _node: HTMLElement;

  props: {
    pair: string,
    children?: Children,
    transitions: Array<TransitionOptions>,
  };

  state = {
    visible: false,
  };

  componentDidMount () {
    process.env.NODE_ENV !== 'production' && console.log('Mounted.');

    this.initialise();
  }

  componentWillUnmount () {
    process.env.NODE_ENV !== 'production' && console.log('Unmounting.');

    this.initialise();
  }

  initialise () {
    const nodeOrFunc = readFromStore(this.props.pair);
    if (!nodeOrFunc) {
      process.env.NODE_ENV !== 'production' && console.log('Adding node to store.');
      this.setState({
        visible: true,
      });
      addToStore(this.props.pair, this._node);
      return;
    }

    if (nodeOrFunc === this._node) {
      process.env.NODE_ENV !== 'production' && console.log('Intialising transition.');

      const node = nodeOrFunc;

      const transitions = this.props.transitions.map(({ transition: name, ...options }) => {
        // Hack to get reverse working. Uh. This should probably be rethought.
        const initTransition = (element) => yubaba[name](element, options);

        return options.reverse
          ? { start: (endElement) => initTransition(endElement).start }
          : initTransition(node.firstElementChild);
      });

      const startTransition = (endNode) => Promise.all(transitions.map((transition) => {
        return transition.start(endNode);
      }))
      .then((results) => {
        // Start all reverse transitions
        return Promise.all(results
          .filter((result) => typeof result === 'function')
          .map((start) => start())
          .concat(results));
      })
      .then((results) => {
        process.env.NODE_ENV !== 'production' && console.log('Finished transition.');
        // Fadeout and cleanup all expanders
        return Promise.all(results
          .filter(({ transition }) => transition === 'expand')
          .map(({ target }) => {
            return yubaba.fadeout(target, {
              duration: 0.75,
              autoCleanup: true,
              autoStart: true,
            }).promise;
          })
          .concat(results));
      })
      .then((results) => {
        // Cleanup everything else left
        console.log(results);
        results.forEach((result) => {
          result.cleanup && result.cleanup();
        });
      });

      addToStore(this.props.pair, startTransition);<commit_msg>fix transition end notification timing<commit_after>// @flow

import type { Children } from 'react';

import React from 'react';
import * as yubaba from 'yubaba-core';

const nodeStore = {};

function readFromStore (pairName) {
  return nodeStore[pairName];
}

function addToStore (pairName, nodeOrFunc) {
  nodeStore[pairName] = nodeOrFunc;
}

// function removeFromStore (pairName) {
//   delete nodeStore[pairName];
// }

export type TransitionOptions = {
  transition: 'move' | 'expand',
};

export default class Transition extends React.Component {
  _node: HTMLElement;

  props: {
    pair: string,
    children?: Children,
    transitions: Array<TransitionOptions>,
  };

  state = {
    visible: false,
  };

  componentDidMount () {
    process.env.NODE_ENV !== 'production' && console.log('Mounted.');

    this.initialise();
  }

  componentWillUnmount () {
    process.env.NODE_ENV !== 'production' && console.log('Unmounting.');

    this.initialise();
  }

  initialise () {
    const nodeOrFunc = readFromStore(this.props.pair);
    if (!nodeOrFunc) {
      process.env.NODE_ENV !== 'production' && console.log('Adding node to store.');
      this.setState({
        visible: true,
      });
      addToStore(this.props.pair, this._node);
      return;
    }

    if (nodeOrFunc === this._node) {
      process.env.NODE_ENV !== 'production' && console.log('Intialising transition.');

      const node = nodeOrFunc;

      const transitions = this.props.transitions.map(({ transition: name, ...options }) => {
        // Hack to get reverse working. Uh. This should probably be rethought.
        const initTransition = (element) => yubaba[name](element, options);

        return options.reverse
          ? { start: (endElement) => initTransition(endElement).start }
          : initTransition(node.firstElementChild);
      });

      const startTransition = (endNode) => Promise.all(transitions.map((transition) => {
        return transition.start(endNode);
      }))
      .then((results) => {
        // Start all reverse transitions
        return Promise.all(results
          .filter((result) => typeof result === 'function')
          .map((start) => start())
          .concat(results));
      })
      .then((results) => {
        process.env.NODE_ENV !== 'production' && console.log('Finished transition.');
        // Fadeout and cleanup all expanders. This is deliberately a broken promise chain.

        Promise.all(results
          .filter(({ transition }) => transition === 'expand')
          .map(({ target }) => {
            return yubaba.fadeout(target, {
              duration: 0.75,
              autoCleanup: true,
              autoStart: true,
            }).promise;
          }))
          .then((fadeoutResults) => {
            // Cleanup anything else left
            fadeoutResults.concat(results).forEach((result) => {
              result.cleanup && result.cleanup();
            });
          });
      });

      addToStore(this.props.pair, startTransition);
{'fraction_non_alphanumeric': 0.14395714763977235, 'fraction_numerical': 0.001004352192835621, 'mean_word_length': 2.5126396237507347, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3606720', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1663, 'n_words': 373}