@forgeroute/ui 0.4.40 → 0.4.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,9 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, Injectable, InjectionToken, PLATFORM_ID, ViewEncapsulation, computed, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, Injectable, InjectionToken, PLATFORM_ID, ViewEncapsulation, computed, effect, inject, input, model, output, signal, untracked, viewChild } from "@angular/core";
3
3
  import { DOCUMENT, isPlatformBrowser } from "@angular/common";
4
- import { AlertComponent, BadgeComponent, ButtonComponent, FORGEROUTE_CONFIG, FormRowComponent, FormSectionComponent, ModalComponent, OptionCardComponent, SkeletonComponent, TextComponent, TextInputComponent } from "@forgeroute/ui";
4
+ import { AlertComponent, BadgeComponent, ButtonComponent, DetailCardComponent, FormRowComponent, FormSectionComponent, ModalComponent, SkeletonComponent, StackComponent, TextComponent, TextInputComponent } from "@forgeroute/ui";
5
5
  import * as i1 from "@angular/forms";
6
6
  import { FormsModule } from "@angular/forms";
7
- import { HttpClient, HttpErrorResponse, HttpParams } from "@angular/common/http";
8
7
  import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
9
8
  const sdkImporter = { load: () => import("@stripe/stripe-js") };
10
9
  const defaultStripeLoader = async (publishableKey, options) => {
@@ -1407,7 +1406,8 @@ var StripePaymentComponent = class StripePaymentComponent {
1407
1406
  "dismissAriaLabel",
1408
1407
  "quiet",
1409
1408
  "compact",
1410
- "inline"
1409
+ "inline",
1410
+ "fill"
1411
1411
  ],
1412
1412
  outputs: ["dismissed"]
1413
1413
  },
@@ -2393,7 +2393,8 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2393
2393
  "dismissAriaLabel",
2394
2394
  "quiet",
2395
2395
  "compact",
2396
- "inline"
2396
+ "inline",
2397
+ "fill"
2397
2398
  ],
2398
2399
  outputs: ["dismissed"]
2399
2400
  },
@@ -2824,90 +2825,239 @@ i0.ɵɵngDeclareClassMetadata({
2824
2825
  }]
2825
2826
  }
2826
2827
  });
2827
- var StripeConnectComponent = class StripeConnectComponent {
2828
- constructor() {
2829
- this.http = inject(HttpClient);
2830
- this.destroyRef = inject(DestroyRef);
2831
- this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
2832
- this.statusEndpoint = input("/integrations/stripe/status", ...ngDevMode ? [{ debugName: "statusEndpoint" }] : /* istanbul ignore next */ []);
2833
- this.connectEndpoint = input("/integrations/stripe/connect", ...ngDevMode ? [{ debugName: "connectEndpoint" }] : /* istanbul ignore next */ []);
2834
- this.connectParams = input(null, ...ngDevMode ? [{ debugName: "connectParams" }] : /* istanbul ignore next */ []);
2835
- this.title = input("Stripe", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
2836
- this.description = input("Collect your customers' payments online. You finish setting up your account on Stripe, then come back here. Payouts go straight to your Stripe account.", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
2837
- this.connectedText = input("Connected. Payments go straight to your Stripe account.", ...ngDevMode ? [{ debugName: "connectedText" }] : /* istanbul ignore next */ []);
2838
- this.connectLabel = input("Connect", ...ngDevMode ? [{ debugName: "connectLabel" }] : /* istanbul ignore next */ []);
2839
- this.reconnectLabel = input("Reconnect", ...ngDevMode ? [{ debugName: "reconnectLabel" }] : /* istanbul ignore next */ []);
2840
- this.loadFailedText = input("The Stripe connection could not be loaded. Please try again.", ...ngDevMode ? [{ debugName: "loadFailedText" }] : /* istanbul ignore next */ []);
2841
- this.connectFailedText = input("Stripe could not be reached. Please try again.", ...ngDevMode ? [{ debugName: "connectFailedText" }] : /* istanbul ignore next */ []);
2842
- this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
2843
- this.statusChange = output();
2844
- this.connected = signal(false, ...ngDevMode ? [{ debugName: "connected" }] : /* istanbul ignore next */ []);
2845
- this.statusKnown = signal(false, ...ngDevMode ? [{ debugName: "statusKnown" }] : /* istanbul ignore next */ []);
2846
- this.connecting = signal(false, ...ngDevMode ? [{ debugName: "connecting" }] : /* istanbul ignore next */ []);
2847
- this.error = signal("", ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
2848
- this.busy = computed(() => !this.statusKnown() && !this.error() || this.connecting(), ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
2849
- this.started = false;
2850
- effect(() => {
2851
- this.statusEndpoint();
2852
- untracked(() => {
2853
- if (!this.started) {
2854
- this.started = true;
2855
- this.refresh();
2856
- }
2857
- });
2828
+ function isStripeUrl(url) {
2829
+ if (!url) return false;
2830
+ try {
2831
+ const u = new URL(url);
2832
+ return u.protocol === "https:" && (u.hostname === "stripe.com" || u.hostname.endsWith(".stripe.com"));
2833
+ } catch {
2834
+ return false;
2835
+ }
2836
+ }
2837
+ var StripeConnectFlow = class {
2838
+ constructor(o) {
2839
+ this.o = o;
2840
+ this.tabOpened = false;
2841
+ }
2842
+ get blocked() {
2843
+ return this.o.state.loading() || !!this.o.disabled?.();
2844
+ }
2845
+ start() {
2846
+ const create = this.o.createAccount();
2847
+ if (!create || this.blocked) return;
2848
+ this.o.state.loading.set(true);
2849
+ const tab = this.openBlankTab();
2850
+ create().pipe(takeUntilDestroyed(this.o.destroyRef)).subscribe({
2851
+ next: (result) => {
2852
+ this.o.state.accountId.set(result.accountId);
2853
+ this.o.state.loading.set(false);
2854
+ this.openStripe(tab, result.onboardingUrl);
2855
+ },
2856
+ error: (error) => {
2857
+ this.closeTab(tab);
2858
+ this.o.state.loading.set(false);
2859
+ this.o.emit({
2860
+ kind: "failed",
2861
+ action: "start",
2862
+ error
2863
+ });
2864
+ }
2858
2865
  });
2859
2866
  }
2860
- refresh() {
2861
- this.error.set("");
2862
- this.http.get(this.apiBase + this.statusEndpoint()).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
2863
- next: (body) => {
2864
- const connected = body?.connected === true;
2865
- this.connected.set(connected);
2866
- this.statusKnown.set(true);
2867
- this.statusChange.emit(connected);
2867
+ check() {
2868
+ const status = this.o.getStatus();
2869
+ if (!status || this.blocked) return;
2870
+ this.o.state.loading.set(true);
2871
+ status().pipe(takeUntilDestroyed(this.o.destroyRef)).subscribe({
2872
+ next: (s) => {
2873
+ this.o.state.complete.set(s.isComplete);
2874
+ this.o.state.detailsSubmitted.set(s.detailsSubmitted ?? false);
2875
+ this.o.state.loading.set(false);
2876
+ if (s.isComplete) this.o.emit({
2877
+ kind: "complete",
2878
+ source: "check"
2879
+ });
2880
+ else if (s.detailsSubmitted) this.o.emit({
2881
+ kind: "verifying",
2882
+ source: "check"
2883
+ });
2884
+ else if (s.onboardingUrl) this.o.emit({ kind: "incomplete" });
2868
2885
  },
2869
- error: (e) => {
2870
- this.statusKnown.set(false);
2871
- this.error.set(this.messageOf(e, this.loadFailedText()));
2886
+ error: (error) => {
2887
+ this.o.state.loading.set(false);
2888
+ this.o.emit({
2889
+ kind: "failed",
2890
+ action: "check",
2891
+ error
2892
+ });
2872
2893
  }
2873
2894
  });
2874
2895
  }
2875
- connect() {
2876
- if (this.connecting() || this.disabled()) return;
2877
- this.error.set("");
2878
- this.connecting.set(true);
2879
- let params = new HttpParams();
2880
- for (const [k, v] of Object.entries(this.connectParams() ?? {})) params = params.set(k, v);
2881
- this.http.get(this.apiBase + this.connectEndpoint(), { params }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
2882
- next: (res) => {
2883
- const url = res?.url ?? res?.authUrl ?? res?.onboardingUrl;
2884
- if (!url || !this.isWebAddress(url)) {
2885
- this.connecting.set(false);
2886
- this.error.set(this.connectFailedText());
2887
- return;
2888
- }
2889
- this.redirect(url);
2896
+ resume() {
2897
+ const status = this.o.getStatus();
2898
+ if (!status || this.blocked) return;
2899
+ this.o.state.loading.set(true);
2900
+ const tab = this.openBlankTab();
2901
+ status().pipe(takeUntilDestroyed(this.o.destroyRef)).subscribe({
2902
+ next: (s) => {
2903
+ this.o.state.loading.set(false);
2904
+ if (s.isComplete) {
2905
+ this.closeTab(tab);
2906
+ this.o.state.complete.set(true);
2907
+ this.o.emit({
2908
+ kind: "complete",
2909
+ source: "resume"
2910
+ });
2911
+ } else if (s.detailsSubmitted) {
2912
+ this.closeTab(tab);
2913
+ this.o.state.detailsSubmitted.set(true);
2914
+ this.o.emit({
2915
+ kind: "verifying",
2916
+ source: "resume"
2917
+ });
2918
+ } else this.openStripe(tab, s.onboardingUrl);
2890
2919
  },
2891
- error: (e) => {
2892
- this.connecting.set(false);
2893
- this.error.set(this.messageOf(e, this.connectFailedText()));
2920
+ error: (error) => {
2921
+ this.closeTab(tab);
2922
+ this.o.state.loading.set(false);
2923
+ this.o.emit({
2924
+ kind: "failed",
2925
+ action: "resume",
2926
+ error
2927
+ });
2894
2928
  }
2895
2929
  });
2896
2930
  }
2897
- redirect(url) {
2898
- window.location.href = url;
2931
+ readStatusOnReturn() {
2932
+ const status = this.o.getStatus();
2933
+ if (!status) return;
2934
+ status().pipe(takeUntilDestroyed(this.o.destroyRef)).subscribe({
2935
+ next: (s) => {
2936
+ this.o.state.complete.set(s.isComplete);
2937
+ this.o.state.detailsSubmitted.set(s.detailsSubmitted ?? false);
2938
+ if (s.isComplete) this.o.emit({
2939
+ kind: "complete",
2940
+ source: "return"
2941
+ });
2942
+ else if (s.detailsSubmitted) this.o.emit({
2943
+ kind: "verifying",
2944
+ source: "return"
2945
+ });
2946
+ },
2947
+ error: () => {}
2948
+ });
2949
+ }
2950
+ openStripe(tab, url) {
2951
+ if (isStripeUrl(url) && tab) {
2952
+ tab.location.href = url;
2953
+ this.tabOpened = true;
2954
+ } else if (isStripeUrl(url)) this.navigateCurrentTab(url);
2955
+ else {
2956
+ this.closeTab(tab);
2957
+ this.o.emit({ kind: "link-unavailable" });
2958
+ }
2959
+ }
2960
+ openBlankTab() {
2961
+ const tab = window.open("about:blank", "_blank");
2962
+ if (tab) try {
2963
+ tab.opener = null;
2964
+ } catch {}
2965
+ return tab;
2899
2966
  }
2900
- isWebAddress(url) {
2967
+ navigateCurrentTab(url) {
2968
+ if (this.o.navigate) this.o.navigate(url);
2969
+ else window.location.href = url;
2970
+ }
2971
+ closeTab(tab) {
2901
2972
  try {
2902
- const p = new URL(url, window.location.origin).protocol;
2903
- return p === "https:" || p === "http:";
2904
- } catch {
2905
- return false;
2973
+ tab?.close();
2974
+ } catch {}
2975
+ }
2976
+ };
2977
+ function stripeConnectNotice(outcome) {
2978
+ switch (outcome.kind) {
2979
+ case "complete": return {
2980
+ variant: "success",
2981
+ message: outcome.source === "resume" ? "Payment account setup is already complete!" : "Payment account setup complete!"
2982
+ };
2983
+ case "verifying": return {
2984
+ variant: "success",
2985
+ message: "Setup submitted! Stripe is verifying your account. This usually takes a few minutes. Click \"Check Status\" to refresh."
2986
+ };
2987
+ case "incomplete": return {
2988
+ variant: "error",
2989
+ message: "Payment account setup is not yet complete. Please continue setup."
2990
+ };
2991
+ case "link-unavailable": return {
2992
+ variant: "error",
2993
+ message: "Unable to retrieve onboarding link. Please try again."
2994
+ };
2995
+ case "failed": return {
2996
+ variant: "error",
2997
+ message: outcome.action === "start" ? "Failed to start payment account setup" : outcome.action === "check" ? "Failed to check payment account status" : "Failed to retrieve onboarding link"
2998
+ };
2999
+ }
3000
+ }
3001
+ var StripeConnectComponent = class StripeConnectComponent {
3002
+ constructor() {
3003
+ this.destroyRef = inject(DestroyRef);
3004
+ this.createAccount = input(null, ...ngDevMode ? [{ debugName: "createAccount" }] : /* istanbul ignore next */ []);
3005
+ this.getStatus = input(null, ...ngDevMode ? [{ debugName: "getStatus" }] : /* istanbul ignore next */ []);
3006
+ this.accountId = model(null, ...ngDevMode ? [{ debugName: "accountId" }] : /* istanbul ignore next */ []);
3007
+ this.complete = model(false, ...ngDevMode ? [{ debugName: "complete" }] : /* istanbul ignore next */ []);
3008
+ this.detailsSubmitted = model(false, ...ngDevMode ? [{ debugName: "detailsSubmitted" }] : /* istanbul ignore next */ []);
3009
+ this.title = input("Stripe Connect Account", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
3010
+ this.showWhenNoAccount = input(false, ...ngDevMode ? [{ debugName: "showWhenNoAccount" }] : /* istanbul ignore next */ []);
3011
+ this.startTitle = input("Connect your Stripe account", ...ngDevMode ? [{ debugName: "startTitle" }] : /* istanbul ignore next */ []);
3012
+ this.startText = input("Collect your customers' payments online. You finish setting up your account on Stripe, then come back here.", ...ngDevMode ? [{ debugName: "startText" }] : /* istanbul ignore next */ []);
3013
+ this.startLabel = input("Set Up Payment Account", ...ngDevMode ? [{ debugName: "startLabel" }] : /* istanbul ignore next */ []);
3014
+ this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
3015
+ this.refreshOnReturn = input(false, ...ngDevMode ? [{ debugName: "refreshOnReturn" }] : /* istanbul ignore next */ []);
3016
+ this.dashboardUrl = input("https://dashboard.stripe.com", ...ngDevMode ? [{ debugName: "dashboardUrl" }] : /* istanbul ignore next */ []);
3017
+ this.outcome = output();
3018
+ this.loading = model(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
3019
+ this.navigateTab = input(null, ...ngDevMode ? [{ debugName: "navigateTab" }] : /* istanbul ignore next */ []);
3020
+ this.visible = computed(() => !!this.accountId() || this.showWhenNoAccount(), ...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
3021
+ this.flow = new StripeConnectFlow({
3022
+ createAccount: () => this.createAccount(),
3023
+ getStatus: () => this.getStatus(),
3024
+ state: {
3025
+ accountId: this.accountId,
3026
+ complete: this.complete,
3027
+ detailsSubmitted: this.detailsSubmitted,
3028
+ loading: this.loading
3029
+ },
3030
+ emit: (outcome) => this.outcome.emit(outcome),
3031
+ disabled: () => this.disabled(),
3032
+ navigate: (url) => this.navigateCurrentTab(url),
3033
+ destroyRef: this.destroyRef
3034
+ });
3035
+ if (typeof document !== "undefined") {
3036
+ const onVisible = () => {
3037
+ if (document.visibilityState !== "visible" || !this.flow.tabOpened || !this.refreshOnReturn() || this.loading()) return;
3038
+ this.flow.tabOpened = false;
3039
+ this.flow.readStatusOnReturn();
3040
+ };
3041
+ document.addEventListener("visibilitychange", onVisible);
3042
+ this.destroyRef.onDestroy(() => document.removeEventListener("visibilitychange", onVisible));
2906
3043
  }
2907
3044
  }
2908
- messageOf(e, fallback) {
2909
- const text = (e instanceof HttpErrorResponse ? e.error : null)?.message;
2910
- return typeof text === "string" && text ? text : fallback;
3045
+ start() {
3046
+ this.flow.start();
3047
+ }
3048
+ check() {
3049
+ this.flow.check();
3050
+ }
3051
+ resume() {
3052
+ this.flow.resume();
3053
+ }
3054
+ openDashboard() {
3055
+ window.open(this.dashboardUrl(), "_blank", "noopener,noreferrer");
3056
+ }
3057
+ navigateCurrentTab(url) {
3058
+ const navigate = this.navigateTab();
3059
+ if (navigate) navigate(url);
3060
+ else window.location.href = url;
2911
3061
  }
2912
3062
  static {
2913
3063
  this.ɵfac = i0.ɵɵngDeclareFactory({
@@ -2927,72 +3077,72 @@ var StripeConnectComponent = class StripeConnectComponent {
2927
3077
  isStandalone: true,
2928
3078
  selector: "ui-stripe-connect",
2929
3079
  inputs: {
2930
- statusEndpoint: {
2931
- classPropertyName: "statusEndpoint",
2932
- publicName: "statusEndpoint",
3080
+ createAccount: {
3081
+ classPropertyName: "createAccount",
3082
+ publicName: "createAccount",
2933
3083
  isSignal: true,
2934
3084
  isRequired: false,
2935
3085
  transformFunction: null
2936
3086
  },
2937
- connectEndpoint: {
2938
- classPropertyName: "connectEndpoint",
2939
- publicName: "connectEndpoint",
3087
+ getStatus: {
3088
+ classPropertyName: "getStatus",
3089
+ publicName: "getStatus",
2940
3090
  isSignal: true,
2941
3091
  isRequired: false,
2942
3092
  transformFunction: null
2943
3093
  },
2944
- connectParams: {
2945
- classPropertyName: "connectParams",
2946
- publicName: "connectParams",
3094
+ accountId: {
3095
+ classPropertyName: "accountId",
3096
+ publicName: "accountId",
2947
3097
  isSignal: true,
2948
3098
  isRequired: false,
2949
3099
  transformFunction: null
2950
3100
  },
2951
- title: {
2952
- classPropertyName: "title",
2953
- publicName: "title",
3101
+ complete: {
3102
+ classPropertyName: "complete",
3103
+ publicName: "complete",
2954
3104
  isSignal: true,
2955
3105
  isRequired: false,
2956
3106
  transformFunction: null
2957
3107
  },
2958
- description: {
2959
- classPropertyName: "description",
2960
- publicName: "description",
3108
+ detailsSubmitted: {
3109
+ classPropertyName: "detailsSubmitted",
3110
+ publicName: "detailsSubmitted",
2961
3111
  isSignal: true,
2962
3112
  isRequired: false,
2963
3113
  transformFunction: null
2964
3114
  },
2965
- connectedText: {
2966
- classPropertyName: "connectedText",
2967
- publicName: "connectedText",
3115
+ title: {
3116
+ classPropertyName: "title",
3117
+ publicName: "title",
2968
3118
  isSignal: true,
2969
3119
  isRequired: false,
2970
3120
  transformFunction: null
2971
3121
  },
2972
- connectLabel: {
2973
- classPropertyName: "connectLabel",
2974
- publicName: "connectLabel",
3122
+ showWhenNoAccount: {
3123
+ classPropertyName: "showWhenNoAccount",
3124
+ publicName: "showWhenNoAccount",
2975
3125
  isSignal: true,
2976
3126
  isRequired: false,
2977
3127
  transformFunction: null
2978
3128
  },
2979
- reconnectLabel: {
2980
- classPropertyName: "reconnectLabel",
2981
- publicName: "reconnectLabel",
3129
+ startTitle: {
3130
+ classPropertyName: "startTitle",
3131
+ publicName: "startTitle",
2982
3132
  isSignal: true,
2983
3133
  isRequired: false,
2984
3134
  transformFunction: null
2985
3135
  },
2986
- loadFailedText: {
2987
- classPropertyName: "loadFailedText",
2988
- publicName: "loadFailedText",
3136
+ startText: {
3137
+ classPropertyName: "startText",
3138
+ publicName: "startText",
2989
3139
  isSignal: true,
2990
3140
  isRequired: false,
2991
3141
  transformFunction: null
2992
3142
  },
2993
- connectFailedText: {
2994
- classPropertyName: "connectFailedText",
2995
- publicName: "connectFailedText",
3143
+ startLabel: {
3144
+ classPropertyName: "startLabel",
3145
+ publicName: "startLabel",
2996
3146
  isSignal: true,
2997
3147
  isRequired: false,
2998
3148
  transformFunction: null
@@ -3003,46 +3153,90 @@ var StripeConnectComponent = class StripeConnectComponent {
3003
3153
  isSignal: true,
3004
3154
  isRequired: false,
3005
3155
  transformFunction: null
3156
+ },
3157
+ refreshOnReturn: {
3158
+ classPropertyName: "refreshOnReturn",
3159
+ publicName: "refreshOnReturn",
3160
+ isSignal: true,
3161
+ isRequired: false,
3162
+ transformFunction: null
3163
+ },
3164
+ dashboardUrl: {
3165
+ classPropertyName: "dashboardUrl",
3166
+ publicName: "dashboardUrl",
3167
+ isSignal: true,
3168
+ isRequired: false,
3169
+ transformFunction: null
3170
+ },
3171
+ loading: {
3172
+ classPropertyName: "loading",
3173
+ publicName: "loading",
3174
+ isSignal: true,
3175
+ isRequired: false,
3176
+ transformFunction: null
3177
+ },
3178
+ navigateTab: {
3179
+ classPropertyName: "navigateTab",
3180
+ publicName: "navigateTab",
3181
+ isSignal: true,
3182
+ isRequired: false,
3183
+ transformFunction: null
3006
3184
  }
3007
3185
  },
3008
- outputs: { statusChange: "statusChange" },
3186
+ outputs: {
3187
+ accountId: "accountIdChange",
3188
+ complete: "completeChange",
3189
+ detailsSubmitted: "detailsSubmittedChange",
3190
+ outcome: "outcome",
3191
+ loading: "loadingChange"
3192
+ },
3009
3193
  ngImport: i0,
3010
3194
  template: `
3011
- <div class="sc" data-testid="stripe-connect" [attr.aria-busy]="busy() ? 'true' : null">
3012
- <ui-option-card [title]="title()" letter="S" color="#635bff" [description]="connected() ? connectedText() : description()"
3013
- [actionLabel]="statusKnown() ? (connected() ? reconnectLabel() : connectLabel()) : ''" [actionVariant]="connected() ? 'secondary' : 'primary'"
3014
- [actionAriaLabel]="(connected() ? reconnectLabel() : connectLabel()) + ' ' + title()" actionTestId="stripe-connect-action"
3015
- [actionLoading]="connecting()" [disabled]="disabled() || connecting()" (action)="connect()" />
3016
- @if (error(); as message) {
3017
- <ui-alert class="sc-error" variant="danger" data-testid="stripe-connect-error">{{ message }}</ui-alert>
3018
- @if (!statusKnown()) {
3019
- <ui-button class="sc-retry" variant="secondary" size="sm" data-testid="stripe-connect-retry" (click)="refresh()">Try again</ui-button>
3195
+ @if (visible()) {
3196
+ <ui-detail-card [collapsible]="false" [title]="title()" [headingLevel]="3" data-testid="connect-account-card">
3197
+ @if (!accountId()) {
3198
+ <ui-alert variant="info" [quiet]="true" [title]="startTitle()" data-testid="connect-status-none">
3199
+ <ui-stack gap="sm">
3200
+ <ui-text size="sm" [text]="startText()" />
3201
+ <ui-stack direction="horizontal">
3202
+ <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="loading() || disabled()" (click)="start()">{{ loading() ? 'Loading...' : startLabel() }}</ui-button>
3203
+ </ui-stack>
3204
+ </ui-stack>
3205
+ </ui-alert>
3206
+ } @else if (complete()) {
3207
+ <ui-alert variant="success" [quiet]="true" title="Account setup complete" data-testid="connect-status-complete">
3208
+ <ui-stack gap="sm">
3209
+ <ui-text size="sm" tone="muted" [text]="'Account ID: ' + accountId()" />
3210
+ <ui-stack direction="horizontal">
3211
+ <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">View Stripe Dashboard</ui-button>
3212
+ </ui-stack>
3213
+ </ui-stack>
3214
+ </ui-alert>
3215
+ } @else if (detailsSubmitted()) {
3216
+ <ui-alert variant="info" [quiet]="true" title="Stripe is verifying your account" data-testid="connect-status-verifying">
3217
+ <ui-stack gap="sm">
3218
+ <ui-text size="sm" text="Your setup has been submitted. Stripe is reviewing your information — this usually takes a few minutes. Payment collection will be enabled automatically once approved." />
3219
+ <ui-stack direction="horizontal">
3220
+ <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="loading() || disabled()" (click)="check()">{{ loading() ? 'Checking...' : 'Check Status' }}</ui-button>
3221
+ </ui-stack>
3222
+ </ui-stack>
3223
+ </ui-alert>
3224
+ } @else {
3225
+ <ui-alert variant="warning" [quiet]="true" title="Account setup incomplete" data-testid="connect-status-incomplete">
3226
+ <ui-stack gap="sm">
3227
+ <ui-text size="sm" text="Complete your Stripe account setup to start collecting payments from customers." />
3228
+ <ui-stack direction="horizontal">
3229
+ <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="loading() || disabled()" (click)="resume()">{{ loading() ? 'Loading...' : 'Complete Setup' }}</ui-button>
3230
+ </ui-stack>
3231
+ </ui-stack>
3232
+ </ui-alert>
3020
3233
  }
3021
- }
3022
- </div>
3234
+ </ui-detail-card>
3235
+ }
3023
3236
  `,
3024
3237
  isInline: true,
3025
- styles: ["ui-stripe-connect{display:block;min-width:0}ui-stripe-connect .sc-error{display:block;margin-top:12px}ui-stripe-connect .sc-retry{display:inline-block;margin-top:12px}\n"],
3238
+ styles: ["ui-stripe-connect{display:block;min-width:0}\n"],
3026
3239
  dependencies: [
3027
- {
3028
- kind: "component",
3029
- type: OptionCardComponent,
3030
- selector: "ui-option-card",
3031
- inputs: [
3032
- "title",
3033
- "description",
3034
- "letter",
3035
- "icon",
3036
- "color",
3037
- "actionLabel",
3038
- "actionVariant",
3039
- "actionAriaLabel",
3040
- "actionTestId",
3041
- "actionLoading",
3042
- "disabled"
3043
- ],
3044
- outputs: ["action"]
3045
- },
3046
3240
  {
3047
3241
  kind: "component",
3048
3242
  type: AlertComponent,
@@ -3054,7 +3248,8 @@ var StripeConnectComponent = class StripeConnectComponent {
3054
3248
  "dismissAriaLabel",
3055
3249
  "quiet",
3056
3250
  "compact",
3057
- "inline"
3251
+ "inline",
3252
+ "fill"
3058
3253
  ],
3059
3254
  outputs: ["dismissed"]
3060
3255
  },
@@ -3087,6 +3282,72 @@ var StripeConnectComponent = class StripeConnectComponent {
3087
3282
  "modal-footer-left",
3088
3283
  "modal-footer-right"
3089
3284
  ]
3285
+ },
3286
+ {
3287
+ kind: "component",
3288
+ type: DetailCardComponent,
3289
+ selector: "ui-detail-card",
3290
+ inputs: [
3291
+ "title",
3292
+ "uppercaseTitle",
3293
+ "headingLevel",
3294
+ "titleId",
3295
+ "ariaLabel",
3296
+ "subtitle",
3297
+ "background",
3298
+ "headerBackground",
3299
+ "footerBackground",
3300
+ "textColor",
3301
+ "showHeader",
3302
+ "collapsible",
3303
+ "expanded",
3304
+ "showEdit",
3305
+ "editLabel",
3306
+ "editTestId",
3307
+ "editIcon",
3308
+ "editAriaLabel",
3309
+ "fill",
3310
+ "maxBodyHeight",
3311
+ "selectable",
3312
+ "selected",
3313
+ "selectedColor",
3314
+ "selectedBackground"
3315
+ ],
3316
+ outputs: [
3317
+ "expandedChange",
3318
+ "editClick",
3319
+ "selectedChange"
3320
+ ]
3321
+ },
3322
+ {
3323
+ kind: "component",
3324
+ type: StackComponent,
3325
+ selector: "ui-stack",
3326
+ inputs: [
3327
+ "gap",
3328
+ "direction",
3329
+ "align",
3330
+ "justify",
3331
+ "wrap",
3332
+ "minHeight",
3333
+ "width",
3334
+ "maxWidth",
3335
+ "padding",
3336
+ "centered"
3337
+ ]
3338
+ },
3339
+ {
3340
+ kind: "component",
3341
+ type: TextComponent,
3342
+ selector: "ui-text",
3343
+ inputs: [
3344
+ "text",
3345
+ "size",
3346
+ "tone",
3347
+ "color",
3348
+ "strong",
3349
+ "weight"
3350
+ ]
3090
3351
  }
3091
3352
  ],
3092
3353
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
@@ -3106,107 +3367,147 @@ i0.ɵɵngDeclareClassMetadata({
3106
3367
  standalone: true,
3107
3368
  changeDetection: ChangeDetectionStrategy.OnPush,
3108
3369
  imports: [
3109
- OptionCardComponent,
3110
3370
  AlertComponent,
3111
- ButtonComponent
3371
+ ButtonComponent,
3372
+ DetailCardComponent,
3373
+ StackComponent,
3374
+ TextComponent
3112
3375
  ],
3113
3376
  template: `
3114
- <div class="sc" data-testid="stripe-connect" [attr.aria-busy]="busy() ? 'true' : null">
3115
- <ui-option-card [title]="title()" letter="S" color="#635bff" [description]="connected() ? connectedText() : description()"
3116
- [actionLabel]="statusKnown() ? (connected() ? reconnectLabel() : connectLabel()) : ''" [actionVariant]="connected() ? 'secondary' : 'primary'"
3117
- [actionAriaLabel]="(connected() ? reconnectLabel() : connectLabel()) + ' ' + title()" actionTestId="stripe-connect-action"
3118
- [actionLoading]="connecting()" [disabled]="disabled() || connecting()" (action)="connect()" />
3119
- @if (error(); as message) {
3120
- <ui-alert class="sc-error" variant="danger" data-testid="stripe-connect-error">{{ message }}</ui-alert>
3121
- @if (!statusKnown()) {
3122
- <ui-button class="sc-retry" variant="secondary" size="sm" data-testid="stripe-connect-retry" (click)="refresh()">Try again</ui-button>
3377
+ @if (visible()) {
3378
+ <ui-detail-card [collapsible]="false" [title]="title()" [headingLevel]="3" data-testid="connect-account-card">
3379
+ @if (!accountId()) {
3380
+ <ui-alert variant="info" [quiet]="true" [title]="startTitle()" data-testid="connect-status-none">
3381
+ <ui-stack gap="sm">
3382
+ <ui-text size="sm" [text]="startText()" />
3383
+ <ui-stack direction="horizontal">
3384
+ <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="loading() || disabled()" (click)="start()">{{ loading() ? 'Loading...' : startLabel() }}</ui-button>
3385
+ </ui-stack>
3386
+ </ui-stack>
3387
+ </ui-alert>
3388
+ } @else if (complete()) {
3389
+ <ui-alert variant="success" [quiet]="true" title="Account setup complete" data-testid="connect-status-complete">
3390
+ <ui-stack gap="sm">
3391
+ <ui-text size="sm" tone="muted" [text]="'Account ID: ' + accountId()" />
3392
+ <ui-stack direction="horizontal">
3393
+ <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">View Stripe Dashboard</ui-button>
3394
+ </ui-stack>
3395
+ </ui-stack>
3396
+ </ui-alert>
3397
+ } @else if (detailsSubmitted()) {
3398
+ <ui-alert variant="info" [quiet]="true" title="Stripe is verifying your account" data-testid="connect-status-verifying">
3399
+ <ui-stack gap="sm">
3400
+ <ui-text size="sm" text="Your setup has been submitted. Stripe is reviewing your information — this usually takes a few minutes. Payment collection will be enabled automatically once approved." />
3401
+ <ui-stack direction="horizontal">
3402
+ <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="loading() || disabled()" (click)="check()">{{ loading() ? 'Checking...' : 'Check Status' }}</ui-button>
3403
+ </ui-stack>
3404
+ </ui-stack>
3405
+ </ui-alert>
3406
+ } @else {
3407
+ <ui-alert variant="warning" [quiet]="true" title="Account setup incomplete" data-testid="connect-status-incomplete">
3408
+ <ui-stack gap="sm">
3409
+ <ui-text size="sm" text="Complete your Stripe account setup to start collecting payments from customers." />
3410
+ <ui-stack direction="horizontal">
3411
+ <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="loading() || disabled()" (click)="resume()">{{ loading() ? 'Loading...' : 'Complete Setup' }}</ui-button>
3412
+ </ui-stack>
3413
+ </ui-stack>
3414
+ </ui-alert>
3123
3415
  }
3124
- }
3125
- </div>
3416
+ </ui-detail-card>
3417
+ }
3126
3418
  `,
3127
3419
  encapsulation: ViewEncapsulation.None,
3128
- styles: ["ui-stripe-connect{display:block;min-width:0}ui-stripe-connect .sc-error{display:block;margin-top:12px}ui-stripe-connect .sc-retry{display:inline-block;margin-top:12px}\n"]
3420
+ styles: ["ui-stripe-connect{display:block;min-width:0}\n"]
3129
3421
  }]
3130
3422
  }],
3131
3423
  ctorParameters: () => [],
3132
3424
  propDecorators: {
3133
- statusEndpoint: [{
3425
+ createAccount: [{
3134
3426
  type: i0.Input,
3135
3427
  args: [{
3136
3428
  isSignal: true,
3137
- alias: "statusEndpoint",
3429
+ alias: "createAccount",
3138
3430
  required: false
3139
3431
  }]
3140
3432
  }],
3141
- connectEndpoint: [{
3433
+ getStatus: [{
3142
3434
  type: i0.Input,
3143
3435
  args: [{
3144
3436
  isSignal: true,
3145
- alias: "connectEndpoint",
3437
+ alias: "getStatus",
3146
3438
  required: false
3147
3439
  }]
3148
3440
  }],
3149
- connectParams: [{
3441
+ accountId: [{
3150
3442
  type: i0.Input,
3151
3443
  args: [{
3152
3444
  isSignal: true,
3153
- alias: "connectParams",
3445
+ alias: "accountId",
3154
3446
  required: false
3155
3447
  }]
3448
+ }, {
3449
+ type: i0.Output,
3450
+ args: ["accountIdChange"]
3156
3451
  }],
3157
- title: [{
3452
+ complete: [{
3158
3453
  type: i0.Input,
3159
3454
  args: [{
3160
3455
  isSignal: true,
3161
- alias: "title",
3456
+ alias: "complete",
3162
3457
  required: false
3163
3458
  }]
3459
+ }, {
3460
+ type: i0.Output,
3461
+ args: ["completeChange"]
3164
3462
  }],
3165
- description: [{
3463
+ detailsSubmitted: [{
3166
3464
  type: i0.Input,
3167
3465
  args: [{
3168
3466
  isSignal: true,
3169
- alias: "description",
3467
+ alias: "detailsSubmitted",
3170
3468
  required: false
3171
3469
  }]
3470
+ }, {
3471
+ type: i0.Output,
3472
+ args: ["detailsSubmittedChange"]
3172
3473
  }],
3173
- connectedText: [{
3474
+ title: [{
3174
3475
  type: i0.Input,
3175
3476
  args: [{
3176
3477
  isSignal: true,
3177
- alias: "connectedText",
3478
+ alias: "title",
3178
3479
  required: false
3179
3480
  }]
3180
3481
  }],
3181
- connectLabel: [{
3482
+ showWhenNoAccount: [{
3182
3483
  type: i0.Input,
3183
3484
  args: [{
3184
3485
  isSignal: true,
3185
- alias: "connectLabel",
3486
+ alias: "showWhenNoAccount",
3186
3487
  required: false
3187
3488
  }]
3188
3489
  }],
3189
- reconnectLabel: [{
3490
+ startTitle: [{
3190
3491
  type: i0.Input,
3191
3492
  args: [{
3192
3493
  isSignal: true,
3193
- alias: "reconnectLabel",
3494
+ alias: "startTitle",
3194
3495
  required: false
3195
3496
  }]
3196
3497
  }],
3197
- loadFailedText: [{
3498
+ startText: [{
3198
3499
  type: i0.Input,
3199
3500
  args: [{
3200
3501
  isSignal: true,
3201
- alias: "loadFailedText",
3502
+ alias: "startText",
3202
3503
  required: false
3203
3504
  }]
3204
3505
  }],
3205
- connectFailedText: [{
3506
+ startLabel: [{
3206
3507
  type: i0.Input,
3207
3508
  args: [{
3208
3509
  isSignal: true,
3209
- alias: "connectFailedText",
3510
+ alias: "startLabel",
3210
3511
  required: false
3211
3512
  }]
3212
3513
  }],
@@ -3218,12 +3519,47 @@ i0.ɵɵngDeclareClassMetadata({
3218
3519
  required: false
3219
3520
  }]
3220
3521
  }],
3221
- statusChange: [{
3522
+ refreshOnReturn: [{
3523
+ type: i0.Input,
3524
+ args: [{
3525
+ isSignal: true,
3526
+ alias: "refreshOnReturn",
3527
+ required: false
3528
+ }]
3529
+ }],
3530
+ dashboardUrl: [{
3531
+ type: i0.Input,
3532
+ args: [{
3533
+ isSignal: true,
3534
+ alias: "dashboardUrl",
3535
+ required: false
3536
+ }]
3537
+ }],
3538
+ outcome: [{
3539
+ type: i0.Output,
3540
+ args: ["outcome"]
3541
+ }],
3542
+ loading: [{
3543
+ type: i0.Input,
3544
+ args: [{
3545
+ isSignal: true,
3546
+ alias: "loading",
3547
+ required: false
3548
+ }]
3549
+ }, {
3222
3550
  type: i0.Output,
3223
- args: ["statusChange"]
3551
+ args: ["loadingChange"]
3552
+ }],
3553
+ navigateTab: [{
3554
+ type: i0.Input,
3555
+ args: [{
3556
+ isSignal: true,
3557
+ alias: "navigateTab",
3558
+ required: false
3559
+ }]
3224
3560
  }]
3225
3561
  }
3226
3562
  });
3227
- export { MICRODEPOSIT_COPY, MicrodepositVerifyComponent, STRIPE_A11Y_MESSAGES, STRIPE_ACH_NOTICE, STRIPE_DEFAULT_ERROR_MESSAGE, STRIPE_ERROR_MESSAGES, STRIPE_LOADER, STRIPE_PAYMENT_DEFAULTS, STRIPE_TECHNICAL_ERROR_MESSAGES, StripeConnectComponent, StripePaymentComponent, StripePaymentService, buildLoadOptions, defaultStripeLoader, depositAmountError, descriptorCodeError, getStripeErrorMessage, isDarkPage, microdepositArrivalText, microdepositCancelMessage, microdepositKeepsActiveText, microdepositProcessingText, microdepositStepsText, normalizeDescriptorCode, normalizeIntent, outcomeOf, paymentMethodIdOf, provideStripePayment, readStripeAppearance, readStripeReturnParams, retrieveIntent, verificationOf, verifyMicrodeposits };
3563
+ export { MICRODEPOSIT_COPY, MicrodepositVerifyComponent, STRIPE_A11Y_MESSAGES, STRIPE_ACH_NOTICE, STRIPE_DEFAULT_ERROR_MESSAGE, STRIPE_ERROR_MESSAGES, STRIPE_LOADER, STRIPE_PAYMENT_DEFAULTS, STRIPE_TECHNICAL_ERROR_MESSAGES, StripeConnectComponent, StripeConnectFlow, StripePaymentComponent, StripePaymentService, buildLoadOptions, defaultStripeLoader, depositAmountError, descriptorCodeError, getStripeErrorMessage, isDarkPage, isStripeUrl, microdepositArrivalText, microdepositCancelMessage, microdepositKeepsActiveText, microdepositProcessingText, microdepositStepsText, normalizeDescriptorCode, normalizeIntent, outcomeOf, paymentMethodIdOf, provideStripePayment, readStripeAppearance, readStripeReturnParams, retrieveIntent, stripeConnectNotice, verificationOf, verifyMicrodeposits };
3228
3564
 
3229
3565
  //# sourceMappingURL=forgeroute-ui-stripe.mjs.map