@capitalos/react 0.0.4 → 0.1.0-beta.2

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.
@@ -1,11 +1,10 @@
1
- /// <reference types="react" />
2
-
3
1
  import { IFrameComponent } from 'iframe-resizer';
4
- import { IframeHTMLAttributes } from 'react';
5
2
  import { IFrameMessageData } from 'iframe-resizer';
6
- import { IFrameOptions as IFrameOptions_2 } from 'iframe-resizer';
3
+ import { IFrameOptions } from 'iframe-resizer';
7
4
  import { IFrameResizedData } from 'iframe-resizer';
8
5
  import { IFrameScrollData } from 'iframe-resizer';
6
+ import { default as React_2 } from 'react';
7
+ import { ReactNode } from 'react';
9
8
 
10
9
  /**
11
10
  * Renders the CapitalOS App.
@@ -27,7 +26,11 @@ export declare function App(props: {
27
26
  * Optional callback for when the app encounters an error.
28
27
  */
29
28
  onError?: (error: Error) => void;
30
- }): JSX.Element | null;
29
+ /**
30
+ * Optional component to render while the app is loading.
31
+ */
32
+ loadingComponent?: ReactNode;
33
+ }): JSX.Element;
31
34
 
32
35
  /**
33
36
  * Base class for all SDK errors
@@ -36,17 +39,13 @@ export declare class CapitalOSError extends Error {
36
39
  constructor(message: string);
37
40
  }
38
41
 
39
- declare type IFrameOptions = Omit<IFrameOptions_2, 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'> & {
42
+ export declare const IframeResizer: React_2.ForwardRefExoticComponent<Omit<IFrameOptions, "closedCallback" | "scrollCallback" | "resizedCallback" | "messageCallback" | "initCallback"> & {
40
43
  onClosed?(iframeId: string): void;
41
44
  onInit?(iframe: IFrameComponent): void;
42
45
  onMessage?(data: IFrameMessageData): void;
43
46
  onResized?(data: IFrameResizedData): void;
44
47
  onScroll?(data: IFrameScrollData): boolean;
45
- };
46
-
47
- export declare function IframeResizer(props: IframeResizerProps): JSX.Element;
48
-
49
- declare type IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>;
48
+ } & React_2.IframeHTMLAttributes<HTMLIFrameElement> & React_2.RefAttributes<HTMLIFrameElement>>;
50
49
 
51
50
  /**
52
51
  * Represents an error that occurs when an invalid token is encountered.
@@ -1,11 +1,10 @@
1
- /// <reference types="react" />
2
-
3
1
  import { IFrameComponent } from 'iframe-resizer';
4
- import { IframeHTMLAttributes } from 'react';
5
2
  import { IFrameMessageData } from 'iframe-resizer';
6
- import { IFrameOptions as IFrameOptions_2 } from 'iframe-resizer';
3
+ import { IFrameOptions } from 'iframe-resizer';
7
4
  import { IFrameResizedData } from 'iframe-resizer';
8
5
  import { IFrameScrollData } from 'iframe-resizer';
6
+ import { default as React_2 } from 'react';
7
+ import { ReactNode } from 'react';
9
8
 
10
9
  /**
11
10
  * Renders the CapitalOS App.
@@ -27,7 +26,11 @@ export declare function App(props: {
27
26
  * Optional callback for when the app encounters an error.
28
27
  */
29
28
  onError?: (error: Error) => void;
30
- }): JSX.Element | null;
29
+ /**
30
+ * Optional component to render while the app is loading.
31
+ */
32
+ loadingComponent?: ReactNode;
33
+ }): JSX.Element;
31
34
 
32
35
  /**
33
36
  * Base class for all SDK errors
@@ -36,17 +39,13 @@ export declare class CapitalOSError extends Error {
36
39
  constructor(message: string);
37
40
  }
38
41
 
39
- declare type IFrameOptions = Omit<IFrameOptions_2, 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'> & {
42
+ export declare const IframeResizer: React_2.ForwardRefExoticComponent<Omit<IFrameOptions, "closedCallback" | "scrollCallback" | "resizedCallback" | "messageCallback" | "initCallback"> & {
40
43
  onClosed?(iframeId: string): void;
41
44
  onInit?(iframe: IFrameComponent): void;
42
45
  onMessage?(data: IFrameMessageData): void;
43
46
  onResized?(data: IFrameResizedData): void;
44
47
  onScroll?(data: IFrameScrollData): boolean;
45
- };
46
-
47
- export declare function IframeResizer(props: IframeResizerProps): JSX.Element;
48
-
49
- declare type IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>;
48
+ } & React_2.IframeHTMLAttributes<HTMLIFrameElement> & React_2.RefAttributes<HTMLIFrameElement>>;
50
49
 
51
50
  /**
52
51
  * Represents an error that occurs when an invalid token is encountered.
@@ -0,0 +1,2 @@
1
+ "use client";var z=Object.defineProperty,T=Object.defineProperties;var O=Object.getOwnPropertyDescriptors;var h=Object.getOwnPropertySymbols;var R=Object.prototype.hasOwnProperty,H=Object.prototype.propertyIsEnumerable;var L=(t,e,r)=>e in t?z(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e)=>{for(var r in e||(e={}))R.call(e,r)&&L(t,r,e[r]);if(h)for(var r of h(e))H.call(e,r)&&L(t,r,e[r]);return t},M=(t,e)=>T(t,O(e));import{connectToChild as A}from"penpal";import l,{useEffect as D,useMemo as P}from"react";var f=class extends Error{constructor(e){super(e),this.name="CapitalOSError"}},m=class extends f{constructor(){super("Invalid token"),this.name="CapitalOSInvalidTokenError"}};import{iframeResizer as k}from"iframe-resizer";import C,{forwardRef as E,useEffect as y,useImperativeHandle as v,useRef as N}from"react";var p=E((t,e)=>{let r=t.title||"iframe",{iframeHTMLAttributes:o,resizerOptions:i}=x(t),a=N(null);return y(()=>{let n=a.current;return k(d({},i),n),()=>n.iFrameResizer&&n.iFrameResizer.removeListeners()}),v(e,()=>a.current),C.createElement("iframe",M(d({},o),{title:r,ref:a}))});p.displayName="IframeResizer";var S=["autoResize","bodyBackground","bodyMargin","bodyPadding","checkOrigin","inPageLinks","heightCalculationMethod","interval","log","maxHeight","maxWidth","minHeight","minWidth","resizeFrom","scrolling","sizeHeight","sizeWidth","warningTimeout","tolerance","widthCalculationMethod","onClosed","onInit","onMessage","onResized","onScroll"],w=new Set(S);function x(t){return Object.keys(t).reduce((r,o)=>(w.has(o)?r.resizerOptions[o]=t[o]:r.iframeHTMLAttributes[o]=t[o],r),{resizerOptions:{},iframeHTMLAttributes:{}})}var W=1e4;function oe(t){let{token:e,className:r,enableLogging:o,onError:i,loadingComponent:a}=t,n=l.useRef(null),[u,I]=l.useState(!1),F=P(()=>{try{let s=decodeURIComponent(e),c=atob(s),b=JSON.parse(c),{path:g}=b;if(!g)throw new m;return`${g}?token=${e}`}catch(s){i==null||i(new m);return}},[e,i]);return D(()=>{let s=A({iframe:n.current,childOrigin:"*",debug:!0,timeout:W,methods:{onLoad:()=>{I(!0)}}});return s.promise.catch(c=>{i==null||i(c),I(!0)}),()=>{s.destroy()}},[e]),l.createElement(l.Fragment,null,!u&&a,l.createElement(p,{src:F,allow:"clipboard-write",checkOrigin:!1,style:{width:"1px",height:"0px",minWidth:"100%"},className:r,log:!!o,ref:n,hidden:!u}))}export{oe as App};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/error.ts","../../src/iframe-resizer.tsx"],"sourcesContent":["'use client'\n\nimport { connectToChild } from 'penpal'\nimport React, { ReactNode, useEffect, useMemo } from 'react'\n\nimport { InvalidTokenError } from './error'\nimport { IframeResizer } from './iframe-resizer'\n\nconst IFRAME_CONNECTION_TIMEOUT_MILLISECONDS = 10_000\n\n/**\n * Renders the CapitalOS App.\n */\nexport function App(props: {\n /**\n * The token provided by initiate-login.\n */\n token: string\n /**\n * Optional CSS class name for the component.\n */\n className?: string\n /**\n * Optional flag indicating whether to log events to the console.\n */\n enableLogging?: boolean\n\n /**\n * Optional callback for when the app encounters an error.\n */\n onError?: (error: Error) => void\n\n /**\n * Optional component to render while the app is loading.\n */\n loadingComponent?: ReactNode\n}) {\n const { token, className, enableLogging, onError, loadingComponent: LoadingComponent } = props\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null)\n\n // represents the state of whether all required react queries returned and the page should be visible\n const [isLoaded, setIsLoaded] = React.useState(false)\n\n // memoize the url based on the token so we don't redo the computation on each render.\n const url = useMemo(() => {\n try {\n const urlDecodedToken = decodeURIComponent(token)\n const base64DecodedToken = atob(urlDecodedToken)\n const jsonToken = JSON.parse(base64DecodedToken)\n const { path } = jsonToken\n if (!path) {\n throw new InvalidTokenError()\n }\n return `${path}?token=${token}`\n } catch (error) {\n onError?.(new InvalidTokenError())\n return undefined\n }\n }, [token, onError])\n\n // connect to child iframe\n useEffect(() => {\n const connection = connectToChild({\n iframe: iframeRef.current!,\n childOrigin: '*',\n debug: true,\n timeout: IFRAME_CONNECTION_TIMEOUT_MILLISECONDS,\n methods: {\n onLoad: () => {\n setIsLoaded(true)\n },\n },\n })\n\n connection.promise.catch((error) => {\n onError?.(error)\n\n // when connection fails it's probably a handshake timeout with the iframe. we will stop showing the loader\n // since the fact we failed communication doesn't necessarily mean the iframe didn't load\n setIsLoaded(true)\n })\n\n return () => {\n connection.destroy()\n }\n }, [token])\n\n return (\n <>\n {/* show loader as long as we're not loaded */}\n {!isLoaded && LoadingComponent}\n {/* hide the iframe as long as we're not loaded */}\n <IframeResizer\n src={url}\n allow=\"clipboard-write\"\n checkOrigin={false}\n style={{ width: '1px', height: '0px', minWidth: '100%' }}\n className={className}\n log={!!enableLogging}\n ref={iframeRef}\n hidden={!isLoaded}\n />\n </>\n )\n}\n","/**\n * Base class for all SDK errors\n */\nexport class CapitalOSError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CapitalOSError'\n }\n}\n\n/**\n * Represents an error that occurs when an invalid token is encountered.\n */\nexport class InvalidTokenError extends CapitalOSError {\n constructor() {\n super('Invalid token')\n this.name = 'CapitalOSInvalidTokenError'\n }\n}\n","import {\n IFrameOptions as BrokenIframeOptions,\n IFrameComponent,\n IFrameMessageData,\n IFrameResizedData,\n IFrameScrollData,\n iframeResizer,\n} from 'iframe-resizer'\nimport React, { IframeHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from 'react'\n\n// the events were renamed but package maintainers didn't update the types.\ntype IFrameOptions = Omit<\n BrokenIframeOptions,\n 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'\n> & {\n onClosed?(iframeId: string): void\n onInit?(iframe: IFrameComponent): void\n onMessage?(data: IFrameMessageData): void\n onResized?(data: IFrameResizedData): void\n onScroll?(data: IFrameScrollData): boolean\n}\n\ntype IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>\ntype EnrichedHtmlIframeElement = HTMLIFrameElement & { iFrameResizer: { removeListeners: () => void } }\n\nexport const IframeResizer = forwardRef((props: IframeResizerProps, ref: React.Ref<HTMLIFrameElement>) => {\n const title = props.title || 'iframe'\n const { iframeHTMLAttributes, resizerOptions } = splitProps(props)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n useEffect(() => {\n // effects run after render, so the ref is guaranteed to be set (unless the component conditionally renders the iframe, which is not the case)\n const iframe = iframeRef.current as EnrichedHtmlIframeElement\n\n iframeResizer({ ...resizerOptions }, iframe)\n\n return () => iframe.iFrameResizer && iframe.iFrameResizer.removeListeners()\n })\n\n // make the ref provided as a prop point to the same place as the internal iframe ref.\n useImperativeHandle(ref, () => iframeRef.current as HTMLIFrameElement)\n\n return <iframe {...iframeHTMLAttributes} title={title} ref={iframeRef} />\n})\n\nIframeResizer.displayName = 'IframeResizer'\n\nconst resizerOptions = [\n 'autoResize',\n 'bodyBackground',\n 'bodyMargin',\n 'bodyPadding',\n 'checkOrigin',\n 'inPageLinks',\n 'heightCalculationMethod',\n 'interval',\n 'log',\n 'maxHeight',\n 'maxWidth',\n 'minHeight',\n 'minWidth',\n 'resizeFrom',\n 'scrolling',\n 'sizeHeight',\n 'sizeWidth',\n 'warningTimeout',\n 'tolerance',\n 'widthCalculationMethod',\n 'onClosed',\n 'onInit',\n 'onMessage',\n 'onResized',\n 'onScroll',\n]\n\nconst resizerOptionsSet = new Set(resizerOptions)\n\n/**\n * split props into the resizer library options and the native iframe attributes.\n * the code is contains many type assertions because typescript doesn't handle reduce well.\n */\nfunction splitProps(props: IframeResizerProps) {\n const split = Object.keys(props).reduce<{\n resizerOptions: IFrameOptions\n iframeHTMLAttributes: IframeHTMLAttributes<HTMLIFrameElement>\n }>(\n (acc, key) => {\n if (resizerOptionsSet.has(key)) {\n acc.resizerOptions[key as keyof IFrameOptions] = props[key as keyof typeof props]\n } else {\n acc.iframeHTMLAttributes[key as keyof IframeHTMLAttributes<HTMLIFrameElement>] =\n props[key as keyof typeof props]\n }\n return acc\n },\n { resizerOptions: {}, iframeHTMLAttributes: {} },\n )\n\n return split\n}\n"],"mappings":"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","names":["connectToChild","React","useEffect","useMemo","CapitalOSError","message","InvalidTokenError","iframeResizer","React","forwardRef","useEffect","useImperativeHandle","useRef","IframeResizer","forwardRef","props","ref","title","iframeHTMLAttributes","resizerOptions","splitProps","iframeRef","useRef","useEffect","iframe","iframeResizer","__spreadValues","useImperativeHandle","React","__spreadProps","resizerOptionsSet","acc","key","IFRAME_CONNECTION_TIMEOUT_MILLISECONDS","App","props","token","className","enableLogging","onError","LoadingComponent","iframeRef","React","isLoaded","setIsLoaded","url","useMemo","urlDecodedToken","base64DecodedToken","jsonToken","path","InvalidTokenError","error","useEffect","connection","connectToChild","IframeResizer"]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";"use client";var L=Object.create;var a=Object.defineProperty,T=Object.defineProperties,R=Object.getOwnPropertyDescriptor,E=Object.getOwnPropertyDescriptors,C=Object.getOwnPropertyNames,u=Object.getOwnPropertySymbols,v=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,y=Object.prototype.propertyIsEnumerable;var I=(e,r,t)=>r in e?a(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,c=(e,r)=>{for(var t in r||(r={}))g.call(r,t)&&I(e,t,r[t]);if(u)for(var t of u(r))y.call(r,t)&&I(e,t,r[t]);return e},h=(e,r)=>T(e,E(r));var x=(e,r)=>{for(var t in r)a(e,t,{get:r[t],enumerable:!0})},b=(e,r,t,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of C(r))!g.call(e,i)&&i!==t&&a(e,i,{get:()=>r[i],enumerable:!(o=R(r,i))||o.enumerable});return e};var z=(e,r,t)=>(t=e!=null?L(v(e)):{},b(r||!e||!e.__esModule?a(t,"default",{value:e,enumerable:!0}):t,e)),w=e=>b(a({},"__esModule",{value:!0}),e);var N={};x(N,{App:()=>P});module.exports=w(N);var M=z(require("react"));var d=class extends Error{constructor(r){super(r),this.name="CapitalOSError"}},m=class extends d{constructor(){super("Invalid token"),this.name="CapitalOSInvalidTokenError"}};var F=require("iframe-resizer"),s=z(require("react"));function k(e){let r=e.title||"iframe",{iframeHTMLAttributes:t,resizerOptions:o}=S(e),i=(0,s.useRef)(null);return(0,s.useEffect)(()=>{let n=i.current;return(0,F.iframeResizer)(c({},o),n),()=>n.iFrameResizer&&n.iFrameResizer.removeListeners()}),s.default.createElement("iframe",h(c({},t),{title:r,ref:i}))}var A=["autoResize","bodyBackground","bodyMargin","bodyPadding","checkOrigin","inPageLinks","heightCalculationMethod","interval","log","maxHeight","maxWidth","minHeight","minWidth","resizeFrom","scrolling","sizeHeight","sizeWidth","warningTimeout","tolerance","widthCalculationMethod","onClosed","onInit","onMessage","onResized","onScroll"],D=new Set(A);function S(e){return Object.keys(e).reduce((t,o)=>(D.has(o)?t.resizerOptions[o]=e[o]:t.iframeHTMLAttributes[o]=e[o],t),{resizerOptions:{},iframeHTMLAttributes:{}})}function P(e){let{token:r,className:t,enableLogging:o,onError:i}=e,n=l=>{i&&i(new m)},f;try{let l=decodeURIComponent(r),O=atob(l),H=JSON.parse(O),{path:p}=H;if(!p)return n(new m),null;f=`${p}?token=${r}`}catch(l){return n(l),null}return M.default.createElement(k,{src:f,allow:"clipboard-write",checkOrigin:!1,style:{width:"1px",height:"0px",minWidth:"100%"},className:t,log:!!o})}0&&(module.exports={App});
1
+ "use strict";"use client";var E=Object.create;var c=Object.defineProperty,y=Object.defineProperties,v=Object.getOwnPropertyDescriptor,N=Object.getOwnPropertyDescriptors,S=Object.getOwnPropertyNames,M=Object.getOwnPropertySymbols,w=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var F=(e,t,r)=>t in e?c(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,p=(e,t)=>{for(var r in t||(t={}))b.call(t,r)&&F(e,r,t[r]);if(M)for(var r of M(t))x.call(t,r)&&F(e,r,t[r]);return e},z=(e,t)=>y(e,N(t));var A=(e,t)=>{for(var r in t)c(e,r,{get:t[r],enumerable:!0})},T=(e,t,r,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of S(t))!b.call(e,o)&&o!==r&&c(e,o,{get:()=>t[o],enumerable:!(i=v(t,o))||i.enumerable});return e};var O=(e,t,r)=>(r=e!=null?E(w(e)):{},T(t||!e||!e.__esModule?c(r,"default",{value:e,enumerable:!0}):r,e)),D=e=>T(c({},"__esModule",{value:!0}),e);var U={};A(U,{App:()=>j});module.exports=D(U);var H=require("penpal"),a=O(require("react"));var u=class extends Error{constructor(t){super(t),this.name="CapitalOSError"}},d=class extends u{constructor(){super("Invalid token"),this.name="CapitalOSInvalidTokenError"}};var R=require("iframe-resizer"),n=O(require("react"));var I=(0,n.forwardRef)((e,t)=>{let r=e.title||"iframe",{iframeHTMLAttributes:i,resizerOptions:o}=_(e),m=(0,n.useRef)(null);return(0,n.useEffect)(()=>{let s=m.current;return(0,R.iframeResizer)(p({},o),s),()=>s.iFrameResizer&&s.iFrameResizer.removeListeners()}),(0,n.useImperativeHandle)(t,()=>m.current),n.default.createElement("iframe",z(p({},i),{title:r,ref:m}))});I.displayName="IframeResizer";var P=["autoResize","bodyBackground","bodyMargin","bodyPadding","checkOrigin","inPageLinks","heightCalculationMethod","interval","log","maxHeight","maxWidth","minHeight","minWidth","resizeFrom","scrolling","sizeHeight","sizeWidth","warningTimeout","tolerance","widthCalculationMethod","onClosed","onInit","onMessage","onResized","onScroll"],W=new Set(P);function _(e){return Object.keys(e).reduce((r,i)=>(W.has(i)?r.resizerOptions[i]=e[i]:r.iframeHTMLAttributes[i]=e[i],r),{resizerOptions:{},iframeHTMLAttributes:{}})}var B=1e4;function j(e){let{token:t,className:r,enableLogging:i,onError:o,loadingComponent:m}=e,s=a.default.useRef(null),[g,h]=a.default.useState(!1),k=(0,a.useMemo)(()=>{try{let l=decodeURIComponent(t),f=atob(l),C=JSON.parse(f),{path:L}=C;if(!L)throw new d;return`${L}?token=${t}`}catch(l){o==null||o(new d);return}},[t,o]);return(0,a.useEffect)(()=>{let l=(0,H.connectToChild)({iframe:s.current,childOrigin:"*",debug:!0,timeout:B,methods:{onLoad:()=>{h(!0)}}});return l.promise.catch(f=>{o==null||o(f),h(!0)}),()=>{l.destroy()}},[t]),a.default.createElement(a.default.Fragment,null,!g&&m,a.default.createElement(I,{src:k,allow:"clipboard-write",checkOrigin:!1,style:{width:"1px",height:"0px",minWidth:"100%"},className:r,log:!!i,ref:s,hidden:!g}))}0&&(module.exports={App});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/error.ts","../src/iframe-resizer.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nimport { InvalidTokenError } from './error'\nimport { IframeResizer } from './iframe-resizer'\n\n/**\n * Renders the CapitalOS App.\n */\nexport function App(\n props: {\n /**\n * The token provided by initiate-login.\n */\n token: string\n /**\n * Optional CSS class name for the component.\n */\n className?: string\n /**\n * Optional flag indicating whether to log events to the console.\n */\n enableLogging?: boolean\n\n /**\n * Optional callback for when the app encounters an error.\n */\n onError?: (error: Error) => void\n },\n) {\n const { token, className, enableLogging, onError } = props\n\n const handleError = (error: unknown) => {\n if (onError) {\n onError(new InvalidTokenError())\n }\n }\n\n let url: string | undefined = undefined\n try {\n const urlDecodedToken = decodeURIComponent(token)\n const base64DecodedToken = atob(urlDecodedToken)\n const jsonToken = JSON.parse(base64DecodedToken)\n const { path } = jsonToken\n if (!path) {\n handleError(new InvalidTokenError())\n return null\n }\n\n // construct the URL for the app\n url = `${path}?token=${token}`\n } catch (error) {\n handleError(error)\n return null\n }\n\n return (\n <IframeResizer\n src={url}\n allow=\"clipboard-write\"\n checkOrigin={false}\n style={{ width: '1px', height: '0px', minWidth: '100%' }}\n className={className}\n log={!!enableLogging}\n />\n )\n}\n","/**\n * Base class for all SDK errors\n */\nexport class CapitalOSError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CapitalOSError'\n }\n}\n\n/**\n * Represents an error that occurs when an invalid token is encountered.\n */\nexport class InvalidTokenError extends CapitalOSError {\n constructor() {\n super('Invalid token')\n this.name = 'CapitalOSInvalidTokenError'\n }\n}\n","import {\n IFrameOptions as BrokenIframeOptions,\n IFrameComponent,\n IFrameMessageData,\n IFrameResizedData,\n IFrameScrollData,\n iframeResizer,\n} from 'iframe-resizer'\nimport React, { IframeHTMLAttributes, useEffect, useRef } from 'react'\n\n// the events were renamed but package maintainers didn't update the types.\ntype IFrameOptions = Omit<\n BrokenIframeOptions,\n 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'\n> & {\n onClosed?(iframeId: string): void\n onInit?(iframe: IFrameComponent): void\n onMessage?(data: IFrameMessageData): void\n onResized?(data: IFrameResizedData): void\n onScroll?(data: IFrameScrollData): boolean\n}\n\ntype IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>\ntype EnrichedHtmlIframeElement = HTMLIFrameElement & { iFrameResizer: { removeListeners: () => void } }\n\nexport function IframeResizer(props: IframeResizerProps) {\n const title = props.title || 'iframe'\n const { iframeHTMLAttributes, resizerOptions } = splitProps(props)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n useEffect(() => {\n // effects run after render, so the ref is guaranteed to be set (unless the component conditionally renderes the iframe, which is not the case)\n const iframe = iframeRef.current as EnrichedHtmlIframeElement\n\n iframeResizer({ ...resizerOptions }, iframe)\n\n return () => iframe.iFrameResizer && iframe.iFrameResizer.removeListeners()\n })\n\n return <iframe {...iframeHTMLAttributes} title={title} ref={iframeRef} />\n}\n\nconst resizerOptions = [\n 'autoResize',\n 'bodyBackground',\n 'bodyMargin',\n 'bodyPadding',\n 'checkOrigin',\n 'inPageLinks',\n 'heightCalculationMethod',\n 'interval',\n 'log',\n 'maxHeight',\n 'maxWidth',\n 'minHeight',\n 'minWidth',\n 'resizeFrom',\n 'scrolling',\n 'sizeHeight',\n 'sizeWidth',\n 'warningTimeout',\n 'tolerance',\n 'widthCalculationMethod',\n 'onClosed',\n 'onInit',\n 'onMessage',\n 'onResized',\n 'onScroll',\n]\n\nconst resizerOptionsSet = new Set(resizerOptions)\n\n/**\n * split props into the resizer library options and the native iframe attributes.\n * the code is contains many type assertions because typescript doesn't handle reduce well.\n */\nfunction splitProps(props: IframeResizerProps) {\n const split = Object.keys(props).reduce<{\n resizerOptions: IFrameOptions\n iframeHTMLAttributes: IframeHTMLAttributes<HTMLIFrameElement>\n }>(\n (acc, key) => {\n if (resizerOptionsSet.has(key)) {\n acc.resizerOptions[key as keyof IFrameOptions] = props[key as keyof typeof props]\n } else {\n acc.iframeHTMLAttributes[key as keyof IframeHTMLAttributes<HTMLIFrameElement>] =\n props[key as keyof typeof props]\n }\n return acc\n },\n { resizerOptions: {}, iframeHTMLAttributes: {} },\n )\n\n return split\n}\n"],"mappings":"85BAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,SAAAE,IAAA,eAAAC,EAAAH,GAEA,IAAAI,EAAkB,oBCCX,IAAMC,EAAN,cAA6B,KAAM,CACxC,YAAYC,EAAiB,CAC3B,MAAMA,CAAO,EACb,KAAK,KAAO,gBACd,CACF,EAKaC,EAAN,cAAgCF,CAAe,CACpD,aAAc,CACZ,MAAM,eAAe,EACrB,KAAK,KAAO,4BACd,CACF,EClBA,IAAAG,EAOO,0BACPC,EAA+D,oBAiBxD,SAASC,EAAcC,EAA2B,CACvD,IAAMC,EAAQD,EAAM,OAAS,SACvB,CAAE,qBAAAE,EAAsB,eAAAC,CAAe,EAAIC,EAAWJ,CAAK,EAC3DK,KAAY,UAA0B,IAAI,EAEhD,sBAAU,IAAM,CAEd,IAAMC,EAASD,EAAU,QAEzB,0BAAcE,EAAA,GAAKJ,GAAkBG,CAAM,EAEpC,IAAMA,EAAO,eAAiBA,EAAO,cAAc,gBAAgB,CAC5E,CAAC,EAEM,EAAAE,QAAA,cAAC,SAAAC,EAAAF,EAAA,GAAWL,GAAX,CAAiC,MAAOD,EAAO,IAAKI,GAAW,CACzE,CAEA,IAAMF,EAAiB,CACrB,aACA,iBACA,aACA,cACA,cACA,cACA,0BACA,WACA,MACA,YACA,WACA,YACA,WACA,aACA,YACA,aACA,YACA,iBACA,YACA,yBACA,WACA,SACA,YACA,YACA,UACF,EAEMO,EAAoB,IAAI,IAAIP,CAAc,EAMhD,SAASC,EAAWJ,EAA2B,CAiB7C,OAhBc,OAAO,KAAKA,CAAK,EAAE,OAI/B,CAACW,EAAKC,KACAF,EAAkB,IAAIE,CAAG,EAC3BD,EAAI,eAAeC,CAA0B,EAAIZ,EAAMY,CAAyB,EAEhFD,EAAI,qBAAqBC,CAAoD,EAC3EZ,EAAMY,CAAyB,EAE5BD,GAET,CAAE,eAAgB,CAAC,EAAG,qBAAsB,CAAC,CAAE,CACjD,CAGF,CFpFO,SAASE,EACdC,EAmBA,CACA,GAAM,CAAE,MAAAC,EAAO,UAAAC,EAAW,cAAAC,EAAe,QAAAC,CAAQ,EAAIJ,EAE/CK,EAAeC,GAAmB,CAClCF,GACFA,EAAQ,IAAIG,CAAmB,CAEnC,EAEIC,EACJ,GAAI,CACF,IAAMC,EAAkB,mBAAmBR,CAAK,EAC1CS,EAAqB,KAAKD,CAAe,EACzCE,EAAY,KAAK,MAAMD,CAAkB,EACzC,CAAE,KAAAE,CAAK,EAAID,EACjB,GAAI,CAACC,EACH,OAAAP,EAAY,IAAIE,CAAmB,EAC5B,KAITC,EAAM,GAAGI,CAAI,UAAUX,CAAK,EAC9B,OAASK,EAAO,CACd,OAAAD,EAAYC,CAAK,EACV,IACT,CAEA,OACE,EAAAO,QAAA,cAACC,EAAA,CACC,IAAKN,EACL,MAAM,kBACN,YAAa,GACb,MAAO,CAAE,MAAO,MAAO,OAAQ,MAAO,SAAU,MAAO,EACvD,UAAWN,EACX,IAAK,CAAC,CAACC,EACT,CAEJ","names":["src_exports","__export","App","__toCommonJS","import_react","CapitalOSError","message","InvalidTokenError","import_iframe_resizer","import_react","IframeResizer","props","title","iframeHTMLAttributes","resizerOptions","splitProps","iframeRef","iframe","__spreadValues","React","__spreadProps","resizerOptionsSet","acc","key","App","props","token","className","enableLogging","onError","handleError","error","InvalidTokenError","url","urlDecodedToken","base64DecodedToken","jsonToken","path","React","IframeResizer"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/error.ts","../src/iframe-resizer.tsx"],"sourcesContent":["'use client'\n\nimport { connectToChild } from 'penpal'\nimport React, { ReactNode, useEffect, useMemo } from 'react'\n\nimport { InvalidTokenError } from './error'\nimport { IframeResizer } from './iframe-resizer'\n\nconst IFRAME_CONNECTION_TIMEOUT_MILLISECONDS = 10_000\n\n/**\n * Renders the CapitalOS App.\n */\nexport function App(props: {\n /**\n * The token provided by initiate-login.\n */\n token: string\n /**\n * Optional CSS class name for the component.\n */\n className?: string\n /**\n * Optional flag indicating whether to log events to the console.\n */\n enableLogging?: boolean\n\n /**\n * Optional callback for when the app encounters an error.\n */\n onError?: (error: Error) => void\n\n /**\n * Optional component to render while the app is loading.\n */\n loadingComponent?: ReactNode\n}) {\n const { token, className, enableLogging, onError, loadingComponent: LoadingComponent } = props\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null)\n\n // represents the state of whether all required react queries returned and the page should be visible\n const [isLoaded, setIsLoaded] = React.useState(false)\n\n // memoize the url based on the token so we don't redo the computation on each render.\n const url = useMemo(() => {\n try {\n const urlDecodedToken = decodeURIComponent(token)\n const base64DecodedToken = atob(urlDecodedToken)\n const jsonToken = JSON.parse(base64DecodedToken)\n const { path } = jsonToken\n if (!path) {\n throw new InvalidTokenError()\n }\n return `${path}?token=${token}`\n } catch (error) {\n onError?.(new InvalidTokenError())\n return undefined\n }\n }, [token, onError])\n\n // connect to child iframe\n useEffect(() => {\n const connection = connectToChild({\n iframe: iframeRef.current!,\n childOrigin: '*',\n debug: true,\n timeout: IFRAME_CONNECTION_TIMEOUT_MILLISECONDS,\n methods: {\n onLoad: () => {\n setIsLoaded(true)\n },\n },\n })\n\n connection.promise.catch((error) => {\n onError?.(error)\n\n // when connection fails it's probably a handshake timeout with the iframe. we will stop showing the loader\n // since the fact we failed communication doesn't necessarily mean the iframe didn't load\n setIsLoaded(true)\n })\n\n return () => {\n connection.destroy()\n }\n }, [token])\n\n return (\n <>\n {/* show loader as long as we're not loaded */}\n {!isLoaded && LoadingComponent}\n {/* hide the iframe as long as we're not loaded */}\n <IframeResizer\n src={url}\n allow=\"clipboard-write\"\n checkOrigin={false}\n style={{ width: '1px', height: '0px', minWidth: '100%' }}\n className={className}\n log={!!enableLogging}\n ref={iframeRef}\n hidden={!isLoaded}\n />\n </>\n )\n}\n","/**\n * Base class for all SDK errors\n */\nexport class CapitalOSError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CapitalOSError'\n }\n}\n\n/**\n * Represents an error that occurs when an invalid token is encountered.\n */\nexport class InvalidTokenError extends CapitalOSError {\n constructor() {\n super('Invalid token')\n this.name = 'CapitalOSInvalidTokenError'\n }\n}\n","import {\n IFrameOptions as BrokenIframeOptions,\n IFrameComponent,\n IFrameMessageData,\n IFrameResizedData,\n IFrameScrollData,\n iframeResizer,\n} from 'iframe-resizer'\nimport React, { IframeHTMLAttributes, forwardRef, useEffect, useImperativeHandle, useRef } from 'react'\n\n// the events were renamed but package maintainers didn't update the types.\ntype IFrameOptions = Omit<\n BrokenIframeOptions,\n 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'\n> & {\n onClosed?(iframeId: string): void\n onInit?(iframe: IFrameComponent): void\n onMessage?(data: IFrameMessageData): void\n onResized?(data: IFrameResizedData): void\n onScroll?(data: IFrameScrollData): boolean\n}\n\ntype IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>\ntype EnrichedHtmlIframeElement = HTMLIFrameElement & { iFrameResizer: { removeListeners: () => void } }\n\nexport const IframeResizer = forwardRef((props: IframeResizerProps, ref: React.Ref<HTMLIFrameElement>) => {\n const title = props.title || 'iframe'\n const { iframeHTMLAttributes, resizerOptions } = splitProps(props)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n useEffect(() => {\n // effects run after render, so the ref is guaranteed to be set (unless the component conditionally renders the iframe, which is not the case)\n const iframe = iframeRef.current as EnrichedHtmlIframeElement\n\n iframeResizer({ ...resizerOptions }, iframe)\n\n return () => iframe.iFrameResizer && iframe.iFrameResizer.removeListeners()\n })\n\n // make the ref provided as a prop point to the same place as the internal iframe ref.\n useImperativeHandle(ref, () => iframeRef.current as HTMLIFrameElement)\n\n return <iframe {...iframeHTMLAttributes} title={title} ref={iframeRef} />\n})\n\nIframeResizer.displayName = 'IframeResizer'\n\nconst resizerOptions = [\n 'autoResize',\n 'bodyBackground',\n 'bodyMargin',\n 'bodyPadding',\n 'checkOrigin',\n 'inPageLinks',\n 'heightCalculationMethod',\n 'interval',\n 'log',\n 'maxHeight',\n 'maxWidth',\n 'minHeight',\n 'minWidth',\n 'resizeFrom',\n 'scrolling',\n 'sizeHeight',\n 'sizeWidth',\n 'warningTimeout',\n 'tolerance',\n 'widthCalculationMethod',\n 'onClosed',\n 'onInit',\n 'onMessage',\n 'onResized',\n 'onScroll',\n]\n\nconst resizerOptionsSet = new Set(resizerOptions)\n\n/**\n * split props into the resizer library options and the native iframe attributes.\n * the code is contains many type assertions because typescript doesn't handle reduce well.\n */\nfunction splitProps(props: IframeResizerProps) {\n const split = Object.keys(props).reduce<{\n resizerOptions: IFrameOptions\n iframeHTMLAttributes: IframeHTMLAttributes<HTMLIFrameElement>\n }>(\n (acc, key) => {\n if (resizerOptionsSet.has(key)) {\n acc.resizerOptions[key as keyof IFrameOptions] = props[key as keyof typeof props]\n } else {\n acc.iframeHTMLAttributes[key as keyof IframeHTMLAttributes<HTMLIFrameElement>] =\n props[key as keyof typeof props]\n }\n return acc\n },\n { resizerOptions: {}, iframeHTMLAttributes: {} },\n )\n\n return split\n}\n"],"mappings":"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","names":["src_exports","__export","App","__toCommonJS","import_penpal","import_react","CapitalOSError","message","InvalidTokenError","import_iframe_resizer","import_react","IframeResizer","props","ref","title","iframeHTMLAttributes","resizerOptions","splitProps","iframeRef","iframe","__spreadValues","React","__spreadProps","resizerOptionsSet","acc","key","IFRAME_CONNECTION_TIMEOUT_MILLISECONDS","App","props","token","className","enableLogging","onError","LoadingComponent","iframeRef","React","isLoaded","setIsLoaded","url","urlDecodedToken","base64DecodedToken","jsonToken","path","InvalidTokenError","error","connection","IframeResizer"]}
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@capitalos/react",
3
- "version": "0.0.4",
3
+ "version": "0.1.0-beta.2",
4
4
  "description": "integrate CapitalOS into your react app",
5
5
  "main": "dist/index.js",
6
- "module": "dist/index.mjs",
6
+ "module": "dist/esm/index.js",
7
7
  "types": "dist/_tsup-dts-rollup.d.ts",
8
8
  "keywords": [
9
9
  "capitalos",
@@ -22,18 +22,27 @@
22
22
  "@trivago/prettier-plugin-sort-imports": "^4.3.0",
23
23
  "@types/iframe-resizer": "^3.5.13",
24
24
  "@types/react": "18.0.20",
25
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
26
+ "@typescript-eslint/parser": "^7.2.0",
27
+ "eslint": "^8.57.0",
28
+ "eslint-config-prettier": "^9.1.0",
29
+ "eslint-plugin-prettier": "^5.1.3",
30
+ "eslint-plugin-react": "^7.34.0",
31
+ "prettier": "^3.2.5",
25
32
  "tsup": "^8.0.1",
26
- "typescript": "^5.3.3"
33
+ "typescript": "^5.3.3",
34
+ "react": "16.8.0"
27
35
  },
28
36
  "dependencies": {
29
37
  "iframe-resizer": "^4.3.9",
30
- "react": "^18.2.0"
38
+ "penpal": "^6.2.2"
31
39
  },
32
40
  "peerDependencies": {
33
41
  "react": ">=16.8.0"
34
42
  },
35
43
  "scripts": {
36
- "build": "tsup src/index.tsx --experimental-dts --minify --format esm,cjs --clean --no-splitting --sourcemap --out-dir dist",
37
- "dev": "pnpm build --watch"
44
+ "build": " pnpm lint && tsup src/index.tsx --experimental-dts --minify --format esm,cjs --clean --no-splitting --sourcemap --legacy-output --out-dir dist",
45
+ "dev": "pnpm build --watch",
46
+ "lint": "eslint . --ext .ts,.tsx"
38
47
  }
39
48
  }
package/dist/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- "use client";var b=Object.defineProperty,z=Object.defineProperties;var F=Object.getOwnPropertyDescriptors;var f=Object.getOwnPropertySymbols;var k=Object.prototype.hasOwnProperty,M=Object.prototype.propertyIsEnumerable;var p=(e,r,t)=>r in e?b(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,m=(e,r)=>{for(var t in r||(r={}))k.call(r,t)&&p(e,t,r[t]);if(f)for(var t of f(r))M.call(r,t)&&p(e,t,r[t]);return e},u=(e,r)=>z(e,F(r));import v from"react";var l=class extends Error{constructor(r){super(r),this.name="CapitalOSError"}},s=class extends l{constructor(){super("Invalid token"),this.name="CapitalOSInvalidTokenError"}};import{iframeResizer as O}from"iframe-resizer";import H,{useEffect as L,useRef as T}from"react";function I(e){let r=e.title||"iframe",{iframeHTMLAttributes:t,resizerOptions:o}=C(e),n=T(null);return L(()=>{let i=n.current;return O(m({},o),i),()=>i.iFrameResizer&&i.iFrameResizer.removeListeners()}),H.createElement("iframe",u(m({},t),{title:r,ref:n}))}var R=["autoResize","bodyBackground","bodyMargin","bodyPadding","checkOrigin","inPageLinks","heightCalculationMethod","interval","log","maxHeight","maxWidth","minHeight","minWidth","resizeFrom","scrolling","sizeHeight","sizeWidth","warningTimeout","tolerance","widthCalculationMethod","onClosed","onInit","onMessage","onResized","onScroll"],E=new Set(R);function C(e){return Object.keys(e).reduce((t,o)=>(E.has(o)?t.resizerOptions[o]=e[o]:t.iframeHTMLAttributes[o]=e[o],t),{resizerOptions:{},iframeHTMLAttributes:{}})}function G(e){let{token:r,className:t,enableLogging:o,onError:n}=e,i=a=>{n&&n(new s)},c;try{let a=decodeURIComponent(r),g=atob(a),h=JSON.parse(g),{path:d}=h;if(!d)return i(new s),null;c=`${d}?token=${r}`}catch(a){return i(a),null}return v.createElement(I,{src:c,allow:"clipboard-write",checkOrigin:!1,style:{width:"1px",height:"0px",minWidth:"100%"},className:t,log:!!o})}export{G as App};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/error.ts","../src/iframe-resizer.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nimport { InvalidTokenError } from './error'\nimport { IframeResizer } from './iframe-resizer'\n\n/**\n * Renders the CapitalOS App.\n */\nexport function App(\n props: {\n /**\n * The token provided by initiate-login.\n */\n token: string\n /**\n * Optional CSS class name for the component.\n */\n className?: string\n /**\n * Optional flag indicating whether to log events to the console.\n */\n enableLogging?: boolean\n\n /**\n * Optional callback for when the app encounters an error.\n */\n onError?: (error: Error) => void\n },\n) {\n const { token, className, enableLogging, onError } = props\n\n const handleError = (error: unknown) => {\n if (onError) {\n onError(new InvalidTokenError())\n }\n }\n\n let url: string | undefined = undefined\n try {\n const urlDecodedToken = decodeURIComponent(token)\n const base64DecodedToken = atob(urlDecodedToken)\n const jsonToken = JSON.parse(base64DecodedToken)\n const { path } = jsonToken\n if (!path) {\n handleError(new InvalidTokenError())\n return null\n }\n\n // construct the URL for the app\n url = `${path}?token=${token}`\n } catch (error) {\n handleError(error)\n return null\n }\n\n return (\n <IframeResizer\n src={url}\n allow=\"clipboard-write\"\n checkOrigin={false}\n style={{ width: '1px', height: '0px', minWidth: '100%' }}\n className={className}\n log={!!enableLogging}\n />\n )\n}\n","/**\n * Base class for all SDK errors\n */\nexport class CapitalOSError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'CapitalOSError'\n }\n}\n\n/**\n * Represents an error that occurs when an invalid token is encountered.\n */\nexport class InvalidTokenError extends CapitalOSError {\n constructor() {\n super('Invalid token')\n this.name = 'CapitalOSInvalidTokenError'\n }\n}\n","import {\n IFrameOptions as BrokenIframeOptions,\n IFrameComponent,\n IFrameMessageData,\n IFrameResizedData,\n IFrameScrollData,\n iframeResizer,\n} from 'iframe-resizer'\nimport React, { IframeHTMLAttributes, useEffect, useRef } from 'react'\n\n// the events were renamed but package maintainers didn't update the types.\ntype IFrameOptions = Omit<\n BrokenIframeOptions,\n 'closedCallback' | 'scrollCallback' | 'resizedCallback' | 'messageCallback' | 'initCallback'\n> & {\n onClosed?(iframeId: string): void\n onInit?(iframe: IFrameComponent): void\n onMessage?(data: IFrameMessageData): void\n onResized?(data: IFrameResizedData): void\n onScroll?(data: IFrameScrollData): boolean\n}\n\ntype IframeResizerProps = IFrameOptions & IframeHTMLAttributes<HTMLIFrameElement>\ntype EnrichedHtmlIframeElement = HTMLIFrameElement & { iFrameResizer: { removeListeners: () => void } }\n\nexport function IframeResizer(props: IframeResizerProps) {\n const title = props.title || 'iframe'\n const { iframeHTMLAttributes, resizerOptions } = splitProps(props)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n useEffect(() => {\n // effects run after render, so the ref is guaranteed to be set (unless the component conditionally renderes the iframe, which is not the case)\n const iframe = iframeRef.current as EnrichedHtmlIframeElement\n\n iframeResizer({ ...resizerOptions }, iframe)\n\n return () => iframe.iFrameResizer && iframe.iFrameResizer.removeListeners()\n })\n\n return <iframe {...iframeHTMLAttributes} title={title} ref={iframeRef} />\n}\n\nconst resizerOptions = [\n 'autoResize',\n 'bodyBackground',\n 'bodyMargin',\n 'bodyPadding',\n 'checkOrigin',\n 'inPageLinks',\n 'heightCalculationMethod',\n 'interval',\n 'log',\n 'maxHeight',\n 'maxWidth',\n 'minHeight',\n 'minWidth',\n 'resizeFrom',\n 'scrolling',\n 'sizeHeight',\n 'sizeWidth',\n 'warningTimeout',\n 'tolerance',\n 'widthCalculationMethod',\n 'onClosed',\n 'onInit',\n 'onMessage',\n 'onResized',\n 'onScroll',\n]\n\nconst resizerOptionsSet = new Set(resizerOptions)\n\n/**\n * split props into the resizer library options and the native iframe attributes.\n * the code is contains many type assertions because typescript doesn't handle reduce well.\n */\nfunction splitProps(props: IframeResizerProps) {\n const split = Object.keys(props).reduce<{\n resizerOptions: IFrameOptions\n iframeHTMLAttributes: IframeHTMLAttributes<HTMLIFrameElement>\n }>(\n (acc, key) => {\n if (resizerOptionsSet.has(key)) {\n acc.resizerOptions[key as keyof IFrameOptions] = props[key as keyof typeof props]\n } else {\n acc.iframeHTMLAttributes[key as keyof IframeHTMLAttributes<HTMLIFrameElement>] =\n props[key as keyof typeof props]\n }\n return acc\n },\n { resizerOptions: {}, iframeHTMLAttributes: {} },\n )\n\n return split\n}\n"],"mappings":"0bAEA,OAAOA,MAAW,QCCX,IAAMC,EAAN,cAA6B,KAAM,CACxC,YAAYC,EAAiB,CAC3B,MAAMA,CAAO,EACb,KAAK,KAAO,gBACd,CACF,EAKaC,EAAN,cAAgCF,CAAe,CACpD,aAAc,CACZ,MAAM,eAAe,EACrB,KAAK,KAAO,4BACd,CACF,EClBA,OAME,iBAAAG,MACK,iBACP,OAAOC,GAA+B,aAAAC,EAAW,UAAAC,MAAc,QAiBxD,SAASC,EAAcC,EAA2B,CACvD,IAAMC,EAAQD,EAAM,OAAS,SACvB,CAAE,qBAAAE,EAAsB,eAAAC,CAAe,EAAIC,EAAWJ,CAAK,EAC3DK,EAAYC,EAA0B,IAAI,EAEhD,OAAAC,EAAU,IAAM,CAEd,IAAMC,EAASH,EAAU,QAEzB,OAAAI,EAAcC,EAAA,GAAKP,GAAkBK,CAAM,EAEpC,IAAMA,EAAO,eAAiBA,EAAO,cAAc,gBAAgB,CAC5E,CAAC,EAEMG,EAAA,cAAC,SAAAC,EAAAF,EAAA,GAAWR,GAAX,CAAiC,MAAOD,EAAO,IAAKI,GAAW,CACzE,CAEA,IAAMF,EAAiB,CACrB,aACA,iBACA,aACA,cACA,cACA,cACA,0BACA,WACA,MACA,YACA,WACA,YACA,WACA,aACA,YACA,aACA,YACA,iBACA,YACA,yBACA,WACA,SACA,YACA,YACA,UACF,EAEMU,EAAoB,IAAI,IAAIV,CAAc,EAMhD,SAASC,EAAWJ,EAA2B,CAiB7C,OAhBc,OAAO,KAAKA,CAAK,EAAE,OAI/B,CAACc,EAAKC,KACAF,EAAkB,IAAIE,CAAG,EAC3BD,EAAI,eAAeC,CAA0B,EAAIf,EAAMe,CAAyB,EAEhFD,EAAI,qBAAqBC,CAAoD,EAC3Ef,EAAMe,CAAyB,EAE5BD,GAET,CAAE,eAAgB,CAAC,EAAG,qBAAsB,CAAC,CAAE,CACjD,CAGF,CFpFO,SAASE,EACdC,EAmBA,CACA,GAAM,CAAE,MAAAC,EAAO,UAAAC,EAAW,cAAAC,EAAe,QAAAC,CAAQ,EAAIJ,EAE/CK,EAAeC,GAAmB,CAClCF,GACFA,EAAQ,IAAIG,CAAmB,CAEnC,EAEIC,EACJ,GAAI,CACF,IAAMC,EAAkB,mBAAmBR,CAAK,EAC1CS,EAAqB,KAAKD,CAAe,EACzCE,EAAY,KAAK,MAAMD,CAAkB,EACzC,CAAE,KAAAE,CAAK,EAAID,EACjB,GAAI,CAACC,EACH,OAAAP,EAAY,IAAIE,CAAmB,EAC5B,KAITC,EAAM,GAAGI,CAAI,UAAUX,CAAK,EAC9B,OAASK,EAAO,CACd,OAAAD,EAAYC,CAAK,EACV,IACT,CAEA,OACEO,EAAA,cAACC,EAAA,CACC,IAAKN,EACL,MAAM,kBACN,YAAa,GACb,MAAO,CAAE,MAAO,MAAO,OAAQ,MAAO,SAAU,MAAO,EACvD,UAAWN,EACX,IAAK,CAAC,CAACC,EACT,CAEJ","names":["React","CapitalOSError","message","InvalidTokenError","iframeResizer","React","useEffect","useRef","IframeResizer","props","title","iframeHTMLAttributes","resizerOptions","splitProps","iframeRef","useRef","useEffect","iframe","iframeResizer","__spreadValues","React","__spreadProps","resizerOptionsSet","acc","key","App","props","token","className","enableLogging","onError","handleError","error","InvalidTokenError","url","urlDecodedToken","base64DecodedToken","jsonToken","path","React","IframeResizer"]}