diff --git a/apps/site/components/Common/Search/index.tsx b/apps/site/components/Common/Search/index.tsx deleted file mode 100644 index 0c12664b61826..0000000000000 --- a/apps/site/components/Common/Search/index.tsx +++ /dev/null @@ -1,145 +0,0 @@ -'use client'; - -import { OramaSearchBox, OramaSearchButton } from '@orama/react-components'; -import { useTranslations, useLocale } from 'next-intl'; -import { useTheme } from 'next-themes'; -import type { FC } from 'react'; - -import { useRouter } from '#site/navigation.mjs'; -import { - ORAMA_CLOUD_ENDPOINT, - ORAMA_CLOUD_API_KEY, - DEFAULT_ORAMA_QUERY_PARAMS, - DEFAULT_ORAMA_SUGGESTIONS, - BASE_URL, -} from '#site/next.constants.mjs'; - -type ResultMapDescription = { - path: string; - pageSectionTitle: string; -}; - -type ResultMapPath = { path: string; siteSection: string }; - -import { themeConfig, translationKeys } from './utils'; - -const uppercaseFirst = (word: string) => - word.charAt(0).toUpperCase() + word.slice(1); - -const getFormattedPath = (path: string, title: string) => - `${path - .replace(/#.+$/, '') - .split('/') - .map(element => element.replaceAll('-', ' ')) - .map(element => uppercaseFirst(element)) - .filter(Boolean) - .join(' > ')} — ${title}`; - -const SearchButton: FC = () => { - const { resolvedTheme } = useTheme(); - const t = useTranslations(); - const locale = useLocale(); - const colorScheme = resolvedTheme as 'light' | 'dark'; - const router = useRouter(); - - const sourceMap = { - title: 'pageSectionTitle', - description: 'formattedPath', - path: 'path', - }; - - const resultMap = { - ...sourceMap, - description: ({ path, pageSectionTitle }: ResultMapDescription) => - getFormattedPath(path, pageSectionTitle), - path: ({ path, siteSection }: ResultMapPath) => - siteSection.toLowerCase() === 'docs' ? `/${path}` : `/${locale}/${path}`, - section: 'siteSection', - }; - - return ( - <> - - {t('components.search.searchPlaceholder')} - - - [key, t(`components.search.${key}`)]) - )} - searchParams={DEFAULT_ORAMA_QUERY_PARAMS} - suggestions={DEFAULT_ORAMA_SUGGESTIONS} - chatMarkdownLinkHref={({ href }) => { - if (!href) { - return href; - } - - const baseURLObject = new URL(BASE_URL); - const baseURLHostName = baseURLObject.hostname; - - const searchBoxURLObject = new URL(href); - const searchBoxURLHostName = searchBoxURLObject.hostname; - const serachBoxURLPathName = searchBoxURLObject.pathname; - - // We do not want to add the locale to the url for external links and docs links - if ( - baseURLHostName !== searchBoxURLHostName || - serachBoxURLPathName.startsWith('/docs/') - ) { - return href; - } - - const URLWithLocale = new URL( - `${locale}${searchBoxURLObject.pathname}`, - searchBoxURLObject.origin - ); - - return URLWithLocale.href; - }} - onAnswerSourceClick={event => { - event.preventDefault(); - - const baseURLObject = new URL(BASE_URL); - - const { path } = event.detail.source; - - const finalPath = path.startsWith('docs/') - ? path - : `${locale}/${path}`; - - const finalURL = new URL(finalPath, baseURLObject); - - window.open(finalURL, '_blank'); - }} - onSearchResultClick={event => { - event.preventDefault(); - - const fullURLObject = new URL(event.detail.result.path, BASE_URL); - - // result.path already contains LOCALE. Locale is set to undefined here so router does not add it once again. - router.push(fullURLObject.href, { locale: undefined }); - }} - /> - - ); -}; - -export default SearchButton; diff --git a/apps/site/components/Common/Search/utils.ts b/apps/site/components/Common/Search/utils.ts deleted file mode 100644 index dca1281ad7154..0000000000000 --- a/apps/site/components/Common/Search/utils.ts +++ /dev/null @@ -1,60 +0,0 @@ -export const themeConfig = { - typography: { - '--font-primary': 'var(--font-open-sans)', - }, - colors: { - light: { - '--text-color-primary': 'var(--color-neutral-900)', - '--text-color-accent': 'var(--color-green-600)', - '--background-color-secondary': 'var(--color-neutral-100)', - '--background-color-tertiary': 'var(--color-neutral-300)', - '--border-color-accent': 'var(--color-green-600)', - '--border-color-primary': 'var(--color-neutral-200)', - '--border-color-tertiary': 'var(--color-green-700)', - '--button-background-color-primary': 'var(--color-green-600)', - '--button-background-color-secondary': 'var(--color-white)', - '--button-background-color-secondary-hover': 'var(--color-neutral-100)', - '--button-border-color-secondary': 'var(--color-neutral-300)', - '--button-text-color-secondary': 'var(--color-neutral-900)', - '--chat-button-border-color-gradientThree': 'var(--color-green-400)', - '--chat-button-border-color-gradientFour': 'var(--color-green-700)', - '--chat-button-background-color-gradientOne': 'var(--color-green-600)', - '--chat-button-background-color-gradientTwo': 'var(--color-green-300)', - }, - dark: { - '--text-color-primary': 'var(--color-neutral-100)', - '--text-color-accent': 'var(--color-green-400)', - '--background-color-secondary': 'var(--color-neutral-950)', - '--background-color-tertiary': 'var(--color-neutral-900)', - '--border-color-accent': 'var(--color-green-400)', - '--border-color-primary': 'var(--color-neutral-900)', - '--border-color-tertiary': 'var(--color-green-300)', - '--button-background-color-primary': 'var(--color-green-400)', - '--button-background-color-secondary': 'var(--color-neutral-950)', - '--button-background-color-secondary-hover': 'var(--color-neutral-900)', - '--button-border-color-secondary': 'var(--color-neutral-900)', - '--button-text-color-secondary': 'var(--color-neutral-200)', - '--chat-button-border-color-gradientThree': 'var(--color-green-400)', - '--chat-button-border-color-gradientFour': 'var(--color-green-700)', - '--chat-button-background-color-gradientOne': 'var(--color-green-400)', - '--chat-button-background-color-gradientTwo': 'var(--color-green-800)', - }, - }, -}; - -export const translationKeys = [ - 'searchPlaceholder', - 'chatPlaceholder', - 'noResultsFoundFor', - 'suggestions', - 'seeAll', - 'addMore', - 'clearChat', - 'errorMessage', - 'disclaimer', - 'startYourSearch', - 'initErrorSearch', - 'initErrorChat', - 'chatButtonLabel', - 'searchButtonLabel', -] as const; diff --git a/apps/site/components/Common/Searchbox/Chat/index.module.css b/apps/site/components/Common/Searchbox/Chat/index.module.css new file mode 100644 index 0000000000000..eb12b023f4591 --- /dev/null +++ b/apps/site/components/Common/Searchbox/Chat/index.module.css @@ -0,0 +1,310 @@ +@reference "../../../styles/index.css"; + +.slidingPanelContent { + @apply overflow-hidden + rounded-tl-3xl + rounded-tr-3xl + bg-neutral-100 + shadow-lg + md:max-w-none + dark:bg-gray-950; + + > div { + @apply relative + h-full + overflow-y-auto + p-6; + } +} + +.slidingPanelInner { + @apply mx-auto + flex + h-full + max-w-4xl + flex-col + justify-between + gap-2; +} + +.slidingPanelTop { + @apply flex + min-h-0 + flex-1 + flex-col + pb-6; +} + +.slidingPanelBottom { + @apply relative + flex-shrink-0; +} + +.slidingPanelCloseButton { + @apply absolute + right-4 + top-4 + z-10 + cursor-pointer + rounded-full + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-300 + dark:text-neutral-400 + dark:hover:bg-neutral-900; + + svg { + @apply h-5 + w-5; + } +} + +.chatInteractionsWrapper { + @apply relative + h-full + items-start + overflow-y-auto + px-8; + + > div { + @apply h-full; + } +} + +.chatUserPrompt { + @apply mb-4 + text-base + text-neutral-900 + dark:text-neutral-200; +} + +.chatSources { + @apply mb-4 + flex + flex-nowrap + items-center + gap-3 + overflow-x-scroll + scroll-smooth + [scrollbar-width:none] + [&::-webkit-scrollbar]:hidden; +} + +.chatSource { + @apply flex + max-w-xs + items-center + gap-2 + text-base; +} + +.chatSourceLink { + @apply rounded-xl + bg-neutral-100 + px-4 + py-2 + text-neutral-900 + transition-colors + duration-300 + hover:bg-neutral-200 + focus:bg-neutral-200 + dark:bg-neutral-950 + dark:text-neutral-200 + hover:dark:bg-neutral-900 + focus:dark:bg-neutral-900; +} + +.chatSourceTitle { + @apply max-w-full + overflow-hidden + truncate + text-ellipsis + whitespace-nowrap + text-sm + font-semibold; +} + +.chatAssistantMessageWrapper { + @apply my-4 + mb-6 + max-w-full + rounded-xl + bg-neutral-100 + px-6 + py-4 + text-base + text-neutral-900 + dark:bg-neutral-950 + dark:text-neutral-200; +} + +.chatAssistantMessage { + p { + @apply font-sm-line-height + mb-3; + } + + pre:not([class*='language-']) { + @apply my-4; + + > div { + @apply rounded-lg + p-3 + text-sm; + } + } + + ul { + @apply list-disc + pl-6; + + li { + @apply mb-2; + } + } + + strong { + @apply font-bold; + } + + h3 { + @apply mb-2 + text-lg + font-bold; + } +} + +.chatLoader { + @apply my-4; +} + +.chatActionsContainer { + @apply flex + items-center + justify-end + pt-2; +} + +.chatActionsList { + @apply flex + list-none + items-center + gap-2 + p-0; +} + +.chatAction { + @apply cursor-pointer + rounded-full + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-300 + dark:text-neutral-400 + dark:hover:bg-neutral-900; + + svg { + @apply h-4 + w-4; + } +} + +.chatActionIconSelected { + @apply text-green-600 + dark:text-green-400; +} + +.promptTextAreaWrapper { + @apply relative + mx-8 + flex + items-center + space-x-2 + rounded-2xl + border + border-neutral-200 + bg-transparent + py-1 + text-base + text-neutral-900 + placeholder:text-neutral-500 + focus:outline-none + dark:border-neutral-900 + dark:bg-neutral-950 + dark:text-neutral-200 + dark:placeholder:text-neutral-600; + + svg { + @apply h-4 + w-4; + } +} + +.scrollDownButton { + @apply absolute + -top-8 + left-1/2 + -translate-x-1/2 + -translate-y-1/2 + cursor-pointer + rounded-lg + bg-neutral-300 + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-400 + dark:bg-neutral-900 + dark:text-white + dark:hover:bg-neutral-800; + + svg { + @apply h-4 + w-4; + } +} + +.promptTextAreaButton { + @apply absolute + right-2 + top-1/2 + -translate-y-1/2 + cursor-pointer + rounded-lg + bg-neutral-300 + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-400 + disabled:cursor-not-allowed + disabled:bg-neutral-200 + disabled:text-neutral-500 + dark:bg-green-400 + dark:text-white + dark:hover:bg-green-400 + dark:disabled:bg-neutral-900 + dark:disabled:text-neutral-700; +} + +.promptTextAreaField { + @apply w-full + resize-none + border-0 + bg-transparent + px-4 + py-2 + focus:outline-none; +} + +.slidingPanelFooter { + @apply flex + items-center + justify-center + pt-2 + text-neutral-700 + dark:text-neutral-700; +} diff --git a/apps/site/components/Common/Searchbox/Chat/index.tsx b/apps/site/components/Common/Searchbox/Chat/index.tsx new file mode 100644 index 0000000000000..7b2ee5f8b3534 --- /dev/null +++ b/apps/site/components/Common/Searchbox/Chat/index.tsx @@ -0,0 +1,185 @@ +'use client'; + +import { ArrowUpIcon } from '@heroicons/react/20/solid'; +import { + ArrowPathRoundedSquareIcon, + ClipboardIcon, + DocumentCheckIcon, +} from '@heroicons/react/24/outline'; +import { + ArrowDownIcon, + PauseCircleIcon, + XMarkIcon, +} from '@heroicons/react/24/solid'; +import Skeleton from '@node-core/ui-components/Common/Skeleton'; +import { + ChatInteractions, + PromptTextArea, + SlidingPanel, +} from '@orama/ui/components'; +import { useScrollableContainer } from '@orama/ui/hooks/useScrollableContainer'; +import Link from 'next/link'; +import { useLocale, useTranslations } from 'next-intl'; +import type { FC, PropsWithChildren } from 'react'; + +import styles from './index.module.css'; + +type SlidingChatPanelProps = PropsWithChildren<{ + open: boolean; + onClose: () => void; +}>; + +export const SlidingChatPanel: FC = ({ + open, + onClose, +}) => { + const locale = useLocale(); + const t = useTranslations(); + const { + containerRef, + showGoToBottomButton, + scrollToBottom, + recalculateGoToBottomButton, + } = useScrollableContainer(); + + return ( + <> + + + + + + +
+
+ scrollToBottom({ animated: true })} + className={styles.chatInteractionsWrapper} + > + {(interaction, index, totalInteractions) => ( + <> + +

{interaction.query}

+
+ + {interaction.loading && !interaction.response ? ( + + ) : ( + <> + + {(document, index: number) => ( +
+ + + {document?.pageSectionTitle as string} + + +
+ )} +
+ +
+ + {interaction.response} + + + {!interaction.loading && ( +
+
    + {index === totalInteractions && ( +
  • + + + +
  • + )} +
  • + + } + > + + +
  • +
+
+ )} +
+ + )} + + )} +
+
+
+ {showGoToBottomButton && ( + + )} + + + } + className={styles.promptTextAreaButton} + > + + + +
+ {t('components.search.disclaimer')} +
+
+
+
+
+ + ); +}; diff --git a/apps/site/components/Common/Searchbox/Search/index.module.css b/apps/site/components/Common/Searchbox/Search/index.module.css new file mode 100644 index 0000000000000..0b7a0707c4ace --- /dev/null +++ b/apps/site/components/Common/Searchbox/Search/index.module.css @@ -0,0 +1,259 @@ +@reference "../../../../styles/index.css"; + +.searchInputWrapper { + @apply relative; + + svg { + @apply absolute + left-3 + top-1/2 + h-4 + w-4 + -translate-y-1/2 + text-neutral-500 + dark:text-neutral-600; + } +} + +.searchInput { + @apply w-full + border-0 + border-b + border-neutral-200 + bg-transparent + py-4 + pl-9 + pr-4 + text-sm + text-neutral-900 + placeholder:text-neutral-500 + focus:outline-none + dark:border-neutral-900 + dark:text-neutral-200 + dark:placeholder:text-neutral-600; +} + +.chatButtonWrapper { + @apply border-b + border-neutral-200 + p-2 + dark:border-neutral-900; + + svg { + @apply h-4 + w-4; + } +} + +.chatButton { + @apply flex + w-full + cursor-pointer + items-center + gap-2 + rounded-lg + border + border-transparent + bg-transparent + p-3 + text-sm + transition-colors + duration-300 + hover:bg-neutral-300 + dark:hover:bg-neutral-900; +} + +.chatButtonWithSearch { + @apply bg-neutral-300 + dark:bg-neutral-900; +} + +.suggestionsWrapper { + @apply flex + min-h-0 + flex-1 + flex-col + overflow-y-auto + text-neutral-900 + dark:text-neutral-200; +} + +.suggestionsList { + @apply mt-1 + space-y-1; +} + +.suggestionsTitle { + @apply mb-3 + mt-3 + text-xs + font-semibold + uppercase + text-neutral-700 + dark:text-neutral-500; +} + +.suggestionItem { + @apply flex + cursor-pointer + items-center + gap-2 + py-2 + text-sm + text-green-600 + dark:text-green-400; + + svg { + @apply h-5 + w-5; + } +} + +.searchResultsWrapper { + @apply h-full + flex-1 + overflow-y-auto + px-5 + pb-6 + pt-3 + text-neutral-900 + dark:text-neutral-200; +} + +.noResultsWrapper { + @apply flex + h-full + items-center + justify-center + py-10 + text-sm + text-neutral-700 + dark:text-neutral-500; +} + +.facetTabItem { + @apply flex + cursor-pointer + items-center + gap-2 + rounded-3xl + border + border-neutral-200 + px-3 + py-1 + text-sm + transition-colors + duration-300 + dark:border-neutral-900; +} + +.facetTabItemSelected { + @apply border-green-600 + dark:border-green-400; +} + +.facetTabsWrapper { + @apply mb-4; +} + +.facetTabsList { + @apply flex + items-center + gap-2; +} + +.facetTabItemCount { + @apply text-neutral-700 + dark:text-neutral-700; +} + +.searchResultsGroupTitle { + @apply my-2 + pl-2 + text-sm + text-neutral-600 + dark:text-neutral-700; +} + +.searchResultsItem { + > a { + @apply flex + items-center + gap-4 + rounded-lg + px-2 + py-4 + text-sm + outline-none + transition-colors + duration-300 + hover:bg-neutral-300 + focus:bg-neutral-300 + dark:border-neutral-900 + dark:bg-neutral-950 + dark:hover:bg-neutral-900 + dark:focus:bg-neutral-900; + } + + svg { + @apply h-5 + w-5; + } +} + +.searchResultsItemDescription { + @apply text-sm + text-neutral-600 + dark:text-neutral-700; +} + +.footer { + @apply flex + items-center + justify-between + rounded-b-xl + border-t + border-neutral-200 + bg-neutral-100 + p-4 + dark:border-neutral-900 + dark:bg-neutral-950; +} + +.poweredByLink { + @apply flex + items-center + gap-2 + text-sm + text-neutral-700 + dark:text-neutral-400; +} + +.shortcutWrapper { + @apply flex + items-center + gap-2; +} + +.shortcutItem { + @apply flex + items-center + gap-2 + text-xs + text-neutral-700 + dark:text-neutral-700; +} + +.shortcutKey { + @apply rounded-md + bg-neutral-200 + p-1 + font-mono + text-xs + dark:bg-neutral-900; + + svg { + @apply h-4 + w-4; + } +} diff --git a/apps/site/components/Common/Searchbox/Search/index.tsx b/apps/site/components/Common/Searchbox/Search/index.tsx new file mode 100644 index 0000000000000..a90ecd479fd1e --- /dev/null +++ b/apps/site/components/Common/Searchbox/Search/index.tsx @@ -0,0 +1,233 @@ +'use client'; + +import { SparklesIcon, DocumentTextIcon } from '@heroicons/react/24/outline'; +import { + MagnifyingGlassIcon, + ArrowTurnDownLeftIcon, + ArrowDownIcon, + ArrowUpIcon, +} from '@heroicons/react/24/solid'; +import { + SearchInput, + FacetTabs, + SearchResults, + Suggestions, +} from '@orama/ui/components'; +import { useSearchContext } from '@orama/ui/contexts'; +import classNames from 'classnames'; +import Image from 'next/image'; +import Link from 'next/link'; +import { useLocale, useTranslations } from 'next-intl'; +import type { FC, PropsWithChildren } from 'react'; + +import styles from './index.module.css'; +import { getFormattedPath } from './utils'; + +type SearchProps = PropsWithChildren<{ + onChatTrigger: () => void; +}>; + +export const Search: FC = ({ onChatTrigger }) => { + const locale = useLocale(); + const t = useTranslations(); + const { searchTerm } = useSearchContext(); + + return ( + <> + + + + + +
+ +
+ +
+ + + + {(group, isSelected) => ( + + {group.name} + + {group.count} + + + )} + + + + + {searchTerm => ( + <> + {searchTerm ? ( +
+

+ {t('components.search.noResultsFoundFor')} "{searchTerm}" +

+
+ ) : ( + +

+ {t('components.search.suggestions')} +

+ + + + {t('components.search.suggestionOne')} + + + + {t('components.search.suggestionTwo')} + + + + {t('components.search.suggestionThree')} + + +
+ )} + + )} +
+ + + {group => ( +
+

{group.name}

+ + {hit => ( + + + +
+ {typeof hit.document?.pageSectionTitle === + 'string' && ( +

+ {hit.document?.pageSectionTitle} +

+ )} + {typeof hit.document?.pageSectionTitle === 'string' && + typeof hit.document?.path === 'string' && ( +

+ {getFormattedPath( + hit.document?.path, + hit.document?.pageSectionTitle + )} +

+ )} +
+ +
+ )} +
+
+ )} +
+
+
+ +
+
+
+ + + + + {t('components.search.keyboardShortcuts.select')} + +
+
+ + + + + + + + {t('components.search.keyboardShortcuts.navigate')} + +
+
+ esc + + {t('components.search.keyboardShortcuts.close')} + +
+
+
+ + {t('components.search.poweredBy')} + {t('components.search.poweredBy') + {t('components.search.poweredBy') + +
+
+ + ); +}; diff --git a/apps/site/components/Common/Searchbox/Search/utils.ts b/apps/site/components/Common/Searchbox/Search/utils.ts new file mode 100644 index 0000000000000..5fc41ceac70f1 --- /dev/null +++ b/apps/site/components/Common/Searchbox/Search/utils.ts @@ -0,0 +1,11 @@ +export const uppercaseFirst = (word: string) => + word.charAt(0).toUpperCase() + word.slice(1); + +export const getFormattedPath = (path: string, title: string) => + `${path + .replace(/#.+$/, '') + .split('/') + .map(element => element.replaceAll('-', ' ')) + .map(element => uppercaseFirst(element)) + .filter(Boolean) + .join(' > ')} — ${title}`; diff --git a/apps/site/components/Common/Searchbox/index.module.css b/apps/site/components/Common/Searchbox/index.module.css new file mode 100644 index 0000000000000..dd86260379dfa --- /dev/null +++ b/apps/site/components/Common/Searchbox/index.module.css @@ -0,0 +1,648 @@ +@reference "../../../styles/index.css"; + +/* .searchWrapper { + @apply relative + flex + w-full + flex-shrink-0; +} */ + +.searchButton { + @apply flex + grow + cursor-pointer + items-center + justify-between + gap-1 + rounded-xl + border + border-neutral-300 + bg-white + py-1 + pl-2 + pr-1 + text-neutral-900 + transition-colors + duration-300 + hover:bg-neutral-100 + dark:border-neutral-900 + dark:bg-neutral-950 + dark:text-neutral-200 + hover:dark:bg-neutral-900; +} + +.searchButtonContent { + @apply relative + flex + flex-nowrap + items-center + gap-1 + text-sm; + + svg { + @apply h-4 + w-4; + } +} + +.searchButtonShortcut { + @apply hidden + rounded-md + bg-neutral-300 + px-2 + py-1 + text-sm + text-neutral-800 + sm:inline + dark:bg-neutral-900 + dark:text-neutral-400; +} + +.modalWrapper { + @apply fixed + left-0 + top-0 + z-50 + flex + h-full + w-full + bg-white/70 + dark:bg-neutral-950/85; +} + +.modalInner { + @apply inset-0 + flex + flex-col + justify-between + bg-neutral-100 + sm:bottom-auto + sm:top-[5vh] + sm:mx-auto + sm:min-h-[200px] + sm:w-[80%] + sm:max-w-[720px] + sm:rounded-xl + sm:border + sm:border-neutral-200 + sm:p-0 + dark:bg-neutral-950 + sm:dark:border-neutral-900; + + max-height: 28vh; +} + +.modalWrapper.modalWrapperWithResults .modalInner { + max-height: 70vh; +} + +.modalContent { + @apply flex + h-full + flex-col; +} + +/* .searchInputWrapper { + @apply relative; + + svg { + @apply absolute + left-3 + top-1/2 + h-4 + w-4 + -translate-y-1/2 + text-neutral-500 + dark:text-neutral-600; + } +} + +.searchInput { + @apply w-full + border-0 + border-b + border-neutral-200 + bg-transparent + py-4 + pl-9 + pr-4 + text-sm + text-neutral-900 + placeholder:text-neutral-500 + focus:outline-none + dark:border-neutral-900 + dark:text-neutral-200 + dark:placeholder:text-neutral-600; +} + +.chatButtonWrapper { + @apply border-b + border-neutral-200 + p-2 + dark:border-neutral-900; + + svg { + @apply h-4 + w-4; + } +} + +.chatButton { + @apply flex + w-full + cursor-pointer + items-center + gap-2 + rounded-lg + border + border-transparent + bg-transparent + p-3 + text-sm + transition-colors + duration-300 + hover:bg-neutral-300 + dark:hover:bg-neutral-900; +} + +.chatButtonWithSearch { + @apply bg-neutral-300 + dark:bg-neutral-900; +} + +.suggestionsWrapper { + @apply flex + min-h-0 + flex-1 + flex-col + overflow-y-auto + text-neutral-900 + dark:text-neutral-200; +} + +.suggestionsList { + @apply mt-1 + space-y-1; +} + +.suggestionsTitle { + @apply mb-3 + mt-3 + text-xs + font-semibold + uppercase + text-neutral-700 + dark:text-neutral-500; +} + +.suggestionItem { + @apply flex + cursor-pointer + items-center + gap-2 + py-2 + text-sm + text-green-600 + dark:text-green-400; + + svg { + @apply h-5 + w-5; + } +} + +.searchResultsWrapper { + @apply h-full + flex-1 + overflow-y-auto + px-5 + pb-6 + pt-3 + text-neutral-900 + dark:text-neutral-200; +} + +.noResultsWrapper { + @apply flex + h-full + items-center + justify-center + py-10 + text-sm + text-neutral-700 + dark:text-neutral-500; +} + +.facetTabItem { + @apply flex + cursor-pointer + items-center + gap-2 + rounded-3xl + border + border-neutral-200 + px-3 + py-1 + text-sm + transition-colors + duration-300 + dark:border-neutral-900; +} + +.facetTabItemSelected { + @apply border-green-600 + dark:border-green-400; +} + +.facetTabsWrapper { + @apply mb-4; +} + +.facetTabsList { + @apply flex + items-center + gap-2; +} + +.facetTabItemCount { + @apply text-neutral-700 + dark:text-neutral-700; +} + +.searchResultsGroupTitle { + @apply my-2 + pl-2 + text-sm + text-neutral-600 + dark:text-neutral-700; +} + +.searchResultsItem { + > a { + @apply flex + items-center + gap-4 + rounded-lg + px-2 + py-4 + text-sm + outline-none + transition-colors + duration-300 + hover:bg-neutral-300 + focus:bg-neutral-300 + dark:border-neutral-900 + dark:bg-neutral-950 + dark:hover:bg-neutral-900 + dark:focus:bg-neutral-900; + } + + svg { + @apply h-5 + w-5; + } +} + +.searchResultsItemDescription { + @apply text-sm + text-neutral-600 + dark:text-neutral-700; +} + +.footer { + @apply flex + items-center + justify-between + rounded-b-xl + border-t + border-neutral-200 + bg-neutral-100 + p-4 + dark:border-neutral-900 + dark:bg-neutral-950; +} + +.poweredByLink { + @apply flex + items-center + gap-2 + text-sm + text-neutral-700 + dark:text-neutral-400; +} + +.shortcutWrapper { + @apply flex + items-center + gap-2; +} + +.shortcutItem { + @apply flex + items-center + gap-2 + text-xs + text-neutral-700 + dark:text-neutral-700; +} + +.shortcutKey { + @apply rounded-md + bg-neutral-200 + p-1 + font-mono + text-xs + dark:bg-neutral-900; + + svg { + @apply h-4 + w-4; + } +} + +.slidingPanelContent { + @apply overflow-hidden + rounded-tl-3xl + rounded-tr-3xl + bg-neutral-100 + shadow-lg + md:max-w-none + dark:bg-gray-950; + + > div { + @apply h-full + overflow-y-auto + p-6; + } +} + +.slidingPanelInner { + @apply mx-auto + flex + h-full + max-w-4xl + flex-col + justify-between + gap-2; +} + +.slidingPanelTop { + @apply flex + min-h-0 + flex-1 + flex-col + pb-6; +} + +.slidingPanelBottom { + @apply relative + flex-shrink-0; +} + +.chatInteractionsWrapper { + @apply relative + h-full + items-start + overflow-y-auto + px-8; + + > div { + @apply h-full; + } +} + +.chatUserPrompt { + @apply mb-4 + text-base + text-neutral-900 + dark:text-neutral-200; +} + +.chatSources { + @apply mb-4 + flex + flex-nowrap + items-center + gap-3 + overflow-x-scroll + scroll-smooth + [scrollbar-width:none] + [&::-webkit-scrollbar]:hidden; +} + +.chatSource { + @apply flex + max-w-xs + items-center + gap-2 + text-base; +} + +.chatSourceLink { + @apply rounded-xl + bg-neutral-100 + px-4 + py-2 + text-neutral-900 + transition-colors + duration-300 + hover:bg-neutral-200 + focus:bg-neutral-200 + dark:bg-neutral-950 + dark:text-neutral-200 + hover:dark:bg-neutral-900 + focus:dark:bg-neutral-900; +} + +.chatSourceTitle { + @apply max-w-full + overflow-hidden + truncate + text-ellipsis + whitespace-nowrap + text-sm + font-semibold; +} + +.chatAssistantMessageWrapper { + @apply my-4 + mb-6 + max-w-full + rounded-xl + bg-neutral-100 + px-6 + py-4 + text-base + text-neutral-900 + dark:bg-neutral-950 + dark:text-neutral-200; +} + +.chatAssistantMessage { + p { + @apply font-sm-line-height + mb-3; + } + + pre:not([class*='language-']) { + @apply my-4; + + > div { + @apply rounded-lg + p-3 + text-sm; + } + } + + ul { + @apply list-disc + pl-6; + + li { + @apply mb-2; + } + } + + strong { + @apply font-bold; + } + + h3 { + @apply mb-2 + text-lg + font-bold; + } +} + +.chatLoader { + @apply my-4; +} + +.chatActionsContainer { + @apply flex + items-center + justify-end + pt-2; +} + +.chatActionsList { + @apply flex + list-none + items-center + gap-2 + p-0; +} + +.chatAction { + @apply cursor-pointer + rounded-full + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-300 + dark:text-neutral-400 + dark:hover:bg-neutral-900; + + svg { + @apply h-4 + w-4; + } +} + +.chatActionIconSelected { + @apply text-green-600 + dark:text-green-400; +} + +.promptTextAreaWrapper { + @apply relative + mx-8 + flex + items-center + space-x-2 + rounded-2xl + border + border-neutral-200 + bg-transparent + py-1 + text-base + text-neutral-900 + placeholder:text-neutral-500 + focus:outline-none + dark:border-neutral-900 + dark:bg-neutral-950 + dark:text-neutral-200 + dark:placeholder:text-neutral-600; + + svg { + @apply h-4 + w-4; + } +} + +.scrollDownButton { + @apply absolute + -top-8 + left-1/2 + -translate-x-1/2 + -translate-y-1/2 + cursor-pointer + rounded-lg + bg-neutral-300 + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-400 + dark:bg-neutral-900 + dark:text-white + dark:hover:bg-neutral-800; + + svg { + @apply h-4 + w-4; + } +} + +.promptTextAreaButton { + @apply absolute + right-2 + top-1/2 + -translate-y-1/2 + cursor-pointer + rounded-lg + bg-neutral-300 + p-2 + text-neutral-800 + transition-colors + duration-300 + hover:bg-neutral-400 + disabled:cursor-not-allowed + disabled:bg-neutral-200 + disabled:text-neutral-500 + dark:bg-green-400 + dark:text-white + dark:hover:bg-green-400 + dark:disabled:bg-neutral-900 + dark:disabled:text-neutral-700; +} + +.promptTextAreaField { + @apply w-full + resize-none + border-0 + bg-transparent + px-4 + py-2 + focus:outline-none; +} + +.slidingPanelFooter { + @apply flex + items-center + justify-center + pt-2 + text-neutral-700 + dark:text-neutral-700; +} */ diff --git a/apps/site/components/Common/Searchbox/index.tsx b/apps/site/components/Common/Searchbox/index.tsx new file mode 100644 index 0000000000000..c646a29130825 --- /dev/null +++ b/apps/site/components/Common/Searchbox/index.tsx @@ -0,0 +1,89 @@ +'use client'; + +import { MagnifyingGlassIcon } from '@heroicons/react/24/solid'; +import { CollectionManager } from '@orama/core'; +import { SearchRoot, ChatRoot, Modal } from '@orama/ui/components'; +import { useSearchContext } from '@orama/ui/contexts'; +import classNames from 'classnames'; +import { useTranslations } from 'next-intl'; +import { useState, type FC, type PropsWithChildren } from 'react'; + +import { SlidingChatPanel } from './Chat'; +import styles from './index.module.css'; +import { Search } from './Search'; + +// TODO: test collection, replace with production collection and env variables +const collectionManager = new CollectionManager({ + collectionID: '85f541b3-b691-4d3e-9874-e7b3b4630adb', + apiKey: 'c1_d2ZKYw9ugj_tyVyWE_o$$Y-RBNf9GcTFfocEufnuRl7rCl3KJlhNJnP2MG-', + cluster: { + readURL: 'https://staging.collections.orama.com', + }, +}); + +const InnerSearchBox: FC = () => { + const [isChatOpen, setIsChatOpen] = useState(false); + + const toggleChatPanel = (): void => { + setIsChatOpen(!isChatOpen); + }; + + return ( + <> + + + + ); +}; + +const SearchWithModal: FC = () => { + const [open, setOpen] = useState(false); + const t = useTranslations(); + const { searchTerm } = useSearchContext(); + + const toggleSearchBox = (): void => { + setOpen(!open); + }; + + return ( + <> + + + + + + + + + + + ); +}; + +const OramaSearch: FC = () => ( + + + + + +); + +export default OramaSearch; diff --git a/apps/site/components/withNavBar.tsx b/apps/site/components/withNavBar.tsx index 8cab6b824c919..f25218903ca91 100644 --- a/apps/site/components/withNavBar.tsx +++ b/apps/site/components/withNavBar.tsx @@ -20,12 +20,15 @@ import { useSiteNavigation } from '#site/hooks'; import { useRouter, usePathname } from '#site/navigation.mjs'; import { availableLocales } from '#site/next.locales.mjs'; -const SearchButton = dynamic(() => import('#site/components/Common/Search'), { - ssr: false, - loading: () => ( - - ), -}); +const SearchButton = dynamic( + () => import('#site/components/Common/Searchbox'), + { + ssr: false, + loading: () => ( + + ), + } +); const WithNavBar: FC = () => { const { navigationItems } = useSiteNavigation(); diff --git a/apps/site/package.json b/apps/site/package.json index bdd04d21b59d5..0e21cb0524035 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -42,6 +42,8 @@ "@opentelemetry/sdk-logs": "~0.202.0", "@orama/react-components": "^0.8.1", "@oramacloud/client": "^2.1.4", + "@orama/ui": "^0.0.6", + "@orama/core": "^1.0.0-rc.3", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.12", "@radix-ui/react-toast": "^1.2.14", diff --git a/apps/site/public/static/logos/orama-logo-icon.svg b/apps/site/public/static/logos/orama-logo-icon.svg new file mode 100644 index 0000000000000..06a6cdb2e2771 --- /dev/null +++ b/apps/site/public/static/logos/orama-logo-icon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/public/static/logos/orama-logo.svg b/apps/site/public/static/logos/orama-logo.svg new file mode 100644 index 0000000000000..cab830769adce --- /dev/null +++ b/apps/site/public/static/logos/orama-logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/site/scripts/orama-search/sync-orama-cloud.mjs b/apps/site/scripts/orama-search/sync-orama-cloud.mjs index 276d19c4e45ad..e8c0740451f84 100644 --- a/apps/site/scripts/orama-search/sync-orama-cloud.mjs +++ b/apps/site/scripts/orama-search/sync-orama-cloud.mjs @@ -1,18 +1,19 @@ -import { CloudManager } from '@oramacloud/client'; +import { CollectionManager } from '@orama/core'; import { siteContent } from './get-documents.mjs'; import { ORAMA_SYNC_BATCH_SIZE } from '../../next.constants.mjs'; // The following follows the instructions at https://docs.orama.com/cloud/data-sources/custom-integrations/webhooks -const INDEX_ID = process.env.ORAMA_INDEX_ID; -const API_KEY = process.env.ORAMA_SECRET_KEY; - -const oramaCloudManager = new CloudManager({ - api_key: API_KEY, +const collectionManager = new CollectionManager({ + authJwtURL: 'https://staging.app.orama.com/api/user/jwt', + collectionID: '85f541b3-b691-4d3e-9874-e7b3b4630adb', + apiKey: 'p_JMpbuY216Pv0WCQFGijQLXwVIJzrf1dy55i3eCbNJDP', }); -const oramaIndex = oramaCloudManager.index(INDEX_ID); +const index = collectionManager.setIndex( + '55cdf5e4-63e3-4498-926a-ee6152a510cd' +); console.log(`Syncing ${siteContent.length} documents to Orama Cloud index`); @@ -29,19 +30,15 @@ const runUpdate = async () => { console.log(`Sending ${batches.length} batches of ${batchSize} documents`); for (const batch of batches) { - // In Orama, "update" is an upsert operation. - await oramaIndex.update(batch); + await index.upsertDocuments(batch); } }; -// Now we proceed to call the APIs in order: -// 1. Empty the index -// 2. Insert the documents -// 3. Trigger a deployment -// Once all these steps are done, the new documents will be available in the live index. -// Allow Orama up to 1 minute to distribute the documents to all the 300+ nodes worldwide. -await oramaIndex.empty(); +// Now we proceed to call the APIs in order. +// The previous implementation used to empty the index before inserting new documents +// to remove documents that are no longer in the source. +// The new API from @orama/core might have a different approach for full sync. +// Based on the provided examples, we are now only running the update. await runUpdate(); -await oramaIndex.deploy(); console.log('Orama Cloud sync completed successfully!'); diff --git a/packages/i18n/src/locales/en.json b/packages/i18n/src/locales/en.json index 064b82e74f790..719b28f77787e 100644 --- a/packages/i18n/src/locales/en.json +++ b/packages/i18n/src/locales/en.json @@ -252,7 +252,18 @@ "initErrorSearch": "Unable to initialize search service", "initErrorChat": "Unable to initialize chat service", "chatButtonLabel": "Get an AI summary", - "searchButtonLabel": "Search" + "searchButtonLabel": "Search", + "poweredBy": "Powered by Orama", + "suggestionOne": "How to install Node.js?", + "suggestionTwo": "How to create an HTTP server?", + "suggestionThree": "Upgrading Node.js version", + "scrollToBottom": "Scroll to bottom", + "closeChat": "Close chat", + "keyboardShortcuts": { + "select": "to select", + "navigate": "to navigate", + "close": "to close" + } }, "blog": { "blogHeader": { diff --git a/packages/i18n/src/locales/es.json b/packages/i18n/src/locales/es.json index dd15732fcecb6..15e2634f52cec 100644 --- a/packages/i18n/src/locales/es.json +++ b/packages/i18n/src/locales/es.json @@ -218,7 +218,7 @@ "text": "Ocurrió un error mientras se realizaba la búsqueda. Por favor, intenta nuevamente más tarde." }, "poweredBy": { - "text": "Impulsado por" + "text": "Impulsado por Orama" }, "noResults": { "text": "Lo sentimos, no hay resultados para {query}." diff --git a/packages/i18n/src/locales/tr.json b/packages/i18n/src/locales/tr.json index 41d9c8ff64e9f..2cfaa4053d1c6 100644 --- a/packages/i18n/src/locales/tr.json +++ b/packages/i18n/src/locales/tr.json @@ -220,7 +220,7 @@ "text": "Arama sırasında bir hata oluştu. Lütfen daha sonra tekrar deneyin." }, "poweredBy": { - "text": "Tarafından desteklenmektedir" + "text": "Tarafından desteklenmektedir Orama" }, "noResults": { "text": "\"{query}\" için sonuç bulunamadı." diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b3dfd68b48b0..bc9f11917b197 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,9 +99,15 @@ importers: '@opentelemetry/sdk-logs': specifier: ~0.202.0 version: 0.202.0(@opentelemetry/api@1.9.0) + '@orama/core': + specifier: ^1.0.0-rc.3 + version: 1.0.0-rc.3 '@orama/react-components': specifier: ^0.8.1 version: 0.8.1(@stencil/core@4.30.0)(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@orama/ui': + specifier: ^0.0.6 + version: 0.0.6(@orama/core@1.0.0-rc.3)(@types/react@19.1.8)(react@19.1.0) '@oramacloud/client': specifier: ^2.1.4 version: 2.1.4 @@ -234,7 +240,7 @@ importers: version: 15.3.5(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) eslint-import-resolver-typescript: specifier: ~4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-mdx: specifier: ~3.6.0 version: 3.6.0(eslint@9.30.1(jiti@2.4.2))(remark-lint-file-extension@3.0.1) @@ -318,7 +324,7 @@ importers: devDependencies: eslint-import-resolver-typescript: specifier: ~4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)) typescript: specifier: 'catalog:' version: 5.8.3 @@ -1930,6 +1936,9 @@ packages: '@orama/core@0.1.11': resolution: {integrity: sha512-cxs2ZrPlL0qCO91ba1FkFg/CX569v6Pqbo0e7EEvRVObBSOI1N1PIYAQ7lTXBUN7mDjpqHvPgOJ0mUuvotSl+Q==} + '@orama/core@1.0.0-rc.3': + resolution: {integrity: sha512-sqYHKgUCjbGFdiB28jvXYAowNlYSN5c1/U3VidbGSUJON/77TA08oVSf1CPwLMhm1tA0OSRAvlFAp4WNPJy+3Q==} + '@orama/cuid2@2.2.3': resolution: {integrity: sha512-Lcak3chblMejdlSHgYU2lS2cdOhDpU6vkfIJH4m+YKvqQyLqs1bB8+w6NT1MG5bO12NUK2GFc34Mn2xshMIQ1g==} @@ -1950,13 +1959,19 @@ packages: react: '>=17.0.0 <20.0.0' react-dom: '>=17.0.0 <20.0.0' - '@orama/switch@3.1.9': - resolution: {integrity: sha512-xOuhvg3e0SnJtYJMEwlKOEpOiuwqWsYanqqsiOWIJne+l+rKA1D1QPJUueN7Vb+IV+iG/1f/ueVVRw1H0ldb7Q==} + '@orama/switch@3.1.6': + resolution: {integrity: sha512-Swj9tQZWQ8tw44sAJmlF15xlJ5+h1GdgysvPGTe1NHJCcAOrX2qxp4OsWB+1vxmIxewP6brnP/U3nUehQNQi6g==} peerDependencies: '@orama/core': ^0.0.10 - '@orama/orama': 3.1.9 + '@orama/orama': 3.1.6 '@oramacloud/client': ^2.1.1 + '@orama/ui@0.0.6': + resolution: {integrity: sha512-aRpCXl+4VECVkkyv3kxd8+FUAFhXfp5G/E93ztfo5jCkNfnPTVI03SUWWUbPiehjtMbzut+P0VkKmG3n0neyhg==} + peerDependencies: + '@orama/core': ^0.1.11 + react: ^19 + '@orama/wc-components@0.8.1': resolution: {integrity: sha512-VLNIbPu9bOwr6bQgvpEmZvifaExf6disF8+zz1f/ipjmcNpZZL+0CWRmkvf5FNg1PHN3WvJrdulrfP01QwLljQ==} @@ -4463,8 +4478,8 @@ packages: remark-lint-file-extension: optional: true - eslint-module-utils@2.12.1: - resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -4497,8 +4512,8 @@ packages: eslint-import-resolver-node: optional: true - eslint-plugin-import@2.32.0: - resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -5028,6 +5043,9 @@ packages: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} + html-url-attributes@3.0.1: + resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} + html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -6467,6 +6485,11 @@ packages: printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + prism-react-renderer@1.3.5: + resolution: {integrity: sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==} + peerDependencies: + react: '>=0.14.9' + proc-log@4.2.0: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -6549,6 +6572,12 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-markdown@10.1.0: + resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} + peerDependencies: + '@types/react': '>=18' + react: '>=18' + react-property@2.0.2: resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==} @@ -9925,6 +9954,12 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros + '@orama/core@1.0.0-rc.3': + dependencies: + '@orama/cuid2': 2.2.3 + zod: 3.24.3 + zod-to-json-schema: 3.24.5(zod@3.24.3) + '@orama/cuid2@2.2.3': dependencies: '@noble/hashes': 1.8.0 @@ -9946,18 +9981,29 @@ snapshots: - '@types/react' - babel-plugin-macros - '@orama/switch@3.1.9(@orama/core@0.1.11)(@orama/orama@3.1.9)(@oramacloud/client@2.1.4)': + '@orama/switch@3.1.6(@orama/core@0.1.11)(@orama/orama@3.1.9)(@oramacloud/client@2.1.4)': dependencies: '@orama/core': 0.1.11 '@orama/orama': 3.1.9 '@oramacloud/client': 2.1.4 + '@orama/ui@0.0.6(@orama/core@1.0.0-rc.3)(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@orama/core': 1.0.0-rc.3 + prism-react-renderer: 1.3.5(react@19.1.0) + react: 19.1.0 + react-markdown: 10.1.0(@types/react@19.1.8)(react@19.1.0) + remark-gfm: 4.0.1 + transitivePeerDependencies: + - '@types/react' + - supports-color + '@orama/wc-components@0.8.1': dependencies: '@orama/core': 0.1.11 '@orama/highlight': 0.1.9 '@orama/orama': 3.1.9 - '@orama/switch': 3.1.9(@orama/core@0.1.11)(@orama/orama@3.1.9)(@oramacloud/client@2.1.4) + '@orama/switch': 3.1.6(@orama/core@0.1.11)(@orama/orama@3.1.9)(@oramacloud/client@2.1.4) '@oramacloud/client': 2.1.4 '@phosphor-icons/webcomponents': 2.1.5 '@stencil/core': 4.30.0 @@ -12785,8 +12831,8 @@ snapshots: '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) eslint: 9.30.1(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-react: 7.37.5(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-react-hooks: 5.2.0(eslint@9.30.1(jiti@2.4.2)) @@ -12812,7 +12858,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -12823,12 +12869,12 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.10.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)): dependencies: debug: 4.4.1 eslint: 9.30.1(jiti@2.4.2) @@ -12839,7 +12885,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.10.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)) transitivePeerDependencies: - supports-color @@ -12866,14 +12912,14 @@ snapshots: - bluebird - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) eslint: 9.30.1(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.32.0)(eslint@9.30.1(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.30.1(jiti@2.4.2)) transitivePeerDependencies: - supports-color @@ -12895,7 +12941,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -12906,7 +12952,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.30.1(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.30.1(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13591,7 +13637,7 @@ snapshots: mdast-util-mdx-expression: 2.0.1 mdast-util-mdx-jsx: 3.2.0 mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.0.0 + property-information: 7.1.0 space-separated-tokens: 2.0.2 style-to-js: 1.1.16 unist-util-position: 5.0.0 @@ -13650,6 +13696,8 @@ snapshots: html-tags@3.3.1: {} + html-url-attributes@3.0.1: {} + html-void-elements@3.0.0: {} html-webpack-plugin@5.6.3(webpack@5.99.9(@swc/core@1.11.24)(esbuild@0.25.5)): @@ -15322,6 +15370,10 @@ snapshots: printable-characters@1.0.42: {} + prism-react-renderer@1.3.5(react@19.1.0): + dependencies: + react: 19.1.0 + proc-log@4.2.0: {} promise-inflight@1.0.1: {} @@ -15403,6 +15455,24 @@ snapshots: react-is@17.0.2: {} + react-markdown@10.1.0(@types/react@19.1.8)(react@19.1.0): + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/react': 19.1.8 + devlop: 1.1.0 + hast-util-to-jsx-runtime: 2.3.6 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.0 + react: 19.1.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + unified: 11.0.5 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + react-property@2.0.2: {} react-remove-scroll-bar@2.3.8(@types/react@19.1.8)(react@19.1.0): @@ -16181,7 +16251,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.3.6 + debug: 4.4.1 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1