@ubidots/react-html-canvas 0.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.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # @ubidots/react-html-canvas
2
+
3
+ React library to interact with Ubidots dashboards from HTML Canvas widgets.
4
+
5
+ ## Instalación
6
+
7
+ ```bash
8
+ pnpm add @ubidots/react-html-canvas
9
+ ```
10
+
11
+ ### Peer Dependencies
12
+
13
+ - react >= 16.8
14
+ - react-dom >= 16.8
15
+
16
+ ## Basic Usage
17
+
18
+ Wrap your app with the Provider and use hooks to access dashboard data/events:
19
+
20
+ ```tsx
21
+ import {
22
+ UbidotsProvider,
23
+ useUbidotsReady,
24
+ useUbidotsSelectedDevice,
25
+ useUbidotsActions,
26
+ } from '@ubidots/react-html-canvas';
27
+
28
+ function DeviceInfo() {
29
+ const ready = useUbidotsReady();
30
+ const device = useUbidotsSelectedDevice();
31
+ const { setDashboardDevice } = useUbidotsActions();
32
+
33
+ if (!ready) return <span>Loading...</span>;
34
+ return (
35
+ <div>
36
+ <pre>{JSON.stringify(device, null, 2)}</pre>
37
+ <button onClick={() => setDashboardDevice('device-id')}>
38
+ Select Device
39
+ </button>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ export default function App() {
45
+ return (
46
+ <UbidotsProvider readyEvents={['receivedToken']}>
47
+ <DeviceInfo />
48
+ </UbidotsProvider>
49
+ );
50
+ }
51
+ ```
52
+
53
+ ## API
54
+
55
+ - Provider
56
+ - UbidotsProvider(props)
57
+ - props:
58
+ - onReady?: () => void
59
+ - readyEvents?: ("receivedToken" | "receivedJWTToken" | "selectedDevice" | ...)[]
60
+ - validateOrigin?: (origin: string) => boolean
61
+ - initialStateOverride?: Partial<State>
62
+
63
+ - Hooks
64
+ - useUbidotsReady(): boolean
65
+ - useUbidotsToken(): string | null
66
+ - useUbidotsSelectedDevice(): Device | null
67
+ - useUbidotsSelectedDevices(): Device[] | null
68
+ - useUbidotsDashboardDateRange(): DateRange | null
69
+ - useUbidotsRealTimeStatus(): boolean | null
70
+ - useUbidotsDeviceObject(): DeviceObject | null
71
+ - useUbidotsDashboardObject(): DashboardObject | null
72
+ - useUbidotsSelectedFilters(): Filter[] | null
73
+ - useUbidotsWidget(): { settings: object; id: string } | null
74
+ - useUbidotsActions(): Actions
75
+ - useUbidotsAPI(): Ubidots API client (autenticado con token)
76
+
77
+ - Acciones (useUbidotsActions)
78
+ - setDashboardDevice(deviceId: string)
79
+ - setDashboardMultipleDevices(deviceIds: string[])
80
+ - setDashboardDateRange(range: { startTime: number; endTime: number })
81
+ - setDashboardLayer(layerId: string)
82
+ - setRealTime(rt: boolean)
83
+ - refreshDashboard()
84
+ - openDrawer({ url: string; width: number })
85
+ - setFullScreen('toggle' | 'enable' | 'disable')
86
+ - getHeaders(): { Authorization | X-Auth-Token, Content-type }
87
+
88
+ ## Examples & Documentation
89
+
90
+ ### 📚 Complete Documentation
91
+
92
+ See the [docs/](./docs/) folder for comprehensive API documentation:
93
+
94
+ - **Provider**: [UbidotsProvider](./docs/UbidotsProvider.md)
95
+ - **Hooks**: Individual documentation for each hook
96
+ - **Types**: TypeScript interfaces and types
97
+ - **Guides**: Setup, patterns, and best practices
98
+
99
+ ### 🎯 Working Examples
100
+
101
+ See the [examples/](./examples/) folder for complete working examples:
102
+
103
+ - **[Basic Usage](./examples/basic-usage/)** - Simple setup and device display
104
+ - **[Device Selector](./examples/device-selector/)** - Interactive device selection with single/multi-select
105
+ - **[Real-time Dashboard](./examples/real-time-dashboard/)** - Live data streaming and controls
106
+ - **[Complete Widget](./examples/complete-widget/)** - Comprehensive example testing all features
107
+ - **[With HOCs](./examples/with-hocs/)** - Higher-Order Components usage
108
+
109
+ ## Configurable Ready State
110
+
111
+ You can control which events must occur before considering the system "ready":
112
+
113
+ ```tsx
114
+ <UbidotsProvider readyEvents={['receivedToken', 'selectedDevice']} />
115
+ ```
116
+
117
+ ## Notes
118
+
119
+ - The vanilla library (ubidots-html-canvas) was used as reference for events/methods. It's not a runtime dependency.
120
+ - The useUbidotsAPI hook exposes an SDK client and authenticates it when the token arrives.
121
+
122
+ ## Development
123
+
124
+ ### Code Quality
125
+
126
+ This project uses ESLint for linting and Prettier for code formatting to ensure consistent code style.
127
+
128
+ #### Available Scripts
129
+
130
+ ```bash
131
+
132
+ # Install dependencies
133
+ pnpm install
134
+
135
+ # Run linter
136
+ pnpm run lint
137
+
138
+ # Run linter with automatic fixes
139
+ pnpm run lint:fix
140
+
141
+ # Format code with Prettier
142
+ pnpm run format
143
+
144
+ # Check if code is properly formatted
145
+ pnpm run format:check
146
+ ```
147
+
148
+ #### VS Code Integration
149
+
150
+ If you're using VS Code, the project includes settings that will:
151
+
152
+ - Format code automatically on save
153
+ - Run ESLint fixes on save
154
+ - Show linting errors and warnings inline
155
+
156
+ Make sure you have the following VS Code extensions installed:
157
+
158
+ - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
159
+ - [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
160
+
161
+ #### Configuration Files
162
+
163
+ - `eslint.config.js` - ESLint configuration with React, TypeScript, and accessibility rules
164
+ - `.prettierrc` - Prettier formatting configuration
165
+ - `.editorconfig` - Editor configuration for consistent coding styles
166
+ - `.vscode/settings.json` - VS Code specific settings
167
+
168
+ ### CI/CD Pipelines
169
+
170
+ This project uses GitHub Actions for continuous integration and deployment:
171
+
172
+ #### Pull Request Checks (`.github/workflows/pr-checks.yml`)
173
+
174
+ Runs on every PR and push to main/develop branches:
175
+
176
+ - **Code Quality & Tests**: Runs on Node.js 18 and 20
177
+ - TypeScript compilation check
178
+ - ESLint code quality check
179
+ - Prettier formatting verification
180
+ - Unit tests execution
181
+ - Build verification
182
+ - **Security Audit**: Checks for vulnerabilities in dependencies
183
+ - **PR Summary**: Posts automated summary comment on PRs
184
+
185
+ #### Deployment Pipeline (`.github/workflows/deploy.yml`)
186
+
187
+ Manual deployment workflow with the following features:
188
+
189
+ - **Manual Trigger**: Only runs when manually triggered from GitHub Actions
190
+ - **Version Selection**: Choose patch, minor, or major version bump
191
+ - **Pre-release Support**: Optional tag for beta/alpha releases
192
+ - **Quality Checks**: Full linting, testing, and build verification
193
+ - **Automated Versioning**: Bumps version and creates git tags
194
+ - **NPM Publishing**: Publishes to NPM with appropriate tags
195
+ - **GitHub Release**: Creates release with installation instructions
196
+
197
+ ### How to Deploy
198
+
199
+ To deploy a new version:
200
+
201
+ 1. Go to the **Actions** tab in GitHub
202
+ 2. Select the **Deploy** workflow
203
+ 3. Click **Run workflow**
204
+ 4. Choose the version bump type (patch/minor/major)
205
+ 5. Optionally add a pre-release tag (e.g., "beta")
206
+ 6. Click **Run workflow**
207
+
208
+ The deployment will:
209
+
210
+ - Run all quality checks
211
+ - Bump the version in package.json
212
+ - Create a git tag
213
+ - Publish to NPM
214
+ - Create a GitHub release
215
+
216
+ ## License
217
+
218
+ MIT
@@ -0,0 +1,3 @@
1
+ import { UbidotsAction, UbidotsState } from '../types/index.ts';
2
+ export declare const initialState: UbidotsState;
3
+ export declare function ubidotsReducer(state: UbidotsState, action: UbidotsAction): UbidotsState;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { OutboundActions } from '../types/index.ts';
2
+ /**
3
+ * Create actions object with header generation
4
+ */
5
+ export declare function createActions(jwtToken: string | null, token: string | null): OutboundActions;
@@ -0,0 +1,38 @@
1
+ import { ReadyEvent } from '../types/index.ts';
2
+ export declare const INBOUND_EVENTS: {
3
+ readonly RECEIVED_TOKEN: "receivedToken";
4
+ readonly RECEIVED_JWT_TOKEN: "receivedJWTToken";
5
+ readonly SELECTED_DEVICE: "selectedDevice";
6
+ readonly SELECTED_DEVICES: "selectedDevices";
7
+ readonly SELECTED_DASHBOARD_DATE_RANGE: "selectedDashboardDateRange";
8
+ readonly SELECTED_DASHBOARD_OBJECT: "selectedDashboardObject";
9
+ readonly SELECTED_DEVICE_OBJECT: "selectedDeviceObject";
10
+ readonly SELECTED_DEVICE_OBJECTS: "selectedDeviceObjects";
11
+ readonly SELECTED_FILTERS: "selectedFilters";
12
+ readonly IS_REAL_TIME_ACTIVE: "isRealTimeActive";
13
+ };
14
+ export declare const OUTBOUND_EVENTS: {
15
+ readonly SET_DASHBOARD_DEVICE: "setDashboardDevice";
16
+ readonly SET_DASHBOARD_MULTIPLE_DEVICES: "setDashboardMultipleDevices";
17
+ readonly SET_DASHBOARD_DATE_RANGE: "setDashboardDateRange";
18
+ readonly SET_DASHBOARD_LAYER: "setDashboardLayer";
19
+ readonly SET_REAL_TIME: "setRealTime";
20
+ readonly REFRESH_DASHBOARD: "refreshDashboard";
21
+ readonly OPEN_DRAWER: "openDrawer";
22
+ readonly SET_FULL_SCREEN: "setFullScreen";
23
+ };
24
+ export declare const ACTION_TYPES: {
25
+ readonly RECEIVED_TOKEN: "RECEIVED_TOKEN";
26
+ readonly RECEIVED_JWT_TOKEN: "RECEIVED_JWT_TOKEN";
27
+ readonly SELECTED_DEVICE: "SELECTED_DEVICE";
28
+ readonly SELECTED_DEVICES: "SELECTED_DEVICES";
29
+ readonly SELECTED_DASHBOARD_DATE_RANGE: "SELECTED_DASHBOARD_DATE_RANGE";
30
+ readonly SELECTED_DASHBOARD_OBJECT: "SELECTED_DASHBOARD_OBJECT";
31
+ readonly SELECTED_DEVICE_OBJECT: "SELECTED_DEVICE_OBJECT";
32
+ readonly SELECTED_DEVICE_OBJECTS: "SELECTED_DEVICE_OBJECTS";
33
+ readonly SELECTED_FILTERS: "SELECTED_FILTERS";
34
+ readonly REAL_TIME_STATUS: "REAL_TIME_STATUS";
35
+ readonly SET_READY: "SET_READY";
36
+ readonly SET_WIDGET: "SET_WIDGET";
37
+ };
38
+ export declare const DEFAULT_READY_EVENTS: ReadyEvent[];
@@ -0,0 +1,14 @@
1
+ import { Dispatch } from 'react';
2
+ import { UbidotsAction, UbidotsState, ReadyEvent } from '../types/index.ts';
3
+ /**
4
+ * Main message handler that uses object mapping instead of switch
5
+ */
6
+ export declare function handleInboundMessage(event: string, payload: unknown, dispatch: Dispatch<UbidotsAction>, satisfiedEventsRef: React.MutableRefObject<Set<ReadyEvent>>): void;
7
+ /**
8
+ * Check if all required events are satisfied and update ready state
9
+ *
10
+ * This function checks two conditions:
11
+ * 1. All required events from readyEvents array have been satisfied
12
+ * 2. OR the state has all required values defined (for public dashboards)
13
+ */
14
+ export declare function checkReadyState(readyEvents: ReadyEvent[], satisfiedEventsRef: React.MutableRefObject<Set<ReadyEvent>>, readyRef: React.MutableRefObject<boolean>, dispatch: Dispatch<UbidotsAction>, state: UbidotsState, onReady?: () => void): void;
@@ -0,0 +1,25 @@
1
+ import { default as React } from 'react';
2
+ import { UbidotsState, UbidotsActions, ReadyEvent } from '../types/index.ts';
3
+ import { initialState } from './UbidotsReducer';
4
+ export interface UbidotsContextValue {
5
+ state: UbidotsState;
6
+ actions: UbidotsActions;
7
+ }
8
+ /**
9
+ * Main hook for accessing Ubidots context
10
+ *
11
+ * This hook provides access to the Ubidots state and actions.
12
+ * Must be used within a UbidotsProvider component.
13
+ *
14
+ * @returns The context value containing state and actions
15
+ * @throws If used outside of UbidotsProvider
16
+ */
17
+ export declare function useUbidots(): UbidotsContextValue;
18
+ export interface UbidotsProviderProps {
19
+ children: React.ReactNode;
20
+ onReady?: () => void;
21
+ readyEvents?: ReadyEvent[];
22
+ validateOrigin?: (origin: string) => boolean;
23
+ initialStateOverride?: Partial<typeof initialState>;
24
+ }
25
+ export declare function UbidotsProvider({ children, onReady, readyEvents, validateOrigin, initialStateOverride, }: UbidotsProviderProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function compose<T>(...fns: Array<(c: T) => T>): (c: T) => T;
@@ -0,0 +1,3 @@
1
+ export * from './withSelectedDevice';
2
+ export * from './withUbidotsActions';
3
+ export * from './compose';
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ import { Device } from '../types/index.ts';
3
+ export declare function withSelectedDevice<P extends {
4
+ selectedDevice?: Device | null;
5
+ }>(Component: React.ComponentType<P>): (props: Omit<P, "selectedDevice">) => React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ import { UbidotsActions } from '../types/index.ts';
3
+ export declare function withUbidotsActions<P extends {
4
+ ubidotsActions?: UbidotsActions;
5
+ }>(Component: React.ComponentType<P>): (props: Omit<P, "ubidotsActions">) => React.JSX.Element;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './useUbidotsReady';
2
+ export * from './useUbidotsSelections';
3
+ export * from './useUbidotsActions';
4
+ export * from './useUbidotsAPI';
@@ -0,0 +1,6 @@
1
+ export interface UbidotsJSClient extends Record<string, unknown> {
2
+ Auth: {
3
+ authenticate: (token: string) => void;
4
+ };
5
+ }
6
+ export declare function useUbidotsAPI(): UbidotsJSClient | null;
@@ -0,0 +1 @@
1
+ export declare function useUbidotsActions(): import('..').OutboundActions;
@@ -0,0 +1 @@
1
+ export declare function useUbidotsReady(): boolean;
@@ -0,0 +1,11 @@
1
+ export declare function useUbidotsToken(): string | null;
2
+ export declare function useUbidotsJWT(): string | null;
3
+ export declare function useUbidotsSelectedDevice(): import('..').Device | null;
4
+ export declare function useUbidotsSelectedDevices(): import('..').Device[] | null;
5
+ export declare function useUbidotsDashboardDateRange(): import('..').DateRange | null;
6
+ export declare function useUbidotsRealTimeStatus(): boolean | null;
7
+ export declare function useUbidotsDeviceObject(): import('..').DeviceObject | null;
8
+ export declare function useUbidotsDashboardObject(): import('..').DashboardObject | null;
9
+ export declare function useUbidotsWidget(): import('..').WidgetInfo | null;
10
+ export declare function useUbidotsSelectedDeviceObjects(): import('..').DeviceObject[] | null;
11
+ export declare function useUbidotsSelectedFilters(): import('..').FilterValue[] | null;
@@ -0,0 +1,4 @@
1
+ export { useUbidots, UbidotsProvider } from './context/ubidots';
2
+ export * from './hooks';
3
+ export * from './hocs';
4
+ export * from './types';
@@ -0,0 +1 @@
1
+ "use strict";var g=Object.defineProperty,w=Object.defineProperties;var m=Object.getOwnPropertyDescriptors;var O=Object.getOwnPropertySymbols;var j=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var I=(e,t,E)=>t in e?g(e,t,{enumerable:!0,configurable:!0,writable:!0,value:E}):e[t]=E,c=(e,t)=>{for(var E in t||(t={}))j.call(t,E)&&I(e,E,t[E]);if(O)for(var E of O(t))N.call(t,E)&&I(e,E,t[E]);return e},r=(e,t)=>w(e,m(t));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),L=require("@ubidots/ubidots-javascript-library"),D={RECEIVED_TOKEN:"receivedToken",RECEIVED_JWT_TOKEN:"receivedJWTToken",SELECTED_DEVICE:"selectedDevice",SELECTED_DEVICES:"selectedDevices",SELECTED_DASHBOARD_DATE_RANGE:"selectedDashboardDateRange",SELECTED_DASHBOARD_OBJECT:"selectedDashboardObject",SELECTED_DEVICE_OBJECT:"selectedDeviceObject",SELECTED_DEVICE_OBJECTS:"selectedDeviceObjects",SELECTED_FILTERS:"selectedFilters",IS_REAL_TIME_ACTIVE:"isRealTimeActive"},u={SET_DASHBOARD_DEVICE:"setDashboardDevice",SET_DASHBOARD_MULTIPLE_DEVICES:"setDashboardMultipleDevices",SET_DASHBOARD_DATE_RANGE:"setDashboardDateRange",SET_DASHBOARD_LAYER:"setDashboardLayer",SET_REAL_TIME:"setRealTime",REFRESH_DASHBOARD:"refreshDashboard",OPEN_DRAWER:"openDrawer",SET_FULL_SCREEN:"setFullScreen"},s={RECEIVED_TOKEN:"RECEIVED_TOKEN",RECEIVED_JWT_TOKEN:"RECEIVED_JWT_TOKEN",SELECTED_DEVICE:"SELECTED_DEVICE",SELECTED_DEVICES:"SELECTED_DEVICES",SELECTED_DASHBOARD_DATE_RANGE:"SELECTED_DASHBOARD_DATE_RANGE",SELECTED_DASHBOARD_OBJECT:"SELECTED_DASHBOARD_OBJECT",SELECTED_DEVICE_OBJECT:"SELECTED_DEVICE_OBJECT",SELECTED_DEVICE_OBJECTS:"SELECTED_DEVICE_OBJECTS",SELECTED_FILTERS:"SELECTED_FILTERS",REAL_TIME_STATUS:"REAL_TIME_STATUS",SET_READY:"SET_READY",SET_WIDGET:"SET_WIDGET"},J=["receivedToken"],H={ready:!1,token:null,jwtToken:null,selectedDevice:null,selectedDevices:null,dateRange:null,dashboardObject:null,deviceObject:null,selectedDeviceObjects:null,selectedFilters:null,realTime:null,widget:null},k={[s.RECEIVED_TOKEN]:(e,t)=>r(c({},e),{token:t.payload}),[s.RECEIVED_JWT_TOKEN]:(e,t)=>r(c({},e),{jwtToken:t.payload}),[s.SELECTED_DEVICE]:(e,t)=>r(c({},e),{selectedDevice:t.payload}),[s.SELECTED_DEVICES]:(e,t)=>r(c({},e),{selectedDevices:t.payload}),[s.SELECTED_DASHBOARD_DATE_RANGE]:(e,t)=>r(c({},e),{dateRange:t.payload}),[s.SELECTED_DASHBOARD_OBJECT]:(e,t)=>r(c({},e),{dashboardObject:t.payload}),[s.SELECTED_DEVICE_OBJECT]:(e,t)=>r(c({},e),{deviceObject:t.payload}),[s.SELECTED_DEVICE_OBJECTS]:(e,t)=>r(c({},e),{selectedDeviceObjects:t.payload}),[s.SELECTED_FILTERS]:(e,t)=>r(c({},e),{selectedFilters:t.payload}),[s.REAL_TIME_STATUS]:(e,t)=>r(c({},e),{realTime:t.payload}),[s.SET_READY]:(e,t)=>r(c({},e),{ready:t.payload}),[s.SET_WIDGET]:(e,t)=>r(c({},e),{widget:t.payload})};function F(e,t){const E=k[t.type];return E?E(e,t):e}const M={[D.RECEIVED_TOKEN]:(e,t,E)=>{t({type:s.RECEIVED_TOKEN,payload:e}),E.current.add("receivedToken")},[D.RECEIVED_JWT_TOKEN]:(e,t,E)=>{t({type:s.RECEIVED_JWT_TOKEN,payload:e}),E.current.add("receivedJWTToken")},[D.SELECTED_DEVICE]:(e,t,E)=>{let n=null;if(typeof e=="string"){const d=e.split(",")[0].trim();d&&(n={id:d})}t({type:s.SELECTED_DEVICE,payload:n}),E.current.add("selectedDevice")},[D.SELECTED_DEVICES]:(e,t,E)=>{t({type:s.SELECTED_DEVICES,payload:e}),E.current.add("selectedDevices")},[D.SELECTED_DASHBOARD_DATE_RANGE]:(e,t,E)=>{t({type:s.SELECTED_DASHBOARD_DATE_RANGE,payload:e}),E.current.add("selectedDashboardDateRange")},[D.SELECTED_DASHBOARD_OBJECT]:(e,t,E)=>{t({type:s.SELECTED_DASHBOARD_OBJECT,payload:e}),E.current.add("selectedDashboardObject")},[D.SELECTED_DEVICE_OBJECT]:(e,t,E)=>{t({type:s.SELECTED_DEVICE_OBJECT,payload:e}),E.current.add("selectedDeviceObject")},[D.SELECTED_DEVICE_OBJECTS]:(e,t,E)=>{t({type:s.SELECTED_DEVICE_OBJECTS,payload:e}),E.current.add("selectedDeviceObjects")},[D.SELECTED_FILTERS]:(e,t,E)=>{t({type:s.SELECTED_FILTERS,payload:e}),E.current.add("selectedFilters")},[D.IS_REAL_TIME_ACTIVE]:(e,t,E)=>{t({type:s.REAL_TIME_STATUS,payload:e}),E.current.add("isRealTimeActive")}};function W(e,t,E,n){const d=M[e];d&&d(t,E,n)}function P(e){const t=e.token!==null||e.jwtToken!==null,E=e.selectedDevice!==null,n=e.dateRange!==null,d=e.dashboardObject!==null;return t&&E&&n&&d}function p(e,t,E,n,d,i){if(!E.current){const l=e.every(_=>t.current.has(_)),S=P(d);(l||S)&&(E.current=!0,n({type:s.SET_READY,payload:!0}),i==null||i())}}function T(e,t){typeof window!="undefined"&&window.parent&&window.parent.postMessage({event:e,payload:t},"*")}function K(e,t){return e?{Authorization:`Bearer ${e}`,"Content-type":"application/json"}:t?{"X-Auth-Token":t,"Content-type":"application/json"}:{"Content-type":"application/json"}}function G(e){if(!e||typeof e!="object")return console.error("[setDashboardDateRange] Invalid date range: must be an object"),!1;const{startTime:t,endTime:E}=e;return typeof t!="number"||typeof E!="number"?(console.error("[setDashboardDateRange] Invalid date range: startTime and endTime must be numbers"),!1):t>=E?(console.error(`[setDashboardDateRange] Invalid date range: startTime (${new Date(t).toISOString()}) must be before endTime (${new Date(E).toISOString()})`),!1):!0}const Y={setDashboardDevice:e=>T(u.SET_DASHBOARD_DEVICE,e),setDashboardMultipleDevices:e=>T(u.SET_DASHBOARD_MULTIPLE_DEVICES,e),setDashboardDateRange:e=>{G(e)&&T(u.SET_DASHBOARD_DATE_RANGE,e)},setDashboardLayer:e=>T(u.SET_DASHBOARD_LAYER,e),setRealTime:e=>T(u.SET_REAL_TIME,e),refreshDashboard:()=>T(u.REFRESH_DASHBOARD),openDrawer:e=>{const t=typeof window!="undefined"?window.widgetId:"react-widget";T(u.OPEN_DRAWER,{drawerInfo:e,id:t})},setFullScreen:e=>T(u.SET_FULL_SCREEN,e)};function x(e,t){return r(c({},Y),{getHeaders:()=>K(e,t)})}const v=o.createContext(void 0);function a(){const e=o.useContext(v);if(!e)throw new Error("useUbidots must be used within UbidotsProvider");return e}function $({children:e,onReady:t,readyEvents:E=J,validateOrigin:n,initialStateOverride:d}){const[i,l]=o.useReducer(F,c(c({},H),d)),S=o.useRef(!1),_=o.useRef(new Set),b=o.useCallback(C=>n?n(C):!0,[n]);o.useEffect(()=>{function C(A){if(!b(A.origin))return;const{event:f,payload:y}=A.data||{};f&&(W(f,y,l,_),p(E,_,S,l,i,t))}return window.addEventListener("message",C),()=>window.removeEventListener("message",C)},[b,t,E,i]),o.useEffect(()=>{p(E,_,S,l,i,t)},[i,E,t]);const R=o.useMemo(()=>x(i.jwtToken,i.token),[i.jwtToken,i.token]),B=o.useMemo(()=>({state:i,actions:R}),[i,R]);return o.createElement(v.Provider,{value:B},e)}function q(){const{state:e}=a();return e.ready}function h(){const{state:e}=a();return e.token}function z(){const{state:e}=a();return e.jwtToken}function U(){const{state:e}=a();return e.selectedDevice}function X(){const{state:e}=a();return e.selectedDevices}function Q(){const{state:e}=a();return e.dateRange}function Z(){const{state:e}=a();return e.realTime}function ee(){const{state:e}=a();return e.deviceObject}function te(){const{state:e}=a();return e.dashboardObject}function Ee(){const{state:e}=a();return e.widget}function se(){const{state:e}=a();return e.selectedDeviceObjects}function ne(){const{state:e}=a();return e.selectedFilters}function V(){return a().actions}function ce(){const e=h(),t=o.useRef(null),[E,n]=o.useState(!1);return o.useEffect(()=>{!t.current&&L.Ubidots&&(t.current=L.Ubidots)},[]),o.useEffect(()=>{t.current&&e&&!E&&(t.current.Auth.authenticate(e),n(!0))},[e,E]),!E||!t.current?null:t.current}function oe(e){return function(E){const n=U();return o.createElement(e,r(c({},E),{selectedDevice:n}))}}function re(e){return function(E){const n=V();return o.createElement(e,r(c({},E),{ubidotsActions:n}))}}function ie(...e){return t=>e.reduceRight((E,n)=>n(E),t)}exports.UbidotsProvider=$;exports.compose=ie;exports.useUbidots=a;exports.useUbidotsAPI=ce;exports.useUbidotsActions=V;exports.useUbidotsDashboardDateRange=Q;exports.useUbidotsDashboardObject=te;exports.useUbidotsDeviceObject=ee;exports.useUbidotsJWT=z;exports.useUbidotsReady=q;exports.useUbidotsRealTimeStatus=Z;exports.useUbidotsSelectedDevice=U;exports.useUbidotsSelectedDeviceObjects=se;exports.useUbidotsSelectedDevices=X;exports.useUbidotsSelectedFilters=ne;exports.useUbidotsToken=h;exports.useUbidotsWidget=Ee;exports.withSelectedDevice=oe;exports.withUbidotsActions=re;
@@ -0,0 +1,370 @@
1
+ var w = Object.defineProperty, g = Object.defineProperties;
2
+ var U = Object.getOwnPropertyDescriptors;
3
+ var L = Object.getOwnPropertySymbols;
4
+ var N = Object.prototype.hasOwnProperty, j = Object.prototype.propertyIsEnumerable;
5
+ var p = (e, t, E) => t in e ? w(e, t, { enumerable: !0, configurable: !0, writable: !0, value: E }) : e[t] = E, r = (e, t) => {
6
+ for (var E in t || (t = {}))
7
+ N.call(t, E) && p(e, E, t[E]);
8
+ if (L)
9
+ for (var E of L(t))
10
+ j.call(t, E) && p(e, E, t[E]);
11
+ return e;
12
+ }, c = (e, t) => g(e, U(t));
13
+ import R, { createContext as H, useContext as J, useReducer as k, useRef as A, useCallback as F, useEffect as C, useMemo as v, useState as M } from "react";
14
+ import { Ubidots as h } from "@ubidots/ubidots-javascript-library";
15
+ const i = {
16
+ RECEIVED_TOKEN: "receivedToken",
17
+ RECEIVED_JWT_TOKEN: "receivedJWTToken",
18
+ SELECTED_DEVICE: "selectedDevice",
19
+ SELECTED_DEVICES: "selectedDevices",
20
+ SELECTED_DASHBOARD_DATE_RANGE: "selectedDashboardDateRange",
21
+ SELECTED_DASHBOARD_OBJECT: "selectedDashboardObject",
22
+ SELECTED_DEVICE_OBJECT: "selectedDeviceObject",
23
+ SELECTED_DEVICE_OBJECTS: "selectedDeviceObjects",
24
+ SELECTED_FILTERS: "selectedFilters",
25
+ IS_REAL_TIME_ACTIVE: "isRealTimeActive"
26
+ }, d = {
27
+ SET_DASHBOARD_DEVICE: "setDashboardDevice",
28
+ SET_DASHBOARD_MULTIPLE_DEVICES: "setDashboardMultipleDevices",
29
+ SET_DASHBOARD_DATE_RANGE: "setDashboardDateRange",
30
+ SET_DASHBOARD_LAYER: "setDashboardLayer",
31
+ SET_REAL_TIME: "setRealTime",
32
+ REFRESH_DASHBOARD: "refreshDashboard",
33
+ OPEN_DRAWER: "openDrawer",
34
+ SET_FULL_SCREEN: "setFullScreen"
35
+ }, n = {
36
+ RECEIVED_TOKEN: "RECEIVED_TOKEN",
37
+ RECEIVED_JWT_TOKEN: "RECEIVED_JWT_TOKEN",
38
+ SELECTED_DEVICE: "SELECTED_DEVICE",
39
+ SELECTED_DEVICES: "SELECTED_DEVICES",
40
+ SELECTED_DASHBOARD_DATE_RANGE: "SELECTED_DASHBOARD_DATE_RANGE",
41
+ SELECTED_DASHBOARD_OBJECT: "SELECTED_DASHBOARD_OBJECT",
42
+ SELECTED_DEVICE_OBJECT: "SELECTED_DEVICE_OBJECT",
43
+ SELECTED_DEVICE_OBJECTS: "SELECTED_DEVICE_OBJECTS",
44
+ SELECTED_FILTERS: "SELECTED_FILTERS",
45
+ REAL_TIME_STATUS: "REAL_TIME_STATUS",
46
+ SET_READY: "SET_READY",
47
+ SET_WIDGET: "SET_WIDGET"
48
+ }, W = ["receivedToken"], K = {
49
+ ready: !1,
50
+ token: null,
51
+ jwtToken: null,
52
+ selectedDevice: null,
53
+ selectedDevices: null,
54
+ dateRange: null,
55
+ dashboardObject: null,
56
+ deviceObject: null,
57
+ selectedDeviceObjects: null,
58
+ selectedFilters: null,
59
+ realTime: null,
60
+ widget: null
61
+ }, G = {
62
+ [n.RECEIVED_TOKEN]: (e, t) => c(r({}, e), {
63
+ token: t.payload
64
+ }),
65
+ [n.RECEIVED_JWT_TOKEN]: (e, t) => c(r({}, e), {
66
+ jwtToken: t.payload
67
+ }),
68
+ [n.SELECTED_DEVICE]: (e, t) => c(r({}, e), {
69
+ selectedDevice: t.payload
70
+ }),
71
+ [n.SELECTED_DEVICES]: (e, t) => c(r({}, e), {
72
+ selectedDevices: t.payload
73
+ }),
74
+ [n.SELECTED_DASHBOARD_DATE_RANGE]: (e, t) => c(r({}, e), {
75
+ dateRange: t.payload
76
+ }),
77
+ [n.SELECTED_DASHBOARD_OBJECT]: (e, t) => c(r({}, e), {
78
+ dashboardObject: t.payload
79
+ }),
80
+ [n.SELECTED_DEVICE_OBJECT]: (e, t) => c(r({}, e), {
81
+ deviceObject: t.payload
82
+ }),
83
+ [n.SELECTED_DEVICE_OBJECTS]: (e, t) => c(r({}, e), {
84
+ selectedDeviceObjects: t.payload
85
+ }),
86
+ [n.SELECTED_FILTERS]: (e, t) => c(r({}, e), {
87
+ selectedFilters: t.payload
88
+ }),
89
+ [n.REAL_TIME_STATUS]: (e, t) => c(r({}, e), {
90
+ realTime: t.payload
91
+ }),
92
+ [n.SET_READY]: (e, t) => c(r({}, e), {
93
+ ready: t.payload
94
+ }),
95
+ [n.SET_WIDGET]: (e, t) => c(r({}, e), {
96
+ widget: t.payload
97
+ })
98
+ };
99
+ function P(e, t) {
100
+ const E = G[t.type];
101
+ return E ? E(e, t) : e;
102
+ }
103
+ const Y = {
104
+ [i.RECEIVED_TOKEN]: (e, t, E) => {
105
+ t({ type: n.RECEIVED_TOKEN, payload: e }), E.current.add("receivedToken");
106
+ },
107
+ [i.RECEIVED_JWT_TOKEN]: (e, t, E) => {
108
+ t({
109
+ type: n.RECEIVED_JWT_TOKEN,
110
+ payload: e
111
+ }), E.current.add("receivedJWTToken");
112
+ },
113
+ [i.SELECTED_DEVICE]: (e, t, E) => {
114
+ let s = null;
115
+ if (typeof e == "string") {
116
+ const D = e.split(",")[0].trim();
117
+ D && (s = { id: D });
118
+ }
119
+ t({ type: n.SELECTED_DEVICE, payload: s }), E.current.add("selectedDevice");
120
+ },
121
+ [i.SELECTED_DEVICES]: (e, t, E) => {
122
+ t({
123
+ type: n.SELECTED_DEVICES,
124
+ payload: e
125
+ }), E.current.add("selectedDevices");
126
+ },
127
+ [i.SELECTED_DASHBOARD_DATE_RANGE]: (e, t, E) => {
128
+ t({
129
+ type: n.SELECTED_DASHBOARD_DATE_RANGE,
130
+ payload: e
131
+ }), E.current.add("selectedDashboardDateRange");
132
+ },
133
+ [i.SELECTED_DASHBOARD_OBJECT]: (e, t, E) => {
134
+ t({
135
+ type: n.SELECTED_DASHBOARD_OBJECT,
136
+ payload: e
137
+ }), E.current.add("selectedDashboardObject");
138
+ },
139
+ [i.SELECTED_DEVICE_OBJECT]: (e, t, E) => {
140
+ t({
141
+ type: n.SELECTED_DEVICE_OBJECT,
142
+ payload: e
143
+ }), E.current.add("selectedDeviceObject");
144
+ },
145
+ [i.SELECTED_DEVICE_OBJECTS]: (e, t, E) => {
146
+ t({
147
+ type: n.SELECTED_DEVICE_OBJECTS,
148
+ payload: e
149
+ }), E.current.add("selectedDeviceObjects");
150
+ },
151
+ [i.SELECTED_FILTERS]: (e, t, E) => {
152
+ t({
153
+ type: n.SELECTED_FILTERS,
154
+ payload: e
155
+ }), E.current.add("selectedFilters");
156
+ },
157
+ [i.IS_REAL_TIME_ACTIVE]: (e, t, E) => {
158
+ t({
159
+ type: n.REAL_TIME_STATUS,
160
+ payload: e
161
+ }), E.current.add("isRealTimeActive");
162
+ }
163
+ };
164
+ function x(e, t, E, s) {
165
+ const D = Y[e];
166
+ D && D(t, E, s);
167
+ }
168
+ function $(e) {
169
+ const t = e.token !== null || e.jwtToken !== null, E = e.selectedDevice !== null, s = e.dateRange !== null, D = e.dashboardObject !== null;
170
+ return t && E && s && D;
171
+ }
172
+ function V(e, t, E, s, D, a) {
173
+ if (!E.current) {
174
+ const u = e.every(
175
+ (_) => t.current.has(_)
176
+ ), l = $(D);
177
+ (u || l) && (E.current = !0, s({ type: n.SET_READY, payload: !0 }), a == null || a());
178
+ }
179
+ }
180
+ function T(e, t) {
181
+ typeof window != "undefined" && window.parent && window.parent.postMessage({ event: e, payload: t }, "*");
182
+ }
183
+ function z(e, t) {
184
+ return e ? {
185
+ Authorization: `Bearer ${e}`,
186
+ "Content-type": "application/json"
187
+ } : t ? {
188
+ "X-Auth-Token": t,
189
+ "Content-type": "application/json"
190
+ } : { "Content-type": "application/json" };
191
+ }
192
+ function X(e) {
193
+ if (!e || typeof e != "object")
194
+ return console.error(
195
+ "[setDashboardDateRange] Invalid date range: must be an object"
196
+ ), !1;
197
+ const { startTime: t, endTime: E } = e;
198
+ return typeof t != "number" || typeof E != "number" ? (console.error(
199
+ "[setDashboardDateRange] Invalid date range: startTime and endTime must be numbers"
200
+ ), !1) : t >= E ? (console.error(
201
+ `[setDashboardDateRange] Invalid date range: startTime (${new Date(t).toISOString()}) must be before endTime (${new Date(E).toISOString()})`
202
+ ), !1) : !0;
203
+ }
204
+ const q = {
205
+ setDashboardDevice: (e) => T(d.SET_DASHBOARD_DEVICE, e),
206
+ setDashboardMultipleDevices: (e) => T(d.SET_DASHBOARD_MULTIPLE_DEVICES, e),
207
+ setDashboardDateRange: (e) => {
208
+ X(e) && T(d.SET_DASHBOARD_DATE_RANGE, e);
209
+ },
210
+ setDashboardLayer: (e) => T(d.SET_DASHBOARD_LAYER, e),
211
+ setRealTime: (e) => T(d.SET_REAL_TIME, e),
212
+ refreshDashboard: () => T(d.REFRESH_DASHBOARD),
213
+ openDrawer: (e) => {
214
+ const t = typeof window != "undefined" ? window.widgetId : "react-widget";
215
+ T(d.OPEN_DRAWER, { drawerInfo: e, id: t });
216
+ },
217
+ setFullScreen: (e) => T(d.SET_FULL_SCREEN, e)
218
+ };
219
+ function Q(e, t) {
220
+ return c(r({}, q), {
221
+ getHeaders: () => z(e, t)
222
+ });
223
+ }
224
+ const B = H(
225
+ void 0
226
+ );
227
+ function o() {
228
+ const e = J(B);
229
+ if (!e) throw new Error("useUbidots must be used within UbidotsProvider");
230
+ return e;
231
+ }
232
+ function re({
233
+ children: e,
234
+ onReady: t,
235
+ readyEvents: E = W,
236
+ validateOrigin: s,
237
+ initialStateOverride: D
238
+ }) {
239
+ const [a, u] = k(P, r(r({}, K), D)), l = A(!1), _ = A(/* @__PURE__ */ new Set()), b = F(
240
+ (S) => s ? s(S) : !0,
241
+ [s]
242
+ );
243
+ C(() => {
244
+ function S(f) {
245
+ if (!b(f.origin)) return;
246
+ const { event: I, payload: m } = f.data || {};
247
+ I && (x(I, m, u, _), V(
248
+ E,
249
+ _,
250
+ l,
251
+ u,
252
+ a,
253
+ t
254
+ ));
255
+ }
256
+ return window.addEventListener("message", S), () => window.removeEventListener("message", S);
257
+ }, [b, t, E, a]), C(() => {
258
+ V(
259
+ E,
260
+ _,
261
+ l,
262
+ u,
263
+ a,
264
+ t
265
+ );
266
+ }, [a, E, t]);
267
+ const O = v(
268
+ () => Q(a.jwtToken, a.token),
269
+ [a.jwtToken, a.token]
270
+ ), y = v(
271
+ () => ({ state: a, actions: O }),
272
+ [a, O]
273
+ );
274
+ return /* @__PURE__ */ R.createElement(B.Provider, { value: y }, e);
275
+ }
276
+ function ce() {
277
+ const { state: e } = o();
278
+ return e.ready;
279
+ }
280
+ function Z() {
281
+ const { state: e } = o();
282
+ return e.token;
283
+ }
284
+ function ae() {
285
+ const { state: e } = o();
286
+ return e.jwtToken;
287
+ }
288
+ function ee() {
289
+ const { state: e } = o();
290
+ return e.selectedDevice;
291
+ }
292
+ function oe() {
293
+ const { state: e } = o();
294
+ return e.selectedDevices;
295
+ }
296
+ function De() {
297
+ const { state: e } = o();
298
+ return e.dateRange;
299
+ }
300
+ function ie() {
301
+ const { state: e } = o();
302
+ return e.realTime;
303
+ }
304
+ function de() {
305
+ const { state: e } = o();
306
+ return e.deviceObject;
307
+ }
308
+ function Te() {
309
+ const { state: e } = o();
310
+ return e.dashboardObject;
311
+ }
312
+ function ue() {
313
+ const { state: e } = o();
314
+ return e.widget;
315
+ }
316
+ function _e() {
317
+ const { state: e } = o();
318
+ return e.selectedDeviceObjects;
319
+ }
320
+ function le() {
321
+ const { state: e } = o();
322
+ return e.selectedFilters;
323
+ }
324
+ function te() {
325
+ return o().actions;
326
+ }
327
+ function Se() {
328
+ const e = Z(), t = A(null), [E, s] = M(!1);
329
+ return C(() => {
330
+ !t.current && h && (t.current = h);
331
+ }, []), C(() => {
332
+ t.current && e && !E && (t.current.Auth.authenticate(e), s(!0));
333
+ }, [e, E]), !E || !t.current ? null : t.current;
334
+ }
335
+ function Ce(e) {
336
+ return function(E) {
337
+ const s = ee();
338
+ return /* @__PURE__ */ R.createElement(e, c(r({}, E), { selectedDevice: s }));
339
+ };
340
+ }
341
+ function Ae(e) {
342
+ return function(E) {
343
+ const s = te();
344
+ return /* @__PURE__ */ R.createElement(e, c(r({}, E), { ubidotsActions: s }));
345
+ };
346
+ }
347
+ function Re(...e) {
348
+ return (t) => e.reduceRight((E, s) => s(E), t);
349
+ }
350
+ export {
351
+ re as UbidotsProvider,
352
+ Re as compose,
353
+ o as useUbidots,
354
+ Se as useUbidotsAPI,
355
+ te as useUbidotsActions,
356
+ De as useUbidotsDashboardDateRange,
357
+ Te as useUbidotsDashboardObject,
358
+ de as useUbidotsDeviceObject,
359
+ ae as useUbidotsJWT,
360
+ ce as useUbidotsReady,
361
+ ie as useUbidotsRealTimeStatus,
362
+ ee as useUbidotsSelectedDevice,
363
+ _e as useUbidotsSelectedDeviceObjects,
364
+ oe as useUbidotsSelectedDevices,
365
+ le as useUbidotsSelectedFilters,
366
+ Z as useUbidotsToken,
367
+ ue as useUbidotsWidget,
368
+ Ce as withSelectedDevice,
369
+ Ae as withUbidotsActions
370
+ };
@@ -0,0 +1 @@
1
+ (function(n,s){typeof exports=="object"&&typeof module!="undefined"?s(exports,require("react"),require("@ubidots/ubidots-javascript-library")):typeof define=="function"&&define.amd?define(["exports","react","@ubidots/ubidots-javascript-library"],s):(n=typeof globalThis!="undefined"?globalThis:n||self,s(n.UbidotsReactHtmlCanvas={},n.React,n.UbidotsJS))})(this,function(n,s,D){"use strict";var ie=Object.defineProperty,oe=Object.defineProperties;var ce=Object.getOwnPropertyDescriptors;var p=Object.getOwnPropertySymbols;var de=Object.prototype.hasOwnProperty,re=Object.prototype.propertyIsEnumerable;var B=(n,s,D)=>s in n?ie(n,s,{enumerable:!0,configurable:!0,writable:!0,value:D}):n[s]=D,c=(n,s)=>{for(var D in s||(s={}))de.call(s,D)&&B(n,D,s[D]);if(p)for(var D of p(s))re.call(s,D)&&B(n,D,s[D]);return n},d=(n,s)=>oe(n,ce(s));const T={RECEIVED_TOKEN:"receivedToken",RECEIVED_JWT_TOKEN:"receivedJWTToken",SELECTED_DEVICE:"selectedDevice",SELECTED_DEVICES:"selectedDevices",SELECTED_DASHBOARD_DATE_RANGE:"selectedDashboardDateRange",SELECTED_DASHBOARD_OBJECT:"selectedDashboardObject",SELECTED_DEVICE_OBJECT:"selectedDeviceObject",SELECTED_DEVICE_OBJECTS:"selectedDeviceObjects",SELECTED_FILTERS:"selectedFilters",IS_REAL_TIME_ACTIVE:"isRealTimeActive"},l={SET_DASHBOARD_DEVICE:"setDashboardDevice",SET_DASHBOARD_MULTIPLE_DEVICES:"setDashboardMultipleDevices",SET_DASHBOARD_DATE_RANGE:"setDashboardDateRange",SET_DASHBOARD_LAYER:"setDashboardLayer",SET_REAL_TIME:"setRealTime",REFRESH_DASHBOARD:"refreshDashboard",OPEN_DRAWER:"openDrawer",SET_FULL_SCREEN:"setFullScreen"},i={RECEIVED_TOKEN:"RECEIVED_TOKEN",RECEIVED_JWT_TOKEN:"RECEIVED_JWT_TOKEN",SELECTED_DEVICE:"SELECTED_DEVICE",SELECTED_DEVICES:"SELECTED_DEVICES",SELECTED_DASHBOARD_DATE_RANGE:"SELECTED_DASHBOARD_DATE_RANGE",SELECTED_DASHBOARD_OBJECT:"SELECTED_DASHBOARD_OBJECT",SELECTED_DEVICE_OBJECT:"SELECTED_DEVICE_OBJECT",SELECTED_DEVICE_OBJECTS:"SELECTED_DEVICE_OBJECTS",SELECTED_FILTERS:"SELECTED_FILTERS",REAL_TIME_STATUS:"REAL_TIME_STATUS",SET_READY:"SET_READY",SET_WIDGET:"SET_WIDGET"},y=["receivedToken"],m={ready:!1,token:null,jwtToken:null,selectedDevice:null,selectedDevices:null,dateRange:null,dashboardObject:null,deviceObject:null,selectedDeviceObjects:null,selectedFilters:null,realTime:null,widget:null},j={[i.RECEIVED_TOKEN]:(e,t)=>d(c({},e),{token:t.payload}),[i.RECEIVED_JWT_TOKEN]:(e,t)=>d(c({},e),{jwtToken:t.payload}),[i.SELECTED_DEVICE]:(e,t)=>d(c({},e),{selectedDevice:t.payload}),[i.SELECTED_DEVICES]:(e,t)=>d(c({},e),{selectedDevices:t.payload}),[i.SELECTED_DASHBOARD_DATE_RANGE]:(e,t)=>d(c({},e),{dateRange:t.payload}),[i.SELECTED_DASHBOARD_OBJECT]:(e,t)=>d(c({},e),{dashboardObject:t.payload}),[i.SELECTED_DEVICE_OBJECT]:(e,t)=>d(c({},e),{deviceObject:t.payload}),[i.SELECTED_DEVICE_OBJECTS]:(e,t)=>d(c({},e),{selectedDeviceObjects:t.payload}),[i.SELECTED_FILTERS]:(e,t)=>d(c({},e),{selectedFilters:t.payload}),[i.REAL_TIME_STATUS]:(e,t)=>d(c({},e),{realTime:t.payload}),[i.SET_READY]:(e,t)=>d(c({},e),{ready:t.payload}),[i.SET_WIDGET]:(e,t)=>d(c({},e),{widget:t.payload})};function w(e,t){const E=j[t.type];return E?E(e,t):e}const g={[T.RECEIVED_TOKEN]:(e,t,E)=>{t({type:i.RECEIVED_TOKEN,payload:e}),E.current.add("receivedToken")},[T.RECEIVED_JWT_TOKEN]:(e,t,E)=>{t({type:i.RECEIVED_JWT_TOKEN,payload:e}),E.current.add("receivedJWTToken")},[T.SELECTED_DEVICE]:(e,t,E)=>{let o=null;if(typeof e=="string"){const u=e.split(",")[0].trim();u&&(o={id:u})}t({type:i.SELECTED_DEVICE,payload:o}),E.current.add("selectedDevice")},[T.SELECTED_DEVICES]:(e,t,E)=>{t({type:i.SELECTED_DEVICES,payload:e}),E.current.add("selectedDevices")},[T.SELECTED_DASHBOARD_DATE_RANGE]:(e,t,E)=>{t({type:i.SELECTED_DASHBOARD_DATE_RANGE,payload:e}),E.current.add("selectedDashboardDateRange")},[T.SELECTED_DASHBOARD_OBJECT]:(e,t,E)=>{t({type:i.SELECTED_DASHBOARD_OBJECT,payload:e}),E.current.add("selectedDashboardObject")},[T.SELECTED_DEVICE_OBJECT]:(e,t,E)=>{t({type:i.SELECTED_DEVICE_OBJECT,payload:e}),E.current.add("selectedDeviceObject")},[T.SELECTED_DEVICE_OBJECTS]:(e,t,E)=>{t({type:i.SELECTED_DEVICE_OBJECTS,payload:e}),E.current.add("selectedDeviceObjects")},[T.SELECTED_FILTERS]:(e,t,E)=>{t({type:i.SELECTED_FILTERS,payload:e}),E.current.add("selectedFilters")},[T.IS_REAL_TIME_ACTIVE]:(e,t,E)=>{t({type:i.REAL_TIME_STATUS,payload:e}),E.current.add("isRealTimeActive")}};function N(e,t,E,o){const u=g[e];u&&u(t,E,o)}function H(e){const t=e.token!==null||e.jwtToken!==null,E=e.selectedDevice!==null,o=e.dateRange!==null,u=e.dashboardObject!==null;return t&&E&&o&&u}function f(e,t,E,o,u,a){if(!E.current){const _=e.every(C=>t.current.has(C)),b=H(u);(_||b)&&(E.current=!0,o({type:i.SET_READY,payload:!0}),a==null||a())}}function S(e,t){typeof window!="undefined"&&window.parent&&window.parent.postMessage({event:e,payload:t},"*")}function J(e,t){return e?{Authorization:`Bearer ${e}`,"Content-type":"application/json"}:t?{"X-Auth-Token":t,"Content-type":"application/json"}:{"Content-type":"application/json"}}function k(e){if(!e||typeof e!="object")return console.error("[setDashboardDateRange] Invalid date range: must be an object"),!1;const{startTime:t,endTime:E}=e;return typeof t!="number"||typeof E!="number"?(console.error("[setDashboardDateRange] Invalid date range: startTime and endTime must be numbers"),!1):t>=E?(console.error(`[setDashboardDateRange] Invalid date range: startTime (${new Date(t).toISOString()}) must be before endTime (${new Date(E).toISOString()})`),!1):!0}const F={setDashboardDevice:e=>S(l.SET_DASHBOARD_DEVICE,e),setDashboardMultipleDevices:e=>S(l.SET_DASHBOARD_MULTIPLE_DEVICES,e),setDashboardDateRange:e=>{k(e)&&S(l.SET_DASHBOARD_DATE_RANGE,e)},setDashboardLayer:e=>S(l.SET_DASHBOARD_LAYER,e),setRealTime:e=>S(l.SET_REAL_TIME,e),refreshDashboard:()=>S(l.REFRESH_DASHBOARD),openDrawer:e=>{const t=typeof window!="undefined"?window.widgetId:"react-widget";S(l.OPEN_DRAWER,{drawerInfo:e,id:t})},setFullScreen:e=>S(l.SET_FULL_SCREEN,e)};function M(e,t){return d(c({},F),{getHeaders:()=>J(e,t)})}const R=s.createContext(void 0);function r(){const e=s.useContext(R);if(!e)throw new Error("useUbidots must be used within UbidotsProvider");return e}function W({children:e,onReady:t,readyEvents:E=y,validateOrigin:o,initialStateOverride:u}){const[a,_]=s.useReducer(w,c(c({},m),u)),b=s.useRef(!1),C=s.useRef(new Set),v=s.useCallback(A=>o?o(A):!0,[o]);s.useEffect(()=>{function A(U){if(!v(U.origin))return;const{event:V,payload:se}=U.data||{};V&&(N(V,se,_,C),f(E,C,b,_,a,t))}return window.addEventListener("message",A),()=>window.removeEventListener("message",A)},[v,t,E,a]),s.useEffect(()=>{f(E,C,b,_,a,t)},[a,E,t]);const h=s.useMemo(()=>M(a.jwtToken,a.token),[a.jwtToken,a.token]),ne=s.useMemo(()=>({state:a,actions:h}),[a,h]);return s.createElement(R.Provider,{value:ne},e)}function P(){const{state:e}=r();return e.ready}function O(){const{state:e}=r();return e.token}function K(){const{state:e}=r();return e.jwtToken}function I(){const{state:e}=r();return e.selectedDevice}function G(){const{state:e}=r();return e.selectedDevices}function Y(){const{state:e}=r();return e.dateRange}function $(){const{state:e}=r();return e.realTime}function q(){const{state:e}=r();return e.deviceObject}function z(){const{state:e}=r();return e.dashboardObject}function X(){const{state:e}=r();return e.widget}function Q(){const{state:e}=r();return e.selectedDeviceObjects}function Z(){const{state:e}=r();return e.selectedFilters}function L(){return r().actions}function x(){const e=O(),t=s.useRef(null),[E,o]=s.useState(!1);return s.useEffect(()=>{!t.current&&D.Ubidots&&(t.current=D.Ubidots)},[]),s.useEffect(()=>{t.current&&e&&!E&&(t.current.Auth.authenticate(e),o(!0))},[e,E]),!E||!t.current?null:t.current}function ee(e){return function(E){const o=I();return s.createElement(e,d(c({},E),{selectedDevice:o}))}}function te(e){return function(E){const o=L();return s.createElement(e,d(c({},E),{ubidotsActions:o}))}}function Ee(...e){return t=>e.reduceRight((E,o)=>o(E),t)}n.UbidotsProvider=W,n.compose=Ee,n.useUbidots=r,n.useUbidotsAPI=x,n.useUbidotsActions=L,n.useUbidotsDashboardDateRange=Y,n.useUbidotsDashboardObject=z,n.useUbidotsDeviceObject=q,n.useUbidotsJWT=K,n.useUbidotsReady=P,n.useUbidotsRealTimeStatus=$,n.useUbidotsSelectedDevice=I,n.useUbidotsSelectedDeviceObjects=Q,n.useUbidotsSelectedDevices=G,n.useUbidotsSelectedFilters=Z,n.useUbidotsToken=O,n.useUbidotsWidget=X,n.withSelectedDevice=ee,n.withUbidotsActions=te,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,96 @@
1
+ export type ReadyEvent = 'receivedToken' | 'receivedJWTToken' | 'selectedDevice' | 'selectedDevices' | 'selectedDashboardDateRange' | 'selectedDashboardObject' | 'selectedDeviceObject' | 'selectedDeviceObjects' | 'selectedFilters' | 'isRealTimeActive';
2
+ export interface Device {
3
+ id: string;
4
+ name?: string;
5
+ label?: string;
6
+ description?: string;
7
+ [k: string]: unknown;
8
+ }
9
+ export interface DateRange {
10
+ startTime: number;
11
+ endTime: number;
12
+ }
13
+ export interface DashboardObject {
14
+ id?: string;
15
+ name?: string;
16
+ [k: string]: unknown;
17
+ }
18
+ export interface DeviceObject {
19
+ id?: string;
20
+ name?: string;
21
+ label?: string;
22
+ [k: string]: unknown;
23
+ }
24
+ export interface WidgetInfo {
25
+ id?: string;
26
+ settings?: Record<string, unknown>;
27
+ }
28
+ export interface FilterValue {
29
+ [k: string]: unknown;
30
+ }
31
+ export interface UbidotsState {
32
+ ready: boolean;
33
+ token: string | null;
34
+ jwtToken: string | null;
35
+ selectedDevice: Device | null;
36
+ selectedDevices: Device[] | null;
37
+ dateRange: DateRange | null;
38
+ dashboardObject: DashboardObject | null;
39
+ deviceObject: DeviceObject | null;
40
+ selectedDeviceObjects: DeviceObject[] | null;
41
+ selectedFilters: FilterValue[] | null;
42
+ realTime: boolean | null;
43
+ widget: WidgetInfo | null;
44
+ }
45
+ export type UbidotsAction = {
46
+ type: 'RECEIVED_TOKEN';
47
+ payload: string;
48
+ } | {
49
+ type: 'RECEIVED_JWT_TOKEN';
50
+ payload: string;
51
+ } | {
52
+ type: 'SELECTED_DEVICE';
53
+ payload: Device | null;
54
+ } | {
55
+ type: 'SELECTED_DEVICES';
56
+ payload: Device[] | null;
57
+ } | {
58
+ type: 'SELECTED_DASHBOARD_DATE_RANGE';
59
+ payload: DateRange | null;
60
+ } | {
61
+ type: 'SELECTED_DASHBOARD_OBJECT';
62
+ payload: DashboardObject | null;
63
+ } | {
64
+ type: 'SELECTED_DEVICE_OBJECT';
65
+ payload: DeviceObject | null;
66
+ } | {
67
+ type: 'SELECTED_DEVICE_OBJECTS';
68
+ payload: DeviceObject[] | null;
69
+ } | {
70
+ type: 'SELECTED_FILTERS';
71
+ payload: FilterValue[] | null;
72
+ } | {
73
+ type: 'REAL_TIME_STATUS';
74
+ payload: boolean | null;
75
+ } | {
76
+ type: 'SET_READY';
77
+ payload: boolean;
78
+ } | {
79
+ type: 'SET_WIDGET';
80
+ payload: WidgetInfo | null;
81
+ };
82
+ export interface OutboundActions {
83
+ setDashboardDevice: (deviceId: string) => void;
84
+ setDashboardMultipleDevices: (deviceIds: string[]) => void;
85
+ setDashboardDateRange: (range: DateRange) => void;
86
+ setDashboardLayer: (layerId: string) => void;
87
+ setRealTime: (rt: boolean) => void;
88
+ refreshDashboard: () => void;
89
+ openDrawer: (opts: {
90
+ url: string;
91
+ width: number;
92
+ }) => void;
93
+ setFullScreen: (setting: 'toggle' | 'enable' | 'disable') => void;
94
+ getHeaders: () => Record<string, string>;
95
+ }
96
+ export type UbidotsActions = OutboundActions;
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "@ubidots/react-html-canvas",
3
+ "version": "0.2.1",
4
+ "description": "React library to interact with Ubidots Dashboards from HTML Canvas widgets (Provider + hooks + actions)",
5
+ "license": "MIT",
6
+ "author": "Ubidots",
7
+ "private": false,
8
+ "type": "module",
9
+ "main": "dist/react-html-canvas.cjs.js",
10
+ "module": "dist/react-html-canvas.es.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/react-html-canvas.es.js",
16
+ "require": "./dist/react-html-canvas.cjs.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "peerDependencies": {
23
+ "@ubidots/ubidots-javascript-library": ">=1.2.1",
24
+ "react": ">=16.8.0",
25
+ "react-dom": ">=16.8.0"
26
+ },
27
+ "devDependencies": {
28
+ "@eslint/js": "9.33.0",
29
+ "@testing-library/jest-dom": "^6.8.0",
30
+ "@testing-library/react": "^16.3.0",
31
+ "@types/jsdom": "^21.1.7",
32
+ "@types/node": "^24.3.0",
33
+ "@types/react": "^18.2.66",
34
+ "@types/react-dom": "^18.2.22",
35
+ "@ubidots/ubidots-javascript-library": "^1.2.1",
36
+ "@vitejs/plugin-react": "^5.0.1",
37
+ "concurrently": "9.2.1",
38
+ "eslint": "9.33.0",
39
+ "eslint-config-prettier": "10.1.8",
40
+ "eslint-plugin-jsx-a11y": "6.10.2",
41
+ "eslint-plugin-prettier": "5.5.4",
42
+ "eslint-plugin-react": "7.37.5",
43
+ "eslint-plugin-react-hooks": "5.2.0",
44
+ "jsdom": "^26.1.0",
45
+ "prettier": "3.6.2",
46
+ "react": "^19.1.1",
47
+ "react-dom": "^19.1.1",
48
+ "rimraf": "^5.0.5",
49
+ "typescript": "^5.4.0",
50
+ "typescript-eslint": "8.40.0",
51
+ "vite": "^5.2.0",
52
+ "vite-plugin-dts": "^4.3.0",
53
+ "vite-tsconfig-paths": "^5.1.4",
54
+ "vitest": "^3.2.4"
55
+ },
56
+ "keywords": [
57
+ "ubidots",
58
+ "react",
59
+ "html-canvas",
60
+ "dashboard",
61
+ "widgets"
62
+ ],
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "git+https://github.com/ubidots/react-html-canvas.git"
66
+ },
67
+ "bugs": {
68
+ "url": "https://github.com/ubidots/react-html-canvas/issues"
69
+ },
70
+ "homepage": "https://github.com/ubidots/react-html-canvas#readme",
71
+ "publishConfig": {
72
+ "access": "public",
73
+ "registry": "https://registry.npmjs.org/"
74
+ },
75
+ "engines": {
76
+ "node": ">=16.0.0",
77
+ "pnpm": ">=8.0.0"
78
+ },
79
+ "scripts": {
80
+ "build": "vite build",
81
+ "build:watch": "vite build --watch",
82
+ "dev": "vite",
83
+ "serve": "python3 -m http.server 8080 --directory dist",
84
+ "serve:tunnel": "pnpm run serve & cloudflared tunnel --url http://localhost:8080",
85
+ "dev:cdn": "concurrently \"pnpm run build:watch\" \"pnpm run serve\"",
86
+ "dev:cdn:tunnel": "concurrently \"pnpm run build:watch\" \"pnpm run serve:tunnel\"",
87
+ "test": "vitest run --reporter=verbose",
88
+ "test:ui": "vitest --ui",
89
+ "typecheck": "tsc --noEmit",
90
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
91
+ "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
92
+ "format": "prettier --write .",
93
+ "format:check": "prettier --check .",
94
+ "clean": "rimraf dist",
95
+ "publish:dry": "pnpm publish --dry-run",
96
+ "publish:beta": "pnpm publish --tag beta",
97
+ "version:patch": "npm version patch",
98
+ "version:minor": "npm version minor",
99
+ "version:major": "npm version major"
100
+ }
101
+ }