@saas-support/react 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class b extends Error{constructor(t,e,s="unknown"){super(e),this.name="SaaSError",this.code=t,this.domain=s}get isNotFound(){return this.code===404}get isUnauthorized(){return this.code===401}get isForbidden(){return this.code===403}get isConflict(){return this.code===409}get isRateLimited(){return this.code===429}}class g{constructor(t,e){this.baseUrl=t,this.authMode=e}async request(t,e,s,r){const i={"Content-Type":"application/json",...this.getAuthHeaders(),...r},a=await(await fetch(`${this.baseUrl}${e}`,{method:t,headers:i,body:s?JSON.stringify(s):void 0})).json();if(a.code&&a.code>=400){const d=this.inferDomain(e);throw new b(a.code,a.message||"Request failed",d)}return a.data}async get(t,e){return this.request("GET",t,void 0,e)}async post(t,e,s){return this.request("POST",t,e,s)}async patch(t,e,s){return this.request("PATCH",t,e,s)}async del(t,e){return this.request("DELETE",t,void 0,e)}getAuthHeaders(){switch(this.authMode.type){case"publishableKey":case"apiKey":return{"X-API-Key":this.authMode.key};case"portalToken":case"embedToken":return{Authorization:`Bearer ${this.authMode.token}`}}}inferDomain(t){return t.startsWith("/auth")?"auth":t.startsWith("/billing")?"billing":t.startsWith("/report")?"report":"unknown"}}class R{constructor(t){this.accessToken=null,this.refreshToken=null,this.refreshTimer=null,this.onRefreshNeeded=null,this.storageKey=`ss_rt_${t.slice(0,12)}`,this.refreshToken=this.loadRefreshToken()}setRefreshCallback(t){this.onRefreshNeeded=t}getAccessToken(){return this.accessToken}getRefreshToken(){return this.refreshToken}hasRefreshToken(){return this.refreshToken!==null}setTokens(t,e){this.accessToken=t,this.refreshToken=e,this.saveRefreshToken(e),this.scheduleRefresh(t)}clearTokens(){this.accessToken=null,this.refreshToken=null,this.removeRefreshToken(),this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}destroy(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}scheduleRefresh(t){var r;this.refreshTimer&&clearTimeout(this.refreshTimer);const e=this.getTokenExpiry(t);if(!e)return;const s=e*1e3-Date.now()-6e4;if(s<=0){(r=this.onRefreshNeeded)==null||r.call(this);return}this.refreshTimer=setTimeout(()=>{var i;(i=this.onRefreshNeeded)==null||i.call(this)},s)}getTokenExpiry(t){try{const e=t.split(".")[1];return JSON.parse(atob(e)).exp??null}catch{return null}}loadRefreshToken(){try{return localStorage.getItem(this.storageKey)}catch{return null}}saveRefreshToken(t){try{localStorage.setItem(this.storageKey,t)}catch{}}removeRefreshToken(){try{localStorage.removeItem(this.storageKey)}catch{}}}class M{constructor(){this.listeners=new Map}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>{var s;(s=this.listeners.get(t))==null||s.delete(e)}}emit(t,e){var s;(s=this.listeners.get(t))==null||s.forEach(r=>r(e))}removeAll(){this.listeners.clear()}}const k=500,T=600,U=5*60*1e3;class w{constructor(t,e,s,r){this.cachedUser=null,this.cachedSettings=null,this.loaded=!1,this.transport=t,this.tokenManager=e,this.emitter=s,this.baseUrl=r}async load(){var t,e;if(!this.loaded){try{this.cachedSettings=await this.transport.get("/auth/settings")}catch{}if((t=this.tokenManager)!=null&&t.hasRefreshToken())try{await this.performRefresh()}catch{(e=this.tokenManager)==null||e.clearTokens()}this.loaded=!0}}async signIn(t,e){const s=await this.transport.post("/auth/login",{email:t,password:e});if("mfaRequired"in s&&s.mfaRequired)return s;const r=s;return this.setSession(r),r}async signUp(t,e){const s=await this.transport.post("/auth/register",{email:t,password:e});return this.setSession(s),s}async signOut(){var e;const t=(e=this.tokenManager)==null?void 0:e.getRefreshToken();if(t)try{await this.transport.post("/auth/logout",{refreshToken:t})}catch{}this.clearSession()}async signInWithOAuth(t){const e=`${this.baseUrl}/auth/oauth/${t}/popup-callback`,{authUrl:s,state:r}=await this.transport.get(`/auth/oauth/${t}?redirect_uri=${encodeURIComponent(e)}`),i=window.screenX+(window.innerWidth-k)/2,y=window.screenY+(window.innerHeight-T)/2,a=window.open(s,"saas-support-oauth",`width=${k},height=${T},left=${i},top=${y},toolbar=no,menubar=no`);return new Promise((d,u)=>{let o=!1;const c=async h=>{var m;if(((m=h.data)==null?void 0:m.type)==="saas-support:oauth-callback"&&!o){if(o=!0,window.removeEventListener("message",c),clearTimeout(f),clearInterval(p),a==null||a.close(),h.data.error){u(new Error(`OAuth error: ${h.data.error}`));return}try{const l=await this.transport.post(`/auth/oauth/${t}/callback`,{code:h.data.code,state:h.data.state||r});this.setSession(l),d(l)}catch(l){u(l)}}};window.addEventListener("message",c);const f=setTimeout(()=>{o||(o=!0,window.removeEventListener("message",c),clearInterval(p),a==null||a.close(),u(new Error("OAuth popup timed out")))},U),p=setInterval(()=>{a!=null&&a.closed&&!o&&(o=!0,clearInterval(p),clearTimeout(f),window.removeEventListener("message",c),u(new Error("OAuth popup was closed")))},500)})}async submitMfaCode(t,e){const s=await this.transport.post("/auth/login/mfa",{mfaToken:t,code:e});return this.setSession(s),s}async sendMagicLink(t,e){await this.transport.post("/auth/magic-link/send",{email:t,redirectUrl:e})}async verifyMagicLink(t){const e=await this.transport.post("/auth/magic-link/verify",{token:t});return this.setSession(e),e}async sendPasswordReset(t,e){await this.transport.post("/auth/password-reset/send",{email:t,redirectUrl:e})}async resetPassword(t,e){await this.transport.post("/auth/password-reset/verify",{token:t,newPassword:e})}async setupMfa(){return this.transport.post("/auth/mfa/setup",void 0,this.authHeaders())}async verifyMfa(t){return this.transport.post("/auth/mfa/verify",{code:t},this.authHeaders())}async disableMfa(t){await this.transport.post("/auth/mfa/disable",{code:t},this.authHeaders())}async getToken(){var e,s,r;const t=((e=this.tokenManager)==null?void 0:e.getAccessToken())??null;if(t)return t;if((s=this.tokenManager)!=null&&s.hasRefreshToken())try{return await this.performRefresh(),((r=this.tokenManager)==null?void 0:r.getAccessToken())??null}catch{return this.clearSession(),null}return null}async getUser(){if(this.cachedUser)return this.cachedUser;const t=await this.getToken();if(!t)return null;try{return this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${t}`}),this.cachedUser}catch{return null}}getUserSync(){return this.cachedUser}isLoaded(){return this.loaded}async getSettings(){if(this.cachedSettings)return this.cachedSettings;try{return this.cachedSettings=await this.transport.get("/auth/settings"),this.cachedSettings}catch{return null}}onAuthStateChange(t){return this.emitter.on("authStateChange",t)}async updateProfile(t){const e=await this.transport.patch("/auth/me",{metadata:t},this.authHeaders());return this.cachedUser=e,this.emitter.emit("authStateChange",e),e}async listOrgs(){return this.transport.get("/auth/orgs",this.authHeaders())}async createOrg(t,e){return this.transport.post("/auth/orgs",{name:t,slug:e},this.authHeaders())}async getOrg(t){return this.transport.get(`/auth/orgs/${t}`,this.authHeaders())}async updateOrg(t,e){return this.transport.patch(`/auth/orgs/${t}`,e,this.authHeaders())}async deleteOrg(t){await this.transport.del(`/auth/orgs/${t}`,this.authHeaders())}async listMembers(t){return this.transport.get(`/auth/orgs/${t}/members`,this.authHeaders())}async sendInvite(t,e,s){return this.transport.post(`/auth/orgs/${t}/invites`,{email:e,role:s},this.authHeaders())}async updateMemberRole(t,e,s){await this.transport.patch(`/auth/orgs/${t}/members/${e}`,{role:s},this.authHeaders())}async removeMember(t,e){await this.transport.del(`/auth/orgs/${t}/members/${e}`,this.authHeaders())}async acceptInvite(t){return this.transport.post(`/auth/invites/${t}/accept`,void 0,this.authHeaders())}async performRefresh(){var s;const t=(s=this.tokenManager)==null?void 0:s.getRefreshToken();if(!t)throw new Error("No refresh token");const e=await this.transport.post("/auth/refresh",{refreshToken:t});if(this.tokenManager.setTokens(e.accessToken,e.refreshToken),!this.cachedUser)try{this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${e.accessToken}`}),this.emitter.emit("authStateChange",this.cachedUser)}catch{}}setSession(t){var e;(e=this.tokenManager)==null||e.setTokens(t.accessToken,t.refreshToken),this.cachedUser=t.user,this.emitter.emit("authStateChange",t.user)}clearSession(){var t;(t=this.tokenManager)==null||t.clearTokens(),this.cachedUser=null,this.emitter.emit("authStateChange",null)}authHeaders(){var e;const t=(e=this.tokenManager)==null?void 0:e.getAccessToken();return t?{Authorization:`Bearer ${t}`}:{}}}class S{constructor(t){this.transport=t}async createCustomer(t){return this.transport.post("/billing/customers",t)}async getCustomer(t){return this.transport.get(`/billing/customers/${t}`)}async updateCustomer(t,e){return this.transport.patch(`/billing/customers/${t}`,e)}async subscribe(t,e){return this.transport.post(`/billing/customers/${t}/subscribe`,{planId:e})}async changePlan(t,e){return this.transport.patch(`/billing/customers/${t}/subscription`,{planId:e})}async cancelSubscription(t){return this.transport.del(`/billing/customers/${t}/subscription`)}async getInvoices(t){return this.transport.get(`/billing/customers/${t}/invoices`)}async ingestUsageEvent(t){return this.transport.post("/billing/events",t)}async getCurrentUsage(t){return this.transport.get(`/billing/customers/${t}/usage`)}async createPortalToken(t,e){return this.transport.post("/billing/portal-tokens",{customerId:t,expiresIn:e})}async applyCoupon(t,e){return this.transport.post(`/billing/customers/${t}/coupon`,{code:e})}}class ${constructor(t){this.transport=t}async executeQuery(t){return this.transport.post("/report/query",t)}async listQueries(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/queries${e}`)}async saveQuery(t){return this.transport.post("/report/queries",t)}async updateQuery(t,e){return this.transport.patch(`/report/queries/${t}`,e)}async deleteQuery(t){await this.transport.del(`/report/queries/${t}`)}async listDashboards(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/dashboards${e}`)}async createDashboard(t){return this.transport.post("/report/dashboards",t)}async getDashboard(t){return this.transport.get(`/report/dashboards/${t}`)}async updateDashboard(t,e){return this.transport.patch(`/report/dashboards/${t}`,e)}async deleteDashboard(t){await this.transport.del(`/report/dashboards/${t}`)}async createEmbedToken(t){return this.transport.post("/report/embed-tokens",t)}async listEmbedTokens(){return this.transport.get("/report/embed-tokens")}async revokeEmbedToken(t){await this.transport.del(`/report/embed-tokens/${t}`)}toQueryString(t){const e=Object.entries(t).filter(([,s])=>s!=null&&s!=="");return e.length===0?"":"?"+e.map(([s,r])=>`${s}=${encodeURIComponent(String(r))}`).join("&")}}const v="https://api.saas-support.com/v1";class E{constructor(t){if(this.tokenManager=null,this.loaded=!1,!t.publishableKey&&!t.apiKey)throw new Error("SaaSSupport: either publishableKey or apiKey is required");const e=t.baseUrl??v;this.emitter=new M;const s=t.publishableKey?new g(e,{type:"publishableKey",key:t.publishableKey}):null,r=t.apiKey?new g(e,{type:"apiKey",key:t.apiKey}):null;t.publishableKey&&(this.tokenManager=new R(t.publishableKey)),this.auth=new w(s??r,this.tokenManager,this.emitter,e),this.billing=new S(r??s),this.report=new $(r??s),this.tokenManager&&this.tokenManager.setRefreshCallback(()=>this.auth.performRefresh())}async load(){this.loaded||(await this.auth.load(),this.loaded=!0)}isLoaded(){return this.loaded}onError(t){return this.emitter.on("error",t)}destroy(){var t;(t=this.tokenManager)==null||t.destroy(),this.emitter.removeAll()}}function C(n){return"mfaRequired"in n&&n.mfaRequired===!0}exports.AuthClient=w;exports.BillingClient=S;exports.ReportClient=$;exports.SaaSError=b;exports.SaaSSupport=E;exports.Transport=g;exports.isMfaRequired=C;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class b extends Error{constructor(t,e,s="unknown"){super(e),this.name="SaaSError",this.code=t,this.domain=s}get isNotFound(){return this.code===404}get isUnauthorized(){return this.code===401}get isForbidden(){return this.code===403}get isConflict(){return this.code===409}get isRateLimited(){return this.code===429}}class g{constructor(t,e){this.baseUrl=t,this.authMode=e}async request(t,e,s,r){const i={"Content-Type":"application/json",...this.getAuthHeaders(),...r},a=await(await fetch(`${this.baseUrl}${e}`,{method:t,headers:i,body:s?JSON.stringify(s):void 0})).json();if(a.code&&a.code>=400){const d=this.inferDomain(e);throw new b(a.code,a.message||"Request failed",d)}return a.data}async get(t,e){return this.request("GET",t,void 0,e)}async post(t,e,s){return this.request("POST",t,e,s)}async patch(t,e,s){return this.request("PATCH",t,e,s)}async del(t,e){return this.request("DELETE",t,void 0,e)}getAuthHeaders(){switch(this.authMode.type){case"publishableKey":case"apiKey":return{"X-API-Key":this.authMode.key};case"portalToken":case"embedToken":return{Authorization:`Bearer ${this.authMode.token}`}}}inferDomain(t){return t.startsWith("/auth")?"auth":t.startsWith("/billing")?"billing":t.startsWith("/report")?"report":"unknown"}}class R{constructor(t){this.accessToken=null,this.refreshToken=null,this.refreshTimer=null,this.onRefreshNeeded=null,this.storageKey=`ss_rt_${t.slice(0,12)}`,this.refreshToken=this.loadRefreshToken()}setRefreshCallback(t){this.onRefreshNeeded=t}getAccessToken(){return this.accessToken}getRefreshToken(){return this.refreshToken}hasRefreshToken(){return this.refreshToken!==null}setTokens(t,e){this.accessToken=t,this.refreshToken=e,this.saveRefreshToken(e),this.scheduleRefresh(t)}clearTokens(){this.accessToken=null,this.refreshToken=null,this.removeRefreshToken(),this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}destroy(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}scheduleRefresh(t){var r;this.refreshTimer&&clearTimeout(this.refreshTimer);const e=this.getTokenExpiry(t);if(!e)return;const s=e*1e3-Date.now()-6e4;if(s<=0){(r=this.onRefreshNeeded)==null||r.call(this);return}this.refreshTimer=setTimeout(()=>{var i;(i=this.onRefreshNeeded)==null||i.call(this)},s)}getTokenExpiry(t){try{const e=t.split(".")[1];return JSON.parse(atob(e)).exp??null}catch{return null}}loadRefreshToken(){try{return localStorage.getItem(this.storageKey)}catch{return null}}saveRefreshToken(t){try{localStorage.setItem(this.storageKey,t)}catch{}}removeRefreshToken(){try{localStorage.removeItem(this.storageKey)}catch{}}}class M{constructor(){this.listeners=new Map}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>{var s;(s=this.listeners.get(t))==null||s.delete(e)}}emit(t,e){var s;(s=this.listeners.get(t))==null||s.forEach(r=>r(e))}removeAll(){this.listeners.clear()}}const k=500,T=600,U=5*60*1e3;class w{constructor(t,e,s,r){this.cachedUser=null,this.cachedSettings=null,this.loaded=!1,this.transport=t,this.tokenManager=e,this.emitter=s,this.baseUrl=r}async load(){var t,e;if(!this.loaded){try{this.cachedSettings=await this.transport.get("/auth/settings")}catch(s){console.warn("[SaaS Support] Failed to load project settings:",s)}if((t=this.tokenManager)!=null&&t.hasRefreshToken())try{await this.performRefresh()}catch{(e=this.tokenManager)==null||e.clearTokens()}this.loaded=!0}}async signIn(t,e){const s=await this.transport.post("/auth/login",{email:t,password:e});if("mfaRequired"in s&&s.mfaRequired)return s;const r=s;return this.setSession(r),r}async signUp(t,e){const s=await this.transport.post("/auth/register",{email:t,password:e});return this.setSession(s),s}async signOut(){var e;const t=(e=this.tokenManager)==null?void 0:e.getRefreshToken();if(t)try{await this.transport.post("/auth/logout",{refreshToken:t})}catch{}this.clearSession()}async signInWithOAuth(t){const e=`${this.baseUrl}/auth/oauth/${t}/popup-callback`,{authUrl:s,state:r}=await this.transport.get(`/auth/oauth/${t}?redirect_uri=${encodeURIComponent(e)}`),i=window.screenX+(window.innerWidth-k)/2,y=window.screenY+(window.innerHeight-T)/2,a=window.open(s,"saas-support-oauth",`width=${k},height=${T},left=${i},top=${y},toolbar=no,menubar=no`);return new Promise((d,c)=>{let o=!1;const u=async h=>{var m;if(((m=h.data)==null?void 0:m.type)==="saas-support:oauth-callback"&&!o){if(o=!0,window.removeEventListener("message",u),clearTimeout(f),clearInterval(p),a==null||a.close(),h.data.error){c(new Error(`OAuth error: ${h.data.error}`));return}try{const l=await this.transport.post(`/auth/oauth/${t}/callback`,{code:h.data.code,state:h.data.state||r});this.setSession(l),d(l)}catch(l){c(l)}}};window.addEventListener("message",u);const f=setTimeout(()=>{o||(o=!0,window.removeEventListener("message",u),clearInterval(p),a==null||a.close(),c(new Error("OAuth popup timed out")))},U),p=setInterval(()=>{a!=null&&a.closed&&!o&&(o=!0,clearInterval(p),clearTimeout(f),window.removeEventListener("message",u),c(new Error("OAuth popup was closed")))},500)})}async submitMfaCode(t,e){const s=await this.transport.post("/auth/login/mfa",{mfaToken:t,code:e});return this.setSession(s),s}async sendMagicLink(t,e){await this.transport.post("/auth/magic-link/send",{email:t,redirectUrl:e})}async verifyMagicLink(t){const e=await this.transport.post("/auth/magic-link/verify",{token:t});return this.setSession(e),e}async sendPasswordReset(t,e){await this.transport.post("/auth/password-reset/send",{email:t,redirectUrl:e})}async resetPassword(t,e){await this.transport.post("/auth/password-reset/verify",{token:t,newPassword:e})}async setupMfa(){return this.transport.post("/auth/mfa/setup",void 0,this.authHeaders())}async verifyMfa(t){return this.transport.post("/auth/mfa/verify",{code:t},this.authHeaders())}async disableMfa(t){await this.transport.post("/auth/mfa/disable",{code:t},this.authHeaders())}async getToken(){var e,s,r;const t=((e=this.tokenManager)==null?void 0:e.getAccessToken())??null;if(t)return t;if((s=this.tokenManager)!=null&&s.hasRefreshToken())try{return await this.performRefresh(),((r=this.tokenManager)==null?void 0:r.getAccessToken())??null}catch{return this.clearSession(),null}return null}async getUser(){if(this.cachedUser)return this.cachedUser;const t=await this.getToken();if(!t)return null;try{return this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${t}`}),this.cachedUser}catch{return null}}getUserSync(){return this.cachedUser}isLoaded(){return this.loaded}async getSettings(){if(this.cachedSettings)return this.cachedSettings;try{return this.cachedSettings=await this.transport.get("/auth/settings"),this.cachedSettings}catch{return null}}onAuthStateChange(t){return this.emitter.on("authStateChange",t)}async updateProfile(t){const e=await this.transport.patch("/auth/me",t,this.authHeaders());return this.cachedUser=e,this.emitter.emit("authStateChange",e),e}async changePassword(t,e){await this.transport.post("/auth/change-password",{currentPassword:t,newPassword:e},this.authHeaders())}async listOrgs(){return this.transport.get("/auth/orgs",this.authHeaders())}async createOrg(t,e){return this.transport.post("/auth/orgs",{name:t,slug:e},this.authHeaders())}async getOrg(t){return this.transport.get(`/auth/orgs/${t}`,this.authHeaders())}async updateOrg(t,e){return this.transport.patch(`/auth/orgs/${t}`,e,this.authHeaders())}async deleteOrg(t){await this.transport.del(`/auth/orgs/${t}`,this.authHeaders())}async listMembers(t){return this.transport.get(`/auth/orgs/${t}/members`,this.authHeaders())}async sendInvite(t,e,s){return this.transport.post(`/auth/orgs/${t}/invites`,{email:e,role:s},this.authHeaders())}async updateMemberRole(t,e,s){await this.transport.patch(`/auth/orgs/${t}/members/${e}`,{role:s},this.authHeaders())}async removeMember(t,e){await this.transport.del(`/auth/orgs/${t}/members/${e}`,this.authHeaders())}async acceptInvite(t){return this.transport.post(`/auth/invites/${t}/accept`,void 0,this.authHeaders())}async performRefresh(){var s;const t=(s=this.tokenManager)==null?void 0:s.getRefreshToken();if(!t)throw new Error("No refresh token");const e=await this.transport.post("/auth/refresh",{refreshToken:t});if(this.tokenManager.setTokens(e.accessToken,e.refreshToken),!this.cachedUser)try{this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${e.accessToken}`}),this.emitter.emit("authStateChange",this.cachedUser)}catch{}}setSession(t){var e;(e=this.tokenManager)==null||e.setTokens(t.accessToken,t.refreshToken),this.cachedUser=t.user,this.emitter.emit("authStateChange",t.user)}clearSession(){var t;(t=this.tokenManager)==null||t.clearTokens(),this.cachedUser=null,this.emitter.emit("authStateChange",null)}authHeaders(){var e;const t=(e=this.tokenManager)==null?void 0:e.getAccessToken();return t?{Authorization:`Bearer ${t}`}:{}}}class S{constructor(t){this.transport=t}async createCustomer(t){return this.transport.post("/billing/customers",t)}async getCustomer(t){return this.transport.get(`/billing/customers/${t}`)}async updateCustomer(t,e){return this.transport.patch(`/billing/customers/${t}`,e)}async subscribe(t,e){return this.transport.post(`/billing/customers/${t}/subscribe`,{planId:e})}async changePlan(t,e){return this.transport.patch(`/billing/customers/${t}/subscription`,{planId:e})}async cancelSubscription(t){return this.transport.del(`/billing/customers/${t}/subscription`)}async getInvoices(t){return this.transport.get(`/billing/customers/${t}/invoices`)}async ingestUsageEvent(t){return this.transport.post("/billing/events",t)}async getCurrentUsage(t){return this.transport.get(`/billing/customers/${t}/usage`)}async createPortalToken(t,e){return this.transport.post("/billing/portal-tokens",{customerId:t,expiresIn:e})}async applyCoupon(t,e){return this.transport.post(`/billing/customers/${t}/coupon`,{code:e})}}class ${constructor(t){this.transport=t}async executeQuery(t){return this.transport.post("/report/query",t)}async listQueries(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/queries${e}`)}async saveQuery(t){return this.transport.post("/report/queries",t)}async updateQuery(t,e){return this.transport.patch(`/report/queries/${t}`,e)}async deleteQuery(t){await this.transport.del(`/report/queries/${t}`)}async listDashboards(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/dashboards${e}`)}async createDashboard(t){return this.transport.post("/report/dashboards",t)}async getDashboard(t){return this.transport.get(`/report/dashboards/${t}`)}async updateDashboard(t,e){return this.transport.patch(`/report/dashboards/${t}`,e)}async deleteDashboard(t){await this.transport.del(`/report/dashboards/${t}`)}async createEmbedToken(t){return this.transport.post("/report/embed-tokens",t)}async listEmbedTokens(){return this.transport.get("/report/embed-tokens")}async revokeEmbedToken(t){await this.transport.del(`/report/embed-tokens/${t}`)}toQueryString(t){const e=Object.entries(t).filter(([,s])=>s!=null&&s!=="");return e.length===0?"":"?"+e.map(([s,r])=>`${s}=${encodeURIComponent(String(r))}`).join("&")}}const v="https://api.saas-support.com/v1";class E{constructor(t){if(this.tokenManager=null,this.loaded=!1,!t.publishableKey&&!t.apiKey)throw new Error("SaaSSupport: either publishableKey or apiKey is required");const e=t.baseUrl??v;this.emitter=new M;const s=t.publishableKey?new g(e,{type:"publishableKey",key:t.publishableKey}):null,r=t.apiKey?new g(e,{type:"apiKey",key:t.apiKey}):null;t.publishableKey&&(this.tokenManager=new R(t.publishableKey)),this.auth=new w(s??r,this.tokenManager,this.emitter,e),this.billing=new S(r??s),this.report=new $(r??s),this.tokenManager&&this.tokenManager.setRefreshCallback(()=>this.auth.performRefresh())}async load(){this.loaded||(await this.auth.load(),this.loaded=!0)}isLoaded(){return this.loaded}onError(t){return this.emitter.on("error",t)}destroy(){var t;(t=this.tokenManager)==null||t.destroy(),this.emitter.removeAll()}}function C(n){return"mfaRequired"in n&&n.mfaRequired===!0}exports.AuthClient=w;exports.BillingClient=S;exports.ReportClient=$;exports.SaaSError=b;exports.SaaSSupport=E;exports.Transport=g;exports.isMfaRequired=C;
package/dist/index.d.ts CHANGED
@@ -39,7 +39,12 @@ export declare class AuthClient {
39
39
  isLoaded(): boolean;
40
40
  getSettings(): Promise<ProjectSettings | null>;
41
41
  onAuthStateChange(callback: AuthStateCallback): () => void;
42
- updateProfile(metadata: Record<string, unknown>): Promise<User>;
42
+ updateProfile(params: {
43
+ name?: string;
44
+ avatarUrl?: string;
45
+ metadata?: Record<string, unknown>;
46
+ }): Promise<User>;
47
+ changePassword(currentPassword: string, newPassword: string): Promise<void>;
43
48
  listOrgs(): Promise<Org[]>;
44
49
  createOrg(name: string, slug: string): Promise<Org>;
45
50
  getOrg(orgId: string): Promise<Org>;
@@ -486,6 +491,8 @@ export declare interface User {
486
491
  emailVerified: boolean;
487
492
  metadata: Record<string, unknown>;
488
493
  mfaEnabled?: boolean;
494
+ name?: string;
495
+ avatarUrl?: string;
489
496
  }
490
497
 
491
498
  export { }
package/dist/index.js CHANGED
@@ -163,7 +163,8 @@ class R {
163
163
  if (!this.loaded) {
164
164
  try {
165
165
  this.cachedSettings = await this.transport.get("/auth/settings");
166
- } catch {
166
+ } catch (s) {
167
+ console.warn("[SaaS Support] Failed to load project settings:", s);
167
168
  }
168
169
  if ((t = this.tokenManager) != null && t.hasRefreshToken())
169
170
  try {
@@ -312,9 +313,12 @@ class R {
312
313
  // Profile
313
314
  // ---------------------------------------------------------------------------
314
315
  async updateProfile(t) {
315
- const e = await this.transport.patch("/auth/me", { metadata: t }, this.authHeaders());
316
+ const e = await this.transport.patch("/auth/me", t, this.authHeaders());
316
317
  return this.cachedUser = e, this.emitter.emit("authStateChange", e), e;
317
318
  }
319
+ async changePassword(t, e) {
320
+ await this.transport.post("/auth/change-password", { currentPassword: t, newPassword: e }, this.authHeaders());
321
+ }
318
322
  // ---------------------------------------------------------------------------
319
323
  // Organizations
320
324
  // ---------------------------------------------------------------------------
package/dist/react.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),n=require("react"),$=require("./index.cjs"),X=require("react-dom"),D=n.createContext(null);function S(){const e=n.useContext(D);if(!e)throw new Error("useSaaSContext must be used within a <SaaSProvider>");return e}function Z({publishableKey:e,apiKey:a,baseUrl:r,appearance:l,children:t}){const[d]=n.useState(()=>new $.SaaSSupport({publishableKey:e,apiKey:a,baseUrl:r})),[i,u]=n.useState(null),[o,c]=n.useState(!1),[p,g]=n.useState(null);return n.useEffect(()=>{let b=!1;d.load().then(async()=>{if(b)return;const f=await d.auth.getUser(),x=await d.auth.getSettings();u(f),g(x),c(!0)});const m=d.auth.onAuthStateChange(f=>{b||u(f)});return()=>{b=!0,m(),d.destroy()}},[d]),s.jsx(D.Provider,{value:{client:d,user:i,isLoaded:o,appearance:l,settings:p},children:t})}const ss={colorPrimary:"#6366f1",colorPrimaryHover:"#4f46e5",colorBackground:"#ffffff",colorText:"#1a1a2e",colorTextSecondary:"#6b7280",colorInputBackground:"#f9fafb",colorInputBorder:"#d1d5db",colorError:"#ef4444",colorSuccess:"#22c55e",colorWarning:"#f59e0b",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',borderRadius:"8px"},es={colorPrimary:"#818cf8",colorPrimaryHover:"#6366f1",colorBackground:"#1e1e2e",colorText:"#e2e8f0",colorTextSecondary:"#94a3b8",colorInputBackground:"#2a2a3e",colorInputBorder:"#3f3f5e",colorError:"#f87171",colorSuccess:"#4ade80",colorWarning:"#fbbf24",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',borderRadius:"8px"};function P(e){const a=(e==null?void 0:e.baseTheme)==="dark"?es:ss,r=e==null?void 0:e.variables;return{colorPrimary:(r==null?void 0:r.colorPrimary)??a.colorPrimary,colorPrimaryHover:r!=null&&r.colorPrimary?rs(r.colorPrimary,10):a.colorPrimaryHover,colorBackground:(r==null?void 0:r.colorBackground)??a.colorBackground,colorText:(r==null?void 0:r.colorText)??a.colorText,colorTextSecondary:a.colorTextSecondary,colorInputBackground:(r==null?void 0:r.colorInputBackground)??a.colorInputBackground,colorInputBorder:(r==null?void 0:r.colorInputBorder)??a.colorInputBorder,colorError:(r==null?void 0:r.colorError)??a.colorError,colorSuccess:(r==null?void 0:r.colorSuccess)??a.colorSuccess,colorWarning:(r==null?void 0:r.colorWarning)??a.colorWarning,fontFamily:(r==null?void 0:r.fontFamily)??a.fontFamily,borderRadius:(r==null?void 0:r.borderRadius)??a.borderRadius}}function rs(e,a){const r=parseInt(e.replace("#",""),16),l=Math.max(0,(r>>16)-Math.round(2.55*a)),t=Math.max(0,(r>>8&255)-Math.round(2.55*a)),d=Math.max(0,(r&255)-Math.round(2.55*a));return`#${(l<<16|t<<8|d).toString(16).padStart(6,"0")}`}function M(e){return`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),t=require("react"),L=require("./index.cjs"),ss=require("react-dom"),D=t.createContext(null);function w(){const e=t.useContext(D);if(!e)throw new Error("useSaaSContext must be used within a <SaaSProvider>");return e}function es({publishableKey:e,apiKey:r,baseUrl:a,appearance:c,children:o}){const[d]=t.useState(()=>new L.SaaSSupport({publishableKey:e,apiKey:r,baseUrl:a})),[i,u]=t.useState(null),[l,n]=t.useState(!1),[m,p]=t.useState(null);return t.useEffect(()=>{let x=!1;d.load().then(async()=>{if(x)return;const h=await d.auth.getUser(),g=await d.auth.getSettings();u(h),p(g),n(!0)});const y=d.auth.onAuthStateChange(h=>{x||u(h)});return()=>{x=!0,y(),d.destroy()}},[d]),s.jsx(D.Provider,{value:{client:d,user:i,isLoaded:l,appearance:c,settings:m},children:o})}const as={colorPrimary:"#6366f1",colorPrimaryHover:"#4f46e5",colorBackground:"#ffffff",colorText:"#1a1a2e",colorTextSecondary:"#6b7280",colorInputBackground:"#f9fafb",colorInputBorder:"#d1d5db",colorError:"#ef4444",colorSuccess:"#22c55e",colorWarning:"#f59e0b",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',borderRadius:"8px"},rs={colorPrimary:"#818cf8",colorPrimaryHover:"#6366f1",colorBackground:"#1e1e2e",colorText:"#e2e8f0",colorTextSecondary:"#94a3b8",colorInputBackground:"#2a2a3e",colorInputBorder:"#3f3f5e",colorError:"#f87171",colorSuccess:"#4ade80",colorWarning:"#fbbf24",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',borderRadius:"8px"};function z(e){const r=(e==null?void 0:e.baseTheme)==="dark"?rs:as,a=e==null?void 0:e.variables;return{colorPrimary:(a==null?void 0:a.colorPrimary)??r.colorPrimary,colorPrimaryHover:a!=null&&a.colorPrimary?ts(a.colorPrimary,10):r.colorPrimaryHover,colorBackground:(a==null?void 0:a.colorBackground)??r.colorBackground,colorText:(a==null?void 0:a.colorText)??r.colorText,colorTextSecondary:r.colorTextSecondary,colorInputBackground:(a==null?void 0:a.colorInputBackground)??r.colorInputBackground,colorInputBorder:(a==null?void 0:a.colorInputBorder)??r.colorInputBorder,colorError:(a==null?void 0:a.colorError)??r.colorError,colorSuccess:(a==null?void 0:a.colorSuccess)??r.colorSuccess,colorWarning:(a==null?void 0:a.colorWarning)??r.colorWarning,fontFamily:(a==null?void 0:a.fontFamily)??r.fontFamily,borderRadius:(a==null?void 0:a.borderRadius)??r.borderRadius}}function ts(e,r){const a=parseInt(e.replace("#",""),16),c=Math.max(0,(a>>16)-Math.round(2.55*r)),o=Math.max(0,(a>>8&255)-Math.round(2.55*r)),d=Math.max(0,(a&255)-Math.round(2.55*r));return`#${(c<<16|o<<8|d).toString(16).padStart(6,"0")}`}function q(e){return`
2
2
  :host {
3
3
  all: initial;
4
4
  font-family: ${e.fontFamily};
@@ -590,4 +590,139 @@
590
590
  font-size: 12px;
591
591
  color: ${e.colorTextSecondary};
592
592
  }
593
- `}function w({children:e,appearance:a}){const r=n.useRef(null),[l,t]=n.useState(null);n.useEffect(()=>{var p;if(!r.current||r.current.shadowRoot){t(((p=r.current)==null?void 0:p.shadowRoot)??null);return}const i=r.current.attachShadow({mode:"open"}),u=P(a),o=document.createElement("style");o.textContent=M(u),i.appendChild(o);const c=document.createElement("div");i.appendChild(c),t(i)},[]),n.useEffect(()=>{if(!l)return;const i=l.querySelector("style");if(i){const u=P(a);i.textContent=M(u)}},[a,l]);const d=(l==null?void 0:l.querySelector("div"))??null;return s.jsx("div",{ref:r,style:{display:"contents"},children:d&&X.createPortal(e,d)})}function q(){const{client:e,user:a,isLoaded:r}=S();return{isLoaded:r,isSignedIn:!!a,user:a,signOut:n.useCallback(()=>e.auth.signOut(),[e]),getToken:n.useCallback(()=>e.auth.getToken(),[e])}}function as(){const{user:e,isLoaded:a}=S();return{user:e,isLoaded:a}}function z(){const{client:e}=S(),[a,r]=n.useState(!1),[l,t]=n.useState(null),d=n.useCallback(async(o,c)=>{r(!0),t(null);try{return await e.auth.signIn(o,c)}catch(p){return t(p instanceof Error?p.message:"Sign in failed"),null}finally{r(!1)}},[e]),i=n.useCallback(async o=>{r(!0),t(null);try{return await e.auth.signInWithOAuth(o)}catch(c){return t(c instanceof Error?c.message:"OAuth sign in failed"),null}finally{r(!1)}},[e]),u=n.useCallback(async(o,c)=>{r(!0),t(null);try{return await e.auth.submitMfaCode(o,c)}catch(p){return t(p instanceof Error?p.message:"MFA verification failed"),null}finally{r(!1)}},[e]);return{signIn:d,signInWithOAuth:i,submitMfaCode:u,isLoading:a,error:l,setError:t}}function F(){const{client:e}=S(),[a,r]=n.useState(!1),[l,t]=n.useState(null);return{signUp:n.useCallback(async(i,u)=>{r(!0),t(null);try{return await e.auth.signUp(i,u)}catch(o){return t(o instanceof Error?o.message:"Sign up failed"),null}finally{r(!1)}},[e]),isLoading:a,error:l,setError:t}}function U(){const{client:e}=S(),[a,r]=n.useState([]),[l,t]=n.useState(null),[d,i]=n.useState([]),[u,o]=n.useState(!1),[c,p]=n.useState(null),g=n.useCallback(async()=>{o(!0),p(null);try{const f=await e.auth.listOrgs();r(f)}catch(f){p(f instanceof Error?f.message:"Failed to load organizations")}finally{o(!1)}},[e]);n.useEffect(()=>{g()},[g]);const b=n.useCallback(async f=>{try{const x=await e.auth.getOrg(f);t(x);const y=await e.auth.listMembers(f);i(y)}catch(x){p(x instanceof Error?x.message:"Failed to load organization")}},[e]),m=n.useCallback(async(f,x)=>{try{const y=await e.auth.createOrg(f,x);return r(h=>[...h,y]),y}catch(y){return p(y instanceof Error?y.message:"Failed to create organization"),null}},[e]);return{orgs:a,selectedOrg:l,members:d,isLoading:u,error:c,refresh:g,selectOrg:b,createOrg:m}}const R='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>',O='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" fill="currentColor"/></svg>';function ts({appearance:e,signUpUrl:a,onSignUp:r}){const{appearance:l,settings:t}=S(),{signIn:d,signInWithOAuth:i,submitMfaCode:u,isLoading:o,error:c,setError:p}=z(),g=e??l,[b,m]=n.useState(""),[f,x]=n.useState(""),[y,h]=n.useState(!1),[j,v]=n.useState(""),[N,k]=n.useState(""),T=n.useCallback(async E=>{if(E.preventDefault(),y){await u(j,N);return}const B=await d(b,f);B&&$.isMfaRequired(B)&&(v(B.mfaToken),h(!0),p(null))},[b,f,y,j,N,d,u,p]),C=n.useCallback(async E=>{await i(E)},[i]),I=(t==null?void 0:t.googleEnabled)||(t==null?void 0:t.githubEnabled);return s.jsx(w,{appearance:g,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Sign in"}),!y&&s.jsxs(s.Fragment,{children:[(t==null?void 0:t.googleEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>C("google"),disabled:o,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:R}}),"Continue with Google"]}),(t==null?void 0:t.githubEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>C("github"),disabled:o,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:O}}),"Continue with GitHub"]}),I&&s.jsx("div",{className:"ss-divider",children:"or"})]}),c&&s.jsx("div",{className:"ss-global-error",children:c}),s.jsxs("form",{onSubmit:T,children:[y?s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-mfa-code",children:"Authentication code"}),s.jsx("input",{id:"ss-mfa-code",className:"ss-input",type:"text",inputMode:"numeric",autoComplete:"one-time-code",placeholder:"Enter 6-digit code",value:N,onChange:E=>k(E.target.value),autoFocus:!0})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-email",children:"Email"}),s.jsx("input",{id:"ss-email",className:"ss-input",type:"email",autoComplete:"email",placeholder:"you@example.com",value:b,onChange:E=>m(E.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-password",children:"Password"}),s.jsx("input",{id:"ss-password",className:"ss-input",type:"password",autoComplete:"current-password",placeholder:"Enter your password",value:f,onChange:E=>x(E.target.value),required:!0})]})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:o,children:[o&&s.jsx("span",{className:"ss-spinner"}),y?"Verify":"Continue"]})]}),y&&s.jsx("div",{className:"ss-footer",children:s.jsx("span",{className:"ss-link",onClick:()=>{h(!1),k(""),p(null)},children:"Back to sign in"})}),!y&&s.jsxs("div",{className:"ss-footer",children:["Don't have an account?"," ",r?s.jsx("span",{className:"ss-link",onClick:r,children:"Sign up"}):a?s.jsx("a",{className:"ss-link",href:a,children:"Sign up"}):s.jsx("span",{className:"ss-link",children:"Sign up"})]})]})})}function ns({appearance:e,signInUrl:a,onSignIn:r}){const{appearance:l,settings:t}=S(),{signUp:d,isLoading:i,error:u,setError:o}=F(),{signInWithOAuth:c}=z(),p=e??l,[g,b]=n.useState(""),[m,f]=n.useState(""),[x,y]=n.useState(""),[h,j]=n.useState(null),v=n.useCallback(async C=>{if(C.preventDefault(),j(null),m!==x){j("Passwords do not match");return}const I=(t==null?void 0:t.passwordMinLength)??8;if(m.length<I){j(`Password must be at least ${I} characters`);return}await d(g,m)},[g,m,x,t,d]),N=n.useCallback(async C=>{await c(C)},[c]),k=(t==null?void 0:t.googleEnabled)||(t==null?void 0:t.githubEnabled),T=h||u;return s.jsx(w,{appearance:p,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Create account"}),(t==null?void 0:t.googleEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>N("google"),disabled:i,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:R}}),"Continue with Google"]}),(t==null?void 0:t.githubEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>N("github"),disabled:i,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:O}}),"Continue with GitHub"]}),k&&s.jsx("div",{className:"ss-divider",children:"or"}),T&&s.jsx("div",{className:"ss-global-error",children:T}),s.jsxs("form",{onSubmit:v,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-email",children:"Email"}),s.jsx("input",{id:"ss-signup-email",className:"ss-input",type:"email",autoComplete:"email",placeholder:"you@example.com",value:g,onChange:C=>b(C.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-password",children:"Password"}),s.jsx("input",{id:"ss-signup-password",className:"ss-input",type:"password",autoComplete:"new-password",placeholder:"Create a password",value:m,onChange:C=>{f(C.target.value),j(null)},required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-confirm",children:"Confirm password"}),s.jsx("input",{id:"ss-signup-confirm",className:"ss-input",type:"password",autoComplete:"new-password",placeholder:"Confirm your password",value:x,onChange:C=>{y(C.target.value),j(null)},required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i,children:[i&&s.jsx("span",{className:"ss-spinner"}),"Create account"]})]}),s.jsxs("div",{className:"ss-footer",children:["Already have an account?"," ",r?s.jsx("span",{className:"ss-link",onClick:r,children:"Sign in"}):a?s.jsx("a",{className:"ss-link",href:a,children:"Sign in"}):s.jsx("span",{className:"ss-link",children:"Sign in"})]})]})})}function os({appearance:e}){const{appearance:a}=S(),{user:r,signOut:l}=q(),t=e??a,[d,i]=n.useState(!1),u=n.useRef(null),o=n.useCallback(p=>{u.current&&!u.current.contains(p.target)&&i(!1)},[]);if(n.useEffect(()=>{if(d){const p=setTimeout(()=>{document.addEventListener("click",o)},0);return()=>{clearTimeout(p),document.removeEventListener("click",o)}}},[d,o]),!r)return null;const c=r.email.charAt(0).toUpperCase();return s.jsx(w,{appearance:t,children:s.jsxs("div",{className:"ss-user-btn",ref:u,children:[s.jsx("button",{type:"button",className:"ss-avatar",onClick:()=>i(!d),"aria-label":"User menu",children:c}),d&&s.jsxs("div",{className:"ss-dropdown",children:[s.jsx("div",{className:"ss-dropdown-header",children:s.jsx("div",{className:"ss-dropdown-email",children:r.email})}),s.jsx("button",{type:"button",className:"ss-dropdown-item ss-dropdown-item-danger",onClick:async()=>{i(!1),await l()},children:"Sign out"})]})]})})}function cs({appearance:e}){const{appearance:a}=S(),{user:r,signOut:l}=q(),t=e??a;return r?s.jsx(w,{appearance:t,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Profile"}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Email"}),s.jsx("input",{className:"ss-input",type:"email",value:r.email,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Provider"}),s.jsx("input",{className:"ss-input",type:"text",value:r.provider,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Email verified"}),s.jsx("input",{className:"ss-input",type:"text",value:r.emailVerified?"Yes":"No",disabled:!0,readOnly:!0})]}),s.jsx("div",{style:{marginTop:"24px"},children:s.jsx("button",{type:"button",className:"ss-btn ss-btn-primary",onClick:()=>l(),style:{background:"#ef4444"},children:"Sign out"})})]})}):null}function ls({appearance:e,onOrgChange:a}){const{appearance:r}=S(),{orgs:l,selectedOrg:t,selectOrg:d,isLoading:i}=U(),u=e??r,[o,c]=n.useState(!1),p=n.useRef(null),g=n.useCallback(m=>{p.current&&!p.current.contains(m.target)&&c(!1)},[]);if(n.useEffect(()=>{if(o){const m=setTimeout(()=>{document.addEventListener("click",g)},0);return()=>{clearTimeout(m),document.removeEventListener("click",g)}}},[o,g]),i||l.length===0)return null;const b=(t==null?void 0:t.name)??"Select organization";return s.jsx(w,{appearance:u,children:s.jsxs("div",{className:"ss-user-btn",ref:p,children:[s.jsxs("button",{type:"button",className:"ss-btn ss-btn-org-switcher",onClick:()=>c(!o),children:[b,s.jsx("span",{className:"ss-chevron",children:o?"▲":"▼"})]}),o&&s.jsx("div",{className:"ss-dropdown ss-dropdown-org",children:l.map(m=>s.jsx("button",{type:"button",className:`ss-dropdown-item ${(t==null?void 0:t.id)===m.id?"ss-dropdown-item-active":""}`,onClick:async()=>{c(!1),await d(m.id),a==null||a(m)},children:m.name},m.id))})]})})}function is(e,a="USD"){return new Intl.NumberFormat("en-US",{style:"currency",currency:a,minimumFractionDigits:e%100===0?0:2}).format(e/100)}function ds({plans:e,currentPlanId:a,onSelectPlan:r,interval:l,appearance:t}){const{appearance:d}=S(),i=t??d,u=l?e.filter(o=>o.interval===l||o.isFree):e;return s.jsx(w,{appearance:i,children:s.jsx("div",{className:"ss-pricing-grid",children:u.map(o=>{const c=o.id===a;return s.jsxs("div",{className:`ss-pricing-card ${c?"ss-pricing-card-current":""}`,children:[s.jsxs("div",{className:"ss-pricing-header",children:[s.jsx("h3",{className:"ss-pricing-name",children:o.name}),o.trialDays>0&&s.jsxs("span",{className:"ss-badge ss-badge-trialing",children:[o.trialDays,"-day trial"]}),o.isFree&&s.jsx("span",{className:"ss-badge ss-badge-active",children:"Free"})]}),s.jsx("div",{className:"ss-pricing-price",children:o.isFree?s.jsx("span",{className:"ss-pricing-amount",children:"Free"}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"ss-pricing-amount",children:is(o.amountCents,o.currency)}),s.jsxs("span",{className:"ss-pricing-interval",children:["/",o.interval]})]})}),o.description&&s.jsx("p",{className:"ss-pricing-desc",children:o.description}),o.features.length>0&&s.jsx("ul",{className:"ss-pricing-features",children:o.features.map((p,g)=>s.jsxs("li",{className:"ss-pricing-feature",children:[s.jsx("span",{className:"ss-check",children:"✓"})," ",p]},g))}),s.jsx("button",{type:"button",className:`ss-btn ${c?"ss-btn-current":"ss-btn-primary"}`,disabled:c,onClick:()=>r(o.id),children:c?"Current plan":"Select plan"})]},o.id)})})})}function us(){const{client:e}=S();return{billing:e.billing}}function L(e){const{client:a}=S();return n.useMemo(()=>{if(e){const r=new $.Transport("https://api.saas-support.com/v1",{type:"portalToken",token:e});return new $.BillingClient(r)}return a.billing},[a,e])}function H(e,a){const r=L(a),[l,t]=n.useState(null),[d,i]=n.useState(!0),[u,o]=n.useState(null),c=n.useCallback(async()=>{i(!0),o(null);try{const p=await r.getCustomer(e);t(p)}catch(p){o(p instanceof Error?p.message:"Failed to load subscription")}finally{i(!1)}},[r,e]);return n.useEffect(()=>{c()},[c]),{customer:l,isLoading:d,error:u,refresh:c}}function W(e,a){const r=L(a),[l,t]=n.useState([]),[d,i]=n.useState(!0),[u,o]=n.useState(null),c=n.useCallback(async()=>{i(!0),o(null);try{const p=await r.getInvoices(e);t(p)}catch(p){o(p instanceof Error?p.message:"Failed to load invoices")}finally{i(!1)}},[r,e]);return n.useEffect(()=>{c()},[c]),{invoices:l,isLoading:d,error:u,refresh:c}}function _(e,a){const r=L(a),[l,t]=n.useState([]),[d,i]=n.useState(!0),[u,o]=n.useState(null),c=n.useCallback(async()=>{i(!0),o(null);try{const p=await r.getCurrentUsage(e);t(p)}catch(p){o(p instanceof Error?p.message:"Failed to load usage")}finally{i(!1)}},[r,e]);return n.useEffect(()=>{c()},[c]),{usage:l,isLoading:d,error:u,refresh:c}}const ps={active:"ss-badge-active"};function Q({customerId:e,portalToken:a,onChangePlan:r,onCancel:l,appearance:t}){const{appearance:d}=S(),{customer:i,isLoading:u,error:o}=H(e,a),c=t??d;return s.jsx(w,{appearance:c,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Subscription"}),u&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),o&&s.jsx("div",{className:"ss-global-error",children:o}),i&&!u&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Customer"}),s.jsx("input",{className:"ss-input",value:i.name||i.email,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Status"}),s.jsx("div",{children:s.jsx("span",{className:`ss-badge ${ps.active}`,children:"Active"})})]}),s.jsxs("div",{className:"ss-btn-group",children:[r&&s.jsx("button",{type:"button",className:"ss-btn ss-btn-primary",onClick:r,children:"Change plan"}),l&&s.jsx("button",{type:"button",className:"ss-btn ss-btn-danger",onClick:l,children:"Cancel subscription"})]})]})]})})}const gs={paid:"ss-badge-active",open:"ss-badge-trialing",draft:"ss-badge-paused",void:"ss-badge-canceled",uncollectible:"ss-badge-past-due"};function xs(e){return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function bs(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2}).format(e/100)}function G({customerId:e,portalToken:a,appearance:r}){const{appearance:l}=S(),{invoices:t,isLoading:d,error:i}=W(e,a),u=r??l,o=[...t].sort((c,p)=>new Date(p.createdAt).getTime()-new Date(c.createdAt).getTime());return s.jsx(w,{appearance:u,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Invoices"}),d&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),i&&s.jsx("div",{className:"ss-global-error",children:i}),!d&&o.length===0&&s.jsx("p",{className:"ss-empty",children:"No invoices yet."}),!d&&o.length>0&&s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{className:"ss-th",children:"Date"}),s.jsx("th",{className:"ss-th",children:"Amount"}),s.jsx("th",{className:"ss-th",children:"Status"}),s.jsx("th",{className:"ss-th",children:"PDF"})]})}),s.jsx("tbody",{children:o.map(c=>s.jsxs("tr",{className:"ss-tr",children:[s.jsx("td",{className:"ss-td",children:xs(c.createdAt)}),s.jsx("td",{className:"ss-td",children:bs(c.amountCents)}),s.jsx("td",{className:"ss-td",children:s.jsx("span",{className:`ss-badge ${gs[c.status]||""}`,children:c.status})}),s.jsx("td",{className:"ss-td",children:c.pdfUrl?s.jsx("a",{className:"ss-link",href:c.pdfUrl,target:"_blank",rel:"noopener noreferrer",children:"Download"}):"—"})]},c.id))})]})]})})}function V({customerId:e,limits:a,portalToken:r,appearance:l}){const{appearance:t}=S(),{usage:d,isLoading:i,error:u}=_(e,r),o=l??t;return s.jsx(w,{appearance:o,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Usage"}),i&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),u&&s.jsx("div",{className:"ss-global-error",children:u}),!i&&d.length===0&&s.jsx("p",{className:"ss-empty",children:"No usage data."}),!i&&d.map(c=>{const p=a==null?void 0:a[c.metric],g=p?Math.min(100,c.total/p*100):null;return s.jsxs("div",{className:"ss-usage-item",children:[s.jsxs("div",{className:"ss-usage-header",children:[s.jsx("span",{className:"ss-usage-metric",children:c.metric}),s.jsxs("span",{className:"ss-usage-value",children:[c.total.toLocaleString(),p?` / ${p.toLocaleString()}`:""]})]}),g!==null&&s.jsx("div",{className:"ss-progress-bar",children:s.jsx("div",{className:`ss-progress-fill ${g>90?"ss-progress-danger":""}`,style:{width:`${g}%`}})})]},c.metric)})]})})}function ms({customerId:e,portalToken:a,limits:r,onChangePlan:l,onCancel:t,appearance:d}){const{appearance:i}=S(),u=d??i,[o,c]=n.useState("subscription"),p=[{id:"subscription",label:"Subscription"},{id:"invoices",label:"Invoices"},{id:"usage",label:"Usage"}];return s.jsx(w,{appearance:u,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Billing"}),s.jsx("div",{className:"ss-tab-group",children:p.map(g=>s.jsx("button",{type:"button",className:`ss-tab ${o===g.id?"ss-tab-active":""}`,onClick:()=>c(g.id),children:g.label},g.id))}),s.jsxs("div",{className:"ss-tab-content",children:[o==="subscription"&&s.jsx(Q,{customerId:e,portalToken:a,onChangePlan:l,onCancel:t}),o==="invoices"&&s.jsx(G,{customerId:e,portalToken:a}),o==="usage"&&s.jsx(V,{customerId:e,portalToken:a,limits:r})]})]})})}function hs({customerId:e,portalToken:a,onApplied:r,appearance:l}){const{appearance:t}=S(),d=L(a),i=l??t,[u,o]=n.useState(""),[c,p]=n.useState(!1),[g,b]=n.useState(null),[m,f]=n.useState(null),x=n.useCallback(async y=>{if(y.preventDefault(),!!u.trim()){p(!0),b(null),f(null);try{const h=await d.applyCoupon(e,u.trim());f(`Coupon applied! ${h.discountType==="percent"?`${h.amount}% off`:`$${(h.amount/100).toFixed(2)} off`}`),o(""),r==null||r(h)}catch(h){b(h instanceof Error?h.message:"Invalid coupon code")}finally{p(!1)}}},[d,e,u,r]);return s.jsx(w,{appearance:i,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Apply coupon"}),g&&s.jsx("div",{className:"ss-global-error",children:g}),m&&s.jsx("div",{className:"ss-success-msg",children:m}),s.jsxs("form",{onSubmit:x,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-coupon-code",children:"Coupon code"}),s.jsx("input",{id:"ss-coupon-code",className:"ss-input",type:"text",placeholder:"Enter coupon code",value:u,onChange:y=>o(y.target.value),required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:c||!u.trim(),children:[c&&s.jsx("span",{className:"ss-spinner"}),"Apply"]})]})]})})}function fs(){const{client:e}=S();return{report:e.report}}function A(){const{client:e}=S(),[a,r]=n.useState(null),[l,t]=n.useState(!1),[d,i]=n.useState(null),u=n.useCallback(async o=>{t(!0),i(null);try{const c=await e.report.executeQuery(o);return r(c),c}catch(c){return i(c instanceof Error?c.message:"Query failed"),null}finally{t(!1)}},[e]);return{result:a,execute:u,isLoading:l,error:d}}function J(e){const{client:a}=S(),[r,l]=n.useState(null),[t,d]=n.useState(!0),[i,u]=n.useState(null),o=n.useCallback(async()=>{d(!0),u(null);try{const c=await a.report.listQueries(e);l(c)}catch(c){u(c instanceof Error?c.message:"Failed to load queries")}finally{d(!1)}},[a,e]);return n.useEffect(()=>{o()},[o]),{queries:(r==null?void 0:r.data)??[],meta:r==null?void 0:r.meta,isLoading:t,error:i,refresh:o}}function ys(e){const{client:a}=S(),[r,l]=n.useState(null),[t,d]=n.useState(!0),[i,u]=n.useState(null),o=n.useCallback(async()=>{d(!0),u(null);try{const c=await a.report.getDashboard(e);l(c)}catch(c){u(c instanceof Error?c.message:"Failed to load dashboard")}finally{d(!1)}},[a,e]);return n.useEffect(()=>{o()},[o]),{dashboard:r,isLoading:t,error:i,refresh:o}}function js(e,a,r="https://api.saas-support.com/v1"){const l=n.useMemo(()=>{const g=new $.Transport(r,{type:"embedToken",token:e});return new $.ReportClient(g)},[e,r]),[t,d]=n.useState(null),[i,u]=n.useState(!0),[o,c]=n.useState(null),p=n.useCallback(async()=>{u(!0),c(null);try{const g=await l.getDashboard(a);d(g)}catch(g){c(g instanceof Error?g.message:"Failed to load dashboard")}finally{u(!1)}},[l,a]);return n.useEffect(()=>{p()},[p]),{dashboard:t,reportClient:l,isLoading:i,error:o,refresh:p}}function Ss({onResult:e,mode:a="both",placeholder:r,appearance:l}){const{appearance:t}=S(),{execute:d,isLoading:i,error:u}=A(),o=l??t,[c,p]=n.useState(""),[g,b]=n.useState(a==="sql"?"sql":"nl"),m=n.useCallback(async f=>{if(f.preventDefault(),!c.trim())return;const y=await d(g==="sql"?{sql:c}:{naturalLanguage:c});y&&(e==null||e(y))},[c,g,d,e]);return s.jsx(w,{appearance:o,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[a==="both"&&s.jsxs("div",{className:"ss-tab-group ss-tab-group-sm",children:[s.jsx("button",{type:"button",className:`ss-tab ${g==="nl"?"ss-tab-active":""}`,onClick:()=>b("nl"),children:"Natural Language"}),s.jsx("button",{type:"button",className:`ss-tab ${g==="sql"?"ss-tab-active":""}`,onClick:()=>b("sql"),children:"SQL"})]}),u&&s.jsx("div",{className:"ss-global-error",children:u}),s.jsxs("form",{onSubmit:m,children:[s.jsx("div",{className:"ss-field",children:s.jsx("textarea",{className:"ss-input ss-query-textarea",placeholder:r??(g==="sql"?"SELECT ...":"Ask a question about your data..."),value:c,onChange:f=>p(f.target.value),rows:3})}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i||!c.trim(),children:[i&&s.jsx("span",{className:"ss-spinner"}),"Run query"]})]})]})})}function Y({columns:e,rows:a,sortable:r=!0,maxRows:l,appearance:t}){const{appearance:d}=S(),i=t??d,[u,o]=n.useState(null),[c,p]=n.useState("asc"),g=n.useMemo(()=>u?[...a].sort((x,y)=>{const h=x[u],j=y[u];if(h==null&&j==null)return 0;if(h==null)return 1;if(j==null)return-1;if(typeof h=="number"&&typeof j=="number")return c==="asc"?h-j:j-h;const v=String(h),N=String(j);return c==="asc"?v.localeCompare(N):N.localeCompare(v)}):a,[a,u,c]),b=l?g.slice(0,l):g,m=x=>{r&&(u===x?p(y=>y==="asc"?"desc":"asc"):(o(x),p("asc")))};function f(x){return x==null?"":typeof x=="object"?JSON.stringify(x):String(x)}return s.jsx(w,{appearance:i,children:s.jsxs("div",{className:"ss-table-container",children:[s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:e.map(x=>s.jsxs("th",{className:`ss-th ${r?"ss-th-sortable":""} ${u===x?c==="asc"?"ss-sorted-asc":"ss-sorted-desc":""}`,onClick:()=>m(x),children:[x,u===x&&s.jsx("span",{className:"ss-sort-indicator",children:c==="asc"?" ▲":" ▼"})]},x))})}),s.jsx("tbody",{children:b.map((x,y)=>s.jsx("tr",{className:"ss-tr",children:e.map(h=>s.jsx("td",{className:"ss-td",children:f(x[h])},h))},y))})]}),l&&a.length>l&&s.jsxs("div",{className:"ss-table-footer",children:["Showing ",l," of ",a.length," rows"]})]})})}function vs(e,a="#6366f1"){const r=parseInt(a.replace("#","").slice(0,2),16),l=[];for(let t=0;t<e;t++){const d=(r+t*Math.floor(360/Math.max(e,1)))%360;l.push(`hsl(${d}, 65%, 55%)`)}return l}function Ns({labels:e,values:a,w:r,h:l,colors:t}){const d=Math.max(...a,1),i=40,u=r-i*2,o=l-i*2,c=Math.max(1,u/e.length-4);return s.jsxs("g",{children:[s.jsx("line",{x1:i,y1:l-i,x2:r-i,y2:l-i,stroke:"#ccc",strokeWidth:1}),a.map((p,g)=>{const b=p/d*o,m=i+u/e.length*g+2,f=l-i-b;return s.jsxs("g",{children:[s.jsx("rect",{x:m,y:f,width:c,height:b,fill:t[g%t.length],rx:2}),s.jsx("text",{x:m+c/2,y:l-i+14,textAnchor:"middle",fontSize:10,fill:"#666",children:e[g].length>8?e[g].slice(0,8)+"...":e[g]})]},g)})]})}function ws({labels:e,values:a,w:r,h:l,colors:t}){const d=Math.max(...a,1),i=40,u=r-i*2,o=l-i*2,c=e.length>1?u/(e.length-1):0,p=a.map((g,b)=>{const m=i+c*b,f=l-i-g/d*o;return`${m},${f}`});return s.jsxs("g",{children:[[.25,.5,.75,1].map(g=>{const b=l-i-g*o;return s.jsx("line",{x1:i,y1:b,x2:r-i,y2:b,stroke:"#eee",strokeWidth:1},g)}),s.jsx("polyline",{points:p.join(" "),fill:"none",stroke:t[0],strokeWidth:2}),a.map((g,b)=>{const m=i+c*b,f=l-i-g/d*o;return s.jsx("circle",{cx:m,cy:f,r:4,fill:t[0]},b)})]})}function ks({labels:e,values:a,w:r,h:l,colors:t}){const d=a.reduce((b,m)=>b+m,0)||1,i=r/2,u=l/2-20,o=Math.min(r,l)/2-40,c=2*Math.PI*o;let p=0;const g=a.map((b,m)=>{const f=b/d,x=f*c,y={dash:x,offset:p,color:t[m%t.length],label:e[m],pct:f};return p+=x,y});return s.jsxs("g",{children:[g.map((b,m)=>s.jsx("circle",{cx:i,cy:u,r:o,fill:"none",stroke:b.color,strokeWidth:o*.6,strokeDasharray:`${b.dash} ${c-b.dash}`,strokeDashoffset:-b.offset,transform:`rotate(-90 ${i} ${u})`},m)),s.jsx("g",{transform:`translate(${i-e.length*30}, ${l-20})`,children:g.slice(0,6).map((b,m)=>s.jsxs("g",{transform:`translate(${m*60}, 0)`,children:[s.jsx("rect",{width:10,height:10,fill:b.color,rx:2}),s.jsx("text",{x:14,y:9,fontSize:9,fill:"#666",children:b.label.length>6?b.label.slice(0,6)+"..":b.label})]},m))})]})}function K({type:e,data:a,title:r,width:l=400,height:t=300,appearance:d}){const{appearance:i}=S(),u=d??i,o=n.useMemo(()=>vs(a.labels.length),[a.labels.length]);return s.jsx(w,{appearance:u,children:s.jsxs("div",{className:"ss-chart-container",children:[r&&s.jsx("h3",{className:"ss-chart-title",children:r}),s.jsxs("svg",{viewBox:`0 0 ${l} ${t}`,width:"100%",style:{maxWidth:l},children:[e==="bar"&&s.jsx(Ns,{labels:a.labels,values:a.values,w:l,h:t,colors:o}),e==="line"&&s.jsx(ws,{labels:a.labels,values:a.values,w:l,h:t,colors:o}),e==="pie"&&s.jsx(ks,{labels:a.labels,values:a.values,w:l,h:t,colors:o})]})]})})}function $s({dashboardId:e,embedToken:a,baseUrl:r,refreshInterval:l,appearance:t}){const d=S(),i=t??(d==null?void 0:d.appearance),u=n.useMemo(()=>{if(a){const h=r??"https://api.saas-support.com/v1",j=new $.Transport(h,{type:"embedToken",token:a});return new $.ReportClient(j)}return d.client.report},[a,r,d]),[o,c]=n.useState([]),[p,g]=n.useState({}),[b,m]=n.useState(!0),[f,x]=n.useState(null),y=n.useCallback(async()=>{m(!0),x(null);try{const h=await u.getDashboard(e),j=JSON.parse(h.layoutJson||"[]");c(j);const v={};for(const N of j)try{const k=await u.listQueries({search:N.queryId,perPage:1});if(k.data.length>0&&k.data[0].generatedSql){const T=await u.executeQuery({sql:k.data[0].generatedSql});v[N.queryId]=T}}catch{}g(v)}catch(h){x(h instanceof Error?h.message:"Failed to load dashboard")}finally{m(!1)}},[u,e]);return n.useEffect(()=>{y()},[y]),n.useEffect(()=>{if(!l||l<=0)return;const h=setInterval(y,l*1e3);return()=>clearInterval(h)},[l,y]),s.jsx(w,{appearance:i,children:s.jsxs("div",{className:"ss-dashboard-grid",children:[b&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading dashboard..."]}),f&&s.jsx("div",{className:"ss-global-error",children:f}),!b&&o.map((h,j)=>{const v=p[h.queryId];if(!v)return null;const N=v.columns.length>=2?{labels:v.rows.map(k=>String(k[v.columns[0]]??"")),values:v.rows.map(k=>Number(k[v.columns[1]]??0))}:{labels:[],values:[]};return s.jsxs("div",{className:"ss-widget",children:[h.title&&s.jsx("h4",{className:"ss-widget-header",children:h.title}),h.chartType==="table"?s.jsx(Y,{columns:v.columns,rows:v.rows,maxRows:50}):s.jsx(K,{type:h.chartType||"bar",data:N,width:h.w,height:h.h})]},j)})]})})}function Cs(e){return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function Es({onSelectQuery:e,onRunQuery:a,appearance:r}){const{appearance:l}=S(),{queries:t,isLoading:d,error:i}=J(),{execute:u,isLoading:o}=A(),c=r??l,p=n.useCallback(async g=>{if(!g.generatedSql)return;const b=await u({sql:g.generatedSql});b&&(a==null||a(b))},[u,a]);return s.jsx(w,{appearance:c,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Saved Queries"}),d&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),i&&s.jsx("div",{className:"ss-global-error",children:i}),!d&&t.length===0&&s.jsx("p",{className:"ss-empty",children:"No saved queries."}),!d&&t.map(g=>s.jsxs("div",{className:"ss-saved-query-card",onClick:()=>e==null?void 0:e(g),children:[s.jsxs("div",{className:"ss-saved-query-header",children:[s.jsx("span",{className:"ss-saved-query-name",children:g.name}),g.chartType&&s.jsx("span",{className:"ss-badge",children:g.chartType})]}),g.naturalLanguage&&s.jsx("p",{className:"ss-saved-query-desc",children:g.naturalLanguage}),s.jsxs("div",{className:"ss-saved-query-footer",children:[s.jsx("span",{className:"ss-saved-query-date",children:Cs(g.createdAt)}),s.jsx("button",{type:"button",className:"ss-btn ss-btn-sm ss-btn-primary",disabled:o||!g.generatedSql,onClick:b=>{b.stopPropagation(),p(g)},children:o?s.jsx("span",{className:"ss-spinner"}):"Run"})]})]},g.id))]})})}function Ts({embedToken:e,dashboardId:a,baseUrl:r="https://api.saas-support.com/v1",refreshInterval:l,appearance:t}){const d=n.useMemo(()=>{const x=new $.Transport(r,{type:"embedToken",token:e});return new $.ReportClient(x)},[e,r]),[i,u]=n.useState([]),[o,c]=n.useState(!0),[p,g]=n.useState(null),b=n.useMemo(()=>P(t),[t]),m=n.useMemo(()=>M(b),[b]),f=n.useCallback(async()=>{c(!0),g(null);try{const x=await d.getDashboard(a),y=JSON.parse(x.layoutJson||"[]"),h=await Promise.all(y.map(async j=>{try{const v=await d.listQueries({search:j.queryId,perPage:1});if(v.data.length>0&&v.data[0].generatedSql){const N=await d.executeQuery({sql:v.data[0].generatedSql});return{...j,result:N}}}catch{}return j}));u(h)}catch(x){g(x instanceof Error?x.message:"Failed to load dashboard")}finally{c(!1)}},[d,a]);return n.useEffect(()=>{f()},[f]),n.useEffect(()=>{if(!l||l<=0)return;const x=setInterval(f,l*1e3);return()=>clearInterval(x)},[l,f]),s.jsx("div",{ref:x=>{if(!x||x.shadowRoot)return;const y=x.attachShadow({mode:"open"}),h=document.createElement("style");h.textContent=m,y.appendChild(h);const j=document.createElement("div");y.appendChild(j)},style:{display:"contents"},children:s.jsxs("div",{className:"ss-dashboard-grid",children:[o&&s.jsx("div",{className:"ss-loading",children:"Loading dashboard..."}),p&&s.jsx("div",{className:"ss-global-error",children:p}),!o&&i.map((x,y)=>{if(!x.result)return null;const{columns:h,rows:j}=x.result;return s.jsxs("div",{className:"ss-widget",children:[x.title&&s.jsx("h4",{className:"ss-widget-header",children:x.title}),s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:h.map(v=>s.jsx("th",{className:"ss-th",children:v},v))})}),s.jsx("tbody",{children:j.slice(0,50).map((v,N)=>s.jsx("tr",{className:"ss-tr",children:h.map(k=>s.jsx("td",{className:"ss-td",children:String(v[k]??"")},k))},N))})]})]},y)})]})})}exports.SaaSError=$.SaaSError;exports.SaaSSupport=$.SaaSSupport;exports.isMfaRequired=$.isMfaRequired;exports.Chart=K;exports.CouponInput=hs;exports.DashboardView=$s;exports.DataTable=Y;exports.InvoiceHistory=G;exports.OrgSwitcher=ls;exports.PaymentPortal=ms;exports.PricingTable=ds;exports.QueryInput=Ss;exports.ReportEmbed=Ts;exports.SaaSContext=D;exports.SaaSProvider=Z;exports.SavedQueryList=Es;exports.SignIn=ts;exports.SignUp=ns;exports.SubscriptionStatus=Q;exports.UsageDisplay=V;exports.UserButton=os;exports.UserProfile=cs;exports.useAuth=q;exports.useBilling=us;exports.useDashboard=ys;exports.useEmbedDashboard=js;exports.useInvoices=W;exports.useOrg=U;exports.useQuery=A;exports.useReport=fs;exports.useSaaSContext=S;exports.useSavedQueries=J;exports.useSignIn=z;exports.useSignUp=F;exports.useSubscription=H;exports.useUsage=_;exports.useUser=as;
593
+
594
+ /* Modal Overlay */
595
+
596
+ .ss-modal-overlay {
597
+ position: fixed;
598
+ top: 0;
599
+ left: 0;
600
+ right: 0;
601
+ bottom: 0;
602
+ background: rgba(0, 0, 0, 0.5);
603
+ display: flex;
604
+ align-items: center;
605
+ justify-content: center;
606
+ z-index: 99999;
607
+ animation: ss-fade-in 0.15s ease-out;
608
+ }
609
+
610
+ @keyframes ss-fade-in {
611
+ from { opacity: 0; }
612
+ to { opacity: 1; }
613
+ }
614
+
615
+ .ss-modal {
616
+ background: ${e.colorBackground};
617
+ border-radius: ${e.borderRadius};
618
+ padding: 32px;
619
+ width: 90%;
620
+ max-width: 480px;
621
+ max-height: 90vh;
622
+ overflow-y: auto;
623
+ box-shadow: 0 16px 64px rgba(0, 0, 0, 0.2);
624
+ border: 1px solid ${e.colorInputBorder};
625
+ animation: ss-scale-in 0.15s ease-out;
626
+ }
627
+
628
+ @keyframes ss-scale-in {
629
+ from { transform: scale(0.95); opacity: 0; }
630
+ to { transform: scale(1); opacity: 1; }
631
+ }
632
+
633
+ .ss-modal-header {
634
+ display: flex;
635
+ align-items: center;
636
+ justify-content: space-between;
637
+ margin-bottom: 24px;
638
+ }
639
+
640
+ .ss-modal-title {
641
+ font-size: 18px;
642
+ font-weight: 700;
643
+ color: ${e.colorText};
644
+ }
645
+
646
+ .ss-modal-close {
647
+ background: none;
648
+ border: none;
649
+ font-size: 20px;
650
+ color: ${e.colorTextSecondary};
651
+ cursor: pointer;
652
+ padding: 4px;
653
+ line-height: 1;
654
+ border-radius: 4px;
655
+ transition: background 0.15s;
656
+ font-family: inherit;
657
+ }
658
+
659
+ .ss-modal-close:hover {
660
+ background: ${e.colorInputBackground};
661
+ color: ${e.colorText};
662
+ }
663
+
664
+ .ss-modal-section {
665
+ padding-top: 20px;
666
+ margin-top: 20px;
667
+ border-top: 1px solid ${e.colorInputBorder};
668
+ }
669
+
670
+ .ss-modal-section-title {
671
+ font-size: 15px;
672
+ font-weight: 600;
673
+ color: ${e.colorText};
674
+ margin-bottom: 16px;
675
+ }
676
+
677
+ .ss-avatar-preview {
678
+ width: 64px;
679
+ height: 64px;
680
+ border-radius: 50%;
681
+ background: ${e.colorPrimary};
682
+ color: #fff;
683
+ display: flex;
684
+ align-items: center;
685
+ justify-content: center;
686
+ font-size: 24px;
687
+ font-weight: 600;
688
+ margin-bottom: 16px;
689
+ overflow: hidden;
690
+ }
691
+
692
+ .ss-avatar-preview img {
693
+ width: 100%;
694
+ height: 100%;
695
+ object-fit: cover;
696
+ }
697
+
698
+ .ss-input-readonly {
699
+ opacity: 0.6;
700
+ cursor: not-allowed;
701
+ }
702
+
703
+ /* Inline form (for org creation in dropdown) */
704
+
705
+ .ss-dropdown-divider {
706
+ height: 1px;
707
+ background: ${e.colorInputBorder};
708
+ margin: 4px 0;
709
+ }
710
+
711
+ .ss-inline-form {
712
+ padding: 12px 16px;
713
+ }
714
+
715
+ .ss-inline-form .ss-field {
716
+ margin-bottom: 8px;
717
+ }
718
+
719
+ .ss-inline-form .ss-input {
720
+ font-size: 13px;
721
+ padding: 6px 10px;
722
+ }
723
+
724
+ .ss-inline-form .ss-btn {
725
+ font-size: 13px;
726
+ padding: 6px 12px;
727
+ }
728
+ `}function P({children:e,appearance:r}){const a=t.useRef(null),[c,o]=t.useState(null);t.useEffect(()=>{var m;if(!a.current||a.current.shadowRoot){o(((m=a.current)==null?void 0:m.shadowRoot)??null);return}const i=a.current.attachShadow({mode:"open"}),u=z(r),l=document.createElement("style");l.textContent=q(u),i.appendChild(l);const n=document.createElement("div");i.appendChild(n),o(i)},[]),t.useEffect(()=>{if(!c)return;const i=c.querySelector("style");if(i){const u=z(r);i.textContent=q(u)}},[r,c]);const d=(c==null?void 0:c.querySelector("div"))??null;return s.jsx("div",{ref:a,style:{display:"contents"},children:d&&ss.createPortal(e,d)})}function M(){const{client:e,user:r,isLoaded:a}=w();return{isLoaded:a,isSignedIn:!!r,user:r,signOut:t.useCallback(()=>e.auth.signOut(),[e]),getToken:t.useCallback(()=>e.auth.getToken(),[e])}}function ns(){const{user:e,isLoaded:r}=w();return{user:e,isLoaded:r}}function F(){const{client:e}=w(),[r,a]=t.useState(!1),[c,o]=t.useState(null),d=t.useCallback(async(l,n)=>{a(!0),o(null);try{return await e.auth.signIn(l,n)}catch(m){return o(m instanceof Error?m.message:"Sign in failed"),null}finally{a(!1)}},[e]),i=t.useCallback(async l=>{a(!0),o(null);try{return await e.auth.signInWithOAuth(l)}catch(n){return o(n instanceof Error?n.message:"OAuth sign in failed"),null}finally{a(!1)}},[e]),u=t.useCallback(async(l,n)=>{a(!0),o(null);try{return await e.auth.submitMfaCode(l,n)}catch(m){return o(m instanceof Error?m.message:"MFA verification failed"),null}finally{a(!1)}},[e]);return{signIn:d,signInWithOAuth:i,submitMfaCode:u,isLoading:r,error:c,setError:o}}function R(){const{client:e}=w(),[r,a]=t.useState(!1),[c,o]=t.useState(null);return{signUp:t.useCallback(async(i,u)=>{a(!0),o(null);try{return await e.auth.signUp(i,u)}catch(l){return o(l instanceof Error?l.message:"Sign up failed"),null}finally{a(!1)}},[e]),isLoading:r,error:c,setError:o}}function O(){const{client:e}=w(),[r,a]=t.useState([]),[c,o]=t.useState(null),[d,i]=t.useState([]),[u,l]=t.useState(!1),[n,m]=t.useState(null),p=t.useCallback(async()=>{l(!0),m(null);try{const h=await e.auth.listOrgs();a(h)}catch(h){m(h instanceof Error?h.message:"Failed to load organizations")}finally{l(!1)}},[e]);t.useEffect(()=>{p()},[p]);const x=t.useCallback(async h=>{try{const g=await e.auth.getOrg(h);o(g);const f=await e.auth.listMembers(h);i(f)}catch(g){m(g instanceof Error?g.message:"Failed to load organization")}},[e]),y=t.useCallback(async(h,g)=>{try{const f=await e.auth.createOrg(h,g);return a(b=>[...b,f]),f}catch(f){return m(f instanceof Error?f.message:"Failed to create organization"),null}},[e]);return{orgs:r,selectedOrg:c,members:d,isLoading:u,error:n,refresh:p,selectOrg:x,createOrg:y}}function A(){const{client:e,user:r}=w(),[a,c]=t.useState(!1),[o,d]=t.useState(null),[i,u]=t.useState(null),l=t.useCallback(async m=>{c(!0),d(null),u(null);try{const p=await e.auth.updateProfile(m);return u("Profile updated"),p}catch(p){return d(p instanceof Error?p.message:"Failed to update profile"),null}finally{c(!1)}},[e]),n=t.useCallback(async(m,p)=>{c(!0),d(null),u(null);try{return await e.auth.changePassword(m,p),u("Password changed successfully"),!0}catch(x){return d(x instanceof Error?x.message:"Failed to change password"),!1}finally{c(!1)}},[e]);return{user:r,updateProfile:l,changePassword:n,isLoading:a,error:o,success:i,setError:d,setSuccess:u}}const W='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>',H='<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" fill="currentColor"/></svg>';function os({appearance:e,signUpUrl:r,onSignUp:a}){const{appearance:c,settings:o}=w(),{signIn:d,signInWithOAuth:i,submitMfaCode:u,isLoading:l,error:n,setError:m}=F(),p=e??c,[x,y]=t.useState(""),[h,g]=t.useState(""),[f,b]=t.useState(!1),[j,v]=t.useState(""),[N,k]=t.useState(""),T=t.useCallback(async I=>{if(I.preventDefault(),f){await u(j,N);return}const C=await d(x,h);C&&L.isMfaRequired(C)&&(v(C.mfaToken),b(!0),m(null))},[x,h,f,j,N,d,u,m]),$=t.useCallback(async I=>{await i(I)},[i]),S=(o==null?void 0:o.googleEnabled)||(o==null?void 0:o.githubEnabled);return s.jsx(P,{appearance:p,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Sign in"}),!f&&s.jsxs(s.Fragment,{children:[(o==null?void 0:o.googleEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>$("google"),disabled:l,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:W}}),"Continue with Google"]}),(o==null?void 0:o.githubEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>$("github"),disabled:l,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:H}}),"Continue with GitHub"]}),S&&s.jsx("div",{className:"ss-divider",children:"or"})]}),n&&s.jsx("div",{className:"ss-global-error",children:n}),s.jsxs("form",{onSubmit:T,children:[f?s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-mfa-code",children:"Authentication code"}),s.jsx("input",{id:"ss-mfa-code",className:"ss-input",type:"text",inputMode:"numeric",autoComplete:"one-time-code",placeholder:"Enter 6-digit code",value:N,onChange:I=>k(I.target.value),autoFocus:!0})]}):s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-email",children:"Email"}),s.jsx("input",{id:"ss-email",className:"ss-input",type:"email",autoComplete:"email",placeholder:"you@example.com",value:x,onChange:I=>y(I.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-password",children:"Password"}),s.jsx("input",{id:"ss-password",className:"ss-input",type:"password",autoComplete:"current-password",placeholder:"Enter your password",value:h,onChange:I=>g(I.target.value),required:!0})]})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:l,children:[l&&s.jsx("span",{className:"ss-spinner"}),f?"Verify":"Continue"]})]}),f&&s.jsx("div",{className:"ss-footer",children:s.jsx("span",{className:"ss-link",onClick:()=>{b(!1),k(""),m(null)},children:"Back to sign in"})}),!f&&s.jsxs("div",{className:"ss-footer",children:["Don't have an account?"," ",a?s.jsx("span",{className:"ss-link",onClick:a,children:"Sign up"}):r?s.jsx("a",{className:"ss-link",href:r,children:"Sign up"}):s.jsx("span",{className:"ss-link",children:"Sign up"})]})]})})}function ls({appearance:e,signInUrl:r,onSignIn:a}){const{appearance:c,settings:o}=w(),{signUp:d,isLoading:i,error:u,setError:l}=R(),{signInWithOAuth:n}=F(),m=e??c,[p,x]=t.useState(""),[y,h]=t.useState(""),[g,f]=t.useState(""),[b,j]=t.useState(null),v=t.useCallback(async $=>{if($.preventDefault(),j(null),y!==g){j("Passwords do not match");return}const S=(o==null?void 0:o.passwordMinLength)??8;if(y.length<S){j(`Password must be at least ${S} characters`);return}await d(p,y)},[p,y,g,o,d]),N=t.useCallback(async $=>{await n($)},[n]),k=(o==null?void 0:o.googleEnabled)||(o==null?void 0:o.githubEnabled),T=b||u;return s.jsx(P,{appearance:m,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Create account"}),(o==null?void 0:o.googleEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>N("google"),disabled:i,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:W}}),"Continue with Google"]}),(o==null?void 0:o.githubEnabled)&&s.jsxs("button",{type:"button",className:"ss-btn-social",onClick:()=>N("github"),disabled:i,children:[s.jsx("span",{dangerouslySetInnerHTML:{__html:H}}),"Continue with GitHub"]}),k&&s.jsx("div",{className:"ss-divider",children:"or"}),T&&s.jsx("div",{className:"ss-global-error",children:T}),s.jsxs("form",{onSubmit:v,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-email",children:"Email"}),s.jsx("input",{id:"ss-signup-email",className:"ss-input",type:"email",autoComplete:"email",placeholder:"you@example.com",value:p,onChange:$=>x($.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-password",children:"Password"}),s.jsx("input",{id:"ss-signup-password",className:"ss-input",type:"password",autoComplete:"new-password",placeholder:"Create a password",value:y,onChange:$=>{h($.target.value),j(null)},required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-signup-confirm",children:"Confirm password"}),s.jsx("input",{id:"ss-signup-confirm",className:"ss-input",type:"password",autoComplete:"new-password",placeholder:"Confirm your password",value:g,onChange:$=>{f($.target.value),j(null)},required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i,children:[i&&s.jsx("span",{className:"ss-spinner"}),"Create account"]})]}),s.jsxs("div",{className:"ss-footer",children:["Already have an account?"," ",a?s.jsx("span",{className:"ss-link",onClick:a,children:"Sign in"}):r?s.jsx("a",{className:"ss-link",href:r,children:"Sign in"}):s.jsx("span",{className:"ss-link",children:"Sign in"})]})]})})}function is({appearance:e}){const{appearance:r}=w(),{user:a,signOut:c}=M(),o=e??r,[d,i]=t.useState(!1),[u,l]=t.useState(!1),n=t.useRef(null),m=t.useCallback(x=>{n.current&&!x.composedPath().includes(n.current)&&i(!1)},[]);if(t.useEffect(()=>{if(d){const x=setTimeout(()=>{document.addEventListener("click",m)},0);return()=>{clearTimeout(x),document.removeEventListener("click",m)}}},[d,m]),!a)return null;const p=(a.name||a.email).charAt(0).toUpperCase();return s.jsx(P,{appearance:o,children:s.jsxs("div",{className:"ss-user-btn",ref:n,children:[s.jsx("button",{type:"button",className:"ss-avatar",onClick:()=>i(!d),"aria-label":"User menu",children:a.avatarUrl?s.jsx("img",{src:a.avatarUrl,alt:"",style:{width:"100%",height:"100%",borderRadius:"50%",objectFit:"cover"}}):p}),d&&s.jsxs("div",{className:"ss-dropdown",children:[s.jsxs("div",{className:"ss-dropdown-header",children:[a.name&&s.jsx("div",{style:{fontWeight:600,fontSize:"14px",color:"inherit"},children:a.name}),s.jsx("div",{className:"ss-dropdown-email",children:a.email})]}),s.jsx("button",{type:"button",className:"ss-dropdown-item",onClick:()=>{i(!1),l(!0)},children:"Profile"}),s.jsx("button",{type:"button",className:"ss-dropdown-item ss-dropdown-item-danger",onClick:async()=>{i(!1),await c()},children:"Sign out"})]}),u&&s.jsx(cs,{onClose:()=>l(!1)})]})})}function cs({onClose:e}){const{user:r,updateProfile:a,changePassword:c,isLoading:o,error:d,success:i,setError:u,setSuccess:l}=A(),[n,m]=t.useState((r==null?void 0:r.name)??""),[p,x]=t.useState((r==null?void 0:r.avatarUrl)??""),[y,h]=t.useState(""),[g,f]=t.useState(""),[b,j]=t.useState(""),[v,N]=t.useState(null),k=t.useCallback(async S=>{S.preventDefault(),u(null),l(null),await a({name:n,avatarUrl:p})},[n,p,a,u,l]),T=t.useCallback(async S=>{if(S.preventDefault(),N(null),u(null),l(null),g!==b){N("Passwords do not match");return}if(g.length<8){N("Password must be at least 8 characters");return}await c(y,g)&&(h(""),f(""),j(""))},[y,g,b,c,u,l]),$=(r==null?void 0:r.provider)==="email";return s.jsx("div",{className:"ss-modal-overlay",onClick:S=>{S.target===S.currentTarget&&e()},children:s.jsxs("div",{className:"ss-modal",children:[s.jsxs("div",{className:"ss-modal-header",children:[s.jsx("span",{className:"ss-modal-title",children:"Profile"}),s.jsx("button",{type:"button",className:"ss-modal-close",onClick:e,children:"✕"})]}),d&&s.jsx("div",{className:"ss-global-error",children:d}),i&&s.jsx("div",{className:"ss-success-msg",children:i}),s.jsx("div",{className:"ss-avatar-preview",children:p?s.jsx("img",{src:p,alt:""}):(n||(r==null?void 0:r.email)||"?").charAt(0).toUpperCase()}),s.jsxs("form",{onSubmit:k,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Name"}),s.jsx("input",{className:"ss-input",type:"text",placeholder:"Your name",value:n,onChange:S=>m(S.target.value)})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Avatar URL"}),s.jsx("input",{className:"ss-input",type:"url",placeholder:"https://example.com/avatar.jpg",value:p,onChange:S=>x(S.target.value)})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Email"}),s.jsx("input",{className:"ss-input ss-input-readonly",type:"email",value:(r==null?void 0:r.email)??"",disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Provider"}),s.jsx("input",{className:"ss-input ss-input-readonly",type:"text",value:(r==null?void 0:r.provider)??"",disabled:!0,readOnly:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:o,children:[o&&s.jsx("span",{className:"ss-spinner"}),"Save changes"]})]}),$&&s.jsxs("div",{className:"ss-modal-section",children:[s.jsx("div",{className:"ss-modal-section-title",children:"Change password"}),v&&s.jsx("div",{className:"ss-global-error",children:v}),s.jsxs("form",{onSubmit:T,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Current password"}),s.jsx("input",{className:"ss-input",type:"password",value:y,onChange:S=>h(S.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"New password"}),s.jsx("input",{className:"ss-input",type:"password",value:g,onChange:S=>f(S.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Confirm new password"}),s.jsx("input",{className:"ss-input",type:"password",value:b,onChange:S=>j(S.target.value),required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:o,children:[o&&s.jsx("span",{className:"ss-spinner"}),"Update password"]})]})]})]})})}function ds({appearance:e}){const{appearance:r}=w(),{user:a,signOut:c}=M(),{updateProfile:o,changePassword:d,isLoading:i,error:u,success:l,setError:n,setSuccess:m}=A(),p=e??r,[x,y]=t.useState((a==null?void 0:a.name)??""),[h,g]=t.useState((a==null?void 0:a.avatarUrl)??""),[f,b]=t.useState(""),[j,v]=t.useState(""),[N,k]=t.useState(""),[T,$]=t.useState(null),S=t.useCallback(async E=>{E.preventDefault(),n(null),m(null),await o({name:x,avatarUrl:h})},[x,h,o,n,m]),I=t.useCallback(async E=>{if(E.preventDefault(),$(null),n(null),m(null),j!==N){$("Passwords do not match");return}if(j.length<8){$("Password must be at least 8 characters");return}await d(f,j)&&(b(""),v(""),k(""))},[f,j,N,d,n,m]);if(!a)return null;const C=a.provider==="email";return s.jsx(P,{appearance:p,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Profile"}),u&&s.jsx("div",{className:"ss-global-error",children:u}),l&&s.jsx("div",{className:"ss-success-msg",children:l}),s.jsx("div",{className:"ss-avatar-preview",style:{margin:"0 auto 16px"},children:h?s.jsx("img",{src:h,alt:""}):(x||a.email).charAt(0).toUpperCase()}),s.jsxs("form",{onSubmit:S,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Name"}),s.jsx("input",{className:"ss-input",type:"text",placeholder:"Your name",value:x,onChange:E=>y(E.target.value)})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Avatar URL"}),s.jsx("input",{className:"ss-input",type:"url",placeholder:"https://example.com/avatar.jpg",value:h,onChange:E=>g(E.target.value)})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Email"}),s.jsx("input",{className:"ss-input ss-input-readonly",type:"email",value:a.email,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Provider"}),s.jsx("input",{className:"ss-input ss-input-readonly",type:"text",value:a.provider,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Email verified"}),s.jsx("input",{className:"ss-input ss-input-readonly",type:"text",value:a.emailVerified?"Yes":"No",disabled:!0,readOnly:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i,children:[i&&s.jsx("span",{className:"ss-spinner"}),"Save changes"]})]}),C&&s.jsxs("div",{className:"ss-modal-section",children:[s.jsx("div",{className:"ss-modal-section-title",children:"Change password"}),T&&s.jsx("div",{className:"ss-global-error",children:T}),s.jsxs("form",{onSubmit:I,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Current password"}),s.jsx("input",{className:"ss-input",type:"password",value:f,onChange:E=>b(E.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"New password"}),s.jsx("input",{className:"ss-input",type:"password",value:j,onChange:E=>v(E.target.value),required:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Confirm new password"}),s.jsx("input",{className:"ss-input",type:"password",value:N,onChange:E=>k(E.target.value),required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i,children:[i&&s.jsx("span",{className:"ss-spinner"}),"Update password"]})]})]}),s.jsx("div",{style:{marginTop:"24px"},children:s.jsx("button",{type:"button",className:"ss-btn ss-btn-danger",onClick:()=>c(),children:"Sign out"})})]})})}function us({appearance:e,onOrgChange:r}){const{appearance:a}=w(),{orgs:c,selectedOrg:o,selectOrg:d,createOrg:i,isLoading:u}=O(),l=e??a,[n,m]=t.useState(!1),[p,x]=t.useState(!1),[y,h]=t.useState(""),[g,f]=t.useState(""),[b,j]=t.useState(null),[v,N]=t.useState(!1),k=t.useRef(null),T=t.useCallback(C=>{k.current&&!C.composedPath().includes(k.current)&&(m(!1),x(!1))},[]);t.useEffect(()=>{if(n){const C=setTimeout(()=>{document.addEventListener("click",T)},0);return()=>{clearTimeout(C),document.removeEventListener("click",T)}}},[n,T]);const $=t.useCallback(C=>{h(C),f(C.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""))},[]),S=t.useCallback(async C=>{C.preventDefault(),j(null),N(!0);try{const E=await i(y,g);E&&(await d(E.id),r==null||r(E),x(!1),h(""),f(""),m(!1))}catch(E){j(E instanceof Error?E.message:"Failed to create organization")}finally{N(!1)}},[y,g,i,d,r]);if(u)return null;const I=(o==null?void 0:o.name)??(c.length===0?"No organization":"Select organization");return s.jsx(P,{appearance:l,children:s.jsxs("div",{className:"ss-user-btn",ref:k,children:[s.jsxs("button",{type:"button",className:"ss-btn ss-btn-org-switcher",onClick:()=>m(!n),children:[I,s.jsx("span",{className:"ss-chevron",children:n?"▲":"▼"})]}),n&&s.jsxs("div",{className:"ss-dropdown ss-dropdown-org",children:[c.map(C=>s.jsx("button",{type:"button",className:`ss-dropdown-item ${(o==null?void 0:o.id)===C.id?"ss-dropdown-item-active":""}`,onClick:async()=>{m(!1),x(!1),await d(C.id),r==null||r(C)},children:C.name},C.id)),s.jsx("div",{className:"ss-dropdown-divider"}),p?s.jsxs("div",{className:"ss-inline-form",children:[b&&s.jsx("div",{className:"ss-global-error",style:{marginBottom:"8px",fontSize:"12px"},children:b}),s.jsxs("form",{onSubmit:S,children:[s.jsx("div",{className:"ss-field",children:s.jsx("input",{className:"ss-input",type:"text",placeholder:"Organization name",value:y,onChange:C=>$(C.target.value),required:!0,autoFocus:!0})}),s.jsx("div",{className:"ss-field",children:s.jsx("input",{className:"ss-input",type:"text",placeholder:"org-slug",value:g,onChange:C=>f(C.target.value),required:!0})}),s.jsxs("div",{className:"ss-btn-group",style:{marginTop:"8px"},children:[s.jsx("button",{type:"button",className:"ss-btn ss-btn-sm ss-btn-current",onClick:()=>{x(!1),j(null)},children:"Cancel"}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-sm ss-btn-primary",disabled:v,children:[v&&s.jsx("span",{className:"ss-spinner"}),"Create"]})]})]})]}):s.jsx("button",{type:"button",className:"ss-dropdown-item",onClick:()=>x(!0),style:{fontWeight:500},children:"+ Create organization"})]})]})})}function ps(e,r="USD"){return new Intl.NumberFormat("en-US",{style:"currency",currency:r,minimumFractionDigits:e%100===0?0:2}).format(e/100)}function ms({plans:e,currentPlanId:r,onSelectPlan:a,interval:c,appearance:o}){const{appearance:d}=w(),i=o??d,u=c?e.filter(l=>l.interval===c||l.isFree):e;return s.jsx(P,{appearance:i,children:s.jsx("div",{className:"ss-pricing-grid",children:u.map(l=>{const n=l.id===r;return s.jsxs("div",{className:`ss-pricing-card ${n?"ss-pricing-card-current":""}`,children:[s.jsxs("div",{className:"ss-pricing-header",children:[s.jsx("h3",{className:"ss-pricing-name",children:l.name}),l.trialDays>0&&s.jsxs("span",{className:"ss-badge ss-badge-trialing",children:[l.trialDays,"-day trial"]}),l.isFree&&s.jsx("span",{className:"ss-badge ss-badge-active",children:"Free"})]}),s.jsx("div",{className:"ss-pricing-price",children:l.isFree?s.jsx("span",{className:"ss-pricing-amount",children:"Free"}):s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"ss-pricing-amount",children:ps(l.amountCents,l.currency)}),s.jsxs("span",{className:"ss-pricing-interval",children:["/",l.interval]})]})}),l.description&&s.jsx("p",{className:"ss-pricing-desc",children:l.description}),l.features.length>0&&s.jsx("ul",{className:"ss-pricing-features",children:l.features.map((m,p)=>s.jsxs("li",{className:"ss-pricing-feature",children:[s.jsx("span",{className:"ss-check",children:"✓"})," ",m]},p))}),s.jsx("button",{type:"button",className:`ss-btn ${n?"ss-btn-current":"ss-btn-primary"}`,disabled:n,onClick:()=>a(l.id),children:n?"Current plan":"Select plan"})]},l.id)})})})}function xs(){const{client:e}=w();return{billing:e.billing}}function B(e){const{client:r}=w();return t.useMemo(()=>{if(e){const a=new L.Transport("https://api.saas-support.com/v1",{type:"portalToken",token:e});return new L.BillingClient(a)}return r.billing},[r,e])}function _(e,r){const a=B(r),[c,o]=t.useState(null),[d,i]=t.useState(!0),[u,l]=t.useState(null),n=t.useCallback(async()=>{i(!0),l(null);try{const m=await a.getCustomer(e);o(m)}catch(m){l(m instanceof Error?m.message:"Failed to load subscription")}finally{i(!1)}},[a,e]);return t.useEffect(()=>{n()},[n]),{customer:c,isLoading:d,error:u,refresh:n}}function Q(e,r){const a=B(r),[c,o]=t.useState([]),[d,i]=t.useState(!0),[u,l]=t.useState(null),n=t.useCallback(async()=>{i(!0),l(null);try{const m=await a.getInvoices(e);o(m)}catch(m){l(m instanceof Error?m.message:"Failed to load invoices")}finally{i(!1)}},[a,e]);return t.useEffect(()=>{n()},[n]),{invoices:c,isLoading:d,error:u,refresh:n}}function G(e,r){const a=B(r),[c,o]=t.useState([]),[d,i]=t.useState(!0),[u,l]=t.useState(null),n=t.useCallback(async()=>{i(!0),l(null);try{const m=await a.getCurrentUsage(e);o(m)}catch(m){l(m instanceof Error?m.message:"Failed to load usage")}finally{i(!1)}},[a,e]);return t.useEffect(()=>{n()},[n]),{usage:c,isLoading:d,error:u,refresh:n}}const gs={active:"ss-badge-active"};function V({customerId:e,portalToken:r,onChangePlan:a,onCancel:c,appearance:o}){const{appearance:d}=w(),{customer:i,isLoading:u,error:l}=_(e,r),n=o??d;return s.jsx(P,{appearance:n,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Subscription"}),u&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),l&&s.jsx("div",{className:"ss-global-error",children:l}),i&&!u&&s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Customer"}),s.jsx("input",{className:"ss-input",value:i.name||i.email,disabled:!0,readOnly:!0})]}),s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",children:"Status"}),s.jsx("div",{children:s.jsx("span",{className:`ss-badge ${gs.active}`,children:"Active"})})]}),s.jsxs("div",{className:"ss-btn-group",children:[a&&s.jsx("button",{type:"button",className:"ss-btn ss-btn-primary",onClick:a,children:"Change plan"}),c&&s.jsx("button",{type:"button",className:"ss-btn ss-btn-danger",onClick:c,children:"Cancel subscription"})]})]})]})})}const bs={paid:"ss-badge-active",open:"ss-badge-trialing",draft:"ss-badge-paused",void:"ss-badge-canceled",uncollectible:"ss-badge-past-due"};function hs(e){return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function fs(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2}).format(e/100)}function J({customerId:e,portalToken:r,appearance:a}){const{appearance:c}=w(),{invoices:o,isLoading:d,error:i}=Q(e,r),u=a??c,l=[...o].sort((n,m)=>new Date(m.createdAt).getTime()-new Date(n.createdAt).getTime());return s.jsx(P,{appearance:u,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Invoices"}),d&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),i&&s.jsx("div",{className:"ss-global-error",children:i}),!d&&l.length===0&&s.jsx("p",{className:"ss-empty",children:"No invoices yet."}),!d&&l.length>0&&s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsxs("tr",{children:[s.jsx("th",{className:"ss-th",children:"Date"}),s.jsx("th",{className:"ss-th",children:"Amount"}),s.jsx("th",{className:"ss-th",children:"Status"}),s.jsx("th",{className:"ss-th",children:"PDF"})]})}),s.jsx("tbody",{children:l.map(n=>s.jsxs("tr",{className:"ss-tr",children:[s.jsx("td",{className:"ss-td",children:hs(n.createdAt)}),s.jsx("td",{className:"ss-td",children:fs(n.amountCents)}),s.jsx("td",{className:"ss-td",children:s.jsx("span",{className:`ss-badge ${bs[n.status]||""}`,children:n.status})}),s.jsx("td",{className:"ss-td",children:n.pdfUrl?s.jsx("a",{className:"ss-link",href:n.pdfUrl,target:"_blank",rel:"noopener noreferrer",children:"Download"}):"—"})]},n.id))})]})]})})}function Y({customerId:e,limits:r,portalToken:a,appearance:c}){const{appearance:o}=w(),{usage:d,isLoading:i,error:u}=G(e,a),l=c??o;return s.jsx(P,{appearance:l,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Usage"}),i&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),u&&s.jsx("div",{className:"ss-global-error",children:u}),!i&&d.length===0&&s.jsx("p",{className:"ss-empty",children:"No usage data."}),!i&&d.map(n=>{const m=r==null?void 0:r[n.metric],p=m?Math.min(100,n.total/m*100):null;return s.jsxs("div",{className:"ss-usage-item",children:[s.jsxs("div",{className:"ss-usage-header",children:[s.jsx("span",{className:"ss-usage-metric",children:n.metric}),s.jsxs("span",{className:"ss-usage-value",children:[n.total.toLocaleString(),m?` / ${m.toLocaleString()}`:""]})]}),p!==null&&s.jsx("div",{className:"ss-progress-bar",children:s.jsx("div",{className:`ss-progress-fill ${p>90?"ss-progress-danger":""}`,style:{width:`${p}%`}})})]},n.metric)})]})})}function ys({customerId:e,portalToken:r,limits:a,onChangePlan:c,onCancel:o,appearance:d}){const{appearance:i}=w(),u=d??i,[l,n]=t.useState("subscription"),m=[{id:"subscription",label:"Subscription"},{id:"invoices",label:"Invoices"},{id:"usage",label:"Usage"}];return s.jsx(P,{appearance:u,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Billing"}),s.jsx("div",{className:"ss-tab-group",children:m.map(p=>s.jsx("button",{type:"button",className:`ss-tab ${l===p.id?"ss-tab-active":""}`,onClick:()=>n(p.id),children:p.label},p.id))}),s.jsxs("div",{className:"ss-tab-content",children:[l==="subscription"&&s.jsx(V,{customerId:e,portalToken:r,onChangePlan:c,onCancel:o}),l==="invoices"&&s.jsx(J,{customerId:e,portalToken:r}),l==="usage"&&s.jsx(Y,{customerId:e,portalToken:r,limits:a})]})]})})}function js({customerId:e,portalToken:r,onApplied:a,appearance:c}){const{appearance:o}=w(),d=B(r),i=c??o,[u,l]=t.useState(""),[n,m]=t.useState(!1),[p,x]=t.useState(null),[y,h]=t.useState(null),g=t.useCallback(async f=>{if(f.preventDefault(),!!u.trim()){m(!0),x(null),h(null);try{const b=await d.applyCoupon(e,u.trim());h(`Coupon applied! ${b.discountType==="percent"?`${b.amount}% off`:`$${(b.amount/100).toFixed(2)} off`}`),l(""),a==null||a(b)}catch(b){x(b instanceof Error?b.message:"Invalid coupon code")}finally{m(!1)}}},[d,e,u,a]);return s.jsx(P,{appearance:i,children:s.jsxs("div",{className:"ss-card",children:[s.jsx("h2",{className:"ss-title",children:"Apply coupon"}),p&&s.jsx("div",{className:"ss-global-error",children:p}),y&&s.jsx("div",{className:"ss-success-msg",children:y}),s.jsxs("form",{onSubmit:g,children:[s.jsxs("div",{className:"ss-field",children:[s.jsx("label",{className:"ss-label",htmlFor:"ss-coupon-code",children:"Coupon code"}),s.jsx("input",{id:"ss-coupon-code",className:"ss-input",type:"text",placeholder:"Enter coupon code",value:u,onChange:f=>l(f.target.value),required:!0})]}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:n||!u.trim(),children:[n&&s.jsx("span",{className:"ss-spinner"}),"Apply"]})]})]})})}function vs(){const{client:e}=w();return{report:e.report}}function U(){const{client:e}=w(),[r,a]=t.useState(null),[c,o]=t.useState(!1),[d,i]=t.useState(null),u=t.useCallback(async l=>{o(!0),i(null);try{const n=await e.report.executeQuery(l);return a(n),n}catch(n){return i(n instanceof Error?n.message:"Query failed"),null}finally{o(!1)}},[e]);return{result:r,execute:u,isLoading:c,error:d}}function K(e){const{client:r}=w(),[a,c]=t.useState(null),[o,d]=t.useState(!0),[i,u]=t.useState(null),l=t.useCallback(async()=>{d(!0),u(null);try{const n=await r.report.listQueries(e);c(n)}catch(n){u(n instanceof Error?n.message:"Failed to load queries")}finally{d(!1)}},[r,e]);return t.useEffect(()=>{l()},[l]),{queries:(a==null?void 0:a.data)??[],meta:a==null?void 0:a.meta,isLoading:o,error:i,refresh:l}}function Ns(e){const{client:r}=w(),[a,c]=t.useState(null),[o,d]=t.useState(!0),[i,u]=t.useState(null),l=t.useCallback(async()=>{d(!0),u(null);try{const n=await r.report.getDashboard(e);c(n)}catch(n){u(n instanceof Error?n.message:"Failed to load dashboard")}finally{d(!1)}},[r,e]);return t.useEffect(()=>{l()},[l]),{dashboard:a,isLoading:o,error:i,refresh:l}}function ws(e,r,a="https://api.saas-support.com/v1"){const c=t.useMemo(()=>{const p=new L.Transport(a,{type:"embedToken",token:e});return new L.ReportClient(p)},[e,a]),[o,d]=t.useState(null),[i,u]=t.useState(!0),[l,n]=t.useState(null),m=t.useCallback(async()=>{u(!0),n(null);try{const p=await c.getDashboard(r);d(p)}catch(p){n(p instanceof Error?p.message:"Failed to load dashboard")}finally{u(!1)}},[c,r]);return t.useEffect(()=>{m()},[m]),{dashboard:o,reportClient:c,isLoading:i,error:l,refresh:m}}function Ss({onResult:e,mode:r="both",placeholder:a,appearance:c}){const{appearance:o}=w(),{execute:d,isLoading:i,error:u}=U(),l=c??o,[n,m]=t.useState(""),[p,x]=t.useState(r==="sql"?"sql":"nl"),y=t.useCallback(async h=>{if(h.preventDefault(),!n.trim())return;const f=await d(p==="sql"?{sql:n}:{naturalLanguage:n});f&&(e==null||e(f))},[n,p,d,e]);return s.jsx(P,{appearance:l,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[r==="both"&&s.jsxs("div",{className:"ss-tab-group ss-tab-group-sm",children:[s.jsx("button",{type:"button",className:`ss-tab ${p==="nl"?"ss-tab-active":""}`,onClick:()=>x("nl"),children:"Natural Language"}),s.jsx("button",{type:"button",className:`ss-tab ${p==="sql"?"ss-tab-active":""}`,onClick:()=>x("sql"),children:"SQL"})]}),u&&s.jsx("div",{className:"ss-global-error",children:u}),s.jsxs("form",{onSubmit:y,children:[s.jsx("div",{className:"ss-field",children:s.jsx("textarea",{className:"ss-input ss-query-textarea",placeholder:a??(p==="sql"?"SELECT ...":"Ask a question about your data..."),value:n,onChange:h=>m(h.target.value),rows:3})}),s.jsxs("button",{type:"submit",className:"ss-btn ss-btn-primary",disabled:i||!n.trim(),children:[i&&s.jsx("span",{className:"ss-spinner"}),"Run query"]})]})]})})}function X({columns:e,rows:r,sortable:a=!0,maxRows:c,appearance:o}){const{appearance:d}=w(),i=o??d,[u,l]=t.useState(null),[n,m]=t.useState("asc"),p=t.useMemo(()=>u?[...r].sort((g,f)=>{const b=g[u],j=f[u];if(b==null&&j==null)return 0;if(b==null)return 1;if(j==null)return-1;if(typeof b=="number"&&typeof j=="number")return n==="asc"?b-j:j-b;const v=String(b),N=String(j);return n==="asc"?v.localeCompare(N):N.localeCompare(v)}):r,[r,u,n]),x=c?p.slice(0,c):p,y=g=>{a&&(u===g?m(f=>f==="asc"?"desc":"asc"):(l(g),m("asc")))};function h(g){return g==null?"":typeof g=="object"?JSON.stringify(g):String(g)}return s.jsx(P,{appearance:i,children:s.jsxs("div",{className:"ss-table-container",children:[s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:e.map(g=>s.jsxs("th",{className:`ss-th ${a?"ss-th-sortable":""} ${u===g?n==="asc"?"ss-sorted-asc":"ss-sorted-desc":""}`,onClick:()=>y(g),children:[g,u===g&&s.jsx("span",{className:"ss-sort-indicator",children:n==="asc"?" ▲":" ▼"})]},g))})}),s.jsx("tbody",{children:x.map((g,f)=>s.jsx("tr",{className:"ss-tr",children:e.map(b=>s.jsx("td",{className:"ss-td",children:h(g[b])},b))},f))})]}),c&&r.length>c&&s.jsxs("div",{className:"ss-table-footer",children:["Showing ",c," of ",r.length," rows"]})]})})}function ks(e,r="#6366f1"){const a=parseInt(r.replace("#","").slice(0,2),16),c=[];for(let o=0;o<e;o++){const d=(a+o*Math.floor(360/Math.max(e,1)))%360;c.push(`hsl(${d}, 65%, 55%)`)}return c}function Cs({labels:e,values:r,w:a,h:c,colors:o}){const d=Math.max(...r,1),i=40,u=a-i*2,l=c-i*2,n=Math.max(1,u/e.length-4);return s.jsxs("g",{children:[s.jsx("line",{x1:i,y1:c-i,x2:a-i,y2:c-i,stroke:"#ccc",strokeWidth:1}),r.map((m,p)=>{const x=m/d*l,y=i+u/e.length*p+2,h=c-i-x;return s.jsxs("g",{children:[s.jsx("rect",{x:y,y:h,width:n,height:x,fill:o[p%o.length],rx:2}),s.jsx("text",{x:y+n/2,y:c-i+14,textAnchor:"middle",fontSize:10,fill:"#666",children:e[p].length>8?e[p].slice(0,8)+"...":e[p]})]},p)})]})}function $s({labels:e,values:r,w:a,h:c,colors:o}){const d=Math.max(...r,1),i=40,u=a-i*2,l=c-i*2,n=e.length>1?u/(e.length-1):0,m=r.map((p,x)=>{const y=i+n*x,h=c-i-p/d*l;return`${y},${h}`});return s.jsxs("g",{children:[[.25,.5,.75,1].map(p=>{const x=c-i-p*l;return s.jsx("line",{x1:i,y1:x,x2:a-i,y2:x,stroke:"#eee",strokeWidth:1},p)}),s.jsx("polyline",{points:m.join(" "),fill:"none",stroke:o[0],strokeWidth:2}),r.map((p,x)=>{const y=i+n*x,h=c-i-p/d*l;return s.jsx("circle",{cx:y,cy:h,r:4,fill:o[0]},x)})]})}function Es({labels:e,values:r,w:a,h:c,colors:o}){const d=r.reduce((x,y)=>x+y,0)||1,i=a/2,u=c/2-20,l=Math.min(a,c)/2-40,n=2*Math.PI*l;let m=0;const p=r.map((x,y)=>{const h=x/d,g=h*n,f={dash:g,offset:m,color:o[y%o.length],label:e[y],pct:h};return m+=g,f});return s.jsxs("g",{children:[p.map((x,y)=>s.jsx("circle",{cx:i,cy:u,r:l,fill:"none",stroke:x.color,strokeWidth:l*.6,strokeDasharray:`${x.dash} ${n-x.dash}`,strokeDashoffset:-x.offset,transform:`rotate(-90 ${i} ${u})`},y)),s.jsx("g",{transform:`translate(${i-e.length*30}, ${c-20})`,children:p.slice(0,6).map((x,y)=>s.jsxs("g",{transform:`translate(${y*60}, 0)`,children:[s.jsx("rect",{width:10,height:10,fill:x.color,rx:2}),s.jsx("text",{x:14,y:9,fontSize:9,fill:"#666",children:x.label.length>6?x.label.slice(0,6)+"..":x.label})]},y))})]})}function Z({type:e,data:r,title:a,width:c=400,height:o=300,appearance:d}){const{appearance:i}=w(),u=d??i,l=t.useMemo(()=>ks(r.labels.length),[r.labels.length]);return s.jsx(P,{appearance:u,children:s.jsxs("div",{className:"ss-chart-container",children:[a&&s.jsx("h3",{className:"ss-chart-title",children:a}),s.jsxs("svg",{viewBox:`0 0 ${c} ${o}`,width:"100%",style:{maxWidth:c},children:[e==="bar"&&s.jsx(Cs,{labels:r.labels,values:r.values,w:c,h:o,colors:l}),e==="line"&&s.jsx($s,{labels:r.labels,values:r.values,w:c,h:o,colors:l}),e==="pie"&&s.jsx(Es,{labels:r.labels,values:r.values,w:c,h:o,colors:l})]})]})})}function Ps({dashboardId:e,embedToken:r,baseUrl:a,refreshInterval:c,appearance:o}){const d=w(),i=o??(d==null?void 0:d.appearance),u=t.useMemo(()=>{if(r){const b=a??"https://api.saas-support.com/v1",j=new L.Transport(b,{type:"embedToken",token:r});return new L.ReportClient(j)}return d.client.report},[r,a,d]),[l,n]=t.useState([]),[m,p]=t.useState({}),[x,y]=t.useState(!0),[h,g]=t.useState(null),f=t.useCallback(async()=>{y(!0),g(null);try{const b=await u.getDashboard(e),j=JSON.parse(b.layoutJson||"[]");n(j);const v={};for(const N of j)try{const k=await u.listQueries({search:N.queryId,perPage:1});if(k.data.length>0&&k.data[0].generatedSql){const T=await u.executeQuery({sql:k.data[0].generatedSql});v[N.queryId]=T}}catch{}p(v)}catch(b){g(b instanceof Error?b.message:"Failed to load dashboard")}finally{y(!1)}},[u,e]);return t.useEffect(()=>{f()},[f]),t.useEffect(()=>{if(!c||c<=0)return;const b=setInterval(f,c*1e3);return()=>clearInterval(b)},[c,f]),s.jsx(P,{appearance:i,children:s.jsxs("div",{className:"ss-dashboard-grid",children:[x&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading dashboard..."]}),h&&s.jsx("div",{className:"ss-global-error",children:h}),!x&&l.map((b,j)=>{const v=m[b.queryId];if(!v)return null;const N=v.columns.length>=2?{labels:v.rows.map(k=>String(k[v.columns[0]]??"")),values:v.rows.map(k=>Number(k[v.columns[1]]??0))}:{labels:[],values:[]};return s.jsxs("div",{className:"ss-widget",children:[b.title&&s.jsx("h4",{className:"ss-widget-header",children:b.title}),b.chartType==="table"?s.jsx(X,{columns:v.columns,rows:v.rows,maxRows:50}):s.jsx(Z,{type:b.chartType||"bar",data:N,width:b.w,height:b.h})]},j)})]})})}function Ts(e){return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function Is({onSelectQuery:e,onRunQuery:r,appearance:a}){const{appearance:c}=w(),{queries:o,isLoading:d,error:i}=K(),{execute:u,isLoading:l}=U(),n=a??c,m=t.useCallback(async p=>{if(!p.generatedSql)return;const x=await u({sql:p.generatedSql});x&&(r==null||r(x))},[u,r]);return s.jsx(P,{appearance:n,children:s.jsxs("div",{className:"ss-card ss-card-wide",children:[s.jsx("h2",{className:"ss-title",children:"Saved Queries"}),d&&s.jsxs("div",{className:"ss-loading",children:[s.jsx("span",{className:"ss-spinner"})," Loading..."]}),i&&s.jsx("div",{className:"ss-global-error",children:i}),!d&&o.length===0&&s.jsx("p",{className:"ss-empty",children:"No saved queries."}),!d&&o.map(p=>s.jsxs("div",{className:"ss-saved-query-card",onClick:()=>e==null?void 0:e(p),children:[s.jsxs("div",{className:"ss-saved-query-header",children:[s.jsx("span",{className:"ss-saved-query-name",children:p.name}),p.chartType&&s.jsx("span",{className:"ss-badge",children:p.chartType})]}),p.naturalLanguage&&s.jsx("p",{className:"ss-saved-query-desc",children:p.naturalLanguage}),s.jsxs("div",{className:"ss-saved-query-footer",children:[s.jsx("span",{className:"ss-saved-query-date",children:Ts(p.createdAt)}),s.jsx("button",{type:"button",className:"ss-btn ss-btn-sm ss-btn-primary",disabled:l||!p.generatedSql,onClick:x=>{x.stopPropagation(),m(p)},children:l?s.jsx("span",{className:"ss-spinner"}):"Run"})]})]},p.id))]})})}function Ls({embedToken:e,dashboardId:r,baseUrl:a="https://api.saas-support.com/v1",refreshInterval:c,appearance:o}){const d=t.useMemo(()=>{const g=new L.Transport(a,{type:"embedToken",token:e});return new L.ReportClient(g)},[e,a]),[i,u]=t.useState([]),[l,n]=t.useState(!0),[m,p]=t.useState(null),x=t.useMemo(()=>z(o),[o]),y=t.useMemo(()=>q(x),[x]),h=t.useCallback(async()=>{n(!0),p(null);try{const g=await d.getDashboard(r),f=JSON.parse(g.layoutJson||"[]"),b=await Promise.all(f.map(async j=>{try{const v=await d.listQueries({search:j.queryId,perPage:1});if(v.data.length>0&&v.data[0].generatedSql){const N=await d.executeQuery({sql:v.data[0].generatedSql});return{...j,result:N}}}catch{}return j}));u(b)}catch(g){p(g instanceof Error?g.message:"Failed to load dashboard")}finally{n(!1)}},[d,r]);return t.useEffect(()=>{h()},[h]),t.useEffect(()=>{if(!c||c<=0)return;const g=setInterval(h,c*1e3);return()=>clearInterval(g)},[c,h]),s.jsx("div",{ref:g=>{if(!g||g.shadowRoot)return;const f=g.attachShadow({mode:"open"}),b=document.createElement("style");b.textContent=y,f.appendChild(b);const j=document.createElement("div");f.appendChild(j)},style:{display:"contents"},children:s.jsxs("div",{className:"ss-dashboard-grid",children:[l&&s.jsx("div",{className:"ss-loading",children:"Loading dashboard..."}),m&&s.jsx("div",{className:"ss-global-error",children:m}),!l&&i.map((g,f)=>{if(!g.result)return null;const{columns:b,rows:j}=g.result;return s.jsxs("div",{className:"ss-widget",children:[g.title&&s.jsx("h4",{className:"ss-widget-header",children:g.title}),s.jsxs("table",{className:"ss-table",children:[s.jsx("thead",{children:s.jsx("tr",{children:b.map(v=>s.jsx("th",{className:"ss-th",children:v},v))})}),s.jsx("tbody",{children:j.slice(0,50).map((v,N)=>s.jsx("tr",{className:"ss-tr",children:b.map(k=>s.jsx("td",{className:"ss-td",children:String(v[k]??"")},k))},N))})]})]},f)})]})})}exports.SaaSError=L.SaaSError;exports.SaaSSupport=L.SaaSSupport;exports.isMfaRequired=L.isMfaRequired;exports.Chart=Z;exports.CouponInput=js;exports.DashboardView=Ps;exports.DataTable=X;exports.InvoiceHistory=J;exports.OrgSwitcher=us;exports.PaymentPortal=ys;exports.PricingTable=ms;exports.QueryInput=Ss;exports.ReportEmbed=Ls;exports.SaaSContext=D;exports.SaaSProvider=es;exports.SavedQueryList=Is;exports.SignIn=os;exports.SignUp=ls;exports.SubscriptionStatus=V;exports.UsageDisplay=Y;exports.UserButton=is;exports.UserProfile=ds;exports.useAuth=M;exports.useBilling=xs;exports.useDashboard=Ns;exports.useEmbedDashboard=ws;exports.useInvoices=Q;exports.useOrg=O;exports.useProfile=A;exports.useQuery=U;exports.useReport=vs;exports.useSaaSContext=w;exports.useSavedQueries=K;exports.useSignIn=F;exports.useSignUp=R;exports.useSubscription=_;exports.useUsage=G;exports.useUser=ns;
package/dist/react.d.ts CHANGED
@@ -45,7 +45,12 @@ declare class AuthClient {
45
45
  isLoaded(): boolean;
46
46
  getSettings(): Promise<ProjectSettings | null>;
47
47
  onAuthStateChange(callback: AuthStateCallback): () => void;
48
- updateProfile(metadata: Record<string, unknown>): Promise<User>;
48
+ updateProfile(params: {
49
+ name?: string;
50
+ avatarUrl?: string;
51
+ metadata?: Record<string, unknown>;
52
+ }): Promise<User>;
53
+ changePassword(currentPassword: string, newPassword: string): Promise<void>;
49
54
  listOrgs(): Promise<Org[]>;
50
55
  createOrg(name: string, slug: string): Promise<Org>;
51
56
  getOrg(orgId: string): Promise<Org>;
@@ -697,6 +702,21 @@ export declare function useOrg(): {
697
702
  createOrg: (name: string, slug: string) => Promise<Org | null>;
698
703
  };
699
704
 
705
+ export declare function useProfile(): {
706
+ user: User | null;
707
+ updateProfile: (params: {
708
+ name?: string;
709
+ avatarUrl?: string;
710
+ metadata?: Record<string, unknown>;
711
+ }) => Promise<User | null>;
712
+ changePassword: (currentPassword: string, newPassword: string) => Promise<boolean>;
713
+ isLoading: boolean;
714
+ error: string | null;
715
+ success: string | null;
716
+ setError: Dispatch<SetStateAction<string | null>>;
717
+ setSuccess: Dispatch<SetStateAction<string | null>>;
718
+ };
719
+
700
720
  export declare function useQuery(): {
701
721
  result: QueryResult | null;
702
722
  execute: (params: QueryParams) => Promise<QueryResult | null>;
@@ -711,6 +731,8 @@ export declare interface User {
711
731
  emailVerified: boolean;
712
732
  metadata: Record<string, unknown>;
713
733
  mfaEnabled?: boolean;
734
+ name?: string;
735
+ avatarUrl?: string;
714
736
  }
715
737
 
716
738
  export declare function UserButton({ appearance: localAppearance }: UserButtonProps): JSX_2.Element | null;