@realtimex/email-automator 2.2.0 → 2.2.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 (48) hide show
  1. package/api/server.ts +0 -6
  2. package/api/src/config/index.ts +3 -0
  3. package/bin/email-automator-setup.js +2 -3
  4. package/bin/email-automator.js +23 -7
  5. package/package.json +1 -2
  6. package/src/App.tsx +0 -622
  7. package/src/components/AccountSettings.tsx +0 -310
  8. package/src/components/AccountSettingsPage.tsx +0 -390
  9. package/src/components/Configuration.tsx +0 -1345
  10. package/src/components/Dashboard.tsx +0 -940
  11. package/src/components/ErrorBoundary.tsx +0 -71
  12. package/src/components/LiveTerminal.tsx +0 -308
  13. package/src/components/LoadingSpinner.tsx +0 -39
  14. package/src/components/Login.tsx +0 -371
  15. package/src/components/Logo.tsx +0 -57
  16. package/src/components/SetupWizard.tsx +0 -388
  17. package/src/components/Toast.tsx +0 -109
  18. package/src/components/migration/MigrationBanner.tsx +0 -97
  19. package/src/components/migration/MigrationModal.tsx +0 -458
  20. package/src/components/migration/MigrationPulseIndicator.tsx +0 -38
  21. package/src/components/mode-toggle.tsx +0 -24
  22. package/src/components/theme-provider.tsx +0 -72
  23. package/src/components/ui/alert.tsx +0 -66
  24. package/src/components/ui/button.tsx +0 -57
  25. package/src/components/ui/card.tsx +0 -75
  26. package/src/components/ui/dialog.tsx +0 -133
  27. package/src/components/ui/input.tsx +0 -22
  28. package/src/components/ui/label.tsx +0 -24
  29. package/src/components/ui/otp-input.tsx +0 -184
  30. package/src/context/AppContext.tsx +0 -422
  31. package/src/context/MigrationContext.tsx +0 -53
  32. package/src/context/TerminalContext.tsx +0 -31
  33. package/src/core/actions.ts +0 -76
  34. package/src/core/auth.ts +0 -108
  35. package/src/core/intelligence.ts +0 -76
  36. package/src/core/processor.ts +0 -112
  37. package/src/hooks/useRealtimeEmails.ts +0 -111
  38. package/src/index.css +0 -140
  39. package/src/lib/api-config.ts +0 -42
  40. package/src/lib/api-old.ts +0 -228
  41. package/src/lib/api.ts +0 -421
  42. package/src/lib/migration-check.ts +0 -264
  43. package/src/lib/sounds.ts +0 -120
  44. package/src/lib/supabase-config.ts +0 -117
  45. package/src/lib/supabase.ts +0 -28
  46. package/src/lib/types.ts +0 -166
  47. package/src/lib/utils.ts +0 -6
  48. package/src/main.tsx +0 -10
@@ -1,57 +0,0 @@
1
- import * as React from "react"
2
- import { Slot } from "@radix-ui/react-slot"
3
- import { cva, type VariantProps } from "class-variance-authority"
4
-
5
- import { cn } from "../../lib/utils"
6
-
7
- const buttonVariants = cva(
8
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0",
9
- {
10
- variants: {
11
- variant: {
12
- default:
13
- "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
14
- destructive:
15
- "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
16
- outline:
17
- "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
18
- secondary:
19
- "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
20
- ghost: "hover:bg-accent hover:text-accent-foreground",
21
- link: "text-primary underline-offset-4 hover:underline",
22
- },
23
- size: {
24
- default: "h-9 px-4 py-2",
25
- sm: "h-8 rounded-md px-3 text-xs",
26
- lg: "h-10 rounded-md px-8",
27
- icon: "h-9 w-9",
28
- },
29
- },
30
- defaultVariants: {
31
- variant: "default",
32
- size: "default",
33
- },
34
- }
35
- )
36
-
37
- export interface ButtonProps
38
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39
- VariantProps<typeof buttonVariants> {
40
- asChild?: boolean
41
- }
42
-
43
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
44
- ({ className, variant, size, asChild = false, ...props }, ref) => {
45
- const Comp = asChild ? Slot : "button"
46
- return (
47
- <Comp
48
- className={cn(buttonVariants({ variant, size, className }))}
49
- ref={ref}
50
- {...props}
51
- />
52
- )
53
- }
54
- )
55
- Button.displayName = "Button"
56
-
57
- export { Button, buttonVariants }
@@ -1,75 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "../../lib/utils"
3
-
4
- const Card = React.forwardRef<
5
- HTMLDivElement,
6
- React.HTMLAttributes<HTMLDivElement>
7
- >(({ className, ...props }, ref) => (
8
- <div
9
- ref={ref}
10
- className={cn(
11
- "rounded-xl border bg-card text-card-foreground shadow",
12
- className
13
- )}
14
- {...props}
15
- />
16
- ))
17
- Card.displayName = "Card"
18
-
19
- const CardHeader = React.forwardRef<
20
- HTMLDivElement,
21
- React.HTMLAttributes<HTMLDivElement>
22
- >(({ className, ...props }, ref) => (
23
- <div
24
- ref={ref}
25
- className={cn("flex flex-col space-y-1.5 p-6", className)}
26
- {...props}
27
- />
28
- ))
29
- CardHeader.displayName = "CardHeader"
30
-
31
- const CardTitle = React.forwardRef<
32
- HTMLDivElement,
33
- React.HTMLAttributes<HTMLDivElement>
34
- >(({ className, ...props }, ref) => (
35
- <div
36
- ref={ref}
37
- className={cn("font-semibold leading-none tracking-tight", className)}
38
- {...props}
39
- />
40
- ))
41
- CardTitle.displayName = "CardTitle"
42
-
43
- const CardDescription = React.forwardRef<
44
- HTMLDivElement,
45
- React.HTMLAttributes<HTMLDivElement>
46
- >(({ className, ...props }, ref) => (
47
- <div
48
- ref={ref}
49
- className={cn("text-sm text-muted-foreground", className)}
50
- {...props}
51
- />
52
- ))
53
- CardDescription.displayName = "CardDescription"
54
-
55
- const CardContent = React.forwardRef<
56
- HTMLDivElement,
57
- React.HTMLAttributes<HTMLDivElement>
58
- >(({ className, ...props }, ref) => (
59
- <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
60
- ))
61
- CardContent.displayName = "CardContent"
62
-
63
- const CardFooter = React.forwardRef<
64
- HTMLDivElement,
65
- React.HTMLAttributes<HTMLDivElement>
66
- >(({ className, ...props }, ref) => (
67
- <div
68
- ref={ref}
69
- className={cn("flex items-center p-6 pt-0", className)}
70
- {...props}
71
- />
72
- ))
73
- CardFooter.displayName = "CardFooter"
74
-
75
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
@@ -1,133 +0,0 @@
1
- import * as React from "react"
2
- import * as DialogPrimitive from "@radix-ui/react-dialog"
3
- import { XIcon } from "lucide-react"
4
-
5
- import { cn } from "@/lib/utils"
6
-
7
- function Dialog({
8
- ...props
9
- }: React.ComponentProps<typeof DialogPrimitive.Root>) {
10
- return <DialogPrimitive.Root data-slot="dialog" {...props} />
11
- }
12
-
13
- function DialogTrigger({
14
- ...props
15
- }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
16
- return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
17
- }
18
-
19
- function DialogPortal({
20
- ...props
21
- }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
22
- return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
23
- }
24
-
25
- function DialogClose({
26
- ...props
27
- }: React.ComponentProps<typeof DialogPrimitive.Close>) {
28
- return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
29
- }
30
-
31
- function DialogOverlay({
32
- className,
33
- ...props
34
- }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
35
- return (
36
- <DialogPrimitive.Overlay
37
- data-slot="dialog-overlay"
38
- className={cn(
39
- "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-black/50",
40
- className
41
- )}
42
- {...props}
43
- />
44
- )
45
- }
46
-
47
- function DialogContent({
48
- className,
49
- children,
50
- ...props
51
- }: React.ComponentProps<typeof DialogPrimitive.Content>) {
52
- return (
53
- <DialogPortal data-slot="dialog-portal">
54
- <DialogOverlay />
55
- <DialogPrimitive.Content
56
- data-slot="dialog-content"
57
- className={cn(
58
- "bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
59
- className
60
- )}
61
- {...props}
62
- >
63
- {children}
64
- <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
65
- <XIcon />
66
- <span className="sr-only">Close</span>
67
- </DialogPrimitive.Close>
68
- </DialogPrimitive.Content>
69
- </DialogPortal>
70
- )
71
- }
72
-
73
- function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
74
- return (
75
- <div
76
- data-slot="dialog-header"
77
- className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
78
- {...props}
79
- />
80
- )
81
- }
82
-
83
- function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
84
- return (
85
- <div
86
- data-slot="dialog-footer"
87
- className={cn(
88
- "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
89
- className
90
- )}
91
- {...props}
92
- />
93
- )
94
- }
95
-
96
- function DialogTitle({
97
- className,
98
- ...props
99
- }: React.ComponentProps<typeof DialogPrimitive.Title>) {
100
- return (
101
- <DialogPrimitive.Title
102
- data-slot="dialog-title"
103
- className={cn("text-lg leading-none font-semibold", className)}
104
- {...props}
105
- />
106
- )
107
- }
108
-
109
- function DialogDescription({
110
- className,
111
- ...props
112
- }: React.ComponentProps<typeof DialogPrimitive.Description>) {
113
- return (
114
- <DialogPrimitive.Description
115
- data-slot="dialog-description"
116
- className={cn("text-muted-foreground text-sm", className)}
117
- {...props}
118
- />
119
- )
120
- }
121
-
122
- export {
123
- Dialog,
124
- DialogClose,
125
- DialogContent,
126
- DialogDescription,
127
- DialogFooter,
128
- DialogHeader,
129
- DialogOverlay,
130
- DialogPortal,
131
- DialogTitle,
132
- DialogTrigger,
133
- }
@@ -1,22 +0,0 @@
1
- import * as React from "react"
2
-
3
- import { cn } from "../../lib/utils"
4
-
5
- const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
6
- ({ className, type, ...props }, ref) => {
7
- return (
8
- <input
9
- type={type}
10
- className={cn(
11
- "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
- className
13
- )}
14
- ref={ref}
15
- {...props}
16
- />
17
- )
18
- }
19
- )
20
- Input.displayName = "Input"
21
-
22
- export { Input }
@@ -1,24 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as LabelPrimitive from "@radix-ui/react-label"
5
-
6
- import { cn } from "@/lib/utils"
7
-
8
- function Label({
9
- className,
10
- ...props
11
- }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12
- return (
13
- <LabelPrimitive.Root
14
- data-slot="label"
15
- className={cn(
16
- "flex items-center gap-2 text-sm leading-none font-medium select-none text-muted-foreground group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
17
- className
18
- )}
19
- {...props}
20
- />
21
- )
22
- }
23
-
24
- export { Label }
@@ -1,184 +0,0 @@
1
- import { useRef, useState, KeyboardEvent, ClipboardEvent } from "react";
2
- import { Input } from "./input";
3
- import { cn } from "../../lib/utils";
4
-
5
- interface OtpInputProps {
6
- length?: number;
7
- value: string;
8
- onChange: (value: string) => void;
9
- onComplete?: (value: string) => void;
10
- disabled?: boolean;
11
- error?: boolean;
12
- }
13
-
14
- export function OtpInput({
15
- length = 6,
16
- value,
17
- onChange,
18
- onComplete,
19
- disabled = false,
20
- error = false,
21
- }: OtpInputProps) {
22
- const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
23
- const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
24
-
25
- const handleChange = (index: number, inputValue: string) => {
26
- // Only allow digits
27
- const digit = inputValue.replace(/[^0-9]/g, "");
28
-
29
- if (digit.length === 0) {
30
- // Handle backspace/delete
31
- const newValue = value.split("");
32
- newValue[index] = " "; // Use space as placeholder to maintain length if needed, or better logic below
33
- // Actually, split("") of string length N gives N chars.
34
- // If we want to clear index, we should rebuild string carefully.
35
-
36
- // Better approach for fixed length string representation:
37
- // We can't easily mutate string directly.
38
- // Let's assume value is a string of digits, potentially shorter than length?
39
- // No, usually value is just the current OTP string.
40
-
41
- const newChars = value.split("");
42
- // Pad if needed? No, value might be "12" for length 6.
43
- // But we map over length.
44
-
45
- // Let's follow the atomic-crm logic logic carefully or improve it.
46
- // atomic-crm logic:
47
- // newValue[index] = "";
48
- // updatedValue = newValue.join("");
49
- // This reduces length if value was "123" and we clear index 1 -> "13".
50
- // This shifts subsequent digits left, which is standard backspace behavior for text input,
51
- // but typical OTP inputs usually clear the digit IN PLACE.
52
- // However, seeing atomic-crm implementation:
53
- /*
54
- const newValue = value.split("");
55
- newValue[index] = "";
56
- const updatedValue = newValue.join("");
57
- */
58
- // This effectively DELETES the char at index.
59
-
60
- // Let's stick to the ported code exactly to match expectations.
61
- // However, I need to make sure 'value' passed in handles getting shorter.
62
-
63
- let valArray = value.split('');
64
- if (index < valArray.length) {
65
- valArray.splice(index, 1); // Remove char at index
66
- }
67
- const updatedValue = valArray.join('');
68
-
69
- onChange(updatedValue);
70
-
71
- // Move to previous input
72
- if (index > 0) {
73
- inputRefs.current[index - 1]?.focus();
74
- }
75
- return;
76
- }
77
-
78
- // Update the value at the current index
79
- // If we are typing in an empty slot (index >= value.length), append?
80
- // If we are typing in existing slot, replace?
81
-
82
- // atomic-crm logic:
83
- /*
84
- const newValue = value.split("");
85
- newValue[index] = digit[0];
86
- const updatedValue = newValue.join("");
87
- */
88
- // This implies value has length equal to inputs? Or at least up to index?
89
- // If value is "1", and I type in box 2 (index 1), newValue[1] = digit.
90
- // "1" split is ["1"]. newValue[1] = "2" -> ["1", "2"]. Join -> "12". Works.
91
-
92
- // But if I click box 3 with value "1", index is 2. newValue[2] = "3". -> ["1", undefined, "3"].
93
- // Join might be "13" or "1undefined3".
94
-
95
- // Let's write robust logic.
96
- const chars = value.split('');
97
- // Fill gaps if jumping ahead? Usually OTP fields auto-focus next.
98
- // But if user clicks manualy...
99
- // Let's just assume we append if index >= length
100
-
101
- // Actually, sticking to exact atomic-crm port is safest if we trust it works there.
102
- // The provided code was:
103
- /*
104
- const newValue = value.split("");
105
- newValue[index] = digit[0];
106
- const updatedValue = newValue.join("");
107
- */
108
-
109
- // I will use a slightly more robust version that ensures we don't get holes if possible,
110
- // or just trust the array manipulation.
111
-
112
- const newChars = [...value]; // split
113
- newChars[index] = digit[0];
114
- onChange(newChars.join(""));
115
-
116
- // Move to next input if not the last one
117
- if (index < length - 1) {
118
- inputRefs.current[index + 1]?.focus();
119
- }
120
-
121
- // Check if OTP is complete
122
- const resultingStr = newChars.join("");
123
- if (resultingStr.length === length && onComplete) {
124
- onComplete(resultingStr);
125
- }
126
- };
127
-
128
- const handleKeyDown = (index: number, e: KeyboardEvent<HTMLInputElement>) => {
129
- if (e.key === "Backspace" && !value[index] && index > 0) {
130
- // If current input is empty and backspace is pressed, move to previous
131
- inputRefs.current[index - 1]?.focus();
132
- } else if (e.key === "ArrowLeft" && index > 0) {
133
- inputRefs.current[index - 1]?.focus();
134
- } else if (e.key === "ArrowRight" && index < length - 1) {
135
- inputRefs.current[index + 1]?.focus();
136
- }
137
- };
138
-
139
- const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {
140
- e.preventDefault();
141
- const pastedData = e.clipboardData.getData("text/plain");
142
- const digits = pastedData.replace(/[^0-9]/g, "").slice(0, length);
143
-
144
- onChange(digits);
145
-
146
- // Focus the next empty input or the last input
147
- const nextIndex = Math.min(digits.length, length - 1);
148
- inputRefs.current[nextIndex]?.focus();
149
-
150
- // Check if OTP is complete
151
- if (digits.length === length && onComplete) {
152
- onComplete(digits);
153
- }
154
- };
155
-
156
- return (
157
- <div className="flex gap-2 justify-center">
158
- {Array.from({ length }).map((_, index) => (
159
- <Input
160
- key={index}
161
- ref={(el) => {
162
- inputRefs.current[index] = el;
163
- }}
164
- type="text"
165
- inputMode="numeric"
166
- maxLength={1}
167
- value={value[index] || ""}
168
- onChange={(e) => handleChange(index, e.target.value)}
169
- onKeyDown={(e) => handleKeyDown(index, e)}
170
- onPaste={handlePaste}
171
- onFocus={() => setFocusedIndex(index)}
172
- onBlur={() => setFocusedIndex(null)}
173
- disabled={disabled}
174
- className={cn(
175
- "w-10 h-10 sm:w-12 sm:h-12 text-center text-lg font-semibold px-0",
176
- error && "border-destructive focus-visible:ring-destructive",
177
- focusedIndex === index && "ring-2 ring-ring",
178
- )}
179
- aria-label={`Digit ${index + 1}`}
180
- />
181
- ))}
182
- </div>
183
- );
184
- }