@airweave/connect-react 0.9.27
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 +132 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +168 -0
- package/dist/index.js +295 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# @airweave/connect-react
|
|
2
|
+
|
|
3
|
+
React hook for integrating Airweave Connect into your application.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @airweave/connect-react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { useAirweaveConnect } from "@airweave/connect-react";
|
|
15
|
+
|
|
16
|
+
function App() {
|
|
17
|
+
const { open, close, isOpen, isLoading, error, status } = useAirweaveConnect({
|
|
18
|
+
getSessionToken: async () => {
|
|
19
|
+
// Call your backend to get a session token
|
|
20
|
+
const response = await fetch("/api/airweave/session", {
|
|
21
|
+
method: "POST",
|
|
22
|
+
});
|
|
23
|
+
const data = await response.json();
|
|
24
|
+
return data.sessionToken;
|
|
25
|
+
},
|
|
26
|
+
theme: {
|
|
27
|
+
mode: "light", // or 'dark' or 'system'
|
|
28
|
+
},
|
|
29
|
+
onSuccess: (connectionId) => {
|
|
30
|
+
console.log("Connection created:", connectionId);
|
|
31
|
+
},
|
|
32
|
+
onError: (error) => {
|
|
33
|
+
console.error("Error:", error.message);
|
|
34
|
+
},
|
|
35
|
+
onClose: (reason) => {
|
|
36
|
+
console.log("Modal closed:", reason);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<button onClick={open} disabled={isLoading}>
|
|
42
|
+
{isLoading ? "Loading..." : "Connect Apps"}
|
|
43
|
+
</button>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## API Reference
|
|
49
|
+
|
|
50
|
+
### `useAirweaveConnect(options)`
|
|
51
|
+
|
|
52
|
+
#### Options
|
|
53
|
+
|
|
54
|
+
| Option | Type | Required | Description |
|
|
55
|
+
| -------------------- | ---------------------------------------------- | -------- | ---------------------------------------------- |
|
|
56
|
+
| `getSessionToken` | `() => Promise<string>` | Yes | Async function to fetch a session token |
|
|
57
|
+
| `theme` | `ConnectTheme` | No | Theme configuration for the Connect UI |
|
|
58
|
+
| `connectUrl` | `string` | No | URL of the hosted Connect iframe |
|
|
59
|
+
| `onSuccess` | `(connectionId: string) => void` | No | Called when a connection is created |
|
|
60
|
+
| `onError` | `(error: SessionError) => void` | No | Called when an error occurs |
|
|
61
|
+
| `onClose` | `(reason: 'success' \| 'cancel' \| 'error') => void` | No | Called when the modal is closed |
|
|
62
|
+
| `onConnectionCreated`| `(connectionId: string) => void` | No | Called when a new connection is created |
|
|
63
|
+
| `onStatusChange` | `(status: SessionStatus) => void` | No | Called when the session status changes |
|
|
64
|
+
|
|
65
|
+
#### Returns
|
|
66
|
+
|
|
67
|
+
| Property | Type | Description |
|
|
68
|
+
| ----------- | ---------------------- | ------------------------------------ |
|
|
69
|
+
| `open` | `() => void` | Opens the Connect modal |
|
|
70
|
+
| `close` | `() => void` | Closes the Connect modal |
|
|
71
|
+
| `isOpen` | `boolean` | Whether the modal is currently open |
|
|
72
|
+
| `isLoading` | `boolean` | Whether a token is being fetched |
|
|
73
|
+
| `error` | `SessionError \| null` | Current error, if any |
|
|
74
|
+
| `status` | `SessionStatus \| null`| Current session status from iframe |
|
|
75
|
+
|
|
76
|
+
## Theme Customization
|
|
77
|
+
|
|
78
|
+
You can customize the appearance of the Connect modal by passing a theme object:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
const { open } = useAirweaveConnect({
|
|
82
|
+
getSessionToken,
|
|
83
|
+
theme: {
|
|
84
|
+
mode: "dark", // 'light', 'dark', or 'system'
|
|
85
|
+
colors: {
|
|
86
|
+
dark: {
|
|
87
|
+
primary: "#6366f1",
|
|
88
|
+
background: "#0f172a",
|
|
89
|
+
surface: "#1e293b",
|
|
90
|
+
text: "#ffffff",
|
|
91
|
+
textMuted: "#9ca3af",
|
|
92
|
+
border: "#334155",
|
|
93
|
+
success: "#22c55e",
|
|
94
|
+
error: "#ef4444",
|
|
95
|
+
},
|
|
96
|
+
light: {
|
|
97
|
+
primary: "#4f46e5",
|
|
98
|
+
background: "#ffffff",
|
|
99
|
+
surface: "#f8fafc",
|
|
100
|
+
text: "#1f2937",
|
|
101
|
+
textMuted: "#6b7280",
|
|
102
|
+
border: "#e5e7eb",
|
|
103
|
+
success: "#22c55e",
|
|
104
|
+
error: "#ef4444",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Backend Integration
|
|
112
|
+
|
|
113
|
+
Your backend needs to create session tokens by calling the Airweave API:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
POST /connect/sessions
|
|
117
|
+
Headers:
|
|
118
|
+
X-API-Key: your-api-key
|
|
119
|
+
Content-Type: application/json
|
|
120
|
+
Body:
|
|
121
|
+
{
|
|
122
|
+
"readable_collection_id": "your-collection-id",
|
|
123
|
+
"mode": "all",
|
|
124
|
+
"end_user_id": "user-123"
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The response will include a `session_token` that you return from your `getSessionToken` function.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const G=require("airweave-connect/lib/types"),v=require("airweave-connect/lib/connection-utils"),re=require("airweave-connect/lib/icons"),m=require("airweave-connect/lib/theme-defaults"),l=require("react/jsx-runtime"),t=require("react"),ne=require("react-dom/client");function se({connectUrl:o,onClose:n,onIframeRef:a,modalStyle:r,showCloseButton:E=!1}){const[b,R]=t.useState(!1);t.useEffect(()=>{const c=requestAnimationFrame(()=>{R(!0)});return()=>cancelAnimationFrame(c)},[]),t.useEffect(()=>{const c=k=>{k.key==="Escape"&&n()};return document.addEventListener("keydown",c),()=>document.removeEventListener("keydown",c)},[n]);const O=c=>{c.target===c.currentTarget&&n()};return l.jsx("div",{style:{position:"fixed",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(0, 0, 0, 0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e4,opacity:b?1:0,transition:"opacity 0.15s ease-out"},onClick:O,children:l.jsxs("div",{style:{position:"relative",width:(r==null?void 0:r.width)??"90%",maxWidth:(r==null?void 0:r.maxWidth)??"400px",height:(r==null?void 0:r.height)??"80%",maxHeight:(r==null?void 0:r.maxHeight)??"540px",backgroundColor:"white",borderRadius:(r==null?void 0:r.borderRadius)??"16px",overflow:"hidden",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",transform:b?"scale(1) translateY(0)":"scale(0.95) translateY(10px)",opacity:b?1:0,transition:"transform 0.15s ease-out, opacity 0.15s ease-out"},children:[E&&l.jsx("button",{onClick:n,style:{position:"absolute",top:12,right:12,width:32,height:32,border:"none",background:"rgba(0, 0, 0, 0.1)",borderRadius:"50%",cursor:"pointer",fontSize:20,color:"#666",display:"flex",alignItems:"center",justifyContent:"center",zIndex:10,transition:"background 0.2s"},onMouseEnter:c=>{c.currentTarget.style.background="rgba(0, 0, 0, 0.2)"},onMouseLeave:c=>{c.currentTarget.style.background="rgba(0, 0, 0, 0.1)"},"aria-label":"Close",children:"×"}),l.jsx("iframe",{ref:a,src:o,style:{width:"100%",height:"100%",border:"none"},title:"Airweave Connect"})]})})}const W="https://connect.airweave.ai";function oe(o,n){const a=new URL(o);return n!=null&&n.mode&&a.searchParams.set("theme",n.mode),a.toString()}function ce(o){try{return new URL(o).origin}catch{return o}}const ue="airweave-connect-root";function Y(o){const{getSessionToken:n,theme:a,connectUrl:r=W,onSuccess:E,onError:b,onClose:R,onConnectionCreated:O,onStatusChange:c,initialView:k,modalStyle:I,showCloseButton:A=!1}=o,[C,L]=t.useState(!1),[B,N]=t.useState(!1),[Q,x]=t.useState(null),[J,X]=t.useState(null),U=t.useRef(null),T=t.useRef(null),f=t.useRef(null),i=t.useRef(null),w=ce(r),P=t.useRef(n);P.current=n;const g=t.useRef({onSuccess:E,onError:b,onClose:R,onConnectionCreated:O,onStatusChange:c});g.current={onSuccess:E,onError:b,onClose:R,onConnectionCreated:O,onStatusChange:c};const y=t.useRef(a);y.current=a;const j=t.useRef(k);j.current=k;const d=t.useCallback(s=>{var u,e;(e=(u=U.current)==null?void 0:u.contentWindow)==null||e.postMessage(s,w)},[w]),p=t.useCallback((s="cancel")=>{var u,e;L(!1),T.current=null,(e=(u=g.current).onClose)==null||e.call(u,s)},[]);t.useEffect(()=>{if(!C)return;const s=u=>{var h,q,D,F,M,V,S,H;if(u.origin!==w)return;const e=u.data;if(!(!e||typeof e!="object"||!("type"in e)))switch(e.type){case"CONNECT_READY":j.current&&d({type:"NAVIGATE",view:j.current});break;case"REQUEST_TOKEN":{const K=e.requestId;P.current().then(z=>{T.current=z,d({type:"TOKEN_RESPONSE",requestId:K,token:z,theme:y.current})}).catch(()=>{d({type:"TOKEN_ERROR",requestId:K,error:"Failed to refresh session token"})});break}case"STATUS_CHANGE":X(e.status),(q=(h=g.current).onStatusChange)==null||q.call(h,e.status),e.status.status==="error"&&(x(e.status.error),(F=(D=g.current).onError)==null||F.call(D,e.status.error));break;case"CONNECTION_CREATED":(V=(M=g.current).onConnectionCreated)==null||V.call(M,e.connectionId),(H=(S=g.current).onSuccess)==null||H.call(S,e.connectionId);break;case"CLOSE":p(e.reason);break}};return window.addEventListener("message",s),()=>window.removeEventListener("message",s)},[C,p,d,w]);const _=oe(r,a);t.useEffect(()=>{C?(i.current||(i.current=document.createElement("div"),i.current.id=ue,document.body.appendChild(i.current)),f.current||(f.current=ne.createRoot(i.current)),f.current.render(l.jsx(se,{connectUrl:_,onClose:()=>p("cancel"),onIframeRef:s=>{U.current=s},modalStyle:I,showCloseButton:A}))):f.current&&f.current.render(l.jsx(l.Fragment,{}))},[C,_,p,I,A]),t.useEffect(()=>()=>{f.current&&(f.current.unmount(),f.current=null),i.current&&i.current.parentNode&&(i.current.parentNode.removeChild(i.current),i.current=null)},[]);const Z=t.useCallback(async()=>{var s,u;N(!0),x(null);try{const e=await n();T.current=e,L(!0)}catch(e){const h={code:"network_error",message:e instanceof Error?e.message:"Failed to get session token"};x(h),(u=(s=g.current).onError)==null||u.call(s,h)}finally{N(!1)}},[n]),$=t.useCallback(()=>{p("cancel")},[p]),ee=t.useCallback(s=>{y.current=s,d({type:"SET_THEME",theme:s})},[d]),te=t.useCallback(s=>{d({type:"NAVIGATE",view:s})},[d]);return{open:Z,close:$,setTheme:ee,navigate:te,isOpen:C,isLoading:B,error:Q,status:J}}function ae({children:o,...n}){const a=Y(n);return l.jsx(l.Fragment,{children:o(a)})}Object.defineProperty(exports,"canConnect",{enumerable:!0,get:()=>v.canConnect});Object.defineProperty(exports,"getStatusColor",{enumerable:!0,get:()=>v.getStatusColor});Object.defineProperty(exports,"getStatusLabel",{enumerable:!0,get:()=>v.getStatusLabel});Object.defineProperty(exports,"getAppIconUrl",{enumerable:!0,get:()=>re.getAppIconUrl});Object.defineProperty(exports,"defaultDarkColors",{enumerable:!0,get:()=>m.defaultDarkColors});Object.defineProperty(exports,"defaultLabels",{enumerable:!0,get:()=>m.defaultLabels});Object.defineProperty(exports,"defaultLightColors",{enumerable:!0,get:()=>m.defaultLightColors});Object.defineProperty(exports,"defaultOptions",{enumerable:!0,get:()=>m.defaultOptions});exports.AirweaveConnect=ae;exports.DEFAULT_CONNECT_URL=W;exports.useAirweaveConnect=Y;Object.keys(G).forEach(o=>{o!=="default"&&!Object.prototype.hasOwnProperty.call(exports,o)&&Object.defineProperty(exports,o,{enumerable:!0,get:()=>G[o]})});
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/ConnectModal.tsx","../src/constants.ts","../src/iframeUrl.ts","../src/useAirweaveConnect.tsx","../src/AirweaveConnect.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { ModalStyle } from \"./useAirweaveConnect\";\n\ninterface ConnectModalProps {\n connectUrl: string;\n onClose: () => void;\n onIframeRef: (iframe: HTMLIFrameElement | null) => void;\n modalStyle?: ModalStyle;\n showCloseButton?: boolean;\n}\n\nexport function ConnectModal({\n connectUrl,\n onClose,\n onIframeRef,\n modalStyle,\n showCloseButton = false,\n}: ConnectModalProps) {\n const [isVisible, setIsVisible] = useState(false);\n\n // Trigger entry animation after mount\n useEffect(() => {\n // Small delay to ensure the initial styles are applied before transitioning\n const timer = requestAnimationFrame(() => {\n setIsVisible(true);\n });\n return () => cancelAnimationFrame(timer);\n }, []);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [onClose]);\n\n // Handle click outside\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10000,\n opacity: isVisible ? 1 : 0,\n transition: \"opacity 0.15s ease-out\",\n }}\n onClick={handleOverlayClick}\n >\n <div\n style={{\n position: \"relative\",\n width: modalStyle?.width ?? \"90%\",\n maxWidth: modalStyle?.maxWidth ?? \"400px\",\n height: modalStyle?.height ?? \"80%\",\n maxHeight: modalStyle?.maxHeight ?? \"540px\",\n backgroundColor: \"white\",\n borderRadius: modalStyle?.borderRadius ?? \"16px\",\n overflow: \"hidden\",\n boxShadow: \"0 25px 50px -12px rgba(0, 0, 0, 0.25)\",\n transform: isVisible\n ? \"scale(1) translateY(0)\"\n : \"scale(0.95) translateY(10px)\",\n opacity: isVisible ? 1 : 0,\n transition: \"transform 0.15s ease-out, opacity 0.15s ease-out\",\n }}\n >\n {showCloseButton && (\n <button\n onClick={onClose}\n style={{\n position: \"absolute\",\n top: 12,\n right: 12,\n width: 32,\n height: 32,\n border: \"none\",\n background: \"rgba(0, 0, 0, 0.1)\",\n borderRadius: \"50%\",\n cursor: \"pointer\",\n fontSize: 20,\n color: \"#666\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"background 0.2s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.2)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.1)\";\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\n )}\n <iframe\n ref={onIframeRef}\n src={connectUrl}\n style={{\n width: \"100%\",\n height: \"100%\",\n border: \"none\",\n }}\n title=\"Airweave Connect\"\n />\n </div>\n </div>\n );\n}\n","export const DEFAULT_CONNECT_URL = \"https://connect.airweave.ai\";\n","import type { ConnectTheme } from \"airweave-connect/lib/types\";\n\n/**\n * Builds the iframe URL with theme query parameter.\n */\nexport function buildIframeUrl(connectUrl: string, theme?: ConnectTheme): string {\n const url = new URL(connectUrl);\n if (theme?.mode) {\n url.searchParams.set(\"theme\", theme.mode);\n }\n return url.toString();\n}\n\n/**\n * Derives the expected origin from a connect URL for secure postMessage validation.\n */\nexport function getExpectedOrigin(connectUrl: string): string {\n try {\n const url = new URL(connectUrl);\n return url.origin;\n } catch {\n // Fallback for invalid URLs - will cause postMessage to fail safely\n return connectUrl;\n }\n}\n","import type {\n ChildToParentMessage,\n ConnectTheme,\n NavigateView,\n ParentToChildMessage,\n SessionError,\n SessionStatus,\n} from \"airweave-connect/lib/types\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport { ConnectModal } from \"./ConnectModal\";\nimport { DEFAULT_CONNECT_URL } from \"./constants\";\nimport { buildIframeUrl, getExpectedOrigin } from \"./iframeUrl\";\nimport type {\n UseAirweaveConnectOptions,\n UseAirweaveConnectReturn,\n} from \"./useAirweaveConnect.types\";\n\n// Re-export types for consumers\nexport type { ModalStyle, UseAirweaveConnectOptions, UseAirweaveConnectReturn } from \"./useAirweaveConnect.types\";\n\nconst CONTAINER_ID = \"airweave-connect-root\";\n\nexport function useAirweaveConnect(\n options: UseAirweaveConnectOptions,\n): UseAirweaveConnectReturn {\n const {\n getSessionToken,\n theme,\n connectUrl = DEFAULT_CONNECT_URL,\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n initialView,\n modalStyle,\n showCloseButton = false,\n } = options;\n\n const [isOpen, setIsOpen] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<SessionError | null>(null);\n const [status, setStatus] = useState<SessionStatus | null>(null);\n\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const sessionTokenRef = useRef<string | null>(null);\n const rootRef = useRef<Root | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Derive expected origin from connectUrl for secure postMessage\n const expectedOrigin = getExpectedOrigin(connectUrl);\n\n // Store callbacks and getSessionToken in refs to avoid re-creating message handler\n const getSessionTokenRef = useRef(getSessionToken);\n getSessionTokenRef.current = getSessionToken;\n\n const callbacksRef = useRef({\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n });\n callbacksRef.current = {\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n };\n\n // Store theme in ref to use in message handler\n const themeRef = useRef(theme);\n themeRef.current = theme;\n\n // Store initialView in ref to use on CONNECT_READY\n const initialViewRef = useRef(initialView);\n initialViewRef.current = initialView;\n\n // Send message to iframe with restricted origin\n const sendToIframe = useCallback(\n (message: ParentToChildMessage) => {\n iframeRef.current?.contentWindow?.postMessage(message, expectedOrigin);\n },\n [expectedOrigin],\n );\n\n const handleClose = useCallback(\n (reason: \"success\" | \"cancel\" | \"error\" = \"cancel\") => {\n setIsOpen(false);\n sessionTokenRef.current = null;\n callbacksRef.current.onClose?.(reason);\n },\n [],\n );\n\n // Handle messages from iframe\n useEffect(() => {\n if (!isOpen) return;\n\n const handleMessage = (event: MessageEvent) => {\n // Validate origin to prevent spoofed messages from malicious sites\n if (event.origin !== expectedOrigin) {\n return;\n }\n\n const data = event.data as ChildToParentMessage;\n if (!data || typeof data !== \"object\" || !(\"type\" in data)) {\n return;\n }\n\n switch (data.type) {\n case \"CONNECT_READY\":\n // Iframe is ready - navigate to initial view if specified\n if (initialViewRef.current) {\n sendToIframe({ type: \"NAVIGATE\", view: initialViewRef.current });\n }\n break;\n\n case \"REQUEST_TOKEN\": {\n // Re-fetch token from the customer's backend to handle expiry/refresh\n const requestId = data.requestId;\n getSessionTokenRef\n .current()\n .then((token) => {\n sessionTokenRef.current = token;\n sendToIframe({\n type: \"TOKEN_RESPONSE\",\n requestId,\n token,\n theme: themeRef.current,\n });\n })\n .catch(() => {\n sendToIframe({\n type: \"TOKEN_ERROR\",\n requestId,\n error: \"Failed to refresh session token\",\n });\n });\n break;\n }\n\n case \"STATUS_CHANGE\":\n setStatus(data.status);\n callbacksRef.current.onStatusChange?.(data.status);\n\n if (data.status.status === \"error\") {\n setError(data.status.error);\n callbacksRef.current.onError?.(data.status.error);\n }\n break;\n\n case \"CONNECTION_CREATED\":\n callbacksRef.current.onConnectionCreated?.(data.connectionId);\n callbacksRef.current.onSuccess?.(data.connectionId);\n break;\n\n case \"CLOSE\":\n handleClose(data.reason);\n break;\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [isOpen, handleClose, sendToIframe, expectedOrigin]);\n\n // Build the iframe URL with theme query parameter\n const iframeUrl = buildIframeUrl(connectUrl, theme);\n\n // Manage modal rendering via createRoot\n useEffect(() => {\n if (isOpen) {\n // Create container if it doesn't exist\n if (!containerRef.current) {\n containerRef.current = document.createElement(\"div\");\n containerRef.current.id = CONTAINER_ID;\n document.body.appendChild(containerRef.current);\n }\n\n // Create root if it doesn't exist\n if (!rootRef.current) {\n rootRef.current = createRoot(containerRef.current);\n }\n\n // Render modal\n rootRef.current.render(\n <ConnectModal\n connectUrl={iframeUrl}\n onClose={() => handleClose(\"cancel\")}\n onIframeRef={(iframe) => {\n iframeRef.current = iframe;\n }}\n modalStyle={modalStyle}\n showCloseButton={showCloseButton}\n />,\n );\n } else {\n // Unmount modal\n if (rootRef.current) {\n rootRef.current.render(<></>);\n }\n }\n }, [isOpen, iframeUrl, handleClose, modalStyle, showCloseButton]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (rootRef.current) {\n rootRef.current.unmount();\n rootRef.current = null;\n }\n if (containerRef.current && containerRef.current.parentNode) {\n containerRef.current.parentNode.removeChild(containerRef.current);\n containerRef.current = null;\n }\n };\n }, []);\n\n const open = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getSessionToken();\n sessionTokenRef.current = token;\n setIsOpen(true);\n } catch (err) {\n const sessionError: SessionError = {\n code: \"network_error\",\n message:\n err instanceof Error ? err.message : \"Failed to get session token\",\n };\n setError(sessionError);\n callbacksRef.current.onError?.(sessionError);\n } finally {\n setIsLoading(false);\n }\n }, [getSessionToken]);\n\n const close = useCallback(() => {\n handleClose(\"cancel\");\n }, [handleClose]);\n\n const setTheme = useCallback(\n (newTheme: ConnectTheme) => {\n themeRef.current = newTheme;\n sendToIframe({ type: \"SET_THEME\", theme: newTheme });\n },\n [sendToIframe],\n );\n\n const navigate = useCallback(\n (view: NavigateView) => {\n sendToIframe({ type: \"NAVIGATE\", view });\n },\n [sendToIframe],\n );\n\n return {\n open,\n close,\n setTheme,\n navigate,\n isOpen,\n isLoading,\n error,\n status,\n };\n}\n","import type { ReactNode } from \"react\";\nimport {\n useAirweaveConnect,\n type UseAirweaveConnectOptions,\n type UseAirweaveConnectReturn,\n} from \"./useAirweaveConnect\";\n\ntype RenderProps = UseAirweaveConnectReturn;\n\nexport interface AirweaveConnectProps extends UseAirweaveConnectOptions {\n /**\n * Render prop that receives all hook return values.\n * Use this to render your trigger button or any custom UI.\n *\n * @example\n * ```tsx\n * <AirweaveConnect getSessionToken={fetchToken}>\n * {({ open, isLoading }) => (\n * <button onClick={open} disabled={isLoading}>\n * {isLoading ? \"Loading...\" : \"Connect\"}\n * </button>\n * )}\n * </AirweaveConnect>\n * ```\n */\n children: (props: RenderProps) => ReactNode;\n}\n\n/**\n * A component wrapper for the useAirweaveConnect hook.\n * Provides a simpler API for common use cases.\n *\n * @example\n * ```tsx\n * // Simple usage\n * <AirweaveConnect\n * getSessionToken={async () => {\n * const res = await fetch(\"/api/connect-session\");\n * const data = await res.json();\n * return data.session_token;\n * }}\n * onSuccess={(connectionId) => {\n * console.log(\"New connection:\", connectionId);\n * }}\n * >\n * {({ open, isLoading }) => (\n * <button onClick={open} disabled={isLoading}>\n * {isLoading ? \"Connecting...\" : \"Connect Apps\"}\n * </button>\n * )}\n * </AirweaveConnect>\n *\n * // With all features\n * <AirweaveConnect\n * getSessionToken={fetchToken}\n * initialView=\"sources\"\n * showCloseButton\n * modalStyle={{ maxWidth: \"600px\" }}\n * onSuccess={handleSuccess}\n * onClose={(reason) => console.log(\"Closed:\", reason)}\n * >\n * {({ open, isLoading, isOpen, navigate }) => (\n * <div>\n * <button onClick={open} disabled={isLoading || isOpen}>\n * {isLoading ? \"Preparing...\" : \"Connect Apps\"}\n * </button>\n * {isOpen && (\n * <button onClick={() => navigate(\"sources\")}>\n * Browse Sources\n * </button>\n * )}\n * </div>\n * )}\n * </AirweaveConnect>\n * ```\n */\nexport function AirweaveConnect({\n children,\n ...hookOptions\n}: AirweaveConnectProps) {\n const hookReturn = useAirweaveConnect(hookOptions);\n return <>{children(hookReturn)}</>;\n}\n"],"names":["ConnectModal","connectUrl","onClose","onIframeRef","modalStyle","showCloseButton","isVisible","setIsVisible","useState","useEffect","timer","handleKeyDown","e","handleOverlayClick","jsx","jsxs","DEFAULT_CONNECT_URL","buildIframeUrl","theme","url","getExpectedOrigin","CONTAINER_ID","useAirweaveConnect","options","getSessionToken","onSuccess","onError","onConnectionCreated","onStatusChange","initialView","isOpen","setIsOpen","isLoading","setIsLoading","error","setError","status","setStatus","iframeRef","useRef","sessionTokenRef","rootRef","containerRef","expectedOrigin","getSessionTokenRef","callbacksRef","themeRef","initialViewRef","sendToIframe","useCallback","message","_b","_a","handleClose","reason","handleMessage","event","data","requestId","token","_d","_c","_f","_e","_h","_g","iframeUrl","createRoot","iframe","Fragment","open","err","sessionError","close","setTheme","newTheme","navigate","view","AirweaveConnect","children","hookOptions","hookReturn"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { canConnect } from 'airweave-connect/lib/connection-utils';
|
|
2
|
+
import { ConnectTheme } from 'airweave-connect/lib/types';
|
|
3
|
+
import { defaultDarkColors } from 'airweave-connect/lib/theme-defaults';
|
|
4
|
+
import { defaultLabels } from 'airweave-connect/lib/theme-defaults';
|
|
5
|
+
import { defaultLightColors } from 'airweave-connect/lib/theme-defaults';
|
|
6
|
+
import { defaultOptions } from 'airweave-connect/lib/theme-defaults';
|
|
7
|
+
import { getAppIconUrl } from 'airweave-connect/lib/icons';
|
|
8
|
+
import { getStatusColor } from 'airweave-connect/lib/connection-utils';
|
|
9
|
+
import { getStatusLabel } from 'airweave-connect/lib/connection-utils';
|
|
10
|
+
import { JSX } from 'react/jsx-runtime';
|
|
11
|
+
import { NavigateView } from 'airweave-connect/lib/types';
|
|
12
|
+
import { ReactNode } from 'react';
|
|
13
|
+
import { SessionError } from 'airweave-connect/lib/types';
|
|
14
|
+
import { SessionStatus } from 'airweave-connect/lib/types';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A component wrapper for the useAirweaveConnect hook.
|
|
18
|
+
* Provides a simpler API for common use cases.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // Simple usage
|
|
23
|
+
* <AirweaveConnect
|
|
24
|
+
* getSessionToken={async () => {
|
|
25
|
+
* const res = await fetch("/api/connect-session");
|
|
26
|
+
* const data = await res.json();
|
|
27
|
+
* return data.session_token;
|
|
28
|
+
* }}
|
|
29
|
+
* onSuccess={(connectionId) => {
|
|
30
|
+
* console.log("New connection:", connectionId);
|
|
31
|
+
* }}
|
|
32
|
+
* >
|
|
33
|
+
* {({ open, isLoading }) => (
|
|
34
|
+
* <button onClick={open} disabled={isLoading}>
|
|
35
|
+
* {isLoading ? "Connecting..." : "Connect Apps"}
|
|
36
|
+
* </button>
|
|
37
|
+
* )}
|
|
38
|
+
* </AirweaveConnect>
|
|
39
|
+
*
|
|
40
|
+
* // With all features
|
|
41
|
+
* <AirweaveConnect
|
|
42
|
+
* getSessionToken={fetchToken}
|
|
43
|
+
* initialView="sources"
|
|
44
|
+
* showCloseButton
|
|
45
|
+
* modalStyle={{ maxWidth: "600px" }}
|
|
46
|
+
* onSuccess={handleSuccess}
|
|
47
|
+
* onClose={(reason) => console.log("Closed:", reason)}
|
|
48
|
+
* >
|
|
49
|
+
* {({ open, isLoading, isOpen, navigate }) => (
|
|
50
|
+
* <div>
|
|
51
|
+
* <button onClick={open} disabled={isLoading || isOpen}>
|
|
52
|
+
* {isLoading ? "Preparing..." : "Connect Apps"}
|
|
53
|
+
* </button>
|
|
54
|
+
* {isOpen && (
|
|
55
|
+
* <button onClick={() => navigate("sources")}>
|
|
56
|
+
* Browse Sources
|
|
57
|
+
* </button>
|
|
58
|
+
* )}
|
|
59
|
+
* </div>
|
|
60
|
+
* )}
|
|
61
|
+
* </AirweaveConnect>
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function AirweaveConnect({ children, ...hookOptions }: AirweaveConnectProps): JSX.Element;
|
|
65
|
+
|
|
66
|
+
export declare interface AirweaveConnectProps extends UseAirweaveConnectOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Render prop that receives all hook return values.
|
|
69
|
+
* Use this to render your trigger button or any custom UI.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```tsx
|
|
73
|
+
* <AirweaveConnect getSessionToken={fetchToken}>
|
|
74
|
+
* {({ open, isLoading }) => (
|
|
75
|
+
* <button onClick={open} disabled={isLoading}>
|
|
76
|
+
* {isLoading ? "Loading..." : "Connect"}
|
|
77
|
+
* </button>
|
|
78
|
+
* )}
|
|
79
|
+
* </AirweaveConnect>
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
children: (props: RenderProps) => ReactNode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { canConnect }
|
|
86
|
+
|
|
87
|
+
export declare const DEFAULT_CONNECT_URL = "https://connect.airweave.ai";
|
|
88
|
+
|
|
89
|
+
export { defaultDarkColors }
|
|
90
|
+
|
|
91
|
+
export { defaultLabels }
|
|
92
|
+
|
|
93
|
+
export { defaultLightColors }
|
|
94
|
+
|
|
95
|
+
export { defaultOptions }
|
|
96
|
+
|
|
97
|
+
export { getAppIconUrl }
|
|
98
|
+
|
|
99
|
+
export { getStatusColor }
|
|
100
|
+
|
|
101
|
+
export { getStatusLabel }
|
|
102
|
+
|
|
103
|
+
/** Modal styling options */
|
|
104
|
+
export declare interface ModalStyle {
|
|
105
|
+
/** Modal width (default: "90%") */
|
|
106
|
+
width?: string;
|
|
107
|
+
/** Modal max width (default: "400px") */
|
|
108
|
+
maxWidth?: string;
|
|
109
|
+
/** Modal height (default: "80%") */
|
|
110
|
+
height?: string;
|
|
111
|
+
/** Modal max height (default: "540px") */
|
|
112
|
+
maxHeight?: string;
|
|
113
|
+
/** Modal border radius (default: "16px") */
|
|
114
|
+
borderRadius?: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
declare type RenderProps = UseAirweaveConnectReturn;
|
|
118
|
+
|
|
119
|
+
export declare function useAirweaveConnect(options: UseAirweaveConnectOptions): UseAirweaveConnectReturn;
|
|
120
|
+
|
|
121
|
+
export declare interface UseAirweaveConnectOptions {
|
|
122
|
+
/** Async function to get a session token from your backend */
|
|
123
|
+
getSessionToken: () => Promise<string>;
|
|
124
|
+
/** Theme configuration for the Connect UI */
|
|
125
|
+
theme?: ConnectTheme;
|
|
126
|
+
/** URL of the hosted Connect iframe (defaults to Airweave hosted) */
|
|
127
|
+
connectUrl?: string;
|
|
128
|
+
/** Called when a connection is successfully created */
|
|
129
|
+
onSuccess?: (connectionId: string) => void;
|
|
130
|
+
/** Called when an error occurs */
|
|
131
|
+
onError?: (error: SessionError) => void;
|
|
132
|
+
/** Called when the modal is closed */
|
|
133
|
+
onClose?: (reason: "success" | "cancel" | "error") => void;
|
|
134
|
+
/** Called when a new connection is created */
|
|
135
|
+
onConnectionCreated?: (connectionId: string) => void;
|
|
136
|
+
/** Called when the session status changes */
|
|
137
|
+
onStatusChange?: (status: SessionStatus) => void;
|
|
138
|
+
/** Initial view to show when modal opens (default: shows connections or sources based on mode) */
|
|
139
|
+
initialView?: NavigateView;
|
|
140
|
+
/** Custom modal styling */
|
|
141
|
+
modalStyle?: ModalStyle;
|
|
142
|
+
/** Show a close button in the modal (default: false) */
|
|
143
|
+
showCloseButton?: boolean;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export declare interface UseAirweaveConnectReturn {
|
|
147
|
+
/** Open the Connect modal */
|
|
148
|
+
open: () => void;
|
|
149
|
+
/** Close the Connect modal */
|
|
150
|
+
close: () => void;
|
|
151
|
+
/** Dynamically update theme/labels while modal is open */
|
|
152
|
+
setTheme: (theme: ConnectTheme) => void;
|
|
153
|
+
/** Navigate to a specific view within the modal */
|
|
154
|
+
navigate: (view: NavigateView) => void;
|
|
155
|
+
/** Whether the modal is currently open */
|
|
156
|
+
isOpen: boolean;
|
|
157
|
+
/** Whether a token is being fetched */
|
|
158
|
+
isLoading: boolean;
|
|
159
|
+
/** Current error, if any */
|
|
160
|
+
error: SessionError | null;
|
|
161
|
+
/** Current session status from the iframe */
|
|
162
|
+
status: SessionStatus | null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
export * from "airweave-connect/lib/types";
|
|
167
|
+
|
|
168
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
export * from "airweave-connect/lib/types";
|
|
2
|
+
import { canConnect as Ce, getStatusColor as Ee, getStatusLabel as be } from "airweave-connect/lib/connection-utils";
|
|
3
|
+
import { getAppIconUrl as we } from "airweave-connect/lib/icons";
|
|
4
|
+
import { defaultDarkColors as Re, defaultLabels as me, defaultLightColors as Te, defaultOptions as ve } from "airweave-connect/lib/theme-defaults";
|
|
5
|
+
import { jsx as C, jsxs as re, Fragment as P } from "react/jsx-runtime";
|
|
6
|
+
import { useState as k, useEffect as w, useRef as l, useCallback as h } from "react";
|
|
7
|
+
import { createRoot as te } from "react-dom/client";
|
|
8
|
+
function ne({
|
|
9
|
+
connectUrl: c,
|
|
10
|
+
onClose: t,
|
|
11
|
+
onIframeRef: i,
|
|
12
|
+
modalStyle: r,
|
|
13
|
+
showCloseButton: x = !1
|
|
14
|
+
}) {
|
|
15
|
+
const [g, R] = k(!1);
|
|
16
|
+
return w(() => {
|
|
17
|
+
const o = requestAnimationFrame(() => {
|
|
18
|
+
R(!0);
|
|
19
|
+
});
|
|
20
|
+
return () => cancelAnimationFrame(o);
|
|
21
|
+
}, []), w(() => {
|
|
22
|
+
const o = (m) => {
|
|
23
|
+
m.key === "Escape" && t();
|
|
24
|
+
};
|
|
25
|
+
return document.addEventListener("keydown", o), () => document.removeEventListener("keydown", o);
|
|
26
|
+
}, [t]), /* @__PURE__ */ C(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
style: {
|
|
30
|
+
position: "fixed",
|
|
31
|
+
top: 0,
|
|
32
|
+
left: 0,
|
|
33
|
+
right: 0,
|
|
34
|
+
bottom: 0,
|
|
35
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
36
|
+
display: "flex",
|
|
37
|
+
alignItems: "center",
|
|
38
|
+
justifyContent: "center",
|
|
39
|
+
zIndex: 1e4,
|
|
40
|
+
opacity: g ? 1 : 0,
|
|
41
|
+
transition: "opacity 0.15s ease-out"
|
|
42
|
+
},
|
|
43
|
+
onClick: (o) => {
|
|
44
|
+
o.target === o.currentTarget && t();
|
|
45
|
+
},
|
|
46
|
+
children: /* @__PURE__ */ re(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
style: {
|
|
50
|
+
position: "relative",
|
|
51
|
+
width: (r == null ? void 0 : r.width) ?? "90%",
|
|
52
|
+
maxWidth: (r == null ? void 0 : r.maxWidth) ?? "400px",
|
|
53
|
+
height: (r == null ? void 0 : r.height) ?? "80%",
|
|
54
|
+
maxHeight: (r == null ? void 0 : r.maxHeight) ?? "540px",
|
|
55
|
+
backgroundColor: "white",
|
|
56
|
+
borderRadius: (r == null ? void 0 : r.borderRadius) ?? "16px",
|
|
57
|
+
overflow: "hidden",
|
|
58
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
59
|
+
transform: g ? "scale(1) translateY(0)" : "scale(0.95) translateY(10px)",
|
|
60
|
+
opacity: g ? 1 : 0,
|
|
61
|
+
transition: "transform 0.15s ease-out, opacity 0.15s ease-out"
|
|
62
|
+
},
|
|
63
|
+
children: [
|
|
64
|
+
x && /* @__PURE__ */ C(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
onClick: t,
|
|
68
|
+
style: {
|
|
69
|
+
position: "absolute",
|
|
70
|
+
top: 12,
|
|
71
|
+
right: 12,
|
|
72
|
+
width: 32,
|
|
73
|
+
height: 32,
|
|
74
|
+
border: "none",
|
|
75
|
+
background: "rgba(0, 0, 0, 0.1)",
|
|
76
|
+
borderRadius: "50%",
|
|
77
|
+
cursor: "pointer",
|
|
78
|
+
fontSize: 20,
|
|
79
|
+
color: "#666",
|
|
80
|
+
display: "flex",
|
|
81
|
+
alignItems: "center",
|
|
82
|
+
justifyContent: "center",
|
|
83
|
+
zIndex: 10,
|
|
84
|
+
transition: "background 0.2s"
|
|
85
|
+
},
|
|
86
|
+
onMouseEnter: (o) => {
|
|
87
|
+
o.currentTarget.style.background = "rgba(0, 0, 0, 0.2)";
|
|
88
|
+
},
|
|
89
|
+
onMouseLeave: (o) => {
|
|
90
|
+
o.currentTarget.style.background = "rgba(0, 0, 0, 0.1)";
|
|
91
|
+
},
|
|
92
|
+
"aria-label": "Close",
|
|
93
|
+
children: "×"
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
/* @__PURE__ */ C(
|
|
97
|
+
"iframe",
|
|
98
|
+
{
|
|
99
|
+
ref: i,
|
|
100
|
+
src: c,
|
|
101
|
+
style: {
|
|
102
|
+
width: "100%",
|
|
103
|
+
height: "100%",
|
|
104
|
+
border: "none"
|
|
105
|
+
},
|
|
106
|
+
title: "Airweave Connect"
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
const oe = "https://connect.airweave.ai";
|
|
116
|
+
function se(c, t) {
|
|
117
|
+
const i = new URL(c);
|
|
118
|
+
return t != null && t.mode && i.searchParams.set("theme", t.mode), i.toString();
|
|
119
|
+
}
|
|
120
|
+
function ce(c) {
|
|
121
|
+
try {
|
|
122
|
+
return new URL(c).origin;
|
|
123
|
+
} catch {
|
|
124
|
+
return c;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const ie = "airweave-connect-root";
|
|
128
|
+
function ae(c) {
|
|
129
|
+
const {
|
|
130
|
+
getSessionToken: t,
|
|
131
|
+
theme: i,
|
|
132
|
+
connectUrl: r = oe,
|
|
133
|
+
onSuccess: x,
|
|
134
|
+
onError: g,
|
|
135
|
+
onClose: R,
|
|
136
|
+
onConnectionCreated: v,
|
|
137
|
+
onStatusChange: o,
|
|
138
|
+
initialView: m,
|
|
139
|
+
modalStyle: L,
|
|
140
|
+
showCloseButton: _ = !1
|
|
141
|
+
} = c, [E, y] = k(!1), [B, U] = k(!1), [Q, I] = k(null), [J, X] = k(null), D = l(null), N = l(null), u = l(null), a = l(null), T = ce(r), F = l(t);
|
|
142
|
+
F.current = t;
|
|
143
|
+
const d = l({
|
|
144
|
+
onSuccess: x,
|
|
145
|
+
onError: g,
|
|
146
|
+
onClose: R,
|
|
147
|
+
onConnectionCreated: v,
|
|
148
|
+
onStatusChange: o
|
|
149
|
+
});
|
|
150
|
+
d.current = {
|
|
151
|
+
onSuccess: x,
|
|
152
|
+
onError: g,
|
|
153
|
+
onClose: R,
|
|
154
|
+
onConnectionCreated: v,
|
|
155
|
+
onStatusChange: o
|
|
156
|
+
};
|
|
157
|
+
const O = l(i);
|
|
158
|
+
O.current = i;
|
|
159
|
+
const A = l(m);
|
|
160
|
+
A.current = m;
|
|
161
|
+
const f = h(
|
|
162
|
+
(n) => {
|
|
163
|
+
var s, e;
|
|
164
|
+
(e = (s = D.current) == null ? void 0 : s.contentWindow) == null || e.postMessage(n, T);
|
|
165
|
+
},
|
|
166
|
+
[T]
|
|
167
|
+
), p = h(
|
|
168
|
+
(n = "cancel") => {
|
|
169
|
+
var s, e;
|
|
170
|
+
y(!1), N.current = null, (e = (s = d.current).onClose) == null || e.call(s, n);
|
|
171
|
+
},
|
|
172
|
+
[]
|
|
173
|
+
);
|
|
174
|
+
w(() => {
|
|
175
|
+
if (!E) return;
|
|
176
|
+
const n = (s) => {
|
|
177
|
+
var b, V, j, H, K, q, z, G;
|
|
178
|
+
if (s.origin !== T)
|
|
179
|
+
return;
|
|
180
|
+
const e = s.data;
|
|
181
|
+
if (!(!e || typeof e != "object" || !("type" in e)))
|
|
182
|
+
switch (e.type) {
|
|
183
|
+
case "CONNECT_READY":
|
|
184
|
+
A.current && f({ type: "NAVIGATE", view: A.current });
|
|
185
|
+
break;
|
|
186
|
+
case "REQUEST_TOKEN": {
|
|
187
|
+
const W = e.requestId;
|
|
188
|
+
F.current().then((Y) => {
|
|
189
|
+
N.current = Y, f({
|
|
190
|
+
type: "TOKEN_RESPONSE",
|
|
191
|
+
requestId: W,
|
|
192
|
+
token: Y,
|
|
193
|
+
theme: O.current
|
|
194
|
+
});
|
|
195
|
+
}).catch(() => {
|
|
196
|
+
f({
|
|
197
|
+
type: "TOKEN_ERROR",
|
|
198
|
+
requestId: W,
|
|
199
|
+
error: "Failed to refresh session token"
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case "STATUS_CHANGE":
|
|
205
|
+
X(e.status), (V = (b = d.current).onStatusChange) == null || V.call(b, e.status), e.status.status === "error" && (I(e.status.error), (H = (j = d.current).onError) == null || H.call(j, e.status.error));
|
|
206
|
+
break;
|
|
207
|
+
case "CONNECTION_CREATED":
|
|
208
|
+
(q = (K = d.current).onConnectionCreated) == null || q.call(K, e.connectionId), (G = (z = d.current).onSuccess) == null || G.call(z, e.connectionId);
|
|
209
|
+
break;
|
|
210
|
+
case "CLOSE":
|
|
211
|
+
p(e.reason);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
return window.addEventListener("message", n), () => window.removeEventListener("message", n);
|
|
216
|
+
}, [E, p, f, T]);
|
|
217
|
+
const M = se(r, i);
|
|
218
|
+
w(() => {
|
|
219
|
+
E ? (a.current || (a.current = document.createElement("div"), a.current.id = ie, document.body.appendChild(a.current)), u.current || (u.current = te(a.current)), u.current.render(
|
|
220
|
+
/* @__PURE__ */ C(
|
|
221
|
+
ne,
|
|
222
|
+
{
|
|
223
|
+
connectUrl: M,
|
|
224
|
+
onClose: () => p("cancel"),
|
|
225
|
+
onIframeRef: (n) => {
|
|
226
|
+
D.current = n;
|
|
227
|
+
},
|
|
228
|
+
modalStyle: L,
|
|
229
|
+
showCloseButton: _
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
)) : u.current && u.current.render(/* @__PURE__ */ C(P, {}));
|
|
233
|
+
}, [E, M, p, L, _]), w(() => () => {
|
|
234
|
+
u.current && (u.current.unmount(), u.current = null), a.current && a.current.parentNode && (a.current.parentNode.removeChild(a.current), a.current = null);
|
|
235
|
+
}, []);
|
|
236
|
+
const Z = h(async () => {
|
|
237
|
+
var n, s;
|
|
238
|
+
U(!0), I(null);
|
|
239
|
+
try {
|
|
240
|
+
const e = await t();
|
|
241
|
+
N.current = e, y(!0);
|
|
242
|
+
} catch (e) {
|
|
243
|
+
const b = {
|
|
244
|
+
code: "network_error",
|
|
245
|
+
message: e instanceof Error ? e.message : "Failed to get session token"
|
|
246
|
+
};
|
|
247
|
+
I(b), (s = (n = d.current).onError) == null || s.call(n, b);
|
|
248
|
+
} finally {
|
|
249
|
+
U(!1);
|
|
250
|
+
}
|
|
251
|
+
}, [t]), $ = h(() => {
|
|
252
|
+
p("cancel");
|
|
253
|
+
}, [p]), S = h(
|
|
254
|
+
(n) => {
|
|
255
|
+
O.current = n, f({ type: "SET_THEME", theme: n });
|
|
256
|
+
},
|
|
257
|
+
[f]
|
|
258
|
+
), ee = h(
|
|
259
|
+
(n) => {
|
|
260
|
+
f({ type: "NAVIGATE", view: n });
|
|
261
|
+
},
|
|
262
|
+
[f]
|
|
263
|
+
);
|
|
264
|
+
return {
|
|
265
|
+
open: Z,
|
|
266
|
+
close: $,
|
|
267
|
+
setTheme: S,
|
|
268
|
+
navigate: ee,
|
|
269
|
+
isOpen: E,
|
|
270
|
+
isLoading: B,
|
|
271
|
+
error: Q,
|
|
272
|
+
status: J
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function de({
|
|
276
|
+
children: c,
|
|
277
|
+
...t
|
|
278
|
+
}) {
|
|
279
|
+
const i = ae(t);
|
|
280
|
+
return /* @__PURE__ */ C(P, { children: c(i) });
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
de as AirweaveConnect,
|
|
284
|
+
oe as DEFAULT_CONNECT_URL,
|
|
285
|
+
Ce as canConnect,
|
|
286
|
+
Re as defaultDarkColors,
|
|
287
|
+
me as defaultLabels,
|
|
288
|
+
Te as defaultLightColors,
|
|
289
|
+
ve as defaultOptions,
|
|
290
|
+
we as getAppIconUrl,
|
|
291
|
+
Ee as getStatusColor,
|
|
292
|
+
be as getStatusLabel,
|
|
293
|
+
ae as useAirweaveConnect
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/ConnectModal.tsx","../src/constants.ts","../src/iframeUrl.ts","../src/useAirweaveConnect.tsx","../src/AirweaveConnect.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { ModalStyle } from \"./useAirweaveConnect\";\n\ninterface ConnectModalProps {\n connectUrl: string;\n onClose: () => void;\n onIframeRef: (iframe: HTMLIFrameElement | null) => void;\n modalStyle?: ModalStyle;\n showCloseButton?: boolean;\n}\n\nexport function ConnectModal({\n connectUrl,\n onClose,\n onIframeRef,\n modalStyle,\n showCloseButton = false,\n}: ConnectModalProps) {\n const [isVisible, setIsVisible] = useState(false);\n\n // Trigger entry animation after mount\n useEffect(() => {\n // Small delay to ensure the initial styles are applied before transitioning\n const timer = requestAnimationFrame(() => {\n setIsVisible(true);\n });\n return () => cancelAnimationFrame(timer);\n }, []);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [onClose]);\n\n // Handle click outside\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10000,\n opacity: isVisible ? 1 : 0,\n transition: \"opacity 0.15s ease-out\",\n }}\n onClick={handleOverlayClick}\n >\n <div\n style={{\n position: \"relative\",\n width: modalStyle?.width ?? \"90%\",\n maxWidth: modalStyle?.maxWidth ?? \"400px\",\n height: modalStyle?.height ?? \"80%\",\n maxHeight: modalStyle?.maxHeight ?? \"540px\",\n backgroundColor: \"white\",\n borderRadius: modalStyle?.borderRadius ?? \"16px\",\n overflow: \"hidden\",\n boxShadow: \"0 25px 50px -12px rgba(0, 0, 0, 0.25)\",\n transform: isVisible\n ? \"scale(1) translateY(0)\"\n : \"scale(0.95) translateY(10px)\",\n opacity: isVisible ? 1 : 0,\n transition: \"transform 0.15s ease-out, opacity 0.15s ease-out\",\n }}\n >\n {showCloseButton && (\n <button\n onClick={onClose}\n style={{\n position: \"absolute\",\n top: 12,\n right: 12,\n width: 32,\n height: 32,\n border: \"none\",\n background: \"rgba(0, 0, 0, 0.1)\",\n borderRadius: \"50%\",\n cursor: \"pointer\",\n fontSize: 20,\n color: \"#666\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 10,\n transition: \"background 0.2s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.2)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"rgba(0, 0, 0, 0.1)\";\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\n )}\n <iframe\n ref={onIframeRef}\n src={connectUrl}\n style={{\n width: \"100%\",\n height: \"100%\",\n border: \"none\",\n }}\n title=\"Airweave Connect\"\n />\n </div>\n </div>\n );\n}\n","export const DEFAULT_CONNECT_URL = \"https://connect.airweave.ai\";\n","import type { ConnectTheme } from \"airweave-connect/lib/types\";\n\n/**\n * Builds the iframe URL with theme query parameter.\n */\nexport function buildIframeUrl(connectUrl: string, theme?: ConnectTheme): string {\n const url = new URL(connectUrl);\n if (theme?.mode) {\n url.searchParams.set(\"theme\", theme.mode);\n }\n return url.toString();\n}\n\n/**\n * Derives the expected origin from a connect URL for secure postMessage validation.\n */\nexport function getExpectedOrigin(connectUrl: string): string {\n try {\n const url = new URL(connectUrl);\n return url.origin;\n } catch {\n // Fallback for invalid URLs - will cause postMessage to fail safely\n return connectUrl;\n }\n}\n","import type {\n ChildToParentMessage,\n ConnectTheme,\n NavigateView,\n ParentToChildMessage,\n SessionError,\n SessionStatus,\n} from \"airweave-connect/lib/types\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport { ConnectModal } from \"./ConnectModal\";\nimport { DEFAULT_CONNECT_URL } from \"./constants\";\nimport { buildIframeUrl, getExpectedOrigin } from \"./iframeUrl\";\nimport type {\n UseAirweaveConnectOptions,\n UseAirweaveConnectReturn,\n} from \"./useAirweaveConnect.types\";\n\n// Re-export types for consumers\nexport type { ModalStyle, UseAirweaveConnectOptions, UseAirweaveConnectReturn } from \"./useAirweaveConnect.types\";\n\nconst CONTAINER_ID = \"airweave-connect-root\";\n\nexport function useAirweaveConnect(\n options: UseAirweaveConnectOptions,\n): UseAirweaveConnectReturn {\n const {\n getSessionToken,\n theme,\n connectUrl = DEFAULT_CONNECT_URL,\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n initialView,\n modalStyle,\n showCloseButton = false,\n } = options;\n\n const [isOpen, setIsOpen] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<SessionError | null>(null);\n const [status, setStatus] = useState<SessionStatus | null>(null);\n\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const sessionTokenRef = useRef<string | null>(null);\n const rootRef = useRef<Root | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Derive expected origin from connectUrl for secure postMessage\n const expectedOrigin = getExpectedOrigin(connectUrl);\n\n // Store callbacks and getSessionToken in refs to avoid re-creating message handler\n const getSessionTokenRef = useRef(getSessionToken);\n getSessionTokenRef.current = getSessionToken;\n\n const callbacksRef = useRef({\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n });\n callbacksRef.current = {\n onSuccess,\n onError,\n onClose,\n onConnectionCreated,\n onStatusChange,\n };\n\n // Store theme in ref to use in message handler\n const themeRef = useRef(theme);\n themeRef.current = theme;\n\n // Store initialView in ref to use on CONNECT_READY\n const initialViewRef = useRef(initialView);\n initialViewRef.current = initialView;\n\n // Send message to iframe with restricted origin\n const sendToIframe = useCallback(\n (message: ParentToChildMessage) => {\n iframeRef.current?.contentWindow?.postMessage(message, expectedOrigin);\n },\n [expectedOrigin],\n );\n\n const handleClose = useCallback(\n (reason: \"success\" | \"cancel\" | \"error\" = \"cancel\") => {\n setIsOpen(false);\n sessionTokenRef.current = null;\n callbacksRef.current.onClose?.(reason);\n },\n [],\n );\n\n // Handle messages from iframe\n useEffect(() => {\n if (!isOpen) return;\n\n const handleMessage = (event: MessageEvent) => {\n // Validate origin to prevent spoofed messages from malicious sites\n if (event.origin !== expectedOrigin) {\n return;\n }\n\n const data = event.data as ChildToParentMessage;\n if (!data || typeof data !== \"object\" || !(\"type\" in data)) {\n return;\n }\n\n switch (data.type) {\n case \"CONNECT_READY\":\n // Iframe is ready - navigate to initial view if specified\n if (initialViewRef.current) {\n sendToIframe({ type: \"NAVIGATE\", view: initialViewRef.current });\n }\n break;\n\n case \"REQUEST_TOKEN\": {\n // Re-fetch token from the customer's backend to handle expiry/refresh\n const requestId = data.requestId;\n getSessionTokenRef\n .current()\n .then((token) => {\n sessionTokenRef.current = token;\n sendToIframe({\n type: \"TOKEN_RESPONSE\",\n requestId,\n token,\n theme: themeRef.current,\n });\n })\n .catch(() => {\n sendToIframe({\n type: \"TOKEN_ERROR\",\n requestId,\n error: \"Failed to refresh session token\",\n });\n });\n break;\n }\n\n case \"STATUS_CHANGE\":\n setStatus(data.status);\n callbacksRef.current.onStatusChange?.(data.status);\n\n if (data.status.status === \"error\") {\n setError(data.status.error);\n callbacksRef.current.onError?.(data.status.error);\n }\n break;\n\n case \"CONNECTION_CREATED\":\n callbacksRef.current.onConnectionCreated?.(data.connectionId);\n callbacksRef.current.onSuccess?.(data.connectionId);\n break;\n\n case \"CLOSE\":\n handleClose(data.reason);\n break;\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [isOpen, handleClose, sendToIframe, expectedOrigin]);\n\n // Build the iframe URL with theme query parameter\n const iframeUrl = buildIframeUrl(connectUrl, theme);\n\n // Manage modal rendering via createRoot\n useEffect(() => {\n if (isOpen) {\n // Create container if it doesn't exist\n if (!containerRef.current) {\n containerRef.current = document.createElement(\"div\");\n containerRef.current.id = CONTAINER_ID;\n document.body.appendChild(containerRef.current);\n }\n\n // Create root if it doesn't exist\n if (!rootRef.current) {\n rootRef.current = createRoot(containerRef.current);\n }\n\n // Render modal\n rootRef.current.render(\n <ConnectModal\n connectUrl={iframeUrl}\n onClose={() => handleClose(\"cancel\")}\n onIframeRef={(iframe) => {\n iframeRef.current = iframe;\n }}\n modalStyle={modalStyle}\n showCloseButton={showCloseButton}\n />,\n );\n } else {\n // Unmount modal\n if (rootRef.current) {\n rootRef.current.render(<></>);\n }\n }\n }, [isOpen, iframeUrl, handleClose, modalStyle, showCloseButton]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (rootRef.current) {\n rootRef.current.unmount();\n rootRef.current = null;\n }\n if (containerRef.current && containerRef.current.parentNode) {\n containerRef.current.parentNode.removeChild(containerRef.current);\n containerRef.current = null;\n }\n };\n }, []);\n\n const open = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const token = await getSessionToken();\n sessionTokenRef.current = token;\n setIsOpen(true);\n } catch (err) {\n const sessionError: SessionError = {\n code: \"network_error\",\n message:\n err instanceof Error ? err.message : \"Failed to get session token\",\n };\n setError(sessionError);\n callbacksRef.current.onError?.(sessionError);\n } finally {\n setIsLoading(false);\n }\n }, [getSessionToken]);\n\n const close = useCallback(() => {\n handleClose(\"cancel\");\n }, [handleClose]);\n\n const setTheme = useCallback(\n (newTheme: ConnectTheme) => {\n themeRef.current = newTheme;\n sendToIframe({ type: \"SET_THEME\", theme: newTheme });\n },\n [sendToIframe],\n );\n\n const navigate = useCallback(\n (view: NavigateView) => {\n sendToIframe({ type: \"NAVIGATE\", view });\n },\n [sendToIframe],\n );\n\n return {\n open,\n close,\n setTheme,\n navigate,\n isOpen,\n isLoading,\n error,\n status,\n };\n}\n","import type { ReactNode } from \"react\";\nimport {\n useAirweaveConnect,\n type UseAirweaveConnectOptions,\n type UseAirweaveConnectReturn,\n} from \"./useAirweaveConnect\";\n\ntype RenderProps = UseAirweaveConnectReturn;\n\nexport interface AirweaveConnectProps extends UseAirweaveConnectOptions {\n /**\n * Render prop that receives all hook return values.\n * Use this to render your trigger button or any custom UI.\n *\n * @example\n * ```tsx\n * <AirweaveConnect getSessionToken={fetchToken}>\n * {({ open, isLoading }) => (\n * <button onClick={open} disabled={isLoading}>\n * {isLoading ? \"Loading...\" : \"Connect\"}\n * </button>\n * )}\n * </AirweaveConnect>\n * ```\n */\n children: (props: RenderProps) => ReactNode;\n}\n\n/**\n * A component wrapper for the useAirweaveConnect hook.\n * Provides a simpler API for common use cases.\n *\n * @example\n * ```tsx\n * // Simple usage\n * <AirweaveConnect\n * getSessionToken={async () => {\n * const res = await fetch(\"/api/connect-session\");\n * const data = await res.json();\n * return data.session_token;\n * }}\n * onSuccess={(connectionId) => {\n * console.log(\"New connection:\", connectionId);\n * }}\n * >\n * {({ open, isLoading }) => (\n * <button onClick={open} disabled={isLoading}>\n * {isLoading ? \"Connecting...\" : \"Connect Apps\"}\n * </button>\n * )}\n * </AirweaveConnect>\n *\n * // With all features\n * <AirweaveConnect\n * getSessionToken={fetchToken}\n * initialView=\"sources\"\n * showCloseButton\n * modalStyle={{ maxWidth: \"600px\" }}\n * onSuccess={handleSuccess}\n * onClose={(reason) => console.log(\"Closed:\", reason)}\n * >\n * {({ open, isLoading, isOpen, navigate }) => (\n * <div>\n * <button onClick={open} disabled={isLoading || isOpen}>\n * {isLoading ? \"Preparing...\" : \"Connect Apps\"}\n * </button>\n * {isOpen && (\n * <button onClick={() => navigate(\"sources\")}>\n * Browse Sources\n * </button>\n * )}\n * </div>\n * )}\n * </AirweaveConnect>\n * ```\n */\nexport function AirweaveConnect({\n children,\n ...hookOptions\n}: AirweaveConnectProps) {\n const hookReturn = useAirweaveConnect(hookOptions);\n return <>{children(hookReturn)}</>;\n}\n"],"names":["ConnectModal","connectUrl","onClose","onIframeRef","modalStyle","showCloseButton","isVisible","setIsVisible","useState","useEffect","timer","handleKeyDown","e","jsx","jsxs","DEFAULT_CONNECT_URL","buildIframeUrl","theme","url","getExpectedOrigin","CONTAINER_ID","useAirweaveConnect","options","getSessionToken","onSuccess","onError","onConnectionCreated","onStatusChange","initialView","isOpen","setIsOpen","isLoading","setIsLoading","error","setError","status","setStatus","iframeRef","useRef","sessionTokenRef","rootRef","containerRef","expectedOrigin","getSessionTokenRef","callbacksRef","themeRef","initialViewRef","sendToIframe","useCallback","message","_b","_a","handleClose","reason","handleMessage","event","data","requestId","token","_d","_c","_f","_e","_h","_g","iframeUrl","createRoot","iframe","Fragment","open","err","sessionError","close","setTheme","newTheme","navigate","view","AirweaveConnect","children","hookOptions","hookReturn"],"mappings":";;;;;;;AAWO,SAASA,GAAa;AAAA,EAC3B,YAAAC;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,YAAAC;AAAA,EACA,iBAAAC,IAAkB;AACpB,GAAsB;AACpB,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAAS,EAAK;AAGhD,SAAAC,EAAU,MAAM;AAEd,UAAMC,IAAQ,sBAAsB,MAAM;AACxC,MAAAH,EAAa,EAAI;AAAA,IACnB,CAAC;AACD,WAAO,MAAM,qBAAqBG,CAAK;AAAA,EACzC,GAAG,CAAA,CAAE,GAGLD,EAAU,MAAM;AACd,UAAME,IAAgB,CAACC,MAAqB;AAC1C,MAAIA,EAAE,QAAQ,YACZV,EAAA;AAAA,IAEJ;AACA,oBAAS,iBAAiB,WAAWS,CAAa,GAC3C,MAAM,SAAS,oBAAoB,WAAWA,CAAa;AAAA,EACpE,GAAG,CAACT,CAAO,CAAC,GAUV,gBAAAW;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,iBAAiB;AAAA,QACjB,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,SAASP,IAAY,IAAI;AAAA,QACzB,YAAY;AAAA,MAAA;AAAA,MAEd,SAtBuB,CAACM,MAAwB;AAClD,QAAIA,EAAE,WAAWA,EAAE,iBACjBV,EAAA;AAAA,MAEJ;AAAA,MAoBI,UAAA,gBAAAY;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,QAAOV,KAAA,gBAAAA,EAAY,UAAS;AAAA,YAC5B,WAAUA,KAAA,gBAAAA,EAAY,aAAY;AAAA,YAClC,SAAQA,KAAA,gBAAAA,EAAY,WAAU;AAAA,YAC9B,YAAWA,KAAA,gBAAAA,EAAY,cAAa;AAAA,YACpC,iBAAiB;AAAA,YACjB,eAAcA,KAAA,gBAAAA,EAAY,iBAAgB;AAAA,YAC1C,UAAU;AAAA,YACV,WAAW;AAAA,YACX,WAAWE,IACP,2BACA;AAAA,YACJ,SAASA,IAAY,IAAI;AAAA,YACzB,YAAY;AAAA,UAAA;AAAA,UAGb,UAAA;AAAA,YAAAD,KACC,gBAAAQ;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAASX;AAAA,gBACT,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,KAAK;AAAA,kBACL,OAAO;AAAA,kBACP,OAAO;AAAA,kBACP,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,YAAY;AAAA,kBACZ,cAAc;AAAA,kBACd,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,OAAO;AAAA,kBACP,SAAS;AAAA,kBACT,YAAY;AAAA,kBACZ,gBAAgB;AAAA,kBAChB,QAAQ;AAAA,kBACR,YAAY;AAAA,gBAAA;AAAA,gBAEd,cAAc,CAACU,MAAM;AACnB,kBAAAA,EAAE,cAAc,MAAM,aAAa;AAAA,gBACrC;AAAA,gBACA,cAAc,CAACA,MAAM;AACnB,kBAAAA,EAAE,cAAc,MAAM,aAAa;AAAA,gBACrC;AAAA,gBACA,cAAW;AAAA,gBACZ,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAIH,gBAAAC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAKV;AAAA,gBACL,KAAKF;AAAA,gBACL,OAAO;AAAA,kBACL,OAAO;AAAA,kBACP,QAAQ;AAAA,kBACR,QAAQ;AAAA,gBAAA;AAAA,gBAEV,OAAM;AAAA,cAAA;AAAA,YAAA;AAAA,UACR;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;AChIO,MAAMc,KAAsB;ACK5B,SAASC,GAAef,GAAoBgB,GAA8B;AAC/E,QAAMC,IAAM,IAAI,IAAIjB,CAAU;AAC9B,SAAIgB,KAAA,QAAAA,EAAO,QACTC,EAAI,aAAa,IAAI,SAASD,EAAM,IAAI,GAEnCC,EAAI,SAAA;AACb;AAKO,SAASC,GAAkBlB,GAA4B;AAC5D,MAAI;AAEF,WADY,IAAI,IAAIA,CAAU,EACnB;AAAA,EACb,QAAQ;AAEN,WAAOA;AAAA,EACT;AACF;ACHA,MAAMmB,KAAe;AAEd,SAASC,GACdC,GAC0B;AAC1B,QAAM;AAAA,IACJ,iBAAAC;AAAA,IACA,OAAAN;AAAA,IACA,YAAAhB,IAAac;AAAA,IACb,WAAAS;AAAA,IACA,SAAAC;AAAA,IACA,SAAAvB;AAAA,IACA,qBAAAwB;AAAA,IACA,gBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,YAAAxB;AAAA,IACA,iBAAAC,IAAkB;AAAA,EAAA,IAChBiB,GAEE,CAACO,GAAQC,CAAS,IAAItB,EAAS,EAAK,GACpC,CAACuB,GAAWC,CAAY,IAAIxB,EAAS,EAAK,GAC1C,CAACyB,GAAOC,CAAQ,IAAI1B,EAA8B,IAAI,GACtD,CAAC2B,GAAQC,CAAS,IAAI5B,EAA+B,IAAI,GAEzD6B,IAAYC,EAAiC,IAAI,GACjDC,IAAkBD,EAAsB,IAAI,GAC5CE,IAAUF,EAAoB,IAAI,GAClCG,IAAeH,EAA8B,IAAI,GAGjDI,IAAiBvB,GAAkBlB,CAAU,GAG7C0C,IAAqBL,EAAOf,CAAe;AACjD,EAAAoB,EAAmB,UAAUpB;AAE7B,QAAMqB,IAAeN,EAAO;AAAA,IAC1B,WAAAd;AAAA,IACA,SAAAC;AAAA,IACA,SAAAvB;AAAA,IACA,qBAAAwB;AAAA,IACA,gBAAAC;AAAA,EAAA,CACD;AACD,EAAAiB,EAAa,UAAU;AAAA,IACrB,WAAApB;AAAA,IACA,SAAAC;AAAA,IACA,SAAAvB;AAAA,IACA,qBAAAwB;AAAA,IACA,gBAAAC;AAAA,EAAA;AAIF,QAAMkB,IAAWP,EAAOrB,CAAK;AAC7B,EAAA4B,EAAS,UAAU5B;AAGnB,QAAM6B,IAAiBR,EAAOV,CAAW;AACzC,EAAAkB,EAAe,UAAUlB;AAGzB,QAAMmB,IAAeC;AAAA,IACnB,CAACC,MAAkC;;AACjC,OAAAC,KAAAC,IAAAd,EAAU,YAAV,gBAAAc,EAAmB,kBAAnB,QAAAD,EAAkC,YAAYD,GAASP;AAAA,IACzD;AAAA,IACA,CAACA,CAAc;AAAA,EAAA,GAGXU,IAAcJ;AAAA,IAClB,CAACK,IAAyC,aAAa;;AACrD,MAAAvB,EAAU,EAAK,GACfS,EAAgB,UAAU,OAC1BW,KAAAC,IAAAP,EAAa,SAAQ,YAArB,QAAAM,EAAA,KAAAC,GAA+BE;AAAA,IACjC;AAAA,IACA,CAAA;AAAA,EAAC;AAIH,EAAA5C,EAAU,MAAM;AACd,QAAI,CAACoB,EAAQ;AAEb,UAAMyB,IAAgB,CAACC,MAAwB;;AAE7C,UAAIA,EAAM,WAAWb;AACnB;AAGF,YAAMc,IAAOD,EAAM;AACnB,UAAI,GAACC,KAAQ,OAAOA,KAAS,YAAY,EAAE,UAAUA;AAIrD,gBAAQA,EAAK,MAAA;AAAA,UACX,KAAK;AAEH,YAAIV,EAAe,WACjBC,EAAa,EAAE,MAAM,YAAY,MAAMD,EAAe,SAAS;AAEjE;AAAA,UAEF,KAAK,iBAAiB;AAEpB,kBAAMW,IAAYD,EAAK;AACvB,YAAAb,EACG,QAAA,EACA,KAAK,CAACe,MAAU;AACf,cAAAnB,EAAgB,UAAUmB,GAC1BX,EAAa;AAAA,gBACX,MAAM;AAAA,gBACN,WAAAU;AAAA,gBACA,OAAAC;AAAA,gBACA,OAAOb,EAAS;AAAA,cAAA,CACjB;AAAA,YACH,CAAC,EACA,MAAM,MAAM;AACX,cAAAE,EAAa;AAAA,gBACX,MAAM;AAAA,gBACN,WAAAU;AAAA,gBACA,OAAO;AAAA,cAAA,CACR;AAAA,YACH,CAAC;AACH;AAAA,UACF;AAAA,UAEA,KAAK;AACH,YAAArB,EAAUoB,EAAK,MAAM,IACrBN,KAAAC,IAAAP,EAAa,SAAQ,mBAArB,QAAAM,EAAA,KAAAC,GAAsCK,EAAK,SAEvCA,EAAK,OAAO,WAAW,YACzBtB,EAASsB,EAAK,OAAO,KAAK,IAC1BG,KAAAC,IAAAhB,EAAa,SAAQ,YAArB,QAAAe,EAAA,KAAAC,GAA+BJ,EAAK,OAAO;AAE7C;AAAA,UAEF,KAAK;AACH,aAAAK,KAAAC,IAAAlB,EAAa,SAAQ,wBAArB,QAAAiB,EAAA,KAAAC,GAA2CN,EAAK,gBAChDO,KAAAC,IAAApB,EAAa,SAAQ,cAArB,QAAAmB,EAAA,KAAAC,GAAiCR,EAAK;AACtC;AAAA,UAEF,KAAK;AACH,YAAAJ,EAAYI,EAAK,MAAM;AACvB;AAAA,QAAA;AAAA,IAEN;AAEA,kBAAO,iBAAiB,WAAWF,CAAa,GACzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAClE,GAAG,CAACzB,GAAQuB,GAAaL,GAAcL,CAAc,CAAC;AAGtD,QAAMuB,IAAYjD,GAAef,GAAYgB,CAAK;AAGlD,EAAAR,EAAU,MAAM;AACd,IAAIoB,KAEGY,EAAa,YAChBA,EAAa,UAAU,SAAS,cAAc,KAAK,GACnDA,EAAa,QAAQ,KAAKrB,IAC1B,SAAS,KAAK,YAAYqB,EAAa,OAAO,IAI3CD,EAAQ,YACXA,EAAQ,UAAU0B,GAAWzB,EAAa,OAAO,IAInDD,EAAQ,QAAQ;AAAA,MACd,gBAAA3B;AAAA,QAACb;AAAA,QAAA;AAAA,UACC,YAAYiE;AAAA,UACZ,SAAS,MAAMb,EAAY,QAAQ;AAAA,UACnC,aAAa,CAACe,MAAW;AACvB,YAAA9B,EAAU,UAAU8B;AAAA,UACtB;AAAA,UACA,YAAA/D;AAAA,UACA,iBAAAC;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,KAIEmC,EAAQ,WACVA,EAAQ,QAAQ,OAAO,gBAAA3B,EAAAuD,GAAA,CAAA,CAAE,CAAG;AAAA,EAGlC,GAAG,CAACvC,GAAQoC,GAAWb,GAAahD,GAAYC,CAAe,CAAC,GAGhEI,EAAU,MACD,MAAM;AACX,IAAI+B,EAAQ,YACVA,EAAQ,QAAQ,QAAA,GAChBA,EAAQ,UAAU,OAEhBC,EAAa,WAAWA,EAAa,QAAQ,eAC/CA,EAAa,QAAQ,WAAW,YAAYA,EAAa,OAAO,GAChEA,EAAa,UAAU;AAAA,EAE3B,GACC,CAAA,CAAE;AAEL,QAAM4B,IAAOrB,EAAY,YAAY;;AACnC,IAAAhB,EAAa,EAAI,GACjBE,EAAS,IAAI;AAEb,QAAI;AACF,YAAMwB,IAAQ,MAAMnC,EAAA;AACpB,MAAAgB,EAAgB,UAAUmB,GAC1B5B,EAAU,EAAI;AAAA,IAChB,SAASwC,GAAK;AACZ,YAAMC,IAA6B;AAAA,QACjC,MAAM;AAAA,QACN,SACED,aAAe,QAAQA,EAAI,UAAU;AAAA,MAAA;AAEzC,MAAApC,EAASqC,CAAY,IACrBrB,KAAAC,IAAAP,EAAa,SAAQ,YAArB,QAAAM,EAAA,KAAAC,GAA+BoB;AAAA,IACjC,UAAA;AACE,MAAAvC,EAAa,EAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAACT,CAAe,CAAC,GAEdiD,IAAQxB,EAAY,MAAM;AAC9B,IAAAI,EAAY,QAAQ;AAAA,EACtB,GAAG,CAACA,CAAW,CAAC,GAEVqB,IAAWzB;AAAA,IACf,CAAC0B,MAA2B;AAC1B,MAAA7B,EAAS,UAAU6B,GACnB3B,EAAa,EAAE,MAAM,aAAa,OAAO2B,GAAU;AAAA,IACrD;AAAA,IACA,CAAC3B,CAAY;AAAA,EAAA,GAGT4B,KAAW3B;AAAA,IACf,CAAC4B,MAAuB;AACtB,MAAA7B,EAAa,EAAE,MAAM,YAAY,MAAA6B,EAAA,CAAM;AAAA,IACzC;AAAA,IACA,CAAC7B,CAAY;AAAA,EAAA;AAGf,SAAO;AAAA,IACL,MAAAsB;AAAA,IACA,OAAAG;AAAA,IACA,UAAAC;AAAA,IACA,UAAAE;AAAA,IACA,QAAA9C;AAAA,IACA,WAAAE;AAAA,IACA,OAAAE;AAAA,IACA,QAAAE;AAAA,EAAA;AAEJ;ACnMO,SAAS0C,GAAgB;AAAA,EAC9B,UAAAC;AAAA,EACA,GAAGC;AACL,GAAyB;AACvB,QAAMC,IAAa3D,GAAmB0D,CAAW;AACjD,SAAO,gBAAAlE,EAAAuD,GAAA,EAAG,UAAAU,EAASE,CAAU,GAAE;AACjC;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@airweave/connect-react",
|
|
3
|
+
"version": "0.9.27",
|
|
4
|
+
"description": "React hook for Airweave Connect",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite build --watch",
|
|
27
|
+
"build": "tsc && vite build",
|
|
28
|
+
"lint": "eslint .",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": ">=19.0.0",
|
|
33
|
+
"react-dom": ">=19.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"airweave-connect": "file:../..",
|
|
37
|
+
"@types/react": "^19.2.0",
|
|
38
|
+
"@types/react-dom": "^19.2.0",
|
|
39
|
+
"@vitejs/plugin-react": "^4.5.2",
|
|
40
|
+
"react": "^19.2.0",
|
|
41
|
+
"react-dom": "^19.2.0",
|
|
42
|
+
"typescript": "^5.8.3",
|
|
43
|
+
"vite": "^6.3.5",
|
|
44
|
+
"vite-plugin-dts": "^4.5.4"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"airweave",
|
|
48
|
+
"connect",
|
|
49
|
+
"react",
|
|
50
|
+
"integrations",
|
|
51
|
+
"oauth"
|
|
52
|
+
],
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/airweave-ai/airweave"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|