@fruga/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, Fruga Team
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # Fruga Relay SDK (`@fruga/sdk`)
2
+
3
+ A lightweight, embeddable widget that allows third-party partners to display insurance quotes and cashback offers directly on their websites.
4
+
5
+ ## Features
6
+ - **Embeddable via Script Tag**: Ready for standalone usage without any dependencies.
7
+ - **Configurable**: Fully customizable `partnerId` and `theme` options.
8
+ - **Isolated Styles**: Uses Shadow DOM to prevent CSS leaks into the partner website.
9
+ - **TypeScript Support**: Full type definitions included.
10
+ - **Lightweight**: Optimized and tree-shaken build.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add @fruga/sdk
16
+ ```
17
+
18
+ For detailed instructions, including CDN usage and troubleshooting, see the [Installation Guide](./docs/INSTALLATION.md).
19
+
20
+ ## Usage
21
+
22
+ The SDK can be integrated via native React components or React hooks.
23
+
24
+ ### Native React Component
25
+
26
+ For an immediate, easy setup in React, import the `<FrugaWidget />` component. This automatically handles mounting and unmounting within the React lifecycle.
27
+
28
+ ```tsx
29
+ import { FrugaWidget } from '@fruga/sdk/loader/react';
30
+
31
+ export default function MyPage() {
32
+ return (
33
+ <div style={{ width: '350px', height: '500px' }}>
34
+ <FrugaWidget
35
+ partnerKey="YOUR_PARTNER_KEY"
36
+ theme="light"
37
+ primaryColor="#ffff33"
38
+ onClose={() => console.log('Widget closed')}
39
+ />
40
+ </div>
41
+ );
42
+ }
43
+ ```
44
+
45
+ ### React Hook (Manual Control)
46
+
47
+ If you need manual control over when the widget mounts (e.g., waiting for a user to click a "Buy Now" button), use the `useFrugaWidget` hook.
48
+
49
+ ```tsx
50
+ import { useFrugaWidget } from '@fruga/sdk/loader/react';
51
+
52
+ export default function App() {
53
+ const { mount, unmount } = useFrugaWidget({
54
+ partnerKey: 'YOUR_PARTNER_KEY',
55
+ containerId: 'my-custom-container',
56
+ autoMount: false
57
+ });
58
+
59
+ return (
60
+ <div>
61
+ <button onClick={mount}>Show Insurance Options</button>
62
+ <button onClick={unmount}>Hide</button>
63
+ <div id="my-custom-container" />
64
+ </div>
65
+ );
66
+ }
67
+ ```
68
+
69
+ ### Script Tag Usage (Vanilla HTML)
70
+
71
+ For non-React websites, drop the script tag directly into your HTML. The script acts independently and initializes the widget in the specified container.
72
+
73
+ ```html
74
+ <div id="fruga-widget-root"></div>
75
+
76
+ <script src="https://unpkg.com/@fruga/sdk/dist/loader.global.js"></script>
77
+ <script>
78
+ FrugaLoader.init({
79
+ partnerKey: 'YOUR_PARTNER_KEY',
80
+ containerId: 'fruga-widget-root',
81
+ autoMount: true
82
+ });
83
+ </script>
84
+ ```
85
+
86
+ ## Configuration Options
87
+
88
+ | Option | Type | Description |
89
+ | --- | --- | --- |
90
+ | `partnerKey` | `string` | **Required.** Your unique partner identifier. |
91
+ | `containerId` | `string` | (Optional) The ID of the container element. Defaults to `fruga-widget-root`. |
92
+ | `theme` | `'light' \| 'dark'` | (Optional) The visual theme. Defaults to `light`. |
93
+ | `primaryColor` | `string` | (Optional) Hex code for the primary brand color. |
94
+ | `autoMount` | `boolean` | (Optional) If `true`, the widget mounts immediately after init. Defaults to `true`. |
95
+ | `onClose` | `() => void` | (Optional) Callback function triggered when the widget is closed internally. |
96
+
97
+ ## API Methods
98
+
99
+ ### `init(options: LoaderOptions)`
100
+ Initializes the loader with the given configuration.
101
+
102
+ ### `mount()`
103
+ Renders the widget into the DOM.
104
+
105
+ ### `unmount()`
106
+ Removes the widget from the DOM.
107
+
108
+ ## Development
109
+
110
+ ```bash
111
+ pnpm install
112
+ pnpm dev # Watch mode for all apps/packages
113
+ pnpm build # Production build
114
+ pnpm test # Run tests
115
+ ```
116
+
117
+ ## License
118
+ ISC
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@fruga/sdk/connect",
3
+ "main": "../dist/connect.js",
4
+ "module": "../dist/connect.mjs",
5
+ "types": "../dist/connect.d.ts"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@fruga/sdk/core",
3
+ "main": "../dist/index.js",
4
+ "module": "../dist/index.mjs",
5
+ "types": "../dist/index.d.ts"
6
+ }
@@ -0,0 +1,73 @@
1
+ type PartnerType = 'RELAY' | 'CONNECT' | 'EXTERNAL_TENANT';
2
+ interface PartnerConfig {
3
+ partnerId: string;
4
+ partnerType: PartnerType;
5
+ theme?: {
6
+ primaryColor?: string;
7
+ mode?: 'light' | 'dark';
8
+ };
9
+ features?: Record<string, boolean>;
10
+ appUrl?: string;
11
+ partnerKey?: string;
12
+ userId?: string;
13
+ }
14
+ interface WidgetUiConfig {
15
+ accent: string;
16
+ defaultTheme: 'light' | 'dark';
17
+ launcherIcon: string;
18
+ showLauncher: boolean;
19
+ launcherLabel: string;
20
+ accentTextDark: string;
21
+ accentTextLight: string;
22
+ allowUserThemeControl: boolean;
23
+ }
24
+ interface BootstrapAuth {
25
+ mode: string;
26
+ audience: string;
27
+ issuer: string;
28
+ tokenTtlSeconds: number;
29
+ }
30
+ interface WidgetBootstrap {
31
+ partnerEnvId: string;
32
+ partnerId: string;
33
+ partnerType: PartnerType;
34
+ partnerPayout: 'PARTNER' | 'USER';
35
+ auth: BootstrapAuth;
36
+ config: {
37
+ ui: WidgetUiConfig;
38
+ validValues: {
39
+ defaultTheme: string[];
40
+ launcherIcon: string[];
41
+ };
42
+ };
43
+ }
44
+ interface RelayConfig {
45
+ containerId: string;
46
+ partnerKey: string;
47
+ token?: string;
48
+ baseUrl?: string;
49
+ theme?: 'light' | 'dark';
50
+ primaryColor?: string;
51
+ userId?: string;
52
+ bootstrapConfig?: WidgetBootstrap;
53
+ isHostMobile?: boolean;
54
+ hostHeight?: number;
55
+ }
56
+ declare global {
57
+ interface Window {
58
+ FrugaRelay?: {
59
+ init: (config: RelayConfig) => void;
60
+ };
61
+ }
62
+ }
63
+
64
+ declare const mount: (el: HTMLElement, config: PartnerConfig) => {
65
+ unmount: () => void;
66
+ };
67
+ declare const _default: {
68
+ mount: (el: HTMLElement, config: PartnerConfig) => {
69
+ unmount: () => void;
70
+ };
71
+ };
72
+
73
+ export { _default as default, mount };
@@ -0,0 +1,73 @@
1
+ type PartnerType = 'RELAY' | 'CONNECT' | 'EXTERNAL_TENANT';
2
+ interface PartnerConfig {
3
+ partnerId: string;
4
+ partnerType: PartnerType;
5
+ theme?: {
6
+ primaryColor?: string;
7
+ mode?: 'light' | 'dark';
8
+ };
9
+ features?: Record<string, boolean>;
10
+ appUrl?: string;
11
+ partnerKey?: string;
12
+ userId?: string;
13
+ }
14
+ interface WidgetUiConfig {
15
+ accent: string;
16
+ defaultTheme: 'light' | 'dark';
17
+ launcherIcon: string;
18
+ showLauncher: boolean;
19
+ launcherLabel: string;
20
+ accentTextDark: string;
21
+ accentTextLight: string;
22
+ allowUserThemeControl: boolean;
23
+ }
24
+ interface BootstrapAuth {
25
+ mode: string;
26
+ audience: string;
27
+ issuer: string;
28
+ tokenTtlSeconds: number;
29
+ }
30
+ interface WidgetBootstrap {
31
+ partnerEnvId: string;
32
+ partnerId: string;
33
+ partnerType: PartnerType;
34
+ partnerPayout: 'PARTNER' | 'USER';
35
+ auth: BootstrapAuth;
36
+ config: {
37
+ ui: WidgetUiConfig;
38
+ validValues: {
39
+ defaultTheme: string[];
40
+ launcherIcon: string[];
41
+ };
42
+ };
43
+ }
44
+ interface RelayConfig {
45
+ containerId: string;
46
+ partnerKey: string;
47
+ token?: string;
48
+ baseUrl?: string;
49
+ theme?: 'light' | 'dark';
50
+ primaryColor?: string;
51
+ userId?: string;
52
+ bootstrapConfig?: WidgetBootstrap;
53
+ isHostMobile?: boolean;
54
+ hostHeight?: number;
55
+ }
56
+ declare global {
57
+ interface Window {
58
+ FrugaRelay?: {
59
+ init: (config: RelayConfig) => void;
60
+ };
61
+ }
62
+ }
63
+
64
+ declare const mount: (el: HTMLElement, config: PartnerConfig) => {
65
+ unmount: () => void;
66
+ };
67
+ declare const _default: {
68
+ mount: (el: HTMLElement, config: PartnerConfig) => {
69
+ unmount: () => void;
70
+ };
71
+ };
72
+
73
+ export { _default as default, mount };
@@ -0,0 +1,26 @@
1
+ "use strict";var fe=Object.create;var q=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var ne=Object.getPrototypeOf,pe=Object.prototype.hasOwnProperty;var me=(e,a)=>{for(var t in a)q(e,t,{get:a[t],enumerable:!0})},V=(e,a,t,u)=>{if(a&&typeof a=="object"||typeof a=="function")for(let o of ce(a))!pe.call(e,o)&&o!==t&&q(e,o,{get:()=>a[o],enumerable:!(u=ie(a,o))||u.enumerable});return e};var E=(e,a,t)=>(t=e!=null?fe(ne(e)):{},V(a||!e||!e.__esModule?q(t,"default",{value:e,enumerable:!0}):t,e)),Le=e=>V(q({},"__esModule",{value:!0}),e);var Me={};me(Me,{default:()=>Be,mount:()=>se});module.exports=Le(Me);var le=E(require("react")),re=E(require("react-dom/client"));var z={widgetTitle:"Savings Box",launcherLabel:"Insurance Savings",launcherIcon:"arrow",showLauncher:!0,mode:"light",allowUserThemeControl:!1,defaultTheme:"light",uiVersion:"current",primary:"#1E40AF",accent:"#2648C9",accentTextLight:"#FFFFFF",accentTextDark:"#FFFFFF",bg:"#0B1220",panel:"#0F1A2E",panel2:"#111F38",itemBg:"rgba(255,255,255,0.03)",text:"#E6EDF7",muted:"#A7B3C6",border:"rgba(255,255,255,0.08)",success:"#34D399",danger:"#EF4444",warning:"#FBBF24",lightBg:"#F8FAFC",lightPanel:"#FFFFFF",lightPanel2:"#F1F5F9",lightItemBg:"rgba(0,0,0,0.04)",lightText:"#0F172A",lightMuted:"#64748B",lightBorder:"rgba(0,0,0,0.1)"};function X(e){let a=e.mode==="light",t=a?e.textColorLight?.trim()||e.lightText:e.textColorDark?.trim()||e.text;return{...e,bg:a?e.lightBg:e.bg,panel:a?e.lightPanel:e.panel,panel2:a?e.lightPanel2:e.panel2,itemBg:a?e.lightItemBg:e.itemBg,text:t,muted:a?e.lightMuted:e.muted,border:a?e.lightBorder:e.border,subtleBg:a?"rgba(0,0,0,0.02)":"rgba(255,255,255,0.03)",tooltipBg:a?"#FFFFFF":"#0B1220",tooltipBorder:a?"rgba(0,0,0,0.12)":"rgba(255,255,255,0.12)",accentText:a?e.accentTextLight?.trim()||"#0F172A":e.accentTextDark?.trim()||"#FFFFFF",isLight:a,mode:e.mode}}var xe=require("react/jsx-runtime");var L=require("react");var O=require("react");var U=(...e)=>e.filter((a,t,u)=>!!a&&a.trim()!==""&&u.indexOf(a)===t).join(" ").trim();var N=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var K=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,t,u)=>u?u.toUpperCase():t.toLowerCase());var G=e=>{let a=K(e);return a.charAt(0).toUpperCase()+a.slice(1)};var B=require("react");var v={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};var Z=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};var P=require("react");var Ce=(0,P.createContext)({});var Q=()=>(0,P.useContext)(Ce);var J=(0,B.forwardRef)(({color:e,size:a,strokeWidth:t,absoluteStrokeWidth:u,className:o="",children:f,iconNode:g,...l},r)=>{let{size:i=24,strokeWidth:d=2,absoluteStrokeWidth:m=!1,color:k="currentColor",className:c=""}=Q()??{},w=u??m?Number(t??d)*24/Number(a??i):t??d;return(0,B.createElement)("svg",{ref:r,...v,width:a??i??v.width,height:a??i??v.height,stroke:e??k,strokeWidth:w,className:U("lucide",c,o),...!f&&!Z(l)&&{"aria-hidden":"true"},...l},[...g.map(([A,h])=>(0,B.createElement)(A,h)),...Array.isArray(f)?f:[f]])});var p=(e,a)=>{let t=(0,O.forwardRef)(({className:u,...o},f)=>(0,O.createElement)(J,{ref:f,iconNode:a,className:U(`lucide-${N(G(e))}`,`lucide-${e}`,u),...o}));return t.displayName=G(e),t};var ge=[["rect",{width:"20",height:"14",x:"2",y:"5",rx:"2",key:"ynyp8z"}],["line",{x1:"2",x2:"22",y1:"10",y2:"10",key:"1b3vmo"}]],M=p("credit-card",ge);var he=[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M20 11v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8",key:"1sqzm4"}],["path",{d:"M7.5 7a1 1 0 0 1 0-5A4.8 8 0 0 1 12 7a4.8 8 0 0 1 4.5-5 1 1 0 0 1 0 5",key:"kc0143"}],["rect",{x:"3",y:"7",width:"18",height:"4",rx:"1",key:"1hberx"}]],D=p("gift",he);var Se=[["path",{d:"M13 5H19V11",key:"1n1gyv"}],["path",{d:"M19 5L5 19",key:"72u4yj"}]],y=p("move-up-right",Se);var we=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],x=p("sparkles",we);var Pe=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],R=p("x",Pe);var T=require("react/jsx-runtime");function _({theme:e}){return e.launcherIcon==="none"?null:e.launcherIcon==="sparkles"?(0,T.jsx)(x,{size:20}):e.launcherIcon==="credit"?(0,T.jsx)(M,{size:20}):e.launcherIcon==="arrow"?(0,T.jsx)(y,{size:20}):(0,T.jsx)(D,{size:20})}var H=require("react");var j=e=>{let a,t=new Set,u=(i,d)=>{let m=typeof i=="function"?i(a):i;if(!Object.is(m,a)){let k=a;a=d??(typeof m!="object"||m===null)?m:Object.assign({},a,m),t.forEach(c=>c(a,k))}},o=()=>a,l={setState:u,getState:o,getInitialState:()=>r,subscribe:i=>(t.add(i),()=>t.delete(i))},r=a=e(u,o,l);return l},$=(e=>e?j(e):j);var b=E(require("react"),1);var ke=e=>e;function Ae(e,a=ke){let t=b.default.useSyncExternalStore(e.subscribe,b.default.useCallback(()=>a(e.getState()),[e,a]),b.default.useCallback(()=>a(e.getInitialState()),[e,a]));return b.default.useDebugValue(t),t}var Y=e=>{let a=$(e),t=u=>Ae(a,u);return Object.assign(t,a),t},ee=(e=>e?Y(e):Y);var S=ee(e=>({isOpen:!1,isFocused:!0,isIdle:!1,available:0,pending:0,mode:"light",token:null,partnerPayout:null,isAddingPayoutFromAlert:!1,showPayoutSuccess:!1,toggle:()=>e(a=>({isOpen:!a.isOpen})),setOpen:a=>e({isOpen:a}),setFocused:a=>e({isFocused:a}),setIdle:a=>e({isIdle:a}),setBalances:(a,t)=>e({available:a,pending:t}),setMode:a=>e({mode:a}),setToken:a=>e({token:a}),setPartnerPayout:a=>e({partnerPayout:a}),setIsAddingPayoutFromAlert:a=>e({isAddingPayoutFromAlert:a}),setShowPayoutSuccess:a=>e({showPayoutSuccess:a})}));function ae(){let{setFocused:e,setIdle:a}=S(),t=(0,H.useRef)(null);(0,H.useEffect)(()=>{let u=()=>e(!0),o=()=>e(!1),f=()=>{a(!1),t.current&&clearTimeout(t.current),t.current=setTimeout(()=>{a(!0)},6e4)},g=()=>{f()};f(),e(document.hasFocus()),window.addEventListener("focus",u),window.addEventListener("blur",o);let l=["mousemove","keydown","scroll","touchstart","mousedown"];return l.forEach(r=>{window.addEventListener(r,g,r==="scroll"?!0:void 0)}),()=>{window.removeEventListener("focus",u),window.removeEventListener("blur",o),l.forEach(r=>{window.removeEventListener(r,g,r==="scroll"?!0:void 0)}),t.current&&clearTimeout(t.current)}},[e,a])}var s=require("react/jsx-runtime"),te=({children:e,theme:a,hostHeight:t=800,isMobile:u=!1})=>{ae();let{isOpen:o,toggle:f,mode:g}=S(),l=a||z,[r,i]=(0,L.useState)(t),[d,m]=(0,L.useState)(u),k=l.allowUserThemeControl?{...l,mode:g}:{...l,mode:l.mode||"light"},c=X(k),w=(0,L.useRef)(null),A=(0,L.useRef)(null);return(0,L.useEffect)(()=>{let h=n=>{if(n.data?.type==="FRUGA_HOST_RESIZE"&&(i(n.data.hostHeight),m(n.data.isHostMobile)),n.data?.type==="FRUGA_TOKEN_UPDATE"){let{setToken:I}=S.getState();I(n.data.token)}if(n.data?.type==="FRUGA_GET_BALANCE"){let{available:I,pending:F}=S.getState();console.log("FRUGA_GET_BALANCE",I,F),window.parent.postMessage({type:"FRUGA_BALANCE_RESPONSE",requestId:n.data.requestId,available:I,pending:F},"*")}};return window.addEventListener("message",h),()=>window.removeEventListener("message",h)},[]),(0,L.useEffect)(()=>{if(!w.current)return;let h=()=>{if(!w.current)return;let I=o?450:100;!o&&A.current&&(I=A.current.offsetWidth+40);let F=o?Math.max(200,r-100):100;d&&o&&(I=window.innerWidth,F=r),window.parent.postMessage({type:"FRUGA_RESIZE",height:F,width:I,isFullscreen:d&&o},"*")},n=new ResizeObserver(()=>h());return n.observe(w.current),h(),()=>n.disconnect()},[o,r,d]),(0,s.jsxs)("div",{ref:w,className:c.mode==="dark"?"dark":"",style:{fontFamily:'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',color:c.text,display:"flex",flexDirection:"column",alignItems:"flex-end",justifyContent:"flex-end",padding:d&&o?"0":"20px",boxSizing:"border-box",height:"100%",margin:0,overscrollBehavior:"contain"},children:[o&&(0,s.jsx)("div",{style:{width:d?"100vw":"410px",minWidth:d?"100vw":"410px",flexShrink:0,maxHeight:d?"100vh":`${Math.max(100,r-100)}px`,height:"100%",marginBottom:d?"0":"20px",backgroundColor:c.accent,borderRadius:d?"0":"16px",boxShadow:d?"none":"0 20px 40px -10px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0,0,0,0.1)",display:"flex",flexDirection:"column",overflow:"hidden",zIndex:9998},children:(0,s.jsx)("div",{className:"fruga-scrollbar",style:{flex:1,minHeight:0,backgroundColor:c.isLight?"#f9f9f9":"#111",display:"flex",flexDirection:"column",boxShadow:d?"none":"0 20px 40px -10px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0,0,0,0.1)"},children:e})}),(0,s.jsxs)("button",{ref:A,onClick:f,style:{backgroundColor:c.accent,color:c.accentText,border:"none",cursor:"pointer",boxShadow:"0 12px 30px -5px rgba(0, 0, 0, 0.1), 0 0 1px rgba(0,0,0, 0.1)",display:o?"none":"flex",alignItems:"center",justifyContent:"center",zIndex:9999,flexShrink:0,borderRadius:"20px",padding:"10px 16px",transition:"transform 0.3s ease-in-out"},className:"flex h-15 items-center gap-2 rounded-xl px-4 active:scale-[0.99]","aria-label":o?"Close widget":"Open widget",children:[l.launcherLabel&&!o?(0,s.jsxs)(s.Fragment,{children:[l.launcherLabel!=="none"&&(0,s.jsx)("div",{className:"text-sm font-semibold",children:l.launcherLabel}),(0,s.jsx)("div",{className:"flex h-6 w-5 shrink-0 items-center justify-center",children:(0,s.jsx)(_,{theme:c})})]}):null,o?(0,s.jsx)(R,{}):null]})]})};var oe=require("react/jsx-runtime");var ue=require("react");var $a=typeof process<"u"&&process.env.VITE_FRUGA_API_URL||"https://api-dev.fruga.co.uk";var C=require("react/jsx-runtime"),de=({partnerKey:e,theme:a,userId:t})=>(0,C.jsx)(te,{primaryColor:a?.primaryColor,theme:a,children:(0,C.jsxs)("div",{style:{padding:"20px",fontFamily:'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'},children:[(0,C.jsx)("h2",{style:{marginTop:0},children:t?`Welcome back, ${t}`:"Connect Widget"}),(0,C.jsx)("p",{children:"This is the Connect widget loaded from the SDK."}),(0,C.jsxs)("p",{children:["Partner Key: ",e]}),t&&(0,C.jsxs)("p",{children:["User Context: ",t]})]})});var W=require("react/jsx-runtime"),se=(e,a)=>{let t=re.default.createRoot(e);return t.render((0,W.jsx)(le.default.StrictMode,{children:(0,W.jsx)(de,{...a})})),{unmount:()=>{t.unmount()}}},Be={mount:se};0&&(module.exports={mount});
2
+ /*! Bundled license information:
3
+
4
+ lucide-react/dist/esm/shared/src/utils/mergeClasses.js:
5
+ lucide-react/dist/esm/shared/src/utils/toKebabCase.js:
6
+ lucide-react/dist/esm/shared/src/utils/toCamelCase.js:
7
+ lucide-react/dist/esm/shared/src/utils/toPascalCase.js:
8
+ lucide-react/dist/esm/defaultAttributes.js:
9
+ lucide-react/dist/esm/shared/src/utils/hasA11yProp.js:
10
+ lucide-react/dist/esm/context.js:
11
+ lucide-react/dist/esm/Icon.js:
12
+ lucide-react/dist/esm/createLucideIcon.js:
13
+ lucide-react/dist/esm/icons/credit-card.js:
14
+ lucide-react/dist/esm/icons/gift.js:
15
+ lucide-react/dist/esm/icons/move-up-right.js:
16
+ lucide-react/dist/esm/icons/sparkles.js:
17
+ lucide-react/dist/esm/icons/x.js:
18
+ lucide-react/dist/esm/lucide-react.js:
19
+ (**
20
+ * @license lucide-react v1.7.0 - ISC
21
+ *
22
+ * This source code is licensed under the ISC license.
23
+ * See the LICENSE file in the root directory of this source tree.
24
+ *)
25
+ */
26
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1,26 @@
1
+ import he from"react";import Se from"react-dom/client";var v={widgetTitle:"Savings Box",launcherLabel:"Insurance Savings",launcherIcon:"arrow",showLauncher:!0,mode:"light",allowUserThemeControl:!1,defaultTheme:"light",uiVersion:"current",primary:"#1E40AF",accent:"#2648C9",accentTextLight:"#FFFFFF",accentTextDark:"#FFFFFF",bg:"#0B1220",panel:"#0F1A2E",panel2:"#111F38",itemBg:"rgba(255,255,255,0.03)",text:"#E6EDF7",muted:"#A7B3C6",border:"rgba(255,255,255,0.08)",success:"#34D399",danger:"#EF4444",warning:"#FBBF24",lightBg:"#F8FAFC",lightPanel:"#FFFFFF",lightPanel2:"#F1F5F9",lightItemBg:"rgba(0,0,0,0.04)",lightText:"#0F172A",lightMuted:"#64748B",lightBorder:"rgba(0,0,0,0.1)"};function O(e){let a=e.mode==="light",t=a?e.textColorLight?.trim()||e.lightText:e.textColorDark?.trim()||e.text;return{...e,bg:a?e.lightBg:e.bg,panel:a?e.lightPanel:e.panel,panel2:a?e.lightPanel2:e.panel2,itemBg:a?e.lightItemBg:e.itemBg,text:t,muted:a?e.lightMuted:e.muted,border:a?e.lightBorder:e.border,subtleBg:a?"rgba(0,0,0,0.02)":"rgba(255,255,255,0.03)",tooltipBg:a?"#FFFFFF":"#0B1220",tooltipBorder:a?"rgba(0,0,0,0.12)":"rgba(255,255,255,0.12)",accentText:a?e.accentTextLight?.trim()||"#0F172A":e.accentTextDark?.trim()||"#FFFFFF",isLight:a,mode:e.mode}}import{jsx as We}from"react/jsx-runtime";import{useState as _,useEffect as j,useRef as $}from"react";import{forwardRef as re,createElement as se}from"react";var M=(...e)=>e.filter((a,t,u)=>!!a&&a.trim()!==""&&u.indexOf(a)===t).join(" ").trim();var H=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();var E=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,t,u)=>u?u.toUpperCase():t.toLowerCase());var T=e=>{let a=E(e);return a.charAt(0).toUpperCase()+a.slice(1)};import{forwardRef as le,createElement as V}from"react";var D={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};var G=e=>{for(let a in e)if(a.startsWith("aria-")||a==="role"||a==="title")return!0;return!1};import{createContext as oe,useContext as ue,useMemo as je,createElement as $e}from"react";var de=oe({});var W=()=>ue(de);var z=le(({color:e,size:a,strokeWidth:t,absoluteStrokeWidth:u,className:o="",children:s,iconNode:I,...l},r)=>{let{size:f=24,strokeWidth:d=2,absoluteStrokeWidth:p=!1,color:S="currentColor",className:i=""}=W()??{},g=u??p?Number(t??d)*24/Number(a??f):t??d;return V("svg",{ref:r,...D,width:a??f??D.width,height:a??f??D.height,stroke:e??S,strokeWidth:g,className:M("lucide",i,o),...!s&&!G(l)&&{"aria-hidden":"true"},...l},[...I.map(([w,x])=>V(w,x)),...Array.isArray(s)?s:[s]])});var n=(e,a)=>{let t=re(({className:u,...o},s)=>se(z,{ref:s,iconNode:a,className:M(`lucide-${H(T(e))}`,`lucide-${e}`,u),...o}));return t.displayName=T(e),t};var fe=[["rect",{width:"20",height:"14",x:"2",y:"5",rx:"2",key:"ynyp8z"}],["line",{x1:"2",x2:"22",y1:"10",y2:"10",key:"1b3vmo"}]],k=n("credit-card",fe);var ie=[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M20 11v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8",key:"1sqzm4"}],["path",{d:"M7.5 7a1 1 0 0 1 0-5A4.8 8 0 0 1 12 7a4.8 8 0 0 1 4.5-5 1 1 0 0 1 0 5",key:"kc0143"}],["rect",{x:"3",y:"7",width:"18",height:"4",rx:"1",key:"1hberx"}]],A=n("gift",ie);var ce=[["path",{d:"M13 5H19V11",key:"1n1gyv"}],["path",{d:"M19 5L5 19",key:"72u4yj"}]],F=n("move-up-right",ce);var ne=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],L=n("sparkles",ne);var pe=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],B=n("x",pe);import{jsx as y}from"react/jsx-runtime";function X({theme:e}){return e.launcherIcon==="none"?null:e.launcherIcon==="sparkles"?y(L,{size:20}):e.launcherIcon==="credit"?y(k,{size:20}):e.launcherIcon==="arrow"?y(F,{size:20}):y(A,{size:20})}import{useEffect as xe,useRef as Ce}from"react";var N=e=>{let a,t=new Set,u=(f,d)=>{let p=typeof f=="function"?f(a):f;if(!Object.is(p,a)){let S=a;a=d??(typeof p!="object"||p===null)?p:Object.assign({},a,p),t.forEach(i=>i(a,S))}},o=()=>a,l={setState:u,getState:o,getInitialState:()=>r,subscribe:f=>(t.add(f),()=>t.delete(f))},r=a=e(u,o,l);return l},K=(e=>e?N(e):N);import R from"react";var me=e=>e;function Le(e,a=me){let t=R.useSyncExternalStore(e.subscribe,R.useCallback(()=>a(e.getState()),[e,a]),R.useCallback(()=>a(e.getInitialState()),[e,a]));return R.useDebugValue(t),t}var Z=e=>{let a=K(e),t=u=>Le(a,u);return Object.assign(t,a),t},Q=(e=>e?Z(e):Z);var C=Q(e=>({isOpen:!1,isFocused:!0,isIdle:!1,available:0,pending:0,mode:"light",token:null,partnerPayout:null,isAddingPayoutFromAlert:!1,showPayoutSuccess:!1,toggle:()=>e(a=>({isOpen:!a.isOpen})),setOpen:a=>e({isOpen:a}),setFocused:a=>e({isFocused:a}),setIdle:a=>e({isIdle:a}),setBalances:(a,t)=>e({available:a,pending:t}),setMode:a=>e({mode:a}),setToken:a=>e({token:a}),setPartnerPayout:a=>e({partnerPayout:a}),setIsAddingPayoutFromAlert:a=>e({isAddingPayoutFromAlert:a}),setShowPayoutSuccess:a=>e({showPayoutSuccess:a})}));function J(){let{setFocused:e,setIdle:a}=C(),t=Ce(null);xe(()=>{let u=()=>e(!0),o=()=>e(!1),s=()=>{a(!1),t.current&&clearTimeout(t.current),t.current=setTimeout(()=>{a(!0)},6e4)},I=()=>{s()};s(),e(document.hasFocus()),window.addEventListener("focus",u),window.addEventListener("blur",o);let l=["mousemove","keydown","scroll","touchstart","mousedown"];return l.forEach(r=>{window.addEventListener(r,I,r==="scroll"?!0:void 0)}),()=>{window.removeEventListener("focus",u),window.removeEventListener("blur",o),l.forEach(r=>{window.removeEventListener(r,I,r==="scroll"?!0:void 0)}),t.current&&clearTimeout(t.current)}},[e,a])}import{Fragment as ge,jsx as h,jsxs as b}from"react/jsx-runtime";var Y=({children:e,theme:a,hostHeight:t=800,isMobile:u=!1})=>{J();let{isOpen:o,toggle:s,mode:I}=C(),l=a||v,[r,f]=_(t),[d,p]=_(u),S=l.allowUserThemeControl?{...l,mode:I}:{...l,mode:l.mode||"light"},i=O(S),g=$(null),w=$(null);return j(()=>{let x=c=>{if(c.data?.type==="FRUGA_HOST_RESIZE"&&(f(c.data.hostHeight),p(c.data.isHostMobile)),c.data?.type==="FRUGA_TOKEN_UPDATE"){let{setToken:m}=C.getState();m(c.data.token)}if(c.data?.type==="FRUGA_GET_BALANCE"){let{available:m,pending:P}=C.getState();console.log("FRUGA_GET_BALANCE",m,P),window.parent.postMessage({type:"FRUGA_BALANCE_RESPONSE",requestId:c.data.requestId,available:m,pending:P},"*")}};return window.addEventListener("message",x),()=>window.removeEventListener("message",x)},[]),j(()=>{if(!g.current)return;let x=()=>{if(!g.current)return;let m=o?450:100;!o&&w.current&&(m=w.current.offsetWidth+40);let P=o?Math.max(200,r-100):100;d&&o&&(m=window.innerWidth,P=r),window.parent.postMessage({type:"FRUGA_RESIZE",height:P,width:m,isFullscreen:d&&o},"*")},c=new ResizeObserver(()=>x());return c.observe(g.current),x(),()=>c.disconnect()},[o,r,d]),b("div",{ref:g,className:i.mode==="dark"?"dark":"",style:{fontFamily:'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',color:i.text,display:"flex",flexDirection:"column",alignItems:"flex-end",justifyContent:"flex-end",padding:d&&o?"0":"20px",boxSizing:"border-box",height:"100%",margin:0,overscrollBehavior:"contain"},children:[o&&h("div",{style:{width:d?"100vw":"410px",minWidth:d?"100vw":"410px",flexShrink:0,maxHeight:d?"100vh":`${Math.max(100,r-100)}px`,height:"100%",marginBottom:d?"0":"20px",backgroundColor:i.accent,borderRadius:d?"0":"16px",boxShadow:d?"none":"0 20px 40px -10px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0,0,0,0.1)",display:"flex",flexDirection:"column",overflow:"hidden",zIndex:9998},children:h("div",{className:"fruga-scrollbar",style:{flex:1,minHeight:0,backgroundColor:i.isLight?"#f9f9f9":"#111",display:"flex",flexDirection:"column",boxShadow:d?"none":"0 20px 40px -10px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0,0,0,0.1)"},children:e})}),b("button",{ref:w,onClick:s,style:{backgroundColor:i.accent,color:i.accentText,border:"none",cursor:"pointer",boxShadow:"0 12px 30px -5px rgba(0, 0, 0, 0.1), 0 0 1px rgba(0,0,0, 0.1)",display:o?"none":"flex",alignItems:"center",justifyContent:"center",zIndex:9999,flexShrink:0,borderRadius:"20px",padding:"10px 16px",transition:"transform 0.3s ease-in-out"},className:"flex h-15 items-center gap-2 rounded-xl px-4 active:scale-[0.99]","aria-label":o?"Close widget":"Open widget",children:[l.launcherLabel&&!o?b(ge,{children:[l.launcherLabel!=="none"&&h("div",{className:"text-sm font-semibold",children:l.launcherLabel}),h("div",{className:"flex h-6 w-5 shrink-0 items-center justify-center",children:h(X,{theme:i})})]}):null,o?h(B,{}):null]})]})};import{Fragment as at,jsx as tt}from"react/jsx-runtime";import{useEffect as dt,useState as lt}from"react";var ft=typeof process<"u"&&process.env.VITE_FRUGA_API_URL||"https://api-dev.fruga.co.uk";import{jsx as q,jsxs as U}from"react/jsx-runtime";var ee=({partnerKey:e,theme:a,userId:t})=>q(Y,{primaryColor:a?.primaryColor,theme:a,children:U("div",{style:{padding:"20px",fontFamily:'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'},children:[q("h2",{style:{marginTop:0},children:t?`Welcome back, ${t}`:"Connect Widget"}),q("p",{children:"This is the Connect widget loaded from the SDK."}),U("p",{children:["Partner Key: ",e]}),t&&U("p",{children:["User Context: ",t]})]})});import{jsx as ae}from"react/jsx-runtime";var we=(e,a)=>{let t=Se.createRoot(e);return t.render(ae(he.StrictMode,{children:ae(ee,{...a})})),{unmount:()=>{t.unmount()}}},Ht={mount:we};export{Ht as default,we as mount};
2
+ /*! Bundled license information:
3
+
4
+ lucide-react/dist/esm/shared/src/utils/mergeClasses.js:
5
+ lucide-react/dist/esm/shared/src/utils/toKebabCase.js:
6
+ lucide-react/dist/esm/shared/src/utils/toCamelCase.js:
7
+ lucide-react/dist/esm/shared/src/utils/toPascalCase.js:
8
+ lucide-react/dist/esm/defaultAttributes.js:
9
+ lucide-react/dist/esm/shared/src/utils/hasA11yProp.js:
10
+ lucide-react/dist/esm/context.js:
11
+ lucide-react/dist/esm/Icon.js:
12
+ lucide-react/dist/esm/createLucideIcon.js:
13
+ lucide-react/dist/esm/icons/credit-card.js:
14
+ lucide-react/dist/esm/icons/gift.js:
15
+ lucide-react/dist/esm/icons/move-up-right.js:
16
+ lucide-react/dist/esm/icons/sparkles.js:
17
+ lucide-react/dist/esm/icons/x.js:
18
+ lucide-react/dist/esm/lucide-react.js:
19
+ (**
20
+ * @license lucide-react v1.7.0 - ISC
21
+ *
22
+ * This source code is licensed under the ISC license.
23
+ * See the LICENSE file in the root directory of this source tree.
24
+ *)
25
+ */
26
+ //# sourceMappingURL=connect.mjs.map
@@ -0,0 +1,5 @@
1
+ {
2
+ "main": "../core.js",
3
+ "module": "../core.mjs",
4
+ "types": "../core.d.ts"
5
+ }