@availity/mui-event-tracker 0.1.0
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.
- package/CHANGELOG.md +18 -0
- package/README.md +61 -0
- package/dist/index.d.mts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +68 -0
- package/dist/index.mjs +39 -0
- package/introduction.stories.mdx +7 -0
- package/jest.config.js +12 -0
- package/package.json +57 -0
- package/project.json +41 -0
- package/src/index.ts +1 -0
- package/src/lib/EventTracker.stories.tsx +139 -0
- package/src/lib/EventTracker.test.tsx +69 -0
- package/src/lib/EventTracker.tsx +68 -0
- package/tsconfig.json +5 -0
- package/tsconfig.spec.json +10 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
|
+
|
|
5
|
+
## 0.1.0 (2024-07-18)
|
|
6
|
+
|
|
7
|
+
### Dependency Updates
|
|
8
|
+
|
|
9
|
+
* `mui-button` updated to version `0.1.0`
|
|
10
|
+
* `mui-form-utils` updated to version `0.1.0`
|
|
11
|
+
* `mui-layout` updated to version `0.1.0`
|
|
12
|
+
* `mui-menu` updated to version `0.1.0`
|
|
13
|
+
* `mui-textfield` updated to version `0.1.0`
|
|
14
|
+
* `mui-typography` updated to version `0.1.0`
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* **mui-event-tracker:** add event tracker component ([5be1273](https://github.com/Availity/element/commit/5be12734a09a53f786579192fd54da4936855086))
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @availity/mui-event-tracker
|
|
2
|
+
|
|
3
|
+
> Availity MUI EventTracker component to be used with @availity/element design system.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@availity/mui-event-tracker)
|
|
6
|
+
[](https://www.npmjs.com/package/@availity/mui-event-tracker)
|
|
7
|
+
[](https://github.com/Availity/element/blob/main/packages/mui-event-tracker/package.json)
|
|
8
|
+
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
This package extends the MUI EventTracker component: [MUI EventTracker Docs](https://mui.com/components/event-tracker/)
|
|
12
|
+
|
|
13
|
+
Live demo and documentation in our [Storybook](https://availity.github.io/element/?path=/docs/components-event-tracker-introduction--docs)
|
|
14
|
+
|
|
15
|
+
Availity standards for design and usage can be found in the [Availity Design Guide](https://zeroheight.com/2e36e50c7)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Import Through @availity/element (Recommended)
|
|
20
|
+
|
|
21
|
+
#### NPM
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @availity/element
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
#### Yarn
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yarn add @availity/element
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Direct Import
|
|
34
|
+
|
|
35
|
+
#### NPM
|
|
36
|
+
|
|
37
|
+
_This package has a few peer dependencies. Add `@mui/material` & `@emotion/react` to your project if not already installed._
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install @availity/mui-event-tracker
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Yarn
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
yarn add @availity/mui-event-tracker
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Usage
|
|
50
|
+
|
|
51
|
+
#### Import through @availity/element
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { EventTracker } from '@availity/element';
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### Direct import
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { EventTracker } from '@availity/mui-event-tracker';
|
|
61
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { AvAnalytics } from '@availity/analytics-core';
|
|
4
|
+
|
|
5
|
+
type EventTrackerProps = {
|
|
6
|
+
/** */
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
/** An array of plugins to pass to the underlying AvAnalytics class instance. */
|
|
9
|
+
plugins?: any[];
|
|
10
|
+
/** Enable or disable page tracking on initialization.
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
pageTracking?: boolean;
|
|
14
|
+
/** Enable or disable auto tracking on initialization.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
autoTrack?: boolean;
|
|
18
|
+
/** Enable or disable recursive functionality on initialization.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
recursive?: boolean;
|
|
22
|
+
/** Customize the prefix used for data event tracker attributes used for auto tracking.
|
|
23
|
+
* @default 'data-analytics'
|
|
24
|
+
*/
|
|
25
|
+
attributePrefix?: string;
|
|
26
|
+
/** Array of event modifiers enabling you to use other keywords for action instead of click for event type matching.
|
|
27
|
+
* @default ['action']
|
|
28
|
+
*/
|
|
29
|
+
eventModifiers?: any[];
|
|
30
|
+
};
|
|
31
|
+
declare const EventTrackerContext: React.Context<AvAnalytics | null>;
|
|
32
|
+
declare const useEventTracker: () => AvAnalytics;
|
|
33
|
+
declare const EventTrackerProvider: ({ children, plugins, pageTracking, autoTrack, recursive, attributePrefix, eventModifiers, }: EventTrackerProps) => react_jsx_runtime.JSX.Element;
|
|
34
|
+
|
|
35
|
+
export { EventTrackerContext, type EventTrackerProps, EventTrackerProvider, useEventTracker };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { AvAnalytics } from '@availity/analytics-core';
|
|
4
|
+
|
|
5
|
+
type EventTrackerProps = {
|
|
6
|
+
/** */
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
/** An array of plugins to pass to the underlying AvAnalytics class instance. */
|
|
9
|
+
plugins?: any[];
|
|
10
|
+
/** Enable or disable page tracking on initialization.
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
pageTracking?: boolean;
|
|
14
|
+
/** Enable or disable auto tracking on initialization.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
autoTrack?: boolean;
|
|
18
|
+
/** Enable or disable recursive functionality on initialization.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
recursive?: boolean;
|
|
22
|
+
/** Customize the prefix used for data event tracker attributes used for auto tracking.
|
|
23
|
+
* @default 'data-analytics'
|
|
24
|
+
*/
|
|
25
|
+
attributePrefix?: string;
|
|
26
|
+
/** Array of event modifiers enabling you to use other keywords for action instead of click for event type matching.
|
|
27
|
+
* @default ['action']
|
|
28
|
+
*/
|
|
29
|
+
eventModifiers?: any[];
|
|
30
|
+
};
|
|
31
|
+
declare const EventTrackerContext: React.Context<AvAnalytics | null>;
|
|
32
|
+
declare const useEventTracker: () => AvAnalytics;
|
|
33
|
+
declare const EventTrackerProvider: ({ children, plugins, pageTracking, autoTrack, recursive, attributePrefix, eventModifiers, }: EventTrackerProps) => react_jsx_runtime.JSX.Element;
|
|
34
|
+
|
|
35
|
+
export { EventTrackerContext, type EventTrackerProps, EventTrackerProvider, useEventTracker };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
EventTrackerContext: () => EventTrackerContext,
|
|
24
|
+
EventTrackerProvider: () => EventTrackerProvider,
|
|
25
|
+
useEventTracker: () => useEventTracker
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(src_exports);
|
|
28
|
+
|
|
29
|
+
// src/lib/EventTracker.tsx
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import_analytics_core = require("@availity/analytics-core");
|
|
32
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
33
|
+
var EventTrackerContext = (0, import_react.createContext)(null);
|
|
34
|
+
var useEventTracker = () => {
|
|
35
|
+
const ctx = (0, import_react.useContext)(EventTrackerContext);
|
|
36
|
+
if (!ctx) {
|
|
37
|
+
throw new Error("useEventTracker must be used within an EventTrackerProvider");
|
|
38
|
+
}
|
|
39
|
+
return ctx;
|
|
40
|
+
};
|
|
41
|
+
var EventTrackerProvider = ({
|
|
42
|
+
children,
|
|
43
|
+
plugins,
|
|
44
|
+
pageTracking = true,
|
|
45
|
+
autoTrack = true,
|
|
46
|
+
recursive = true,
|
|
47
|
+
attributePrefix = "data-analytics",
|
|
48
|
+
eventModifiers = ["action"]
|
|
49
|
+
}) => {
|
|
50
|
+
const analytics = (0, import_react.useMemo)(
|
|
51
|
+
() => new import_analytics_core.AvAnalytics(plugins, Promise, pageTracking, autoTrack, { recursive, attributePrefix, eventModifiers }),
|
|
52
|
+
[attributePrefix, autoTrack, eventModifiers, pageTracking, plugins, recursive]
|
|
53
|
+
);
|
|
54
|
+
(0, import_react.useEffect)(() => {
|
|
55
|
+
analytics.init();
|
|
56
|
+
if (pageTracking) {
|
|
57
|
+
analytics.trackPageView();
|
|
58
|
+
}
|
|
59
|
+
return () => analytics.stopAutoTrack();
|
|
60
|
+
}, [analytics, pageTracking]);
|
|
61
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTrackerContext.Provider, { value: analytics, children });
|
|
62
|
+
};
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
EventTrackerContext,
|
|
66
|
+
EventTrackerProvider,
|
|
67
|
+
useEventTracker
|
|
68
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/lib/EventTracker.tsx
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo } from "react";
|
|
3
|
+
import { AvAnalytics } from "@availity/analytics-core";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
var EventTrackerContext = createContext(null);
|
|
6
|
+
var useEventTracker = () => {
|
|
7
|
+
const ctx = useContext(EventTrackerContext);
|
|
8
|
+
if (!ctx) {
|
|
9
|
+
throw new Error("useEventTracker must be used within an EventTrackerProvider");
|
|
10
|
+
}
|
|
11
|
+
return ctx;
|
|
12
|
+
};
|
|
13
|
+
var EventTrackerProvider = ({
|
|
14
|
+
children,
|
|
15
|
+
plugins,
|
|
16
|
+
pageTracking = true,
|
|
17
|
+
autoTrack = true,
|
|
18
|
+
recursive = true,
|
|
19
|
+
attributePrefix = "data-analytics",
|
|
20
|
+
eventModifiers = ["action"]
|
|
21
|
+
}) => {
|
|
22
|
+
const analytics = useMemo(
|
|
23
|
+
() => new AvAnalytics(plugins, Promise, pageTracking, autoTrack, { recursive, attributePrefix, eventModifiers }),
|
|
24
|
+
[attributePrefix, autoTrack, eventModifiers, pageTracking, plugins, recursive]
|
|
25
|
+
);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
analytics.init();
|
|
28
|
+
if (pageTracking) {
|
|
29
|
+
analytics.trackPageView();
|
|
30
|
+
}
|
|
31
|
+
return () => analytics.stopAutoTrack();
|
|
32
|
+
}, [analytics, pageTracking]);
|
|
33
|
+
return /* @__PURE__ */ jsx(EventTrackerContext.Provider, { value: analytics, children });
|
|
34
|
+
};
|
|
35
|
+
export {
|
|
36
|
+
EventTrackerContext,
|
|
37
|
+
EventTrackerProvider,
|
|
38
|
+
useEventTracker
|
|
39
|
+
};
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const global = require('../../jest.config.global');
|
|
2
|
+
|
|
3
|
+
const esModules = ['uuid'];
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
...global,
|
|
7
|
+
displayName: 'event-tracker',
|
|
8
|
+
coverageDirectory: '../../coverage/event-tracker',
|
|
9
|
+
transformIgnorePatterns: [
|
|
10
|
+
`/node_modules/(?!${esModules})`
|
|
11
|
+
]
|
|
12
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@availity/mui-event-tracker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Availity MUI EventTracker Component - part of the @availity/element design system",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"typescript",
|
|
8
|
+
"availity",
|
|
9
|
+
"mui"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://availity.github.io/element/?path=/docs/components-event-tracker-introduction--docs",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Availity/element/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/Availity/element.git",
|
|
18
|
+
"directory": "packages/event-tracker"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "Availity Developers <AVOSS@availity.com>",
|
|
22
|
+
"browser": "./dist/index.js",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"module": "./dist/index.mjs",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
28
|
+
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"clean:nm": "rm -rf node_modules",
|
|
31
|
+
"publish": "yarn npm publish --tolerate-republish --access public",
|
|
32
|
+
"publish:canary": "yarn npm publish --access public --tag canary"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@availity/mui-button": "^0.6.7",
|
|
36
|
+
"@availity/mui-form-utils": "^0.11.3",
|
|
37
|
+
"@availity/mui-layout": "^0.1.6",
|
|
38
|
+
"@availity/mui-menu": "^0.2.7",
|
|
39
|
+
"@availity/mui-textfield": "^0.5.21",
|
|
40
|
+
"@availity/mui-typography": "^0.2.0",
|
|
41
|
+
"@mui/material": "^5.15.15",
|
|
42
|
+
"react": "18.2.0",
|
|
43
|
+
"react-dom": "18.2.0",
|
|
44
|
+
"tsup": "^8.0.2",
|
|
45
|
+
"typescript": "^5.4.5"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@mui/material": "^5.11.9",
|
|
49
|
+
"react": ">=16.3.0"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@availity/analytics-core": "^4.1.2"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mui-event-tracker",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/event-tracker/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"targets": {
|
|
8
|
+
"lint": {
|
|
9
|
+
"executor": "@nx/eslint:lint",
|
|
10
|
+
"options": {
|
|
11
|
+
"eslintConfig": ".eslintrc.json",
|
|
12
|
+
"silent": false,
|
|
13
|
+
"fix": false,
|
|
14
|
+
"cache": true,
|
|
15
|
+
"cacheLocation": "./node_modules/.cache/event-tracker/.eslintcache",
|
|
16
|
+
"maxWarnings": -1,
|
|
17
|
+
"quiet": false,
|
|
18
|
+
"noEslintrc": false,
|
|
19
|
+
"hasTypeAwareRules": true,
|
|
20
|
+
"cacheStrategy": "metadata"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"test": {
|
|
24
|
+
"executor": "@nx/jest:jest",
|
|
25
|
+
"outputs": ["{workspaceRoot}/coverage/event-tracker"],
|
|
26
|
+
"options": {
|
|
27
|
+
"jestConfig": "packages/event-tracker/jest.config.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"version": {
|
|
31
|
+
"executor": "@jscutlery/semver:version",
|
|
32
|
+
"options": {
|
|
33
|
+
"preset": "conventional",
|
|
34
|
+
"commitMessageFormat": "chore({projectName}): release version ${version} [skip ci]",
|
|
35
|
+
"tagPrefix": "@availity/{projectName}@",
|
|
36
|
+
"trackDeps": true,
|
|
37
|
+
"skipCommitTypes": ["docs"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/EventTracker';
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Each exported component in the package should have its own stories file
|
|
2
|
+
|
|
3
|
+
import { useState, useMemo } from 'react';
|
|
4
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
|
+
import { Typography } from '@availity/mui-typography';
|
|
6
|
+
import { Grid, Box } from '@availity/mui-layout';
|
|
7
|
+
import { FormControl, FormLabel, Select, Input, SelectChangeEvent } from '@availity/mui-form-utils';
|
|
8
|
+
import { TextField } from '@availity/mui-textfield';
|
|
9
|
+
import { MenuItem } from '@availity/mui-menu';
|
|
10
|
+
import { Button } from '@availity/mui-button';
|
|
11
|
+
import { EventTrackerProvider, useEventTracker, EventTrackerProps } from './EventTracker';
|
|
12
|
+
|
|
13
|
+
const meta: Meta<typeof EventTrackerProvider> = {
|
|
14
|
+
title: 'Components/EventTracker/EventTracker',
|
|
15
|
+
component: EventTrackerProvider,
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
|
|
21
|
+
type EventTrackerUiProps = {
|
|
22
|
+
count: number;
|
|
23
|
+
state: string;
|
|
24
|
+
selectValue: string;
|
|
25
|
+
setCount: React.Dispatch<React.SetStateAction<number>>;
|
|
26
|
+
setSelectValue: React.Dispatch<React.SetStateAction<string>>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const EventTrackerUI = ({ count, state, selectValue, setCount, setSelectValue }: EventTrackerUiProps) => {
|
|
30
|
+
const { trackEvent } = useEventTracker();
|
|
31
|
+
|
|
32
|
+
const handleChange = (event: SelectChangeEvent) => {
|
|
33
|
+
setSelectValue(event.target.value as string);
|
|
34
|
+
};
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<Typography>
|
|
38
|
+
This example is set up to track user events. <code>Select</code> allows logging for the blur event.
|
|
39
|
+
<br />
|
|
40
|
+
<code>Textarea</code> and <code>Input</code> log when focused. Both of these buttons log when clicked.
|
|
41
|
+
</Typography>
|
|
42
|
+
<Typography>Events logged: {count}</Typography>
|
|
43
|
+
<pre>LastEvent: {state}</pre>
|
|
44
|
+
<Grid container direction="column" maxWidth="500px" data-analytics-app-name="app">
|
|
45
|
+
<FormControl>
|
|
46
|
+
<FormLabel id="select-label">Select</FormLabel>
|
|
47
|
+
<Select
|
|
48
|
+
labelId="select-label"
|
|
49
|
+
value={selectValue}
|
|
50
|
+
onChange={handleChange}
|
|
51
|
+
onBlur={() => trackEvent({ action: 'blur', appName: 'app', elemId: 'select-label', event: 'blur' })}
|
|
52
|
+
>
|
|
53
|
+
<MenuItem value="10">10</MenuItem>
|
|
54
|
+
<MenuItem value="20">20</MenuItem>
|
|
55
|
+
<MenuItem value="30">30</MenuItem>
|
|
56
|
+
</Select>
|
|
57
|
+
</FormControl>
|
|
58
|
+
<Box marginTop={2}>
|
|
59
|
+
<FormControl>
|
|
60
|
+
<FormLabel id="textarea-label" htmlFor="textarea">
|
|
61
|
+
Text Area
|
|
62
|
+
</FormLabel>
|
|
63
|
+
<TextField id="textarea" multiline data-analytics-action="focus" />
|
|
64
|
+
</FormControl>
|
|
65
|
+
</Box>
|
|
66
|
+
<FormControl>
|
|
67
|
+
<FormLabel id="input-label" htmlFor="input">
|
|
68
|
+
Input
|
|
69
|
+
</FormLabel>
|
|
70
|
+
<Input id="input" data-analytics-action="focus" />
|
|
71
|
+
</FormControl>
|
|
72
|
+
<Grid container justifyContent="space-between" data-analytics-container="buttons" marginTop={2}>
|
|
73
|
+
<Button
|
|
74
|
+
id="reset-button"
|
|
75
|
+
data-analytics-action="click"
|
|
76
|
+
data-analytics-test-id="world"
|
|
77
|
+
onClick={() => setCount(0)}
|
|
78
|
+
color="secondary"
|
|
79
|
+
children="Reset Count"
|
|
80
|
+
/>
|
|
81
|
+
<Button
|
|
82
|
+
id="my-button"
|
|
83
|
+
data-analytics-action="click"
|
|
84
|
+
data-analytics-test-id="hello"
|
|
85
|
+
color="primary"
|
|
86
|
+
children="Click Me"
|
|
87
|
+
/>
|
|
88
|
+
</Grid>
|
|
89
|
+
</Grid>
|
|
90
|
+
</>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const _EventTracker: StoryObj<typeof EventTrackerProvider> = {
|
|
95
|
+
render: (args: EventTrackerProps) => {
|
|
96
|
+
const [state, setState] = useState('');
|
|
97
|
+
const [count, setCount] = useState(0);
|
|
98
|
+
const [selectValue, setSelectValue] = useState('');
|
|
99
|
+
|
|
100
|
+
const plugins = useMemo(
|
|
101
|
+
() => [
|
|
102
|
+
{
|
|
103
|
+
isEnabled: () => {
|
|
104
|
+
console.log('checking isEnabled');
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
107
|
+
init: () => {
|
|
108
|
+
console.log('init');
|
|
109
|
+
},
|
|
110
|
+
trackEvent(event: unknown) {
|
|
111
|
+
console.log('track event', event);
|
|
112
|
+
setState(JSON.stringify(event, null, 2));
|
|
113
|
+
setCount((current) => current + 1);
|
|
114
|
+
},
|
|
115
|
+
trackPageView(url: unknown) {
|
|
116
|
+
console.log('track page view', url);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
[]
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<EventTrackerProvider {...args} plugins={plugins}>
|
|
125
|
+
<EventTrackerUI
|
|
126
|
+
count={count}
|
|
127
|
+
setCount={setCount}
|
|
128
|
+
state={state}
|
|
129
|
+
selectValue={selectValue}
|
|
130
|
+
setSelectValue={setSelectValue}
|
|
131
|
+
/>
|
|
132
|
+
</EventTrackerProvider>
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
args: {
|
|
136
|
+
eventModifiers: ['action'],
|
|
137
|
+
recursive: true,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, cleanup, fireEvent, waitFor } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
import { EventTrackerProvider, useEventTracker } from './EventTracker';
|
|
5
|
+
|
|
6
|
+
const makePlugin = () => ({
|
|
7
|
+
isEnabled: jest.fn(() => true),
|
|
8
|
+
init: jest.fn(),
|
|
9
|
+
trackEvent: jest.fn(),
|
|
10
|
+
trackPageView: jest.fn(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('EventTracker', () => {
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
cleanup();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should allow click events', async () => {
|
|
19
|
+
const plugins = [makePlugin()];
|
|
20
|
+
|
|
21
|
+
const { getByText } = render(
|
|
22
|
+
<EventTrackerProvider plugins={plugins}>
|
|
23
|
+
<button data-analytics-on="click" data-analytics-action="click" type="button">
|
|
24
|
+
Hello World
|
|
25
|
+
</button>
|
|
26
|
+
</EventTrackerProvider>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const btn = getByText('Hello World');
|
|
30
|
+
|
|
31
|
+
fireEvent.click(btn);
|
|
32
|
+
|
|
33
|
+
expect(plugins[0].trackEvent).toHaveBeenCalledTimes(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should allow trackEvents from code', async () => {
|
|
37
|
+
const plugins = [makePlugin()];
|
|
38
|
+
|
|
39
|
+
const Button = () => {
|
|
40
|
+
const { trackEvent } = useEventTracker();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<button
|
|
44
|
+
onClick={() =>
|
|
45
|
+
trackEvent({
|
|
46
|
+
url: '/test',
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
>
|
|
50
|
+
Hello World
|
|
51
|
+
</button>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const { getByText } = render(
|
|
56
|
+
<EventTrackerProvider plugins={plugins}>
|
|
57
|
+
<Button />
|
|
58
|
+
</EventTrackerProvider>
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const btn = getByText('Hello World');
|
|
62
|
+
|
|
63
|
+
fireEvent.click(btn);
|
|
64
|
+
|
|
65
|
+
await waitFor(() => {
|
|
66
|
+
expect(plugins[0].trackEvent).toHaveBeenCalledTimes(1);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo } from 'react';
|
|
2
|
+
import { AvAnalytics } from '@availity/analytics-core';
|
|
3
|
+
|
|
4
|
+
export type EventTrackerProps = {
|
|
5
|
+
/** */
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
/** An array of plugins to pass to the underlying AvAnalytics class instance. */
|
|
8
|
+
plugins?: any[];
|
|
9
|
+
/** Enable or disable page tracking on initialization.
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
pageTracking?: boolean;
|
|
13
|
+
/** Enable or disable auto tracking on initialization.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
autoTrack?: boolean;
|
|
17
|
+
/** Enable or disable recursive functionality on initialization.
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
recursive?: boolean;
|
|
21
|
+
/** Customize the prefix used for data event tracker attributes used for auto tracking.
|
|
22
|
+
* @default 'data-analytics'
|
|
23
|
+
*/
|
|
24
|
+
attributePrefix?: string;
|
|
25
|
+
/** Array of event modifiers enabling you to use other keywords for action instead of click for event type matching.
|
|
26
|
+
* @default ['action']
|
|
27
|
+
*/
|
|
28
|
+
eventModifiers?: any[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const EventTrackerContext = createContext<AvAnalytics | null>(null);
|
|
32
|
+
|
|
33
|
+
export const useEventTracker = () => {
|
|
34
|
+
const ctx = useContext(EventTrackerContext);
|
|
35
|
+
|
|
36
|
+
if (!ctx) {
|
|
37
|
+
throw new Error('useEventTracker must be used within an EventTrackerProvider');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return ctx;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const EventTrackerProvider = ({
|
|
44
|
+
children,
|
|
45
|
+
plugins,
|
|
46
|
+
pageTracking = true,
|
|
47
|
+
autoTrack = true,
|
|
48
|
+
recursive = true,
|
|
49
|
+
attributePrefix = 'data-analytics',
|
|
50
|
+
eventModifiers = ['action'],
|
|
51
|
+
}: EventTrackerProps) => {
|
|
52
|
+
const analytics = useMemo(
|
|
53
|
+
() => new AvAnalytics(plugins, Promise, pageTracking, autoTrack, { recursive, attributePrefix, eventModifiers }),
|
|
54
|
+
[attributePrefix, autoTrack, eventModifiers, pageTracking, plugins, recursive]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
analytics.init();
|
|
59
|
+
|
|
60
|
+
if (pageTracking) {
|
|
61
|
+
analytics.trackPageView();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return () => analytics.stopAutoTrack();
|
|
65
|
+
}, [analytics, pageTracking]);
|
|
66
|
+
|
|
67
|
+
return <EventTrackerContext.Provider value={analytics}>{children}</EventTrackerContext.Provider>;
|
|
68
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../dist/out-tsc",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"types": ["jest", "node", "@testing-library/jest-dom"],
|
|
7
|
+
"allowJs": true
|
|
8
|
+
},
|
|
9
|
+
"include": ["**/*.test.js", "**/*.test.ts", "**/*.test.tsx", "**/*.d.ts"]
|
|
10
|
+
}
|