@atlaskit/analytics-next 11.1.4 → 11.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/AnalyticsReactContext/package.json +15 -0
  2. package/CHANGELOG.md +21 -0
  3. package/afm-cc/tsconfig.json +0 -2
  4. package/afm-products/tsconfig.json +0 -2
  5. package/cleanProps/package.json +15 -0
  6. package/dist/cjs/components/AnalyticsReactContext.js +13 -0
  7. package/dist/cjs/events/UIAnalyticsEvent.js +11 -1
  8. package/dist/cjs/index.js +2 -2
  9. package/dist/cjs/utils/isModernContextEnabledEnv.js +2 -1
  10. package/dist/es2019/components/AnalyticsReactContext.js +1 -0
  11. package/dist/es2019/events/UIAnalyticsEvent.js +13 -1
  12. package/dist/es2019/index.js +1 -1
  13. package/dist/es2019/utils/isModernContextEnabledEnv.js +2 -1
  14. package/dist/esm/components/AnalyticsReactContext.js +1 -0
  15. package/dist/esm/events/UIAnalyticsEvent.js +11 -1
  16. package/dist/esm/index.js +1 -1
  17. package/dist/esm/utils/isModernContextEnabledEnv.js +2 -1
  18. package/dist/types/components/AnalyticsContext/index.d.ts +1 -1
  19. package/dist/types/components/AnalyticsContext/types.d.ts +1 -1
  20. package/dist/types/components/AnalyticsListener/LegacyAnalyticsListener.d.ts +1 -1
  21. package/dist/types/components/AnalyticsListener/index.d.ts +1 -1
  22. package/dist/types/components/AnalyticsListener/types.d.ts +1 -1
  23. package/dist/types/components/AnalyticsReactContext.d.ts +2 -0
  24. package/dist/types/hocs/withAnalyticsEvents.d.ts +1 -1
  25. package/dist/types/hooks/useAnalyticsEvents.d.ts +1 -1
  26. package/dist/types/hooks/usePatchedProps.d.ts +1 -1
  27. package/dist/types/index.d.ts +2 -2
  28. package/dist/types/types.d.ts +1 -1
  29. package/dist/types/utils/createAndFireEvent.d.ts +2 -2
  30. package/dist/types/utils/isModernContextEnabledEnv.d.ts +2 -2
  31. package/dist/types-ts4.5/components/AnalyticsContext/index.d.ts +1 -1
  32. package/dist/types-ts4.5/components/AnalyticsContext/types.d.ts +1 -1
  33. package/dist/types-ts4.5/components/AnalyticsListener/LegacyAnalyticsListener.d.ts +1 -1
  34. package/dist/types-ts4.5/components/AnalyticsListener/index.d.ts +1 -1
  35. package/dist/types-ts4.5/components/AnalyticsListener/types.d.ts +1 -1
  36. package/dist/types-ts4.5/components/AnalyticsReactContext.d.ts +2 -0
  37. package/dist/types-ts4.5/hocs/withAnalyticsEvents.d.ts +1 -1
  38. package/dist/types-ts4.5/hooks/useAnalyticsEvents.d.ts +1 -1
  39. package/dist/types-ts4.5/hooks/usePatchedProps.d.ts +1 -1
  40. package/dist/types-ts4.5/index.d.ts +2 -2
  41. package/dist/types-ts4.5/types.d.ts +1 -1
  42. package/dist/types-ts4.5/utils/createAndFireEvent.d.ts +2 -2
  43. package/dist/types-ts4.5/utils/isModernContextEnabledEnv.d.ts +2 -2
  44. package/docs/0-intro.tsx +68 -37
  45. package/docs/10-concepts.tsx +138 -112
  46. package/docs/20-usage-with-presentational-components.tsx +177 -198
  47. package/docs/30-usage-for-container-components.tsx +69 -53
  48. package/docs/40-listeners.tsx +17 -14
  49. package/docs/50-error-boundary.tsx +28 -22
  50. package/docs/60-events.tsx +27 -19
  51. package/docs/70-advanced-usage.tsx +182 -179
  52. package/docs/80-upgrade-guide.tsx +182 -100
  53. package/docs/DocBlocks.tsx +106 -0
  54. package/package.json +2 -2
  55. package/tsconfig.json +1 -2
  56. package/usePlatformLeafSyntheticEventHandler/package.json +15 -0
  57. package/afm-jira/tsconfig.json +0 -33
@@ -1,19 +1,9 @@
1
+ /* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading -- Legacy analytics-next docs intentionally use plain HTML prose instead of ADS docs primitives. */
1
2
  import React from 'react';
2
3
 
3
- import { code, md, Props } from '@atlaskit/docs';
4
+ import { CodeBlock, PropsBlock } from './DocBlocks';
4
5
 
5
- const _default_1: any = md`
6
- ${code`import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';`}
7
-
8
- Wrap part of your tree in \`AnalyticsErrorBoundary\` to provide error boundary track to any events created beneath it.
9
-
10
- When a component is created verifies all of the components above it in the tree and any error will be catched and tracked automatically.
11
-
12
- It's up to the developer pass this information when you're adding the component.
13
-
14
- Usage:
15
-
16
- ${code`
6
+ const usageCode = `
17
7
  import {
18
8
  AnalyticsListener,
19
9
  AnalyticsErrorBoundary
@@ -43,13 +33,29 @@ class ButtonWithAnalyticsErrorBoundary extends React.Component {
43
33
  )
44
34
  }
45
35
  }
46
- `}
47
-
48
- ${(
49
- <Props
50
- heading="AnalyticsErrorBoundary Props"
51
- props={require('!!extract-react-types-loader!../src/components/AnalyticsErrorBoundary')}
52
- />
53
- )}
54
36
  `;
55
- export default _default_1;
37
+
38
+ export default function ErrorBoundaryDocs(): React.JSX.Element {
39
+ return (
40
+ <div>
41
+ <CodeBlock code={`import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';`} />
42
+ <p>
43
+ Wrap part of your tree in <code>AnalyticsErrorBoundary</code> to provide error boundary
44
+ track to any events created beneath it.
45
+ </p>
46
+ <p>
47
+ When a component is created verifies all of the components above it in the tree and any
48
+ error will be catched and tracked automatically.
49
+ </p>
50
+ <p>
51
+ It&apos;s up to the developer pass this information when you&apos;re adding the component.
52
+ </p>
53
+ <h4>Usage</h4>
54
+ <CodeBlock code={usageCode} />
55
+ <PropsBlock
56
+ heading="AnalyticsErrorBoundary Props"
57
+ props={require('!!extract-react-types-loader!../src/components/AnalyticsErrorBoundary')}
58
+ />
59
+ </div>
60
+ );
61
+ }
@@ -1,12 +1,9 @@
1
- import { code, md } from '@atlaskit/docs';
1
+ /* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading -- Legacy analytics-next docs intentionally use plain HTML prose instead of ADS docs primitives. */
2
+ import React from 'react';
2
3
 
3
- const _default_1: any = md`
4
- <a name="UIAnalyticsEvent"></a>
5
- ### UIAnalyticsEvent
4
+ import { CodeBlock } from './DocBlocks';
6
5
 
7
- The class can be used to represent an analytics event triggered by a user interaction. It has the following interface:
8
-
9
- ${code`
6
+ const uiAnalyticsEventCode = `
10
7
  /** An array of objects containing data provided by any AnalyticsContext
11
8
  * components in the tree above where this event was created. */
12
9
  context: Array<{}>;
@@ -40,16 +37,27 @@ update(
40
37
  [string]: any,
41
38
  }),
42
39
  ) => UIAnalyticsEvent;
43
- `}
44
-
45
- <a name="AnalyticsEvent"></a>
46
- ### AnalyticsEvent
47
-
48
- ${code`import { AnalyticsEvent } from '@atlaskit/analytics-next';`}
49
-
50
- A more generic type of event which only contains a payload and an update method.
51
- If you want to create an event outside of the UI you can create an instance of this class directly.
52
-
53
- Please see [UIAnalyticsEvent](#UIAnalyticsEvent) for more information.
54
40
  `;
55
- export default _default_1;
41
+
42
+ export default function EventsDocs(): React.JSX.Element {
43
+ return (
44
+ <div>
45
+ <h3 id="UIAnalyticsEvent">UIAnalyticsEvent</h3>
46
+ <p>
47
+ The class can be used to represent an analytics event triggered by a user interaction. It
48
+ has the following interface:
49
+ </p>
50
+ <CodeBlock code={uiAnalyticsEventCode} />
51
+ <h3 id="AnalyticsEvent">AnalyticsEvent</h3>
52
+ <CodeBlock code={`import { AnalyticsEvent } from '@atlaskit/analytics-next';`} />
53
+ <p>
54
+ A more generic type of event which only contains a payload and an update method. If you want
55
+ to create an event outside of the UI you can create an instance of this class directly.
56
+ </p>
57
+ <p>
58
+ {/* eslint-disable-next-line @atlaskit/design-system/no-html-anchor -- This legacy docs page keeps plain hash links for local section navigation. */}
59
+ Please see <a href="#UIAnalyticsEvent">UIAnalyticsEvent</a> for more information.
60
+ </p>
61
+ </div>
62
+ );
63
+ }
@@ -1,38 +1,14 @@
1
+ /* eslint-disable @atlaskit/design-system/use-primitives-text, @atlaskit/design-system/use-heading, @atlaskit/design-system/no-html-anchor -- Legacy analytics-next docs intentionally use plain HTML prose and hash links instead of ADS docs primitives. */
1
2
  import React from 'react';
2
3
 
3
- import { code, Example, md } from '@atlaskit/docs';
4
+ import { CodeBlock, ExampleBlock } from './DocBlocks';
4
5
 
5
- const _default_1: any = md`
6
- ### Contents
7
-
8
- * [Adding more information to an event](#adding-more-information-to-an-event)
9
- * [Using a channel](#using-a-channel)
10
- * [Passing an event to your consumers](#passing-an-event-to-your-consumers)
11
- * [Cloning an event](#cloning-an-event)
12
- * [Tracking events outside the UI](#tracking-events-outside-the-ui)
13
-
14
- <a name="adding-more-information-to-an-event"></a>
15
- ## Adding more information to an event
16
-
17
- This package provides two methods for adding extra information to analytics events.
18
- The first method is by adding data to the analytics events payload. The second method
19
- is to provide contextual information to any event.
20
-
21
- <a name="adding-data-to-an-events-payload"></a>
22
- ### Adding data to an event's payload
23
-
24
- Before firing an analytics event, you can add data the payload by using the \`update\` method.
25
- Here's an example of how that looks:
26
-
27
- ##### SaveButton.js
28
-
29
- ${code`
6
+ const saveButtonCode = `
30
7
  import Button from '@atlaskit/button';
31
8
 
32
9
  const SaveButton = ({ onClick }) => (
33
10
  <Button
34
11
  onClick={(e, analytic) => {
35
- // update will merge the value into the existing payload
36
12
  analytic
37
13
  .update({ timestamp: Date.now() })
38
14
  .fire();
@@ -44,52 +20,20 @@ const SaveButton = ({ onClick }) => (
44
20
  Save
45
21
  </Button>
46
22
  );
47
- `}
48
-
49
- In addition to accepting an object, the \`update\` method accepts a function which is called
50
- with the event's current payload and is expected to return a new payload.
51
-
52
- Below is a fleshed out example demonstrating how to add extra information to the event's payload.
53
-
54
- ${(
55
- <Example
56
- packageName="@atlaskit/analytics-next"
57
- Component={require('../examples/40-updating-an-event').default}
58
- title="Updating an event's payload"
59
- source={require('!!raw-loader!../examples/40-updating-an-event')}
60
- />
61
- )}
62
-
63
- <a name="using-a-channel"></a>
64
- ## Using a channel
65
-
66
- The feature is likey more useful for component authors.
67
-
68
- When calling \`fire\` on an analytics event, you can optionally specify a channel
69
- to fire the event on. Only listeners on that channel will recieve the event.
70
-
71
- ##### Button.js (handleClick method)
23
+ `;
72
24
 
73
- ${code`
25
+ const usingChannelCode = `
74
26
  handleClick = e => {
75
- // Create our analytics event
76
27
  const analyticsEvent = this.props.createAnalyticsEvent({ action: 'click' });
77
-
78
- // Fire our analytics event on the 'atlaskit' channel
79
28
  analyticsEvent.fire('atlaskit');
80
29
 
81
30
  if (this.props.onClick) {
82
31
  this.props.onClick(e);
83
32
  }
84
33
  };
85
- `}
86
-
87
- In the above example, we fire events on the \`'atlaskit'\` channel. To listen
88
- on this channel we would set up our App like:
89
-
90
- ##### App.js (render method)
34
+ `;
91
35
 
92
- ${code`
36
+ const appRenderCode = `
93
37
  render() {
94
38
  return (
95
39
  <AnalyticsListener channel="atlaskit" onEvent={this.handleEvent}>
@@ -97,147 +41,53 @@ render() {
97
41
  </AnalyticsListener>
98
42
  );
99
43
  }
100
- `}
101
-
102
- The \`AnalyticsListener\` component accepts \`channel\` and \`onEvent\` props. When an event is fired on this Listener's channel its onEvent function will be called.
103
-
104
- <a name="passing-an-event-to-your-consumers"></a>
105
- ## Passing an event to your consumers
106
-
107
- The features described in this section are likey to be more useful to component
108
- authors.
109
-
110
- If you are building components, you might not want to fire an event as
111
- soon as it's created - instead it is better to provide the event to the consumer
112
- of your component. The consumer then has a chance to add more information and fire
113
- the event when they're ready.
114
-
115
- This is exactly the approach we took to instrument our own Atlaskit components.
116
- This section will show you how we did it and how to use the same approach in
117
- your components.
118
-
119
- The most straight forward way is to pass the event as an extra argument to the
120
- corresponding callback prop. Here's our updated Button component:
121
-
122
- ##### Button.js (handleClick method)
44
+ `;
123
45
 
124
- ${code`
46
+ const passingEventCode = `
125
47
  handleClick = e => {
126
- // Create our analytics event
127
48
  const analyticsEvent = this.props.createAnalyticsEvent({ action: 'click' });
128
49
 
129
50
  if (this.props.onClick) {
130
- // Pass the event through the corresponding callback prop
131
51
  this.props.onClick(e, analyticsEvent);
132
52
  }
133
53
  };
134
- `}
135
-
136
- This is a pretty common pattern for component authors, so \`withAnalyticsEvents\`
137
- provides a shortcut:
138
-
139
- ##### Button.js
54
+ `;
140
55
 
141
- ${code`
56
+ const shortcutCode = `
142
57
  const ButtonWithAnalytics = withAnalyticsEvents({
143
- // simply provide a payload we'll automatically create an event for you
144
58
  onClick: { action: 'click' }
145
59
  })(Button);
146
- `}
147
-
148
- \`withAnalyticsEvents\` accepts an optional object mapping callback prop names to payloads.
149
- This event will be automatically added as a final argument to the callback prop.
150
- If the analytics event payload needs to include some information from the components
151
- props, \`withAnalyticsEvents\` also accepts a function.
152
-
153
- ##### Button.js
60
+ `;
154
61
 
155
- ${code`
62
+ const propsFunctionCode = `
156
63
  const ButtonWithAnalytics = withAnalyticsEvents({
157
- // this function should return an analytics event
158
64
  onClick: (createEvent, props) => {
159
65
  return createEvent({ action: 'click', appearance: props.appearance });
160
66
  },
161
67
  })(Button);
162
- `}
163
-
164
- ${(
165
- <Example
166
- packageName="@atlaskit/analytics-next"
167
- Component={require('../examples/30-passing-events-to-a-callback').default}
168
- title="Passing events through callbacks"
169
- source={require('!!raw-loader!../examples/30-passing-events-to-a-callback')}
170
- />
171
- )}
172
-
173
- <a name="cloning-an-event"></a>
174
- ## Cloning an event
175
-
176
- The features described in this section are likey to be more useful to component
177
- authors.
178
-
179
- Once an event has been fired it cannot be updated or fired again. This poses a
180
- problem for library component authors who want to record their own analytics
181
- events, while also exposing analytics events to their consumers.
182
-
183
- That's where \`.clone\` comes in.
184
-
185
- Let's imagine a Form component. If it accepted an \`onSubmit\` callback prop we could do something like this:
186
-
187
- ##### Form.js (onSubmit method):
68
+ `;
188
69
 
189
- ${code`
70
+ const cloningCode = `
190
71
  onSubmit = analyticsEvent => {
191
72
  const { value } = this.state;
192
-
193
- // Clone the analytics event
194
73
  const publicEvent = analyticsEvent.clone();
195
-
196
- // Add whatever data we want to know about to our event and fire it
197
74
  analyticsEvent.update({ value }).fire('atlaskit');
198
75
 
199
76
  if (this.props.onSubmit) {
200
- // Pass the cloned event to the callback prop for consumers to use
201
77
  this.props.onSubmit(value, publicEvent);
202
78
  }
203
79
  };
204
- `}
205
-
206
- This is a common enough usecase that we have built a helper to make this
207
- easier to do.
208
-
209
- ##### Form.js (onSubmit method):
80
+ `;
210
81
 
211
- ${code`
82
+ const cloningShortcutCode = `
212
83
  import { withAnalyticsEvents, createAndFireEvent } from '@atlaskit/analytics-next';
213
84
 
214
85
  const FormWithAnalytics = withAnalyticsEvents({
215
86
  onSubmit: createAndFireEvent('atlaskit')({ action: 'submit' })
216
87
  })(Form);
217
- `}
218
-
219
- This will create the event with the payload, fire it on the specified channel
220
- and return a clone of the event.
221
-
222
- ${(
223
- <Example
224
- packageName="@atlaskit/analytics-next"
225
- Component={require('../examples/50-cloning-an-event').default}
226
- title="Cloning an event"
227
- source={require('!!raw-loader!../examples/50-cloning-an-event')}
228
- />
229
- )}
230
-
231
- <a name="tracking-events-outside-the-ui"></a>
232
- ## Tracking events outside the UI
233
-
234
- This library provides tools for tracking interactions with UI components, and makes it really easy to capture the UI context and state when these events occur. But what if the event you're tracking doesn't care about the UI? Can you still use this library to track it?
235
-
236
- Well, sure - but you might not need to. An event has to be created by a UI component to get \`context\` and a \`.fire\` method. Without these properties an analytics event is basically a payload! It might be simpler to just create an object and pass it directly to the function that handles your events.
237
-
238
- In case it is useful for you to have a consistent interface for your events, even if they're not coming from the UI, we do export the base \`AnalyticsEvent\` class. Here's an example of how you might use it:
88
+ `;
239
89
 
240
- ${code`
90
+ const outsideUiCode = `
241
91
  import { AnalyticsEvent } from '@atlaskit/analytics-next';
242
92
  import sendAnalyticsEventToBackend from './sendAnalyticsEventToBackend';
243
93
 
@@ -250,22 +100,175 @@ const fetchBacon = async () => {
250
100
 
251
101
  const responseTime = performance.now() - startTime;
252
102
 
253
- /** This event records server response time. This function doesn't live inside
254
- * a component and we don't care what state the UI is in when it runs. It
255
- * would be annoying if we had to create the event inside a component, then
256
- * pass it to this function. We can create a generic AnalyticsEvent and handle
257
- * it all inside this function instead. */
258
103
  const analyticsEvent = new AnalyticsEvent({
259
104
  payload: { action: 'server-request', data, responseTime },
260
105
  });
261
106
 
262
- /** Because we're not in the UI this event doesn't have any
263
- * AnalyticsListeners, which means it doesn't have a .fire method. We need to
264
- * explicitly pass it to the function that will handle it. */
265
107
  sendAnalyticsEventToBackend(analyticsEvent);
266
108
 
267
109
  return data;
268
110
  };
269
- `}
270
111
  `;
271
- export default _default_1;
112
+
113
+ export default function AdvancedUsage(): React.JSX.Element {
114
+ return (
115
+ <div>
116
+ <h3>Contents</h3>
117
+ <ul>
118
+ <li>
119
+ <a href="#adding-more-information-to-an-event">Adding more information to an event</a>
120
+ </li>
121
+ <li>
122
+ <a href="#using-a-channel">Using a channel</a>
123
+ </li>
124
+ <li>
125
+ <a href="#passing-an-event-to-your-consumers">Passing an event to your consumers</a>
126
+ </li>
127
+ <li>
128
+ <a href="#cloning-an-event">Cloning an event</a>
129
+ </li>
130
+ <li>
131
+ <a href="#tracking-events-outside-the-ui">Tracking events outside the UI</a>
132
+ </li>
133
+ </ul>
134
+
135
+ <h2 id="adding-more-information-to-an-event">Adding more information to an event</h2>
136
+ <p>
137
+ This package provides two methods for adding extra information to analytics events. The
138
+ first method is by adding data to the analytics events payload. The second method is to
139
+ provide contextual information to any event.
140
+ </p>
141
+ <h3>Adding data to an event&apos;s payload</h3>
142
+ <p>
143
+ Before firing an analytics event, you can add data the payload by using the{' '}
144
+ <code>update</code> method. Here&apos;s an example of how that looks:
145
+ </p>
146
+ <h5>SaveButton.js</h5>
147
+ <CodeBlock code={saveButtonCode} />
148
+ <p>
149
+ In addition to accepting an object, the <code>update</code> method accepts a function which
150
+ is called with the event&apos;s current payload and is expected to return a new payload.
151
+ </p>
152
+ <p>
153
+ Below is a fleshed out example demonstrating how to add extra information to the
154
+ event&apos;s payload.
155
+ </p>
156
+ <ExampleBlock
157
+ Component={require('../examples/40-updating-an-event').default}
158
+ title="Updating an event's payload"
159
+ source={require('!!raw-loader!../examples/40-updating-an-event')}
160
+ />
161
+
162
+ <h2 id="using-a-channel">Using a channel</h2>
163
+ <p>The feature is likey more useful for component authors.</p>
164
+ <p>
165
+ When calling <code>fire</code> on an analytics event, you can optionally specify a channel
166
+ to fire the event on. Only listeners on that channel will recieve the event.
167
+ </p>
168
+ <h5>Button.js (handleClick method)</h5>
169
+ <CodeBlock code={usingChannelCode} />
170
+ <p>
171
+ In the above example, we fire events on the <code>&apos;atlaskit&apos;</code> channel. To
172
+ listen on this channel we would set up our App like:
173
+ </p>
174
+ <h5>App.js (render method)</h5>
175
+ <CodeBlock code={appRenderCode} />
176
+ <p>
177
+ The <code>AnalyticsListener</code> component accepts <code>channel</code> and{' '}
178
+ <code>onEvent</code> props. When an event is fired on this Listener&apos;s channel its
179
+ onEvent function will be called.
180
+ </p>
181
+
182
+ <h2 id="passing-an-event-to-your-consumers">Passing an event to your consumers</h2>
183
+ <p>
184
+ The features described in this section are likey to be more useful to component authors.
185
+ </p>
186
+ <p>
187
+ If you are building components, you might not want to fire an event as soon as it&apos;s
188
+ created - instead it is better to provide the event to the consumer of your component. The
189
+ consumer then has a chance to add more information and fire the event when they&apos;re
190
+ ready.
191
+ </p>
192
+ <p>
193
+ This is exactly the approach we took to instrument our own Atlaskit components. This section
194
+ will show you how we did it and how to use the same approach in your components.
195
+ </p>
196
+ <p>
197
+ The most straight forward way is to pass the event as an extra argument to the corresponding
198
+ callback prop. Here&apos;s our updated Button component:
199
+ </p>
200
+ <h5>Button.js (handleClick method)</h5>
201
+ <CodeBlock code={passingEventCode} />
202
+ <p>
203
+ This is a pretty common pattern for component authors, so <code>withAnalyticsEvents</code>{' '}
204
+ provides a shortcut:
205
+ </p>
206
+ <h5>Button.js</h5>
207
+ <CodeBlock code={shortcutCode} />
208
+ <p>
209
+ <code>withAnalyticsEvents</code> accepts an optional object mapping callback prop names to
210
+ payloads. This event will be automatically added as a final argument to the callback prop.
211
+ If the analytics event payload needs to include some information from the components props,{' '}
212
+ <code>withAnalyticsEvents</code> also accepts a function.
213
+ </p>
214
+ <h5>Button.js</h5>
215
+ <CodeBlock code={propsFunctionCode} />
216
+ <ExampleBlock
217
+ Component={require('../examples/30-passing-events-to-a-callback').default}
218
+ title="Passing events through callbacks"
219
+ source={require('!!raw-loader!../examples/30-passing-events-to-a-callback')}
220
+ />
221
+
222
+ <h2 id="cloning-an-event">Cloning an event</h2>
223
+ <p>
224
+ The features described in this section are likey to be more useful to component authors.
225
+ </p>
226
+ <p>
227
+ Once an event has been fired it cannot be updated or fired again. This poses a problem for
228
+ library component authors who want to record their own analytics events, while also exposing
229
+ analytics events to their consumers.
230
+ </p>
231
+ <p>
232
+ That&apos;s where <code>.clone</code> comes in.
233
+ </p>
234
+ <p>
235
+ Let&apos;s imagine a Form component. If it accepted an <code>onSubmit</code> callback prop
236
+ we could do something like this:
237
+ </p>
238
+ <h5>Form.js (onSubmit method):</h5>
239
+ <CodeBlock code={cloningCode} />
240
+ <p>This is a common enough usecase that we have built a helper to make this easier to do.</p>
241
+ <h5>Form.js (onSubmit method):</h5>
242
+ <CodeBlock code={cloningShortcutCode} />
243
+ <p>
244
+ This will create the event with the payload, fire it on the specified channel and return a
245
+ clone of the event.
246
+ </p>
247
+ <ExampleBlock
248
+ Component={require('../examples/50-cloning-an-event').default}
249
+ title="Cloning an event"
250
+ source={require('!!raw-loader!../examples/50-cloning-an-event')}
251
+ />
252
+
253
+ <h2 id="tracking-events-outside-the-ui">Tracking events outside the UI</h2>
254
+ <p>
255
+ This library provides tools for tracking interactions with UI components, and makes it
256
+ really easy to capture the UI context and state when these events occur. But what if the
257
+ event you&apos;re tracking doesn&apos;t care about the UI? Can you still use this library to
258
+ track it?
259
+ </p>
260
+ <p>
261
+ Well, sure - but you might not need to. An event has to be created by a UI component to get{' '}
262
+ <code>context</code> and a <code>.fire</code> method. Without these properties an analytics
263
+ event is basically a payload! It might be simpler to just create an object and pass it
264
+ directly to the function that handles your events.
265
+ </p>
266
+ <p>
267
+ In case it is useful for you to have a consistent interface for your events, even if
268
+ they&apos;re not coming from the UI, we do export the base <code>AnalyticsEvent</code>{' '}
269
+ class. Here&apos;s an example of how you might use it:
270
+ </p>
271
+ <CodeBlock code={outsideUiCode} />
272
+ </div>
273
+ );
274
+ }