yaxa-svelte 1.0.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 (169) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/assets/favicon.svg +15 -0
  4. package/dist/components/elements/Avatar.svelte +106 -0
  5. package/dist/components/elements/Avatar.svelte.d.ts +40 -0
  6. package/dist/components/elements/AvatarGroup.svelte +18 -0
  7. package/dist/components/elements/AvatarGroup.svelte.d.ts +8 -0
  8. package/dist/components/elements/Badge.svelte +202 -0
  9. package/dist/components/elements/Badge.svelte.d.ts +75 -0
  10. package/dist/components/elements/Button.svelte +300 -0
  11. package/dist/components/elements/Button.svelte.d.ts +109 -0
  12. package/dist/components/elements/ButtonGroup.svelte +22 -0
  13. package/dist/components/elements/ButtonGroup.svelte.d.ts +9 -0
  14. package/dist/components/elements/Chip.svelte +117 -0
  15. package/dist/components/elements/Chip.svelte.d.ts +15 -0
  16. package/dist/components/elements/DataTable.svelte +222 -0
  17. package/dist/components/elements/DataTable.svelte.d.ts +43 -0
  18. package/dist/components/elements/Icon.svelte +87 -0
  19. package/dist/components/elements/Icon.svelte.d.ts +10 -0
  20. package/dist/components/elements/Kbd.svelte +37 -0
  21. package/dist/components/elements/Kbd.svelte.d.ts +32 -0
  22. package/dist/components/elements/Link.svelte +63 -0
  23. package/dist/components/elements/Link.svelte.d.ts +15 -0
  24. package/dist/components/elements/Logo.svelte +77 -0
  25. package/dist/components/elements/Logo.svelte.d.ts +9 -0
  26. package/dist/components/elements/Meter.svelte +87 -0
  27. package/dist/components/elements/Meter.svelte.d.ts +14 -0
  28. package/dist/components/elements/Progress.svelte +63 -0
  29. package/dist/components/elements/Progress.svelte.d.ts +49 -0
  30. package/dist/components/elements/Skeleton.svelte +12 -0
  31. package/dist/components/elements/Skeleton.svelte.d.ts +6 -0
  32. package/dist/components/elements/Spinner.svelte +39 -0
  33. package/dist/components/elements/Spinner.svelte.d.ts +7 -0
  34. package/dist/components/forms/Checkbox.svelte +77 -0
  35. package/dist/components/forms/Checkbox.svelte.d.ts +17 -0
  36. package/dist/components/forms/ColorPicker.svelte +142 -0
  37. package/dist/components/forms/ColorPicker.svelte.d.ts +10 -0
  38. package/dist/components/forms/Form.svelte +84 -0
  39. package/dist/components/forms/Form.svelte.d.ts +14 -0
  40. package/dist/components/forms/FormField.svelte +56 -0
  41. package/dist/components/forms/FormField.svelte.d.ts +14 -0
  42. package/dist/components/forms/Input.svelte +138 -0
  43. package/dist/components/forms/Input.svelte.d.ts +58 -0
  44. package/dist/components/forms/RadioGroup.svelte +74 -0
  45. package/dist/components/forms/RadioGroup.svelte.d.ts +17 -0
  46. package/dist/components/forms/Select.svelte +91 -0
  47. package/dist/components/forms/Select.svelte.d.ts +50 -0
  48. package/dist/components/forms/Slider.svelte +37 -0
  49. package/dist/components/forms/Slider.svelte.d.ts +12 -0
  50. package/dist/components/forms/Switch.svelte +81 -0
  51. package/dist/components/forms/Switch.svelte.d.ts +53 -0
  52. package/dist/components/forms/Textarea.svelte +73 -0
  53. package/dist/components/forms/Textarea.svelte.d.ts +64 -0
  54. package/dist/components/layout/Card.svelte +89 -0
  55. package/dist/components/layout/Card.svelte.d.ts +64 -0
  56. package/dist/components/layout/Container.svelte +36 -0
  57. package/dist/components/layout/Container.svelte.d.ts +37 -0
  58. package/dist/components/layout/Divider.svelte +45 -0
  59. package/dist/components/layout/Divider.svelte.d.ts +11 -0
  60. package/dist/components/layout/Footer.svelte +96 -0
  61. package/dist/components/layout/Footer.svelte.d.ts +10 -0
  62. package/dist/components/layout/Header.svelte +175 -0
  63. package/dist/components/layout/Header.svelte.d.ts +12 -0
  64. package/dist/components/layout/Section.svelte +62 -0
  65. package/dist/components/layout/Section.svelte.d.ts +14 -0
  66. package/dist/components/layout/YaxaApp.svelte +48 -0
  67. package/dist/components/layout/YaxaApp.svelte.d.ts +12 -0
  68. package/dist/components/navigation/Breadcrumb.svelte +58 -0
  69. package/dist/components/navigation/Breadcrumb.svelte.d.ts +13 -0
  70. package/dist/components/navigation/CommandPalette.svelte +201 -0
  71. package/dist/components/navigation/CommandPalette.svelte.d.ts +19 -0
  72. package/dist/components/navigation/DropdownMenu.svelte +75 -0
  73. package/dist/components/navigation/DropdownMenu.svelte.d.ts +20 -0
  74. package/dist/components/navigation/Pagination.svelte +106 -0
  75. package/dist/components/navigation/Pagination.svelte.d.ts +10 -0
  76. package/dist/components/navigation/Tabs.svelte +91 -0
  77. package/dist/components/navigation/Tabs.svelte.d.ts +18 -0
  78. package/dist/components/overlays/Accordion.svelte +54 -0
  79. package/dist/components/overlays/Accordion.svelte.d.ts +16 -0
  80. package/dist/components/overlays/Alert.svelte +110 -0
  81. package/dist/components/overlays/Alert.svelte.d.ts +37 -0
  82. package/dist/components/overlays/ContextMenu.svelte +67 -0
  83. package/dist/components/overlays/ContextMenu.svelte.d.ts +21 -0
  84. package/dist/components/overlays/Modal.svelte +99 -0
  85. package/dist/components/overlays/Modal.svelte.d.ts +40 -0
  86. package/dist/components/overlays/Popover.svelte +33 -0
  87. package/dist/components/overlays/Popover.svelte.d.ts +11 -0
  88. package/dist/components/overlays/Slideover.svelte +102 -0
  89. package/dist/components/overlays/Slideover.svelte.d.ts +37 -0
  90. package/dist/components/overlays/Tooltip.svelte +39 -0
  91. package/dist/components/overlays/Tooltip.svelte.d.ts +12 -0
  92. package/dist/components/saas/AuthCard.svelte +273 -0
  93. package/dist/components/saas/AuthCard.svelte.d.ts +16 -0
  94. package/dist/components/saas/PricingCard.svelte +166 -0
  95. package/dist/components/saas/PricingCard.svelte.d.ts +19 -0
  96. package/dist/components/saas/PricingTable.svelte +139 -0
  97. package/dist/components/saas/PricingTable.svelte.d.ts +11 -0
  98. package/dist/components/saas/SubscriptionCard.svelte +162 -0
  99. package/dist/components/saas/SubscriptionCard.svelte.d.ts +16 -0
  100. package/dist/components/saas/UserMenu.svelte +137 -0
  101. package/dist/components/saas/UserMenu.svelte.d.ts +19 -0
  102. package/dist/components/seo/Favicons.svelte +22 -0
  103. package/dist/components/seo/Favicons.svelte.d.ts +8 -0
  104. package/dist/components/seo/OgImage.svelte +61 -0
  105. package/dist/components/seo/OgImage.svelte.d.ts +12 -0
  106. package/dist/components/seo/Seo.svelte +170 -0
  107. package/dist/components/seo/Seo.svelte.d.ts +21 -0
  108. package/dist/composables/useAuth.svelte.d.ts +23 -0
  109. package/dist/composables/useAuth.svelte.js +157 -0
  110. package/dist/composables/useClipboard.svelte.d.ts +9 -0
  111. package/dist/composables/useClipboard.svelte.js +36 -0
  112. package/dist/composables/useColorMode.svelte.d.ts +8 -0
  113. package/dist/composables/useColorMode.svelte.js +20 -0
  114. package/dist/composables/useDebounce.svelte.d.ts +3 -0
  115. package/dist/composables/useDebounce.svelte.js +17 -0
  116. package/dist/composables/useMediaQuery.svelte.d.ts +3 -0
  117. package/dist/composables/useMediaQuery.svelte.js +17 -0
  118. package/dist/composables/useShortcuts.svelte.d.ts +10 -0
  119. package/dist/composables/useShortcuts.svelte.js +50 -0
  120. package/dist/composables/useToast.d.ts +19 -0
  121. package/dist/composables/useToast.js +34 -0
  122. package/dist/index.d.ts +101 -0
  123. package/dist/index.js +92 -0
  124. package/dist/server/auth/hook.d.ts +14 -0
  125. package/dist/server/auth/hook.js +36 -0
  126. package/dist/server/auth/index.d.ts +39 -0
  127. package/dist/server/auth/index.js +69 -0
  128. package/dist/server/db/index.d.ts +18 -0
  129. package/dist/server/db/index.js +43 -0
  130. package/dist/server/db/schema-pg.d.ts +977 -0
  131. package/dist/server/db/schema-pg.js +83 -0
  132. package/dist/server/db/schema-sqlite.d.ts +1045 -0
  133. package/dist/server/db/schema-sqlite.js +83 -0
  134. package/dist/server/db/types.d.ts +44 -0
  135. package/dist/server/db/types.js +1 -0
  136. package/dist/server/email/index.d.ts +27 -0
  137. package/dist/server/email/index.js +79 -0
  138. package/dist/server/polar/index.d.ts +29 -0
  139. package/dist/server/polar/index.js +49 -0
  140. package/dist/server/polar/webhook.d.ts +16 -0
  141. package/dist/server/polar/webhook.js +118 -0
  142. package/dist/site/config.d.ts +63 -0
  143. package/dist/site/config.js +48 -0
  144. package/dist/site/context.d.ts +11 -0
  145. package/dist/site/context.js +23 -0
  146. package/dist/site/hook.d.ts +15 -0
  147. package/dist/site/hook.js +38 -0
  148. package/dist/site/manifest.d.ts +6 -0
  149. package/dist/site/manifest.js +32 -0
  150. package/dist/site/og.d.ts +14 -0
  151. package/dist/site/og.js +116 -0
  152. package/dist/site/robots.d.ts +10 -0
  153. package/dist/site/robots.js +54 -0
  154. package/dist/site/schema.d.ts +67 -0
  155. package/dist/site/schema.js +67 -0
  156. package/dist/site/seo-helpers.d.ts +36 -0
  157. package/dist/site/seo-helpers.js +21 -0
  158. package/dist/site/sitemap-xsl.d.ts +6 -0
  159. package/dist/site/sitemap-xsl.js +164 -0
  160. package/dist/site/sitemap.d.ts +20 -0
  161. package/dist/site/sitemap.js +61 -0
  162. package/dist/styles/yaxa.css +84 -0
  163. package/dist/theme/theme.svelte.d.ts +74 -0
  164. package/dist/theme/theme.svelte.js +421 -0
  165. package/dist/utils/cn.d.ts +3 -0
  166. package/dist/utils/cn.js +3 -0
  167. package/dist/vite/index.d.ts +20 -0
  168. package/dist/vite/index.js +29 -0
  169. package/package.json +108 -0
@@ -0,0 +1,40 @@
1
+ import { type VariantProps } from '../../utils/cn';
2
+ import type { Snippet } from 'svelte';
3
+ export declare const modalVariants: import("tailwind-variants").TVReturnType<{
4
+ size: {
5
+ sm: "max-w-sm";
6
+ md: "max-w-lg";
7
+ lg: "max-w-2xl";
8
+ xl: "max-w-4xl";
9
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100vh-2rem)]";
10
+ };
11
+ }, undefined, "fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-neutral-200 bg-white p-6 shadow-2xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 dark:border-neutral-800 dark:bg-neutral-900", {
12
+ size: {
13
+ sm: "max-w-sm";
14
+ md: "max-w-lg";
15
+ lg: "max-w-2xl";
16
+ xl: "max-w-4xl";
17
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100vh-2rem)]";
18
+ };
19
+ }, undefined, import("tailwind-variants").TVReturnTypeLike<{
20
+ size: {
21
+ sm: "max-w-sm";
22
+ md: "max-w-lg";
23
+ lg: "max-w-2xl";
24
+ xl: "max-w-4xl";
25
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100vh-2rem)]";
26
+ };
27
+ }, undefined>>;
28
+ export type ModalProps = VariantProps<typeof modalVariants> & {
29
+ open?: boolean;
30
+ title?: string;
31
+ description?: string;
32
+ trigger?: Snippet;
33
+ header?: Snippet;
34
+ footer?: Snippet;
35
+ children?: Snippet;
36
+ class?: string;
37
+ };
38
+ declare const Modal: import("svelte").Component<ModalProps, {}, "open">;
39
+ type Modal = ReturnType<typeof Modal>;
40
+ export default Modal;
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import { Popover } from 'bits-ui';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ open?: boolean;
7
+ trigger?: Snippet;
8
+ children?: Snippet;
9
+ class?: string;
10
+ }
11
+
12
+ let { open = $bindable(false), trigger, children, class: className = '' }: Props = $props();
13
+ </script>
14
+
15
+ <Popover.Root bind:open>
16
+ {#if trigger}
17
+ <Popover.Trigger class="inline-flex">
18
+ {@render trigger()}
19
+ </Popover.Trigger>
20
+ {/if}
21
+
22
+ <Popover.Portal>
23
+ <Popover.Content
24
+ class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 z-50 rounded-xl border border-neutral-200 bg-white p-4 shadow-xl duration-150 outline-none dark:border-neutral-800 dark:bg-neutral-900 {className}"
25
+ sideOffset={8}
26
+ >
27
+ {#if children}
28
+ {@render children()}
29
+ {/if}
30
+ <Popover.Arrow class="fill-neutral-200 dark:fill-neutral-800" />
31
+ </Popover.Content>
32
+ </Popover.Portal>
33
+ </Popover.Root>
@@ -0,0 +1,11 @@
1
+ import { Popover } from 'bits-ui';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ open?: boolean;
5
+ trigger?: Snippet;
6
+ children?: Snippet;
7
+ class?: string;
8
+ }
9
+ declare const Popover: import("svelte").Component<Props, {}, "open">;
10
+ type Popover = ReturnType<typeof Popover>;
11
+ export default Popover;
@@ -0,0 +1,102 @@
1
+ <script module lang="ts">
2
+ import { tv, type VariantProps } from '../../utils/cn';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ export const slideoverVariants = tv({
6
+ base: 'fixed z-50 flex flex-col border-neutral-200 bg-white p-6 shadow-2xl transition-transform duration-300 dark:border-neutral-800 dark:bg-neutral-900',
7
+ variants: {
8
+ side: {
9
+ right:
10
+ 'inset-y-0 right-0 h-full w-full max-w-md border-l data-[state=closed]:translate-x-full data-[state=open]:translate-x-0',
11
+ left: 'inset-y-0 left-0 h-full w-full max-w-md border-r data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0',
12
+ top: 'inset-x-0 top-0 w-full max-h-[80vh] border-b data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0',
13
+ bottom:
14
+ 'inset-x-0 bottom-0 w-full max-h-[80vh] rounded-t-2xl border-t data-[state=closed]:translate-y-full data-[state=open]:translate-y-0'
15
+ }
16
+ },
17
+ defaultVariants: {
18
+ side: 'right'
19
+ }
20
+ });
21
+
22
+ export type SlideoverProps = VariantProps<typeof slideoverVariants> & {
23
+ open?: boolean;
24
+ title?: string;
25
+ description?: string;
26
+ trigger?: Snippet;
27
+ header?: Snippet;
28
+ footer?: Snippet;
29
+ children?: Snippet;
30
+ class?: string;
31
+ };
32
+ </script>
33
+
34
+ <script lang="ts">
35
+ import { Dialog } from 'bits-ui';
36
+ import Icon from '../elements/Icon.svelte';
37
+
38
+ let {
39
+ open = $bindable(false),
40
+ side = 'right',
41
+ title,
42
+ description,
43
+ trigger,
44
+ header,
45
+ footer,
46
+ children,
47
+ class: className = ''
48
+ }: SlideoverProps = $props();
49
+ </script>
50
+
51
+ <Dialog.Root bind:open>
52
+ {#if trigger}
53
+ <Dialog.Trigger class="inline-flex">
54
+ {@render trigger()}
55
+ </Dialog.Trigger>
56
+ {/if}
57
+
58
+ <Dialog.Portal>
59
+ <Dialog.Overlay
60
+ class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-neutral-900/60 backdrop-blur-xs duration-300"
61
+ />
62
+ <Dialog.Content class={slideoverVariants({ side, class: className })}>
63
+ {#if header}
64
+ {@render header()}
65
+ {:else if title || description}
66
+ <div class="mb-4">
67
+ {#if title}
68
+ <Dialog.Title class="text-lg font-bold text-neutral-900 dark:text-white">
69
+ {title}
70
+ </Dialog.Title>
71
+ {/if}
72
+ {#if description}
73
+ <Dialog.Description class="mt-1 text-sm text-neutral-500 dark:text-neutral-400">
74
+ {description}
75
+ </Dialog.Description>
76
+ {/if}
77
+ </div>
78
+ {/if}
79
+
80
+ {#if children}
81
+ <div class="my-2 flex-1 overflow-y-auto">
82
+ {@render children()}
83
+ </div>
84
+ {/if}
85
+
86
+ {#if footer}
87
+ <div
88
+ class="mt-6 flex justify-end gap-3 border-t border-neutral-100 pt-4 dark:border-neutral-800"
89
+ >
90
+ {@render footer()}
91
+ </div>
92
+ {/if}
93
+
94
+ <Dialog.Close
95
+ class="absolute top-4 right-4 rounded-lg p-1 text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600 dark:hover:bg-neutral-800 dark:hover:text-neutral-200"
96
+ aria-label="Close slideover"
97
+ >
98
+ <Icon name="cross" size="sm" />
99
+ </Dialog.Close>
100
+ </Dialog.Content>
101
+ </Dialog.Portal>
102
+ </Dialog.Root>
@@ -0,0 +1,37 @@
1
+ import { type VariantProps } from '../../utils/cn';
2
+ import type { Snippet } from 'svelte';
3
+ export declare const slideoverVariants: import("tailwind-variants").TVReturnType<{
4
+ side: {
5
+ right: "inset-y-0 right-0 h-full w-full max-w-md border-l data-[state=closed]:translate-x-full data-[state=open]:translate-x-0";
6
+ left: "inset-y-0 left-0 h-full w-full max-w-md border-r data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0";
7
+ top: "inset-x-0 top-0 w-full max-h-[80vh] border-b data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0";
8
+ bottom: "inset-x-0 bottom-0 w-full max-h-[80vh] rounded-t-2xl border-t data-[state=closed]:translate-y-full data-[state=open]:translate-y-0";
9
+ };
10
+ }, undefined, "fixed z-50 flex flex-col border-neutral-200 bg-white p-6 shadow-2xl transition-transform duration-300 dark:border-neutral-800 dark:bg-neutral-900", {
11
+ side: {
12
+ right: "inset-y-0 right-0 h-full w-full max-w-md border-l data-[state=closed]:translate-x-full data-[state=open]:translate-x-0";
13
+ left: "inset-y-0 left-0 h-full w-full max-w-md border-r data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0";
14
+ top: "inset-x-0 top-0 w-full max-h-[80vh] border-b data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0";
15
+ bottom: "inset-x-0 bottom-0 w-full max-h-[80vh] rounded-t-2xl border-t data-[state=closed]:translate-y-full data-[state=open]:translate-y-0";
16
+ };
17
+ }, undefined, import("tailwind-variants").TVReturnTypeLike<{
18
+ side: {
19
+ right: "inset-y-0 right-0 h-full w-full max-w-md border-l data-[state=closed]:translate-x-full data-[state=open]:translate-x-0";
20
+ left: "inset-y-0 left-0 h-full w-full max-w-md border-r data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0";
21
+ top: "inset-x-0 top-0 w-full max-h-[80vh] border-b data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0";
22
+ bottom: "inset-x-0 bottom-0 w-full max-h-[80vh] rounded-t-2xl border-t data-[state=closed]:translate-y-full data-[state=open]:translate-y-0";
23
+ };
24
+ }, undefined>>;
25
+ export type SlideoverProps = VariantProps<typeof slideoverVariants> & {
26
+ open?: boolean;
27
+ title?: string;
28
+ description?: string;
29
+ trigger?: Snippet;
30
+ header?: Snippet;
31
+ footer?: Snippet;
32
+ children?: Snippet;
33
+ class?: string;
34
+ };
35
+ declare const Slideover: import("svelte").Component<SlideoverProps, {}, "open">;
36
+ type Slideover = ReturnType<typeof Slideover>;
37
+ export default Slideover;
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import { Tooltip } from 'bits-ui';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ text?: string;
7
+ side?: 'top' | 'right' | 'bottom' | 'left';
8
+ trigger?: Snippet;
9
+ content?: Snippet;
10
+ children?: Snippet;
11
+ }
12
+
13
+ let { text, side = 'top', trigger, content, children }: Props = $props();
14
+ </script>
15
+
16
+ <Tooltip.Root>
17
+ <Tooltip.Trigger class="inline-flex">
18
+ {#if trigger}
19
+ {@render trigger()}
20
+ {:else if children}
21
+ {@render children()}
22
+ {/if}
23
+ </Tooltip.Trigger>
24
+
25
+ <Tooltip.Portal>
26
+ <Tooltip.Content
27
+ {side}
28
+ sideOffset={6}
29
+ class="animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 z-50 overflow-hidden rounded-md bg-neutral-900 px-3 py-1.5 text-sm font-medium text-white shadow-md dark:bg-neutral-100 dark:text-neutral-900"
30
+ >
31
+ {#if content}
32
+ {@render content()}
33
+ {:else if text}
34
+ {text}
35
+ {/if}
36
+ <Tooltip.Arrow class="fill-neutral-900 dark:fill-neutral-100" />
37
+ </Tooltip.Content>
38
+ </Tooltip.Portal>
39
+ </Tooltip.Root>
@@ -0,0 +1,12 @@
1
+ import { Tooltip } from 'bits-ui';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ text?: string;
5
+ side?: 'top' | 'right' | 'bottom' | 'left';
6
+ trigger?: Snippet;
7
+ content?: Snippet;
8
+ children?: Snippet;
9
+ }
10
+ declare const Tooltip: import("svelte").Component<Props, {}, "">;
11
+ type Tooltip = ReturnType<typeof Tooltip>;
12
+ export default Tooltip;
@@ -0,0 +1,273 @@
1
+ <script lang="ts">
2
+ import Card from '../layout/Card.svelte';
3
+ import Button from '../elements/Button.svelte';
4
+ import Input from '../forms/Input.svelte';
5
+ import FormField from '../forms/FormField.svelte';
6
+ import Divider from '../layout/Divider.svelte';
7
+ import Alert from '../overlays/Alert.svelte';
8
+ import Icon from '../elements/Icon.svelte';
9
+ import { useAuth, type SocialProvider } from '../../composables/useAuth.svelte';
10
+
11
+ interface Props {
12
+ title?: string;
13
+ subtitle?: string;
14
+ mode?: 'signin' | 'signup' | 'magic-link';
15
+ providers?: SocialProvider[];
16
+ showSocial?: boolean;
17
+ showMagicLinkToggle?: boolean;
18
+ callbackURL?: string;
19
+ class?: string;
20
+ onsuccess?: () => void;
21
+ onerror?: (err: string) => void;
22
+ }
23
+
24
+ let {
25
+ title,
26
+ subtitle,
27
+ mode = 'signin',
28
+ providers = ['github', 'google'],
29
+ showSocial = true,
30
+ showMagicLinkToggle = true,
31
+ callbackURL = '/dashboard',
32
+ class: className = '',
33
+ onsuccess,
34
+ onerror
35
+ }: Props = $props();
36
+
37
+ const auth = useAuth();
38
+
39
+ let customMode = $state<'signin' | 'signup' | 'magic-link' | null>(null);
40
+ let currentMode = $derived(customMode ?? mode);
41
+
42
+ let name = $state('');
43
+ let email = $state('');
44
+ let password = $state('');
45
+ let localError = $state<string | null>(null);
46
+ let magicLinkSent = $state(false);
47
+
48
+ async function handleSocial(provider: SocialProvider) {
49
+ localError = null;
50
+ await auth.signInWithSocial(provider);
51
+ }
52
+
53
+ async function handleSubmit(e: SubmitEvent) {
54
+ e.preventDefault();
55
+ localError = null;
56
+
57
+ if (currentMode === 'magic-link') {
58
+ const ok = await auth.signInWithMagicLink(email);
59
+ if (ok) {
60
+ magicLinkSent = true;
61
+ if (onsuccess) onsuccess();
62
+ } else {
63
+ localError = auth.error || 'Failed to send magic link';
64
+ if (onerror) onerror(localError);
65
+ }
66
+ return;
67
+ }
68
+
69
+ if (currentMode === 'signup') {
70
+ const ok = await auth.signUpWithEmail(email, password, name);
71
+ if (ok) {
72
+ if (onsuccess) onsuccess();
73
+ if (typeof window !== 'undefined') window.location.href = callbackURL;
74
+ } else {
75
+ localError = auth.error || 'Could not create account';
76
+ if (onerror) onerror(localError);
77
+ }
78
+ return;
79
+ }
80
+
81
+ // Sign In mode
82
+ const ok = await auth.signInWithEmail(email, password);
83
+ if (ok) {
84
+ if (onsuccess) onsuccess();
85
+ if (typeof window !== 'undefined') window.location.href = callbackURL;
86
+ } else {
87
+ localError = auth.error || 'Invalid email or password';
88
+ if (onerror) onerror(localError);
89
+ }
90
+ }
91
+ </script>
92
+
93
+ <Card
94
+ class="mx-auto w-full max-w-md space-y-6 border-zinc-200 p-6 shadow-xl sm:p-8 dark:border-zinc-800 {className}"
95
+ >
96
+ <!-- Header -->
97
+ <div class="space-y-1.5 text-center">
98
+ <h2 class="text-2xl font-bold tracking-tight text-zinc-900 dark:text-zinc-50">
99
+ {#if title}
100
+ {title}
101
+ {:else if currentMode === 'signup'}
102
+ Create an account
103
+ {:else if currentMode === 'magic-link'}
104
+ Sign in with Magic Link
105
+ {:else}
106
+ Welcome back
107
+ {/if}
108
+ </h2>
109
+ <p class="text-sm text-zinc-500 dark:text-zinc-400">
110
+ {#if subtitle}
111
+ {subtitle}
112
+ {:else if currentMode === 'signup'}
113
+ Start your 14-day free trial, no credit card required.
114
+ {:else if currentMode === 'magic-link'}
115
+ We will email you a passwordless sign-in link.
116
+ {:else}
117
+ Sign in to access your dashboard and workspace.
118
+ {/if}
119
+ </p>
120
+ </div>
121
+
122
+ <!-- Error Alert -->
123
+ {#if localError || auth.error}
124
+ <Alert
125
+ color="error"
126
+ title="Authentication Error"
127
+ description={localError || auth.error || ''}
128
+ />
129
+ {/if}
130
+
131
+ <!-- Magic Link Success State -->
132
+ {#if magicLinkSent}
133
+ <div
134
+ class="space-y-2 rounded-xl border border-emerald-500/20 bg-emerald-50/50 p-5 text-center dark:bg-emerald-950/20"
135
+ >
136
+ <div class="flex justify-center text-emerald-600 dark:text-emerald-400">
137
+ <Icon name="check" class="h-8 w-8" />
138
+ </div>
139
+ <h3 class="font-semibold text-zinc-900 dark:text-zinc-100">Check your email</h3>
140
+ <p class="text-sm text-zinc-600 dark:text-zinc-400">
141
+ We've sent a magic link to <strong class="text-zinc-900 dark:text-zinc-100">{email}</strong
142
+ >.
143
+ </p>
144
+ <Button
145
+ variant="ghost"
146
+ size="sm"
147
+ class="mt-2 text-xs"
148
+ onclick={() => {
149
+ magicLinkSent = false;
150
+ }}
151
+ >
152
+ Use a different method
153
+ </Button>
154
+ </div>
155
+ {:else}
156
+ <!-- Social Login Buttons -->
157
+ {#if showSocial && providers.length > 0}
158
+ <div class="grid grid-cols-1 gap-2.5 sm:grid-cols-2">
159
+ {#each providers as provider}
160
+ <Button
161
+ variant="outline"
162
+ class="w-full justify-center gap-2 font-medium"
163
+ loading={auth.isLoading}
164
+ onclick={() => handleSocial(provider)}
165
+ >
166
+ {#if provider === 'github'}
167
+ <Icon name="github" class="h-4 w-4" />
168
+ <span>GitHub</span>
169
+ {:else if provider === 'google'}
170
+ <Icon name="external-link" class="h-4 w-4" />
171
+ <span>Google</span>
172
+ {:else}
173
+ <span>{provider}</span>
174
+ {/if}
175
+ </Button>
176
+ {/each}
177
+ </div>
178
+
179
+ <Divider label="or continue with" />
180
+ {/if}
181
+
182
+ <!-- Email Form -->
183
+ <form onsubmit={handleSubmit} class="space-y-4">
184
+ {#if currentMode === 'signup'}
185
+ <FormField label="Full Name" required>
186
+ <Input type="text" placeholder="Alex Johnson" bind:value={name} required />
187
+ </FormField>
188
+ {/if}
189
+
190
+ <FormField label="Email address" required>
191
+ <Input type="email" placeholder="name@company.com" bind:value={email} required />
192
+ </FormField>
193
+
194
+ {#if currentMode !== 'magic-link'}
195
+ <FormField label="Password" required>
196
+ <Input type="password" placeholder="••••••••" bind:value={password} required />
197
+ </FormField>
198
+ {/if}
199
+
200
+ <Button
201
+ type="submit"
202
+ variant="solid"
203
+ color="primary"
204
+ class="w-full justify-center font-semibold shadow-md"
205
+ loading={auth.isLoading}
206
+ >
207
+ {#if currentMode === 'signup'}
208
+ Create Account
209
+ {:else if currentMode === 'magic-link'}
210
+ Send Magic Link
211
+ {:else}
212
+ Sign In
213
+ {/if}
214
+ </Button>
215
+ </form>
216
+
217
+ <!-- Mode Switchers -->
218
+ <div class="flex flex-col items-center gap-2 pt-2 text-xs text-zinc-500 dark:text-zinc-400">
219
+ {#if currentMode === 'signin'}
220
+ <div>
221
+ Don't have an account?
222
+ <button
223
+ type="button"
224
+ class="font-semibold text-primary-600 hover:underline dark:text-primary-400"
225
+ onclick={() => {
226
+ customMode = 'signup';
227
+ localError = null;
228
+ }}
229
+ >
230
+ Sign up
231
+ </button>
232
+ </div>
233
+ {#if showMagicLinkToggle}
234
+ <button
235
+ type="button"
236
+ class="text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200"
237
+ onclick={() => {
238
+ customMode = 'magic-link';
239
+ localError = null;
240
+ }}
241
+ >
242
+ Sign in with a passwordless magic link
243
+ </button>
244
+ {/if}
245
+ {:else if currentMode === 'signup'}
246
+ <div>
247
+ Already have an account?
248
+ <button
249
+ type="button"
250
+ class="font-semibold text-primary-600 hover:underline dark:text-primary-400"
251
+ onclick={() => {
252
+ customMode = 'signin';
253
+ localError = null;
254
+ }}
255
+ >
256
+ Sign in
257
+ </button>
258
+ </div>
259
+ {:else}
260
+ <button
261
+ type="button"
262
+ class="font-semibold text-primary-600 hover:underline dark:text-primary-400"
263
+ onclick={() => {
264
+ customMode = 'signin';
265
+ localError = null;
266
+ }}
267
+ >
268
+ ← Back to email and password sign in
269
+ </button>
270
+ {/if}
271
+ </div>
272
+ {/if}
273
+ </Card>
@@ -0,0 +1,16 @@
1
+ import { type SocialProvider } from '../../composables/useAuth.svelte';
2
+ interface Props {
3
+ title?: string;
4
+ subtitle?: string;
5
+ mode?: 'signin' | 'signup' | 'magic-link';
6
+ providers?: SocialProvider[];
7
+ showSocial?: boolean;
8
+ showMagicLinkToggle?: boolean;
9
+ callbackURL?: string;
10
+ class?: string;
11
+ onsuccess?: () => void;
12
+ onerror?: (err: string) => void;
13
+ }
14
+ declare const AuthCard: import("svelte").Component<Props, {}, "">;
15
+ type AuthCard = ReturnType<typeof AuthCard>;
16
+ export default AuthCard;