@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 +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +6 -2
- package/dist/react.cjs +137 -2
- package/dist/react.d.ts +23 -1
- package/dist/react.js +1052 -637
- package/package.json +1 -1
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(
|
|
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",
|
|
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"),
|
|
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(
|
|
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;
|