goji-search 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 (25) hide show
  1. package/README.md +70 -0
  2. package/dist/goji-search/components/elements/action-buttons.d.ts +12 -0
  3. package/dist/goji-search/components/elements/action-buttons.js +135 -0
  4. package/dist/goji-search/components/elements/calendar-integration.d.ts +5 -0
  5. package/dist/goji-search/components/elements/calendar-integration.js +49 -0
  6. package/dist/goji-search/components/elements/inspiration-menu.d.ts +7 -0
  7. package/dist/goji-search/components/elements/inspiration-menu.js +79 -0
  8. package/dist/goji-search/components/elements/message-list.d.ts +24 -0
  9. package/dist/goji-search/components/elements/message-list.js +293 -0
  10. package/dist/goji-search/components/elements/search-input.d.ts +15 -0
  11. package/dist/goji-search/components/elements/search-input.js +90 -0
  12. package/dist/goji-search/components/elements/suggested-questions.d.ts +6 -0
  13. package/dist/goji-search/components/elements/suggested-questions.js +54 -0
  14. package/dist/goji-search/components/goji-search-component.d.ts +2 -0
  15. package/dist/goji-search/components/goji-search-component.js +505 -0
  16. package/dist/goji-search/config/company.d.ts +29 -0
  17. package/dist/goji-search/config/company.js +68 -0
  18. package/dist/goji-search/lib/calendar-config.d.ts +9 -0
  19. package/dist/goji-search/lib/calendar-config.js +10 -0
  20. package/dist/goji-search/lib/goji-client.d.ts +81 -0
  21. package/dist/goji-search/lib/goji-client.js +176 -0
  22. package/dist/goji-search.css +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +2 -0
  25. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Goji Embed
2
+
3
+ A lightweight React component library providing embeddable form and button components for seamless integration into your React applications.
4
+
5
+ ## Features
6
+
7
+ - **Embeddable Form**: Easily add a customizable form to your app.
8
+ - **Embeddable Button**: Simple, reusable button component.
9
+ - **TypeScript Support**: Fully typed for a great developer experience.
10
+ - **Zero Dependencies**: Only requires React as a peer dependency.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install goji-embed
16
+ # or
17
+ yarn add goji-embed
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```tsx
23
+ import { GojiEmbedForm, GojiEmbedButton } from 'goji-embed';
24
+
25
+ function App() {
26
+ return (
27
+ <div>
28
+ <GojiEmbedForm /* props here */ />
29
+ <GojiEmbedButton /* props here */ />
30
+ </div>
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## Components
36
+
37
+ ### `<GojiEmbedForm />`
38
+
39
+ A form component for embedding in your React app.
40
+
41
+ **Props:**
42
+ *(Document your props here, e.g. onSubmit, fields, etc.)*
43
+
44
+ ---
45
+
46
+ ### `<GojiEmbedButton />`
47
+
48
+ A reusable button component.
49
+
50
+ **Props:**
51
+ *(Document your props here, e.g. onClick, label, etc.)*
52
+
53
+ ---
54
+
55
+ ## Development
56
+
57
+ - Built with [Vite](https://vitejs.dev/) and [TypeScript](https://www.typescriptlang.org/).
58
+ - To build the library:
59
+ ```bash
60
+ npm run build
61
+ ```
62
+
63
+ ## License
64
+
65
+ MIT
66
+
67
+ ---
68
+
69
+ *Feel free to open issues or pull requests for improvements or bug fixes!*
70
+ *creating dev branch*
@@ -0,0 +1,12 @@
1
+ interface ActionButtonsProps {
2
+ size: "xs" | "s" | "m" | "l" | "xl";
3
+ isHovered: boolean;
4
+ isStreaming: boolean;
5
+ searchQuery: string;
6
+ onSubmit: () => void;
7
+ onVoiceSearch: () => void;
8
+ onClose: () => void;
9
+ onCalendarClick: () => void;
10
+ }
11
+ export declare function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSubmit, onVoiceSearch, onClose, onCalendarClick, }: ActionButtonsProps): import("react/jsx-runtime").JSX.Element | null;
12
+ export {};
@@ -0,0 +1,135 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Mic, Calendar, ArrowUp } from "lucide-react";
3
+ import { useState, useId } from "react";
4
+ export function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSubmit, onVoiceSearch, onClose, onCalendarClick, // Added calendar click handler
5
+ }) {
6
+ if (size !== "m" && size !== "l" && size !== "xl")
7
+ return null;
8
+ // tooltip hover/focus states
9
+ const [hoverCalendar, setHoverCalendar] = useState(false);
10
+ const [hoverSubmit, setHoverSubmit] = useState(false);
11
+ const [hoverVoice, setHoverVoice] = useState(false);
12
+ // base id for accessibility
13
+ const idBase = useId();
14
+ const calendarTooltipId = `${idBase}-calendar-tip`;
15
+ const submitTooltipId = `${idBase}-submit-tip`;
16
+ const voiceTooltipId = `${idBase}-voice-tip`;
17
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { position: "relative", display: "inline-block", marginLeft: "0.25rem" }, onMouseEnter: () => setHoverSubmit(true), onMouseLeave: () => setHoverSubmit(false), children: [_jsx("button", { type: "submit", disabled: isStreaming, onClick: onSubmit, "aria-describedby": hoverSubmit ? submitTooltipId : undefined, onFocus: () => setHoverSubmit(true), onBlur: () => setHoverSubmit(false), style: {
18
+ borderRadius: "1.3rem",
19
+ border: "1px solid rgba(255, 255, 255, 0.3)",
20
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
21
+ padding: size === "l" || size === "xl" ? "0.5rem" : "0.3rem",
22
+ display: "flex",
23
+ alignItems: "center",
24
+ justifyContent: "center",
25
+ color: "rgba(0, 0, 0, 0.75)",
26
+ backdropFilter: "blur(20px)",
27
+ WebkitBackdropFilter: "blur(20px)",
28
+ transition: "all 0.2s",
29
+ cursor: isStreaming ? "not-allowed" : "pointer",
30
+ outline: "none",
31
+ opacity: isStreaming ? 0.5 : size === "m" && !isHovered ? 0.7 : 1,
32
+ boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
33
+ }, children: _jsx(ArrowUp, { style: {
34
+ width: size === "l" || size === "xl" ? "1rem" : "0.875rem",
35
+ height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
36
+ } }) }), _jsx("span", { id: submitTooltipId, role: "tooltip", style: {
37
+ position: "absolute",
38
+ top: "calc(100% + 0.4rem)",
39
+ left: "50%",
40
+ transform: "translateX(-50%)",
41
+ whiteSpace: "nowrap",
42
+ background: "rgba(0,0,0,0.9)",
43
+ color: "#fff",
44
+ padding: "4px 6px",
45
+ borderRadius: "1.3rem",
46
+ fontSize: "0.55rem",
47
+ boxShadow: "0 6px 18px rgba(0,0,0,0.35)",
48
+ opacity: hoverSubmit ? 1 : 0,
49
+ pointerEvents: "none",
50
+ transition: "opacity 120ms ease-in-out",
51
+ zIndex: 30,
52
+ }, children: "Send message" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginLeft: "0.25rem" }, onMouseEnter: () => setHoverVoice(true), onMouseLeave: () => setHoverVoice(false), children: [_jsx("button", { type: "button", onClick: onVoiceSearch, "aria-describedby": hoverVoice ? voiceTooltipId : undefined, onBlur: (e) => {
53
+ setHoverVoice(false);
54
+ e.currentTarget.style.boxShadow = "inset 0 1px 0 rgba(255, 255, 255, 0.3)";
55
+ }, style: {
56
+ borderRadius: "1.3rem",
57
+ border: "1px solid rgba(255, 255, 255, 0.3)",
58
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
59
+ padding: size === "l" || size === "xl" ? "0.5rem" : "0.3rem",
60
+ display: "flex",
61
+ alignItems: "center",
62
+ justifyContent: "center",
63
+ outlineColor: "none",
64
+ color: "rgba(0, 0, 0, 0.75)",
65
+ backdropFilter: "blur(20px)",
66
+ WebkitBackdropFilter: "blur(20px)",
67
+ transition: "all 0.2s",
68
+ cursor: "pointer",
69
+ outline: "none",
70
+ opacity: size === "m" && !isHovered ? 0.7 : 1,
71
+ boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
72
+ }, onMouseEnter: (e) => {
73
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
74
+ }, onMouseLeave: (e) => {
75
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
76
+ }, children: _jsx(Mic, { style: {
77
+ width: size === "l" || size === "xl" ? "1rem" : "0.875rem",
78
+ height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
79
+ } }) }), _jsx("span", { id: voiceTooltipId, role: "tooltip", style: {
80
+ position: "absolute",
81
+ top: "calc(100% + 0.4rem)",
82
+ left: "50%",
83
+ transform: "translateX(-50%)",
84
+ whiteSpace: "nowrap",
85
+ background: "rgba(0,0,0,0.9)",
86
+ color: "#fff",
87
+ padding: "4px 6px",
88
+ borderRadius: "1.3rem",
89
+ fontSize: "0.55rem",
90
+ boxShadow: "0 6px 18px rgba(0,0,0,0.35)",
91
+ opacity: hoverVoice ? 1 : 0,
92
+ pointerEvents: "none",
93
+ transition: "opacity 120ms ease-in-out",
94
+ zIndex: 30,
95
+ }, children: "Voice input" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginRight: "0.25rem" }, onMouseEnter: () => setHoverCalendar(true), onMouseLeave: () => setHoverCalendar(false), children: [_jsxs("button", { type: "button", disabled: isStreaming, onClick: onCalendarClick, "aria-describedby": hoverCalendar ? calendarTooltipId : undefined, onFocus: () => setHoverCalendar(true), onBlur: () => setHoverCalendar(false), style: {
96
+ borderRadius: "1.3rem",
97
+ border: "1px solid rgba(255, 255, 255, 0.3)",
98
+ backgroundColor: "rgb(0, 0, 0)",
99
+ padding: size === "l" || size === "xl" ? "0.5rem" : "0.4rem",
100
+ display: size === "l" || size === "m" || size === "xl" ? "flex" : "none",
101
+ alignItems: "center",
102
+ outlineColor: "none",
103
+ justifyContent: "center",
104
+ color: "rgb(255, 255, 255)",
105
+ transition: "all 0.2s",
106
+ cursor: isStreaming ? "not-allowed" : "pointer",
107
+ outline: "none",
108
+ opacity: isStreaming ? 0.7 : size === "l" && !isHovered ? 0.85 : 1,
109
+ }, children: [_jsx(Calendar, { style: {
110
+ width: size === "l" || size === "xl" ? "1rem" : "0.875rem",
111
+ height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
112
+ } }), _jsx("span", { style: {
113
+ marginLeft: "0.5rem",
114
+ fontSize: "0.7rem",
115
+ fontWeight: 400,
116
+ display: size === "m" ? "none" : "block",
117
+ transition: "all 0.4s",
118
+ }, children: "Book a call" })] }), _jsx("span", { id: calendarTooltipId, role: "tooltip", style: {
119
+ position: "absolute",
120
+ top: "calc(100% + 0.4rem)",
121
+ left: "50%",
122
+ transform: "translateX(-50%)",
123
+ whiteSpace: "nowrap",
124
+ background: "rgba(0,0,0,0.9)",
125
+ color: "#fff",
126
+ padding: "4px 6px",
127
+ borderRadius: "1.3rem",
128
+ fontSize: "0.55rem",
129
+ boxShadow: "0 6px 18px rgba(0,0,0,0.35)",
130
+ opacity: hoverCalendar ? 1 : 0,
131
+ pointerEvents: "none",
132
+ transition: "opacity 120ms ease-in-out",
133
+ zIndex: 30,
134
+ }, children: "Book a call" })] })] }));
135
+ }
@@ -0,0 +1,5 @@
1
+ interface CalendarIntegrationProps {
2
+ onBooked?: () => void;
3
+ }
4
+ export default function CalendarIntegration(props?: CalendarIntegrationProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Cal, { getCalApi } from "@calcom/embed-react";
3
+ import { useEffect } from "react";
4
+ import { getCalendarConfig } from "../../lib/calendar-config";
5
+ export default function CalendarIntegration(props = {}) {
6
+ const { onBooked } = props;
7
+ const calendarConfig = getCalendarConfig();
8
+ useEffect(() => {
9
+ if (!calendarConfig || calendarConfig.provider !== "calcom")
10
+ return;
11
+ void (async () => {
12
+ const cal = await getCalApi({ namespace: calendarConfig.namespace || "default" });
13
+ cal("ui", {
14
+ hideEventTypeDetails: false,
15
+ layout: calendarConfig.layout || "month_view",
16
+ });
17
+ // Listen for successful booking
18
+ try {
19
+ cal("on", {
20
+ action: "bookingSuccessful",
21
+ callback: () => {
22
+ window.dispatchEvent(new Event("calendar-booked"));
23
+ onBooked?.();
24
+ },
25
+ });
26
+ }
27
+ catch (_) {
28
+ // no-op
29
+ }
30
+ })();
31
+ // Also listen via postMessage
32
+ const handleMessage = (event) => {
33
+ const data = event?.data;
34
+ const name = data?.event || data?.action || data?.name;
35
+ if (typeof name === "string" &&
36
+ name.toLowerCase().includes("booking") &&
37
+ name.toLowerCase().includes("success")) {
38
+ window.dispatchEvent(new Event("calendar-booked"));
39
+ onBooked?.();
40
+ }
41
+ };
42
+ window.addEventListener("message", handleMessage);
43
+ return () => window.removeEventListener("message", handleMessage);
44
+ }, [calendarConfig, onBooked]);
45
+ return (_jsx("div", { style: { width: "100%", height: "100%", overflow: "auto" }, children: _jsx(Cal, { namespace: calendarConfig.namespace || "default", calLink: calendarConfig.link, style: { width: "100%", height: "100%", minHeight: "500px" }, config: {
46
+ layout: calendarConfig.layout || "month_view",
47
+ theme: calendarConfig.theme || "light",
48
+ } }) }));
49
+ }
@@ -0,0 +1,7 @@
1
+ interface InspirationMenuProps {
2
+ questions: string[];
3
+ onQuestionClick: (question: string) => void;
4
+ onClose: () => void;
5
+ }
6
+ export declare function InspirationMenu({ questions, onQuestionClick, onClose }: InspirationMenuProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { X } from "lucide-react";
3
+ export function InspirationMenu({ questions, onQuestionClick, onClose }) {
4
+ return (_jsxs("div", { style: {
5
+ position: "absolute",
6
+ bottom: "calc(100% + 0.5rem)",
7
+ left: 0,
8
+ minWidth: "16rem",
9
+ maxWidth: "20rem",
10
+ borderRadius: "0.75rem",
11
+ border: "1px solid rgba(85, 85, 85, 0.18)",
12
+ backgroundColor: "rgb(248, 239, 255)",
13
+ boxShadow: "0 8px 28px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.4)",
14
+ padding: "0.625rem",
15
+ animation: "slideUpMenu 0.25s cubic-bezier(0.4, 0, 0.2, 1)",
16
+ zIndex: 100,
17
+ }, onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { style: {
18
+ display: "flex",
19
+ justifyContent: "space-between",
20
+ alignItems: "center",
21
+ marginBottom: "0.5rem",
22
+ paddingBottom: "0.5rem",
23
+ borderBottom: "1px solid rgba(0, 0, 0, 0.06)",
24
+ }, children: [_jsx("div", { style: {
25
+ fontSize: "0.6875rem",
26
+ fontWeight: 600,
27
+ color: "rgba(0, 0, 0, 0.5)",
28
+ letterSpacing: "0.05em",
29
+ textTransform: "capitalize",
30
+ }, children: "Inspiration" }), _jsx("button", { type: "button", onClick: onClose, style: {
31
+ padding: "0.25rem",
32
+ borderRadius: "0.375rem",
33
+ border: "1px solid rgba(255, 255, 255, 0.2)",
34
+ backgroundColor: "rgba(255, 255, 255, 0.15)",
35
+ color: "rgba(0, 0, 0, 0.5)",
36
+ cursor: "pointer",
37
+ display: "flex",
38
+ alignItems: "center",
39
+ justifyContent: "center",
40
+ transition: "all 0.2s",
41
+ outline: "none",
42
+ backdropFilter: "blur(10px)",
43
+ WebkitBackdropFilter: "blur(10px)",
44
+ }, onMouseEnter: (e) => {
45
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
46
+ e.currentTarget.style.color = "rgba(0, 0, 0, 0.8)";
47
+ e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.35)";
48
+ }, onMouseLeave: (e) => {
49
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.15)";
50
+ e.currentTarget.style.color = "rgba(0, 0, 0, 0.5)";
51
+ e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.2)";
52
+ }, children: _jsx(X, { style: { width: "0.875rem", height: "0.875rem" } }) })] }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: questions.map((question, index) => (_jsx("button", { type: "button", onClick: () => onQuestionClick(question), style: {
53
+ padding: "0.5rem 0.75rem",
54
+ borderRadius: "1.3rem",
55
+ border: "1px solid rgba(255, 255, 255, 0.25)",
56
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
57
+ color: "rgba(0, 0, 0, 0.75)",
58
+ fontSize: "0.75rem",
59
+ textAlign: "left",
60
+ cursor: "pointer",
61
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
62
+ backdropFilter: "blur(20px) saturate(180%)",
63
+ WebkitBackdropFilter: "blur(20px) saturate(180%)",
64
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
65
+ outline: "none",
66
+ lineHeight: "1.3",
67
+ }, onMouseEnter: (e) => {
68
+ e.currentTarget.style.backgroundColor = "rgba(0, 122, 255, 0.15)";
69
+ e.currentTarget.style.borderColor = "rgba(0, 122, 255, 0.3)";
70
+ e.currentTarget.style.transform = "translateY(-1px)";
71
+ e.currentTarget.style.boxShadow =
72
+ "0 3px 8px rgba(0, 122, 255, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.4)";
73
+ }, onMouseLeave: (e) => {
74
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
75
+ e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.25)";
76
+ e.currentTarget.style.transform = "translateY(0)";
77
+ e.currentTarget.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
78
+ }, children: question }, index))) })] }));
79
+ }
@@ -0,0 +1,24 @@
1
+ interface ChatSource {
2
+ index: number;
3
+ url: string;
4
+ title: string;
5
+ domain: string;
6
+ page_type: string;
7
+ score: number;
8
+ }
9
+ interface Message {
10
+ role: "user" | "assistant";
11
+ content: string;
12
+ timestamp: number;
13
+ sources?: ChatSource[];
14
+ }
15
+ interface MessageListProps {
16
+ messages: Message[];
17
+ isStreaming: boolean;
18
+ aiAvatarSrc?: string;
19
+ onClose?: () => void;
20
+ onExpand?: () => void;
21
+ size?: "m" | "l" | "xl" | "s" | "xs";
22
+ }
23
+ export declare function MessageList({ messages, isStreaming, aiAvatarSrc, onClose, onExpand, size, }: MessageListProps): import("react/jsx-runtime").JSX.Element;
24
+ export {};