@sampleapp.ai/sdk 1.0.24 → 1.0.25

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.
@@ -0,0 +1,144 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import React from "react";
14
+ import { useState, useEffect, useRef, forwardRef } from "react";
15
+ import { motion, AnimatePresence } from "framer-motion";
16
+ import { Textarea } from "../ui/textarea";
17
+ export const TypingTextarea = forwardRef((_a, ref) => {
18
+ var { texts, typingSpeed = 30, deletingSpeed = 15, delayAfterText = 800, onSubmit, isStreaming = false, className = "", placeholderClassName = "", value, onChange, onFocus, onBlur, onKeyDown, onPaste, placeholder: originalPlaceholder, rows = 1 } = _a, props = __rest(_a, ["texts", "typingSpeed", "deletingSpeed", "delayAfterText", "onSubmit", "isStreaming", "className", "placeholderClassName", "value", "onChange", "onFocus", "onBlur", "onKeyDown", "onPaste", "placeholder", "rows"]);
19
+ const [displayText, setDisplayText] = useState("");
20
+ const [isDeleting, setIsDeleting] = useState(false);
21
+ const [textIndex, setTextIndex] = useState(0);
22
+ const [isWaiting, setIsWaiting] = useState(false);
23
+ const [showTabHint, setShowTabHint] = useState(false);
24
+ const [isPausing, setIsPausing] = useState(false);
25
+ const localRef = useRef(null);
26
+ const textareaRef = ref || localRef;
27
+ const currentText = texts[textIndex];
28
+ const isEmpty = value === "" || value === undefined;
29
+ // const isFullTextDisplayed = displayText === currentText && !isDeleting;
30
+ // Handle animation only when textarea is empty
31
+ useEffect(() => {
32
+ if (!isEmpty)
33
+ return;
34
+ let timeout;
35
+ if (isWaiting) {
36
+ timeout = setTimeout(() => {
37
+ setIsWaiting(false);
38
+ setIsPausing(true);
39
+ setShowTabHint(true);
40
+ }, delayAfterText);
41
+ return () => clearTimeout(timeout);
42
+ }
43
+ if (isPausing) {
44
+ // Show tab hint for 3 seconds with fade animation
45
+ timeout = setTimeout(() => {
46
+ setShowTabHint(false);
47
+ setTimeout(() => {
48
+ setIsPausing(false);
49
+ setIsDeleting(true);
50
+ }, 300); // Wait for fade out animation
51
+ }, 3000);
52
+ return () => clearTimeout(timeout);
53
+ }
54
+ if (isDeleting) {
55
+ if (displayText === "") {
56
+ setIsDeleting(false);
57
+ setTextIndex((prevIndex) => (prevIndex + 1) % texts.length);
58
+ }
59
+ else {
60
+ timeout = setTimeout(() => {
61
+ setDisplayText((prevText) => prevText.slice(0, -1));
62
+ }, deletingSpeed);
63
+ }
64
+ }
65
+ else {
66
+ if (displayText === currentText) {
67
+ setIsWaiting(true);
68
+ }
69
+ else {
70
+ timeout = setTimeout(() => {
71
+ setDisplayText(currentText.slice(0, displayText.length + 1));
72
+ }, typingSpeed);
73
+ }
74
+ }
75
+ return () => clearTimeout(timeout);
76
+ }, [
77
+ displayText,
78
+ isDeleting,
79
+ textIndex,
80
+ isWaiting,
81
+ isPausing,
82
+ currentText,
83
+ texts,
84
+ typingSpeed,
85
+ deletingSpeed,
86
+ delayAfterText,
87
+ isEmpty,
88
+ ]);
89
+ const handleKeyDown = (e) => {
90
+ if (e.key === "Tab" && isEmpty) {
91
+ e.preventDefault();
92
+ onChange === null || onChange === void 0 ? void 0 : onChange({
93
+ target: { value: currentText },
94
+ });
95
+ return;
96
+ }
97
+ if (e.key === "Enter") {
98
+ if (e.shiftKey) {
99
+ return;
100
+ }
101
+ e.preventDefault();
102
+ if (isStreaming) {
103
+ return;
104
+ }
105
+ onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(e);
106
+ }
107
+ onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(e);
108
+ };
109
+ return (React.createElement("div", { style: { position: "relative", width: "100%" } },
110
+ isEmpty && (React.createElement("div", { style: {
111
+ position: "absolute",
112
+ top: 0,
113
+ right: 0,
114
+ bottom: 0,
115
+ left: 0,
116
+ pointerEvents: "none",
117
+ display: "flex",
118
+ alignItems: "flex-start",
119
+ paddingLeft: "4px",
120
+ paddingRight: "4px",
121
+ paddingTop: "0",
122
+ paddingBottom: "0",
123
+ marginTop: "4px",
124
+ } },
125
+ React.createElement("p", { style: Object.assign({ color: "#a1a1aa", fontWeight: "500", lineHeight: "1.5" }, (placeholderClassName ? {} : {})) },
126
+ displayText,
127
+ React.createElement(AnimatePresence, null, showTabHint && (React.createElement(motion.span, { initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, transition: { duration: 0.3 }, style: {
128
+ fontSize: "12px",
129
+ color: "#d1d5db", // zinc-300 for dark mode
130
+ backgroundColor: "#27272a", // zinc-800 for dark mode
131
+ paddingLeft: "6px",
132
+ paddingRight: "6px",
133
+ paddingTop: "2px",
134
+ paddingBottom: "2px",
135
+ borderRadius: "8px",
136
+ border: "1px solid #3f3f46", // zinc-700 for dark mode
137
+ alignItems: "center",
138
+ marginLeft: "8px",
139
+ display: "inline-flex",
140
+ whiteSpace: "nowrap",
141
+ } }, "Tab to select")))))),
142
+ React.createElement(Textarea, Object.assign({ ref: textareaRef, placeholder: originalPlaceholder, style: className ? {} : {}, value: value, onFocus: onFocus, onBlur: onBlur, onChange: onChange, onKeyDown: handleKeyDown, onPaste: onPaste, rows: rows }, props))));
143
+ });
144
+ TypingTextarea.displayName = "TypingTextarea";
@@ -0,0 +1,129 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { motion } from "framer-motion";
4
+ export const VoiceIcon = ({ isRecording, isTranscribing }) => {
5
+ if (isTranscribing) {
6
+ return (React.createElement("div", { style: {
7
+ position: "relative",
8
+ width: "20px",
9
+ height: "16px",
10
+ display: "flex",
11
+ alignItems: "center",
12
+ justifyContent: "center",
13
+ } },
14
+ React.createElement(motion.div, { style: {
15
+ width: "12px",
16
+ height: "12px",
17
+ border: "2px solid white",
18
+ borderTop: "2px solid transparent",
19
+ borderRadius: "50%",
20
+ }, animate: {
21
+ rotate: 360,
22
+ }, transition: {
23
+ duration: 1,
24
+ repeat: Infinity,
25
+ ease: "linear",
26
+ } })));
27
+ }
28
+ if (isRecording) {
29
+ return (React.createElement("div", { style: {
30
+ position: "relative",
31
+ width: "20px",
32
+ height: "16px",
33
+ display: "flex",
34
+ alignItems: "center",
35
+ justifyContent: "center",
36
+ } },
37
+ React.createElement(motion.div, { style: {
38
+ width: "12px",
39
+ height: "12px",
40
+ backgroundColor: "white",
41
+ borderRadius: "2px",
42
+ }, animate: {
43
+ scale: [1, 0.95, 1],
44
+ }, transition: {
45
+ duration: 1,
46
+ repeat: Infinity,
47
+ ease: "easeInOut",
48
+ } })));
49
+ }
50
+ return (React.createElement("div", { style: {
51
+ position: "relative",
52
+ width: "20px",
53
+ height: "16px",
54
+ display: "flex",
55
+ alignItems: "center",
56
+ justifyContent: "center",
57
+ } },
58
+ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: "2px" } },
59
+ React.createElement(motion.div, { style: {
60
+ width: "1.5px",
61
+ height: "8px",
62
+ backgroundColor: "currentColor",
63
+ borderRadius: "999px",
64
+ }, animate: {
65
+ scaleY: [0.4, 0.8, 0.4],
66
+ opacity: [0.6, 0.9, 0.6],
67
+ }, transition: {
68
+ duration: 1.8,
69
+ repeat: Infinity,
70
+ ease: "easeInOut",
71
+ delay: 0,
72
+ } }),
73
+ React.createElement(motion.div, { style: {
74
+ width: "1.5px",
75
+ height: "12px",
76
+ backgroundColor: "currentColor",
77
+ borderRadius: "999px",
78
+ }, animate: {
79
+ scaleY: [0.5, 1, 0.5],
80
+ opacity: [0.7, 1, 0.7],
81
+ }, transition: {
82
+ duration: 2.1,
83
+ repeat: Infinity,
84
+ ease: "easeInOut",
85
+ delay: 0.2,
86
+ } }),
87
+ React.createElement(motion.div, { style: {
88
+ width: "1.5px",
89
+ height: "16px",
90
+ backgroundColor: "currentColor",
91
+ borderRadius: "999px",
92
+ }, animate: {
93
+ scaleY: [0.6, 1, 0.6],
94
+ opacity: [0.8, 1, 0.8],
95
+ }, transition: {
96
+ duration: 1.6,
97
+ repeat: Infinity,
98
+ ease: "easeInOut",
99
+ delay: 0.4,
100
+ } }),
101
+ React.createElement(motion.div, { style: {
102
+ width: "1.5px",
103
+ height: "12px",
104
+ backgroundColor: "currentColor",
105
+ borderRadius: "999px",
106
+ }, animate: {
107
+ scaleY: [0.5, 0.9, 0.5],
108
+ opacity: [0.7, 1, 0.7],
109
+ }, transition: {
110
+ duration: 1.9,
111
+ repeat: Infinity,
112
+ ease: "easeInOut",
113
+ delay: 0.6,
114
+ } }),
115
+ React.createElement(motion.div, { style: {
116
+ width: "1.5px",
117
+ height: "8px",
118
+ backgroundColor: "currentColor",
119
+ borderRadius: "999px",
120
+ }, animate: {
121
+ scaleY: [0.4, 0.7, 0.4],
122
+ opacity: [0.6, 0.9, 0.6],
123
+ }, transition: {
124
+ duration: 2.2,
125
+ repeat: Infinity,
126
+ ease: "easeInOut",
127
+ delay: 0.8,
128
+ } }))));
129
+ };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { Button } from "../ui/button";
4
+ import { VoiceIcon } from "./voice-button/voice-icon";
5
+ export const VoiceButton = ({ isRecording, isTranscribing, onVoiceRecording, playgroundUid, // eslint-disable-line @typescript-eslint/no-unused-vars
6
+ isLoggedIn = false, }) => {
7
+ // Don't show voice button for statsig playground
8
+ // if (playgroundUid === "statsig") {
9
+ // return null;
10
+ // }
11
+ const getTooltipText = () => {
12
+ if (isTranscribing) {
13
+ return "Transcribing your voice...";
14
+ }
15
+ if (isRecording) {
16
+ return "Click to stop recording";
17
+ }
18
+ if (isLoggedIn) {
19
+ return "Voice Mode – Build with voice (Ctrl/Cmd + /)";
20
+ }
21
+ return "Sign up to use voice mode";
22
+ };
23
+ return (React.createElement(Button, { size: "sm", variant: "ghostOutline", style: Object.assign(Object.assign({ height: "32px", paddingLeft: "8px", paddingRight: "8px", fontSize: "12px", fontWeight: "500", transition: "all 0.2s ease-in-out" }, (isRecording && {
24
+ backgroundColor: "#ef4444", // red-500
25
+ borderColor: "#ef4444",
26
+ boxShadow: "0 10px 15px -3px rgba(239, 68, 68, 0.25)",
27
+ color: "white",
28
+ })), (isTranscribing && {
29
+ backgroundColor: "#3b82f6", // blue-500
30
+ borderColor: "#3b82f6",
31
+ boxShadow: "0 10px 15px -3px rgba(59, 130, 246, 0.25)",
32
+ color: "white",
33
+ })), onClick: () => {
34
+ if (isLoggedIn && !isTranscribing) {
35
+ onVoiceRecording();
36
+ }
37
+ else if (!isLoggedIn) {
38
+ window.location.href = "/sign-up";
39
+ }
40
+ }, disabled: isTranscribing },
41
+ React.createElement(VoiceIcon, { isRecording: isRecording, isTranscribing: isTranscribing })));
42
+ };
@@ -0,0 +1,190 @@
1
+ import React from "react";
2
+ // Removed cn import as we're using inline styles
3
+ import { motion } from "framer-motion";
4
+ // Voice Recording Overlay Component
5
+ export const VoiceOverlay = ({ isRecording, isTranscribing, onDismiss, }) => {
6
+ // const pathname = usePathname();
7
+ // Enable overlay on main playground pages (/pg/) and subdomain playgrounds (*.sampleapp.ai),
8
+ // // but disable on chat building pages (/chat/)
9
+ // const isLocalhost =
10
+ // typeof window !== "undefined" &&
11
+ // (window.location.hostname === "localhost" ||
12
+ // window.location.hostname.endsWith(".localhost"));
13
+ // const isSubdomainPlayground =
14
+ // typeof window !== "undefined" &&
15
+ // window.location.hostname.endsWith(".sampleapp.ai") &&
16
+ // window.location.hostname !== "sampleapp.ai"; // exclude main domain
17
+ // const isPlaygroundPath =
18
+ // pathname.startsWith("/pg/") && !pathname.includes("/chat");
19
+ // const overlayEnabled =
20
+ // isPlaygroundPath ||
21
+ // isSubdomainPlayground ||
22
+ // (isLocalhost && !pathname.includes("/chat"));
23
+ const overlayEnabled = true;
24
+ const isVisible = overlayEnabled && (isRecording || isTranscribing);
25
+ const isDark = true;
26
+ if (!isVisible)
27
+ return null;
28
+ return (React.createElement(motion.div, { style: {
29
+ position: "fixed",
30
+ top: 0,
31
+ right: 0,
32
+ bottom: 0,
33
+ left: 0,
34
+ zIndex: 50,
35
+ display: "flex",
36
+ alignItems: "center",
37
+ justifyContent: "center",
38
+ backgroundColor: isDark
39
+ ? "rgba(0, 0, 0, 0.2)"
40
+ : "rgba(255, 255, 255, 0.2)",
41
+ }, onClick: isTranscribing ? undefined : onDismiss },
42
+ React.createElement(motion.div, { style: {
43
+ backdropFilter: "blur(4px)",
44
+ borderRadius: "16px",
45
+ padding: "32px",
46
+ border: "1px solid",
47
+ borderColor: isDark
48
+ ? "rgba(255, 255, 255, 0.15)"
49
+ : "rgba(0, 0, 0, 0.15)",
50
+ backgroundColor: isDark
51
+ ? "rgba(255, 255, 255, 0.12)"
52
+ : "rgba(0, 0, 0, 0.12)",
53
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
54
+ }, onClick: (e) => e.stopPropagation() },
55
+ React.createElement("div", { style: {
56
+ display: "flex",
57
+ flexDirection: "column",
58
+ alignItems: "center",
59
+ gap: "24px",
60
+ } }, isTranscribing ? (React.createElement(React.Fragment, null,
61
+ React.createElement(motion.div, { style: {
62
+ width: "64px",
63
+ height: "64px",
64
+ border: "4px solid",
65
+ borderColor: isDark
66
+ ? "rgba(255, 255, 255, 0.3)"
67
+ : "rgba(0, 0, 0, 0.3)",
68
+ borderTopColor: isDark ? "white" : "black",
69
+ borderRadius: "50%",
70
+ }, animate: { rotate: 360 }, transition: { duration: 1, repeat: Infinity, ease: "linear" } }),
71
+ React.createElement("div", { style: { textAlign: "center" } },
72
+ React.createElement("h3", { style: {
73
+ fontSize: "20px",
74
+ fontWeight: "600",
75
+ marginBottom: "8px",
76
+ color: isDark ? "white" : "black",
77
+ } }, "Just a sec..."),
78
+ React.createElement("p", { style: {
79
+ color: isDark
80
+ ? "rgba(255, 255, 255, 0.7)"
81
+ : "rgba(0, 0, 0, 0.7)",
82
+ } }, "Let me write that down for you")))) : (React.createElement(React.Fragment, null,
83
+ React.createElement("div", { style: {
84
+ position: "relative",
85
+ display: "flex",
86
+ alignItems: "center",
87
+ justifyContent: "center",
88
+ width: "128px",
89
+ height: "64px",
90
+ } },
91
+ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: "8px" } },
92
+ React.createElement(motion.div, { style: {
93
+ width: "8px",
94
+ height: "32px",
95
+ borderRadius: "999px",
96
+ backgroundColor: isDark ? "white" : "black",
97
+ }, animate: {
98
+ scaleY: [0.4, 0.8, 0.4],
99
+ opacity: [0.6, 0.9, 0.6],
100
+ }, transition: {
101
+ duration: 1.8,
102
+ repeat: Infinity,
103
+ ease: "easeInOut",
104
+ delay: 0,
105
+ } }),
106
+ React.createElement(motion.div, { style: {
107
+ width: "8px",
108
+ height: "48px",
109
+ borderRadius: "999px",
110
+ backgroundColor: isDark ? "white" : "black",
111
+ }, animate: {
112
+ scaleY: [0.5, 1, 0.5],
113
+ opacity: [0.7, 1, 0.7],
114
+ }, transition: {
115
+ duration: 2.1,
116
+ repeat: Infinity,
117
+ ease: "easeInOut",
118
+ delay: 0.2,
119
+ } }),
120
+ React.createElement(motion.div, { style: {
121
+ width: "8px",
122
+ height: "64px",
123
+ borderRadius: "999px",
124
+ backgroundColor: isDark ? "white" : "black",
125
+ }, animate: {
126
+ scaleY: [0.6, 1, 0.6],
127
+ opacity: [0.8, 1, 0.8],
128
+ }, transition: {
129
+ duration: 1.6,
130
+ repeat: Infinity,
131
+ ease: "easeInOut",
132
+ delay: 0.4,
133
+ } }),
134
+ React.createElement(motion.div, { style: {
135
+ width: "8px",
136
+ height: "48px",
137
+ borderRadius: "999px",
138
+ backgroundColor: isDark ? "white" : "black",
139
+ }, animate: {
140
+ scaleY: [0.5, 0.9, 0.5],
141
+ opacity: [0.7, 1, 0.7],
142
+ }, transition: {
143
+ duration: 1.9,
144
+ repeat: Infinity,
145
+ ease: "easeInOut",
146
+ delay: 0.6,
147
+ } }),
148
+ React.createElement(motion.div, { style: {
149
+ width: "8px",
150
+ height: "32px",
151
+ borderRadius: "999px",
152
+ backgroundColor: isDark ? "white" : "black",
153
+ }, animate: {
154
+ scaleY: [0.4, 0.7, 0.4],
155
+ opacity: [0.6, 0.9, 0.6],
156
+ }, transition: {
157
+ duration: 2.2,
158
+ repeat: Infinity,
159
+ ease: "easeInOut",
160
+ delay: 0.8,
161
+ } }))),
162
+ React.createElement("div", { style: { textAlign: "center" } },
163
+ React.createElement("h3", { style: {
164
+ fontSize: "20px",
165
+ fontWeight: "600",
166
+ marginBottom: "8px",
167
+ color: isDark ? "white" : "black",
168
+ } }, "I'm listening..."),
169
+ React.createElement("p", { style: {
170
+ color: isDark
171
+ ? "rgba(255, 255, 255, 0.7)"
172
+ : "rgba(0, 0, 0, 0.7)",
173
+ } }, "Tell me what you'd like to build today")),
174
+ React.createElement(motion.button, { style: {
175
+ paddingLeft: "24px",
176
+ paddingRight: "24px",
177
+ paddingTop: "12px",
178
+ paddingBottom: "12px",
179
+ backdropFilter: "blur(4px)",
180
+ borderRadius: "12px",
181
+ fontWeight: "500",
182
+ transition: "all 0.15s ease",
183
+ backgroundColor: isDark
184
+ ? "rgba(255, 255, 255, 0.2)"
185
+ : "rgba(0, 0, 0, 0.2)",
186
+ border: `1px solid ${isDark ? "rgba(255, 255, 255, 0.3)" : "rgba(0, 0, 0, 0.3)"}`,
187
+ color: isDark ? "white" : "black",
188
+ cursor: "pointer",
189
+ }, onClick: onDismiss, whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 } }, "Stop")))))));
190
+ };