import React from 'react';

import { code, md } from '@atlaskit/docs';
import Link from '@atlaskit/link';

const _default_1: any = md`
This section will guide how to add analytics tracking to presentational and other
components that don't fit into the "Container" category.

For a conceptual overview of \`@atlaskit/analytics-next\`, please consult the
[concepts page](./concepts).

There are several ways to add analytics to a component, via React hooks, or
via higher order components (HOCs) - consult the Recommended Usage table for
our suggested approach.

## API

### Hooks API

* [\`useAnalyticsEvents\`](#use-analytics-events)
* [\`useCallbackWithAnalytics\`](#use-callback-with-analytics)
* [\`usePlatformLeafEventHandler\` and \`usePlatformLeafSyntheticEventHandler\`](#use-platform-leaf-event-handlers)

### HOCs API

* [\`withAnalyticsEvents\`](#with-analytics-events)

### Recommended Usage

${(
	<table>
		<tr>
			<th>Component Type</th>
			<th>Recommendation</th>
		</tr>
		<tr>
			<td>Class components</td>
			<td>
				You have only the <Link href="#with-analytics-events">HOC option</Link>
			</td>
		</tr>
		<tr>
			<td>Atlaskit function components</td>
			<td>
				Use{' '}
				<Link href="#use-platform-leaf-event-handler">
					{/* eslint-disable-next-line @atlaskit/design-system/no-html-code */}
					<code>usePlatformLeafEventHandler</code>
				</Link>
				.
			</td>
		</tr>
		<tr>
			<td>Other function components</td>
			<td>
				Use{' '}
				<Link href="#use-callback-with-analytics">
					{/* eslint-disable-next-line @atlaskit/design-system/no-html-code */}
					<code>useCallbackWithAnalytics</code>
				</Link>{' '}
				if you want something basic.
				<br />
				Use{' '}
				<Link href="#use-analytics-events">
					{/* eslint-disable-next-line @atlaskit/design-system/no-html-code */}
					<code>useAnalyticsEvents</code>
				</Link>{' '}
				if you want more control.
			</td>
		</tr>
	</table>
)}

### Examples

<a name="use-analytics-events"></a>
#### The \`useAnalyticsEvents\` hook

This custom React hook provides a method \`createAnalyticsEvent\` for creating \`UIAnalyticsEvent\`s.

${code`
import React, { useCallback } from 'react';
import { useAnalyticsEvents } from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {} }) => {
  const { createAnalyticsEvent } = useAnalyticsEvents();

  const handler = useCallback((clickEvent) => {
    const analyticsEvent = createAnalyticsEvent({
      action: 'clicked',
      componentName: 'my-button',
      packageName: '@atlaskit/my-button',
      packageVersion: '1.0.0'
    });

    // do what you like with the event, fire / modify / clone
    // this here is the typical usage pattern for atlaskit components

    const clonedEvent = analyticsEvent.clone();

    analyticsEvent.fire("atlaskit");

    // firing is prevented from happening more than once
    // so that's why we pass a clone to be accessed by the parent component
    // which might also want to fire their own event on this ui interaction
    onClick(clickEvent, clonedEvent);
  }, [ createAnalyticsEvent, onClick ]);

  return (
    <button onClick={handler}>Track me</button>
  );
}

export MyButton;
`}

<a name="use-callback-with-analytics"></a>
#### The \`useCallbackWithAnalytics\` hook

This custom React hook takes a callback function and an event payload, and channel, and
returns a callback to fire the event and call the provided function.

The hooks stores the input and memoizes the return value to optimize performance.

${code`
import React, { useCallback } from 'react';
import { useCallbackWithAnalytics } from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {} }) => {
  const handler = useCallbackWithAnalytics(onClick, {
    action: 'clicked',
    componentName: 'my-button',
    packageName: '@atlaskit/my-button',
    packageVersion: '1.0.0'
  }, 'atlaskit');

    return (
    <button onClick={handler}>Track me</button>
  );
}

export MyButton;
`}

<a name="with-analytics-events"></a>
#### The \`withAnalyticsEvents\` HOC

A HOC which provides the wrapped component with a method for creating \`UIAnalyticsEvent\`s,
via \`props.createAnalyticsEvent\`.

The HOC supports a few ways to use it for convinvience.

The first is to use the \`createAnalyticsEvent\` prop the HOC passes to the component manually:

${code`
import { withAnalyticsEvents } from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {}, createAnalyticsEvent }) => {
  const handler = (clickEvent) => {
    const analyticsEvent = createAnalyticsEvent({
      action: 'clicked',
      componentName: 'my-button',
      packageName: '@atlaskit/my-button',
      packageVersion: '1.0.0'
    });

    // do what you like with the event, fire / modify / clone
    // this here is the typical usage pattern for atlaskit components

    const clonedEvent = analyticsEvent.clone();

    analyticsEvent.fire("atlaskit");

    // firing is prevented from happening more than once
    // so that's why we pass a clone to be accessed by the parent component
    // which might also want to fire their own event on this ui interaction
    onClick(clickEvent, clonedEvent);
  };

  return (
    <button onClick={handler}>Track me</button>
  );
}

const AnalyticsWrappedButton = withAnalyticsEvents()(MyButton);

export AnalyticsWrappedButton;
`}

&nbsp;

Altenatively, the HOC accepts an optional map as its first argument, which provides a shortcut
for passing a new analytics event as an additional parameter to the corresponding callback prop.

${code`
import { withAnalyticsEvents } from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {} }) => {
  const handler = (clickEvent, analyticsEvent) => {
    // do what you like with the event, fire / modify / clone
    // this here is the typical usage pattern for atlaskit components

    const clonedEvent = analyticsEvent.clone();

    analyticsEvent.fire("atlaskit");

    // firing is prevented from happening more than once
    // so that's why we pass a clone to be accessed by the parent component
    // which might also want to fire their own event on this ui interaction
    onClick(clickEvent, clonedEvent);
  };

  return (
    <button onClick={handler}>Track me</button>
  );
}

const AnalyticsWrappedButton = withAnalyticsEvents({
  onClick: (createAnalyticsEvent) => createAnalyticsEvent({
    action: 'clicked',
    componentName: 'my-button',
    packageName: '@atlaskit/my-button',
    packageVersion: '1.0.0'
  })
})(MyButton);

export AnalyticsWrappedButton;
`}

&nbsp;

Since creating and returning an event is such a common pattern an even more concise shorthand is supported:

${code`
import { withAnalyticsEvents } from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {} }) => {
  const handler = (clickEvent, analyticsEvent) => {
    // do what you like with the event, fire / modify / clone
    // this here is the typical usage pattern for atlaskit components

    const clonedEvent = analyticsEvent.clone();

    analyticsEvent.fire("atlaskit");

    // firing is prevented from happening more than once
    // so that's why we pass a clone to be accessed by the parent component
    // which might also want to fire their own event on this ui interaction
    onClick(clickEvent, clonedEvent);
  };

  return (
    <button onClick={handler}>Track me</button>
  );
}

const AnalyticsWrappedButton = withAnalyticsEvents({
  onClick: {
    action: 'clicked',
    componentName: 'my-button',
    packageName: '@atlaskit/my-button',
    packageVersion: '1.0.0'
  }
})(MyButton);

export AnalyticsWrappedButton;
`}

<a name="use-platform-leaf-event-handlers"></a>
#### The \`usePlatformLeafEventHandler\` and \`usePlatformLeafSyntheticEventHandler\` hooks

These hooks were built with internal leaf node components purely in mind.

They dispatch an event on the \`atlaskit\` channel, then pass it to the
wrapped function as the last argument in case you want to something additional with the event.

\`usePlatformLeafEventHandler\` takes a function with two arguments (\`value\` and
 \`analyticsEvent\`), while \`usePlatformLeafSyntheticEventHandler\` takes a function
 with just one argument for the \`analyticsEvent\`

&nbsp;

**WARNING:** *These hooks make an assumption that the component being wrapped is a "leaf-node"
component, i.e., they have no children that require analytics themselves. This
is so it can include the component name, package name, and package version as context
in the analytics event. It assumes no children need this context and makes no attempt to
pass it to them. This gains us a decent performance optimization. Use the other hooks
if you are unsure you can use these safely.*

&nbsp;

${code`
import React, { useCallback } from 'react';
import {
  usePlatformLeafEventHandler,
  usePlatformLeafSyntheticEventHandler
} from '@atlaskit/analytics-next';

const MyButton = ({ onClick = () => {}, onActivate = () => {}}) => {

  /**
   *        Event 1: usePlatformLeafEventHandler
  */
  // this isn't necessary if you are happy with just firing on the 'atlaskit' channel
  const wrapped = (clickEvent, analyticsEvent) => {
    // do what you like with the event, fire / modify / clone
    // this here is the typical usage pattern for atlaskit components
    const clonedEvent = analyticsEvent.clone();
    analyticsEvent.fire("otherChannel");

    // firing is prevented from happening more than once
    // so that's why we pass a clone to be accessed by the parent component
    // which might also want to fire their own event on this ui interaction
    onClick(clickEvent, clonedEvent);
  };
  const handler = usePlatformLeafEventHandler({
    fn: wrapped, // use onClick instead if you want to just fire on 'atlaskit'
    action: 'clicked',
    componentName: 'my-button',
    actionSubject : 'clickButton', // will use componentName as fallback if actionSubject is not passed
    packageName: '@atlaskit/my-button',
    packageVersion: '1.0.0',
    analyticsData: {
      // any additional data can live here
      style: 'fancy'
    },
  });

  /**
   * Event 2: Synthetic event using usePlatformLeafSyntheticEventHandler
  */
 const wrappedSynthetic = (analyticsEvent) => {
    // A synthetic 'activate' event; same as above, but without a DOM event passed in
    const clonedEvent = analyticsEvent.clone();
    analyticsEvent.fire("otherChannel");
    onActivate(clonedEvent);
  };
  const syntheticHandler = usePlatformLeafSyntheticEventHandler({
    fn: wrappedSynthetic, // use onActivate instead if you want to just fire on 'atlaskit'
    action: 'activated',
    componentName: 'my-button',
    packageName: '@atlaskit/my-button',
    packageVersion: '1.0.0',
    analyticsData: {
      // any additional data can live here
      style: 'fancy'
    },
  });

  return (
    // In this example the synthetic event is triggered by onFocus
    <button onClick={handler} onFocus={syntheticHandler}>Track me</button>
  );
}

export MyButton;
`}

`;
export default _default_1;
