@docsearch/core 5.0.0-beta.1 → 5.0.0-beta.2
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/esm/index.d.ts +8 -0
- package/dist/esm/index.js +7 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.d.ts
CHANGED
|
@@ -31,6 +31,10 @@ interface DocSearchRef {
|
|
|
31
31
|
readonly isSidepanelSupported: boolean;
|
|
32
32
|
}
|
|
33
33
|
interface DocSearchContext {
|
|
34
|
+
/** Default Algolia application ID for child DocSearch/Sidepanel components. */
|
|
35
|
+
appId?: string;
|
|
36
|
+
/** Default Algolia API key for child DocSearch/Sidepanel components. */
|
|
37
|
+
apiKey?: string;
|
|
34
38
|
docsearchState: DocSearchState;
|
|
35
39
|
setDocsearchState: (newState: DocSearchState) => void;
|
|
36
40
|
searchButtonRef: React.RefObject<HTMLButtonElement | null>;
|
|
@@ -60,6 +64,10 @@ interface DocSearchCallbacks {
|
|
|
60
64
|
}
|
|
61
65
|
interface DocSearchProps extends DocSearchCallbacks {
|
|
62
66
|
children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;
|
|
67
|
+
/** Default Algolia application id for descendant DocSearch views. */
|
|
68
|
+
appId?: string;
|
|
69
|
+
/** Default Algolia API key for descendant DocSearch views. */
|
|
70
|
+
apiKey?: string;
|
|
63
71
|
theme?: DocSearchTheme;
|
|
64
72
|
initialQuery?: string;
|
|
65
73
|
keyboardShortcuts?: KeyboardShortcuts;
|
package/dist/esm/index.js
CHANGED
|
@@ -48,6 +48,8 @@ function _objectWithoutProperties(e, t) {
|
|
|
48
48
|
//#region src/DocSearch.tsx
|
|
49
49
|
const _excluded = [
|
|
50
50
|
"children",
|
|
51
|
+
"appId",
|
|
52
|
+
"apiKey",
|
|
51
53
|
"theme",
|
|
52
54
|
"onReady",
|
|
53
55
|
"onOpen",
|
|
@@ -58,7 +60,7 @@ const _excluded = [
|
|
|
58
60
|
const Context = React.createContext(void 0);
|
|
59
61
|
Context.displayName = "DocSearchContext";
|
|
60
62
|
function DocSearchInner(_ref, ref) {
|
|
61
|
-
let { children, theme, onReady, onOpen, onClose, onSidepanelOpen, onSidepanelClose } = _ref, props = _objectWithoutProperties(_ref, _excluded);
|
|
63
|
+
let { children, appId, apiKey, theme, onReady, onOpen, onClose, onSidepanelOpen, onSidepanelClose } = _ref, props = _objectWithoutProperties(_ref, _excluded);
|
|
62
64
|
const [docsearchState, setDocsearchState] = React.useState("ready");
|
|
63
65
|
const [initialQuery, setInitialQuery] = React.useState(props.initialQuery || "");
|
|
64
66
|
const searchButtonRef = React.useRef(null);
|
|
@@ -165,6 +167,8 @@ function DocSearchInner(_ref, ref) {
|
|
|
165
167
|
keyboardShortcuts
|
|
166
168
|
});
|
|
167
169
|
const value = React.useMemo(() => ({
|
|
170
|
+
appId,
|
|
171
|
+
apiKey,
|
|
168
172
|
docsearchState,
|
|
169
173
|
setDocsearchState,
|
|
170
174
|
searchButtonRef,
|
|
@@ -179,6 +183,8 @@ function DocSearchInner(_ref, ref) {
|
|
|
179
183
|
registerView,
|
|
180
184
|
isHybridModeSupported
|
|
181
185
|
}), [
|
|
186
|
+
appId,
|
|
187
|
+
apiKey,
|
|
182
188
|
docsearchState,
|
|
183
189
|
searchButtonRef,
|
|
184
190
|
initialQuery,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/useIsMobile.ts","../../src/DocSearch.tsx"],"sourcesContent":["import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport { useDocSearchKeyboardEvents } from './useDocSearchKeyboardEvents';\nimport { useIsMobile } from './useIsMobile';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\nimport type { KeyboardShortcuts } from './useKeyboardShortcuts.ts';\nimport type { DocSearchTheme } from './useTheme';\nimport { useTheme } from './useTheme';\n\nexport type DocSearchState =\n | 'modal-askai'\n | 'modal-search'\n | 'ready'\n | 'sidepanel';\n\nexport type View = 'modal' | 'sidepanel' | (Record<string, unknown> & string);\n\nexport type InitialAskAiMessage = {\n query: string;\n messageId?: string;\n suggestedQuestionId?: string;\n};\n\nexport type OnAskAiToggle = (\n active: boolean,\n initialMessage?: InitialAskAiMessage\n) => void;\n\n/** Imperative handle exposed by the DocSearch provider for programmatic control. */\nexport interface DocSearchRef {\n /** Opens the search modal. */\n open: () => void;\n /** Closes the search modal. */\n close: () => void;\n /** Opens Ask AI mode (sidepanel if available, otherwise modal). */\n openAskAi: (initialMessage?: InitialAskAiMessage) => void;\n /** Opens the sidepanel directly (no-op if sidepanel view not registered). */\n openSidepanel: (initialMessage?: InitialAskAiMessage) => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the modal is currently open. */\n readonly isOpen: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isSidepanelOpen: boolean;\n /** Returns true if sidepanel view is registered (hybrid mode). */\n readonly isSidepanelSupported: boolean;\n}\n\nexport interface DocSearchContext {\n docsearchState: DocSearchState;\n setDocsearchState: (newState: DocSearchState) => void;\n searchButtonRef: React.RefObject<HTMLButtonElement | null>;\n initialQuery: string;\n keyboardShortcuts: Required<KeyboardShortcuts>;\n openModal: () => void;\n closeModal: () => void;\n isAskAiActive: boolean;\n isModalActive: boolean;\n onAskAiToggle: OnAskAiToggle;\n initialAskAiMessage: InitialAskAiMessage | undefined;\n registerView: (view: View) => void;\n isHybridModeSupported: boolean;\n}\n\n/** Lifecycle callbacks for DocSearch. */\nexport interface DocSearchCallbacks {\n /** Called once DocSearch is mounted and ready for interaction. */\n onReady?: () => void;\n /** Called when the modal opens. */\n onOpen?: () => void;\n /** Called when the modal closes. */\n onClose?: () => void;\n /** Called when the sidepanel opens. */\n onSidepanelOpen?: () => void;\n /** Called when the sidepanel closes. */\n onSidepanelClose?: () => void;\n}\n\nexport interface DocSearchProps extends DocSearchCallbacks {\n children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;\n theme?: DocSearchTheme;\n initialQuery?: string;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nconst Context = React.createContext<DocSearchContext | undefined>(undefined);\nContext.displayName = 'DocSearchContext';\n\nfunction DocSearchInner(\n {\n children,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: DocSearchProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n const [docsearchState, setDocsearchState] =\n React.useState<DocSearchState>('ready');\n const [initialQuery, setInitialQuery] = React.useState<string>(\n props.initialQuery || ''\n );\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);\n const [initialAskAiMessage, setInitialAskAiMessage] =\n React.useState<InitialAskAiMessage>();\n const [registeredViews, setRegisteredViews] = React.useState(\n () => new Set<View>()\n );\n const isMobile = useIsMobile();\n const prevStateRef = React.useRef<DocSearchState>('ready');\n\n const isModalActive = ['modal-search', 'modal-askai'].includes(\n docsearchState\n );\n const isAskAiActive = docsearchState === 'modal-askai';\n const isHybridModeSupported = !isMobile && registeredViews.has('sidepanel');\n const isSidepanelOpen = docsearchState === 'sidepanel';\n\n // Call onReady on mount\n React.useEffect(() => {\n onReady?.();\n }, [onReady]);\n\n // Track state changes for lifecycle callbacks\n React.useEffect(() => {\n const prevState = prevStateRef.current;\n const currentState = docsearchState;\n\n // Modal opened\n if (\n (currentState === 'modal-search' || currentState === 'modal-askai') &&\n prevState !== 'modal-search' &&\n prevState !== 'modal-askai'\n ) {\n onOpen?.();\n }\n\n // Modal closed\n if (\n currentState === 'ready' &&\n (prevState === 'modal-search' || prevState === 'modal-askai')\n ) {\n onClose?.();\n }\n\n // Sidepanel opened\n if (currentState === 'sidepanel' && prevState !== 'sidepanel') {\n onSidepanelOpen?.();\n }\n\n // Sidepanel closed\n if (currentState !== 'sidepanel' && prevState === 'sidepanel') {\n onSidepanelClose?.();\n }\n\n prevStateRef.current = currentState;\n }, [docsearchState, onOpen, onClose, onSidepanelOpen, onSidepanelClose]);\n\n const openModal = React.useCallback((): void => {\n setDocsearchState('modal-search');\n }, []);\n\n const closeModal = React.useCallback((): void => {\n setDocsearchState('ready');\n // Refocus the Modal trigger on close\n searchButtonRef.current?.focus();\n setInitialQuery(props.initialQuery ?? '');\n }, [setDocsearchState, props.initialQuery]);\n\n const onAskAiToggle: OnAskAiToggle = React.useCallback(\n (active, initialMessage) => {\n // Don't use hybrid mode on mobile\n if (!isMobile && active && isHybridModeSupported) {\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n return;\n }\n\n setDocsearchState(active ? 'modal-askai' : 'modal-search');\n },\n [setDocsearchState, isMobile, isHybridModeSupported]\n );\n\n const openSidepanel = React.useCallback(\n (initialMessage?: InitialAskAiMessage): void => {\n // Guard: no-op if sidepanel view hasn't been registered\n if (!registeredViews.has('sidepanel')) return;\n\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n },\n [setDocsearchState, registeredViews]\n );\n\n const onInput = React.useCallback(\n (event: KeyboardEvent): void => {\n setDocsearchState('modal-search');\n setInitialQuery(event.key);\n },\n [setDocsearchState, setInitialQuery]\n );\n\n const registerView = React.useCallback(\n (view: View): void => {\n if (registeredViews.has(view)) return;\n\n setRegisteredViews((prev) => {\n const newViews = new Set(prev);\n newViews.add(view);\n return newViews;\n });\n },\n [registeredViews]\n );\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: openModal,\n close: closeModal,\n openAskAi: (initialMessage?: InitialAskAiMessage): void =>\n onAskAiToggle(true, initialMessage),\n openSidepanel,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isModalActive;\n },\n get isSidepanelOpen(): boolean {\n return isSidepanelOpen;\n },\n get isSidepanelSupported(): boolean {\n return isHybridModeSupported;\n },\n }),\n [\n openModal,\n closeModal,\n onAskAiToggle,\n openSidepanel,\n isModalActive,\n isSidepanelOpen,\n isHybridModeSupported,\n ]\n );\n\n useTheme({ theme });\n\n useDocSearchKeyboardEvents({\n isOpen: isModalActive,\n onOpen: openModal,\n onClose: closeModal,\n onAskAiToggle,\n onInput,\n isAskAiActive,\n searchButtonRef,\n keyboardShortcuts,\n });\n\n const value: DocSearchContext = React.useMemo(\n () => ({\n docsearchState,\n setDocsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n }),\n [\n docsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n ]\n );\n\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport const DocSearch = React.forwardRef(DocSearchInner);\nDocSearch.displayName = 'DocSearch';\n\nexport function useDocSearch(): DocSearchContext {\n const ctx = React.useContext(Context);\n\n if (ctx === undefined) {\n throw new Error(\n '`useDocSearch` must be used within the `DocSearch` provider'\n );\n }\n\n return ctx;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/useIsMobile.ts","../../src/DocSearch.tsx"],"sourcesContent":["import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport { useDocSearchKeyboardEvents } from './useDocSearchKeyboardEvents';\nimport { useIsMobile } from './useIsMobile';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\nimport type { KeyboardShortcuts } from './useKeyboardShortcuts.ts';\nimport type { DocSearchTheme } from './useTheme';\nimport { useTheme } from './useTheme';\n\nexport type DocSearchState =\n | 'modal-askai'\n | 'modal-search'\n | 'ready'\n | 'sidepanel';\n\nexport type View = 'modal' | 'sidepanel' | (Record<string, unknown> & string);\n\nexport type InitialAskAiMessage = {\n query: string;\n messageId?: string;\n suggestedQuestionId?: string;\n};\n\nexport type OnAskAiToggle = (\n active: boolean,\n initialMessage?: InitialAskAiMessage\n) => void;\n\n/** Imperative handle exposed by the DocSearch provider for programmatic control. */\nexport interface DocSearchRef {\n /** Opens the search modal. */\n open: () => void;\n /** Closes the search modal. */\n close: () => void;\n /** Opens Ask AI mode (sidepanel if available, otherwise modal). */\n openAskAi: (initialMessage?: InitialAskAiMessage) => void;\n /** Opens the sidepanel directly (no-op if sidepanel view not registered). */\n openSidepanel: (initialMessage?: InitialAskAiMessage) => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the modal is currently open. */\n readonly isOpen: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isSidepanelOpen: boolean;\n /** Returns true if sidepanel view is registered (hybrid mode). */\n readonly isSidepanelSupported: boolean;\n}\n\nexport interface DocSearchContext {\n /** Default Algolia application ID for child DocSearch/Sidepanel components. */\n appId?: string;\n /** Default Algolia API key for child DocSearch/Sidepanel components. */\n apiKey?: string;\n docsearchState: DocSearchState;\n setDocsearchState: (newState: DocSearchState) => void;\n searchButtonRef: React.RefObject<HTMLButtonElement | null>;\n initialQuery: string;\n keyboardShortcuts: Required<KeyboardShortcuts>;\n openModal: () => void;\n closeModal: () => void;\n isAskAiActive: boolean;\n isModalActive: boolean;\n onAskAiToggle: OnAskAiToggle;\n initialAskAiMessage: InitialAskAiMessage | undefined;\n registerView: (view: View) => void;\n isHybridModeSupported: boolean;\n}\n\n/** Lifecycle callbacks for DocSearch. */\nexport interface DocSearchCallbacks {\n /** Called once DocSearch is mounted and ready for interaction. */\n onReady?: () => void;\n /** Called when the modal opens. */\n onOpen?: () => void;\n /** Called when the modal closes. */\n onClose?: () => void;\n /** Called when the sidepanel opens. */\n onSidepanelOpen?: () => void;\n /** Called when the sidepanel closes. */\n onSidepanelClose?: () => void;\n}\n\nexport interface DocSearchProps extends DocSearchCallbacks {\n children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;\n /** Default Algolia application id for descendant DocSearch views. */\n appId?: string;\n /** Default Algolia API key for descendant DocSearch views. */\n apiKey?: string;\n theme?: DocSearchTheme;\n initialQuery?: string;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nconst Context = React.createContext<DocSearchContext | undefined>(undefined);\nContext.displayName = 'DocSearchContext';\n\nfunction DocSearchInner(\n {\n children,\n appId,\n apiKey,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: DocSearchProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n const [docsearchState, setDocsearchState] =\n React.useState<DocSearchState>('ready');\n const [initialQuery, setInitialQuery] = React.useState<string>(\n props.initialQuery || ''\n );\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);\n const [initialAskAiMessage, setInitialAskAiMessage] =\n React.useState<InitialAskAiMessage>();\n const [registeredViews, setRegisteredViews] = React.useState(\n () => new Set<View>()\n );\n const isMobile = useIsMobile();\n const prevStateRef = React.useRef<DocSearchState>('ready');\n\n const isModalActive = ['modal-search', 'modal-askai'].includes(\n docsearchState\n );\n const isAskAiActive = docsearchState === 'modal-askai';\n const isHybridModeSupported = !isMobile && registeredViews.has('sidepanel');\n const isSidepanelOpen = docsearchState === 'sidepanel';\n\n // Call onReady on mount\n React.useEffect(() => {\n onReady?.();\n }, [onReady]);\n\n // Track state changes for lifecycle callbacks\n React.useEffect(() => {\n const prevState = prevStateRef.current;\n const currentState = docsearchState;\n\n // Modal opened\n if (\n (currentState === 'modal-search' || currentState === 'modal-askai') &&\n prevState !== 'modal-search' &&\n prevState !== 'modal-askai'\n ) {\n onOpen?.();\n }\n\n // Modal closed\n if (\n currentState === 'ready' &&\n (prevState === 'modal-search' || prevState === 'modal-askai')\n ) {\n onClose?.();\n }\n\n // Sidepanel opened\n if (currentState === 'sidepanel' && prevState !== 'sidepanel') {\n onSidepanelOpen?.();\n }\n\n // Sidepanel closed\n if (currentState !== 'sidepanel' && prevState === 'sidepanel') {\n onSidepanelClose?.();\n }\n\n prevStateRef.current = currentState;\n }, [docsearchState, onOpen, onClose, onSidepanelOpen, onSidepanelClose]);\n\n const openModal = React.useCallback((): void => {\n setDocsearchState('modal-search');\n }, []);\n\n const closeModal = React.useCallback((): void => {\n setDocsearchState('ready');\n // Refocus the Modal trigger on close\n searchButtonRef.current?.focus();\n setInitialQuery(props.initialQuery ?? '');\n }, [setDocsearchState, props.initialQuery]);\n\n const onAskAiToggle: OnAskAiToggle = React.useCallback(\n (active, initialMessage) => {\n // Don't use hybrid mode on mobile\n if (!isMobile && active && isHybridModeSupported) {\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n return;\n }\n\n setDocsearchState(active ? 'modal-askai' : 'modal-search');\n },\n [setDocsearchState, isMobile, isHybridModeSupported]\n );\n\n const openSidepanel = React.useCallback(\n (initialMessage?: InitialAskAiMessage): void => {\n // Guard: no-op if sidepanel view hasn't been registered\n if (!registeredViews.has('sidepanel')) return;\n\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n },\n [setDocsearchState, registeredViews]\n );\n\n const onInput = React.useCallback(\n (event: KeyboardEvent): void => {\n setDocsearchState('modal-search');\n setInitialQuery(event.key);\n },\n [setDocsearchState, setInitialQuery]\n );\n\n const registerView = React.useCallback(\n (view: View): void => {\n if (registeredViews.has(view)) return;\n\n setRegisteredViews((prev) => {\n const newViews = new Set(prev);\n newViews.add(view);\n return newViews;\n });\n },\n [registeredViews]\n );\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: openModal,\n close: closeModal,\n openAskAi: (initialMessage?: InitialAskAiMessage): void =>\n onAskAiToggle(true, initialMessage),\n openSidepanel,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isModalActive;\n },\n get isSidepanelOpen(): boolean {\n return isSidepanelOpen;\n },\n get isSidepanelSupported(): boolean {\n return isHybridModeSupported;\n },\n }),\n [\n openModal,\n closeModal,\n onAskAiToggle,\n openSidepanel,\n isModalActive,\n isSidepanelOpen,\n isHybridModeSupported,\n ]\n );\n\n useTheme({ theme });\n\n useDocSearchKeyboardEvents({\n isOpen: isModalActive,\n onOpen: openModal,\n onClose: closeModal,\n onAskAiToggle,\n onInput,\n isAskAiActive,\n searchButtonRef,\n keyboardShortcuts,\n });\n\n const value: DocSearchContext = React.useMemo(\n () => ({\n appId,\n apiKey,\n docsearchState,\n setDocsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n }),\n [\n appId,\n apiKey,\n docsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n ]\n );\n\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport const DocSearch = React.forwardRef(DocSearchInner);\nDocSearch.displayName = 'DocSearch';\n\nexport function useDocSearch(): DocSearchContext {\n const ctx = React.useContext(Context);\n\n if (ctx === undefined) {\n throw new Error(\n '`useDocSearch` must be used within the `DocSearch` provider'\n );\n }\n\n return ctx;\n}\n"],"mappings":"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"}
|
package/dist/umd/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! @docsearch/core 5.0.0-beta.
|
|
2
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.DocSearchCore={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);function l(e){"@babel/helpers - typeof";return l=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},l(e)}function u(e,t){if(l(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(l(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function d(e){var t=u(e,`string`);return l(t)==`symbol`?t:t+``}function f(e,t,n){return(t=d(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function p(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function m(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?p(Object(n),!0).forEach(function(t){f(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):p(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}let h={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function g(e){return m(m({},h),e)}function _(e){let t=e.composedPath()[0],n=t.tagName;return t.isContentEditable||n===`INPUT`||n===`SELECT`||n===`TEXTAREA`}function v({isOpen:e,isAskAiActive:n,onAskAiToggle:r,onClose:i,onOpen:a,keyboardShortcuts:o=h}){t.default.useEffect(()=>{function t(t){var s;if(e&&t.code===`Escape`&&n){r(!1);return}let c=o[`Ctrl/Cmd+K`]&&((s=t.key)==null?void 0:s.toLowerCase())===`k`&&(t.metaKey||t.ctrlKey),l=o[`/`]&&t.key===`/`;(t.code===`Escape`&&e||c||!_(t)&&l&&!e)&&(t.preventDefault(),e?i():document.body.classList.contains(`DocSearch--active`)||a())}return window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`keydown`,t)}},[e,n,o,a,i,r])}let y=()=>{let[e,n]=t.default.useState(!1);return t.default.useEffect(()=>{let e=()=>{let e=window.matchMedia(`(max-width: 768px)`);n(e.matches)};return e(),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`resize`,e)}},[]),e},b=({theme:e})=>{(0,t.useEffect)(()=>{if(!e)return;let t=document.documentElement.dataset.theme;if(e!==t)return document.documentElement.dataset.theme=e,()=>{t===void 0?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=t}},[e])};function x(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}function S(e,t){if(e==null)return{};var n,r,i=x(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}let C=[`children`,`theme`,`onReady`,`onOpen`,`onClose`,`onSidepanelOpen`,`onSidepanelClose`],w=t.default.createContext(void 0);w.displayName=`DocSearchContext`;function T(e,n){let{children:r,
|
|
1
|
+
/*! @docsearch/core 5.0.0-beta.2 (UNRELEASED c7e1a88) | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */
|
|
2
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react")):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.DocSearchCore={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e};t=((e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(t,1);function l(e){"@babel/helpers - typeof";return l=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},l(e)}function u(e,t){if(l(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(l(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function d(e){var t=u(e,`string`);return l(t)==`symbol`?t:t+``}function f(e,t,n){return(t=d(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function p(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function m(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?p(Object(n),!0).forEach(function(t){f(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):p(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}let h={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function g(e){return m(m({},h),e)}function _(e){let t=e.composedPath()[0],n=t.tagName;return t.isContentEditable||n===`INPUT`||n===`SELECT`||n===`TEXTAREA`}function v({isOpen:e,isAskAiActive:n,onAskAiToggle:r,onClose:i,onOpen:a,keyboardShortcuts:o=h}){t.default.useEffect(()=>{function t(t){var s;if(e&&t.code===`Escape`&&n){r(!1);return}let c=o[`Ctrl/Cmd+K`]&&((s=t.key)==null?void 0:s.toLowerCase())===`k`&&(t.metaKey||t.ctrlKey),l=o[`/`]&&t.key===`/`;(t.code===`Escape`&&e||c||!_(t)&&l&&!e)&&(t.preventDefault(),e?i():document.body.classList.contains(`DocSearch--active`)||a())}return window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`keydown`,t)}},[e,n,o,a,i,r])}let y=()=>{let[e,n]=t.default.useState(!1);return t.default.useEffect(()=>{let e=()=>{let e=window.matchMedia(`(max-width: 768px)`);n(e.matches)};return e(),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`resize`,e)}},[]),e},b=({theme:e})=>{(0,t.useEffect)(()=>{if(!e)return;let t=document.documentElement.dataset.theme;if(e!==t)return document.documentElement.dataset.theme=e,()=>{t===void 0?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=t}},[e])};function x(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}function S(e,t){if(e==null)return{};var n,r,i=x(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}let C=[`children`,`appId`,`apiKey`,`theme`,`onReady`,`onOpen`,`onClose`,`onSidepanelOpen`,`onSidepanelClose`],w=t.default.createContext(void 0);w.displayName=`DocSearchContext`;function T(e,n){let{children:r,appId:i,apiKey:a,theme:o,onReady:s,onOpen:c,onClose:l,onSidepanelOpen:u,onSidepanelClose:d}=e,f=S(e,C),[p,m]=t.default.useState(`ready`),[h,_]=t.default.useState(f.initialQuery||``),x=t.default.useRef(null),T=g(f.keyboardShortcuts),[E,D]=t.default.useState(),[O,k]=t.default.useState(()=>new Set),A=y(),j=t.default.useRef(`ready`),M=[`modal-search`,`modal-askai`].includes(p),N=p===`modal-askai`,P=!A&&O.has(`sidepanel`),F=p===`sidepanel`;t.default.useEffect(()=>{s==null||s()},[s]),t.default.useEffect(()=>{let e=j.current,t=p;(t===`modal-search`||t===`modal-askai`)&&e!==`modal-search`&&e!==`modal-askai`&&(c==null||c()),t===`ready`&&(e===`modal-search`||e===`modal-askai`)&&(l==null||l()),t===`sidepanel`&&e!==`sidepanel`&&(u==null||u()),t!==`sidepanel`&&e===`sidepanel`&&(d==null||d()),j.current=t},[p,c,l,u,d]);let I=t.default.useCallback(()=>{m(`modal-search`)},[]),L=t.default.useCallback(()=>{var e,t;m(`ready`),(e=x.current)==null||e.focus(),_((t=f.initialQuery)==null?``:t)},[m,f.initialQuery]),R=t.default.useCallback((e,t)=>{if(!A&&e&&P){D(t),m(`sidepanel`);return}m(e?`modal-askai`:`modal-search`)},[m,A,P]),z=t.default.useCallback(e=>{O.has(`sidepanel`)&&(D(e),m(`sidepanel`))},[m,O]),B=t.default.useCallback(e=>{m(`modal-search`),_(e.key)},[m,_]),V=t.default.useCallback(e=>{O.has(e)||k(t=>{let n=new Set(t);return n.add(e),n})},[O]);t.default.useImperativeHandle(n,()=>({open:I,close:L,openAskAi:e=>R(!0,e),openSidepanel:z,get isReady(){return!0},get isOpen(){return M},get isSidepanelOpen(){return F},get isSidepanelSupported(){return P}}),[I,L,R,z,M,F,P]),b({theme:o}),v({isOpen:M,onOpen:I,onClose:L,onAskAiToggle:R,onInput:B,isAskAiActive:N,searchButtonRef:x,keyboardShortcuts:T});let H=t.default.useMemo(()=>({appId:i,apiKey:a,docsearchState:p,setDocsearchState:m,searchButtonRef:x,initialQuery:h,keyboardShortcuts:T,openModal:I,closeModal:L,isAskAiActive:N,isModalActive:M,onAskAiToggle:R,initialAskAiMessage:E,registerView:V,isHybridModeSupported:P}),[i,a,p,x,h,T,I,L,N,M,R,E,V,P]);return t.default.createElement(w.Provider,{value:H},r)}let E=t.default.forwardRef(T);E.displayName=`DocSearch`;function D(){let e=t.default.useContext(w);if(e===void 0)throw Error("`useDocSearch` must be used within the `DocSearch` provider");return e}e.DEFAULT_KEYBOARD_SHORTCUTS=h,e.DocSearch=E,e.useDocSearch=D,e.useDocSearchKeyboardEvents=v,e.useKeyboardShortcuts=g,e.useTheme=b});
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/umd/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["React","React"],"sources":["../../src/useKeyboardShortcuts.ts","../../src/useDocSearchKeyboardEvents.ts","../../src/useIsMobile.ts","../../src/useTheme.ts","../../src/DocSearch.tsx"],"sourcesContent":["export interface DocSearchModalShortcuts {\n /**\n * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.\n *\n * @default true\n */\n 'Ctrl/Cmd+K'?: boolean;\n /**\n * Enable/disable the / shortcut to open the DocSearch modal.\n *\n * @default true\n */\n '/'?: boolean;\n}\n\nexport interface SidepanelShortcuts {\n /**\n * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.\n *\n * @default true\n */\n 'Ctrl/Cmd+I'?: boolean;\n}\n\nexport type KeyboardShortcuts = DocSearchModalShortcuts & SidepanelShortcuts;\n\n/**\n * Default keyboard shortcuts configuration for DocSearch. These values are used\n * when no keyboardShortcuts prop is provided or when specific shortcuts are not\n * configured.\n */\nexport const DEFAULT_KEYBOARD_SHORTCUTS: Required<KeyboardShortcuts> = {\n 'Ctrl/Cmd+K': true,\n '/': true,\n 'Ctrl/Cmd+I': true,\n} as const;\n\n/**\n * Merges user-provided keyboard shortcuts with defaults.\n *\n * @param userShortcuts - Optional user configuration.\n * @returns Complete keyboard shortcuts configuration with defaults applied.\n */\nexport function useKeyboardShortcuts(\n userShortcuts?: KeyboardShortcuts\n): Required<KeyboardShortcuts> {\n return {\n ...DEFAULT_KEYBOARD_SHORTCUTS,\n ...userShortcuts,\n };\n}\n","import React from 'react';\n\nimport {\n DEFAULT_KEYBOARD_SHORTCUTS,\n type KeyboardShortcuts,\n} from './useKeyboardShortcuts';\n\nexport interface UseDocSearchKeyboardEventsProps {\n isOpen: boolean;\n onOpen: () => void;\n onClose: () => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n onInput?: (event: KeyboardEvent) => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n searchButtonRef?: React.RefObject<HTMLButtonElement | null>;\n isAskAiActive: boolean;\n onAskAiToggle: (toggle: boolean) => void;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nfunction isEditingContent(event: KeyboardEvent): boolean {\n const element = event.composedPath()[0] as HTMLElement;\n const tagName = element.tagName;\n\n return (\n element.isContentEditable ||\n tagName === 'INPUT' ||\n tagName === 'SELECT' ||\n tagName === 'TEXTAREA'\n );\n}\n\nexport function useDocSearchKeyboardEvents({\n isOpen,\n isAskAiActive,\n onAskAiToggle,\n onClose,\n onOpen,\n keyboardShortcuts = DEFAULT_KEYBOARD_SHORTCUTS,\n}: UseDocSearchKeyboardEventsProps): void {\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent): void {\n if (isOpen && event.code === 'Escape' && isAskAiActive) {\n onAskAiToggle(false);\n return;\n }\n\n const isCmdK =\n keyboardShortcuts['Ctrl/Cmd+K'] &&\n event.key?.toLowerCase() === 'k' &&\n (event.metaKey || event.ctrlKey);\n const isSlash = keyboardShortcuts['/'] && event.key === '/';\n\n if (\n (event.code === 'Escape' && isOpen) ||\n isCmdK ||\n (!isEditingContent(event) && isSlash && !isOpen)\n ) {\n event.preventDefault();\n\n if (isOpen) {\n onClose();\n } else if (!document.body.classList.contains('DocSearch--active')) {\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [\n isOpen,\n isAskAiActive,\n keyboardShortcuts,\n onOpen,\n onClose,\n onAskAiToggle,\n ]);\n}\n","import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","import { useEffect } from 'react';\n\nexport type DocSearchTheme = 'dark' | 'light';\n\nexport interface UseThemeProps {\n theme?: DocSearchTheme;\n}\n\nexport const useTheme = ({ theme }: UseThemeProps): void => {\n useEffect(() => {\n if (!theme) {\n return undefined;\n }\n\n const previousTheme = document.documentElement.dataset.theme;\n\n if (theme === previousTheme) {\n return undefined;\n }\n\n document.documentElement.dataset.theme = theme;\n\n return (): void => {\n if (previousTheme === undefined) {\n delete document.documentElement.dataset.theme;\n } else {\n document.documentElement.dataset.theme = previousTheme;\n }\n };\n }, [theme]);\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport { useDocSearchKeyboardEvents } from './useDocSearchKeyboardEvents';\nimport { useIsMobile } from './useIsMobile';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\nimport type { KeyboardShortcuts } from './useKeyboardShortcuts.ts';\nimport type { DocSearchTheme } from './useTheme';\nimport { useTheme } from './useTheme';\n\nexport type DocSearchState =\n | 'modal-askai'\n | 'modal-search'\n | 'ready'\n | 'sidepanel';\n\nexport type View = 'modal' | 'sidepanel' | (Record<string, unknown> & string);\n\nexport type InitialAskAiMessage = {\n query: string;\n messageId?: string;\n suggestedQuestionId?: string;\n};\n\nexport type OnAskAiToggle = (\n active: boolean,\n initialMessage?: InitialAskAiMessage\n) => void;\n\n/** Imperative handle exposed by the DocSearch provider for programmatic control. */\nexport interface DocSearchRef {\n /** Opens the search modal. */\n open: () => void;\n /** Closes the search modal. */\n close: () => void;\n /** Opens Ask AI mode (sidepanel if available, otherwise modal). */\n openAskAi: (initialMessage?: InitialAskAiMessage) => void;\n /** Opens the sidepanel directly (no-op if sidepanel view not registered). */\n openSidepanel: (initialMessage?: InitialAskAiMessage) => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the modal is currently open. */\n readonly isOpen: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isSidepanelOpen: boolean;\n /** Returns true if sidepanel view is registered (hybrid mode). */\n readonly isSidepanelSupported: boolean;\n}\n\nexport interface DocSearchContext {\n docsearchState: DocSearchState;\n setDocsearchState: (newState: DocSearchState) => void;\n searchButtonRef: React.RefObject<HTMLButtonElement | null>;\n initialQuery: string;\n keyboardShortcuts: Required<KeyboardShortcuts>;\n openModal: () => void;\n closeModal: () => void;\n isAskAiActive: boolean;\n isModalActive: boolean;\n onAskAiToggle: OnAskAiToggle;\n initialAskAiMessage: InitialAskAiMessage | undefined;\n registerView: (view: View) => void;\n isHybridModeSupported: boolean;\n}\n\n/** Lifecycle callbacks for DocSearch. */\nexport interface DocSearchCallbacks {\n /** Called once DocSearch is mounted and ready for interaction. */\n onReady?: () => void;\n /** Called when the modal opens. */\n onOpen?: () => void;\n /** Called when the modal closes. */\n onClose?: () => void;\n /** Called when the sidepanel opens. */\n onSidepanelOpen?: () => void;\n /** Called when the sidepanel closes. */\n onSidepanelClose?: () => void;\n}\n\nexport interface DocSearchProps extends DocSearchCallbacks {\n children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;\n theme?: DocSearchTheme;\n initialQuery?: string;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nconst Context = React.createContext<DocSearchContext | undefined>(undefined);\nContext.displayName = 'DocSearchContext';\n\nfunction DocSearchInner(\n {\n children,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: DocSearchProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n const [docsearchState, setDocsearchState] =\n React.useState<DocSearchState>('ready');\n const [initialQuery, setInitialQuery] = React.useState<string>(\n props.initialQuery || ''\n );\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);\n const [initialAskAiMessage, setInitialAskAiMessage] =\n React.useState<InitialAskAiMessage>();\n const [registeredViews, setRegisteredViews] = React.useState(\n () => new Set<View>()\n );\n const isMobile = useIsMobile();\n const prevStateRef = React.useRef<DocSearchState>('ready');\n\n const isModalActive = ['modal-search', 'modal-askai'].includes(\n docsearchState\n );\n const isAskAiActive = docsearchState === 'modal-askai';\n const isHybridModeSupported = !isMobile && registeredViews.has('sidepanel');\n const isSidepanelOpen = docsearchState === 'sidepanel';\n\n // Call onReady on mount\n React.useEffect(() => {\n onReady?.();\n }, [onReady]);\n\n // Track state changes for lifecycle callbacks\n React.useEffect(() => {\n const prevState = prevStateRef.current;\n const currentState = docsearchState;\n\n // Modal opened\n if (\n (currentState === 'modal-search' || currentState === 'modal-askai') &&\n prevState !== 'modal-search' &&\n prevState !== 'modal-askai'\n ) {\n onOpen?.();\n }\n\n // Modal closed\n if (\n currentState === 'ready' &&\n (prevState === 'modal-search' || prevState === 'modal-askai')\n ) {\n onClose?.();\n }\n\n // Sidepanel opened\n if (currentState === 'sidepanel' && prevState !== 'sidepanel') {\n onSidepanelOpen?.();\n }\n\n // Sidepanel closed\n if (currentState !== 'sidepanel' && prevState === 'sidepanel') {\n onSidepanelClose?.();\n }\n\n prevStateRef.current = currentState;\n }, [docsearchState, onOpen, onClose, onSidepanelOpen, onSidepanelClose]);\n\n const openModal = React.useCallback((): void => {\n setDocsearchState('modal-search');\n }, []);\n\n const closeModal = React.useCallback((): void => {\n setDocsearchState('ready');\n // Refocus the Modal trigger on close\n searchButtonRef.current?.focus();\n setInitialQuery(props.initialQuery ?? '');\n }, [setDocsearchState, props.initialQuery]);\n\n const onAskAiToggle: OnAskAiToggle = React.useCallback(\n (active, initialMessage) => {\n // Don't use hybrid mode on mobile\n if (!isMobile && active && isHybridModeSupported) {\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n return;\n }\n\n setDocsearchState(active ? 'modal-askai' : 'modal-search');\n },\n [setDocsearchState, isMobile, isHybridModeSupported]\n );\n\n const openSidepanel = React.useCallback(\n (initialMessage?: InitialAskAiMessage): void => {\n // Guard: no-op if sidepanel view hasn't been registered\n if (!registeredViews.has('sidepanel')) return;\n\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n },\n [setDocsearchState, registeredViews]\n );\n\n const onInput = React.useCallback(\n (event: KeyboardEvent): void => {\n setDocsearchState('modal-search');\n setInitialQuery(event.key);\n },\n [setDocsearchState, setInitialQuery]\n );\n\n const registerView = React.useCallback(\n (view: View): void => {\n if (registeredViews.has(view)) return;\n\n setRegisteredViews((prev) => {\n const newViews = new Set(prev);\n newViews.add(view);\n return newViews;\n });\n },\n [registeredViews]\n );\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: openModal,\n close: closeModal,\n openAskAi: (initialMessage?: InitialAskAiMessage): void =>\n onAskAiToggle(true, initialMessage),\n openSidepanel,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isModalActive;\n },\n get isSidepanelOpen(): boolean {\n return isSidepanelOpen;\n },\n get isSidepanelSupported(): boolean {\n return isHybridModeSupported;\n },\n }),\n [\n openModal,\n closeModal,\n onAskAiToggle,\n openSidepanel,\n isModalActive,\n isSidepanelOpen,\n isHybridModeSupported,\n ]\n );\n\n useTheme({ theme });\n\n useDocSearchKeyboardEvents({\n isOpen: isModalActive,\n onOpen: openModal,\n onClose: closeModal,\n onAskAiToggle,\n onInput,\n isAskAiActive,\n searchButtonRef,\n keyboardShortcuts,\n });\n\n const value: DocSearchContext = React.useMemo(\n () => ({\n docsearchState,\n setDocsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n }),\n [\n docsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n ]\n );\n\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport const DocSearch = React.forwardRef(DocSearchInner);\nDocSearch.displayName = 'DocSearch';\n\nexport function useDocSearch(): DocSearchContext {\n const ctx = React.useContext(Context);\n\n if (ctx === undefined) {\n throw new Error(\n '`useDocSearch` must be used within the `DocSearch` provider'\n );\n }\n\n return ctx;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["React","React"],"sources":["../../src/useKeyboardShortcuts.ts","../../src/useDocSearchKeyboardEvents.ts","../../src/useIsMobile.ts","../../src/useTheme.ts","../../src/DocSearch.tsx"],"sourcesContent":["export interface DocSearchModalShortcuts {\n /**\n * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.\n *\n * @default true\n */\n 'Ctrl/Cmd+K'?: boolean;\n /**\n * Enable/disable the / shortcut to open the DocSearch modal.\n *\n * @default true\n */\n '/'?: boolean;\n}\n\nexport interface SidepanelShortcuts {\n /**\n * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.\n *\n * @default true\n */\n 'Ctrl/Cmd+I'?: boolean;\n}\n\nexport type KeyboardShortcuts = DocSearchModalShortcuts & SidepanelShortcuts;\n\n/**\n * Default keyboard shortcuts configuration for DocSearch. These values are used\n * when no keyboardShortcuts prop is provided or when specific shortcuts are not\n * configured.\n */\nexport const DEFAULT_KEYBOARD_SHORTCUTS: Required<KeyboardShortcuts> = {\n 'Ctrl/Cmd+K': true,\n '/': true,\n 'Ctrl/Cmd+I': true,\n} as const;\n\n/**\n * Merges user-provided keyboard shortcuts with defaults.\n *\n * @param userShortcuts - Optional user configuration.\n * @returns Complete keyboard shortcuts configuration with defaults applied.\n */\nexport function useKeyboardShortcuts(\n userShortcuts?: KeyboardShortcuts\n): Required<KeyboardShortcuts> {\n return {\n ...DEFAULT_KEYBOARD_SHORTCUTS,\n ...userShortcuts,\n };\n}\n","import React from 'react';\n\nimport {\n DEFAULT_KEYBOARD_SHORTCUTS,\n type KeyboardShortcuts,\n} from './useKeyboardShortcuts';\n\nexport interface UseDocSearchKeyboardEventsProps {\n isOpen: boolean;\n onOpen: () => void;\n onClose: () => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n onInput?: (event: KeyboardEvent) => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n searchButtonRef?: React.RefObject<HTMLButtonElement | null>;\n isAskAiActive: boolean;\n onAskAiToggle: (toggle: boolean) => void;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nfunction isEditingContent(event: KeyboardEvent): boolean {\n const element = event.composedPath()[0] as HTMLElement;\n const tagName = element.tagName;\n\n return (\n element.isContentEditable ||\n tagName === 'INPUT' ||\n tagName === 'SELECT' ||\n tagName === 'TEXTAREA'\n );\n}\n\nexport function useDocSearchKeyboardEvents({\n isOpen,\n isAskAiActive,\n onAskAiToggle,\n onClose,\n onOpen,\n keyboardShortcuts = DEFAULT_KEYBOARD_SHORTCUTS,\n}: UseDocSearchKeyboardEventsProps): void {\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent): void {\n if (isOpen && event.code === 'Escape' && isAskAiActive) {\n onAskAiToggle(false);\n return;\n }\n\n const isCmdK =\n keyboardShortcuts['Ctrl/Cmd+K'] &&\n event.key?.toLowerCase() === 'k' &&\n (event.metaKey || event.ctrlKey);\n const isSlash = keyboardShortcuts['/'] && event.key === '/';\n\n if (\n (event.code === 'Escape' && isOpen) ||\n isCmdK ||\n (!isEditingContent(event) && isSlash && !isOpen)\n ) {\n event.preventDefault();\n\n if (isOpen) {\n onClose();\n } else if (!document.body.classList.contains('DocSearch--active')) {\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [\n isOpen,\n isAskAiActive,\n keyboardShortcuts,\n onOpen,\n onClose,\n onAskAiToggle,\n ]);\n}\n","import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","import { useEffect } from 'react';\n\nexport type DocSearchTheme = 'dark' | 'light';\n\nexport interface UseThemeProps {\n theme?: DocSearchTheme;\n}\n\nexport const useTheme = ({ theme }: UseThemeProps): void => {\n useEffect(() => {\n if (!theme) {\n return undefined;\n }\n\n const previousTheme = document.documentElement.dataset.theme;\n\n if (theme === previousTheme) {\n return undefined;\n }\n\n document.documentElement.dataset.theme = theme;\n\n return (): void => {\n if (previousTheme === undefined) {\n delete document.documentElement.dataset.theme;\n } else {\n document.documentElement.dataset.theme = previousTheme;\n }\n };\n }, [theme]);\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport { useDocSearchKeyboardEvents } from './useDocSearchKeyboardEvents';\nimport { useIsMobile } from './useIsMobile';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\nimport type { KeyboardShortcuts } from './useKeyboardShortcuts.ts';\nimport type { DocSearchTheme } from './useTheme';\nimport { useTheme } from './useTheme';\n\nexport type DocSearchState =\n | 'modal-askai'\n | 'modal-search'\n | 'ready'\n | 'sidepanel';\n\nexport type View = 'modal' | 'sidepanel' | (Record<string, unknown> & string);\n\nexport type InitialAskAiMessage = {\n query: string;\n messageId?: string;\n suggestedQuestionId?: string;\n};\n\nexport type OnAskAiToggle = (\n active: boolean,\n initialMessage?: InitialAskAiMessage\n) => void;\n\n/** Imperative handle exposed by the DocSearch provider for programmatic control. */\nexport interface DocSearchRef {\n /** Opens the search modal. */\n open: () => void;\n /** Closes the search modal. */\n close: () => void;\n /** Opens Ask AI mode (sidepanel if available, otherwise modal). */\n openAskAi: (initialMessage?: InitialAskAiMessage) => void;\n /** Opens the sidepanel directly (no-op if sidepanel view not registered). */\n openSidepanel: (initialMessage?: InitialAskAiMessage) => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the modal is currently open. */\n readonly isOpen: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isSidepanelOpen: boolean;\n /** Returns true if sidepanel view is registered (hybrid mode). */\n readonly isSidepanelSupported: boolean;\n}\n\nexport interface DocSearchContext {\n /** Default Algolia application ID for child DocSearch/Sidepanel components. */\n appId?: string;\n /** Default Algolia API key for child DocSearch/Sidepanel components. */\n apiKey?: string;\n docsearchState: DocSearchState;\n setDocsearchState: (newState: DocSearchState) => void;\n searchButtonRef: React.RefObject<HTMLButtonElement | null>;\n initialQuery: string;\n keyboardShortcuts: Required<KeyboardShortcuts>;\n openModal: () => void;\n closeModal: () => void;\n isAskAiActive: boolean;\n isModalActive: boolean;\n onAskAiToggle: OnAskAiToggle;\n initialAskAiMessage: InitialAskAiMessage | undefined;\n registerView: (view: View) => void;\n isHybridModeSupported: boolean;\n}\n\n/** Lifecycle callbacks for DocSearch. */\nexport interface DocSearchCallbacks {\n /** Called once DocSearch is mounted and ready for interaction. */\n onReady?: () => void;\n /** Called when the modal opens. */\n onOpen?: () => void;\n /** Called when the modal closes. */\n onClose?: () => void;\n /** Called when the sidepanel opens. */\n onSidepanelOpen?: () => void;\n /** Called when the sidepanel closes. */\n onSidepanelClose?: () => void;\n}\n\nexport interface DocSearchProps extends DocSearchCallbacks {\n children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;\n /** Default Algolia application id for descendant DocSearch views. */\n appId?: string;\n /** Default Algolia API key for descendant DocSearch views. */\n apiKey?: string;\n theme?: DocSearchTheme;\n initialQuery?: string;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nconst Context = React.createContext<DocSearchContext | undefined>(undefined);\nContext.displayName = 'DocSearchContext';\n\nfunction DocSearchInner(\n {\n children,\n appId,\n apiKey,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: DocSearchProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n const [docsearchState, setDocsearchState] =\n React.useState<DocSearchState>('ready');\n const [initialQuery, setInitialQuery] = React.useState<string>(\n props.initialQuery || ''\n );\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);\n const [initialAskAiMessage, setInitialAskAiMessage] =\n React.useState<InitialAskAiMessage>();\n const [registeredViews, setRegisteredViews] = React.useState(\n () => new Set<View>()\n );\n const isMobile = useIsMobile();\n const prevStateRef = React.useRef<DocSearchState>('ready');\n\n const isModalActive = ['modal-search', 'modal-askai'].includes(\n docsearchState\n );\n const isAskAiActive = docsearchState === 'modal-askai';\n const isHybridModeSupported = !isMobile && registeredViews.has('sidepanel');\n const isSidepanelOpen = docsearchState === 'sidepanel';\n\n // Call onReady on mount\n React.useEffect(() => {\n onReady?.();\n }, [onReady]);\n\n // Track state changes for lifecycle callbacks\n React.useEffect(() => {\n const prevState = prevStateRef.current;\n const currentState = docsearchState;\n\n // Modal opened\n if (\n (currentState === 'modal-search' || currentState === 'modal-askai') &&\n prevState !== 'modal-search' &&\n prevState !== 'modal-askai'\n ) {\n onOpen?.();\n }\n\n // Modal closed\n if (\n currentState === 'ready' &&\n (prevState === 'modal-search' || prevState === 'modal-askai')\n ) {\n onClose?.();\n }\n\n // Sidepanel opened\n if (currentState === 'sidepanel' && prevState !== 'sidepanel') {\n onSidepanelOpen?.();\n }\n\n // Sidepanel closed\n if (currentState !== 'sidepanel' && prevState === 'sidepanel') {\n onSidepanelClose?.();\n }\n\n prevStateRef.current = currentState;\n }, [docsearchState, onOpen, onClose, onSidepanelOpen, onSidepanelClose]);\n\n const openModal = React.useCallback((): void => {\n setDocsearchState('modal-search');\n }, []);\n\n const closeModal = React.useCallback((): void => {\n setDocsearchState('ready');\n // Refocus the Modal trigger on close\n searchButtonRef.current?.focus();\n setInitialQuery(props.initialQuery ?? '');\n }, [setDocsearchState, props.initialQuery]);\n\n const onAskAiToggle: OnAskAiToggle = React.useCallback(\n (active, initialMessage) => {\n // Don't use hybrid mode on mobile\n if (!isMobile && active && isHybridModeSupported) {\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n return;\n }\n\n setDocsearchState(active ? 'modal-askai' : 'modal-search');\n },\n [setDocsearchState, isMobile, isHybridModeSupported]\n );\n\n const openSidepanel = React.useCallback(\n (initialMessage?: InitialAskAiMessage): void => {\n // Guard: no-op if sidepanel view hasn't been registered\n if (!registeredViews.has('sidepanel')) return;\n\n setInitialAskAiMessage(initialMessage);\n setDocsearchState('sidepanel');\n },\n [setDocsearchState, registeredViews]\n );\n\n const onInput = React.useCallback(\n (event: KeyboardEvent): void => {\n setDocsearchState('modal-search');\n setInitialQuery(event.key);\n },\n [setDocsearchState, setInitialQuery]\n );\n\n const registerView = React.useCallback(\n (view: View): void => {\n if (registeredViews.has(view)) return;\n\n setRegisteredViews((prev) => {\n const newViews = new Set(prev);\n newViews.add(view);\n return newViews;\n });\n },\n [registeredViews]\n );\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: openModal,\n close: closeModal,\n openAskAi: (initialMessage?: InitialAskAiMessage): void =>\n onAskAiToggle(true, initialMessage),\n openSidepanel,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isModalActive;\n },\n get isSidepanelOpen(): boolean {\n return isSidepanelOpen;\n },\n get isSidepanelSupported(): boolean {\n return isHybridModeSupported;\n },\n }),\n [\n openModal,\n closeModal,\n onAskAiToggle,\n openSidepanel,\n isModalActive,\n isSidepanelOpen,\n isHybridModeSupported,\n ]\n );\n\n useTheme({ theme });\n\n useDocSearchKeyboardEvents({\n isOpen: isModalActive,\n onOpen: openModal,\n onClose: closeModal,\n onAskAiToggle,\n onInput,\n isAskAiActive,\n searchButtonRef,\n keyboardShortcuts,\n });\n\n const value: DocSearchContext = React.useMemo(\n () => ({\n appId,\n apiKey,\n docsearchState,\n setDocsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n }),\n [\n appId,\n apiKey,\n docsearchState,\n searchButtonRef,\n initialQuery,\n keyboardShortcuts,\n openModal,\n closeModal,\n isAskAiActive,\n isModalActive,\n onAskAiToggle,\n initialAskAiMessage,\n registerView,\n isHybridModeSupported,\n ]\n );\n\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport const DocSearch = React.forwardRef(DocSearchInner);\nDocSearch.displayName = 'DocSearch';\n\nexport function useDocSearch(): DocSearchContext {\n const ctx = React.useContext(Context);\n\n if (ctx === undefined) {\n throw new Error(\n '`useDocSearch` must be used within the `DocSearch` provider'\n );\n }\n\n return ctx;\n}\n"],"mappings":"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"}
|