@capitalos/vue 0.1.0-rc.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ComputedRef, DeepReadonly, Ref } from "vue";
2
- import { CapitalOSError, ErrorCode, Logger, Logger as Logger$1, RawErrorDetails, ThemeColorScheme, ThemeColorScheme as ThemeColorScheme$1, TokenData, TokenData as TokenData$1 } from "@capitalos/core";
2
+ import { Account, AccountStatus, CapitalOSError, ErrorCode, Logger, Logger as Logger$1, RawErrorDetails, ThemeColorScheme, ThemeColorScheme as ThemeColorScheme$1, TokenData, TokenData as TokenData$1 } from "@capitalos/core";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  interface CapitalOsConfig {
@@ -38,8 +38,18 @@ declare function createCapitalOs(config: CapitalOsConfig): {
38
38
  declare const CardsApp: any;
39
39
 
40
40
  //#endregion
41
- //#region src/composables/use-capitalos-auth.d.ts
41
+ //#region src/components/BillPayApp.d.ts
42
42
  //# sourceMappingURL=CardsApp.d.ts.map
43
+ declare const BillPayApp: any;
44
+
45
+ //#endregion
46
+ //#region src/components/Onboarding.d.ts
47
+ //# sourceMappingURL=BillPayApp.d.ts.map
48
+ declare const Onboarding: any;
49
+
50
+ //#endregion
51
+ //#region src/composables/use-capitalos-auth.d.ts
52
+ //# sourceMappingURL=Onboarding.d.ts.map
43
53
  interface UseCapitalOsAuthReturn extends CapitalOsState {
44
54
  authState: ComputedRef<AuthState>;
45
55
  }
@@ -48,5 +58,5 @@ declare function useCapitalOsAuth(): UseCapitalOsAuthReturn;
48
58
  //#endregion
49
59
  //# sourceMappingURL=use-capitalos-auth.d.ts.map
50
60
 
51
- export { AuthState, CAPITALOS_INJECTION_KEY, CapitalOSError, CapitalOsConfig, CardsApp, ErrorCode, Logger, RawErrorDetails, ThemeColorScheme, TokenData, UseCapitalOsAuthReturn, createCapitalOs, useCapitalOsAuth };
61
+ export { Account, AccountStatus, AuthState, BillPayApp, CAPITALOS_INJECTION_KEY, CapitalOSError, CapitalOsConfig, CardsApp, ErrorCode, Logger, Onboarding, RawErrorDetails, ThemeColorScheme, TokenData, UseCapitalOsAuthReturn, createCapitalOs, useCapitalOsAuth };
52
62
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/plugin.ts","../src/components/CardsApp.ts","../src/composables/use-capitalos-auth.ts"],"sourcesContent":null,"mappings":";;;;UAMiB,eAAA;kBAKC;EALD,aAAA,CAAA,EAAA,OAAe;EAAA,MAAA,CAAA,EAerB,QAfqB;EAAA,KAKd,CAAA,EAeR,kBAfQ;;AAeR,UAMO,cAAA,CANP;EAAgB,SAAA,EAOb,YAPa,CAOA,GAPA,CAOI,WAPJ,GAAA,SAAA,CAAA,CAAA;EAMT,SAAA,EAEJ,YAFkB,CAEL,GAFK,CAAA,OAAA,CAAA,CAAA;EAAA,KAAA,EAGtB,YAHsB,CAGT,GAHS,CAGL,KAHK,GAAA,SAAA,CAAA,CAAA;EAAA,eACD,EAAA,GAAA,GAAA,IAAA;EAAS,MAAb,EAIhB,eAJgB;;AACA,KASd,SAAA,GATc,MAAA,GAAA,SAAA,GAAA,eAAA,GAAA,OAAA;;;;;cCSb;UAsCH,eAAA;ED3EO,KAAA,EAAA,CAAA,KAAA,EC4EA,MD5Ee,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,IAAA;EAAA,OAAA,EAAA,MAAA;;UCkFtB,OAAA,CDnEC;EAAM,OAKP,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAgB,OAAA,EAAA,MAAA;AAM1B;AAA+B,iBCyFf,eAAA,CDzFe,MAAA,ECyFS,eDzFT,CAAA,EAAA;EAAA,OACD,CAAA,QAAA,EC0FR,eD1FQ,GC0FU,OD1FV,CAAA,EAAA,IAAA;CAAS;;;;cEqB1B;;;;;UC/CI,sBAAA,SAA+B;aAInC,YAAY;AHLzB;AAAgC,iBGahB,gBAAA,CAAA,CHbgB,EGaI,sBHbJ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/plugin.ts","../src/components/CardsApp.ts","../src/components/BillPayApp.ts","../src/components/Onboarding.ts","../src/composables/use-capitalos-auth.ts"],"sourcesContent":null,"mappings":";;;;UAMiB,eAAA;kBAKC;EALD,aAAA,CAAA,EAAA,OAAe;EAAA,MAAA,CAAA,EAerB,QAfqB;EAAA,KAKd,CAAA,EAeR,kBAfQ;;AAeR,UAMO,cAAA,CANP;EAAgB,SAAA,EAOb,YAPa,CAOA,GAPA,CAOI,WAPJ,GAAA,SAAA,CAAA,CAAA;EAMT,SAAA,EAEJ,YAFkB,CAEL,GAFK,CAAA,OAAA,CAAA,CAAA;EAAA,KAAA,EAGtB,YAHsB,CAGT,GAHS,CAGL,KAHK,GAAA,SAAA,CAAA,CAAA;EAAA,eACD,EAAA,GAAA,GAAA,IAAA;EAAS,MAAb,EAIhB,eAJgB;;AACA,KASd,SAAA,GATc,MAAA,GAAA,SAAA,GAAA,eAAA,GAAA,OAAA;;;;;cCSb;UAsCH,eAAA;ED3EO,KAAA,EAAA,CAAA,KAAA,EC4EA,MD5Ee,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,IAAA;EAAA,OAAA,EAAA,MAAA;;UCkFtB,OAAA,CDnEC;EAAM,OAKP,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAgB,OAAA,EAAA,MAAA;AAM1B;AAA+B,iBCyFf,eAAA,CDzFe,MAAA,ECyFS,eDzFT,CAAA,EAAA;EAAA,OACD,CAAA,QAAA,EC0FR,eD1FQ,GC0FU,OD1FV,CAAA,EAAA,IAAA;CAAS;;;;cEL1B;;;;;cCAA;;;;;cCOA;;;;;UC5BI,sBAAA,SAA+B;aAInC,YAAY;ALLzB;AAAgC,iBKahB,gBAAA,CAAA,CLbgB,EKaI,sBLbJ"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ComputedRef, DeepReadonly, Ref } from "vue";
2
- import { CapitalOSError, ErrorCode, Logger, Logger as Logger$1, RawErrorDetails, ThemeColorScheme, ThemeColorScheme as ThemeColorScheme$1, TokenData, TokenData as TokenData$1 } from "@capitalos/core";
2
+ import { Account, AccountStatus, CapitalOSError, ErrorCode, Logger, Logger as Logger$1, RawErrorDetails, ThemeColorScheme, ThemeColorScheme as ThemeColorScheme$1, TokenData, TokenData as TokenData$1 } from "@capitalos/core";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  interface CapitalOsConfig {
@@ -38,8 +38,18 @@ declare function createCapitalOs(config: CapitalOsConfig): {
38
38
  declare const CardsApp: any;
39
39
 
40
40
  //#endregion
41
- //#region src/composables/use-capitalos-auth.d.ts
41
+ //#region src/components/BillPayApp.d.ts
42
42
  //# sourceMappingURL=CardsApp.d.ts.map
43
+ declare const BillPayApp: any;
44
+
45
+ //#endregion
46
+ //#region src/components/Onboarding.d.ts
47
+ //# sourceMappingURL=BillPayApp.d.ts.map
48
+ declare const Onboarding: any;
49
+
50
+ //#endregion
51
+ //#region src/composables/use-capitalos-auth.d.ts
52
+ //# sourceMappingURL=Onboarding.d.ts.map
43
53
  interface UseCapitalOsAuthReturn extends CapitalOsState {
44
54
  authState: ComputedRef<AuthState>;
45
55
  }
@@ -48,5 +58,5 @@ declare function useCapitalOsAuth(): UseCapitalOsAuthReturn;
48
58
  //#endregion
49
59
  //# sourceMappingURL=use-capitalos-auth.d.ts.map
50
60
 
51
- export { AuthState, CAPITALOS_INJECTION_KEY, CapitalOSError, CapitalOsConfig, CardsApp, ErrorCode, Logger, RawErrorDetails, ThemeColorScheme, TokenData, UseCapitalOsAuthReturn, createCapitalOs, useCapitalOsAuth };
61
+ export { Account, AccountStatus, AuthState, BillPayApp, CAPITALOS_INJECTION_KEY, CapitalOSError, CapitalOsConfig, CardsApp, ErrorCode, Logger, Onboarding, RawErrorDetails, ThemeColorScheme, TokenData, UseCapitalOsAuthReturn, createCapitalOs, useCapitalOsAuth };
52
62
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/plugin.ts","../src/components/CardsApp.ts","../src/composables/use-capitalos-auth.ts"],"sourcesContent":null,"mappings":";;;;UAMiB,eAAA;kBAKC;EALD,aAAA,CAAA,EAAA,OAAe;EAAA,MAAA,CAAA,EAerB,QAfqB;EAAA,KAKd,CAAA,EAeR,kBAfQ;;AAeR,UAMO,cAAA,CANP;EAAgB,SAAA,EAOb,YAPa,CAOA,GAPA,CAOI,WAPJ,GAAA,SAAA,CAAA,CAAA;EAMT,SAAA,EAEJ,YAFkB,CAEL,GAFK,CAAA,OAAA,CAAA,CAAA;EAAA,KAAA,EAGtB,YAHsB,CAGT,GAHS,CAGL,KAHK,GAAA,SAAA,CAAA,CAAA;EAAA,eACD,EAAA,GAAA,GAAA,IAAA;EAAS,MAAb,EAIhB,eAJgB;;AACA,KASd,SAAA,GATc,MAAA,GAAA,SAAA,GAAA,eAAA,GAAA,OAAA;;;;;cCSb;UAsCH,eAAA;ED3EO,KAAA,EAAA,CAAA,KAAA,EC4EA,MD5Ee,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,IAAA;EAAA,OAAA,EAAA,MAAA;;UCkFtB,OAAA,CDnEC;EAAM,OAKP,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAgB,OAAA,EAAA,MAAA;AAM1B;AAA+B,iBCyFf,eAAA,CDzFe,MAAA,ECyFS,eDzFT,CAAA,EAAA;EAAA,OACD,CAAA,QAAA,EC0FR,eD1FQ,GC0FU,OD1FV,CAAA,EAAA,IAAA;CAAS;;;;cEqB1B;;;;;UC/CI,sBAAA,SAA+B;aAInC,YAAY;AHLzB;AAAgC,iBGahB,gBAAA,CAAA,CHbgB,EGaI,sBHbJ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/plugin.ts","../src/components/CardsApp.ts","../src/components/BillPayApp.ts","../src/components/Onboarding.ts","../src/composables/use-capitalos-auth.ts"],"sourcesContent":null,"mappings":";;;;UAMiB,eAAA;kBAKC;EALD,aAAA,CAAA,EAAA,OAAe;EAAA,MAAA,CAAA,EAerB,QAfqB;EAAA,KAKd,CAAA,EAeR,kBAfQ;;AAeR,UAMO,cAAA,CANP;EAAgB,SAAA,EAOb,YAPa,CAOA,GAPA,CAOI,WAPJ,GAAA,SAAA,CAAA,CAAA;EAMT,SAAA,EAEJ,YAFkB,CAEL,GAFK,CAAA,OAAA,CAAA,CAAA;EAAA,KAAA,EAGtB,YAHsB,CAGT,GAHS,CAGL,KAHK,GAAA,SAAA,CAAA,CAAA;EAAA,eACD,EAAA,GAAA,GAAA,IAAA;EAAS,MAAb,EAIhB,eAJgB;;AACA,KASd,SAAA,GATc,MAAA,GAAA,SAAA,GAAA,eAAA,GAAA,OAAA;;;;;cCSb;UAsCH,eAAA;ED3EO,KAAA,EAAA,CAAA,KAAA,EC4EA,MD5Ee,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,IAAA;EAAA,OAAA,EAAA,MAAA;;UCkFtB,OAAA,CDnEC;EAAM,OAKP,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAgB,OAAA,EAAA,MAAA;AAM1B;AAA+B,iBCyFf,eAAA,CDzFe,MAAA,ECyFS,eDzFT,CAAA,EAAA;EAAA,OACD,CAAA,QAAA,EC0FR,eD1FQ,GC0FU,OD1FV,CAAA,EAAA,IAAA;CAAS;;;;cEL1B;;;;;cCAA;;;;;cCOA;;;;;UC5BI,sBAAA,SAA+B;aAInC,YAAY;ALLzB;AAAgC,iBKahB,gBAAA,CAAA,CLbgB,EKaI,sBLbJ"}
package/dist/index.js CHANGED
@@ -142,6 +142,27 @@ function createCapitalOs(config) {
142
142
  } };
143
143
  }
144
144
 
145
+ //#endregion
146
+ //#region src/components/common-props.ts
147
+ /**
148
+ * Common props shared by all CapitalOS Vue components.
149
+ */
150
+ const commonProps = {
151
+ theme: String,
152
+ heightOffsetPx: {
153
+ type: Number,
154
+ default: 12
155
+ },
156
+ enableLogging: Boolean
157
+ };
158
+ /**
159
+ * Common emits shared by all CapitalOS Vue components.
160
+ */
161
+ const commonEmits = {
162
+ loaded: () => true,
163
+ error: (error) => error instanceof __capitalos_core.CapitalOSError
164
+ };
165
+
145
166
  //#endregion
146
167
  //#region src/composables/use-capitalos-auth.ts
147
168
  /**
@@ -166,7 +187,89 @@ function useCapitalOsAuth() {
166
187
 
167
188
  //#endregion
168
189
  //#region package.json
169
- var version = "0.1.0-rc.1";
190
+ var version = "0.1.0";
191
+
192
+ //#endregion
193
+ //#region src/composables/use-iframe-component.ts
194
+ /**
195
+ * Composable that handles common iframe component setup.
196
+ *
197
+ * Manages:
198
+ * - Container ref and iframe manager lifecycle
199
+ * - Token data subscription and iframe initialization
200
+ * - Common callbacks (onLoad, onError, onTokenExpired)
201
+ * - Cleanup on unmount
202
+ * - Render function for the container div
203
+ *
204
+ * Note: Rendering context props (e.g., entryPoint, exitPoint for Onboarding) are read once
205
+ * at iframe initialization. Changes to these props after the iframe loads will NOT trigger
206
+ * re-initialization. This matches the behavior of the React SDK.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * setup(props, { emit }) {
211
+ * const { render } = useIframeComponent({
212
+ * props,
213
+ * emit,
214
+ * getRenderingContext: () => ({ entryPoint: 'cardsApp' }),
215
+ * })
216
+ * return render
217
+ * }
218
+ * ```
219
+ */
220
+ function useIframeComponent(options) {
221
+ const { props, emit, getRenderingContext, componentCallbacks } = options;
222
+ const containerRef = (0, vue.ref)(null);
223
+ const { tokenData, config, invalidateToken } = useCapitalOsAuth();
224
+ let iframeManager = null;
225
+ function initializeIframe(token, container) {
226
+ iframeManager?.destroy();
227
+ const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false;
228
+ const resolvedTheme = props.theme ?? config.theme;
229
+ iframeManager = new __capitalos_core.IframeManager({
230
+ container,
231
+ tokenData: token,
232
+ renderingContext: getRenderingContext(),
233
+ theme: resolvedTheme,
234
+ enableLogging: resolvedEnableLogging,
235
+ logger: config.logger,
236
+ sdkVersion: version,
237
+ heightOffsetPx: props.heightOffsetPx,
238
+ callbacks: {
239
+ onLoad: () => {
240
+ emit("loaded");
241
+ },
242
+ onError: (rawError) => {
243
+ emit("error", new __capitalos_core.CapitalOSError(rawError));
244
+ },
245
+ onTokenExpired: () => {
246
+ invalidateToken();
247
+ },
248
+ ...componentCallbacks
249
+ }
250
+ });
251
+ }
252
+ (0, vue.watch)([tokenData, containerRef], ([newTokenData, container]) => {
253
+ if (newTokenData && container) initializeIframe(newTokenData, container);
254
+ }, { immediate: true });
255
+ (0, vue.onUnmounted)(() => {
256
+ iframeManager?.destroy();
257
+ iframeManager = null;
258
+ });
259
+ function render() {
260
+ return (0, vue.h)("div", {
261
+ ref: (el) => {
262
+ containerRef.value = el;
263
+ },
264
+ class: "capitalos-iframe-container",
265
+ style: { width: "100%" }
266
+ });
267
+ }
268
+ return {
269
+ containerRef,
270
+ render
271
+ };
272
+ }
170
273
 
171
274
  //#endregion
172
275
  //#region src/components/CardsApp.ts
@@ -193,74 +296,128 @@ var version = "0.1.0-rc.1";
193
296
  * const onCardsError = (error) => console.error(error)
194
297
  * </script>
195
298
  * ```
196
- *
197
- * Note: CardsApp is not designed to be conditionally mounted/unmounted frequently.
198
- * For show/hide behavior, consumers should toggle visibility (e.g., v-show) rather
199
- * than mount/unmount repeatedly.
200
299
  */
201
300
  const CardsApp = (0, vue.defineComponent)({
202
301
  name: "CardsApp",
302
+ props: commonProps,
303
+ emits: commonEmits,
304
+ setup(props, { emit }) {
305
+ const { render } = useIframeComponent({
306
+ props,
307
+ emit,
308
+ getRenderingContext: () => ({ entryPoint: "cardsApp" })
309
+ });
310
+ return render;
311
+ }
312
+ });
313
+
314
+ //#endregion
315
+ //#region src/components/BillPayApp.ts
316
+ /**
317
+ * BillPayApp component that renders the CapitalOS bill payment interface in an iframe.
318
+ *
319
+ * The component emits events for loading state - consumers should handle their own loading UI:
320
+ *
321
+ * @example
322
+ * ```vue
323
+ * <template>
324
+ * <div v-if="!billPayLoaded">Loading...</div>
325
+ * <BillPayApp
326
+ * @loaded="billPayLoaded = true"
327
+ * @error="onBillPayError"
328
+ * />
329
+ * </template>
330
+ *
331
+ * <script setup>
332
+ * import { ref } from 'vue'
333
+ * import { BillPayApp } from '@capitalos/vue'
334
+ *
335
+ * const billPayLoaded = ref(false)
336
+ * const onBillPayError = (error) => console.error(error)
337
+ * </script>
338
+ * ```
339
+ */
340
+ const BillPayApp = (0, vue.defineComponent)({
341
+ name: "BillPayApp",
342
+ props: commonProps,
343
+ emits: commonEmits,
344
+ setup(props, { emit }) {
345
+ const { render } = useIframeComponent({
346
+ props,
347
+ emit,
348
+ getRenderingContext: () => ({ entryPoint: "billPayApp" })
349
+ });
350
+ return render;
351
+ }
352
+ });
353
+
354
+ //#endregion
355
+ //#region src/components/Onboarding.ts
356
+ /**
357
+ * Onboarding component that renders the CapitalOS onboarding flow in an iframe.
358
+ *
359
+ * The component emits events for loading state and completion - consumers should handle their own loading UI:
360
+ *
361
+ * @example
362
+ * ```vue
363
+ * <template>
364
+ * <div v-if="!onboardingLoaded">Loading...</div>
365
+ * <Onboarding
366
+ * entry-point="welcome"
367
+ * exit-point="activation"
368
+ * @loaded="onboardingLoaded = true"
369
+ * @error="onOnboardingError"
370
+ * @done="onOnboardingComplete"
371
+ * />
372
+ * </template>
373
+ *
374
+ * <script setup>
375
+ * import { ref } from 'vue'
376
+ * import { Onboarding } from '@capitalos/vue'
377
+ *
378
+ * const onboardingLoaded = ref(false)
379
+ * const onOnboardingError = (error) => console.error(error)
380
+ * const onOnboardingComplete = (account) => {
381
+ * console.log('Onboarding complete:', account.status)
382
+ * }
383
+ * </script>
384
+ * ```
385
+ */
386
+ const Onboarding = (0, vue.defineComponent)({
387
+ name: "Onboarding",
203
388
  props: {
204
- theme: String,
205
- heightOffsetPx: {
206
- type: Number,
207
- default: 12
208
- },
209
- enableLogging: Boolean
389
+ ...commonProps,
390
+ entryPoint: String,
391
+ exitPoint: String,
392
+ allowExitOnNonApproved: {
393
+ type: Boolean,
394
+ default: void 0
395
+ }
210
396
  },
211
397
  emits: {
212
- loaded: () => true,
213
- error: (error) => error instanceof __capitalos_core.CapitalOSError
398
+ ...commonEmits,
399
+ done: (_account) => true
214
400
  },
215
401
  setup(props, { emit }) {
216
- const containerRef = (0, vue.ref)(null);
217
- const { tokenData, config, invalidateToken } = useCapitalOsAuth();
218
- let iframeManager = null;
219
- function initializeIframe(token, container) {
220
- iframeManager?.destroy();
221
- const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false;
222
- const resolvedTheme = props.theme ?? config.theme;
223
- iframeManager = new __capitalos_core.IframeManager({
224
- container,
225
- tokenData: token,
226
- renderingContext: { entryPoint: "cardsApp" },
227
- theme: resolvedTheme,
228
- enableLogging: resolvedEnableLogging,
229
- logger: config.logger,
230
- sdkVersion: version,
231
- heightOffsetPx: props.heightOffsetPx,
232
- callbacks: {
233
- onLoad: () => {
234
- emit("loaded");
235
- },
236
- onError: (rawError) => {
237
- const capitalOsError = new __capitalos_core.CapitalOSError(rawError);
238
- emit("error", capitalOsError);
239
- },
240
- onTokenExpired: () => {
241
- invalidateToken();
242
- }
243
- }
244
- });
245
- }
246
- (0, vue.watch)([tokenData, containerRef], ([newTokenData, container]) => {
247
- if (newTokenData && container) initializeIframe(newTokenData, container);
248
- }, { immediate: true });
249
- (0, vue.onUnmounted)(() => {
250
- iframeManager?.destroy();
251
- iframeManager = null;
252
- });
253
- return () => (0, vue.h)("div", {
254
- ref: (el) => {
255
- containerRef.value = el;
256
- },
257
- class: "capitalos-iframe-container",
258
- style: { width: "100%" }
402
+ const { render } = useIframeComponent({
403
+ props,
404
+ emit,
405
+ getRenderingContext: () => ({
406
+ entryPoint: "onboarding",
407
+ onboardingEntryPoint: props.entryPoint,
408
+ onboardingExitPoint: props.exitPoint,
409
+ allowExitOnNonApproved: props.allowExitOnNonApproved
410
+ }),
411
+ componentCallbacks: { onboarding: { onDone: (account) => {
412
+ emit("done", account);
413
+ } } }
259
414
  });
415
+ return render;
260
416
  }
261
417
  });
262
418
 
263
419
  //#endregion
420
+ exports.BillPayApp = BillPayApp
264
421
  exports.CAPITALOS_INJECTION_KEY = CAPITALOS_INJECTION_KEY
265
422
  Object.defineProperty(exports, 'CapitalOSError', {
266
423
  enumerable: true,
@@ -275,6 +432,7 @@ Object.defineProperty(exports, 'ErrorCode', {
275
432
  return __capitalos_core.ErrorCode;
276
433
  }
277
434
  });
435
+ exports.Onboarding = Onboarding
278
436
  exports.createCapitalOs = createCapitalOs
279
437
  exports.useCapitalOsAuth = useCapitalOsAuth
280
438
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["globalState: CapitalOsState | null","error: unknown","appOrVue: Vue2Constructor | Vue3App","config: CapitalOsConfig","logger","activeAbortController: AbortController | null","TokenType","TokenParamKey","TokenParamLocation","state: CapitalOsState","error: CapitalOSError","CapitalOSError","iframeManager: IframeManager | null","token: TokenData","container: HTMLElement","IframeManager","SDK_VERSION","rawError: RawErrorDetails","el: Element | null"],"sources":["../src/plugin.ts","../src/composables/use-capitalos-auth.ts","../package.json","../src/components/CardsApp.ts"],"sourcesContent":["// =============================================================================\n// MAINTAINER NOTE: Vue 2.7 vs Vue 3 Plugin Compatibility\n// =============================================================================\n//\n// Vue 2.7 and Vue 3 call plugin.install() with DIFFERENT arguments:\n//\n// Vue 3 consumer code:\n// const app = createApp(App)\n// app.use(myPlugin) // → calls myPlugin.install(app) with app INSTANCE\n//\n// Vue 2.7 consumer code:\n// Vue.use(myPlugin) // → calls myPlugin.install(Vue) with Vue CONSTRUCTOR\n//\n// This matters because:\n// - Vue 3's app instance has app.provide() for dependency injection\n// - Vue 2.7's Vue constructor does NOT have provide() - must use Vue.mixin()\n//\n// This plugin detects which API is available and uses the appropriate method.\n// As an additional fallback for edge cases, we also store state in a module-level\n// variable that `useCapitalOsAuth` can access if `inject()` returns undefined.\n//\n// FUTURE: If we ever need to support Vue < 2.7 or have more complex version-\n// specific logic throughout the codebase, consider using `vue-demi` package\n// (https://github.com/vueuse/vue-demi) which abstracts all Vue 2/3 differences.\n// For now, our simple detection is sufficient since Vue 2.7 has Composition API\n// backported and we only need to handle the plugin install signature difference.\n// =============================================================================\n\nimport { ref, readonly } from 'vue'\nimport {\n exchangeOneTimeToken,\n createLogger,\n TokenType,\n TokenParamKey,\n TokenParamLocation,\n type TokenData,\n} from '@capitalos/core'\nimport type { CapitalOsConfig, CapitalOsState } from './types'\n\n/**\n * Injection key for CapitalOS state.\n * Used with Vue's provide/inject system.\n */\nexport const CAPITALOS_INJECTION_KEY = Symbol('capitalos')\n\n// MAINTAINER NOTE: Module-level state storage for Vue 2.7 compatibility fallback.\n//\n// In Vue 2.7, even with the mixin approach, there can be edge cases where\n// `inject()` doesn't find the provided value (e.g., in the root component\n// or components created before the mixin is applied). This global fallback\n// ensures `useCapitalOsAuth()` always has access to the state.\nlet globalState: CapitalOsState | null = null\n\n// @internal - used by useCapitalOsAuth for Vue 2.7 fallback\nexport function getGlobalState(): CapitalOsState | null {\n return globalState\n}\n\nconst TOKEN_EXCHANGE_TIMEOUT_MS = 10_000\n\n// Converts an unknown error to an Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) {\n return error\n }\n return new Error(String(error))\n}\n\n// MAINTAINER NOTE: Module-level guard against double installation (singleton pattern).\n//\n// This MUST be module-level (not inside createCapitalOs) because:\n// - The plugin creates reactive state that should only exist once\n// - Multiple installations would create multiple token exchange iframes\n// - Multiple auth states would cause inconsistent behavior\n//\n// If a consumer accidentally calls Vue.use(createCapitalOs(...)) twice,\n// the second call will be silently ignored with a warning.\nlet installed = false\n\n// Type for Vue 2 constructor passed to plugin install.\n// In Vue 2.7, `Vue.use(plugin)` passes the Vue constructor.\ninterface Vue2Constructor {\n mixin: (mixin: Record<string, unknown>) => void\n version: string\n}\n\n// Type for Vue 3 app instance passed to plugin install.\n// In Vue 3, `app.use(plugin)` passes the app instance.\ninterface Vue3App {\n provide: (key: symbol, value: unknown) => void\n version: string\n}\n\n// Detect Vue version by checking for Vue 3's `provide` method.\n// Vue 3 app instances have `app.provide()`, Vue 2 constructors don't.\nfunction isVue3App(appOrVue: Vue2Constructor | Vue3App): appOrVue is Vue3App {\n return typeof (appOrVue as Vue3App).provide === 'function'\n}\n\n/**\n * Creates the CapitalOS Vue plugin.\n *\n * Usage (Vue 3):\n * ```typescript\n * import { createApp } from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * const app = createApp(App)\n * app.use(createCapitalOs({ getToken: async () => { ... } }))\n * app.mount('#app')\n * ```\n *\n * Usage (Vue 2.7):\n * ```typescript\n * import Vue from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * Vue.use(createCapitalOs({ getToken: async () => { ... } }))\n * new Vue({ render: h => h(App) }).$mount('#app')\n * ```\n */\nexport function createCapitalOs(config: CapitalOsConfig) {\n return {\n install(appOrVue: Vue2Constructor | Vue3App) {\n // Prevent double installation\n if (installed) {\n const logger = createLogger(config.enableLogging, config.logger)\n logger.warn('[CapitalOS] Plugin already installed, skipping duplicate installation')\n return\n }\n installed = true\n\n const logger = createLogger(config.enableLogging, config.logger)\n\n // Create reactive state\n const tokenData = ref<TokenData | undefined>(undefined)\n const isLoading = ref(false)\n const error = ref<Error | undefined>(undefined)\n\n // AbortController for cancelling in-flight token exchanges\n let activeAbortController: AbortController | null = null\n\n // Refreshes the token by fetching a new one-time token and exchanging it.\n async function refreshToken(): Promise<void> {\n // Prevent concurrent refresh calls - if already loading, skip\n if (isLoading.value) {\n logger.log('[CapitalOS] Token refresh already in progress, skipping')\n return\n }\n\n logger.log('[CapitalOS] Starting token refresh')\n isLoading.value = true\n error.value = undefined\n\n // Abort any in-flight exchange when a new one begins\n activeAbortController?.abort()\n const abortController = new AbortController()\n activeAbortController = abortController\n\n try {\n const oneTimeToken = await config.getToken()\n logger.log('[CapitalOS] Received one-time token')\n\n // Check if aborted after getToken\n if (abortController.signal.aborted) {\n return\n }\n\n // Exchange for long-lived token using @capitalos/core\n const result = await exchangeOneTimeToken({\n oneTimeToken,\n enableLogging: config.enableLogging,\n logger: config.logger,\n timeoutMs: TOKEN_EXCHANGE_TIMEOUT_MS,\n signal: abortController.signal,\n })\n\n // Check if aborted after exchange\n if (abortController.signal.aborted) {\n return\n }\n\n tokenData.value = {\n token: result.longLivedToken,\n tokenType: TokenType.longLived,\n baseUrl: result.baseUrl,\n paramKey: TokenParamKey.accessToken,\n paramLocation: TokenParamLocation.hash,\n }\n logger.log('[CapitalOS] Token exchange complete')\n } catch (e) {\n // Ignore abort errors\n if (e instanceof Error && e.name === 'AbortError') {\n return\n }\n\n const err = toError(e)\n logger.error(`[CapitalOS] Token refresh failed: ${err.message}`)\n error.value = err\n } finally {\n if (activeAbortController === abortController) {\n activeAbortController = null\n }\n isLoading.value = false\n }\n }\n\n // Invalidates the current token, triggering a refresh.\n // Called when the iframe signals that the token has expired.\n function invalidateToken(): void {\n logger.log('[CapitalOS] Invalidating token')\n tokenData.value = undefined\n error.value = undefined\n refreshToken()\n }\n\n // Create state object to provide\n const state: CapitalOsState = {\n tokenData: readonly(tokenData),\n isLoading: readonly(isLoading),\n error: readonly(error),\n invalidateToken,\n config,\n }\n\n // Store globally as fallback for Vue 2.7 edge cases where inject() fails\n globalState = state\n\n // Provide state using the appropriate API based on Vue version\n if (isVue3App(appOrVue)) {\n // Vue 3: use app.provide() - this makes state available to all components\n // via inject(CAPITALOS_INJECTION_KEY)\n appOrVue.provide(CAPITALOS_INJECTION_KEY, state)\n } else {\n // Vue 2.7: use Vue.mixin() to add a provide function to all components.\n // This is the Vue 2 equivalent of app.provide() - it injects the provide\n // option into every component so inject() can find our state.\n appOrVue.mixin({\n provide() {\n return {\n [CAPITALOS_INJECTION_KEY]: state,\n }\n },\n })\n }\n\n // Start token exchange eagerly (matches Angular behavior)\n refreshToken()\n },\n }\n}\n","import { inject, computed, type ComputedRef } from 'vue'\nimport { CAPITALOS_INJECTION_KEY, getGlobalState } from '../plugin'\nimport type { CapitalOsState, AuthState } from '../types'\n\n/**\n * Return type for useCapitalOsAuth composable\n */\nexport interface UseCapitalOsAuthReturn extends CapitalOsState {\n /**\n * Computed authentication state\n */\n authState: ComputedRef<AuthState>\n}\n\n/**\n * @internal\n * Internal composable for accessing CapitalOS authentication state.\n * Used by SDK components - not intended for direct consumer use.\n */\nexport function useCapitalOsAuth(): UseCapitalOsAuthReturn {\n // MAINTAINER NOTE: Vue 2.7 vs Vue 3 Compatibility\n //\n // Try inject() first - this works in:\n // - Vue 3 (via app.provide)\n // - Vue 2.7 (via mixin provide, in most components)\n //\n // Fall back to getGlobalState() for Vue 2.7 edge cases where inject() fails,\n // such as the root component or components created before the mixin is applied.\n //\n // Do NOT remove the ?? getGlobalState() fallback - it's required for Vue 2.7.\n const state = inject<CapitalOsState>(CAPITALOS_INJECTION_KEY) ?? getGlobalState()\n\n if (!state) {\n throw new Error(\n 'useCapitalOsAuth must be used in a component where createCapitalOs plugin is installed. ' +\n 'Make sure to call app.use(createCapitalOs({ ... })) or Vue.use(createCapitalOs({ ... })) in your main.ts'\n )\n }\n\n const authState = computed<AuthState>(() => {\n if (state.isLoading.value) return 'loading'\n if (state.error.value) return 'error'\n if (state.tokenData.value) return 'authenticated'\n return 'idle'\n })\n\n return {\n ...state,\n authState,\n }\n}\n","{\n \"name\": \"@capitalos/vue\",\n \"version\": \"0.1.0-rc.1\",\n \"description\": \"Vue SDK for CapitalOS\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"tsdown --watch\",\n \"lint\": \"eslint src --ext .ts --fix\",\n \"lint-ci\": \"eslint src --ext .ts\",\n \"start\": \"pnpm --filter vue-test-app dev\",\n \"start:all\": \"concurrently \\\"pnpm --filter sdk-test-server start\\\" \\\"pnpm start\\\"\"\n },\n \"keywords\": [\n \"capitalos\",\n \"vue\",\n \"sdk\",\n \"iframe\"\n ],\n \"author\": \"CapitalOS\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"vue\": \"^2.7.0 || ^3.0.0\"\n },\n \"dependencies\": {\n \"@capitalos/core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"tsdown\": \"^0.9.2\",\n \"typescript\": \"^5.6.2\",\n \"vue\": \"^3.5.13\",\n \"concurrently\": \"^9.1.2\"\n }\n}\n","// =============================================================================\n// MAINTAINER NOTE: Why defineComponent + render function instead of SFC?\n// =============================================================================\n//\n// This component uses `defineComponent()` with a render function (`h()`) instead\n// of a Single File Component (.vue file) for Vue 2.7/3 compatibility:\n//\n// - SFCs require different compilers for Vue 2 vs Vue 3\n// - Render functions work identically in both versions\n// - Simpler build - no vue-compiler needed, just TypeScript\n//\n// This is a deliberate architectural choice for cross-version compatibility.\n// Do NOT convert this to an SFC without understanding the implications.\n// =============================================================================\n\nimport { defineComponent, h, ref, watch, onUnmounted, type PropType } from 'vue'\nimport {\n IframeManager,\n CapitalOSError,\n type ThemeColorScheme,\n type TokenData,\n type RawErrorDetails,\n} from '@capitalos/core'\nimport { useCapitalOsAuth } from '../composables/use-capitalos-auth'\nimport { version as SDK_VERSION } from '../../package.json'\n\n/**\n * CardsApp component that renders the CapitalOS cards interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!cardsLoaded\">Loading...</div>\n * <CardsApp\n * @loaded=\"cardsLoaded = true\"\n * @error=\"onCardsError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { CardsApp } from '@capitalos/vue'\n *\n * const cardsLoaded = ref(false)\n * const onCardsError = (error) => console.error(error)\n * </script>\n * ```\n *\n * Note: CardsApp is not designed to be conditionally mounted/unmounted frequently.\n * For show/hide behavior, consumers should toggle visibility (e.g., v-show) rather\n * than mount/unmount repeatedly.\n */\nexport const CardsApp = defineComponent({\n name: 'CardsApp',\n props: {\n /**\n * Theme color scheme for the cards interface.\n * Overrides the theme set in plugin configuration.\n */\n theme: String as PropType<ThemeColorScheme>,\n /**\n * Offset in pixels to add to the iframe height calculation.\n * Useful for avoiding scrollbars when the content height changes dynamically.\n */\n heightOffsetPx: {\n type: Number,\n default: 12,\n },\n /**\n * Whether to enable logging for debugging purposes.\n * Overrides the enableLogging set in plugin configuration.\n */\n enableLogging: Boolean,\n },\n emits: {\n /**\n * Emitted when the cards interface has finished loading.\n */\n loaded: () => true,\n /**\n * Emitted when an error occurs in the cards interface.\n */\n error: (error: CapitalOSError) => error instanceof CapitalOSError,\n },\n setup(props, { emit }) {\n const containerRef = ref<HTMLElement | null>(null)\n const { tokenData, config, invalidateToken } = useCapitalOsAuth()\n\n let iframeManager: IframeManager | null = null\n\n function initializeIframe(token: TokenData, container: HTMLElement): void {\n // Destroy previous iframe before creating new one (matches Angular/React behavior)\n // This ensures token refresh works correctly - new token = new iframe\n iframeManager?.destroy()\n\n const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false\n const resolvedTheme = props.theme ?? config.theme\n\n iframeManager = new IframeManager({\n container,\n tokenData: token,\n renderingContext: { entryPoint: 'cardsApp' },\n theme: resolvedTheme,\n enableLogging: resolvedEnableLogging,\n logger: config.logger,\n sdkVersion: SDK_VERSION,\n heightOffsetPx: props.heightOffsetPx,\n callbacks: {\n onLoad: () => {\n emit('loaded')\n },\n onError: (rawError: RawErrorDetails) => {\n const capitalOsError = new CapitalOSError(rawError)\n emit('error', capitalOsError)\n },\n onTokenExpired: () => {\n invalidateToken()\n },\n },\n })\n }\n\n // MAINTAINER NOTE: Watch for tokenData and container changes to initialize the iframe.\n //\n // Why watch both tokenData AND containerRef?\n // - tokenData: comes from async token exchange, may not be ready on mount\n // - containerRef: DOM element, available after first render\n //\n // Why { immediate: true }?\n // - If tokenData is already available when component mounts, we want to\n // initialize immediately without waiting for a change\n // - Without this, the iframe wouldn't load until tokenData changes again\n watch(\n [tokenData, containerRef],\n ([newTokenData, container]) => {\n if (newTokenData && container) {\n initializeIframe(newTokenData, container)\n }\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n iframeManager?.destroy()\n iframeManager = null\n })\n\n // MAINTAINER NOTE: Render function - creates the container div for the iframe.\n //\n // Why use a function ref `ref: (el) => { ... }` instead of `ref: containerRef`?\n //\n // Vue 2.7 and Vue 3 handle template refs differently in render functions:\n // - Vue 3: can use `ref: containerRef` directly\n // - Vue 2.7: requires function ref pattern for reliable element access\n //\n // The function ref pattern works in both versions, so we use it for compatibility.\n // Do NOT change this to `ref: containerRef` - it will break Vue 2.7 support.\n //\n // The `as unknown as string` type assertion is required because:\n // - Vue 3's TypeScript types don't properly express that function refs are valid\n // - The function ref pattern IS valid at runtime in both Vue 2.7 and Vue 3\n // - This is a known limitation of Vue 3's type definitions\n return () =>\n h('div', {\n // Type assertion required: Vue 3's types don't support function refs in h(),\n // but function refs ARE valid at runtime in both Vue 2.7 and Vue 3\n ref: ((el: Element | null) => {\n containerRef.value = el as HTMLElement | null\n }) as unknown as string,\n class: 'capitalos-iframe-container',\n style: { width: '100%' },\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["globalState: CapitalOsState | null","error: unknown","appOrVue: Vue2Constructor | Vue3App","config: CapitalOsConfig","logger","activeAbortController: AbortController | null","TokenType","TokenParamKey","TokenParamLocation","state: CapitalOsState","error: CapitalOSError","CapitalOSError","options: UseIframeComponentOptions","iframeManager: IframeManager | null","token: TokenData","container: HTMLElement","IframeManager","SDK_VERSION","rawError: RawErrorDetails","CapitalOSError","el: Element | null","_account: Account","account: Account"],"sources":["../src/plugin.ts","../src/components/common-props.ts","../src/composables/use-capitalos-auth.ts","../package.json","../src/composables/use-iframe-component.ts","../src/components/CardsApp.ts","../src/components/BillPayApp.ts","../src/components/Onboarding.ts"],"sourcesContent":["// =============================================================================\n// MAINTAINER NOTE: Vue 2.7 vs Vue 3 Plugin Compatibility\n// =============================================================================\n//\n// Vue 2.7 and Vue 3 call plugin.install() with DIFFERENT arguments:\n//\n// Vue 3 consumer code:\n// const app = createApp(App)\n// app.use(myPlugin) // → calls myPlugin.install(app) with app INSTANCE\n//\n// Vue 2.7 consumer code:\n// Vue.use(myPlugin) // → calls myPlugin.install(Vue) with Vue CONSTRUCTOR\n//\n// This matters because:\n// - Vue 3's app instance has app.provide() for dependency injection\n// - Vue 2.7's Vue constructor does NOT have provide() - must use Vue.mixin()\n//\n// This plugin detects which API is available and uses the appropriate method.\n// As an additional fallback for edge cases, we also store state in a module-level\n// variable that `useCapitalOsAuth` can access if `inject()` returns undefined.\n//\n// FUTURE: If we ever need to support Vue < 2.7 or have more complex version-\n// specific logic throughout the codebase, consider using `vue-demi` package\n// (https://github.com/vueuse/vue-demi) which abstracts all Vue 2/3 differences.\n// For now, our simple detection is sufficient since Vue 2.7 has Composition API\n// backported and we only need to handle the plugin install signature difference.\n// =============================================================================\n\nimport { ref, readonly } from 'vue'\nimport {\n exchangeOneTimeToken,\n createLogger,\n TokenType,\n TokenParamKey,\n TokenParamLocation,\n type TokenData,\n} from '@capitalos/core'\nimport type { CapitalOsConfig, CapitalOsState } from './types'\n\n/**\n * Injection key for CapitalOS state.\n * Used with Vue's provide/inject system.\n */\nexport const CAPITALOS_INJECTION_KEY = Symbol('capitalos')\n\n// MAINTAINER NOTE: Module-level state storage for Vue 2.7 compatibility fallback.\n//\n// In Vue 2.7, even with the mixin approach, there can be edge cases where\n// `inject()` doesn't find the provided value (e.g., in the root component\n// or components created before the mixin is applied). This global fallback\n// ensures `useCapitalOsAuth()` always has access to the state.\nlet globalState: CapitalOsState | null = null\n\n// @internal - used by useCapitalOsAuth for Vue 2.7 fallback\nexport function getGlobalState(): CapitalOsState | null {\n return globalState\n}\n\nconst TOKEN_EXCHANGE_TIMEOUT_MS = 10_000\n\n// Converts an unknown error to an Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) {\n return error\n }\n return new Error(String(error))\n}\n\n// MAINTAINER NOTE: Module-level guard against double installation (singleton pattern).\n//\n// This MUST be module-level (not inside createCapitalOs) because:\n// - The plugin creates reactive state that should only exist once\n// - Multiple installations would create multiple token exchange iframes\n// - Multiple auth states would cause inconsistent behavior\n//\n// If a consumer accidentally calls Vue.use(createCapitalOs(...)) twice,\n// the second call will be silently ignored with a warning.\nlet installed = false\n\n// Type for Vue 2 constructor passed to plugin install.\n// In Vue 2.7, `Vue.use(plugin)` passes the Vue constructor.\ninterface Vue2Constructor {\n mixin: (mixin: Record<string, unknown>) => void\n version: string\n}\n\n// Type for Vue 3 app instance passed to plugin install.\n// In Vue 3, `app.use(plugin)` passes the app instance.\ninterface Vue3App {\n provide: (key: symbol, value: unknown) => void\n version: string\n}\n\n// Detect Vue version by checking for Vue 3's `provide` method.\n// Vue 3 app instances have `app.provide()`, Vue 2 constructors don't.\nfunction isVue3App(appOrVue: Vue2Constructor | Vue3App): appOrVue is Vue3App {\n return typeof (appOrVue as Vue3App).provide === 'function'\n}\n\n/**\n * Creates the CapitalOS Vue plugin.\n *\n * Usage (Vue 3):\n * ```typescript\n * import { createApp } from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * const app = createApp(App)\n * app.use(createCapitalOs({ getToken: async () => { ... } }))\n * app.mount('#app')\n * ```\n *\n * Usage (Vue 2.7):\n * ```typescript\n * import Vue from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * Vue.use(createCapitalOs({ getToken: async () => { ... } }))\n * new Vue({ render: h => h(App) }).$mount('#app')\n * ```\n */\nexport function createCapitalOs(config: CapitalOsConfig) {\n return {\n install(appOrVue: Vue2Constructor | Vue3App) {\n // Prevent double installation\n if (installed) {\n const logger = createLogger(config.enableLogging, config.logger)\n logger.warn('[CapitalOS] Plugin already installed, skipping duplicate installation')\n return\n }\n installed = true\n\n const logger = createLogger(config.enableLogging, config.logger)\n\n // Create reactive state\n const tokenData = ref<TokenData | undefined>(undefined)\n const isLoading = ref(false)\n const error = ref<Error | undefined>(undefined)\n\n // AbortController for cancelling in-flight token exchanges\n let activeAbortController: AbortController | null = null\n\n // Refreshes the token by fetching a new one-time token and exchanging it.\n async function refreshToken(): Promise<void> {\n // Prevent concurrent refresh calls - if already loading, skip\n if (isLoading.value) {\n logger.log('[CapitalOS] Token refresh already in progress, skipping')\n return\n }\n\n logger.log('[CapitalOS] Starting token refresh')\n isLoading.value = true\n error.value = undefined\n\n // Abort any in-flight exchange when a new one begins\n activeAbortController?.abort()\n const abortController = new AbortController()\n activeAbortController = abortController\n\n try {\n const oneTimeToken = await config.getToken()\n logger.log('[CapitalOS] Received one-time token')\n\n // Check if aborted after getToken\n if (abortController.signal.aborted) {\n return\n }\n\n // Exchange for long-lived token using @capitalos/core\n const result = await exchangeOneTimeToken({\n oneTimeToken,\n enableLogging: config.enableLogging,\n logger: config.logger,\n timeoutMs: TOKEN_EXCHANGE_TIMEOUT_MS,\n signal: abortController.signal,\n })\n\n // Check if aborted after exchange\n if (abortController.signal.aborted) {\n return\n }\n\n tokenData.value = {\n token: result.longLivedToken,\n tokenType: TokenType.longLived,\n baseUrl: result.baseUrl,\n paramKey: TokenParamKey.accessToken,\n paramLocation: TokenParamLocation.hash,\n }\n logger.log('[CapitalOS] Token exchange complete')\n } catch (e) {\n // Ignore abort errors\n if (e instanceof Error && e.name === 'AbortError') {\n return\n }\n\n const err = toError(e)\n logger.error(`[CapitalOS] Token refresh failed: ${err.message}`)\n error.value = err\n } finally {\n if (activeAbortController === abortController) {\n activeAbortController = null\n }\n isLoading.value = false\n }\n }\n\n // Invalidates the current token, triggering a refresh.\n // Called when the iframe signals that the token has expired.\n function invalidateToken(): void {\n logger.log('[CapitalOS] Invalidating token')\n tokenData.value = undefined\n error.value = undefined\n refreshToken()\n }\n\n // Create state object to provide\n const state: CapitalOsState = {\n tokenData: readonly(tokenData),\n isLoading: readonly(isLoading),\n error: readonly(error),\n invalidateToken,\n config,\n }\n\n // Store globally as fallback for Vue 2.7 edge cases where inject() fails\n globalState = state\n\n // Provide state using the appropriate API based on Vue version\n if (isVue3App(appOrVue)) {\n // Vue 3: use app.provide() - this makes state available to all components\n // via inject(CAPITALOS_INJECTION_KEY)\n appOrVue.provide(CAPITALOS_INJECTION_KEY, state)\n } else {\n // Vue 2.7: use Vue.mixin() to add a provide function to all components.\n // This is the Vue 2 equivalent of app.provide() - it injects the provide\n // option into every component so inject() can find our state.\n appOrVue.mixin({\n provide() {\n return {\n [CAPITALOS_INJECTION_KEY]: state,\n }\n },\n })\n }\n\n // Start token exchange eagerly (matches Angular behavior)\n refreshToken()\n },\n }\n}\n","import type { PropType } from 'vue'\nimport type { ThemeColorScheme } from '@capitalos/core'\nimport { CapitalOSError } from '@capitalos/core'\n\n/**\n * Common props shared by all CapitalOS Vue components.\n */\nexport const commonProps = {\n /**\n * Theme color scheme for the interface.\n * Overrides the theme set in plugin configuration.\n */\n theme: String as PropType<ThemeColorScheme>,\n /**\n * Offset in pixels to add to the iframe height calculation.\n * Useful for avoiding scrollbars when the content height changes dynamically.\n */\n heightOffsetPx: {\n type: Number,\n default: 12,\n },\n /**\n * Whether to enable logging for debugging purposes.\n * Overrides the enableLogging set in plugin configuration.\n */\n enableLogging: Boolean,\n}\n\n/**\n * Common emits shared by all CapitalOS Vue components.\n */\nexport const commonEmits = {\n /**\n * Emitted when the interface has finished loading.\n */\n loaded: () => true,\n /**\n * Emitted when an error occurs in the interface.\n */\n error: (error: CapitalOSError) => error instanceof CapitalOSError,\n}\n","import { inject, computed, type ComputedRef } from 'vue'\nimport { CAPITALOS_INJECTION_KEY, getGlobalState } from '../plugin'\nimport type { CapitalOsState, AuthState } from '../types'\n\n/**\n * Return type for useCapitalOsAuth composable\n */\nexport interface UseCapitalOsAuthReturn extends CapitalOsState {\n /**\n * Computed authentication state\n */\n authState: ComputedRef<AuthState>\n}\n\n/**\n * @internal\n * Internal composable for accessing CapitalOS authentication state.\n * Used by SDK components - not intended for direct consumer use.\n */\nexport function useCapitalOsAuth(): UseCapitalOsAuthReturn {\n // MAINTAINER NOTE: Vue 2.7 vs Vue 3 Compatibility\n //\n // Try inject() first - this works in:\n // - Vue 3 (via app.provide)\n // - Vue 2.7 (via mixin provide, in most components)\n //\n // Fall back to getGlobalState() for Vue 2.7 edge cases where inject() fails,\n // such as the root component or components created before the mixin is applied.\n //\n // Do NOT remove the ?? getGlobalState() fallback - it's required for Vue 2.7.\n const state = inject<CapitalOsState>(CAPITALOS_INJECTION_KEY) ?? getGlobalState()\n\n if (!state) {\n throw new Error(\n 'useCapitalOsAuth must be used in a component where createCapitalOs plugin is installed. ' +\n 'Make sure to call app.use(createCapitalOs({ ... })) or Vue.use(createCapitalOs({ ... })) in your main.ts'\n )\n }\n\n const authState = computed<AuthState>(() => {\n if (state.isLoading.value) return 'loading'\n if (state.error.value) return 'error'\n if (state.tokenData.value) return 'authenticated'\n return 'idle'\n })\n\n return {\n ...state,\n authState,\n }\n}\n","{\n \"name\": \"@capitalos/vue\",\n \"version\": \"0.1.0\",\n \"description\": \"Vue SDK for CapitalOS\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"tsdown --watch\",\n \"lint\": \"eslint src --ext .ts --fix\",\n \"lint-ci\": \"eslint src --ext .ts\",\n \"start\": \"pnpm --filter vue-test-app dev\",\n \"start:all\": \"concurrently \\\"pnpm --filter sdk-test-server start\\\" \\\"pnpm start\\\"\",\n \"test:pack\": \"pnpm build && pnpm pack\",\n \"prepublishOnly\": \"pnpm build\"\n },\n \"keywords\": [\n \"capitalos\",\n \"vue\",\n \"sdk\",\n \"iframe\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/CapitalOS/theboss\",\n \"directory\": \"sdk/vue\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/CapitalOS/theboss/issues\"\n },\n \"author\": \"CapitalOS\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"vue\": \"^2.7.0 || ^3.0.0\"\n },\n \"dependencies\": {\n \"@capitalos/core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"tsdown\": \"^0.9.2\",\n \"typescript\": \"^5.6.2\",\n \"vue\": \"^3.5.13\",\n \"concurrently\": \"^9.1.2\"\n }\n}\n","import { ref, watch, onUnmounted, h, type VNode, type Ref } from 'vue'\nimport {\n IframeManager,\n CapitalOSError,\n type TokenData,\n type RawErrorDetails,\n type RenderingContext,\n type IframeManagerConfig,\n} from '@capitalos/core'\nimport { useCapitalOsAuth } from './use-capitalos-auth'\nimport { version as SDK_VERSION } from '../../package.json'\n\n/**\n * Props expected by useIframeComponent - matches commonProps shape\n */\nexport interface IframeComponentProps {\n theme?: 'light' | 'dark' | 'system'\n heightOffsetPx: number\n enableLogging?: boolean\n}\n\n/**\n * Emit function type for common events\n */\nexport interface CommonEmitFn {\n (event: 'loaded'): void\n (event: 'error', error: CapitalOSError): void\n}\n\n/**\n * Component-specific callbacks to pass to IframeManager.\n * Excludes common callbacks (onLoad, onError, onTokenExpired) which the composable handles.\n */\nexport type ComponentCallbacks = Omit<IframeManagerConfig['callbacks'], 'onLoad' | 'onError' | 'onTokenExpired'>\n\n/**\n * Options for configuring the iframe component\n */\nexport interface UseIframeComponentOptions {\n /** Props from the component */\n props: IframeComponentProps\n /** Emit function from the component */\n emit: CommonEmitFn\n /** Function that returns the rendering context for this component */\n getRenderingContext: () => RenderingContext\n /** Component-specific callbacks (onboarding, tokenExchange, etc.) */\n componentCallbacks?: ComponentCallbacks\n}\n\n/**\n * Return type for useIframeComponent\n */\nexport interface UseIframeComponentReturn {\n /** Ref to the container element */\n containerRef: Ref<HTMLElement | null>\n /** Render function that returns the container div */\n render: () => VNode\n}\n\n/**\n * Composable that handles common iframe component setup.\n *\n * Manages:\n * - Container ref and iframe manager lifecycle\n * - Token data subscription and iframe initialization\n * - Common callbacks (onLoad, onError, onTokenExpired)\n * - Cleanup on unmount\n * - Render function for the container div\n *\n * Note: Rendering context props (e.g., entryPoint, exitPoint for Onboarding) are read once\n * at iframe initialization. Changes to these props after the iframe loads will NOT trigger\n * re-initialization. This matches the behavior of the React SDK.\n *\n * @example\n * ```ts\n * setup(props, { emit }) {\n * const { render } = useIframeComponent({\n * props,\n * emit,\n * getRenderingContext: () => ({ entryPoint: 'cardsApp' }),\n * })\n * return render\n * }\n * ```\n */\nexport function useIframeComponent(options: UseIframeComponentOptions): UseIframeComponentReturn {\n const { props, emit, getRenderingContext, componentCallbacks } = options\n\n const containerRef = ref<HTMLElement | null>(null)\n const { tokenData, config, invalidateToken } = useCapitalOsAuth()\n\n let iframeManager: IframeManager | null = null\n\n function initializeIframe(token: TokenData, container: HTMLElement): void {\n // Destroy previous iframe before creating new one (matches Angular/React behavior)\n // This ensures token refresh works correctly - new token = new iframe\n iframeManager?.destroy()\n\n const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false\n const resolvedTheme = props.theme ?? config.theme\n\n iframeManager = new IframeManager({\n container,\n tokenData: token,\n renderingContext: getRenderingContext(),\n theme: resolvedTheme,\n enableLogging: resolvedEnableLogging,\n logger: config.logger,\n sdkVersion: SDK_VERSION,\n heightOffsetPx: props.heightOffsetPx,\n callbacks: {\n onLoad: () => {\n emit('loaded')\n },\n onError: (rawError: RawErrorDetails) => {\n emit('error', new CapitalOSError(rawError))\n },\n onTokenExpired: () => {\n invalidateToken()\n },\n ...componentCallbacks,\n },\n })\n }\n\n // Watch for tokenData and container changes to initialize the iframe.\n //\n // Why watch both tokenData AND containerRef?\n // - tokenData: comes from async token exchange, may not be ready on mount\n // - containerRef: DOM element, available after first render\n //\n // Why { immediate: true }?\n // - If tokenData is already available when component mounts, we want to\n // initialize immediately without waiting for a change\n // - Without this, the iframe wouldn't load until tokenData changes again\n watch(\n [tokenData, containerRef],\n ([newTokenData, container]) => {\n if (newTokenData && container) {\n initializeIframe(newTokenData, container)\n }\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n iframeManager?.destroy()\n iframeManager = null\n })\n\n // Render function - creates the container div for the iframe.\n //\n // Why use a function ref `ref: (el) => { ... }` instead of `ref: containerRef`?\n //\n // Vue 2.7 and Vue 3 handle template refs differently in render functions:\n // - Vue 3: can use `ref: containerRef` directly\n // - Vue 2.7: requires function ref pattern for reliable element access\n //\n // The function ref pattern works in both versions, so we use it for compatibility.\n // Do NOT change this to `ref: containerRef` - it will break Vue 2.7 support.\n //\n // The `as unknown as string` type assertion is required because:\n // - Vue 3's TypeScript types don't properly express that function refs are valid\n // - The function ref pattern IS valid at runtime in both Vue 2.7 and Vue 3\n // - This is a known limitation of Vue 3's type definitions\n function render(): VNode {\n return h('div', {\n // Type assertion required: Vue 3's types don't support function refs in h(),\n // but function refs ARE valid at runtime in both Vue 2.7 and Vue 3\n ref: ((el: Element | null) => {\n containerRef.value = el as HTMLElement | null\n }) as unknown as string,\n class: 'capitalos-iframe-container',\n style: { width: '100%' },\n })\n }\n\n return {\n containerRef,\n render,\n }\n}\n","import { defineComponent } from 'vue'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * CardsApp component that renders the CapitalOS cards interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!cardsLoaded\">Loading...</div>\n * <CardsApp\n * @loaded=\"cardsLoaded = true\"\n * @error=\"onCardsError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { CardsApp } from '@capitalos/vue'\n *\n * const cardsLoaded = ref(false)\n * const onCardsError = (error) => console.error(error)\n * </script>\n * ```\n */\nexport const CardsApp = defineComponent({\n name: 'CardsApp',\n props: commonProps,\n emits: commonEmits,\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({ entryPoint: 'cardsApp' }),\n })\n\n return render\n },\n})\n","import { defineComponent } from 'vue'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * BillPayApp component that renders the CapitalOS bill payment interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!billPayLoaded\">Loading...</div>\n * <BillPayApp\n * @loaded=\"billPayLoaded = true\"\n * @error=\"onBillPayError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { BillPayApp } from '@capitalos/vue'\n *\n * const billPayLoaded = ref(false)\n * const onBillPayError = (error) => console.error(error)\n * </script>\n * ```\n */\nexport const BillPayApp = defineComponent({\n name: 'BillPayApp',\n props: commonProps,\n emits: commonEmits,\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({ entryPoint: 'billPayApp' }),\n })\n\n return render\n },\n})\n","import { defineComponent, type PropType } from 'vue'\nimport type { Account, OnboardingEntryPoint, OnboardingExitPoint } from '@capitalos/core'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * Onboarding component that renders the CapitalOS onboarding flow in an iframe.\n *\n * The component emits events for loading state and completion - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!onboardingLoaded\">Loading...</div>\n * <Onboarding\n * entry-point=\"welcome\"\n * exit-point=\"activation\"\n * @loaded=\"onboardingLoaded = true\"\n * @error=\"onOnboardingError\"\n * @done=\"onOnboardingComplete\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { Onboarding } from '@capitalos/vue'\n *\n * const onboardingLoaded = ref(false)\n * const onOnboardingError = (error) => console.error(error)\n * const onOnboardingComplete = (account) => {\n * console.log('Onboarding complete:', account.status)\n * }\n * </script>\n * ```\n */\nexport const Onboarding = defineComponent({\n name: 'Onboarding',\n props: {\n ...commonProps,\n /**\n * The starting point of the onboarding flow.\n * @default 'welcome'\n */\n entryPoint: String as PropType<OnboardingEntryPoint>,\n /**\n * The ending point of the onboarding flow.\n * @default 'activation'\n */\n exitPoint: String as PropType<OnboardingExitPoint>,\n /**\n * Whether to allow the user to exit the onboarding flow by clicking the done button\n * when they finished the onboarding form but are still not approved (e.g. waiting or pending).\n * This should only be false if you want the user to stay on the onboarding flow\n * (e.g. to add bank account) and not exit the flow.\n * @default true\n */\n allowExitOnNonApproved: {\n type: Boolean,\n default: undefined,\n },\n },\n emits: {\n ...commonEmits,\n /**\n * Emitted when the onboarding flow completes successfully.\n */\n done: (_account: Account) => true,\n },\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({\n entryPoint: 'onboarding',\n onboardingEntryPoint: props.entryPoint,\n onboardingExitPoint: props.exitPoint,\n allowExitOnNonApproved: props.allowExitOnNonApproved,\n }),\n componentCallbacks: {\n onboarding: {\n onDone: (account: Account) => {\n emit('done', account)\n },\n },\n },\n })\n\n return render\n },\n})\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -118,6 +118,27 @@ function createCapitalOs(config) {
118
118
  } };
119
119
  }
120
120
 
121
+ //#endregion
122
+ //#region src/components/common-props.ts
123
+ /**
124
+ * Common props shared by all CapitalOS Vue components.
125
+ */
126
+ const commonProps = {
127
+ theme: String,
128
+ heightOffsetPx: {
129
+ type: Number,
130
+ default: 12
131
+ },
132
+ enableLogging: Boolean
133
+ };
134
+ /**
135
+ * Common emits shared by all CapitalOS Vue components.
136
+ */
137
+ const commonEmits = {
138
+ loaded: () => true,
139
+ error: (error) => error instanceof CapitalOSError$1
140
+ };
141
+
121
142
  //#endregion
122
143
  //#region src/composables/use-capitalos-auth.ts
123
144
  /**
@@ -142,7 +163,89 @@ function useCapitalOsAuth() {
142
163
 
143
164
  //#endregion
144
165
  //#region package.json
145
- var version = "0.1.0-rc.1";
166
+ var version = "0.1.0";
167
+
168
+ //#endregion
169
+ //#region src/composables/use-iframe-component.ts
170
+ /**
171
+ * Composable that handles common iframe component setup.
172
+ *
173
+ * Manages:
174
+ * - Container ref and iframe manager lifecycle
175
+ * - Token data subscription and iframe initialization
176
+ * - Common callbacks (onLoad, onError, onTokenExpired)
177
+ * - Cleanup on unmount
178
+ * - Render function for the container div
179
+ *
180
+ * Note: Rendering context props (e.g., entryPoint, exitPoint for Onboarding) are read once
181
+ * at iframe initialization. Changes to these props after the iframe loads will NOT trigger
182
+ * re-initialization. This matches the behavior of the React SDK.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * setup(props, { emit }) {
187
+ * const { render } = useIframeComponent({
188
+ * props,
189
+ * emit,
190
+ * getRenderingContext: () => ({ entryPoint: 'cardsApp' }),
191
+ * })
192
+ * return render
193
+ * }
194
+ * ```
195
+ */
196
+ function useIframeComponent(options) {
197
+ const { props, emit, getRenderingContext, componentCallbacks } = options;
198
+ const containerRef = ref(null);
199
+ const { tokenData, config, invalidateToken } = useCapitalOsAuth();
200
+ let iframeManager = null;
201
+ function initializeIframe(token, container) {
202
+ iframeManager?.destroy();
203
+ const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false;
204
+ const resolvedTheme = props.theme ?? config.theme;
205
+ iframeManager = new IframeManager({
206
+ container,
207
+ tokenData: token,
208
+ renderingContext: getRenderingContext(),
209
+ theme: resolvedTheme,
210
+ enableLogging: resolvedEnableLogging,
211
+ logger: config.logger,
212
+ sdkVersion: version,
213
+ heightOffsetPx: props.heightOffsetPx,
214
+ callbacks: {
215
+ onLoad: () => {
216
+ emit("loaded");
217
+ },
218
+ onError: (rawError) => {
219
+ emit("error", new CapitalOSError$1(rawError));
220
+ },
221
+ onTokenExpired: () => {
222
+ invalidateToken();
223
+ },
224
+ ...componentCallbacks
225
+ }
226
+ });
227
+ }
228
+ watch([tokenData, containerRef], ([newTokenData, container]) => {
229
+ if (newTokenData && container) initializeIframe(newTokenData, container);
230
+ }, { immediate: true });
231
+ onUnmounted(() => {
232
+ iframeManager?.destroy();
233
+ iframeManager = null;
234
+ });
235
+ function render() {
236
+ return h("div", {
237
+ ref: (el) => {
238
+ containerRef.value = el;
239
+ },
240
+ class: "capitalos-iframe-container",
241
+ style: { width: "100%" }
242
+ });
243
+ }
244
+ return {
245
+ containerRef,
246
+ render
247
+ };
248
+ }
146
249
 
147
250
  //#endregion
148
251
  //#region src/components/CardsApp.ts
@@ -169,73 +272,126 @@ var version = "0.1.0-rc.1";
169
272
  * const onCardsError = (error) => console.error(error)
170
273
  * </script>
171
274
  * ```
172
- *
173
- * Note: CardsApp is not designed to be conditionally mounted/unmounted frequently.
174
- * For show/hide behavior, consumers should toggle visibility (e.g., v-show) rather
175
- * than mount/unmount repeatedly.
176
275
  */
177
276
  const CardsApp = defineComponent({
178
277
  name: "CardsApp",
278
+ props: commonProps,
279
+ emits: commonEmits,
280
+ setup(props, { emit }) {
281
+ const { render } = useIframeComponent({
282
+ props,
283
+ emit,
284
+ getRenderingContext: () => ({ entryPoint: "cardsApp" })
285
+ });
286
+ return render;
287
+ }
288
+ });
289
+
290
+ //#endregion
291
+ //#region src/components/BillPayApp.ts
292
+ /**
293
+ * BillPayApp component that renders the CapitalOS bill payment interface in an iframe.
294
+ *
295
+ * The component emits events for loading state - consumers should handle their own loading UI:
296
+ *
297
+ * @example
298
+ * ```vue
299
+ * <template>
300
+ * <div v-if="!billPayLoaded">Loading...</div>
301
+ * <BillPayApp
302
+ * @loaded="billPayLoaded = true"
303
+ * @error="onBillPayError"
304
+ * />
305
+ * </template>
306
+ *
307
+ * <script setup>
308
+ * import { ref } from 'vue'
309
+ * import { BillPayApp } from '@capitalos/vue'
310
+ *
311
+ * const billPayLoaded = ref(false)
312
+ * const onBillPayError = (error) => console.error(error)
313
+ * </script>
314
+ * ```
315
+ */
316
+ const BillPayApp = defineComponent({
317
+ name: "BillPayApp",
318
+ props: commonProps,
319
+ emits: commonEmits,
320
+ setup(props, { emit }) {
321
+ const { render } = useIframeComponent({
322
+ props,
323
+ emit,
324
+ getRenderingContext: () => ({ entryPoint: "billPayApp" })
325
+ });
326
+ return render;
327
+ }
328
+ });
329
+
330
+ //#endregion
331
+ //#region src/components/Onboarding.ts
332
+ /**
333
+ * Onboarding component that renders the CapitalOS onboarding flow in an iframe.
334
+ *
335
+ * The component emits events for loading state and completion - consumers should handle their own loading UI:
336
+ *
337
+ * @example
338
+ * ```vue
339
+ * <template>
340
+ * <div v-if="!onboardingLoaded">Loading...</div>
341
+ * <Onboarding
342
+ * entry-point="welcome"
343
+ * exit-point="activation"
344
+ * @loaded="onboardingLoaded = true"
345
+ * @error="onOnboardingError"
346
+ * @done="onOnboardingComplete"
347
+ * />
348
+ * </template>
349
+ *
350
+ * <script setup>
351
+ * import { ref } from 'vue'
352
+ * import { Onboarding } from '@capitalos/vue'
353
+ *
354
+ * const onboardingLoaded = ref(false)
355
+ * const onOnboardingError = (error) => console.error(error)
356
+ * const onOnboardingComplete = (account) => {
357
+ * console.log('Onboarding complete:', account.status)
358
+ * }
359
+ * </script>
360
+ * ```
361
+ */
362
+ const Onboarding = defineComponent({
363
+ name: "Onboarding",
179
364
  props: {
180
- theme: String,
181
- heightOffsetPx: {
182
- type: Number,
183
- default: 12
184
- },
185
- enableLogging: Boolean
365
+ ...commonProps,
366
+ entryPoint: String,
367
+ exitPoint: String,
368
+ allowExitOnNonApproved: {
369
+ type: Boolean,
370
+ default: void 0
371
+ }
186
372
  },
187
373
  emits: {
188
- loaded: () => true,
189
- error: (error) => error instanceof CapitalOSError$1
374
+ ...commonEmits,
375
+ done: (_account) => true
190
376
  },
191
377
  setup(props, { emit }) {
192
- const containerRef = ref(null);
193
- const { tokenData, config, invalidateToken } = useCapitalOsAuth();
194
- let iframeManager = null;
195
- function initializeIframe(token, container) {
196
- iframeManager?.destroy();
197
- const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false;
198
- const resolvedTheme = props.theme ?? config.theme;
199
- iframeManager = new IframeManager({
200
- container,
201
- tokenData: token,
202
- renderingContext: { entryPoint: "cardsApp" },
203
- theme: resolvedTheme,
204
- enableLogging: resolvedEnableLogging,
205
- logger: config.logger,
206
- sdkVersion: version,
207
- heightOffsetPx: props.heightOffsetPx,
208
- callbacks: {
209
- onLoad: () => {
210
- emit("loaded");
211
- },
212
- onError: (rawError) => {
213
- const capitalOsError = new CapitalOSError$1(rawError);
214
- emit("error", capitalOsError);
215
- },
216
- onTokenExpired: () => {
217
- invalidateToken();
218
- }
219
- }
220
- });
221
- }
222
- watch([tokenData, containerRef], ([newTokenData, container]) => {
223
- if (newTokenData && container) initializeIframe(newTokenData, container);
224
- }, { immediate: true });
225
- onUnmounted(() => {
226
- iframeManager?.destroy();
227
- iframeManager = null;
228
- });
229
- return () => h("div", {
230
- ref: (el) => {
231
- containerRef.value = el;
232
- },
233
- class: "capitalos-iframe-container",
234
- style: { width: "100%" }
378
+ const { render } = useIframeComponent({
379
+ props,
380
+ emit,
381
+ getRenderingContext: () => ({
382
+ entryPoint: "onboarding",
383
+ onboardingEntryPoint: props.entryPoint,
384
+ onboardingExitPoint: props.exitPoint,
385
+ allowExitOnNonApproved: props.allowExitOnNonApproved
386
+ }),
387
+ componentCallbacks: { onboarding: { onDone: (account) => {
388
+ emit("done", account);
389
+ } } }
235
390
  });
391
+ return render;
236
392
  }
237
393
  });
238
394
 
239
395
  //#endregion
240
- export { CAPITALOS_INJECTION_KEY, CapitalOSError, CardsApp, ErrorCode, createCapitalOs, useCapitalOsAuth };
396
+ export { BillPayApp, CAPITALOS_INJECTION_KEY, CapitalOSError, CardsApp, ErrorCode, Onboarding, createCapitalOs, useCapitalOsAuth };
241
397
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["globalState: CapitalOsState | null","error: unknown","appOrVue: Vue2Constructor | Vue3App","config: CapitalOsConfig","logger","activeAbortController: AbortController | null","state: CapitalOsState","error: CapitalOSError","CapitalOSError","iframeManager: IframeManager | null","token: TokenData","container: HTMLElement","SDK_VERSION","rawError: RawErrorDetails","el: Element | null"],"sources":["../src/plugin.ts","../src/composables/use-capitalos-auth.ts","../package.json","../src/components/CardsApp.ts"],"sourcesContent":["// =============================================================================\n// MAINTAINER NOTE: Vue 2.7 vs Vue 3 Plugin Compatibility\n// =============================================================================\n//\n// Vue 2.7 and Vue 3 call plugin.install() with DIFFERENT arguments:\n//\n// Vue 3 consumer code:\n// const app = createApp(App)\n// app.use(myPlugin) // → calls myPlugin.install(app) with app INSTANCE\n//\n// Vue 2.7 consumer code:\n// Vue.use(myPlugin) // → calls myPlugin.install(Vue) with Vue CONSTRUCTOR\n//\n// This matters because:\n// - Vue 3's app instance has app.provide() for dependency injection\n// - Vue 2.7's Vue constructor does NOT have provide() - must use Vue.mixin()\n//\n// This plugin detects which API is available and uses the appropriate method.\n// As an additional fallback for edge cases, we also store state in a module-level\n// variable that `useCapitalOsAuth` can access if `inject()` returns undefined.\n//\n// FUTURE: If we ever need to support Vue < 2.7 or have more complex version-\n// specific logic throughout the codebase, consider using `vue-demi` package\n// (https://github.com/vueuse/vue-demi) which abstracts all Vue 2/3 differences.\n// For now, our simple detection is sufficient since Vue 2.7 has Composition API\n// backported and we only need to handle the plugin install signature difference.\n// =============================================================================\n\nimport { ref, readonly } from 'vue'\nimport {\n exchangeOneTimeToken,\n createLogger,\n TokenType,\n TokenParamKey,\n TokenParamLocation,\n type TokenData,\n} from '@capitalos/core'\nimport type { CapitalOsConfig, CapitalOsState } from './types'\n\n/**\n * Injection key for CapitalOS state.\n * Used with Vue's provide/inject system.\n */\nexport const CAPITALOS_INJECTION_KEY = Symbol('capitalos')\n\n// MAINTAINER NOTE: Module-level state storage for Vue 2.7 compatibility fallback.\n//\n// In Vue 2.7, even with the mixin approach, there can be edge cases where\n// `inject()` doesn't find the provided value (e.g., in the root component\n// or components created before the mixin is applied). This global fallback\n// ensures `useCapitalOsAuth()` always has access to the state.\nlet globalState: CapitalOsState | null = null\n\n// @internal - used by useCapitalOsAuth for Vue 2.7 fallback\nexport function getGlobalState(): CapitalOsState | null {\n return globalState\n}\n\nconst TOKEN_EXCHANGE_TIMEOUT_MS = 10_000\n\n// Converts an unknown error to an Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) {\n return error\n }\n return new Error(String(error))\n}\n\n// MAINTAINER NOTE: Module-level guard against double installation (singleton pattern).\n//\n// This MUST be module-level (not inside createCapitalOs) because:\n// - The plugin creates reactive state that should only exist once\n// - Multiple installations would create multiple token exchange iframes\n// - Multiple auth states would cause inconsistent behavior\n//\n// If a consumer accidentally calls Vue.use(createCapitalOs(...)) twice,\n// the second call will be silently ignored with a warning.\nlet installed = false\n\n// Type for Vue 2 constructor passed to plugin install.\n// In Vue 2.7, `Vue.use(plugin)` passes the Vue constructor.\ninterface Vue2Constructor {\n mixin: (mixin: Record<string, unknown>) => void\n version: string\n}\n\n// Type for Vue 3 app instance passed to plugin install.\n// In Vue 3, `app.use(plugin)` passes the app instance.\ninterface Vue3App {\n provide: (key: symbol, value: unknown) => void\n version: string\n}\n\n// Detect Vue version by checking for Vue 3's `provide` method.\n// Vue 3 app instances have `app.provide()`, Vue 2 constructors don't.\nfunction isVue3App(appOrVue: Vue2Constructor | Vue3App): appOrVue is Vue3App {\n return typeof (appOrVue as Vue3App).provide === 'function'\n}\n\n/**\n * Creates the CapitalOS Vue plugin.\n *\n * Usage (Vue 3):\n * ```typescript\n * import { createApp } from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * const app = createApp(App)\n * app.use(createCapitalOs({ getToken: async () => { ... } }))\n * app.mount('#app')\n * ```\n *\n * Usage (Vue 2.7):\n * ```typescript\n * import Vue from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * Vue.use(createCapitalOs({ getToken: async () => { ... } }))\n * new Vue({ render: h => h(App) }).$mount('#app')\n * ```\n */\nexport function createCapitalOs(config: CapitalOsConfig) {\n return {\n install(appOrVue: Vue2Constructor | Vue3App) {\n // Prevent double installation\n if (installed) {\n const logger = createLogger(config.enableLogging, config.logger)\n logger.warn('[CapitalOS] Plugin already installed, skipping duplicate installation')\n return\n }\n installed = true\n\n const logger = createLogger(config.enableLogging, config.logger)\n\n // Create reactive state\n const tokenData = ref<TokenData | undefined>(undefined)\n const isLoading = ref(false)\n const error = ref<Error | undefined>(undefined)\n\n // AbortController for cancelling in-flight token exchanges\n let activeAbortController: AbortController | null = null\n\n // Refreshes the token by fetching a new one-time token and exchanging it.\n async function refreshToken(): Promise<void> {\n // Prevent concurrent refresh calls - if already loading, skip\n if (isLoading.value) {\n logger.log('[CapitalOS] Token refresh already in progress, skipping')\n return\n }\n\n logger.log('[CapitalOS] Starting token refresh')\n isLoading.value = true\n error.value = undefined\n\n // Abort any in-flight exchange when a new one begins\n activeAbortController?.abort()\n const abortController = new AbortController()\n activeAbortController = abortController\n\n try {\n const oneTimeToken = await config.getToken()\n logger.log('[CapitalOS] Received one-time token')\n\n // Check if aborted after getToken\n if (abortController.signal.aborted) {\n return\n }\n\n // Exchange for long-lived token using @capitalos/core\n const result = await exchangeOneTimeToken({\n oneTimeToken,\n enableLogging: config.enableLogging,\n logger: config.logger,\n timeoutMs: TOKEN_EXCHANGE_TIMEOUT_MS,\n signal: abortController.signal,\n })\n\n // Check if aborted after exchange\n if (abortController.signal.aborted) {\n return\n }\n\n tokenData.value = {\n token: result.longLivedToken,\n tokenType: TokenType.longLived,\n baseUrl: result.baseUrl,\n paramKey: TokenParamKey.accessToken,\n paramLocation: TokenParamLocation.hash,\n }\n logger.log('[CapitalOS] Token exchange complete')\n } catch (e) {\n // Ignore abort errors\n if (e instanceof Error && e.name === 'AbortError') {\n return\n }\n\n const err = toError(e)\n logger.error(`[CapitalOS] Token refresh failed: ${err.message}`)\n error.value = err\n } finally {\n if (activeAbortController === abortController) {\n activeAbortController = null\n }\n isLoading.value = false\n }\n }\n\n // Invalidates the current token, triggering a refresh.\n // Called when the iframe signals that the token has expired.\n function invalidateToken(): void {\n logger.log('[CapitalOS] Invalidating token')\n tokenData.value = undefined\n error.value = undefined\n refreshToken()\n }\n\n // Create state object to provide\n const state: CapitalOsState = {\n tokenData: readonly(tokenData),\n isLoading: readonly(isLoading),\n error: readonly(error),\n invalidateToken,\n config,\n }\n\n // Store globally as fallback for Vue 2.7 edge cases where inject() fails\n globalState = state\n\n // Provide state using the appropriate API based on Vue version\n if (isVue3App(appOrVue)) {\n // Vue 3: use app.provide() - this makes state available to all components\n // via inject(CAPITALOS_INJECTION_KEY)\n appOrVue.provide(CAPITALOS_INJECTION_KEY, state)\n } else {\n // Vue 2.7: use Vue.mixin() to add a provide function to all components.\n // This is the Vue 2 equivalent of app.provide() - it injects the provide\n // option into every component so inject() can find our state.\n appOrVue.mixin({\n provide() {\n return {\n [CAPITALOS_INJECTION_KEY]: state,\n }\n },\n })\n }\n\n // Start token exchange eagerly (matches Angular behavior)\n refreshToken()\n },\n }\n}\n","import { inject, computed, type ComputedRef } from 'vue'\nimport { CAPITALOS_INJECTION_KEY, getGlobalState } from '../plugin'\nimport type { CapitalOsState, AuthState } from '../types'\n\n/**\n * Return type for useCapitalOsAuth composable\n */\nexport interface UseCapitalOsAuthReturn extends CapitalOsState {\n /**\n * Computed authentication state\n */\n authState: ComputedRef<AuthState>\n}\n\n/**\n * @internal\n * Internal composable for accessing CapitalOS authentication state.\n * Used by SDK components - not intended for direct consumer use.\n */\nexport function useCapitalOsAuth(): UseCapitalOsAuthReturn {\n // MAINTAINER NOTE: Vue 2.7 vs Vue 3 Compatibility\n //\n // Try inject() first - this works in:\n // - Vue 3 (via app.provide)\n // - Vue 2.7 (via mixin provide, in most components)\n //\n // Fall back to getGlobalState() for Vue 2.7 edge cases where inject() fails,\n // such as the root component or components created before the mixin is applied.\n //\n // Do NOT remove the ?? getGlobalState() fallback - it's required for Vue 2.7.\n const state = inject<CapitalOsState>(CAPITALOS_INJECTION_KEY) ?? getGlobalState()\n\n if (!state) {\n throw new Error(\n 'useCapitalOsAuth must be used in a component where createCapitalOs plugin is installed. ' +\n 'Make sure to call app.use(createCapitalOs({ ... })) or Vue.use(createCapitalOs({ ... })) in your main.ts'\n )\n }\n\n const authState = computed<AuthState>(() => {\n if (state.isLoading.value) return 'loading'\n if (state.error.value) return 'error'\n if (state.tokenData.value) return 'authenticated'\n return 'idle'\n })\n\n return {\n ...state,\n authState,\n }\n}\n","{\n \"name\": \"@capitalos/vue\",\n \"version\": \"0.1.0-rc.1\",\n \"description\": \"Vue SDK for CapitalOS\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"tsdown --watch\",\n \"lint\": \"eslint src --ext .ts --fix\",\n \"lint-ci\": \"eslint src --ext .ts\",\n \"start\": \"pnpm --filter vue-test-app dev\",\n \"start:all\": \"concurrently \\\"pnpm --filter sdk-test-server start\\\" \\\"pnpm start\\\"\"\n },\n \"keywords\": [\n \"capitalos\",\n \"vue\",\n \"sdk\",\n \"iframe\"\n ],\n \"author\": \"CapitalOS\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"vue\": \"^2.7.0 || ^3.0.0\"\n },\n \"dependencies\": {\n \"@capitalos/core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"tsdown\": \"^0.9.2\",\n \"typescript\": \"^5.6.2\",\n \"vue\": \"^3.5.13\",\n \"concurrently\": \"^9.1.2\"\n }\n}\n","// =============================================================================\n// MAINTAINER NOTE: Why defineComponent + render function instead of SFC?\n// =============================================================================\n//\n// This component uses `defineComponent()` with a render function (`h()`) instead\n// of a Single File Component (.vue file) for Vue 2.7/3 compatibility:\n//\n// - SFCs require different compilers for Vue 2 vs Vue 3\n// - Render functions work identically in both versions\n// - Simpler build - no vue-compiler needed, just TypeScript\n//\n// This is a deliberate architectural choice for cross-version compatibility.\n// Do NOT convert this to an SFC without understanding the implications.\n// =============================================================================\n\nimport { defineComponent, h, ref, watch, onUnmounted, type PropType } from 'vue'\nimport {\n IframeManager,\n CapitalOSError,\n type ThemeColorScheme,\n type TokenData,\n type RawErrorDetails,\n} from '@capitalos/core'\nimport { useCapitalOsAuth } from '../composables/use-capitalos-auth'\nimport { version as SDK_VERSION } from '../../package.json'\n\n/**\n * CardsApp component that renders the CapitalOS cards interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!cardsLoaded\">Loading...</div>\n * <CardsApp\n * @loaded=\"cardsLoaded = true\"\n * @error=\"onCardsError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { CardsApp } from '@capitalos/vue'\n *\n * const cardsLoaded = ref(false)\n * const onCardsError = (error) => console.error(error)\n * </script>\n * ```\n *\n * Note: CardsApp is not designed to be conditionally mounted/unmounted frequently.\n * For show/hide behavior, consumers should toggle visibility (e.g., v-show) rather\n * than mount/unmount repeatedly.\n */\nexport const CardsApp = defineComponent({\n name: 'CardsApp',\n props: {\n /**\n * Theme color scheme for the cards interface.\n * Overrides the theme set in plugin configuration.\n */\n theme: String as PropType<ThemeColorScheme>,\n /**\n * Offset in pixels to add to the iframe height calculation.\n * Useful for avoiding scrollbars when the content height changes dynamically.\n */\n heightOffsetPx: {\n type: Number,\n default: 12,\n },\n /**\n * Whether to enable logging for debugging purposes.\n * Overrides the enableLogging set in plugin configuration.\n */\n enableLogging: Boolean,\n },\n emits: {\n /**\n * Emitted when the cards interface has finished loading.\n */\n loaded: () => true,\n /**\n * Emitted when an error occurs in the cards interface.\n */\n error: (error: CapitalOSError) => error instanceof CapitalOSError,\n },\n setup(props, { emit }) {\n const containerRef = ref<HTMLElement | null>(null)\n const { tokenData, config, invalidateToken } = useCapitalOsAuth()\n\n let iframeManager: IframeManager | null = null\n\n function initializeIframe(token: TokenData, container: HTMLElement): void {\n // Destroy previous iframe before creating new one (matches Angular/React behavior)\n // This ensures token refresh works correctly - new token = new iframe\n iframeManager?.destroy()\n\n const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false\n const resolvedTheme = props.theme ?? config.theme\n\n iframeManager = new IframeManager({\n container,\n tokenData: token,\n renderingContext: { entryPoint: 'cardsApp' },\n theme: resolvedTheme,\n enableLogging: resolvedEnableLogging,\n logger: config.logger,\n sdkVersion: SDK_VERSION,\n heightOffsetPx: props.heightOffsetPx,\n callbacks: {\n onLoad: () => {\n emit('loaded')\n },\n onError: (rawError: RawErrorDetails) => {\n const capitalOsError = new CapitalOSError(rawError)\n emit('error', capitalOsError)\n },\n onTokenExpired: () => {\n invalidateToken()\n },\n },\n })\n }\n\n // MAINTAINER NOTE: Watch for tokenData and container changes to initialize the iframe.\n //\n // Why watch both tokenData AND containerRef?\n // - tokenData: comes from async token exchange, may not be ready on mount\n // - containerRef: DOM element, available after first render\n //\n // Why { immediate: true }?\n // - If tokenData is already available when component mounts, we want to\n // initialize immediately without waiting for a change\n // - Without this, the iframe wouldn't load until tokenData changes again\n watch(\n [tokenData, containerRef],\n ([newTokenData, container]) => {\n if (newTokenData && container) {\n initializeIframe(newTokenData, container)\n }\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n iframeManager?.destroy()\n iframeManager = null\n })\n\n // MAINTAINER NOTE: Render function - creates the container div for the iframe.\n //\n // Why use a function ref `ref: (el) => { ... }` instead of `ref: containerRef`?\n //\n // Vue 2.7 and Vue 3 handle template refs differently in render functions:\n // - Vue 3: can use `ref: containerRef` directly\n // - Vue 2.7: requires function ref pattern for reliable element access\n //\n // The function ref pattern works in both versions, so we use it for compatibility.\n // Do NOT change this to `ref: containerRef` - it will break Vue 2.7 support.\n //\n // The `as unknown as string` type assertion is required because:\n // - Vue 3's TypeScript types don't properly express that function refs are valid\n // - The function ref pattern IS valid at runtime in both Vue 2.7 and Vue 3\n // - This is a known limitation of Vue 3's type definitions\n return () =>\n h('div', {\n // Type assertion required: Vue 3's types don't support function refs in h(),\n // but function refs ARE valid at runtime in both Vue 2.7 and Vue 3\n ref: ((el: Element | null) => {\n containerRef.value = el as HTMLElement | null\n }) as unknown as string,\n class: 'capitalos-iframe-container',\n style: { width: '100%' },\n })\n },\n})\n"],"mappings":";;;;;;;;AA2CA,MAAa,0BAA0B,OAAO,YAAY;AAQ1D,IAAIA,cAAqC;AAGzC,SAAgB,iBAAwC;AACtD,QAAO;AACR;AAED,MAAM,4BAA4B;AAGlC,SAAS,QAAQC,OAAuB;AACtC,KAAI,iBAAiB,MACnB,QAAO;AAET,QAAO,IAAI,MAAM,OAAO,MAAM;AAC/B;AAWD,IAAI,YAAY;AAkBhB,SAAS,UAAUC,UAA0D;AAC3E,eAAe,SAAqB,YAAY;AACjD;;;;;;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,gBAAgBC,QAAyB;AACvD,QAAO,EACL,QAAQD,UAAqC;AAE3C,MAAI,WAAW;GACb,MAAME,WAAS,aAAa,OAAO,eAAe,OAAO,OAAO;AAChE,YAAO,KAAK,wEAAwE;AACpF;EACD;AACD,cAAY;EAEZ,MAAM,SAAS,aAAa,OAAO,eAAe,OAAO,OAAO;EAGhE,MAAM,YAAY,WAAqC;EACvD,MAAM,YAAY,IAAI,MAAM;EAC5B,MAAM,QAAQ,WAAiC;EAG/C,IAAIC,wBAAgD;EAGpD,eAAe,eAA8B;AAE3C,OAAI,UAAU,OAAO;AACnB,WAAO,IAAI,0DAA0D;AACrE;GACD;AAED,UAAO,IAAI,qCAAqC;AAChD,aAAU,QAAQ;AAClB,SAAM;AAGN,0BAAuB,OAAO;GAC9B,MAAM,kBAAkB,IAAI;AAC5B,2BAAwB;AAExB,OAAI;IACF,MAAM,eAAe,MAAM,OAAO,UAAU;AAC5C,WAAO,IAAI,sCAAsC;AAGjD,QAAI,gBAAgB,OAAO,QACzB;IAIF,MAAM,SAAS,MAAM,qBAAqB;KACxC;KACA,eAAe,OAAO;KACtB,QAAQ,OAAO;KACf,WAAW;KACX,QAAQ,gBAAgB;IACzB,EAAC;AAGF,QAAI,gBAAgB,OAAO,QACzB;AAGF,cAAU,QAAQ;KAChB,OAAO,OAAO;KACd,WAAW,UAAU;KACrB,SAAS,OAAO;KAChB,UAAU,cAAc;KACxB,eAAe,mBAAmB;IACnC;AACD,WAAO,IAAI,sCAAsC;GAClD,SAAQ,GAAG;AAEV,QAAI,aAAa,SAAS,EAAE,SAAS,aACnC;IAGF,MAAM,MAAM,QAAQ,EAAE;AACtB,WAAO,OAAO,oCAAoC,IAAI,QAAQ,EAAE;AAChE,UAAM,QAAQ;GACf,UAAS;AACR,QAAI,0BAA0B,gBAC5B,yBAAwB;AAE1B,cAAU,QAAQ;GACnB;EACF;EAID,SAAS,kBAAwB;AAC/B,UAAO,IAAI,iCAAiC;AAC5C,aAAU;AACV,SAAM;AACN,iBAAc;EACf;EAGD,MAAMC,QAAwB;GAC5B,WAAW,SAAS,UAAU;GAC9B,WAAW,SAAS,UAAU;GAC9B,OAAO,SAAS,MAAM;GACtB;GACA;EACD;AAGD,gBAAc;AAGd,MAAI,UAAU,SAAS,CAGrB,UAAS,QAAQ,yBAAyB,MAAM;MAKhD,UAAS,MAAM,EACb,UAAU;AACR,UAAO,GACJ,0BAA0B,MAC5B;EACF,EACF,EAAC;AAIJ,gBAAc;CACf,EACF;AACF;;;;;;;;;ACvOD,SAAgB,mBAA2C;CAWzD,MAAM,QAAQ,OAAuB,wBAAwB,IAAI,gBAAgB;AAEjF,MAAK,MACH,OAAM,IAAI,MACR;CAKJ,MAAM,YAAY,SAAoB,MAAM;AAC1C,MAAI,MAAM,UAAU,MAAO,QAAO;AAClC,MAAI,MAAM,MAAM,MAAO,QAAO;AAC9B,MAAI,MAAM,UAAU,MAAO,QAAO;AAClC,SAAO;CACR,EAAC;AAEF,QAAO;EACL,GAAG;EACH;CACD;AACF;;;;cChDY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACoDb,MAAa,WAAW,gBAAgB;CACtC,MAAM;CACN,OAAO;EAKL,OAAO;EAKP,gBAAgB;GACd,MAAM;GACN,SAAS;EACV;EAKD,eAAe;CAChB;CACD,OAAO;EAIL,QAAQ,MAAM;EAId,OAAO,CAACC,UAA0B,iBAAiBC;CACpD;CACD,MAAM,OAAO,EAAE,MAAM,EAAE;EACrB,MAAM,eAAe,IAAwB,KAAK;EAClD,MAAM,EAAE,WAAW,QAAQ,iBAAiB,GAAG,kBAAkB;EAEjE,IAAIC,gBAAsC;EAE1C,SAAS,iBAAiBC,OAAkBC,WAA8B;AAGxE,kBAAe,SAAS;GAExB,MAAM,wBAAwB,MAAM,iBAAiB,OAAO,iBAAiB;GAC7E,MAAM,gBAAgB,MAAM,SAAS,OAAO;AAE5C,mBAAgB,IAAI,cAAc;IAChC;IACA,WAAW;IACX,kBAAkB,EAAE,YAAY,WAAY;IAC5C,OAAO;IACP,eAAe;IACf,QAAQ,OAAO;IACf,YAAYC;IACZ,gBAAgB,MAAM;IACtB,WAAW;KACT,QAAQ,MAAM;AACZ,WAAK,SAAS;KACf;KACD,SAAS,CAACC,aAA8B;MACtC,MAAM,iBAAiB,IAAIL,iBAAe;AAC1C,WAAK,SAAS,eAAe;KAC9B;KACD,gBAAgB,MAAM;AACpB,uBAAiB;KAClB;IACF;GACF;EACF;AAYD,QACE,CAAC,WAAW,YAAa,GACzB,CAAC,CAAC,cAAc,UAAU,KAAK;AAC7B,OAAI,gBAAgB,UAClB,kBAAiB,cAAc,UAAU;EAE5C,GACD,EAAE,WAAW,KAAM,EACpB;AAED,cAAY,MAAM;AAChB,kBAAe,SAAS;AACxB,mBAAgB;EACjB,EAAC;AAiBF,SAAO,MACL,EAAE,OAAO;GAGP,KAAM,CAACM,OAAuB;AAC5B,iBAAa,QAAQ;GACtB;GACD,OAAO;GACP,OAAO,EAAE,OAAO,OAAQ;EACzB,EAAC;CACL;AACF,EAAC"}
1
+ {"version":3,"file":"index.mjs","names":["globalState: CapitalOsState | null","error: unknown","appOrVue: Vue2Constructor | Vue3App","config: CapitalOsConfig","logger","activeAbortController: AbortController | null","state: CapitalOsState","error: CapitalOSError","CapitalOSError","options: UseIframeComponentOptions","iframeManager: IframeManager | null","token: TokenData","container: HTMLElement","SDK_VERSION","rawError: RawErrorDetails","CapitalOSError","el: Element | null","_account: Account","account: Account"],"sources":["../src/plugin.ts","../src/components/common-props.ts","../src/composables/use-capitalos-auth.ts","../package.json","../src/composables/use-iframe-component.ts","../src/components/CardsApp.ts","../src/components/BillPayApp.ts","../src/components/Onboarding.ts"],"sourcesContent":["// =============================================================================\n// MAINTAINER NOTE: Vue 2.7 vs Vue 3 Plugin Compatibility\n// =============================================================================\n//\n// Vue 2.7 and Vue 3 call plugin.install() with DIFFERENT arguments:\n//\n// Vue 3 consumer code:\n// const app = createApp(App)\n// app.use(myPlugin) // → calls myPlugin.install(app) with app INSTANCE\n//\n// Vue 2.7 consumer code:\n// Vue.use(myPlugin) // → calls myPlugin.install(Vue) with Vue CONSTRUCTOR\n//\n// This matters because:\n// - Vue 3's app instance has app.provide() for dependency injection\n// - Vue 2.7's Vue constructor does NOT have provide() - must use Vue.mixin()\n//\n// This plugin detects which API is available and uses the appropriate method.\n// As an additional fallback for edge cases, we also store state in a module-level\n// variable that `useCapitalOsAuth` can access if `inject()` returns undefined.\n//\n// FUTURE: If we ever need to support Vue < 2.7 or have more complex version-\n// specific logic throughout the codebase, consider using `vue-demi` package\n// (https://github.com/vueuse/vue-demi) which abstracts all Vue 2/3 differences.\n// For now, our simple detection is sufficient since Vue 2.7 has Composition API\n// backported and we only need to handle the plugin install signature difference.\n// =============================================================================\n\nimport { ref, readonly } from 'vue'\nimport {\n exchangeOneTimeToken,\n createLogger,\n TokenType,\n TokenParamKey,\n TokenParamLocation,\n type TokenData,\n} from '@capitalos/core'\nimport type { CapitalOsConfig, CapitalOsState } from './types'\n\n/**\n * Injection key for CapitalOS state.\n * Used with Vue's provide/inject system.\n */\nexport const CAPITALOS_INJECTION_KEY = Symbol('capitalos')\n\n// MAINTAINER NOTE: Module-level state storage for Vue 2.7 compatibility fallback.\n//\n// In Vue 2.7, even with the mixin approach, there can be edge cases where\n// `inject()` doesn't find the provided value (e.g., in the root component\n// or components created before the mixin is applied). This global fallback\n// ensures `useCapitalOsAuth()` always has access to the state.\nlet globalState: CapitalOsState | null = null\n\n// @internal - used by useCapitalOsAuth for Vue 2.7 fallback\nexport function getGlobalState(): CapitalOsState | null {\n return globalState\n}\n\nconst TOKEN_EXCHANGE_TIMEOUT_MS = 10_000\n\n// Converts an unknown error to an Error object\nfunction toError(error: unknown): Error {\n if (error instanceof Error) {\n return error\n }\n return new Error(String(error))\n}\n\n// MAINTAINER NOTE: Module-level guard against double installation (singleton pattern).\n//\n// This MUST be module-level (not inside createCapitalOs) because:\n// - The plugin creates reactive state that should only exist once\n// - Multiple installations would create multiple token exchange iframes\n// - Multiple auth states would cause inconsistent behavior\n//\n// If a consumer accidentally calls Vue.use(createCapitalOs(...)) twice,\n// the second call will be silently ignored with a warning.\nlet installed = false\n\n// Type for Vue 2 constructor passed to plugin install.\n// In Vue 2.7, `Vue.use(plugin)` passes the Vue constructor.\ninterface Vue2Constructor {\n mixin: (mixin: Record<string, unknown>) => void\n version: string\n}\n\n// Type for Vue 3 app instance passed to plugin install.\n// In Vue 3, `app.use(plugin)` passes the app instance.\ninterface Vue3App {\n provide: (key: symbol, value: unknown) => void\n version: string\n}\n\n// Detect Vue version by checking for Vue 3's `provide` method.\n// Vue 3 app instances have `app.provide()`, Vue 2 constructors don't.\nfunction isVue3App(appOrVue: Vue2Constructor | Vue3App): appOrVue is Vue3App {\n return typeof (appOrVue as Vue3App).provide === 'function'\n}\n\n/**\n * Creates the CapitalOS Vue plugin.\n *\n * Usage (Vue 3):\n * ```typescript\n * import { createApp } from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * const app = createApp(App)\n * app.use(createCapitalOs({ getToken: async () => { ... } }))\n * app.mount('#app')\n * ```\n *\n * Usage (Vue 2.7):\n * ```typescript\n * import Vue from 'vue'\n * import { createCapitalOs } from '@capitalos/vue'\n *\n * Vue.use(createCapitalOs({ getToken: async () => { ... } }))\n * new Vue({ render: h => h(App) }).$mount('#app')\n * ```\n */\nexport function createCapitalOs(config: CapitalOsConfig) {\n return {\n install(appOrVue: Vue2Constructor | Vue3App) {\n // Prevent double installation\n if (installed) {\n const logger = createLogger(config.enableLogging, config.logger)\n logger.warn('[CapitalOS] Plugin already installed, skipping duplicate installation')\n return\n }\n installed = true\n\n const logger = createLogger(config.enableLogging, config.logger)\n\n // Create reactive state\n const tokenData = ref<TokenData | undefined>(undefined)\n const isLoading = ref(false)\n const error = ref<Error | undefined>(undefined)\n\n // AbortController for cancelling in-flight token exchanges\n let activeAbortController: AbortController | null = null\n\n // Refreshes the token by fetching a new one-time token and exchanging it.\n async function refreshToken(): Promise<void> {\n // Prevent concurrent refresh calls - if already loading, skip\n if (isLoading.value) {\n logger.log('[CapitalOS] Token refresh already in progress, skipping')\n return\n }\n\n logger.log('[CapitalOS] Starting token refresh')\n isLoading.value = true\n error.value = undefined\n\n // Abort any in-flight exchange when a new one begins\n activeAbortController?.abort()\n const abortController = new AbortController()\n activeAbortController = abortController\n\n try {\n const oneTimeToken = await config.getToken()\n logger.log('[CapitalOS] Received one-time token')\n\n // Check if aborted after getToken\n if (abortController.signal.aborted) {\n return\n }\n\n // Exchange for long-lived token using @capitalos/core\n const result = await exchangeOneTimeToken({\n oneTimeToken,\n enableLogging: config.enableLogging,\n logger: config.logger,\n timeoutMs: TOKEN_EXCHANGE_TIMEOUT_MS,\n signal: abortController.signal,\n })\n\n // Check if aborted after exchange\n if (abortController.signal.aborted) {\n return\n }\n\n tokenData.value = {\n token: result.longLivedToken,\n tokenType: TokenType.longLived,\n baseUrl: result.baseUrl,\n paramKey: TokenParamKey.accessToken,\n paramLocation: TokenParamLocation.hash,\n }\n logger.log('[CapitalOS] Token exchange complete')\n } catch (e) {\n // Ignore abort errors\n if (e instanceof Error && e.name === 'AbortError') {\n return\n }\n\n const err = toError(e)\n logger.error(`[CapitalOS] Token refresh failed: ${err.message}`)\n error.value = err\n } finally {\n if (activeAbortController === abortController) {\n activeAbortController = null\n }\n isLoading.value = false\n }\n }\n\n // Invalidates the current token, triggering a refresh.\n // Called when the iframe signals that the token has expired.\n function invalidateToken(): void {\n logger.log('[CapitalOS] Invalidating token')\n tokenData.value = undefined\n error.value = undefined\n refreshToken()\n }\n\n // Create state object to provide\n const state: CapitalOsState = {\n tokenData: readonly(tokenData),\n isLoading: readonly(isLoading),\n error: readonly(error),\n invalidateToken,\n config,\n }\n\n // Store globally as fallback for Vue 2.7 edge cases where inject() fails\n globalState = state\n\n // Provide state using the appropriate API based on Vue version\n if (isVue3App(appOrVue)) {\n // Vue 3: use app.provide() - this makes state available to all components\n // via inject(CAPITALOS_INJECTION_KEY)\n appOrVue.provide(CAPITALOS_INJECTION_KEY, state)\n } else {\n // Vue 2.7: use Vue.mixin() to add a provide function to all components.\n // This is the Vue 2 equivalent of app.provide() - it injects the provide\n // option into every component so inject() can find our state.\n appOrVue.mixin({\n provide() {\n return {\n [CAPITALOS_INJECTION_KEY]: state,\n }\n },\n })\n }\n\n // Start token exchange eagerly (matches Angular behavior)\n refreshToken()\n },\n }\n}\n","import type { PropType } from 'vue'\nimport type { ThemeColorScheme } from '@capitalos/core'\nimport { CapitalOSError } from '@capitalos/core'\n\n/**\n * Common props shared by all CapitalOS Vue components.\n */\nexport const commonProps = {\n /**\n * Theme color scheme for the interface.\n * Overrides the theme set in plugin configuration.\n */\n theme: String as PropType<ThemeColorScheme>,\n /**\n * Offset in pixels to add to the iframe height calculation.\n * Useful for avoiding scrollbars when the content height changes dynamically.\n */\n heightOffsetPx: {\n type: Number,\n default: 12,\n },\n /**\n * Whether to enable logging for debugging purposes.\n * Overrides the enableLogging set in plugin configuration.\n */\n enableLogging: Boolean,\n}\n\n/**\n * Common emits shared by all CapitalOS Vue components.\n */\nexport const commonEmits = {\n /**\n * Emitted when the interface has finished loading.\n */\n loaded: () => true,\n /**\n * Emitted when an error occurs in the interface.\n */\n error: (error: CapitalOSError) => error instanceof CapitalOSError,\n}\n","import { inject, computed, type ComputedRef } from 'vue'\nimport { CAPITALOS_INJECTION_KEY, getGlobalState } from '../plugin'\nimport type { CapitalOsState, AuthState } from '../types'\n\n/**\n * Return type for useCapitalOsAuth composable\n */\nexport interface UseCapitalOsAuthReturn extends CapitalOsState {\n /**\n * Computed authentication state\n */\n authState: ComputedRef<AuthState>\n}\n\n/**\n * @internal\n * Internal composable for accessing CapitalOS authentication state.\n * Used by SDK components - not intended for direct consumer use.\n */\nexport function useCapitalOsAuth(): UseCapitalOsAuthReturn {\n // MAINTAINER NOTE: Vue 2.7 vs Vue 3 Compatibility\n //\n // Try inject() first - this works in:\n // - Vue 3 (via app.provide)\n // - Vue 2.7 (via mixin provide, in most components)\n //\n // Fall back to getGlobalState() for Vue 2.7 edge cases where inject() fails,\n // such as the root component or components created before the mixin is applied.\n //\n // Do NOT remove the ?? getGlobalState() fallback - it's required for Vue 2.7.\n const state = inject<CapitalOsState>(CAPITALOS_INJECTION_KEY) ?? getGlobalState()\n\n if (!state) {\n throw new Error(\n 'useCapitalOsAuth must be used in a component where createCapitalOs plugin is installed. ' +\n 'Make sure to call app.use(createCapitalOs({ ... })) or Vue.use(createCapitalOs({ ... })) in your main.ts'\n )\n }\n\n const authState = computed<AuthState>(() => {\n if (state.isLoading.value) return 'loading'\n if (state.error.value) return 'error'\n if (state.tokenData.value) return 'authenticated'\n return 'idle'\n })\n\n return {\n ...state,\n authState,\n }\n}\n","{\n \"name\": \"@capitalos/vue\",\n \"version\": \"0.1.0\",\n \"description\": \"Vue SDK for CapitalOS\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"dev\": \"tsdown --watch\",\n \"lint\": \"eslint src --ext .ts --fix\",\n \"lint-ci\": \"eslint src --ext .ts\",\n \"start\": \"pnpm --filter vue-test-app dev\",\n \"start:all\": \"concurrently \\\"pnpm --filter sdk-test-server start\\\" \\\"pnpm start\\\"\",\n \"test:pack\": \"pnpm build && pnpm pack\",\n \"prepublishOnly\": \"pnpm build\"\n },\n \"keywords\": [\n \"capitalos\",\n \"vue\",\n \"sdk\",\n \"iframe\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/CapitalOS/theboss\",\n \"directory\": \"sdk/vue\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/CapitalOS/theboss/issues\"\n },\n \"author\": \"CapitalOS\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"vue\": \"^2.7.0 || ^3.0.0\"\n },\n \"dependencies\": {\n \"@capitalos/core\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"tsdown\": \"^0.9.2\",\n \"typescript\": \"^5.6.2\",\n \"vue\": \"^3.5.13\",\n \"concurrently\": \"^9.1.2\"\n }\n}\n","import { ref, watch, onUnmounted, h, type VNode, type Ref } from 'vue'\nimport {\n IframeManager,\n CapitalOSError,\n type TokenData,\n type RawErrorDetails,\n type RenderingContext,\n type IframeManagerConfig,\n} from '@capitalos/core'\nimport { useCapitalOsAuth } from './use-capitalos-auth'\nimport { version as SDK_VERSION } from '../../package.json'\n\n/**\n * Props expected by useIframeComponent - matches commonProps shape\n */\nexport interface IframeComponentProps {\n theme?: 'light' | 'dark' | 'system'\n heightOffsetPx: number\n enableLogging?: boolean\n}\n\n/**\n * Emit function type for common events\n */\nexport interface CommonEmitFn {\n (event: 'loaded'): void\n (event: 'error', error: CapitalOSError): void\n}\n\n/**\n * Component-specific callbacks to pass to IframeManager.\n * Excludes common callbacks (onLoad, onError, onTokenExpired) which the composable handles.\n */\nexport type ComponentCallbacks = Omit<IframeManagerConfig['callbacks'], 'onLoad' | 'onError' | 'onTokenExpired'>\n\n/**\n * Options for configuring the iframe component\n */\nexport interface UseIframeComponentOptions {\n /** Props from the component */\n props: IframeComponentProps\n /** Emit function from the component */\n emit: CommonEmitFn\n /** Function that returns the rendering context for this component */\n getRenderingContext: () => RenderingContext\n /** Component-specific callbacks (onboarding, tokenExchange, etc.) */\n componentCallbacks?: ComponentCallbacks\n}\n\n/**\n * Return type for useIframeComponent\n */\nexport interface UseIframeComponentReturn {\n /** Ref to the container element */\n containerRef: Ref<HTMLElement | null>\n /** Render function that returns the container div */\n render: () => VNode\n}\n\n/**\n * Composable that handles common iframe component setup.\n *\n * Manages:\n * - Container ref and iframe manager lifecycle\n * - Token data subscription and iframe initialization\n * - Common callbacks (onLoad, onError, onTokenExpired)\n * - Cleanup on unmount\n * - Render function for the container div\n *\n * Note: Rendering context props (e.g., entryPoint, exitPoint for Onboarding) are read once\n * at iframe initialization. Changes to these props after the iframe loads will NOT trigger\n * re-initialization. This matches the behavior of the React SDK.\n *\n * @example\n * ```ts\n * setup(props, { emit }) {\n * const { render } = useIframeComponent({\n * props,\n * emit,\n * getRenderingContext: () => ({ entryPoint: 'cardsApp' }),\n * })\n * return render\n * }\n * ```\n */\nexport function useIframeComponent(options: UseIframeComponentOptions): UseIframeComponentReturn {\n const { props, emit, getRenderingContext, componentCallbacks } = options\n\n const containerRef = ref<HTMLElement | null>(null)\n const { tokenData, config, invalidateToken } = useCapitalOsAuth()\n\n let iframeManager: IframeManager | null = null\n\n function initializeIframe(token: TokenData, container: HTMLElement): void {\n // Destroy previous iframe before creating new one (matches Angular/React behavior)\n // This ensures token refresh works correctly - new token = new iframe\n iframeManager?.destroy()\n\n const resolvedEnableLogging = props.enableLogging ?? config.enableLogging ?? false\n const resolvedTheme = props.theme ?? config.theme\n\n iframeManager = new IframeManager({\n container,\n tokenData: token,\n renderingContext: getRenderingContext(),\n theme: resolvedTheme,\n enableLogging: resolvedEnableLogging,\n logger: config.logger,\n sdkVersion: SDK_VERSION,\n heightOffsetPx: props.heightOffsetPx,\n callbacks: {\n onLoad: () => {\n emit('loaded')\n },\n onError: (rawError: RawErrorDetails) => {\n emit('error', new CapitalOSError(rawError))\n },\n onTokenExpired: () => {\n invalidateToken()\n },\n ...componentCallbacks,\n },\n })\n }\n\n // Watch for tokenData and container changes to initialize the iframe.\n //\n // Why watch both tokenData AND containerRef?\n // - tokenData: comes from async token exchange, may not be ready on mount\n // - containerRef: DOM element, available after first render\n //\n // Why { immediate: true }?\n // - If tokenData is already available when component mounts, we want to\n // initialize immediately without waiting for a change\n // - Without this, the iframe wouldn't load until tokenData changes again\n watch(\n [tokenData, containerRef],\n ([newTokenData, container]) => {\n if (newTokenData && container) {\n initializeIframe(newTokenData, container)\n }\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n iframeManager?.destroy()\n iframeManager = null\n })\n\n // Render function - creates the container div for the iframe.\n //\n // Why use a function ref `ref: (el) => { ... }` instead of `ref: containerRef`?\n //\n // Vue 2.7 and Vue 3 handle template refs differently in render functions:\n // - Vue 3: can use `ref: containerRef` directly\n // - Vue 2.7: requires function ref pattern for reliable element access\n //\n // The function ref pattern works in both versions, so we use it for compatibility.\n // Do NOT change this to `ref: containerRef` - it will break Vue 2.7 support.\n //\n // The `as unknown as string` type assertion is required because:\n // - Vue 3's TypeScript types don't properly express that function refs are valid\n // - The function ref pattern IS valid at runtime in both Vue 2.7 and Vue 3\n // - This is a known limitation of Vue 3's type definitions\n function render(): VNode {\n return h('div', {\n // Type assertion required: Vue 3's types don't support function refs in h(),\n // but function refs ARE valid at runtime in both Vue 2.7 and Vue 3\n ref: ((el: Element | null) => {\n containerRef.value = el as HTMLElement | null\n }) as unknown as string,\n class: 'capitalos-iframe-container',\n style: { width: '100%' },\n })\n }\n\n return {\n containerRef,\n render,\n }\n}\n","import { defineComponent } from 'vue'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * CardsApp component that renders the CapitalOS cards interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!cardsLoaded\">Loading...</div>\n * <CardsApp\n * @loaded=\"cardsLoaded = true\"\n * @error=\"onCardsError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { CardsApp } from '@capitalos/vue'\n *\n * const cardsLoaded = ref(false)\n * const onCardsError = (error) => console.error(error)\n * </script>\n * ```\n */\nexport const CardsApp = defineComponent({\n name: 'CardsApp',\n props: commonProps,\n emits: commonEmits,\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({ entryPoint: 'cardsApp' }),\n })\n\n return render\n },\n})\n","import { defineComponent } from 'vue'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * BillPayApp component that renders the CapitalOS bill payment interface in an iframe.\n *\n * The component emits events for loading state - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!billPayLoaded\">Loading...</div>\n * <BillPayApp\n * @loaded=\"billPayLoaded = true\"\n * @error=\"onBillPayError\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { BillPayApp } from '@capitalos/vue'\n *\n * const billPayLoaded = ref(false)\n * const onBillPayError = (error) => console.error(error)\n * </script>\n * ```\n */\nexport const BillPayApp = defineComponent({\n name: 'BillPayApp',\n props: commonProps,\n emits: commonEmits,\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({ entryPoint: 'billPayApp' }),\n })\n\n return render\n },\n})\n","import { defineComponent, type PropType } from 'vue'\nimport type { Account, OnboardingEntryPoint, OnboardingExitPoint } from '@capitalos/core'\nimport { commonProps, commonEmits } from './common-props'\nimport { useIframeComponent } from '../composables/use-iframe-component'\n\n/**\n * Onboarding component that renders the CapitalOS onboarding flow in an iframe.\n *\n * The component emits events for loading state and completion - consumers should handle their own loading UI:\n *\n * @example\n * ```vue\n * <template>\n * <div v-if=\"!onboardingLoaded\">Loading...</div>\n * <Onboarding\n * entry-point=\"welcome\"\n * exit-point=\"activation\"\n * @loaded=\"onboardingLoaded = true\"\n * @error=\"onOnboardingError\"\n * @done=\"onOnboardingComplete\"\n * />\n * </template>\n *\n * <script setup>\n * import { ref } from 'vue'\n * import { Onboarding } from '@capitalos/vue'\n *\n * const onboardingLoaded = ref(false)\n * const onOnboardingError = (error) => console.error(error)\n * const onOnboardingComplete = (account) => {\n * console.log('Onboarding complete:', account.status)\n * }\n * </script>\n * ```\n */\nexport const Onboarding = defineComponent({\n name: 'Onboarding',\n props: {\n ...commonProps,\n /**\n * The starting point of the onboarding flow.\n * @default 'welcome'\n */\n entryPoint: String as PropType<OnboardingEntryPoint>,\n /**\n * The ending point of the onboarding flow.\n * @default 'activation'\n */\n exitPoint: String as PropType<OnboardingExitPoint>,\n /**\n * Whether to allow the user to exit the onboarding flow by clicking the done button\n * when they finished the onboarding form but are still not approved (e.g. waiting or pending).\n * This should only be false if you want the user to stay on the onboarding flow\n * (e.g. to add bank account) and not exit the flow.\n * @default true\n */\n allowExitOnNonApproved: {\n type: Boolean,\n default: undefined,\n },\n },\n emits: {\n ...commonEmits,\n /**\n * Emitted when the onboarding flow completes successfully.\n */\n done: (_account: Account) => true,\n },\n setup(props, { emit }) {\n const { render } = useIframeComponent({\n props,\n emit,\n getRenderingContext: () => ({\n entryPoint: 'onboarding',\n onboardingEntryPoint: props.entryPoint,\n onboardingExitPoint: props.exitPoint,\n allowExitOnNonApproved: props.allowExitOnNonApproved,\n }),\n componentCallbacks: {\n onboarding: {\n onDone: (account: Account) => {\n emit('done', account)\n },\n },\n },\n })\n\n return render\n },\n})\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capitalos/vue",
3
- "version": "0.1.0-rc.1",
3
+ "version": "0.1.0",
4
4
  "description": "Vue SDK for CapitalOS",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -20,32 +20,42 @@
20
20
  "files": [
21
21
  "dist"
22
22
  ],
23
+ "scripts": {
24
+ "build": "tsdown",
25
+ "dev": "tsdown --watch",
26
+ "lint": "eslint src --ext .ts --fix",
27
+ "lint-ci": "eslint src --ext .ts",
28
+ "start": "pnpm --filter vue-test-app dev",
29
+ "start:all": "concurrently \"pnpm --filter sdk-test-server start\" \"pnpm start\"",
30
+ "test:pack": "pnpm build && pnpm pack",
31
+ "prepublishOnly": "pnpm build"
32
+ },
23
33
  "keywords": [
24
34
  "capitalos",
25
35
  "vue",
26
36
  "sdk",
27
37
  "iframe"
28
38
  ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/CapitalOS/theboss",
42
+ "directory": "sdk/vue"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/CapitalOS/theboss/issues"
46
+ },
29
47
  "author": "CapitalOS",
30
48
  "license": "MIT",
31
49
  "peerDependencies": {
32
50
  "vue": "^2.7.0 || ^3.0.0"
33
51
  },
34
52
  "dependencies": {
35
- "@capitalos/core": "0.1.0-rc.1"
53
+ "@capitalos/core": "workspace:*"
36
54
  },
37
55
  "devDependencies": {
38
56
  "tsdown": "^0.9.2",
39
57
  "typescript": "^5.6.2",
40
58
  "vue": "^3.5.13",
41
59
  "concurrently": "^9.1.2"
42
- },
43
- "scripts": {
44
- "build": "tsdown",
45
- "dev": "tsdown --watch",
46
- "lint": "eslint src --ext .ts --fix",
47
- "lint-ci": "eslint src --ext .ts",
48
- "start": "pnpm --filter vue-test-app dev",
49
- "start:all": "concurrently \"pnpm --filter sdk-test-server start\" \"pnpm start\""
50
60
  }
51
- }
61
+ }