Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ dist
coverage

yarn-error.log
.idea
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,49 @@
npm install @statflo/widget-sdk # or yarn add @statflo/widget-sdk
```

## Getting Started

### Example Widgets

Two example widgets are provided, one using React and one using vanilla javascript.

#### React Example Widget

1. Install the React example widget
```
yarn --cwd examples/react install
```
2. Start the React example widget
```
yarn --cwd examples/react start
```
3. View the React example widget at [http://localhost:3001](http://localhost:3001)

#### Vanilla JS Example Widget

1. Install the Vanilla JS example widget
```
yarn --cwd examples/vanillajs install
```
2. Start the Vanilla JS example widget
```
yarn --cwd examples/vanillajs start
```
3. View the Vanilla JS example widget at [http://localhost:3002](http://localhost:3002)

### Widget Playground

We have provided a live playground at [https://statflo.github.io/widget-sdk/conversations](https://statflo.github.io/widget-sdk/conversations)
where you can test your widgets as you build them. We recommend building the example widgets
above and testing them in the playground so you can get familiar with this project.

#### Suggested Workflow

1. Check out "Getting Started" guide in the left-hand navigation menu.
2. Click on "Widget Manager" in the left-hand navigation menu and try adding the example widgets above by clicking "Add Widget" in the top left.
3. Click on "Conversations" in the left-hand navigation to view your newly added widgets.
4. Click on "Event Manager" to simulate sending events to your widgets.

## Creating a widget

Please see our [Examples](https://github.com/Statflo/widget-sdk/tree/main/examples).
Expand All @@ -38,9 +81,9 @@ import useWidgetStore from "@statflo/widget-sdk";

```typescript
import useWidgetStore from "@statflo/widget-sdk";
import { create } from "zustand";
import { useStore } from "zustand";

const useBoundWidgetStore = create(useWidgetStore);
const publishEvent = useStore(useWidgetStore, (state: WidgetState) => state.publishEvent);
```

### Publishing an event
Expand All @@ -60,7 +103,7 @@ publishEvent(new WidgetEvent("MESSAGE_UPDATED", "<YOUR MESSAGE>"));
```typescript
import { WidgetEvent } from "@statflo/widget-sdk";

const { publishEvent } = useBoundWidgetStore((state) => state);
const publishEvent = useStore(useWidgetStore, (state: WidgetState) => state.publishEvent);

useEffect(() => {
// This event only fires on component initialization
Expand Down Expand Up @@ -230,4 +273,4 @@ By default, the target origin will be the url of the widget you register with th

## Adding a widget to Statflo

Once your widget has been deployed and is ready to be integrated into the application, please reach out to the Statflo team.
Once your widget has been deployed and is ready to be integrated into the application, please reach out to the Statflo team.
5 changes: 2 additions & 3 deletions examples/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@statflo/widget-sdk": "./../../",
"@statflo/widget-sdk": "latest",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand All @@ -21,8 +21,7 @@
"typescript": "^4.8.4",
"web-vitals": "^2.1.4",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"zustand": "^4.3.3"
"webpack-dev-server": "^4.11.1"
},
"scripts": {
"start": "webpack serve",
Expand Down
97 changes: 53 additions & 44 deletions examples/react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
import React, { useEffect, useState } from "react";
import React, {useEffect, useState} from "react";
import "iframe-resizer-react";
import { create } from "zustand";
import {useStore} from "zustand";
import "./App.css";

import useWidgetStore, { WidgetEvent } from "@statflo/widget-sdk";
import useWidgetStore, {WidgetEvent, WidgetState} from "@statflo/widget-sdk";

const useBoundWidgetStore = create(useWidgetStore);

const App = () => {
const { events, publishEvent, getLatestEvent } = useBoundWidgetStore(
(state) => state
);
const events = useStore(useWidgetStore, (state: WidgetState) => state.events)
const publishEvent = useStore(useWidgetStore, (state: WidgetState) => state.publishEvent)
const getLatestEvent = useStore(useWidgetStore, (state: WidgetState) => state.getLatestEvent)

const [token, setToken] = useState("");
const [email, setEmail] = useState("");
const [account, setAccount] = useState("");
const [device, setDevice] = useState("");

const fetchUser = (token: string) => {
fetch("https://app.statflo.com/v2/api/auth/me", {
headers: { authorization: `Bearer ${token}` },
})
.then((response) => response.json())
.then((json) => {
setEmail(json.user.email);
})
.catch(() => {});
};
const getDevice = () => {
const devices = [
'Samsung Galaxy S25 Ultra',
'Apple iPhone 16 Pro Max',
'Google Pixel 9a',
];

useEffect(() => {
// Simulate a token being emitted from the Statflo UI to this widget.
// If you'd like to test with a live token it can be acquired
// at https://app.statflo.com/v2/api/auth/me after first logging in.
publishEvent(new WidgetEvent("TOKEN_UPDATED", "<YOUR TEST TOKEN>"));
}, []);
return devices[Math.floor(Math.random() * devices.length)];
}

const sendFollowUp = () => {
publishEvent(new WidgetEvent("REPLACE_MESSAGE", `Hi, how are you enjoying your ${device}?`));
}

useEffect(() => {
const latest = getLatestEvent();
Expand All @@ -41,42 +36,56 @@ const App = () => {
}

switch (latest.type) {
case "TOKEN_UPDATED":
setToken(latest.data);
case "CURRENT_ACCOUNT_ID":
setAccount(latest.data);
setDevice(getDevice());
break;
}
}, [events]);

useEffect(() => {
if (!token) {
return;
}

fetchUser(token);
}, [token]);
}, [device, events, getLatestEvent, publishEvent]);

return (
<div className="container g-0 border-top border-2">
<div className="container g-0 border-top border-2 p-3">
<div className="row justify-content-center no-gutters g-0">
<h6 className="text-center pt-2">React Widget</h6>
<h6 className="text-center pt-2">
React Inventory Widget
</h6>

<form className="col pt-3 mb-4 border-bottom border-2">
<form
className="col pt-3 border-bottom border-2"
>
<fieldset disabled>
<div className="mb-3">
<label className="form-label visually-hidden" htmlFor="Email">
Email
<label className="form-label" htmlFor="account">
Account
</label>
<input
name="account"
className="form-control form-control-sm"
id="account"
value={account}
readOnly={true}
placeholder="..."
/>
</div>
<div className="mb-3">
<label className="form-label" htmlFor="device">
Device
</label>
<input
name="email"
name="device"
className="form-control form-control-sm"
id="email"
value={email}
id="device"
value={device}
readOnly={true}
placeholder="..."
/>
</div>
</fieldset>
</form>
<button id="send" className="btn btn-primary" disabled={!device}
onClick={sendFollowUp}>
Send Follow Up
</button>
</div>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions examples/react/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ module.exports = {
entry: "./src/index",
mode: "development",
output: {
publicPath: 'http://localhost:3000/'
publicPath: 'http://localhost:3001/'
},
devServer: {
port: 3000,
port: 3001,
allowedHosts: 'all'
},
module: {
Expand Down
24 changes: 13 additions & 11 deletions examples/react/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1638,15 +1638,19 @@
dependencies:
"@sinonjs/commons" "^1.7.0"

"@statflo/widget-sdk@./../../":
version "0.4.2"
"@statflo/widget-sdk@latest":
version "0.4.10"
resolved "https://registry.yarnpkg.com/@statflo/widget-sdk/-/widget-sdk-0.4.10.tgz#7d48e3a33eea8eabbe6763fe98432cd4590d7071"
integrity sha512-JEwQ/pLBSti5fUj831OfX1EYhj5wBZO2qZS9KzYJXxcdhipg4uDhkMdrAhdY0u+OdPluWUGEAzSBYIR1GK9BcQ==
dependencies:
iframe-resizer "^4.3.2"
iframe-resizer-react "^1.1.0"
react "^18.2.0"
react-error-boundary "^3.1.4"
typescript "^4.9.3"
uuid "^9.0.0"
zustand "^4.3.3"
zustand "^5.0.3"
optionalDependencies:
react ">=16.8"
use-sync-external-store "1.2.0"

"@surma/rollup-plugin-off-main-thread@^2.2.3":
Expand Down Expand Up @@ -7598,7 +7602,7 @@ react-scripts@5.0.1:
optionalDependencies:
fsevents "^2.3.2"

react@>=16.8, react@^18.2.0:
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
Expand Down Expand Up @@ -9374,9 +9378,7 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==

zustand@^4.3.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.6.tgz#ce7804eb75361af0461a2d0536b65461ec5de86f"
integrity sha512-6J5zDxjxLE+yukC2XZWf/IyWVKnXT9b9HUv09VJ/bwGCpKNcaTqp7Ws28Xr8jnbvnZcdRaidztAPsXFBIqufiw==
dependencies:
use-sync-external-store "1.2.0"
zustand@^5.0.3:
version "5.0.5"
resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.5.tgz#3e236f6a953142d975336d179bc735d97db17e84"
integrity sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==
2 changes: 1 addition & 1 deletion examples/vanillajs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"@statflo/widget-sdk": "./../../",
"@statflo/widget-sdk": "latest",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.75.0"
},
Expand Down
Loading