@nlweb-ai/search-components 0.1.9

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.
package/dist/index.js ADDED
@@ -0,0 +1,1766 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ChatSearch: () => ChatSearch,
24
+ DebugTool: () => DebugTool,
25
+ HistorySidebar: () => HistorySidebar,
26
+ SiteDropdown: () => SiteDropdown,
27
+ useNlWeb: () => useNlWeb,
28
+ useSearchSession: () => useSearchSession,
29
+ useSearchSessions: () => useSearchSessions
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // #style-inject:#style-inject
34
+ function styleInject(css, { insertAt } = {}) {
35
+ if (!css || typeof document === "undefined") return;
36
+ const head = document.head || document.getElementsByTagName("head")[0];
37
+ const style = document.createElement("style");
38
+ style.type = "text/css";
39
+ if (insertAt === "top") {
40
+ if (head.firstChild) {
41
+ head.insertBefore(style, head.firstChild);
42
+ } else {
43
+ head.appendChild(style);
44
+ }
45
+ } else {
46
+ head.appendChild(style);
47
+ }
48
+ if (style.styleSheet) {
49
+ style.styleSheet.cssText = css;
50
+ } else {
51
+ style.appendChild(document.createTextNode(css));
52
+ }
53
+ }
54
+
55
+ // src/styles.css
56
+ styleInject('/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root,\n :host {\n --font-sans:\n ui-sans-serif,\n system-ui,\n sans-serif,\n "Apple Color Emoji",\n "Segoe UI Emoji",\n "Segoe UI Symbol",\n "Noto Color Emoji";\n --font-mono:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-yellow-500: oklch(79.5% 0.184 86.047);\n --color-blue-300: oklch(80.9% 0.105 251.813);\n --color-blue-600: oklch(54.6% 0.245 262.881);\n --color-gray-50: oklch(98.5% 0.002 247.839);\n --color-gray-100: oklch(96.7% 0.003 264.542);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-gray-900: oklch(21% 0.034 264.665);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --container-xl: 36rem;\n --container-2xl: 42rem;\n --container-3xl: 48rem;\n --container-7xl: 80rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-base: 1rem;\n --text-base--line-height: calc(1.5 / 1);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --font-weight-normal: 400;\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --leading-relaxed: 1.625;\n --radius-sm: 0.25rem;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --radius-2xl: 1rem;\n --animate-spin: spin 1s linear infinite;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html,\n :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b,\n strong {\n font-weight: bolder;\n }\n code,\n kbd,\n samp,\n pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol,\n ul,\n menu {\n list-style: none;\n }\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n button,\n input,\n select,\n optgroup,\n textarea,\n ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit,\n ::-webkit-datetime-edit-year-field,\n ::-webkit-datetime-edit-month-field,\n ::-webkit-datetime-edit-day-field,\n ::-webkit-datetime-edit-hour-field,\n ::-webkit-datetime-edit-minute-field,\n ::-webkit-datetime-edit-second-field,\n ::-webkit-datetime-edit-millisecond-field,\n ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button,\n input:where([type=button], [type=reset], [type=submit]),\n ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button,\n ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=until-found])) {\n display: none !important;\n }\n}\n@layer utilities {\n .shimmer-container {\n container-type: inline-size;\n & .shimmer {\n --shimmer-track-width: 100cqw;\n --shimmer-track-height: max(100cqh, 50cqw, 200px);\n }\n }\n .pointer-events-none {\n pointer-events: none;\n }\n .invisible {\n visibility: hidden;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .inset-y-0 {\n inset-block: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-3 {\n top: calc(var(--spacing) * 3);\n }\n .top-4 {\n top: calc(var(--spacing) * 4);\n }\n .top-12 {\n top: calc(var(--spacing) * 12);\n }\n .top-\\[calc\\(100\\%_-_100px\\)\\] {\n top: calc(100% - 100px);\n }\n .right-0 {\n right: calc(var(--spacing) * 0);\n }\n .right-2 {\n right: calc(var(--spacing) * 2);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .right-6 {\n right: calc(var(--spacing) * 6);\n }\n .right-10 {\n right: calc(var(--spacing) * 10);\n }\n .bottom-0 {\n bottom: calc(var(--spacing) * 0);\n }\n .bottom-8 {\n bottom: calc(var(--spacing) * 8);\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-2 {\n left: calc(var(--spacing) * 2);\n }\n .left-3\\.5 {\n left: calc(var(--spacing) * 3.5);\n }\n .left-4 {\n left: calc(var(--spacing) * 4);\n }\n .left-10 {\n left: calc(var(--spacing) * 10);\n }\n .z-10 {\n z-index: 10;\n }\n .z-30 {\n z-index: 30;\n }\n .z-50 {\n z-index: 50;\n }\n .container {\n width: 100%;\n @media (width >= 40rem) {\n max-width: 40rem;\n }\n @media (width >= 48rem) {\n max-width: 48rem;\n }\n @media (width >= 64rem) {\n max-width: 64rem;\n }\n @media (width >= 80rem) {\n max-width: 80rem;\n }\n @media (width >= 96rem) {\n max-width: 96rem;\n }\n }\n .m-0 {\n margin: calc(var(--spacing) * 0);\n }\n .-mx-2 {\n margin-inline: calc(var(--spacing) * -2);\n }\n .mx-auto {\n margin-inline: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-3 {\n margin-bottom: calc(var(--spacing) * 3);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .ml-auto {\n margin-left: auto;\n }\n .line-clamp-2 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n }\n .line-clamp-3 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .hidden {\n display: none;\n }\n .size-4 {\n width: calc(var(--spacing) * 4);\n height: calc(var(--spacing) * 4);\n }\n .size-5 {\n width: calc(var(--spacing) * 5);\n height: calc(var(--spacing) * 5);\n }\n .size-6 {\n width: calc(var(--spacing) * 6);\n height: calc(var(--spacing) * 6);\n }\n .h-2 {\n height: calc(var(--spacing) * 2);\n }\n .h-3 {\n height: calc(var(--spacing) * 3);\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-7 {\n height: calc(var(--spacing) * 7);\n }\n .h-12 {\n height: calc(var(--spacing) * 12);\n }\n .h-36 {\n height: calc(var(--spacing) * 36);\n }\n .h-full\\! {\n height: 100% !important;\n }\n .h-screen {\n height: 100vh;\n }\n .max-h-12 {\n max-height: calc(var(--spacing) * 12);\n }\n .max-h-60 {\n max-height: calc(var(--spacing) * 60);\n }\n .max-h-\\[60vh\\] {\n max-height: 60vh;\n }\n .max-h-\\[80vh\\] {\n max-height: 80vh;\n }\n .w-1\\/6 {\n width: calc(1/6 * 100%);\n }\n .w-3 {\n width: calc(var(--spacing) * 3);\n }\n .w-3\\/4 {\n width: calc(3/4 * 100%);\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-5\\/6 {\n width: calc(5/6 * 100%);\n }\n .w-7 {\n width: calc(var(--spacing) * 7);\n }\n .w-10\\/12 {\n width: calc(10/12 * 100%);\n }\n .w-11\\/12 {\n width: calc(11/12 * 100%);\n }\n .w-full {\n width: 100%;\n }\n .w-full\\! {\n width: 100% !important;\n }\n .w-screen {\n width: 100vw;\n }\n .max-w-2xl {\n max-width: var(--container-2xl);\n }\n .max-w-3xl {\n max-width: var(--container-3xl);\n }\n .max-w-7xl {\n max-width: var(--container-7xl);\n }\n .max-w-12 {\n max-width: calc(var(--spacing) * 12);\n }\n .max-w-70 {\n max-width: calc(var(--spacing) * 70);\n }\n .max-w-xl {\n max-width: var(--container-xl);\n }\n .min-w-0 {\n min-width: calc(var(--spacing) * 0);\n }\n .min-w-50 {\n min-width: calc(var(--spacing) * 50);\n }\n .min-w-64 {\n min-width: calc(var(--spacing) * 64);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-shrink-0 {\n flex-shrink: 0;\n }\n .shimmer {\n --_gradient-width: calc(var(--_spread) + var(--shimmer-track-height) * tan(var(--shimmer-angle)));\n --_active-distance: calc(var(--shimmer-track-width, 200px) + var(--_gradient-width));\n --_duration: var(--shimmer-duration, calc(var(--_active-distance) / var(--_speed) / 1px * 1000));\n --_repeat-delay: var(--shimmer-repeat-delay, calc(20000 / var(--_speed)));\n --_repeat-delay-px: calc(var(--_repeat-delay) * var(--_active-distance) / var(--_duration));\n --_xy-offset-px: calc((var(--shimmer-x, 0) + var(--shimmer-y, 0) * tan(var(--shimmer-angle))) * 1px);\n --_bg-width: calc( 100% + var(--shimmer-track-width, 100%) + var(--_gradient-width) + var(--_repeat-delay-px) );\n --_position: calc( var(--shimmer-track-width, (100% - var(--_gradient-width) - var(--_repeat-delay-px)) / 2) + var(--_gradient-width) / 2 + var(--_repeat-delay-px) - var(--_xy-offset-px) );\n &:not(.shimmer-bg) {\n --_speed: var(--shimmer-speed, 200);\n --_spread: var(--shimmer-spread, calc(4ch + 80px));\n --_bg: currentColor;\n --_fg: var(--shimmer-color, oklch(from currentColor l c h / calc(alpha * 0.2)));\n background-clip: text;\n -webkit-text-fill-color: transparent;\n }\n &.shimmer-bg {\n --_speed: var(--shimmer-speed, 1000);\n --_spread: var(--shimmer-spread, 480px);\n --_bg: transparent;\n --_fg: var(--shimmer-color, oklch(from currentColor 0 c h / 0.06));\n }\n @media (prefers-color-scheme: dark) {\n &:not(.shimmer-bg) {\n --_fg: var(--shimmer-color, oklch(from currentColor max(0.8, calc(l + 0.4)) c h / calc(alpha + 0.4)));\n }\n &.shimmer-bg {\n --_fg: var(--shimmer-color, oklch(from currentColor 0 c h / 0.30));\n }\n }\n @-moz-document url-prefix() {\n --_duration: var(--shimmer-duration, calc(375000 / var(--_speed)));\n }\n --_mix-96: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-96: color-mix(in oklch, var(--_fg), var(--_bg) 96%);\n }\n --_mix-83: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-83: color-mix(in oklch, var(--_fg), var(--_bg) 83%);\n }\n --_mix-67: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-67: color-mix(in oklch, var(--_fg), var(--_bg) 67%);\n }\n --_mix-50: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-50: color-mix(in oklch, var(--_fg), var(--_bg) 50%);\n }\n --_mix-33: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-33: color-mix(in oklch, var(--_fg), var(--_bg) 33%);\n }\n --_mix-17: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-17: color-mix(in oklch, var(--_fg), var(--_bg) 17%);\n }\n --_mix-4: var(--_fg);\n @supports (color: color-mix(in lab, red, red)) {\n --_mix-4: color-mix(in oklch, var(--_fg), var(--_bg) 4%);\n }\n background:\n linear-gradient(\n calc(90deg + var(--shimmer-angle)),\n var(--_bg) calc(var(--_position) - var(--_spread) * 0.5),\n var(--_mix-96) calc(var(--_position) - var(--_spread) * 0.44),\n var(--_mix-83) calc(var(--_position) - var(--_spread) * 0.37),\n var(--_mix-67) calc(var(--_position) - var(--_spread) * 0.31),\n var(--_mix-50) calc(var(--_position) - var(--_spread) * 0.25),\n var(--_mix-33) calc(var(--_position) - var(--_spread) * 0.19),\n var(--_mix-17) calc(var(--_position) - var(--_spread) * 0.12),\n var(--_mix-4) calc(var(--_position) - var(--_spread) * 0.06),\n var(--_fg) var(--_position),\n var(--_mix-4) calc(var(--_position) + var(--_spread) * 0.06),\n var(--_mix-17) calc(var(--_position) + var(--_spread) * 0.12),\n var(--_mix-33) calc(var(--_position) + var(--_spread) * 0.19),\n var(--_mix-50) calc(var(--_position) + var(--_spread) * 0.25),\n var(--_mix-67) calc(var(--_position) + var(--_spread) * 0.31),\n var(--_mix-83) calc(var(--_position) + var(--_spread) * 0.37),\n var(--_mix-96) calc(var(--_position) + var(--_spread) * 0.44),\n var(--_bg) calc(var(--_position) + var(--_spread) * 0.5)) 0 0 / var(--_bg-width) 100% no-repeat;\n animation: tw-shimmer 1s linear 0s infinite backwards;\n animation-duration: calc((var(--_duration) + var(--_repeat-delay)) * 1ms);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-default {\n cursor: default;\n }\n .cursor-not-allowed {\n cursor: not-allowed;\n }\n .grid-cols-1 {\n grid-template-columns: repeat(1, minmax(0, 1fr));\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-row {\n flex-direction: row;\n }\n .items-center {\n align-items: center;\n }\n .items-stretch {\n align-items: stretch;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .justify-start {\n justify-content: flex-start;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-3 {\n gap: calc(var(--spacing) * 3);\n }\n .gap-6 {\n gap: calc(var(--spacing) * 6);\n }\n .space-y-1 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-2 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-3 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-4 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .divide-y {\n :where(& > :not(:last-child)) {\n --tw-divide-y-reverse: 0;\n border-bottom-style: var(--tw-border-style);\n border-top-style: var(--tw-border-style);\n border-top-width: calc(1px * var(--tw-divide-y-reverse));\n border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n }\n }\n .truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .overflow-auto {\n overflow: auto;\n }\n .overflow-hidden {\n overflow: hidden;\n }\n .overflow-y-auto {\n overflow-y: auto;\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded\\! {\n border-radius: 0.25rem !important;\n }\n .rounded-2xl {\n border-radius: var(--radius-2xl);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .rounded-md {\n border-radius: var(--radius-md);\n }\n .rounded-tr-sm {\n border-top-right-radius: var(--radius-sm);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-r {\n border-right-style: var(--tw-border-style);\n border-right-width: 1px;\n }\n .border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 1px;\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-none {\n --tw-border-style: none;\n border-style: none;\n }\n .border-gray-200 {\n border-color: var(--color-gray-200);\n }\n .border-gray-300 {\n border-color: var(--color-gray-300);\n }\n .border-gray-400 {\n border-color: var(--color-gray-400);\n }\n .border-gray-900 {\n border-color: var(--color-gray-900);\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-black\\/30 {\n background-color: color-mix(in srgb, #000 30%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 30%, transparent);\n }\n }\n .bg-blue-600 {\n background-color: var(--color-blue-600);\n }\n .bg-gray-50 {\n background-color: var(--color-gray-50);\n }\n .bg-gray-100 {\n background-color: var(--color-gray-100);\n }\n .bg-gray-200 {\n background-color: var(--color-gray-200);\n }\n .bg-gray-200\\/50 {\n background-color: color-mix(in srgb, oklch(92.8% 0.006 264.531) 50%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-gray-200) 50%, transparent);\n }\n }\n .bg-gray-900 {\n background-color: var(--color-gray-900);\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .bg-gradient-to-b {\n --tw-gradient-position: to bottom in oklab;\n background-image: linear-gradient(var(--tw-gradient-stops));\n }\n .from-transparent {\n --tw-gradient-from: transparent;\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .to-white {\n --tw-gradient-to: var(--color-white);\n --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));\n }\n .object-cover\\! {\n object-fit: cover !important;\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-3 {\n padding: calc(var(--spacing) * 3);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .p-8 {\n padding: calc(var(--spacing) * 8);\n }\n .px-2 {\n padding-inline: calc(var(--spacing) * 2);\n }\n .px-3 {\n padding-inline: calc(var(--spacing) * 3);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .px-5 {\n padding-inline: calc(var(--spacing) * 5);\n }\n .px-6 {\n padding-inline: calc(var(--spacing) * 6);\n }\n .py-1 {\n padding-block: calc(var(--spacing) * 1);\n }\n .py-1\\.5 {\n padding-block: calc(var(--spacing) * 1.5);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .py-3 {\n padding-block: calc(var(--spacing) * 3);\n }\n .py-6 {\n padding-block: calc(var(--spacing) * 6);\n }\n .py-8 {\n padding-block: calc(var(--spacing) * 8);\n }\n .pt-16 {\n padding-top: calc(var(--spacing) * 16);\n }\n .pr-2 {\n padding-right: calc(var(--spacing) * 2);\n }\n .pr-3 {\n padding-right: calc(var(--spacing) * 3);\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .pr-10 {\n padding-right: calc(var(--spacing) * 10);\n }\n .pr-12 {\n padding-right: calc(var(--spacing) * 12);\n }\n .pr-20 {\n padding-right: calc(var(--spacing) * 20);\n }\n .pb-0 {\n padding-bottom: calc(var(--spacing) * 0);\n }\n .pb-2 {\n padding-bottom: calc(var(--spacing) * 2);\n }\n .pb-24 {\n padding-bottom: calc(var(--spacing) * 24);\n }\n .pl-2 {\n padding-left: calc(var(--spacing) * 2);\n }\n .pl-3 {\n padding-left: calc(var(--spacing) * 3);\n }\n .pl-4 {\n padding-left: calc(var(--spacing) * 4);\n }\n .pl-8 {\n padding-left: calc(var(--spacing) * 8);\n }\n .pl-10 {\n padding-left: calc(var(--spacing) * 10);\n }\n .text-center {\n text-align: center;\n }\n .text-left {\n text-align: left;\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-base {\n font-size: var(--text-base);\n line-height: var(--tw-leading, var(--text-base--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .leading-5 {\n --tw-leading: calc(var(--spacing) * 5);\n line-height: calc(var(--spacing) * 5);\n }\n .leading-relaxed {\n --tw-leading: var(--leading-relaxed);\n line-height: var(--leading-relaxed);\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-normal {\n --tw-font-weight: var(--font-weight-normal);\n font-weight: var(--font-weight-normal);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .whitespace-pre-line {\n white-space: pre-line;\n }\n .text-blue-600 {\n color: var(--color-blue-600);\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-600 {\n color: var(--color-gray-600);\n }\n .text-gray-700 {\n color: var(--color-gray-700);\n }\n .text-gray-800 {\n color: var(--color-gray-800);\n }\n .text-gray-900 {\n color: var(--color-gray-900);\n }\n .text-white {\n color: var(--color-white);\n }\n .text-yellow-500 {\n color: var(--color-yellow-500);\n }\n .uppercase {\n text-transform: uppercase;\n }\n .italic {\n font-style: italic;\n }\n .no-underline\\! {\n text-decoration-line: none !important;\n }\n .underline {\n text-decoration-line: underline;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .opacity-25 {\n opacity: 25%;\n }\n .opacity-50 {\n opacity: 50%;\n }\n .opacity-75 {\n opacity: 75%;\n }\n .opacity-100 {\n opacity: 100%;\n }\n .shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .shadow-md {\n --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .shadow-sm {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .shadow-xl {\n --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .ring-1 {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .ring-2 {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n .ring-black\\/5 {\n --tw-ring-color: color-mix(in srgb, #000 5%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-ring-color: color-mix(in oklab, var(--color-black) 5%, transparent);\n }\n }\n .ring-gray-100 {\n --tw-ring-color: var(--color-gray-100);\n }\n .blur {\n --tw-blur: blur(8px);\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .filter {\n filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);\n }\n .transition-all {\n transition-property: all;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-colors {\n transition-property:\n color,\n background-color,\n border-color,\n outline-color,\n text-decoration-color,\n fill,\n stroke,\n --tw-gradient-from,\n --tw-gradient-via,\n --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .shimmer-color-gray-300\\/30 {\n --alpha: 100%;\n --alpha: calc(30 * 1%);\n --shimmer-color: oklch(87.2% 0.01 258.338);\n @supports (color: color-mix(in lab, red, red)) {\n --shimmer-color: color-mix(in oklab, var(--color-gray-300) var(--alpha, 100%), transparent);\n }\n }\n .shimmer-color-gray-400\\/20 {\n --alpha: 100%;\n --alpha: calc(20 * 1%);\n --shimmer-color: oklch(70.7% 0.022 261.325);\n @supports (color: color-mix(in lab, red, red)) {\n --shimmer-color: color-mix(in oklab, var(--color-gray-400) var(--alpha, 100%), transparent);\n }\n }\n .outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .\\[--shimmer-x\\:60\\] {\n --shimmer-x: 60;\n }\n .\\[--shimmer-y\\:0\\] {\n --shimmer-y: 0;\n }\n .\\[--shimmer-y\\:20\\] {\n --shimmer-y: 20;\n }\n .\\[--shimmer-y\\:40\\] {\n --shimmer-y: 40;\n }\n .\\[--shimmer-y\\:60\\] {\n --shimmer-y: 60;\n }\n .\\[--shimmer-y\\:80\\] {\n --shimmer-y: 80;\n }\n .group-hover\\:opacity-100 {\n &:is(:where(.group):hover *) {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n }\n .hover\\:border-gray-300 {\n &:hover {\n @media (hover: hover) {\n border-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:border-gray-400 {\n &:hover {\n @media (hover: hover) {\n border-color: var(--color-gray-400);\n }\n }\n }\n .hover\\:bg-gray-50 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-50);\n }\n }\n }\n .hover\\:bg-gray-100 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-100);\n }\n }\n }\n .hover\\:bg-gray-800 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-800);\n }\n }\n }\n .hover\\:text-black {\n &:hover {\n @media (hover: hover) {\n color: var(--color-black);\n }\n }\n }\n .hover\\:text-gray-700 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-gray-700);\n }\n }\n }\n .hover\\:text-red-500 {\n &:hover {\n @media (hover: hover) {\n color: var(--color-red-500);\n }\n }\n }\n .focus\\:ring-0 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .focus-visible\\:ring-2 {\n &:focus-visible {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow:\n var(--tw-inset-shadow),\n var(--tw-inset-ring-shadow),\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow);\n }\n }\n .focus-visible\\:ring-white\\/75 {\n &:focus-visible {\n --tw-ring-color: color-mix(in srgb, #fff 75%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n --tw-ring-color: color-mix(in oklab, var(--color-white) 75%, transparent);\n }\n }\n }\n .focus-visible\\:ring-offset-2 {\n &:focus-visible {\n --tw-ring-offset-width: 2px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus-visible\\:ring-offset-blue-300 {\n &:focus-visible {\n --tw-ring-offset-color: var(--color-blue-300);\n }\n }\n .active\\:scale-95 {\n &:active {\n --tw-scale-x: 95%;\n --tw-scale-y: 95%;\n --tw-scale-z: 95%;\n scale: var(--tw-scale-x) var(--tw-scale-y);\n }\n }\n .data-closed\\:opacity-0 {\n &[data-closed] {\n opacity: 0%;\n }\n }\n .sm\\:grid-cols-2 {\n @media (width >= 40rem) {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n }\n .sm\\:text-sm {\n @media (width >= 40rem) {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n }\n .md\\:min-w-md {\n @media (width >= 48rem) {\n min-width: var(--container-md);\n }\n }\n .md\\:grid-cols-3 {\n @media (width >= 48rem) {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n }\n}\n@property --shimmer-track-height { syntax: "<length>"; inherits: true; initial-value: 200px; }\n@property --shimmer-angle { syntax: "<angle>"; inherits: true; initial-value: 15deg; }\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n border-color: var(--color-gray-200, currentcolor);\n }\n}\n.editor-paragraph {\n margin-bottom: 0px !important;\n}\n@property --tw-space-y-reverse { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-divide-y-reverse { syntax: "*"; inherits: false; initial-value: 0; }\n@property --tw-border-style { syntax: "*"; inherits: false; initial-value: solid; }\n@property --tw-gradient-position { syntax: "*"; inherits: false; }\n@property --tw-gradient-from { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-via { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-to { syntax: "<color>"; inherits: false; initial-value: #0000; }\n@property --tw-gradient-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-via-stops { syntax: "*"; inherits: false; }\n@property --tw-gradient-from-position { syntax: "<length-percentage>"; inherits: false; initial-value: 0%; }\n@property --tw-gradient-via-position { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }\n@property --tw-gradient-to-position { syntax: "<length-percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-leading { syntax: "*"; inherits: false; }\n@property --tw-font-weight { syntax: "*"; inherits: false; }\n@property --tw-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-inset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-inset-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-ring-color { syntax: "*"; inherits: false; }\n@property --tw-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-inset-ring-color { syntax: "*"; inherits: false; }\n@property --tw-inset-ring-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-ring-inset { syntax: "*"; inherits: false; }\n@property --tw-ring-offset-width { syntax: "<length>"; inherits: false; initial-value: 0px; }\n@property --tw-ring-offset-color { syntax: "*"; inherits: false; initial-value: #fff; }\n@property --tw-ring-offset-shadow { syntax: "*"; inherits: false; initial-value: 0 0 #0000; }\n@property --tw-blur { syntax: "*"; inherits: false; }\n@property --tw-brightness { syntax: "*"; inherits: false; }\n@property --tw-contrast { syntax: "*"; inherits: false; }\n@property --tw-grayscale { syntax: "*"; inherits: false; }\n@property --tw-hue-rotate { syntax: "*"; inherits: false; }\n@property --tw-invert { syntax: "*"; inherits: false; }\n@property --tw-opacity { syntax: "*"; inherits: false; }\n@property --tw-saturate { syntax: "*"; inherits: false; }\n@property --tw-sepia { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-color { syntax: "*"; inherits: false; }\n@property --tw-drop-shadow-alpha { syntax: "<percentage>"; inherits: false; initial-value: 100%; }\n@property --tw-drop-shadow-size { syntax: "*"; inherits: false; }\n@property --tw-duration { syntax: "*"; inherits: false; }\n@property --tw-scale-x { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-y { syntax: "*"; inherits: false; initial-value: 1; }\n@property --tw-scale-z { syntax: "*"; inherits: false; initial-value: 1; }\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes tw-shimmer {\n from {\n background-position: 100% 0;\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n :root,\n :host {\n --shimmer-track-height: 200px;\n --shimmer-angle: 15deg;\n }\n *,\n ::before,\n ::after,\n ::backdrop {\n --tw-space-y-reverse: 0;\n --tw-divide-y-reverse: 0;\n --tw-border-style: solid;\n --tw-gradient-position: initial;\n --tw-gradient-from: #0000;\n --tw-gradient-via: #0000;\n --tw-gradient-to: #0000;\n --tw-gradient-stops: initial;\n --tw-gradient-via-stops: initial;\n --tw-gradient-from-position: 0%;\n --tw-gradient-via-position: 50%;\n --tw-gradient-to-position: 100%;\n --tw-leading: initial;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-blur: initial;\n --tw-brightness: initial;\n --tw-contrast: initial;\n --tw-grayscale: initial;\n --tw-hue-rotate: initial;\n --tw-invert: initial;\n --tw-opacity: initial;\n --tw-saturate: initial;\n --tw-sepia: initial;\n --tw-drop-shadow: initial;\n --tw-drop-shadow-color: initial;\n --tw-drop-shadow-alpha: 100%;\n --tw-drop-shadow-size: initial;\n --tw-duration: initial;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-scale-z: 1;\n }\n }\n}\n');
57
+
58
+ // src/components/ChatSearch.tsx
59
+ var import_react5 = require("react");
60
+
61
+ // src/lib/useNlWeb.ts
62
+ var import_react = require("react");
63
+
64
+ // src/lib/parseSchema.ts
65
+ var import_zod = require("zod");
66
+
67
+ // src/lib/util.ts
68
+ function abridgedCount(n) {
69
+ if (n < 1e3) {
70
+ return n.toString();
71
+ }
72
+ if (n < 1e6) {
73
+ const divided2 = n / 1e3;
74
+ const formatted2 = divided2 % 1 === 0 ? divided2.toString() : divided2.toFixed(1);
75
+ return formatted2 + "K";
76
+ }
77
+ if (n < 1e9) {
78
+ const divided2 = n / 1e6;
79
+ const formatted2 = divided2 % 1 === 0 ? divided2.toString() : divided2.toFixed(1);
80
+ return formatted2 + "M";
81
+ }
82
+ const divided = n / 1e9;
83
+ const formatted = divided % 1 === 0 ? divided.toString() : divided.toFixed(1);
84
+ return formatted + "B";
85
+ }
86
+ function filterTruthy(arr) {
87
+ return arr.filter(Boolean);
88
+ }
89
+ function intersperse(arr, sep) {
90
+ if (arr.length === 0) return [];
91
+ return arr.slice(1).reduce((acc, item) => acc.concat([sep, item]), [arr[0]]);
92
+ }
93
+ function shortQuantity(value) {
94
+ const parsed = tryParseNumber(value);
95
+ return typeof parsed === "number" && !isNaN(parsed) ? abridgedCount(parsed) : String(value);
96
+ }
97
+ function tryParseNumber(value) {
98
+ try {
99
+ return typeof value === "string" ? parseFloat(value) : value;
100
+ } catch {
101
+ return value;
102
+ }
103
+ }
104
+
105
+ // src/lib/parseSchema.ts
106
+ var ImageObjectSchema = import_zod.z.object({
107
+ "@type": import_zod.z.literal("ImageObject").optional(),
108
+ "@id": import_zod.z.string(),
109
+ url: import_zod.z.string().optional(),
110
+ contentUrl: import_zod.z.string().optional()
111
+ }).passthrough();
112
+ var ImageSchema = import_zod.z.union([
113
+ import_zod.z.string(),
114
+ ImageObjectSchema,
115
+ import_zod.z.array(import_zod.z.union([import_zod.z.string(), ImageObjectSchema]))
116
+ ]);
117
+ var PersonSchema = import_zod.z.object({
118
+ "@type": import_zod.z.literal("Person").optional(),
119
+ name: import_zod.z.string(),
120
+ url: import_zod.z.string().optional()
121
+ }).passthrough();
122
+ var OrganizationSchema = import_zod.z.object({
123
+ "@type": import_zod.z.literal("Organization").optional(),
124
+ name: import_zod.z.string(),
125
+ url: import_zod.z.string().optional()
126
+ }).passthrough();
127
+ var RatingSchema = import_zod.z.object({
128
+ "@type": import_zod.z.literal("Rating").optional(),
129
+ ratingValue: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]),
130
+ bestRating: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional(),
131
+ worstRating: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional()
132
+ }).passthrough();
133
+ var AggregateRatingSchema = import_zod.z.object({
134
+ "@type": import_zod.z.literal("AggregateRating").optional(),
135
+ ratingValue: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]),
136
+ bestRating: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional(),
137
+ worstRating: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional(),
138
+ ratingCount: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional(),
139
+ reviewCount: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional()
140
+ }).passthrough();
141
+ var ReviewSchema = import_zod.z.object({
142
+ "@type": import_zod.z.literal("Review").optional(),
143
+ datePublished: import_zod.z.string().optional(),
144
+ reviewBody: import_zod.z.string().optional(),
145
+ reviewRating: RatingSchema.optional(),
146
+ author: import_zod.z.union([PersonSchema, OrganizationSchema, import_zod.z.string()]).optional()
147
+ }).passthrough();
148
+ var VideoObjectSchema = import_zod.z.object({
149
+ "@type": import_zod.z.literal("VideoObject").optional(),
150
+ name: import_zod.z.string().optional(),
151
+ description: import_zod.z.string().optional(),
152
+ thumbnailUrl: import_zod.z.string().optional(),
153
+ uploadDate: import_zod.z.string().optional(),
154
+ contentUrl: import_zod.z.string().optional(),
155
+ embedUrl: import_zod.z.string().optional(),
156
+ duration: import_zod.z.string().optional()
157
+ }).passthrough();
158
+ function resultTypeIs(result, type) {
159
+ if (Array.isArray(result["@type"])) {
160
+ return result["@type"].includes(type);
161
+ }
162
+ return result["@type"] == type;
163
+ }
164
+ function getThumbnailCandidates(result) {
165
+ function filter(candidates) {
166
+ return deduplicate(filterTruthy(candidates));
167
+ }
168
+ if (isArticleResult(result) && typeof result.thumbnailUrl === "string") {
169
+ const thumbnailUrl = result.thumbnailUrl ? result.thumbnailUrl.startsWith("http") ? result.thumbnailUrl : `https://${result.site}${result.thumbnailUrl}` : null;
170
+ return filter([thumbnailUrl, getImageUrl(result.image)]);
171
+ }
172
+ if (isMovieResult(result)) {
173
+ return filter([getImageUrl(result.image), result.trailer?.thumbnailUrl]);
174
+ }
175
+ return filter([getImageUrl(result.image)]);
176
+ }
177
+ function deduplicate(array) {
178
+ const seen = /* @__PURE__ */ new Set();
179
+ return array.filter((item) => {
180
+ if (seen.has(item)) {
181
+ return false;
182
+ }
183
+ seen.add(item);
184
+ return true;
185
+ });
186
+ }
187
+ function getImageUrl(image) {
188
+ if (!image) {
189
+ return null;
190
+ }
191
+ if (typeof image === "string") {
192
+ return image;
193
+ }
194
+ if (Array.isArray(image)) {
195
+ if (image.length === 0) {
196
+ return null;
197
+ }
198
+ const firstImage = image[0];
199
+ if (typeof firstImage === "string") {
200
+ return firstImage;
201
+ }
202
+ return firstImage.contentUrl || firstImage.url || null;
203
+ }
204
+ return image.contentUrl || image.url || image["@id"];
205
+ }
206
+ var RecipeSchema = import_zod.z.object({
207
+ "@type": import_zod.z.union([
208
+ import_zod.z.literal("Recipe"),
209
+ import_zod.z.array(import_zod.z.string()).refine((arr) => arr.includes("Recipe"), {
210
+ message: "Array must contain 'Recipe'"
211
+ })
212
+ ]),
213
+ "@id": import_zod.z.string(),
214
+ score: import_zod.z.number(),
215
+ site: import_zod.z.string(),
216
+ name: import_zod.z.string().optional(),
217
+ recipeIngredient: import_zod.z.union([import_zod.z.array(import_zod.z.string()), import_zod.z.string()]).optional(),
218
+ recipeInstructions: import_zod.z.any().optional(),
219
+ recipeYield: import_zod.z.any().optional(),
220
+ cookTime: import_zod.z.string().optional(),
221
+ prepTime: import_zod.z.string().optional(),
222
+ totalTime: import_zod.z.string().optional(),
223
+ description: import_zod.z.string().optional(),
224
+ image: ImageSchema.optional()
225
+ }).passthrough();
226
+ var ArticleSchema = import_zod.z.object({
227
+ "@type": import_zod.z.union([
228
+ import_zod.z.literal("Article"),
229
+ import_zod.z.literal("NewsArticle"),
230
+ import_zod.z.literal("BlogPosting"),
231
+ import_zod.z.array(import_zod.z.string()).refine(
232
+ (arr) => arr.includes("Article") || arr.includes("NewsArticle") || arr.includes("BlogPosting"),
233
+ {
234
+ message: "Array must contain 'Article', 'NewsArticle', or 'BlogPosting'"
235
+ }
236
+ )
237
+ ]),
238
+ "@id": import_zod.z.string(),
239
+ score: import_zod.z.number(),
240
+ site: import_zod.z.string(),
241
+ headline: import_zod.z.string().optional(),
242
+ description: import_zod.z.string().optional(),
243
+ image: ImageSchema.optional(),
244
+ author: import_zod.z.any().optional(),
245
+ publisher: import_zod.z.any().optional(),
246
+ datePublished: import_zod.z.string().optional(),
247
+ dateModified: import_zod.z.string().optional(),
248
+ thumbnailUrl: import_zod.z.string().optional()
249
+ }).passthrough();
250
+ function isArticleResult(result) {
251
+ return resultTypeIs(result, "Article") || resultTypeIs(result, "NewsArticle") || resultTypeIs(result, "BlogPosting");
252
+ }
253
+ var MovieSchema = import_zod.z.object({
254
+ "@type": import_zod.z.union([
255
+ import_zod.z.literal("Movie"),
256
+ import_zod.z.array(import_zod.z.string()).refine((arr) => arr.includes("Movie"), {
257
+ message: "Array must contain 'Movie'"
258
+ })
259
+ ]),
260
+ "@id": import_zod.z.string(),
261
+ score: import_zod.z.number(),
262
+ site: import_zod.z.string(),
263
+ name: import_zod.z.string().optional(),
264
+ description: import_zod.z.string().optional(),
265
+ image: ImageSchema.optional(),
266
+ url: import_zod.z.string().optional(),
267
+ genre: import_zod.z.array(import_zod.z.string()).optional(),
268
+ datePublished: import_zod.z.string().optional(),
269
+ director: import_zod.z.union([PersonSchema, import_zod.z.array(PersonSchema)]).optional(),
270
+ actor: import_zod.z.union([PersonSchema, import_zod.z.array(PersonSchema)]).optional(),
271
+ aggregateRating: AggregateRatingSchema.optional(),
272
+ duration: import_zod.z.string().optional(),
273
+ contentRating: import_zod.z.string().optional(),
274
+ productionCompany: import_zod.z.union([OrganizationSchema, import_zod.z.array(OrganizationSchema)]).optional(),
275
+ trailer: VideoObjectSchema.optional(),
276
+ review: import_zod.z.union([ReviewSchema, import_zod.z.array(ReviewSchema)]).optional(),
277
+ sameAs: import_zod.z.array(import_zod.z.string()).optional(),
278
+ // Additional schema.org/Movie properties
279
+ countryOfOrigin: import_zod.z.any().optional(),
280
+ musicBy: import_zod.z.union([PersonSchema, import_zod.z.array(PersonSchema)]).optional(),
281
+ producer: import_zod.z.union([
282
+ PersonSchema,
283
+ OrganizationSchema,
284
+ import_zod.z.array(import_zod.z.union([PersonSchema, OrganizationSchema]))
285
+ ]).optional()
286
+ }).passthrough();
287
+ function isMovieResult(result) {
288
+ return resultTypeIs(result, "Movie");
289
+ }
290
+ var SummarySchema = import_zod.z.object({
291
+ "@type": import_zod.z.literal("Summary"),
292
+ text: import_zod.z.string()
293
+ }).passthrough();
294
+ function parseSchema(data) {
295
+ const recipeResult = RecipeSchema.safeParse(data);
296
+ if (recipeResult.success) {
297
+ return recipeResult.data;
298
+ }
299
+ const movieResult = MovieSchema.safeParse(data);
300
+ if (movieResult.success) {
301
+ return movieResult.data;
302
+ }
303
+ const articleResult = ArticleSchema.safeParse(data);
304
+ if (articleResult.success) {
305
+ return articleResult.data;
306
+ }
307
+ const summaryResult = SummarySchema.safeParse(data);
308
+ if (summaryResult.success) {
309
+ return summaryResult.data;
310
+ } else {
311
+ console.log("failed to parse", data);
312
+ }
313
+ return null;
314
+ }
315
+
316
+ // src/lib/useNlWeb.ts
317
+ function convertParamsToRequest(params, site, numRetrievalResults = 50, maxResults = 9) {
318
+ const v054Request = {
319
+ query: {
320
+ text: params.query,
321
+ site,
322
+ max_results: maxResults,
323
+ num_results: numRetrievalResults
324
+ },
325
+ prefer: {
326
+ streaming: true,
327
+ response_format: "conv_search",
328
+ mode: "list, summarize"
329
+ },
330
+ meta: {
331
+ api_version: "0.54",
332
+ start_num: params.resultOffset || 0
333
+ }
334
+ };
335
+ if (params.userId) {
336
+ v054Request.meta.user = {
337
+ id: params.userId
338
+ };
339
+ }
340
+ if (params.remember) {
341
+ v054Request.meta.remember = true;
342
+ }
343
+ if (params.conversationHistory && params.conversationHistory.length > 0) {
344
+ v054Request.context = {
345
+ "@type": "ConversationalContext",
346
+ prev: params.conversationHistory.slice(-5)
347
+ // Last 5 queries
348
+ };
349
+ }
350
+ return v054Request;
351
+ }
352
+ function useNlWeb(config) {
353
+ const { endpoint, site, maxResults = 9, numRetrievalResults = 50 } = config;
354
+ const [state, setState] = (0, import_react.useState)({
355
+ results: [],
356
+ query: null,
357
+ error: null,
358
+ rawLogs: [],
359
+ streamingIndex: -1,
360
+ loading: false
361
+ });
362
+ const abortControllerRef = (0, import_react.useRef)(null);
363
+ const sortResultsByScore = (0, import_react.useCallback)(
364
+ (results) => {
365
+ return [...results].sort((a, b) => {
366
+ const scoreA = a.score || 0;
367
+ const scoreB = b.score || 0;
368
+ return scoreB - scoreA;
369
+ });
370
+ },
371
+ []
372
+ );
373
+ const handleStreamingResponse = (0, import_react.useCallback)(
374
+ async (response) => {
375
+ const reader = response.body?.getReader();
376
+ if (!reader) {
377
+ throw new Error("Response body is not readable");
378
+ }
379
+ const decoder = new TextDecoder();
380
+ let buffer = "";
381
+ const accumulatedResults = [];
382
+ let summary = "";
383
+ let decontextualizedQuery = "";
384
+ const debugLogs = [];
385
+ try {
386
+ while (true) {
387
+ const { value, done } = await reader.read();
388
+ if (done) break;
389
+ buffer += decoder.decode(value, { stream: true });
390
+ const lines = buffer.split("\n");
391
+ buffer = lines.pop() || "";
392
+ for (const line of lines) {
393
+ if (!line.trim() || !line.startsWith("data: ")) continue;
394
+ try {
395
+ const dataStr = line.slice(6);
396
+ const data = JSON.parse(dataStr);
397
+ debugLogs.push(data);
398
+ if (data._meta) {
399
+ if (data._meta.response_type === "Failure" && data.error) {
400
+ const error = data.error;
401
+ throw new Error(`Error (${error.code}): ${error.message}`);
402
+ } else if (data._meta.decontextualized_query) {
403
+ decontextualizedQuery = data._meta.decontextualized_query;
404
+ setState((prev) => ({
405
+ ...prev,
406
+ rawLogs: debugLogs,
407
+ decontextualizedQuery
408
+ }));
409
+ }
410
+ }
411
+ if (data.results && Array.isArray(data.results)) {
412
+ data.results.forEach((result) => {
413
+ const parsed = parseSchema(result);
414
+ if (parsed) {
415
+ if (parsed["@type"] == "Summary") {
416
+ summary = parsed.text;
417
+ } else {
418
+ const exists = accumulatedResults.some(
419
+ (item) => item["@id"] == parsed["@id"]
420
+ );
421
+ if (!exists) {
422
+ accumulatedResults.push(parsed);
423
+ }
424
+ }
425
+ }
426
+ });
427
+ const sortedResults = sortResultsByScore(accumulatedResults);
428
+ setState((prev) => ({
429
+ ...prev,
430
+ rawLogs: debugLogs,
431
+ summary,
432
+ results: sortedResults,
433
+ decontextualizedQuery
434
+ }));
435
+ }
436
+ if (data.structuredData && Array.isArray(data.structuredData)) {
437
+ data.structuredData.forEach((result) => {
438
+ const exists = accumulatedResults.some(
439
+ (item) => item.url && item.url === result.url || item.name && item.name === result.name
440
+ );
441
+ if (!exists) {
442
+ accumulatedResults.push(result);
443
+ }
444
+ });
445
+ const sortedResults = sortResultsByScore(accumulatedResults);
446
+ setState((prev) => ({
447
+ ...prev,
448
+ rawLogs: debugLogs,
449
+ results: sortedResults,
450
+ decontextualizedQuery
451
+ }));
452
+ }
453
+ } catch (err) {
454
+ console.error("Error parsing SSE line:", err, "Line:", line);
455
+ }
456
+ }
457
+ }
458
+ return {
459
+ results: sortResultsByScore(accumulatedResults),
460
+ summary,
461
+ decontextualizedQuery,
462
+ rawLogs: debugLogs
463
+ };
464
+ } finally {
465
+ reader.releaseLock();
466
+ }
467
+ },
468
+ [sortResultsByScore]
469
+ );
470
+ const search = (0, import_react.useCallback)(
471
+ async (params) => {
472
+ if (abortControllerRef.current) {
473
+ abortControllerRef.current.abort();
474
+ }
475
+ const abortController = new AbortController();
476
+ abortControllerRef.current = abortController;
477
+ const query = params.query;
478
+ const streamingIndex = params.conversationHistory ? params.conversationHistory.length : 0;
479
+ setState({
480
+ results: [],
481
+ query,
482
+ error: null,
483
+ rawLogs: [],
484
+ streamingIndex,
485
+ resultOffset: params.resultOffset || 0,
486
+ loading: true
487
+ });
488
+ try {
489
+ const v054Request = convertParamsToRequest(
490
+ params,
491
+ site,
492
+ numRetrievalResults,
493
+ maxResults
494
+ );
495
+ const response = await fetch(endpoint, {
496
+ method: "POST",
497
+ headers: {
498
+ "Content-Type": "application/json",
499
+ Accept: "text/event-stream"
500
+ },
501
+ body: JSON.stringify(v054Request),
502
+ signal: abortController.signal
503
+ });
504
+ if (!response.ok) {
505
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
506
+ }
507
+ const results = await handleStreamingResponse(response);
508
+ setState({
509
+ results: results.results,
510
+ summary: results.summary,
511
+ decontextualizedQuery: results.decontextualizedQuery,
512
+ error: null,
513
+ query,
514
+ resultOffset: params.resultOffset,
515
+ streamingIndex,
516
+ rawLogs: results.rawLogs,
517
+ loading: false
518
+ });
519
+ return results;
520
+ } catch (error) {
521
+ if (error.name !== "AbortError") {
522
+ const errorMessage = error.message || "An error occurred during search";
523
+ setState({
524
+ results: [],
525
+ query: null,
526
+ error: errorMessage,
527
+ rawLogs: [],
528
+ streamingIndex,
529
+ loading: false
530
+ });
531
+ throw error;
532
+ }
533
+ return {
534
+ results: [],
535
+ rawLogs: []
536
+ };
537
+ }
538
+ },
539
+ [endpoint, site, maxResults, handleStreamingResponse]
540
+ );
541
+ const cancelSearch = (0, import_react.useCallback)(() => {
542
+ if (abortControllerRef.current) {
543
+ abortControllerRef.current.abort();
544
+ abortControllerRef.current = null;
545
+ setState((prev) => ({
546
+ ...prev,
547
+ query: null
548
+ }));
549
+ }
550
+ }, []);
551
+ const clearResults = (0, import_react.useCallback)(() => {
552
+ setState({
553
+ results: [],
554
+ query: null,
555
+ error: null,
556
+ streamingIndex: -1,
557
+ loading: false
558
+ });
559
+ }, []);
560
+ (0, import_react.useEffect)(() => {
561
+ clearResults();
562
+ }, [site]);
563
+ return {
564
+ ...state,
565
+ search,
566
+ cancelSearch,
567
+ clearResults
568
+ };
569
+ }
570
+
571
+ // src/components/ChatSearch.tsx
572
+ var import_react6 = require("@headlessui/react");
573
+ var import_solid2 = require("@heroicons/react/24/solid");
574
+ var import_clsx2 = require("clsx");
575
+
576
+ // src/components/SearchQuery.tsx
577
+ var import_react2 = require("react");
578
+ var import_react3 = require("@headlessui/react");
579
+ var import_solid = require("@heroicons/react/24/solid");
580
+ var import_clsx = require("clsx");
581
+ var import_LexicalComposer = require("@lexical/react/LexicalComposer");
582
+ var import_LexicalPlainTextPlugin = require("@lexical/react/LexicalPlainTextPlugin");
583
+ var import_LexicalContentEditable = require("@lexical/react/LexicalContentEditable");
584
+ var import_LexicalHistoryPlugin = require("@lexical/react/LexicalHistoryPlugin");
585
+ var import_LexicalComposerContext = require("@lexical/react/LexicalComposerContext");
586
+ var import_useLexicalIsTextContentEmpty = require("@lexical/react/useLexicalIsTextContentEmpty");
587
+ var import_lexical = require("lexical");
588
+ var import_jsx_runtime = require("react/jsx-runtime");
589
+ function EnterKeyPlugin({
590
+ onSubmit,
591
+ disabled
592
+ }) {
593
+ const [editor] = (0, import_LexicalComposerContext.useLexicalComposerContext)();
594
+ (0, import_react2.useEffect)(() => {
595
+ return editor.registerCommand(
596
+ import_lexical.KEY_ENTER_COMMAND,
597
+ (event) => {
598
+ if (disabled) {
599
+ event.preventDefault();
600
+ return true;
601
+ }
602
+ if (event.shiftKey) {
603
+ return false;
604
+ } else {
605
+ event.preventDefault();
606
+ onSubmit();
607
+ return true;
608
+ }
609
+ },
610
+ import_lexical.COMMAND_PRIORITY_HIGH
611
+ );
612
+ }, [editor, onSubmit, disabled]);
613
+ return null;
614
+ }
615
+ function InitialValuePlugin({ initQuery }) {
616
+ const [editor] = (0, import_LexicalComposerContext.useLexicalComposerContext)();
617
+ (0, import_react2.useEffect)(() => {
618
+ if (initQuery) {
619
+ editor.update(() => {
620
+ const root = (0, import_lexical.$getRoot)();
621
+ root.clear();
622
+ const paragraph = (0, import_lexical.$createParagraphNode)();
623
+ paragraph.append((0, import_lexical.$createTextNode)(initQuery));
624
+ root.append(paragraph);
625
+ });
626
+ }
627
+ }, [editor, initQuery]);
628
+ return null;
629
+ }
630
+ function FocusPlugin({
631
+ onFocusChange
632
+ }) {
633
+ const [editor] = (0, import_LexicalComposerContext.useLexicalComposerContext)();
634
+ (0, import_react2.useEffect)(() => {
635
+ return editor.registerRootListener((rootElement, prevRootElement) => {
636
+ if (prevRootElement !== null) {
637
+ prevRootElement.removeEventListener("focus", () => onFocusChange(true));
638
+ prevRootElement.removeEventListener("blur", () => onFocusChange(false));
639
+ }
640
+ if (rootElement !== null) {
641
+ rootElement.addEventListener("focus", () => onFocusChange(true));
642
+ rootElement.addEventListener("blur", () => onFocusChange(false));
643
+ }
644
+ });
645
+ }, [editor, onFocusChange]);
646
+ return null;
647
+ }
648
+ function EditorStatePlugin({
649
+ editorRef,
650
+ onEmptyChange,
651
+ onMultilineChange
652
+ }) {
653
+ const [editor] = (0, import_LexicalComposerContext.useLexicalComposerContext)();
654
+ const isEmpty = (0, import_useLexicalIsTextContentEmpty.useLexicalIsTextContentEmpty)(editor);
655
+ const initialHeightRef = (0, import_react2.useRef)(null);
656
+ const isMultilineRef = (0, import_react2.useRef)(false);
657
+ (0, import_react2.useEffect)(() => {
658
+ editorRef.current = editor;
659
+ return () => {
660
+ editorRef.current = null;
661
+ };
662
+ }, [editor, editorRef]);
663
+ (0, import_react2.useEffect)(() => {
664
+ onEmptyChange(isEmpty);
665
+ if (isEmpty && isMultilineRef.current) {
666
+ isMultilineRef.current = false;
667
+ onMultilineChange(false);
668
+ }
669
+ }, [isEmpty, onEmptyChange, onMultilineChange]);
670
+ (0, import_react2.useEffect)(() => {
671
+ const rootElement = editor.getRootElement();
672
+ if (!rootElement) return;
673
+ if (initialHeightRef.current === null) {
674
+ initialHeightRef.current = rootElement.offsetHeight;
675
+ }
676
+ const resizeObserver = new ResizeObserver((entries) => {
677
+ for (const entry of entries) {
678
+ const currentHeight = entry.contentRect.height;
679
+ if (initialHeightRef.current !== null && currentHeight >= initialHeightRef.current) {
680
+ if (!isMultilineRef.current) {
681
+ isMultilineRef.current = true;
682
+ onMultilineChange(true);
683
+ }
684
+ }
685
+ }
686
+ });
687
+ resizeObserver.observe(rootElement);
688
+ return () => {
689
+ resizeObserver.disconnect();
690
+ };
691
+ }, [editor, onMultilineChange]);
692
+ return null;
693
+ }
694
+ function SearchQuery({
695
+ initQuery,
696
+ className,
697
+ inputClassName,
698
+ loading,
699
+ handleSearch,
700
+ placeholder = "Ask anything..."
701
+ }) {
702
+ const [isFocused, setIsFocused] = (0, import_react2.useState)(false);
703
+ const [isMultiline, setIsMultiline] = (0, import_react2.useState)(false);
704
+ const [hasText, setHasText] = (0, import_react2.useState)(!!initQuery);
705
+ const editorRef = (0, import_react2.useRef)(null);
706
+ const initialConfig = {
707
+ namespace: "SearchQuery",
708
+ theme: {
709
+ paragraph: "editor-paragraph",
710
+ text: {
711
+ bold: "editor-text-bold",
712
+ italic: "editor-text-italic",
713
+ underline: "editor-text-underline"
714
+ }
715
+ },
716
+ onError: (error) => {
717
+ console.error(error);
718
+ }
719
+ };
720
+ const handleSubmit = (0, import_react2.useCallback)(async () => {
721
+ if (!editorRef.current || loading) return;
722
+ const query = editorRef.current.getEditorState().read(() => {
723
+ const root = (0, import_lexical.$getRoot)();
724
+ return root.getTextContent();
725
+ });
726
+ if (query.trim()) {
727
+ await handleSearch(query);
728
+ }
729
+ }, [loading, handleSearch]);
730
+ const handleEmptyChange = (0, import_react2.useCallback)((isEmpty) => {
731
+ setHasText(!isEmpty);
732
+ }, []);
733
+ const handleMultilineChange = (0, import_react2.useCallback)((isMultiline2) => {
734
+ setIsMultiline(isMultiline2);
735
+ }, []);
736
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_LexicalComposer.LexicalComposer, { initialConfig, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
737
+ "div",
738
+ {
739
+ className: (0, import_clsx.clsx)(
740
+ `flex relative rounded-lg border transition-all duration-200`,
741
+ isFocused ? "border-gray-400 shadow-md ring-2 ring-gray-100" : "border-gray-200 hover:border-gray-300",
742
+ isMultiline ? "flex-col items-stretch gap-0" : "flex-row items-center gap-3",
743
+ className || "bg-white"
744
+ ),
745
+ children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
747
+ "div",
748
+ {
749
+ className: (0, import_clsx.clsx)(
750
+ "absolute left-3.5 pointer-events-none z-10",
751
+ isMultiline ? "hidden" : ""
752
+ ),
753
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_solid.MagnifyingGlassIcon, { className: "size-4 text-gray-400" })
754
+ }
755
+ ),
756
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 relative", children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
758
+ import_LexicalPlainTextPlugin.PlainTextPlugin,
759
+ {
760
+ contentEditable: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
761
+ import_LexicalContentEditable.ContentEditable,
762
+ {
763
+ className: (0, import_clsx.clsx)(
764
+ "outline-none flex-1 m-0 rounded-md text-base px-4 py-3 text-gray-900",
765
+ isMultiline ? "pl-4" : "pl-10 pr-12",
766
+ inputClassName,
767
+ loading && "opacity-50 cursor-not-allowed"
768
+ ),
769
+ "aria-placeholder": placeholder,
770
+ placeholder: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
771
+ "div",
772
+ {
773
+ className: (0, import_clsx.clsx)(
774
+ "absolute top-3 text-base text-gray-400 pointer-events-none select-none",
775
+ isMultiline ? "left-4" : "left-10 truncate right-10"
776
+ ),
777
+ children: placeholder
778
+ }
779
+ )
780
+ }
781
+ ),
782
+ ErrorBoundary: () => null
783
+ }
784
+ ),
785
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_LexicalHistoryPlugin.HistoryPlugin, {}),
786
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EnterKeyPlugin, { onSubmit: handleSubmit, disabled: loading }),
787
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InitialValuePlugin, { initQuery }),
788
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusPlugin, { onFocusChange: setIsFocused }),
789
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
790
+ EditorStatePlugin,
791
+ {
792
+ editorRef,
793
+ onEmptyChange: handleEmptyChange,
794
+ onMultilineChange: handleMultilineChange
795
+ }
796
+ )
797
+ ] }),
798
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
799
+ "div",
800
+ {
801
+ className: (0, import_clsx.clsx)(
802
+ isMultiline ? "relative flex justify-end p-2" : "absolute right-2 "
803
+ ),
804
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
805
+ import_react3.Button,
806
+ {
807
+ type: "button",
808
+ onClick: handleSubmit,
809
+ disabled: !hasText || loading,
810
+ className: `p-2 rounded-md transition-all duration-200 ${hasText && !loading ? "bg-black text-white hover:bg-gray-800 active:scale-95" : "bg-gray-100 text-gray-400 cursor-not-allowed"}`,
811
+ "aria-label": "Submit search",
812
+ children: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
813
+ "svg",
814
+ {
815
+ className: "w-4 h-4 animate-spin",
816
+ fill: "none",
817
+ viewBox: "0 0 24 24",
818
+ children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
820
+ "circle",
821
+ {
822
+ className: "opacity-25",
823
+ cx: "12",
824
+ cy: "12",
825
+ r: "10",
826
+ stroke: "currentColor",
827
+ strokeWidth: "4"
828
+ }
829
+ ),
830
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
831
+ "path",
832
+ {
833
+ className: "opacity-75",
834
+ fill: "currentColor",
835
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
836
+ }
837
+ )
838
+ ]
839
+ }
840
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_solid.ArrowRightIcon, { className: "size-4" })
841
+ }
842
+ )
843
+ }
844
+ )
845
+ ]
846
+ }
847
+ ) });
848
+ }
849
+
850
+ // src/lib/useAutoScroll.ts
851
+ var import_react4 = require("react");
852
+ var useAutoScroll = (dependency) => {
853
+ const containerRef = (0, import_react4.useRef)(null);
854
+ const anchorRef = (0, import_react4.useRef)(null);
855
+ const shouldScrollRef = (0, import_react4.useRef)(true);
856
+ const scrollToAnchor = (0, import_react4.useCallback)(() => {
857
+ if (anchorRef.current) {
858
+ anchorRef.current.scrollIntoView({
859
+ behavior: "smooth",
860
+ block: "center"
861
+ });
862
+ }
863
+ }, []);
864
+ (0, import_react4.useEffect)(() => {
865
+ if (shouldScrollRef.current) {
866
+ scrollToAnchor();
867
+ }
868
+ }, dependency);
869
+ return { containerRef, anchorRef };
870
+ };
871
+
872
+ // src/components/ChatSearch.tsx
873
+ var import_jsx_runtime2 = require("react/jsx-runtime");
874
+ function decodeHtmlEntities(text) {
875
+ return text.replace(
876
+ /&#x([0-9a-fA-F]+);/g,
877
+ (_, hex) => String.fromCharCode(parseInt(hex, 16))
878
+ ).replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(parseInt(dec, 10))).replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&nbsp;/g, " ");
879
+ }
880
+ function ResultCardSkeleton() {
881
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "block w-full transition-all overflow-hidden shimmer-container", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col gap-3", children: [
882
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-36 w-full shimmer shimmer-bg shimmer-color-gray-300/30 [--shimmer-x:60] [--shimmer-y:0] bg-gray-100 rounded" }),
883
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0 space-y-2", children: [
884
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 bg-gray-100 rounded w-3/4" }),
885
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-1", children: [
886
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-3 bg-gray-100 rounded w-full" }),
887
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-3 bg-gray-100 rounded w-5/6" }),
888
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-3 bg-gray-100 rounded w-5/6" })
889
+ ] }),
890
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-2 bg-gray-100 rounded w-1/6" })
891
+ ] })
892
+ ] }) });
893
+ }
894
+ function ResultCard({ result }) {
895
+ const srcs = getThumbnailCandidates(result);
896
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
897
+ "a",
898
+ {
899
+ href: result.url || result.grounding || "#",
900
+ target: "_blank",
901
+ rel: "noopener noreferrer",
902
+ className: "block no-underline! transition-all duration-200 overflow-hidden",
903
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col gap-3", children: [
904
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
905
+ Thumbnail,
906
+ {
907
+ srcs,
908
+ alt: decodeHtmlEntities(
909
+ result.name || result.title || "Result image"
910
+ )
911
+ }
912
+ ),
913
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0", children: [
914
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-medium text-gray-900 text-sm mb-1 line-clamp-2", children: decodeHtmlEntities(
915
+ result.name || result.title || "Untitled"
916
+ ) }),
917
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ResultCardDetails, { result }),
918
+ result.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-600 line-clamp-3 mb-2", children: typeof result.description == "string" ? decodeHtmlEntities(result.description) : "" }),
919
+ result.site && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1 text-xs text-gray-500", children: [
920
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
921
+ "svg",
922
+ {
923
+ className: "w-3 h-3",
924
+ fill: "none",
925
+ stroke: "currentColor",
926
+ viewBox: "0 0 24 24",
927
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
928
+ "path",
929
+ {
930
+ strokeLinecap: "round",
931
+ strokeLinejoin: "round",
932
+ strokeWidth: 2,
933
+ d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
934
+ }
935
+ )
936
+ }
937
+ ),
938
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate", children: result.site })
939
+ ] })
940
+ ] })
941
+ ] })
942
+ }
943
+ );
944
+ }
945
+ function ResultCardDetails({ result }) {
946
+ if (isMovieResult(result)) {
947
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
948
+ result.director && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-xs text-gray-500 font-semibold", children: Array.isArray(result.director) ? result.director.map((d) => d.name).join(", ") : result.director.name }),
949
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center gap-1", children: intersperse(
950
+ [
951
+ result.aggregateRating?.ratingValue ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex items-center gap-1", children: [
952
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-yellow-500", children: "\u2605" }),
953
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs", children: typeof result.aggregateRating.ratingValue === "number" ? result.aggregateRating.ratingValue.toFixed(1) : result.aggregateRating.ratingValue })
954
+ ] }) : null,
955
+ result.aggregateRating?.ratingCount ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs text-gray-500", children: [
956
+ shortQuantity(result.aggregateRating.ratingCount),
957
+ " review",
958
+ result.aggregateRating.ratingCount != 1 ? "s" : ""
959
+ ] }) : null
960
+ ].filter(Boolean),
961
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs text-gray-400", children: "|" })
962
+ ) })
963
+ ] });
964
+ }
965
+ return null;
966
+ }
967
+ function Thumbnail({
968
+ srcs,
969
+ className,
970
+ ...rest
971
+ }) {
972
+ const [srcIndex, setSrcIndex] = (0, import_react5.useState)(0);
973
+ function advance() {
974
+ setSrcIndex((srcIndex2) => {
975
+ const nextIndex = srcIndex2 + 1;
976
+ return Math.min(nextIndex, srcs.length);
977
+ });
978
+ }
979
+ const srcsExhausted = srcIndex >= srcs.length;
980
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
981
+ "div",
982
+ {
983
+ className: (0, import_clsx2.clsx)(
984
+ "relative text-xs flex-shrink-0 h-36 rounded",
985
+ srcsExhausted && "bg-gray-100 flex items-center justify-center",
986
+ className
987
+ ),
988
+ children: [
989
+ srcsExhausted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_solid2.NewspaperIcon, { className: "absolute size-5 text-gray-400" }) : null,
990
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
991
+ "img",
992
+ {
993
+ src: srcs[srcIndex],
994
+ className: (0, import_clsx2.clsx)(
995
+ "w-full! h-full! object-cover! rounded!",
996
+ srcsExhausted && "invisible"
997
+ ),
998
+ ...rest,
999
+ onError: advance
1000
+ }
1001
+ )
1002
+ ]
1003
+ }
1004
+ );
1005
+ }
1006
+ function SummarySkeleton() {
1007
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3 w-full md:min-w-md shimmer-container", children: [
1008
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 shimmer shimmer-bg shimmer-color-gray-400/20 [--shimmer-x:60] [--shimmer-y:0] bg-gray-200 rounded-md w-full" }),
1009
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 shimmer shimmer-bg shimmer-color-gray-400/20 [--shimmer-x:60] [--shimmer-y:20] bg-gray-200 rounded-md w-11/12" }),
1010
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 shimmer shimmer-bg shimmer-color-gray-400/20 [--shimmer-x:60] [--shimmer-y:40] bg-gray-200 rounded-md w-full" }),
1011
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 shimmer shimmer-bg shimmer-color-gray-400/20 [--shimmer-x:60] [--shimmer-y:60] bg-gray-200 rounded-md w-10/12" }),
1012
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-4 shimmer shimmer-bg shimmer-color-gray-400/20 [--shimmer-x:60] [--shimmer-y:80] bg-gray-200 rounded-md w-full" })
1013
+ ] });
1014
+ }
1015
+ function SummaryCard({ summary }) {
1016
+ if (summary) {
1017
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-lg text-gray-800 leading-relaxed", children: summary });
1018
+ }
1019
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SummarySkeleton, {});
1020
+ }
1021
+ function SearchingFor({
1022
+ query,
1023
+ streaming
1024
+ }) {
1025
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1026
+ "div",
1027
+ {
1028
+ className: (0, import_clsx2.clsx)(
1029
+ "text-gray-500 gap-1 flex items-center text-sm pb-2 px-2",
1030
+ streaming && "shimmer"
1031
+ ),
1032
+ children: query ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-gray-800 overflow-ellipse", children: [
1033
+ "Searching for: ",
1034
+ query
1035
+ ] }, query) : "Working on it"
1036
+ }
1037
+ );
1038
+ }
1039
+ function PageButton({
1040
+ page,
1041
+ onClick,
1042
+ activePage,
1043
+ disabled = true
1044
+ }) {
1045
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1046
+ import_react6.Button,
1047
+ {
1048
+ disabled,
1049
+ onClick,
1050
+ className: (0, import_clsx2.clsx)(
1051
+ "text-sm p-2 size-6 rounded-md transition-colors duration-200 hover:bg-gray-100 flex items-center justify-center",
1052
+ page == activePage ? "text-gray-700" : "text-gray-400",
1053
+ disabled ? "opacity-50 pointer-events-none" : ""
1054
+ ),
1055
+ children: page + 1
1056
+ }
1057
+ );
1058
+ }
1059
+ function AssistantMessage({
1060
+ summary,
1061
+ results,
1062
+ loading,
1063
+ addResults,
1064
+ followUpQuery,
1065
+ config,
1066
+ anchorRef
1067
+ }) {
1068
+ const nlweb = useNlWeb(config);
1069
+ const maxResults = config.maxResults || 50;
1070
+ const numRetrievalResults = config.numRetrievalResults || 50;
1071
+ const pagesAvailable = Math.floor(numRetrievalResults / maxResults);
1072
+ const [page, setPage] = (0, import_react5.useState)(0);
1073
+ const pageRange = Array.from(
1074
+ { length: pagesAvailable + 1 },
1075
+ (_, index) => index
1076
+ );
1077
+ async function viewMoreResults(pageNumber) {
1078
+ setPage(pageNumber);
1079
+ const offsetToFetch = pageNumber * maxResults;
1080
+ if (results.length <= offsetToFetch) {
1081
+ const response = await nlweb.search({
1082
+ query: followUpQuery,
1083
+ conversationHistory: [],
1084
+ resultOffset: offsetToFetch
1085
+ });
1086
+ await addResults(response.results);
1087
+ }
1088
+ }
1089
+ const pageOffset = page * maxResults;
1090
+ const isStreamingPage = pageOffset == nlweb.resultOffset;
1091
+ const resultsOfPage = isStreamingPage ? nlweb.results : results.slice(pageOffset, (page + 1) * maxResults);
1092
+ const skeletonCount = Math.max(0, 9 - resultsOfPage.length);
1093
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-3xl flex-1 bg-gray-50 p-6 rounded-lg", children: [
1094
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-4 mb-2", children: [
1095
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SummaryCard, { summary }),
1096
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: anchorRef }),
1097
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6", children: [
1098
+ resultsOfPage.map((r, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ResultCard, { result: r }, r.url || r.name || idx)),
1099
+ (loading || nlweb.loading && isStreamingPage) && Array.from({ length: skeletonCount }).map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ResultCardSkeleton, {}, `skeleton-${idx}`))
1100
+ ] })
1101
+ ] }),
1102
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex mt-4 -mx-2 items-center gap-2", children: pageRange.map(
1103
+ (p) => results.length >= p * maxResults && (p + 1) * maxResults < numRetrievalResults && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1104
+ PageButton,
1105
+ {
1106
+ onClick: () => viewMoreResults(p),
1107
+ page: p,
1108
+ activePage: page,
1109
+ disabled: loading
1110
+ },
1111
+ p
1112
+ )
1113
+ ) })
1114
+ ] }) });
1115
+ }
1116
+ function QueryMessage({ query }) {
1117
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex justify-end mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "max-w-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "bg-gray-900 text-white rounded-2xl rounded-tr-sm px-4 py-3 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm leading-relaxed whitespace-pre-line", children: query }) }) }) });
1118
+ }
1119
+ function ChatEntry({
1120
+ index,
1121
+ query,
1122
+ loading,
1123
+ decontextualizedQuery,
1124
+ summary,
1125
+ results,
1126
+ config,
1127
+ addResults,
1128
+ anchorRef
1129
+ }) {
1130
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1131
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(QueryMessage, { query }) : null,
1132
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SearchingFor, { streaming: loading, query: decontextualizedQuery }) : null,
1133
+ results.length > 0 || loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1134
+ AssistantMessage,
1135
+ {
1136
+ anchorRef,
1137
+ summary,
1138
+ results,
1139
+ loading,
1140
+ followUpQuery: decontextualizedQuery || query,
1141
+ addResults,
1142
+ config
1143
+ }
1144
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex max-w-3xl text-base text-gray-500 justify-start bg-gray-50 p-6 rounded-lg", children: "No results found" })
1145
+ ] }, `${query}-${index}`);
1146
+ }
1147
+ function ChatResults({
1148
+ nlweb,
1149
+ config,
1150
+ searches,
1151
+ addResults,
1152
+ anchorRef
1153
+ }) {
1154
+ const combinedStreamedResults = searches.length - 1 == nlweb.streamingIndex && searches[nlweb.streamingIndex]?.response ? [
1155
+ ...nlweb.results,
1156
+ ...searches[nlweb.streamingIndex].response.results.slice(
1157
+ nlweb.results.length
1158
+ )
1159
+ ] : nlweb.results;
1160
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-4 py-6", children: [
1161
+ searches.map(
1162
+ (r, idx) => idx != nlweb.streamingIndex && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1163
+ ChatEntry,
1164
+ {
1165
+ loading: false,
1166
+ index: idx,
1167
+ query: r.query,
1168
+ results: r.response.results,
1169
+ summary: r.response.summary,
1170
+ decontextualizedQuery: r.response.decontextualizedQuery,
1171
+ config,
1172
+ addResults: (results) => addResults(r.id || "", results)
1173
+ },
1174
+ `${r.query}-${idx}`
1175
+ )
1176
+ ),
1177
+ nlweb.query && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1178
+ ChatEntry,
1179
+ {
1180
+ index: nlweb.streamingIndex,
1181
+ query: nlweb.query,
1182
+ results: combinedStreamedResults,
1183
+ summary: nlweb.summary,
1184
+ decontextualizedQuery: nlweb.decontextualizedQuery,
1185
+ loading: nlweb.loading,
1186
+ anchorRef,
1187
+ config,
1188
+ addResults: (r) => addResults(searches[nlweb.streamingIndex].id || "", r)
1189
+ },
1190
+ `${nlweb.query}-${nlweb.streamingIndex}`
1191
+ )
1192
+ ] });
1193
+ }
1194
+ function ChatSearch({
1195
+ searches,
1196
+ addSearch,
1197
+ addResults,
1198
+ startSession,
1199
+ endSession,
1200
+ nlweb,
1201
+ config,
1202
+ children,
1203
+ sidebar,
1204
+ sessionId = "NLWEB_DEFAULT_SESSION"
1205
+ }) {
1206
+ const { anchorRef } = useAutoScroll([nlweb.query]);
1207
+ const [searchOpen, setSearchOpen] = (0, import_react5.useState)(searches.length > 0);
1208
+ function closeSearch() {
1209
+ setSearchOpen(false);
1210
+ if (endSession) {
1211
+ endSession();
1212
+ }
1213
+ }
1214
+ async function handleSearch(query, isRoot) {
1215
+ let response;
1216
+ let sId = sessionId;
1217
+ if (isRoot) {
1218
+ sId = await startSession(query) || sessionId;
1219
+ setSearchOpen(true);
1220
+ response = await nlweb.search({
1221
+ query
1222
+ });
1223
+ } else {
1224
+ response = await nlweb.search({
1225
+ query,
1226
+ conversationHistory: searches.map((r) => r.query)
1227
+ });
1228
+ }
1229
+ if (sId) {
1230
+ const search = { query, response, sessionId: sId };
1231
+ await addSearch(search);
1232
+ }
1233
+ }
1234
+ (0, import_react5.useEffect)(() => {
1235
+ if (searches.length > 0 && !searchOpen) {
1236
+ setSearchOpen(true);
1237
+ }
1238
+ }, [searches]);
1239
+ const rootQuery = searches.length > 0 ? searches[0].query : nlweb.query;
1240
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mb-6 min-w-50 max-h-12 relative z-30", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1242
+ SearchQuery,
1243
+ {
1244
+ loading: nlweb.loading,
1245
+ handleSearch: (q) => handleSearch(q, true)
1246
+ }
1247
+ ) }),
1248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1249
+ import_react6.Dialog,
1250
+ {
1251
+ className: "relative z-50",
1252
+ open: searchOpen,
1253
+ onClose: closeSearch,
1254
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fixed bg-white inset-0 w-screen h-screen overflow-hidden", children: [
1255
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1256
+ import_react6.Button,
1257
+ {
1258
+ onClick: closeSearch,
1259
+ className: "z-50 text-gray-500 hover:text-black absolute right-6 top-4",
1260
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_solid2.XMarkIcon, { className: "size-5" })
1261
+ }
1262
+ ),
1263
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1264
+ import_react6.DialogPanel,
1265
+ {
1266
+ className: "w-full h-screen flex items-stretch overflow-hidden",
1267
+ children: [
1268
+ sidebar,
1269
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
1270
+ children,
1271
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "relative flex-1 overflow-hidden flex flex-col", children: [
1272
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 overflow-y-auto p-4 pt-16 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-7xl mx-auto", children: [
1273
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mb-6 max-w-xl mx-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1274
+ SearchQuery,
1275
+ {
1276
+ className: "bg-gray-50",
1277
+ loading: nlweb.loading,
1278
+ handleSearch: (q) => handleSearch(q, true),
1279
+ initQuery: rootQuery
1280
+ },
1281
+ rootQuery || "empty-search"
1282
+ ) }),
1283
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1284
+ ChatResults,
1285
+ {
1286
+ nlweb,
1287
+ searches,
1288
+ addResults,
1289
+ config,
1290
+ anchorRef
1291
+ }
1292
+ )
1293
+ ] }) }),
1294
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute pointer-events-none bottom-0 top-[calc(100%_-_100px)] bg-gradient-to-b from-transparent to-white left-0 right-0" }),
1295
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute bottom-8 left-4 right-4", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "max-w-xl mx-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1296
+ SearchQuery,
1297
+ {
1298
+ loading: nlweb.loading,
1299
+ handleSearch: (q) => handleSearch(q, false),
1300
+ inputClassName: "max-h-[60vh] overflow-y-auto",
1301
+ className: "shadow-xl bg-white",
1302
+ placeholder: "Enter a follow up query"
1303
+ },
1304
+ nlweb.query
1305
+ ) }) })
1306
+ ] })
1307
+ ] })
1308
+ ]
1309
+ }
1310
+ )
1311
+ ] })
1312
+ }
1313
+ )
1314
+ ] });
1315
+ }
1316
+
1317
+ // src/components/HistorySidebar.tsx
1318
+ var import_react7 = require("@headlessui/react");
1319
+ var import_solid3 = require("@heroicons/react/24/solid");
1320
+ var import_react8 = require("@headlessui/react");
1321
+ var import_react9 = require("react");
1322
+ var import_clsx3 = require("clsx");
1323
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1324
+ function SiteBadge({ site }) {
1325
+ const siteParts = site.split(".");
1326
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "px-3 py-2 flex gap-2 items-center text-xs font-medium text-gray-400 uppercase", children: siteParts[0] });
1327
+ }
1328
+ function SessionButton({
1329
+ session,
1330
+ onSelect,
1331
+ onDelete,
1332
+ selected = false
1333
+ }) {
1334
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1335
+ "div",
1336
+ {
1337
+ className: (0, import_clsx3.clsx)(
1338
+ "flex group hover:bg-gray-100 rounded-md overflow-hidden",
1339
+ selected ? "bg-gray-200/50" : ""
1340
+ ),
1341
+ children: [
1342
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1343
+ import_react7.Button,
1344
+ {
1345
+ onClick: onSelect,
1346
+ className: "w-full text-left px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 rounded-md truncate",
1347
+ children: session.query
1348
+ }
1349
+ ),
1350
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1351
+ import_react7.Button,
1352
+ {
1353
+ onClick: onDelete,
1354
+ className: "opacity-0 group-hover:opacity-100 px-2 flex items-center justify-center text-gray-400 hover:text-red-500 rounded-md transition-all",
1355
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_solid3.XMarkIcon, { className: "size-4" })
1356
+ }
1357
+ )
1358
+ ]
1359
+ }
1360
+ );
1361
+ }
1362
+ function HistorySidebar({
1363
+ selected,
1364
+ sessions,
1365
+ onSelect,
1366
+ onDelete,
1367
+ onCreate
1368
+ }) {
1369
+ const [isOpen, setIsOpen] = (0, import_react9.useState)(sessions.length > 1);
1370
+ const groupedSessions = sessions.reduce((acc, session) => {
1371
+ const site = session.backend.site;
1372
+ if (!acc[site]) {
1373
+ acc[site] = [];
1374
+ }
1375
+ acc[site].push(session);
1376
+ return acc;
1377
+ }, {});
1378
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1379
+ "div",
1380
+ {
1381
+ className: (0, import_clsx3.clsx)(
1382
+ "flex-1 flex flex-col relative z-50 transition-all",
1383
+ isOpen ? "max-w-70" : "max-w-12"
1384
+ ),
1385
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col flex-1 overflow-hidden", children: [
1386
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1387
+ "div",
1388
+ {
1389
+ className: (0, import_clsx3.clsx)(
1390
+ "absolute right-2 top-0 h-12 flex items-center",
1391
+ !isOpen ? "left-2 flex justify-center" : ""
1392
+ ),
1393
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1394
+ import_react7.Button,
1395
+ {
1396
+ onClick: () => setIsOpen(!isOpen),
1397
+ className: "text-gray-400 hover:text-gray-700 transition-colors rounded-lg w-7 h-7 hover:bg-gray-50 flex items-center justify-center",
1398
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_solid3.Bars3Icon, { className: "size-5" })
1399
+ }
1400
+ )
1401
+ }
1402
+ ),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1404
+ "div",
1405
+ {
1406
+ className: (0, import_clsx3.clsx)(
1407
+ "border-r min-w-64 bg-gray-50 overflow-y-auto",
1408
+ "flex-1 data-closed:opacity-0"
1409
+ ),
1410
+ children: [
1411
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1412
+ "div",
1413
+ {
1414
+ className: (0, import_clsx3.clsx)(
1415
+ "h-12 items-center font-medium p-4 px-5 pb-0 pointer-events-none text-xs text-gray-500 transition-opacity",
1416
+ isOpen ? "opacity-100" : "opacity-0"
1417
+ ),
1418
+ children: "Chats"
1419
+ }
1420
+ ),
1421
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1422
+ import_react7.Button,
1423
+ {
1424
+ onClick: onCreate,
1425
+ className: (0, import_clsx3.clsx)(
1426
+ "flex items-center gap-2 text-left px-2 py-2 text-sm text-gray-700 hover:bg-gray-100 rounded-md truncate",
1427
+ isOpen ? "w-full" : ""
1428
+ ),
1429
+ children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_solid3.PencilSquareIcon, { className: "size-4 text-gray-400" }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react8.Transition, { show: isOpen, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "New Chat" }) })
1432
+ ]
1433
+ }
1434
+ ) }),
1435
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react8.Transition, { show: isOpen, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "divide-y", children: [
1436
+ Object.entries(groupedSessions).map(([site, siteSessions]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "p-2", children: [
1437
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SiteBadge, { site }),
1438
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "space-y-1", children: siteSessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1439
+ SessionButton,
1440
+ {
1441
+ selected: session.sessionId == selected,
1442
+ session,
1443
+ onSelect: () => onSelect(session),
1444
+ onDelete: () => onDelete(session.sessionId)
1445
+ },
1446
+ session.sessionId
1447
+ )) })
1448
+ ] }, site)),
1449
+ sessions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "px-3 py-8 text-sm text-gray-500 text-center", children: "No search history yet" })
1450
+ ] }) })
1451
+ ]
1452
+ }
1453
+ )
1454
+ ] })
1455
+ }
1456
+ );
1457
+ }
1458
+
1459
+ // src/components/DebugTools.tsx
1460
+ var import_solid4 = require("@heroicons/react/24/solid");
1461
+ var import_react10 = require("react");
1462
+ var import_react11 = require("@headlessui/react");
1463
+ var import_clsx4 = require("clsx");
1464
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1465
+ function translateResultsToNlWebRequests(streamingState, results, config) {
1466
+ const turns = [];
1467
+ for (let i = 0; i < results.length; i++) {
1468
+ const result = results[i];
1469
+ const params = {
1470
+ query: result.query,
1471
+ conversationHistory: i > 0 ? results.slice(0, i).map((r) => r.query) : void 0
1472
+ };
1473
+ const request = convertParamsToRequest(
1474
+ params,
1475
+ config.site,
1476
+ config.numRetrievalResults,
1477
+ config.maxResults
1478
+ );
1479
+ turns.push({
1480
+ request,
1481
+ response: result.response.rawLogs || []
1482
+ });
1483
+ }
1484
+ if (streamingState.query) {
1485
+ const streamingParams = {
1486
+ query: streamingState.query,
1487
+ conversationHistory: results.length > 0 ? results.map((r) => r.query) : void 0
1488
+ };
1489
+ const streamingRequest = convertParamsToRequest(
1490
+ streamingParams,
1491
+ config.site,
1492
+ config.numRetrievalResults,
1493
+ config.maxResults
1494
+ );
1495
+ turns.push({
1496
+ request: streamingRequest,
1497
+ response: streamingState.rawLogs || []
1498
+ });
1499
+ }
1500
+ return turns;
1501
+ }
1502
+ function CodeBlock({ code }) {
1503
+ const [copied, setCopied] = (0, import_react10.useState)(false);
1504
+ const handleCopy = async () => {
1505
+ try {
1506
+ await navigator.clipboard.writeText(code);
1507
+ setCopied(true);
1508
+ setTimeout(() => setCopied(false), 2e3);
1509
+ } catch (err) {
1510
+ console.error("Failed to copy:", err);
1511
+ }
1512
+ };
1513
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative overflow-hidden", children: [
1514
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1515
+ import_react11.Button,
1516
+ {
1517
+ onClick: handleCopy,
1518
+ className: "absolute top-0 right-0 px-3 py-1.5 text-xs font-medium text-gray-600 bg-white border border-gray-300 rounded hover:bg-gray-50 hover:border-gray-400 transition-colors",
1519
+ children: copied ? "Copied!" : "Copy"
1520
+ }
1521
+ ),
1522
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: "overflow-auto text-gray-500 text-sm pr-20", children: code })
1523
+ ] });
1524
+ }
1525
+ function MessagesDialog({
1526
+ isOpen,
1527
+ onClose,
1528
+ searches,
1529
+ streamingState,
1530
+ config
1531
+ }) {
1532
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react11.Dialog, { open: isOpen, onClose, className: "relative z-50", children: [
1533
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "fixed inset-0 bg-black/30", "aria-hidden": "true" }),
1534
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "fixed inset-0 flex items-center justify-center p-4", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react11.DialogPanel, { className: "flex flex-col bg-white rounded-lg shadow-xl max-w-3xl w-full max-h-[80vh] overflow-hidden flex flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react11.TabGroup, { className: "flex flex-col flex-1 overflow-hidden", children: [
1535
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react11.TabList, { className: "flex border-b bg-gray-50", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1536
+ import_react11.Tab,
1537
+ {
1538
+ className: ({ selected }) => (0, import_clsx4.clsx)(
1539
+ "px-6 py-3 text-sm font-medium outline-none transition-colors",
1540
+ selected ? "border-b-2 border-gray-900 text-gray-900" : "text-gray-500 hover:text-gray-700"
1541
+ ),
1542
+ children: "Raw Messages"
1543
+ }
1544
+ ) }),
1545
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react11.TabPanels, { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react11.TabPanel, { className: "p-6", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1546
+ CodeBlock,
1547
+ {
1548
+ code: JSON.stringify(
1549
+ translateResultsToNlWebRequests(
1550
+ streamingState,
1551
+ searches,
1552
+ config
1553
+ ),
1554
+ null,
1555
+ 2
1556
+ )
1557
+ }
1558
+ ) }) })
1559
+ ] }) }) })
1560
+ ] });
1561
+ }
1562
+ function DebugTool({
1563
+ searches,
1564
+ streamingState,
1565
+ config
1566
+ }) {
1567
+ const [messagesOpen, setMessagesOpen] = (0, import_react10.useState)(false);
1568
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1569
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1570
+ import_react11.Button,
1571
+ {
1572
+ onClick: () => setMessagesOpen(true),
1573
+ className: "flex bg-white items-center gap-2 ml-auto text-gray-600 hover:bg-gray-100 p-3 py-2 rounded-md text-sm",
1574
+ children: [
1575
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_solid4.BugAntIcon, { className: "size-4 text-gray-500" }),
1576
+ "JSON"
1577
+ ]
1578
+ }
1579
+ ),
1580
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1581
+ MessagesDialog,
1582
+ {
1583
+ isOpen: messagesOpen,
1584
+ onClose: () => setMessagesOpen(false),
1585
+ searches,
1586
+ streamingState,
1587
+ config
1588
+ }
1589
+ )
1590
+ ] });
1591
+ }
1592
+
1593
+ // src/components/SiteDropdown.tsx
1594
+ var import_react12 = require("react");
1595
+ var import_react13 = require("@headlessui/react");
1596
+ var import_solid5 = require("@heroicons/react/20/solid");
1597
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1598
+ function SiteDropdown({
1599
+ sites,
1600
+ selected,
1601
+ onSelect,
1602
+ placeholder = "Select a site..."
1603
+ }) {
1604
+ const [query, setQuery] = (0, import_react12.useState)("");
1605
+ const filteredSites = query === "" ? sites : sites.filter((site) => {
1606
+ return site.url.toLowerCase().includes(query.toLowerCase());
1607
+ });
1608
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react13.Combobox, { value: selected.url, onChange: onSelect, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative w-full", children: [
1609
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative flex items-center w-full cursor-default overflow-hidden rounded-lg bg-white text-left border focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 sm:text-sm", children: [
1610
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1611
+ import_react13.ComboboxInput,
1612
+ {
1613
+ className: "w-full pl-8 rounded-md text-sm border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0",
1614
+ displayValue: (site) => site || "",
1615
+ onChange: (event) => setQuery(event.target.value),
1616
+ placeholder
1617
+ }
1618
+ ),
1619
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react13.ComboboxButton, { className: "absolute inset-y-0 left-0 flex items-center pl-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_solid5.GlobeAltIcon, { className: "text-gray-400 size-4" }) }),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react13.ComboboxButton, { className: "absolute inset-y-0 right-0 flex items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_solid5.ChevronUpDownIcon, { className: "text-gray-400 size-4" }) })
1621
+ ] }),
1622
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react13.ComboboxOptions, { className: "absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm z-10", children: [
1623
+ filteredSites.map((site) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1624
+ import_react13.ComboboxOption,
1625
+ {
1626
+ className: ({ focus }) => `relative text-sm cursor-default select-none py-2 pl-10 pr-4 ${focus ? "bg-blue-600 text-white" : "text-gray-900"}`,
1627
+ value: site.url,
1628
+ children: ({ selected: selected2, focus }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1629
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1630
+ "span",
1631
+ {
1632
+ className: `block truncate ${selected2 ? "font-medium" : "font-normal"}`,
1633
+ children: site.url
1634
+ }
1635
+ ),
1636
+ selected2 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1637
+ "span",
1638
+ {
1639
+ className: `absolute inset-y-0 left-0 flex items-center pl-3 ${focus ? "text-white" : "text-blue-600"}`,
1640
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_solid5.CheckIcon, { className: "h-5 w-5", "aria-hidden": "true" })
1641
+ }
1642
+ ) : null,
1643
+ site.featured ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1644
+ "span",
1645
+ {
1646
+ className: `absolute inset-y-0 right-0 flex items-center pr-3 ${focus ? "text-white" : "text-blue-600"}`,
1647
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_solid5.StarIcon, { className: "size-5 text-yellow-500" })
1648
+ }
1649
+ ) : null
1650
+ ] })
1651
+ },
1652
+ site.url
1653
+ )),
1654
+ query !== "" && !sites.some(
1655
+ (site) => site.url.toLowerCase() === query.toLowerCase()
1656
+ ) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1657
+ import_react13.ComboboxOption,
1658
+ {
1659
+ className: ({ focus }) => `relative text-sm cursor-default select-none py-2 pl-10 pr-4 ${focus ? "bg-blue-600 text-white" : "text-gray-900"}`,
1660
+ value: query,
1661
+ children: ({ focus }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1662
+ "span",
1663
+ {
1664
+ className: `block truncate ${focus ? "font-medium" : "font-normal"}`,
1665
+ children: [
1666
+ 'Use "',
1667
+ query,
1668
+ '"'
1669
+ ]
1670
+ }
1671
+ )
1672
+ }
1673
+ )
1674
+ ] })
1675
+ ] }) });
1676
+ }
1677
+
1678
+ // src/lib/useHistory.ts
1679
+ var import_dexie_react_hooks = require("dexie-react-hooks");
1680
+
1681
+ // src/lib/db.ts
1682
+ var import_dexie = require("dexie");
1683
+ var db = new import_dexie.Dexie("ChatHistory");
1684
+ db.version(1).stores({
1685
+ messages: "++id, sessionId",
1686
+ // primary key "id" (for the runtime!),
1687
+ sessions: "sessionId, created, updated"
1688
+ });
1689
+
1690
+ // src/lib/useHistory.ts
1691
+ function useSearchSessions() {
1692
+ const sessions = (0, import_dexie_react_hooks.useLiveQuery)(
1693
+ () => db.sessions.orderBy("updated").reverse().toArray(),
1694
+ []
1695
+ ) ?? [];
1696
+ async function startSession(sessionId, query, backend) {
1697
+ await db.transaction("rw", db.messages, db.sessions, async () => {
1698
+ const duplicates = sessions.filter((s) => s.query == query);
1699
+ for (const s of duplicates) {
1700
+ await db.messages.where("sessionId").equals(s.sessionId).delete();
1701
+ db.sessions.delete(s.sessionId);
1702
+ }
1703
+ const created = /* @__PURE__ */ new Date();
1704
+ const updated = /* @__PURE__ */ new Date();
1705
+ await db.sessions.put({ sessionId, query, backend, created, updated });
1706
+ });
1707
+ }
1708
+ async function deleteSession(sessionId) {
1709
+ await db.transaction("rw", db.messages, db.sessions, async () => {
1710
+ await db.messages.where("sessionId").equals(sessionId).delete();
1711
+ db.sessions.delete(sessionId);
1712
+ });
1713
+ }
1714
+ return {
1715
+ sessions,
1716
+ startSession,
1717
+ deleteSession
1718
+ };
1719
+ }
1720
+ function useSearchSession(sessionId) {
1721
+ const queryResults = (0, import_dexie_react_hooks.useLiveQuery)(async () => {
1722
+ if (!sessionId) return [];
1723
+ return await db.messages.where("sessionId").equals(sessionId).sortBy("id");
1724
+ }, [sessionId]) ?? [];
1725
+ async function addSearch(result) {
1726
+ await db.transaction("rw", db.messages, db.sessions, async () => {
1727
+ db.sessions.update(result.sessionId, {
1728
+ updated: /* @__PURE__ */ new Date()
1729
+ });
1730
+ db.messages.add(result);
1731
+ });
1732
+ }
1733
+ async function addResults(id, results) {
1734
+ await db.transaction("rw", db.messages, db.sessions, async () => {
1735
+ const currMessage = await db.messages.get(id);
1736
+ if (currMessage) {
1737
+ db.sessions.update(currMessage.sessionId, {
1738
+ updated: /* @__PURE__ */ new Date()
1739
+ });
1740
+ db.messages.update(id, {
1741
+ ...currMessage,
1742
+ response: {
1743
+ ...currMessage.response,
1744
+ results: [...currMessage.response.results, ...results]
1745
+ }
1746
+ });
1747
+ }
1748
+ });
1749
+ }
1750
+ return {
1751
+ searches: queryResults,
1752
+ addSearch,
1753
+ addResults
1754
+ };
1755
+ }
1756
+ // Annotate the CommonJS export names for ESM import in node:
1757
+ 0 && (module.exports = {
1758
+ ChatSearch,
1759
+ DebugTool,
1760
+ HistorySidebar,
1761
+ SiteDropdown,
1762
+ useNlWeb,
1763
+ useSearchSession,
1764
+ useSearchSessions
1765
+ });
1766
+ //# sourceMappingURL=index.js.map