@atmo-dev/kit 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +214 -2
  3. package/dist/components/Avatar.svelte +35 -0
  4. package/dist/components/Avatar.svelte.d.ts +9 -0
  5. package/dist/components/Badge.svelte +21 -0
  6. package/dist/components/Badge.svelte.d.ts +7 -0
  7. package/dist/components/Button.svelte +94 -0
  8. package/dist/components/Button.svelte.d.ts +13 -0
  9. package/dist/components/Checkbox.svelte +29 -0
  10. package/dist/components/Checkbox.svelte.d.ts +8 -0
  11. package/dist/components/Heading.svelte +24 -0
  12. package/dist/components/Heading.svelte.d.ts +8 -0
  13. package/dist/components/Icon.svelte +24 -0
  14. package/dist/components/Icon.svelte.d.ts +8 -0
  15. package/dist/components/IconButton.svelte +24 -0
  16. package/dist/components/IconButton.svelte.d.ts +8 -0
  17. package/dist/components/IconRail.svelte +186 -0
  18. package/dist/components/IconRail.svelte.d.ts +26 -0
  19. package/dist/components/InlineEditor.svelte +120 -0
  20. package/dist/components/InlineEditor.svelte.d.ts +19 -0
  21. package/dist/components/Input.svelte +32 -0
  22. package/dist/components/Input.svelte.d.ts +9 -0
  23. package/dist/components/InsetImage.svelte +29 -0
  24. package/dist/components/InsetImage.svelte.d.ts +9 -0
  25. package/dist/components/Label.svelte +19 -0
  26. package/dist/components/Label.svelte.d.ts +7 -0
  27. package/dist/components/LinkCard.svelte +47 -0
  28. package/dist/components/LinkCard.svelte.d.ts +12 -0
  29. package/dist/components/Modal.svelte +93 -0
  30. package/dist/components/Modal.svelte.d.ts +12 -0
  31. package/dist/components/NestedComments.svelte +61 -0
  32. package/dist/components/NestedComments.svelte.d.ts +8 -0
  33. package/dist/components/Popover.svelte +49 -0
  34. package/dist/components/Popover.svelte.d.ts +12 -0
  35. package/dist/components/PostComposer.svelte +41 -0
  36. package/dist/components/PostComposer.svelte.d.ts +16 -0
  37. package/dist/components/PostContent.svelte +62 -0
  38. package/dist/components/PostContent.svelte.d.ts +8 -0
  39. package/dist/components/PostVideo.svelte +74 -0
  40. package/dist/components/PostVideo.svelte.d.ts +9 -0
  41. package/dist/components/Select.svelte +34 -0
  42. package/dist/components/Select.svelte.d.ts +9 -0
  43. package/dist/components/Subheading.svelte +22 -0
  44. package/dist/components/Subheading.svelte.d.ts +8 -0
  45. package/dist/components/Surface.svelte +40 -0
  46. package/dist/components/Surface.svelte.d.ts +11 -0
  47. package/dist/components/Tabs.svelte +47 -0
  48. package/dist/components/Tabs.svelte.d.ts +16 -0
  49. package/dist/components/Textarea.svelte +20 -0
  50. package/dist/components/Textarea.svelte.d.ts +7 -0
  51. package/dist/components/ToggleGroup.svelte +32 -0
  52. package/dist/components/ToggleGroup.svelte.d.ts +12 -0
  53. package/dist/components/ToggleGroupItem.svelte +26 -0
  54. package/dist/components/ToggleGroupItem.svelte.d.ts +8 -0
  55. package/dist/components/WorkspaceSidebar.svelte +82 -0
  56. package/dist/components/WorkspaceSidebar.svelte.d.ts +10 -0
  57. package/dist/components/login/ActorSearchField.svelte +238 -0
  58. package/dist/components/login/ActorSearchField.svelte.d.ts +19 -0
  59. package/dist/components/login/AtmosphereApps.svelte +19 -0
  60. package/dist/components/login/AtmosphereApps.svelte.d.ts +18 -0
  61. package/dist/components/login/LoginDialog.svelte +78 -0
  62. package/dist/components/login/LoginDialog.svelte.d.ts +9 -0
  63. package/dist/components/login/LoginForm.svelte +402 -0
  64. package/dist/components/login/LoginForm.svelte.d.ts +28 -0
  65. package/dist/components/login/RecentAccounts.svelte +57 -0
  66. package/dist/components/login/RecentAccounts.svelte.d.ts +10 -0
  67. package/dist/components/login/brands/README.md +7 -0
  68. package/dist/components/login/brands/blacksky.svg +3 -0
  69. package/dist/components/login/brands/bluesky.svg +3 -0
  70. package/dist/components/login/brands/bookhive.svg +3 -0
  71. package/dist/components/login/brands/graze.svg +3 -0
  72. package/dist/components/login/brands/leaflet.svg +3 -0
  73. package/dist/components/login/brands/pckt.svg +3 -0
  74. package/dist/components/login/brands/surf.svg +3 -0
  75. package/dist/components/login/brands/tangled.svg +3 -0
  76. package/dist/components/login/handle.d.ts +3 -0
  77. package/dist/components/login/handle.js +11 -0
  78. package/dist/components/login/permissions.d.ts +3 -0
  79. package/dist/components/login/permissions.js +13 -0
  80. package/dist/components/login/recent-accounts.d.ts +16 -0
  81. package/dist/components/login/recent-accounts.js +87 -0
  82. package/dist/components/login/search.d.ts +9 -0
  83. package/dist/components/login/search.js +47 -0
  84. package/dist/components/login/types.d.ts +27 -0
  85. package/dist/components/login/types.js +1 -0
  86. package/dist/confetti.d.ts +2 -0
  87. package/dist/confetti.js +13 -0
  88. package/dist/index.d.ts +51 -0
  89. package/dist/index.js +39 -0
  90. package/dist/palettes.d.ts +2 -0
  91. package/dist/palettes.js +30 -0
  92. package/dist/social/mention-suggestions.d.ts +35 -0
  93. package/dist/social/mention-suggestions.js +122 -0
  94. package/dist/social/posts.d.ts +95 -0
  95. package/dist/social/posts.js +59 -0
  96. package/dist/social/richtext.d.ts +25 -0
  97. package/dist/social/richtext.js +100 -0
  98. package/dist/styles.d.ts +2 -0
  99. package/dist/styles.js +3 -0
  100. package/dist/theme.css +503 -0
  101. package/dist/theme.d.ts +2 -0
  102. package/dist/theme.js +23 -0
  103. package/dist/utils.d.ts +2 -0
  104. package/dist/utils.js +6 -0
  105. package/package.json +99 -3
@@ -0,0 +1,82 @@
1
+ <script lang="ts">
2
+ import { tick, type Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { MediaQuery } from 'svelte/reactivity';
5
+ import Surface from './Surface.svelte';
6
+ import Modal from './Modal.svelte';
7
+ import { cn } from '../utils.js';
8
+ let {
9
+ label,
10
+ open = $bindable(false),
11
+ children,
12
+ class: className,
13
+ style,
14
+ ...rest
15
+ }: Omit<HTMLAttributes<HTMLElement>, 'children'> & {
16
+ label: string;
17
+ open?: boolean;
18
+ children: Snippet;
19
+ } = $props();
20
+ // Native null means “remove the attribute”; Bits UI accepts undefined instead.
21
+ const modalAttributes = $derived(
22
+ Object.fromEntries(Object.entries(rest).filter(([, value]) => value !== null))
23
+ );
24
+ let desktop = $state<HTMLElement | null>(null);
25
+ const mobile = new MediaQuery('(max-width: 900px)', false);
26
+ let drawerWasOpen = false;
27
+ $effect(() => {
28
+ const leavingDrawer = !mobile.current && drawerWasOpen;
29
+ drawerWasOpen = mobile.current && open;
30
+ if (!mobile.current) open = false;
31
+ if (leavingDrawer) {
32
+ void tick().then(() => {
33
+ if (!mobile.current)
34
+ desktop
35
+ ?.querySelector<HTMLElement>(
36
+ 'a[href], button:not(:disabled), input:not(:disabled), [tabindex="0"]'
37
+ )
38
+ ?.focus();
39
+ });
40
+ }
41
+ });
42
+ </script>
43
+
44
+ {#if !mobile.current}
45
+ <Surface
46
+ {...rest}
47
+ as="aside"
48
+ bind:ref={desktop}
49
+ {style}
50
+ aria-label={label}
51
+ data-slot="workspace-sidebar"
52
+ class={cn(
53
+ 'fixed top-[calc(var(--atmo-nav-top,0px)+12px)] bottom-3 left-3 z-40 w-[var(--atmo-sidebar-width,238px)] overflow-hidden rounded-[21px_18px_23px_19px] p-0 [@media(max-width:900px)]:hidden',
54
+ className
55
+ )}
56
+ >
57
+ <nav aria-label={label} class="h-full overflow-y-auto overscroll-contain px-3 py-4">
58
+ {@render children()}
59
+ </nav>
60
+ </Surface>
61
+ {:else}
62
+ <Modal
63
+ {...modalAttributes}
64
+ bind:open
65
+ title={label}
66
+ onCloseAutoFocus={(event) => {
67
+ if (!mobile.current) {
68
+ event.preventDefault();
69
+ }
70
+ }}
71
+ style={style ?? undefined}
72
+ data-slot="workspace-sidebar"
73
+ class={cn(
74
+ 'top-[calc(var(--atmo-nav-top,0px)+12px)] bottom-3 left-3 flex h-auto max-h-none w-[min(280px,calc(100%-24px))] max-w-none translate-x-0 translate-y-0 flex-col overflow-hidden rounded-[21px_18px_23px_19px] bg-recess p-3 shadow-(--ui-recess-shadow) sm:p-3 [&>header]:mb-3 [&>header]:px-2 [&>header]:pt-2 [&>header_h2]:text-sm',
75
+ className
76
+ )}
77
+ >
78
+ <nav aria-label={label} class="min-h-0 flex-1 overflow-y-auto overscroll-contain">
79
+ {@render children()}
80
+ </nav>
81
+ </Modal>
82
+ {/if}
@@ -0,0 +1,10 @@
1
+ import { type Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & {
4
+ label: string;
5
+ open?: boolean;
6
+ children: Snippet;
7
+ };
8
+ declare const WorkspaceSidebar: import("svelte").Component<$$ComponentProps, {}, "open">;
9
+ type WorkspaceSidebar = ReturnType<typeof WorkspaceSidebar>;
10
+ export default WorkspaceSidebar;
@@ -0,0 +1,238 @@
1
+ <script lang="ts">
2
+ import { untrack } from 'svelte';
3
+ import { Combobox } from 'bits-ui';
4
+ import { AtSign, LoaderCircle } from '@sketchyicons/svelte';
5
+ import type { ActorSearch, ActorSummary } from './types.js';
6
+ import { actorName } from './types.js';
7
+ import { cleanActors } from './search.js';
8
+ import Input from '../Input.svelte';
9
+ import Avatar from '../Avatar.svelte';
10
+ import Icon from '../Icon.svelte';
11
+ import { control } from '../../styles.js';
12
+ import { cn } from '../../utils.js';
13
+ import { readTheme, observeTheme } from '../../theme.js';
14
+ let {
15
+ value = $bindable(''),
16
+ searchActors,
17
+ onSelect,
18
+ label = 'Your handle',
19
+ placeholder = 'yourname.bsky.social',
20
+ id,
21
+ name = 'handle',
22
+ disabled = false,
23
+ invalid = false,
24
+ describedby,
25
+ debounce = 250,
26
+ class: className,
27
+ ref = $bindable(null)
28
+ }: {
29
+ value?: string;
30
+ searchActors?: ActorSearch;
31
+ onSelect?: (actor: ActorSummary) => void;
32
+ label?: string;
33
+ placeholder?: string;
34
+ id?: string;
35
+ name?: string;
36
+ disabled?: boolean;
37
+ invalid?: boolean;
38
+ describedby?: string;
39
+ debounce?: number;
40
+ class?: string;
41
+ ref?: HTMLInputElement | null;
42
+ } = $props();
43
+ const uid = $props.id();
44
+ const listId = `${uid}-suggestions`;
45
+ let open = $state(false),
46
+ focused = $state(false),
47
+ selection = $state('');
48
+ let results = $state<ActorSummary[]>([]);
49
+ let status = $state<'idle' | 'loading' | 'ready' | 'error'>('idle');
50
+ let inherited = $state('');
51
+ let dismissedQuery = '';
52
+ const message = $derived(
53
+ status === 'error'
54
+ ? 'Search unavailable. Enter your full handle to continue.'
55
+ : status === 'ready' && !results.length
56
+ ? 'No suggestions. You can still enter a full handle.'
57
+ : ''
58
+ );
59
+ const announcement = $derived(
60
+ status === 'loading'
61
+ ? 'Searching accounts.'
62
+ : message || (status === 'ready' ? `${results.length} accounts found.` : '')
63
+ );
64
+ const descriptionIds = $derived(
65
+ [describedby, message ? `${uid}-status` : undefined].filter(Boolean).join(' ') || undefined
66
+ );
67
+ $effect(() => {
68
+ const query = value.trim().replace(/^@+/, '');
69
+ const provider = searchActors;
70
+ if (disabled || !provider || query.length < 2) {
71
+ results = [];
72
+ status = 'idle';
73
+ open = false;
74
+ return;
75
+ }
76
+ if (!focused) {
77
+ open = false;
78
+ untrack(() => {
79
+ if (status === 'loading') status = 'idle';
80
+ });
81
+ return;
82
+ }
83
+ const controller = new AbortController();
84
+ results = [];
85
+ status = 'loading';
86
+ open = false;
87
+ const timer = setTimeout(
88
+ async () => {
89
+ try {
90
+ const found = await provider(query, controller.signal);
91
+ if (controller.signal.aborted) return;
92
+ results = cleanActors(found);
93
+ status = 'ready';
94
+ if (dismissedQuery !== query) open = results.length > 0;
95
+ } catch {
96
+ if (controller.signal.aborted) return;
97
+ results = [];
98
+ status = 'error';
99
+ }
100
+ },
101
+ Math.max(0, debounce)
102
+ );
103
+ return () => {
104
+ clearTimeout(timer);
105
+ controller.abort();
106
+ };
107
+ });
108
+ $effect(() => {
109
+ if (open && !results.length) open = false;
110
+ });
111
+ $effect(() => {
112
+ if (!open || !ref) {
113
+ inherited = '';
114
+ return;
115
+ }
116
+ const element = ref;
117
+ const sync = () => (inherited = readTheme(element));
118
+ sync();
119
+ return observeTheme(element, sync);
120
+ });
121
+ function choose(handle: string) {
122
+ const actor = results.find((actor) => actor.handle === handle);
123
+ if (!actor) return;
124
+ selection = handle;
125
+ value = actor.handle;
126
+ open = false;
127
+ onSelect?.(actor);
128
+ }
129
+ function keydown(event: KeyboardEvent) {
130
+ if (event.key === 'Escape') dismissedQuery = value.trim().replace(/^@+/, '');
131
+ if (
132
+ event.key === 'Enter' &&
133
+ !event.isComposing &&
134
+ !ref?.getAttribute('aria-activedescendant')
135
+ ) {
136
+ event.preventDefault();
137
+ open = false;
138
+ ref?.form?.requestSubmit();
139
+ }
140
+ }
141
+ </script>
142
+
143
+ <div class={cn('relative min-w-0', className)} data-slot="actor-search">
144
+ <Icon
145
+ img={AtSign}
146
+ size={18}
147
+ class="pointer-events-none absolute top-[13px] left-3 z-1 text-muted"
148
+ />
149
+ {#if searchActors}
150
+ <Combobox.Root
151
+ type="single"
152
+ {disabled}
153
+ bind:open
154
+ value={selection}
155
+ inputValue={value}
156
+ allowDeselect={false}
157
+ onValueChange={choose}
158
+ >
159
+ <Combobox.Input
160
+ {id}
161
+ {name}
162
+ aria-label={label}
163
+ aria-controls={open ? listId : undefined}
164
+ aria-describedby={descriptionIds}
165
+ aria-invalid={invalid || undefined}
166
+ {placeholder}
167
+ bind:ref
168
+ data-autofocus
169
+ autocomplete="off"
170
+ autocapitalize="none"
171
+ spellcheck="false"
172
+ class={cn(control, 'pr-10 pl-10')}
173
+ oninput={(event) => {
174
+ value = event.currentTarget.value;
175
+ selection = '';
176
+ dismissedQuery = '';
177
+ }}
178
+ onfocus={() => {
179
+ focused = true;
180
+ dismissedQuery = '';
181
+ }}
182
+ onblur={() => (focused = false)}
183
+ onkeydown={keydown}
184
+ />
185
+ {#if inherited}<Combobox.Portal
186
+ ><Combobox.Content
187
+ id={listId}
188
+ aria-label={`${label} suggestions`}
189
+ sideOffset={6}
190
+ collisionPadding={12}
191
+ style={inherited}
192
+ class="z-70 max-h-[min(20rem,var(--bits-combobox-content-available-height))] w-(--bits-combobox-anchor-width) min-w-52 overflow-y-auto overscroll-contain rounded-ui border border-line bg-field p-1.5 font-sans text-ink outline-none"
193
+ >
194
+ {#each results as actor (actor.did)}<Combobox.Item
195
+ value={actor.handle}
196
+ label={actor.handle}
197
+ class="flex min-h-14 cursor-pointer items-center gap-3 rounded-ui px-2.5 py-2 outline-none data-highlighted:bg-accent-soft data-highlighted:text-action"
198
+ ><Avatar
199
+ name={actorName(actor)}
200
+ src={actor.avatar}
201
+ size={32}
202
+ aria-hidden="true"
203
+ /><span class="grid min-w-0 gap-0.5"
204
+ ><strong class="truncate text-[.8125rem] font-medium">{actorName(actor)}</strong
205
+ >{#if actor.displayName}<span class="truncate text-xs text-muted"
206
+ >@{actor.handle}</span
207
+ >{/if}</span
208
+ ></Combobox.Item
209
+ >{/each}
210
+ </Combobox.Content></Combobox.Portal
211
+ >{/if}
212
+ </Combobox.Root>
213
+ {#if status === 'loading'}<Icon
214
+ img={LoaderCircle}
215
+ size={16}
216
+ class="pointer-events-none absolute top-3.5 right-3 text-muted motion-safe:animate-spin"
217
+ />{/if}
218
+ {:else}<Input
219
+ {id}
220
+ {name}
221
+ bind:value
222
+ bind:ref
223
+ aria-label={label}
224
+ aria-describedby={describedby}
225
+ aria-invalid={invalid || undefined}
226
+ {disabled}
227
+ {placeholder}
228
+ autocomplete="username"
229
+ autocapitalize="none"
230
+ spellcheck="false"
231
+ data-autofocus
232
+ class="pl-10"
233
+ />{/if}
234
+ {#if message}<p id={`${uid}-status`} class="mt-2 text-xs leading-relaxed text-muted">
235
+ {message}
236
+ </p>{/if}
237
+ <span class="sr-only" role="status">{announcement}</span>
238
+ </div>
@@ -0,0 +1,19 @@
1
+ import type { ActorSearch, ActorSummary } from './types.js';
2
+ type $$ComponentProps = {
3
+ value?: string;
4
+ searchActors?: ActorSearch;
5
+ onSelect?: (actor: ActorSummary) => void;
6
+ label?: string;
7
+ placeholder?: string;
8
+ id?: string;
9
+ name?: string;
10
+ disabled?: boolean;
11
+ invalid?: boolean;
12
+ describedby?: string;
13
+ debounce?: number;
14
+ class?: string;
15
+ ref?: HTMLInputElement | null;
16
+ };
17
+ declare const ActorSearchField: import("svelte").Component<$$ComponentProps, {}, "value" | "ref">;
18
+ type ActorSearchField = ReturnType<typeof ActorSearchField>;
19
+ export default ActorSearchField;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import bluesky from './brands/bluesky.svg?url';
3
+ import blacksky from './brands/blacksky.svg?url';
4
+ import graze from './brands/graze.svg?url';
5
+ import leaflet from './brands/leaflet.svg?url';
6
+ import tangled from './brands/tangled.svg?url';
7
+ import bookhive from './brands/bookhive.svg?url';
8
+ import surf from './brands/surf.svg?url';
9
+ import pckt from './brands/pckt.svg?url';
10
+ const apps = [bluesky, blacksky, graze, leaflet, tangled, bookhive, surf, pckt];
11
+ </script>
12
+
13
+ <!-- Existing brand marks, not replacement UI icons. Static: no endless decorative motion. -->
14
+ <div class="flex items-center justify-between gap-2 py-2" aria-hidden="true">
15
+ {#each apps as src (src)}<span
16
+ class="size-5 shrink-0 bg-muted [mask-size:contain] [mask-position:center] [mask-repeat:no-repeat] opacity-70 sm:size-6"
17
+ style:mask-image={`url("${src}")`}
18
+ ></span>{/each}
19
+ </div>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const AtmosphereApps: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type AtmosphereApps = InstanceType<typeof AtmosphereApps>;
18
+ export default AtmosphereApps;
@@ -0,0 +1,78 @@
1
+ <script lang="ts" module>
2
+ import type { LoginFormProps } from './LoginForm.svelte';
3
+ export type LoginDialogProps = Omit<LoginFormProps, 'showHeader' | 'ref'> & {
4
+ open?: boolean;
5
+ closeOnSuccess?: boolean;
6
+ formClass?: string;
7
+ };
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import { tick } from 'svelte';
12
+ import Modal from '../Modal.svelte';
13
+ import LoginForm from './LoginForm.svelte';
14
+ import type { ActorSummary, LoginStep } from './types.js';
15
+ import { cn } from '../../utils.js';
16
+ let {
17
+ open = $bindable(false),
18
+ recentAccounts = $bindable([]),
19
+ closeOnSuccess = true,
20
+ title = 'Log in with your Atmosphere account',
21
+ description,
22
+ onSuccess,
23
+ onStepChange,
24
+ class: className,
25
+ formClass,
26
+ ...formProps
27
+ }: LoginDialogProps = $props();
28
+ const uid = $props.id();
29
+ let step = $state<LoginStep>('login');
30
+ const dialogTitle = $derived(
31
+ step === 'permissions'
32
+ ? 'Requested permissions'
33
+ : step === 'signup'
34
+ ? 'Already have an account?'
35
+ : title
36
+ );
37
+ const dialogDescription = $derived(
38
+ step === 'permissions'
39
+ ? 'Choose what this app can access. Required permissions stay on.'
40
+ : step === 'signup'
41
+ ? 'You can use a Bluesky, Blacksky, or other Atmosphere account here. Otherwise, continue to create one.'
42
+ : description
43
+ );
44
+ $effect(() => {
45
+ if (!open) step = 'login';
46
+ });
47
+ async function changed(next: LoginStep) {
48
+ step = next;
49
+ onStepChange?.(next);
50
+ if (next !== 'login') {
51
+ await tick();
52
+ document.getElementById(uid)?.querySelector<HTMLElement>('h2')?.focus();
53
+ }
54
+ }
55
+ function completed(handle: string, actor?: ActorSummary) {
56
+ if (closeOnSuccess) open = false;
57
+ onSuccess?.(handle, actor);
58
+ }
59
+ </script>
60
+
61
+ <Modal
62
+ bind:open
63
+ id={uid}
64
+ title={dialogTitle}
65
+ description={dialogDescription}
66
+ class={cn('max-w-sm [&>header]:mb-4', className)}
67
+ >
68
+ <LoginForm
69
+ {...formProps}
70
+ bind:recentAccounts
71
+ {title}
72
+ {description}
73
+ showHeader={false}
74
+ class={formClass}
75
+ onSuccess={completed}
76
+ onStepChange={changed}
77
+ />
78
+ </Modal>
@@ -0,0 +1,9 @@
1
+ import type { LoginFormProps } from './LoginForm.svelte';
2
+ export type LoginDialogProps = Omit<LoginFormProps, 'showHeader' | 'ref'> & {
3
+ open?: boolean;
4
+ closeOnSuccess?: boolean;
5
+ formClass?: string;
6
+ };
7
+ declare const LoginDialog: import("svelte").Component<LoginDialogProps, {}, "open" | "recentAccounts">;
8
+ type LoginDialog = ReturnType<typeof LoginDialog>;
9
+ export default LoginDialog;