@nebulr-group/bridge-svelte 0.1.0-beta.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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/dist/auth/route-guard.d.ts +2 -0
  4. package/dist/auth/route-guard.js +28 -0
  5. package/dist/client/BridgeBootstrap.d.ts +8 -0
  6. package/dist/client/BridgeBootstrap.js +105 -0
  7. package/dist/client/BridgeBootstrap.svelte +43 -0
  8. package/dist/client/BridgeBootstrap.svelte.d.ts +6 -0
  9. package/dist/client/components/FeatureFlag.svelte +37 -0
  10. package/dist/client/components/FeatureFlag.svelte.d.ts +15 -0
  11. package/dist/client/components/ProfileName.svelte +18 -0
  12. package/dist/client/components/ProfileName.svelte.d.ts +6 -0
  13. package/dist/client/components/developer/ApiTokenManagement.svelte +365 -0
  14. package/dist/client/components/developer/ApiTokenManagement.svelte.d.ts +6 -0
  15. package/dist/client/components/sdk-auth/ForgotPassword.svelte +170 -0
  16. package/dist/client/components/sdk-auth/ForgotPassword.svelte.d.ts +10 -0
  17. package/dist/client/components/sdk-auth/LoginForm.svelte +414 -0
  18. package/dist/client/components/sdk-auth/LoginForm.svelte.d.ts +25 -0
  19. package/dist/client/components/sdk-auth/MagicLink.svelte +92 -0
  20. package/dist/client/components/sdk-auth/MagicLink.svelte.d.ts +9 -0
  21. package/dist/client/components/sdk-auth/MfaChallenge.svelte +150 -0
  22. package/dist/client/components/sdk-auth/MfaChallenge.svelte.d.ts +9 -0
  23. package/dist/client/components/sdk-auth/MfaSetup.svelte +182 -0
  24. package/dist/client/components/sdk-auth/MfaSetup.svelte.d.ts +8 -0
  25. package/dist/client/components/sdk-auth/PasskeyLogin.svelte +99 -0
  26. package/dist/client/components/sdk-auth/PasskeyLogin.svelte.d.ts +10 -0
  27. package/dist/client/components/sdk-auth/PasskeyRequestSetupLink.svelte +83 -0
  28. package/dist/client/components/sdk-auth/PasskeyRequestSetupLink.svelte.d.ts +7 -0
  29. package/dist/client/components/sdk-auth/PasskeySetup.svelte +151 -0
  30. package/dist/client/components/sdk-auth/PasskeySetup.svelte.d.ts +11 -0
  31. package/dist/client/components/sdk-auth/SignupForm.svelte +119 -0
  32. package/dist/client/components/sdk-auth/SignupForm.svelte.d.ts +14 -0
  33. package/dist/client/components/sdk-auth/SsoButton.svelte +70 -0
  34. package/dist/client/components/sdk-auth/SsoButton.svelte.d.ts +13 -0
  35. package/dist/client/components/sdk-auth/SsoProviderIcon.svelte +56 -0
  36. package/dist/client/components/sdk-auth/SsoProviderIcon.svelte.d.ts +7 -0
  37. package/dist/client/components/sdk-auth/TenantSelector.svelte +83 -0
  38. package/dist/client/components/sdk-auth/TenantSelector.svelte.d.ts +11 -0
  39. package/dist/client/components/sdk-auth/WorkspaceSelector.svelte +108 -0
  40. package/dist/client/components/sdk-auth/WorkspaceSelector.svelte.d.ts +16 -0
  41. package/dist/client/components/sdk-auth/shared/Alert.svelte +17 -0
  42. package/dist/client/components/sdk-auth/shared/Alert.svelte.d.ts +9 -0
  43. package/dist/client/components/sdk-auth/shared/AuthFormWrapper.svelte +23 -0
  44. package/dist/client/components/sdk-auth/shared/AuthFormWrapper.svelte.d.ts +10 -0
  45. package/dist/client/components/sdk-auth/shared/Spinner.svelte +16 -0
  46. package/dist/client/components/sdk-auth/shared/Spinner.svelte.d.ts +7 -0
  47. package/dist/client/components/subscription/PlanSelector.svelte +204 -0
  48. package/dist/client/components/subscription/PlanSelector.svelte.d.ts +22 -0
  49. package/dist/client/components/team/TeamAddUserDialog.svelte +125 -0
  50. package/dist/client/components/team/TeamAddUserDialog.svelte.d.ts +17 -0
  51. package/dist/client/components/team/TeamConfirmDialog.svelte +80 -0
  52. package/dist/client/components/team/TeamConfirmDialog.svelte.d.ts +21 -0
  53. package/dist/client/components/team/TeamEditUserDialog.svelte +131 -0
  54. package/dist/client/components/team/TeamEditUserDialog.svelte.d.ts +19 -0
  55. package/dist/client/components/team/TeamManagementPanel.svelte +72 -0
  56. package/dist/client/components/team/TeamManagementPanel.svelte.d.ts +20 -0
  57. package/dist/client/components/team/TeamProfileForm.svelte +129 -0
  58. package/dist/client/components/team/TeamProfileForm.svelte.d.ts +7 -0
  59. package/dist/client/components/team/TeamUserActionsMenu.svelte +63 -0
  60. package/dist/client/components/team/TeamUserActionsMenu.svelte.d.ts +9 -0
  61. package/dist/client/components/team/TeamUserList.svelte +226 -0
  62. package/dist/client/components/team/TeamUserList.svelte.d.ts +7 -0
  63. package/dist/client/components/team/TeamWorkspaceForm.svelte +134 -0
  64. package/dist/client/components/team/TeamWorkspaceForm.svelte.d.ts +7 -0
  65. package/dist/client/stores/config.store.d.ts +6 -0
  66. package/dist/client/stores/config.store.js +76 -0
  67. package/dist/client/utils/cn.d.ts +1 -0
  68. package/dist/client/utils/cn.js +3 -0
  69. package/dist/core/bridge-instance.d.ts +52 -0
  70. package/dist/core/bridge-instance.js +160 -0
  71. package/dist/index.d.ts +34 -0
  72. package/dist/index.js +39 -0
  73. package/dist/shared/feature-flag.d.ts +6 -0
  74. package/dist/shared/feature-flag.js +13 -0
  75. package/dist/shared/logger.d.ts +18 -0
  76. package/dist/shared/logger.js +32 -0
  77. package/dist/shared/profile.d.ts +18 -0
  78. package/dist/shared/profile.js +25 -0
  79. package/dist/shared/types/config.d.ts +42 -0
  80. package/dist/shared/types/config.js +1 -0
  81. package/dist/styles.css +1089 -0
  82. package/package.json +86 -0
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ interface Props extends HTMLAttributes<HTMLDivElement> {
4
+ onSignup?: () => void;
5
+ onError?: (error: Error) => void;
6
+ showLoginLink?: boolean;
7
+ /** Override login page URL. Default: derived from BridgeConfig loginRoute. */
8
+ loginHref?: string | undefined;
9
+ heading?: string;
10
+ footer?: Snippet;
11
+ }
12
+ declare const SignupForm: import("svelte").Component<Props, {}, "">;
13
+ type SignupForm = ReturnType<typeof SignupForm>;
14
+ export default SignupForm;
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLButtonAttributes } from 'svelte/elements';
4
+ import type { FederationConnection } from '@thebridge/auth-core';
5
+ import { getBridgeAuth } from '../../../core/bridge-instance.js';
6
+ import Spinner from './shared/Spinner.svelte';
7
+
8
+ interface Props extends HTMLButtonAttributes {
9
+ connection: FederationConnection;
10
+ label?: string;
11
+ onSuccess?: () => void;
12
+ onError?: (error: Error) => void;
13
+ icon?: Snippet;
14
+ }
15
+
16
+ let {
17
+ connection,
18
+ label,
19
+ onSuccess,
20
+ onError,
21
+ icon,
22
+ class: className,
23
+ style,
24
+ ...rest
25
+ }: Props = $props();
26
+
27
+ let loading = $state(false);
28
+ let buttonLabel = $derived(label ?? `Continue with ${connection.name}`);
29
+
30
+ async function handleClick() {
31
+ if (loading) return;
32
+ loading = true;
33
+ try {
34
+ const result = await getBridgeAuth().startSsoLogin(connection.type);
35
+ if (result.type === 'auth_success') {
36
+ onSuccess?.();
37
+ } else if (result.type === 'auth_error') {
38
+ throw new Error(result.error || 'SSO login failed');
39
+ }
40
+ // auth_mfa_required and auth_tenant_selection are handled by authState store
41
+ } catch (err: any) {
42
+ const message = err.message?.includes('popup')
43
+ ? 'Pop-up was blocked. Please allow pop-ups and try again.'
44
+ : err.message || 'SSO login failed';
45
+ onError?.(new Error(message));
46
+ } finally {
47
+ loading = false;
48
+ }
49
+ }
50
+ </script>
51
+
52
+ <button
53
+ type="button"
54
+ class={className}
55
+ {style}
56
+ data-bridge-sso-button
57
+ data-loading={loading}
58
+ onclick={handleClick}
59
+ disabled={loading}
60
+ {...rest}
61
+ >
62
+ <span class="bridge-sso-btn-inner">
63
+ {#if loading}
64
+ <Spinner size={16} />
65
+ {:else if icon}
66
+ {@render icon()}
67
+ {/if}
68
+ <span>{buttonLabel}</span>
69
+ </span>
70
+ </button>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLButtonAttributes } from 'svelte/elements';
3
+ import type { FederationConnection } from '@thebridge/auth-core';
4
+ interface Props extends HTMLButtonAttributes {
5
+ connection: FederationConnection;
6
+ label?: string;
7
+ onSuccess?: () => void;
8
+ onError?: (error: Error) => void;
9
+ icon?: Snippet;
10
+ }
11
+ declare const SsoButton: import("svelte").Component<Props, {}, "">;
12
+ type SsoButton = ReturnType<typeof SsoButton>;
13
+ export default SsoButton;
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+
4
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
5
+ type: string;
6
+ }
7
+
8
+ let { type, class: className, style, ...rest }: Props = $props();
9
+ </script>
10
+
11
+ <span class={className} {style} data-bridge-sso-icon data-provider={type} {...rest}>
12
+ {#if type === 'google'}
13
+ <!-- Google "G" icon -->
14
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="18" height="18" aria-hidden="true">
15
+ <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
16
+ <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
17
+ <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
18
+ <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
19
+ <path fill="none" d="M0 0h48v48H0z"/>
20
+ </svg>
21
+
22
+ {:else if type === 'ms-azure-ad'}
23
+ <!-- Microsoft logo -->
24
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21" width="18" height="18" aria-hidden="true">
25
+ <rect x="1" y="1" width="9" height="9" fill="#f25022"/>
26
+ <rect x="11" y="1" width="9" height="9" fill="#00a4ef"/>
27
+ <rect x="1" y="11" width="9" height="9" fill="#7fba00"/>
28
+ <rect x="11" y="11" width="9" height="9" fill="#ffb900"/>
29
+ </svg>
30
+
31
+ {:else if type === 'linkedin'}
32
+ <!-- LinkedIn logo -->
33
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
34
+ <path fill="#0077B5" d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
35
+ </svg>
36
+
37
+ {:else if type === 'facebook'}
38
+ <!-- Facebook logo -->
39
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
40
+ <path fill="#1877F2" d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
41
+ </svg>
42
+
43
+ {:else if type === 'github'}
44
+ <!-- GitHub logo -->
45
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
46
+ <path fill="currentColor" d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
47
+ </svg>
48
+
49
+ {:else if type === 'apple'}
50
+ <!-- Apple logo -->
51
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" width="16" height="18" aria-hidden="true">
52
+ <path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76 0-103.7 40.8-165.9 40.8s-105-57.8-155.5-127.4C46 790.7 0 663 0 541.8c0-207.5 135.4-317.3 269-317.3 80 0 146.6 44.2 196.3 44.2 47.4 0 121.9-47.4 212.1-47.4 36.5 0 139.1 3.2 213.1 117.1zM570.1 107.3c34.3-41.5 58.9-99.1 58.9-156.7 0-8-0.6-16.1-2-23.5-55.1 2-120.9 36.7-161.8 83.8-31.5 35.8-61.7 93.4-61.7 151.7 0 8.6 1.3 17.3 1.9 20 3.3 0.5 8.7 1.4 14 1.4 49.6 0 110.8-32.8 150.7-76.7z"/>
53
+ </svg>
54
+
55
+ {/if}
56
+ </span>
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
3
+ type: string;
4
+ }
5
+ declare const SsoProviderIcon: import("svelte").Component<Props, {}, "">;
6
+ type SsoProviderIcon = ReturnType<typeof SsoProviderIcon>;
7
+ export default SsoProviderIcon;
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import type { TenantUser } from '@thebridge/auth-core';
5
+ import { getBridgeAuth, tenantUsersStore } from '../../../core/bridge-instance.js';
6
+ import AuthFormWrapper from './shared/AuthFormWrapper.svelte';
7
+ import Spinner from './shared/Spinner.svelte';
8
+ import Alert from './shared/Alert.svelte';
9
+
10
+ interface Props extends HTMLAttributes<HTMLDivElement> {
11
+ onSelect?: () => void;
12
+ onError?: (error: Error) => void;
13
+ tenantItem?: Snippet<[TenantUser]>;
14
+ }
15
+
16
+ let {
17
+ onSelect,
18
+ onError,
19
+ tenantItem,
20
+ class: className,
21
+ style,
22
+ ...rest
23
+ }: Props = $props();
24
+
25
+ let loading = $state(false);
26
+ let selectedId = $state<string | null>(null);
27
+ let error = $state<string | null>(null);
28
+
29
+ async function handleSelect(tenantUser: TenantUser) {
30
+ if (loading) return;
31
+ error = null;
32
+ selectedId = tenantUser.id;
33
+ loading = true;
34
+ try {
35
+ await getBridgeAuth().selectTenant(tenantUser.id);
36
+ onSelect?.();
37
+ } catch (err: any) {
38
+ error = err.message || 'Failed to select workspace.';
39
+ onError?.(err);
40
+ } finally {
41
+ loading = false;
42
+ selectedId = null;
43
+ }
44
+ }
45
+ </script>
46
+
47
+ <AuthFormWrapper heading="Choose a workspace" class={className} {style} {...rest}>
48
+ {#if error}
49
+ <Alert variant="error">{error}</Alert>
50
+ {/if}
51
+
52
+ <div class="bridge-tenant-list">
53
+ {#each $tenantUsersStore as tu (tu.id)}
54
+ <button
55
+ type="button"
56
+ class="bridge-tenant-item"
57
+ data-tenant-id={tu.id}
58
+ data-loading={selectedId === tu.id}
59
+ onclick={() => handleSelect(tu)}
60
+ disabled={loading}
61
+ >
62
+ {#if tenantItem}
63
+ {@render tenantItem(tu)}
64
+ {:else}
65
+ <span class="bridge-tenant-avatar">
66
+ {#if tu.tenant.logo}
67
+ <img src={tu.tenant.logo} alt={tu.tenant.name} />
68
+ {:else}
69
+ {tu.tenant.name.charAt(0).toUpperCase()}
70
+ {/if}
71
+ </span>
72
+ <span class="bridge-tenant-info">
73
+ <span class="bridge-tenant-name">{tu.tenant.name}</span>
74
+ <span class="bridge-tenant-user">{tu.fullName}</span>
75
+ </span>
76
+ {#if selectedId === tu.id}
77
+ <Spinner size={18} />
78
+ {/if}
79
+ {/if}
80
+ </button>
81
+ {/each}
82
+ </div>
83
+ </AuthFormWrapper>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { TenantUser } from '@thebridge/auth-core';
4
+ interface Props extends HTMLAttributes<HTMLDivElement> {
5
+ onSelect?: () => void;
6
+ onError?: (error: Error) => void;
7
+ tenantItem?: Snippet<[TenantUser]>;
8
+ }
9
+ declare const TenantSelector: import("svelte").Component<Props, {}, "">;
10
+ type TenantSelector = ReturnType<typeof TenantSelector>;
11
+ export default TenantSelector;
@@ -0,0 +1,108 @@
1
+ <script lang="ts">
2
+ import type { HTMLDivAttributes } from 'svelte/elements';
3
+ import type { Snippet } from 'svelte';
4
+ import type { Workspace } from '@thebridge/auth-core';
5
+ import { onMount } from 'svelte';
6
+ import { getBridgeAuth, profileStore } from '../../../core/bridge-instance.js';
7
+ import Spinner from './shared/Spinner.svelte';
8
+ import Alert from './shared/Alert.svelte';
9
+
10
+ interface Props extends HTMLDivAttributes {
11
+ onSwitch?: () => void;
12
+ onError?: (error: Error) => void;
13
+ workspaceItem?: Snippet<[{ workspace: Workspace; isActive: boolean; isLoading: boolean; onSelect: () => void }]>;
14
+ }
15
+
16
+ let {
17
+ onSwitch,
18
+ onError,
19
+ workspaceItem,
20
+ class: className,
21
+ style,
22
+ ...rest
23
+ }: Props = $props();
24
+
25
+ let workspaces = $state<Workspace[]>([]);
26
+ let loadError = $state<string | null>(null);
27
+ let loadingList = $state(true);
28
+ let switchingId = $state<string | null>(null);
29
+ let switchError = $state<string | null>(null);
30
+
31
+ const currentWorkspaceId = $derived($profileStore?.id ?? null);
32
+
33
+ onMount(async () => {
34
+ try {
35
+ workspaces = await getBridgeAuth().getWorkspaces();
36
+ } catch (err: any) {
37
+ loadError = err.message || 'Failed to load workspaces.';
38
+ } finally {
39
+ loadingList = false;
40
+ }
41
+ });
42
+
43
+ async function handleSelect(workspace: Workspace) {
44
+ if (switchingId) return;
45
+ switchError = null;
46
+ switchingId = workspace.id;
47
+ try {
48
+ await getBridgeAuth().switchWorkspace(workspace.id);
49
+ onSwitch?.();
50
+ } catch (err: any) {
51
+ switchError = err.message || 'Failed to switch workspace.';
52
+ onError?.(err);
53
+ } finally {
54
+ switchingId = null;
55
+ }
56
+ }
57
+ </script>
58
+
59
+ <div
60
+ class={className}
61
+ {style}
62
+ data-bridge-workspace-selector
63
+ data-loading-list={loadingList}
64
+ {...rest}
65
+ >
66
+ {#if loadError || switchError}
67
+ <Alert variant="error">{loadError ?? switchError}</Alert>
68
+ {/if}
69
+
70
+ {#if loadingList}
71
+ <div data-bridge-workspace-loading>
72
+ <Spinner size={24} />
73
+ </div>
74
+ {:else}
75
+ <div data-bridge-workspace-list>
76
+ {#each workspaces as ws (ws.id)}
77
+ {#if workspaceItem}
78
+ {@render workspaceItem({ workspace: ws, isActive: ws.id === currentWorkspaceId, isLoading: switchingId === ws.id, onSelect: () => handleSelect(ws) })}
79
+ {:else}
80
+ <button
81
+ type="button"
82
+ data-bridge-workspace-item
83
+ data-active={ws.id === currentWorkspaceId}
84
+ data-loading={switchingId === ws.id}
85
+ disabled={!!switchingId}
86
+ onclick={() => handleSelect(ws)}
87
+ >
88
+ <span data-bridge-workspace-avatar>
89
+ {#if ws.tenant.logo}
90
+ <img src={ws.tenant.logo} alt={ws.tenant.name} />
91
+ {:else}
92
+ {ws.tenant.name.charAt(0).toUpperCase()}
93
+ {/if}
94
+ </span>
95
+ <span data-bridge-workspace-info>
96
+ <span data-bridge-workspace-name>{ws.tenant.name}</span>
97
+ <span data-bridge-workspace-user>{ws.fullName}</span>
98
+ </span>
99
+ {#if switchingId === ws.id}
100
+ <Spinner size={18} />
101
+ {/if}
102
+ </button>
103
+ {/if}
104
+ {/each}
105
+ </div>
106
+ {/if}
107
+ </div>
108
+ <!-- no <style> block -->
@@ -0,0 +1,16 @@
1
+ import type { HTMLDivAttributes } from 'svelte/elements';
2
+ import type { Snippet } from 'svelte';
3
+ import type { Workspace } from '@thebridge/auth-core';
4
+ interface Props extends HTMLDivAttributes {
5
+ onSwitch?: () => void;
6
+ onError?: (error: Error) => void;
7
+ workspaceItem?: Snippet<[{
8
+ workspace: Workspace;
9
+ isActive: boolean;
10
+ isLoading: boolean;
11
+ onSelect: () => void;
12
+ }]>;
13
+ }
14
+ declare const WorkspaceSelector: import("svelte").Component<Props, {}, "">;
15
+ type WorkspaceSelector = ReturnType<typeof WorkspaceSelector>;
16
+ export default WorkspaceSelector;
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+
5
+ interface Props extends HTMLAttributes<HTMLDivElement> {
6
+ variant?: 'error' | 'info' | 'success';
7
+ children?: Snippet;
8
+ }
9
+
10
+ let { variant = 'error', children, class: className, style, ...rest }: Props = $props();
11
+ </script>
12
+
13
+ {#if children}
14
+ <div class={className} {style} data-variant={variant} data-bridge-alert role="alert" {...rest}>
15
+ {@render children()}
16
+ </div>
17
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ interface Props extends HTMLAttributes<HTMLDivElement> {
4
+ variant?: 'error' | 'info' | 'success';
5
+ children?: Snippet;
6
+ }
7
+ declare const Alert: import("svelte").Component<Props, {}, "">;
8
+ type Alert = ReturnType<typeof Alert>;
9
+ export default Alert;
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+
5
+ interface Props extends HTMLAttributes<HTMLDivElement> {
6
+ heading?: string;
7
+ headingSnippet?: Snippet;
8
+ children?: Snippet;
9
+ }
10
+
11
+ let { heading, headingSnippet, children, class: className, style, ...rest }: Props = $props();
12
+ </script>
13
+
14
+ <div class={className} {style} data-bridge-auth-form {...rest}>
15
+ {#if headingSnippet}
16
+ {@render headingSnippet()}
17
+ {:else if heading}
18
+ <h2 class="bridge-auth-heading">{heading}</h2>
19
+ {/if}
20
+ {#if children}
21
+ {@render children()}
22
+ {/if}
23
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ interface Props extends HTMLAttributes<HTMLDivElement> {
4
+ heading?: string;
5
+ headingSnippet?: Snippet;
6
+ children?: Snippet;
7
+ }
8
+ declare const AuthFormWrapper: import("svelte").Component<Props, {}, "">;
9
+ type AuthFormWrapper = ReturnType<typeof AuthFormWrapper>;
10
+ export default AuthFormWrapper;
@@ -0,0 +1,16 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+
4
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
5
+ size?: number;
6
+ }
7
+
8
+ let { size = 24, class: className, style, ...rest }: Props = $props();
9
+ </script>
10
+
11
+ <span
12
+ class={className}
13
+ style="width: {size}px; height: {size}px;{style ? ' ' + style : ''}"
14
+ data-bridge-spinner
15
+ {...rest}
16
+ ></span>
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
3
+ size?: number;
4
+ }
5
+ declare const Spinner: import("svelte").Component<Props, {}, "">;
6
+ type Spinner = ReturnType<typeof Spinner>;
7
+ export default Spinner;