@docsearch/core 4.7.0 → 5.0.0-beta.1

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.
@@ -1,138 +1,71 @@
1
- import React, { JSX } from 'react';
2
-
3
- interface DocSearchModalShortcuts {
4
- /**
5
- * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.
6
- *
7
- * @default true
8
- */
9
- 'Ctrl/Cmd+K'?: boolean;
10
- /**
11
- * Enable/disable the / shortcut to open the DocSearch modal.
12
- *
13
- * @default true
14
- */
15
- '/'?: boolean;
16
- }
17
- interface SidepanelShortcuts {
18
- /**
19
- * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.
20
- *
21
- * @default true
22
- */
23
- 'Ctrl/Cmd+I'?: boolean;
24
- }
25
- type KeyboardShortcuts = DocSearchModalShortcuts & SidepanelShortcuts;
26
- /**
27
- * Default keyboard shortcuts configuration for DocSearch.
28
- * These values are used when no keyboardShortcuts prop is provided
29
- * or when specific shortcuts are not configured.
30
- */
31
- declare const DEFAULT_KEYBOARD_SHORTCUTS: Required<KeyboardShortcuts>;
32
- /**
33
- * Merges user-provided keyboard shortcuts with defaults.
34
- *
35
- * @param userShortcuts - Optional user configuration.
36
- * @returns Complete keyboard shortcuts configuration with defaults applied.
37
- */
38
- declare function useKeyboardShortcuts(userShortcuts?: KeyboardShortcuts): Required<KeyboardShortcuts>;
39
-
40
- type DocSearchTheme = 'dark' | 'light';
41
- interface UseThemeProps {
42
- theme?: DocSearchTheme;
43
- }
44
- declare const useTheme: ({ theme }: UseThemeProps) => void;
45
-
1
+ import { DEFAULT_KEYBOARD_SHORTCUTS, DocSearchModalShortcuts, KeyboardShortcuts, SidepanelShortcuts, useKeyboardShortcuts } from "./useKeyboardShortcuts.js";
2
+ import { DocSearchTheme, UseThemeProps, useTheme } from "./useTheme.js";
3
+ import { UseDocSearchKeyboardEventsProps, useDocSearchKeyboardEvents } from "./useDocSearchKeyboardEvents.js";
4
+ import React, { JSX } from "react";
5
+ //#region src/DocSearch.d.ts
46
6
  type DocSearchState = 'modal-askai' | 'modal-search' | 'ready' | 'sidepanel';
47
7
  type View = 'modal' | 'sidepanel' | (Record<string, unknown> & string);
48
8
  type InitialAskAiMessage = {
49
- query: string;
50
- messageId?: string;
51
- suggestedQuestionId?: string;
9
+ query: string;
10
+ messageId?: string;
11
+ suggestedQuestionId?: string;
52
12
  };
53
13
  type OnAskAiToggle = (active: boolean, initialMessage?: InitialAskAiMessage) => void;
54
- /**
55
- * Imperative handle exposed by the DocSearch provider for programmatic control.
56
- */
14
+ /** Imperative handle exposed by the DocSearch provider for programmatic control. */
57
15
  interface DocSearchRef {
58
- /** Opens the search modal. */
59
- open: () => void;
60
- /** Closes the search modal. */
61
- close: () => void;
62
- /** Opens Ask AI mode (sidepanel if available, otherwise modal). */
63
- openAskAi: (initialMessage?: InitialAskAiMessage) => void;
64
- /** Opens the sidepanel directly (no-op if sidepanel view not registered). */
65
- openSidepanel: (initialMessage?: InitialAskAiMessage) => void;
66
- /** Returns true once the component is mounted and ready. */
67
- readonly isReady: boolean;
68
- /** Returns true if the modal is currently open. */
69
- readonly isOpen: boolean;
70
- /** Returns true if the sidepanel is currently open. */
71
- readonly isSidepanelOpen: boolean;
72
- /** Returns true if sidepanel view is registered (hybrid mode). */
73
- readonly isSidepanelSupported: boolean;
16
+ /** Opens the search modal. */
17
+ open: () => void;
18
+ /** Closes the search modal. */
19
+ close: () => void;
20
+ /** Opens Ask AI mode (sidepanel if available, otherwise modal). */
21
+ openAskAi: (initialMessage?: InitialAskAiMessage) => void;
22
+ /** Opens the sidepanel directly (no-op if sidepanel view not registered). */
23
+ openSidepanel: (initialMessage?: InitialAskAiMessage) => void;
24
+ /** Returns true once the component is mounted and ready. */
25
+ readonly isReady: boolean;
26
+ /** Returns true if the modal is currently open. */
27
+ readonly isOpen: boolean;
28
+ /** Returns true if the sidepanel is currently open. */
29
+ readonly isSidepanelOpen: boolean;
30
+ /** Returns true if sidepanel view is registered (hybrid mode). */
31
+ readonly isSidepanelSupported: boolean;
74
32
  }
75
33
  interface DocSearchContext {
76
- docsearchState: DocSearchState;
77
- setDocsearchState: (newState: DocSearchState) => void;
78
- searchButtonRef: React.RefObject<HTMLButtonElement | null>;
79
- initialQuery: string;
80
- keyboardShortcuts: Required<KeyboardShortcuts>;
81
- openModal: () => void;
82
- closeModal: () => void;
83
- isAskAiActive: boolean;
84
- isModalActive: boolean;
85
- onAskAiToggle: OnAskAiToggle;
86
- initialAskAiMessage: InitialAskAiMessage | undefined;
87
- clearInitialAskAiMessage: () => void;
88
- registerView: (view: View) => void;
89
- isHybridModeSupported: boolean;
34
+ docsearchState: DocSearchState;
35
+ setDocsearchState: (newState: DocSearchState) => void;
36
+ searchButtonRef: React.RefObject<HTMLButtonElement | null>;
37
+ initialQuery: string;
38
+ keyboardShortcuts: Required<KeyboardShortcuts>;
39
+ openModal: () => void;
40
+ closeModal: () => void;
41
+ isAskAiActive: boolean;
42
+ isModalActive: boolean;
43
+ onAskAiToggle: OnAskAiToggle;
44
+ initialAskAiMessage: InitialAskAiMessage | undefined;
45
+ registerView: (view: View) => void;
46
+ isHybridModeSupported: boolean;
90
47
  }
91
- /**
92
- * Lifecycle callbacks for DocSearch.
93
- */
48
+ /** Lifecycle callbacks for DocSearch. */
94
49
  interface DocSearchCallbacks {
95
- /** Called once DocSearch is mounted and ready for interaction. */
96
- onReady?: () => void;
97
- /** Called when the modal opens. */
98
- onOpen?: () => void;
99
- /** Called when the modal closes. */
100
- onClose?: () => void;
101
- /** Called when the sidepanel opens. */
102
- onSidepanelOpen?: () => void;
103
- /** Called when the sidepanel closes. */
104
- onSidepanelClose?: () => void;
50
+ /** Called once DocSearch is mounted and ready for interaction. */
51
+ onReady?: () => void;
52
+ /** Called when the modal opens. */
53
+ onOpen?: () => void;
54
+ /** Called when the modal closes. */
55
+ onClose?: () => void;
56
+ /** Called when the sidepanel opens. */
57
+ onSidepanelOpen?: () => void;
58
+ /** Called when the sidepanel closes. */
59
+ onSidepanelClose?: () => void;
105
60
  }
106
61
  interface DocSearchProps extends DocSearchCallbacks {
107
- children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;
108
- theme?: DocSearchTheme;
109
- initialQuery?: string;
110
- keyboardShortcuts?: KeyboardShortcuts;
62
+ children: Array<JSX.Element | null> | JSX.Element | React.ReactNode | null;
63
+ theme?: DocSearchTheme;
64
+ initialQuery?: string;
65
+ keyboardShortcuts?: KeyboardShortcuts;
111
66
  }
112
67
  declare const DocSearch: React.ForwardRefExoticComponent<DocSearchProps & React.RefAttributes<DocSearchRef>>;
113
68
  declare function useDocSearch(): DocSearchContext;
114
-
115
- interface UseDocSearchKeyboardEventsProps {
116
- isOpen: boolean;
117
- onOpen: () => void;
118
- onClose: () => void;
119
- /**
120
- * Deprecated: Still here for backwards compat.
121
- *
122
- * @deprecated
123
- */
124
- onInput?: (event: KeyboardEvent) => void;
125
- /**
126
- * Deprecated: Still here for backwards compat.
127
- *
128
- * @deprecated
129
- */
130
- searchButtonRef?: React.RefObject<HTMLButtonElement | null>;
131
- isAskAiActive: boolean;
132
- onAskAiToggle: (toggle: boolean) => void;
133
- keyboardShortcuts?: KeyboardShortcuts;
134
- }
135
- declare function useDocSearchKeyboardEvents({ isOpen, isAskAiActive, onAskAiToggle, onClose, onOpen, keyboardShortcuts, }: UseDocSearchKeyboardEventsProps): void;
136
-
137
- export { DEFAULT_KEYBOARD_SHORTCUTS, DocSearch, useDocSearch, useDocSearchKeyboardEvents, useKeyboardShortcuts, useTheme };
138
- export type { DocSearchCallbacks, DocSearchContext, DocSearchModalShortcuts, DocSearchProps, DocSearchRef, DocSearchState, DocSearchTheme, InitialAskAiMessage, KeyboardShortcuts, OnAskAiToggle, SidepanelShortcuts, UseDocSearchKeyboardEventsProps, UseThemeProps, View };
69
+ //#endregion
70
+ export { DEFAULT_KEYBOARD_SHORTCUTS, DocSearch, DocSearchCallbacks, DocSearchContext, DocSearchModalShortcuts, DocSearchProps, DocSearchRef, DocSearchState, DocSearchTheme, InitialAskAiMessage, KeyboardShortcuts, OnAskAiToggle, SidepanelShortcuts, UseDocSearchKeyboardEventsProps, UseThemeProps, View, useDocSearch, useDocSearchKeyboardEvents, useKeyboardShortcuts, useTheme };
71
+ //# sourceMappingURL=index.d.ts.map
package/dist/esm/index.js CHANGED
@@ -1 +1,207 @@
1
- import e,{useEffect as t}from"react";function n(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t);if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(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 a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach(function(t){r(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,u=[],l=!0,c=!1;try{if(a=(n=n.call(e)).next,0===t);else for(;!(l=(r=a.call(n)).done)&&(u.push(r.value),u.length!==t);l=!0);}catch(e){c=!0,o=e}finally{try{if(!l&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(c)throw o}}return u}}(e,t)||function(e,t){if(e){if("string"==typeof e)return n(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var u={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function l(e){return a(a({},u),e)}function c(t){var n=t.isOpen,r=t.isAskAiActive,o=t.onAskAiToggle,a=t.onClose,i=t.onOpen,l=t.keyboardShortcuts,c=void 0===l?u:l;e.useEffect(function(){function e(e){var t;if(n&&"Escape"===e.code&&r)o(!1);else{var u=c["Ctrl/Cmd+K"]&&"k"===(null===(t=e.key)||void 0===t?void 0:t.toLowerCase())&&(e.metaKey||e.ctrlKey),l=c["/"]&&"/"===e.key;("Escape"===e.code&&n||u||!function(e){var t=e.composedPath()[0],n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n||"BUTTON"===n}(e)&&l&&!n)&&(e.preventDefault(),n?a():document.body.classList.contains("DocSearch--active")||i())}}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}},[n,r,c,i,a,o])}var s=function(e){var n=e.theme;t(function(){if(n){var e=document.documentElement.dataset.theme;if(n!==e)return document.documentElement.dataset.theme=n,function(){void 0===e?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=e}}},[n])},d=["children","theme","onReady","onOpen","onClose","onSidepanelOpen","onSidepanelClose"],f=e.createContext(void 0);f.displayName="DocSearchContext";var p=e.forwardRef(function(t,n){var r=t.children,o=t.theme,a=t.onReady,u=t.onOpen,p=t.onClose,m=t.onSidepanelOpen,v=t.onSidepanelClose,y=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(-1!==t.indexOf(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],-1===t.indexOf(n)&&{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(t,d),h=i(e.useState("ready"),2),b=h[0],S=h[1],O=i(e.useState(y.initialQuery||""),2),w=O[0],g=O[1],k=e.useRef(null),A=l(y.keyboardShortcuts),C=i(e.useState(),2),E=C[0],j=C[1],P=i(e.useState(function(){return new Set}),2),D=P[0],T=P[1],x=function(){var t=i(e.useState(!1),2),n=t[0],r=t[1];return e.useEffect(function(){var e=function(){var e=window.matchMedia("(max-width: 768px)");r(e.matches)};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}},[]),n}(),M=e.useRef("ready"),I=["modal-search","modal-askai"].includes(b),R="modal-askai"===b,L=!x&&D.has("sidepanel"),N="sidepanel"===b;e.useEffect(function(){null==a||a()},[a]),e.useEffect(function(){var e=M.current,t=b;"modal-search"!==t&&"modal-askai"!==t||"modal-search"===e||"modal-askai"===e||null==u||u(),"ready"!==t||"modal-search"!==e&&"modal-askai"!==e||null==p||p(),"sidepanel"===t&&"sidepanel"!==e&&(null==m||m()),"sidepanel"!==t&&"sidepanel"===e&&(null==v||v()),M.current=t},[b,u,p,m,v]);var K=e.useCallback(function(){S("modal-search")},[]),Q=e.useCallback(function(){var e,t;S("ready"),null===(e=k.current)||void 0===e||e.focus(),g(null!==(t=y.initialQuery)&&void 0!==t?t:"")},[S,y.initialQuery]),U=e.useCallback(function(e,t){if(!x&&e&&L)return j(t),void S("sidepanel");S(e?"modal-askai":"modal-search")},[S,x,L]),z=e.useCallback(function(e){D.has("sidepanel")&&(j(e),S("sidepanel"))},[S,D]);e.useCallback(function(e){S("modal-search"),g(e.key)},[S,g]);var B=e.useCallback(function(){j(void 0)},[]),H=e.useCallback(function(e){D.has(e)||T(function(t){var n=new Set(t);return n.add(e),n})},[D]);e.useImperativeHandle(n,function(){return{open:K,close:Q,openAskAi:function(e){return U(!0,e)},openSidepanel:z,get isReady(){return!0},get isOpen(){return I},get isSidepanelOpen(){return N},get isSidepanelSupported(){return L}}},[K,Q,U,z,I,N,L]),s({theme:o}),c({isOpen:I,onOpen:K,onClose:Q,onAskAiToggle:U,isAskAiActive:R,keyboardShortcuts:A});var V=e.useMemo(function(){return{docsearchState:b,setDocsearchState:S,searchButtonRef:k,initialQuery:w,keyboardShortcuts:A,openModal:K,closeModal:Q,isAskAiActive:R,isModalActive:I,onAskAiToggle:U,initialAskAiMessage:E,clearInitialAskAiMessage:B,registerView:H,isHybridModeSupported:L}},[b,k,w,A,K,Q,R,I,U,E,B,H,L]);return e.createElement(f.Provider,{value:V},r)});function m(){var t=e.useContext(f);if(void 0===t)throw new Error("`useDocSearch` must be used within the `DocSearch` provider");return t}p.displayName="DocSearch";export{u as DEFAULT_KEYBOARD_SHORTCUTS,p as DocSearch,m as useDocSearch,c as useDocSearchKeyboardEvents,l as useKeyboardShortcuts,s as useTheme};
1
+ import { n as useKeyboardShortcuts, t as DEFAULT_KEYBOARD_SHORTCUTS } from "./useKeyboardShortcuts-D47pg3fZ.js";
2
+ import { useDocSearchKeyboardEvents } from "./useDocSearchKeyboardEvents.js";
3
+ import { useTheme } from "./useTheme.js";
4
+ import React from "react";
5
+
6
+ //#region src/useIsMobile.ts
7
+ const useIsMobile = () => {
8
+ const [isMobile, setIsMobile] = React.useState(false);
9
+ React.useEffect(() => {
10
+ const checkForMobile = () => {
11
+ const isMobileMediaQuery = window.matchMedia("(max-width: 768px)");
12
+ setIsMobile(isMobileMediaQuery.matches);
13
+ };
14
+ checkForMobile();
15
+ window.addEventListener("resize", checkForMobile);
16
+ return () => {
17
+ window.removeEventListener("resize", checkForMobile);
18
+ };
19
+ }, []);
20
+ return isMobile;
21
+ };
22
+
23
+ //#endregion
24
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectWithoutPropertiesLoose.js
25
+ function _objectWithoutPropertiesLoose(r, e) {
26
+ if (null == r) return {};
27
+ var t = {};
28
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
29
+ if (e.includes(n)) continue;
30
+ t[n] = r[n];
31
+ }
32
+ return t;
33
+ }
34
+
35
+ //#endregion
36
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectWithoutProperties.js
37
+ function _objectWithoutProperties(e, t) {
38
+ if (null == e) return {};
39
+ var o, r, i = _objectWithoutPropertiesLoose(e, t);
40
+ if (Object.getOwnPropertySymbols) {
41
+ var s = Object.getOwnPropertySymbols(e);
42
+ for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
43
+ }
44
+ return i;
45
+ }
46
+
47
+ //#endregion
48
+ //#region src/DocSearch.tsx
49
+ const _excluded = [
50
+ "children",
51
+ "theme",
52
+ "onReady",
53
+ "onOpen",
54
+ "onClose",
55
+ "onSidepanelOpen",
56
+ "onSidepanelClose"
57
+ ];
58
+ const Context = React.createContext(void 0);
59
+ Context.displayName = "DocSearchContext";
60
+ function DocSearchInner(_ref, ref) {
61
+ let { children, theme, onReady, onOpen, onClose, onSidepanelOpen, onSidepanelClose } = _ref, props = _objectWithoutProperties(_ref, _excluded);
62
+ const [docsearchState, setDocsearchState] = React.useState("ready");
63
+ const [initialQuery, setInitialQuery] = React.useState(props.initialQuery || "");
64
+ const searchButtonRef = React.useRef(null);
65
+ const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);
66
+ const [initialAskAiMessage, setInitialAskAiMessage] = React.useState();
67
+ const [registeredViews, setRegisteredViews] = React.useState(() => /* @__PURE__ */ new Set());
68
+ const isMobile = useIsMobile();
69
+ const prevStateRef = React.useRef("ready");
70
+ const isModalActive = ["modal-search", "modal-askai"].includes(docsearchState);
71
+ const isAskAiActive = docsearchState === "modal-askai";
72
+ const isHybridModeSupported = !isMobile && registeredViews.has("sidepanel");
73
+ const isSidepanelOpen = docsearchState === "sidepanel";
74
+ React.useEffect(() => {
75
+ onReady === null || onReady === void 0 || onReady();
76
+ }, [onReady]);
77
+ React.useEffect(() => {
78
+ const prevState = prevStateRef.current;
79
+ const currentState = docsearchState;
80
+ if ((currentState === "modal-search" || currentState === "modal-askai") && prevState !== "modal-search" && prevState !== "modal-askai") onOpen === null || onOpen === void 0 || onOpen();
81
+ if (currentState === "ready" && (prevState === "modal-search" || prevState === "modal-askai")) onClose === null || onClose === void 0 || onClose();
82
+ if (currentState === "sidepanel" && prevState !== "sidepanel") onSidepanelOpen === null || onSidepanelOpen === void 0 || onSidepanelOpen();
83
+ if (currentState !== "sidepanel" && prevState === "sidepanel") onSidepanelClose === null || onSidepanelClose === void 0 || onSidepanelClose();
84
+ prevStateRef.current = currentState;
85
+ }, [
86
+ docsearchState,
87
+ onOpen,
88
+ onClose,
89
+ onSidepanelOpen,
90
+ onSidepanelClose
91
+ ]);
92
+ const openModal = React.useCallback(() => {
93
+ setDocsearchState("modal-search");
94
+ }, []);
95
+ const closeModal = React.useCallback(() => {
96
+ var _searchButtonRef$curr, _props$initialQuery;
97
+ setDocsearchState("ready");
98
+ (_searchButtonRef$curr = searchButtonRef.current) === null || _searchButtonRef$curr === void 0 || _searchButtonRef$curr.focus();
99
+ setInitialQuery((_props$initialQuery = props.initialQuery) !== null && _props$initialQuery !== void 0 ? _props$initialQuery : "");
100
+ }, [setDocsearchState, props.initialQuery]);
101
+ const onAskAiToggle = React.useCallback((active, initialMessage) => {
102
+ if (!isMobile && active && isHybridModeSupported) {
103
+ setInitialAskAiMessage(initialMessage);
104
+ setDocsearchState("sidepanel");
105
+ return;
106
+ }
107
+ setDocsearchState(active ? "modal-askai" : "modal-search");
108
+ }, [
109
+ setDocsearchState,
110
+ isMobile,
111
+ isHybridModeSupported
112
+ ]);
113
+ const openSidepanel = React.useCallback((initialMessage) => {
114
+ if (!registeredViews.has("sidepanel")) return;
115
+ setInitialAskAiMessage(initialMessage);
116
+ setDocsearchState("sidepanel");
117
+ }, [setDocsearchState, registeredViews]);
118
+ const onInput = React.useCallback((event) => {
119
+ setDocsearchState("modal-search");
120
+ setInitialQuery(event.key);
121
+ }, [setDocsearchState, setInitialQuery]);
122
+ const registerView = React.useCallback((view) => {
123
+ if (registeredViews.has(view)) return;
124
+ setRegisteredViews((prev) => {
125
+ const newViews = new Set(prev);
126
+ newViews.add(view);
127
+ return newViews;
128
+ });
129
+ }, [registeredViews]);
130
+ React.useImperativeHandle(ref, () => ({
131
+ open: openModal,
132
+ close: closeModal,
133
+ openAskAi: (initialMessage) => onAskAiToggle(true, initialMessage),
134
+ openSidepanel,
135
+ get isReady() {
136
+ return true;
137
+ },
138
+ get isOpen() {
139
+ return isModalActive;
140
+ },
141
+ get isSidepanelOpen() {
142
+ return isSidepanelOpen;
143
+ },
144
+ get isSidepanelSupported() {
145
+ return isHybridModeSupported;
146
+ }
147
+ }), [
148
+ openModal,
149
+ closeModal,
150
+ onAskAiToggle,
151
+ openSidepanel,
152
+ isModalActive,
153
+ isSidepanelOpen,
154
+ isHybridModeSupported
155
+ ]);
156
+ useTheme({ theme });
157
+ useDocSearchKeyboardEvents({
158
+ isOpen: isModalActive,
159
+ onOpen: openModal,
160
+ onClose: closeModal,
161
+ onAskAiToggle,
162
+ onInput,
163
+ isAskAiActive,
164
+ searchButtonRef,
165
+ keyboardShortcuts
166
+ });
167
+ const value = React.useMemo(() => ({
168
+ docsearchState,
169
+ setDocsearchState,
170
+ searchButtonRef,
171
+ initialQuery,
172
+ keyboardShortcuts,
173
+ openModal,
174
+ closeModal,
175
+ isAskAiActive,
176
+ isModalActive,
177
+ onAskAiToggle,
178
+ initialAskAiMessage,
179
+ registerView,
180
+ isHybridModeSupported
181
+ }), [
182
+ docsearchState,
183
+ searchButtonRef,
184
+ initialQuery,
185
+ keyboardShortcuts,
186
+ openModal,
187
+ closeModal,
188
+ isAskAiActive,
189
+ isModalActive,
190
+ onAskAiToggle,
191
+ initialAskAiMessage,
192
+ registerView,
193
+ isHybridModeSupported
194
+ ]);
195
+ return /* @__PURE__ */ React.createElement(Context.Provider, { value }, children);
196
+ }
197
+ const DocSearch = React.forwardRef(DocSearchInner);
198
+ DocSearch.displayName = "DocSearch";
199
+ function useDocSearch() {
200
+ const ctx = React.useContext(Context);
201
+ if (ctx === void 0) throw new Error("`useDocSearch` must be used within the `DocSearch` provider");
202
+ return ctx;
203
+ }
204
+
205
+ //#endregion
206
+ export { DEFAULT_KEYBOARD_SHORTCUTS, DocSearch, useDocSearch, useDocSearchKeyboardEvents, useKeyboardShortcuts, useTheme };
207
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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,50 +1,27 @@
1
- import React from 'react';
2
-
3
- interface DocSearchModalShortcuts {
4
- /**
5
- * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.
6
- *
7
- * @default true
8
- */
9
- 'Ctrl/Cmd+K'?: boolean;
10
- /**
11
- * Enable/disable the / shortcut to open the DocSearch modal.
12
- *
13
- * @default true
14
- */
15
- '/'?: boolean;
16
- }
17
- interface SidepanelShortcuts {
18
- /**
19
- * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.
20
- *
21
- * @default true
22
- */
23
- 'Ctrl/Cmd+I'?: boolean;
24
- }
25
- type KeyboardShortcuts = DocSearchModalShortcuts & SidepanelShortcuts;
26
-
1
+ import { KeyboardShortcuts } from "./useKeyboardShortcuts.js";
2
+ import React from "react";
3
+ //#region src/useDocSearchKeyboardEvents.d.ts
27
4
  interface UseDocSearchKeyboardEventsProps {
28
- isOpen: boolean;
29
- onOpen: () => void;
30
- onClose: () => void;
31
- /**
32
- * Deprecated: Still here for backwards compat.
33
- *
34
- * @deprecated
35
- */
36
- onInput?: (event: KeyboardEvent) => void;
37
- /**
38
- * Deprecated: Still here for backwards compat.
39
- *
40
- * @deprecated
41
- */
42
- searchButtonRef?: React.RefObject<HTMLButtonElement | null>;
43
- isAskAiActive: boolean;
44
- onAskAiToggle: (toggle: boolean) => void;
45
- keyboardShortcuts?: KeyboardShortcuts;
5
+ isOpen: boolean;
6
+ onOpen: () => void;
7
+ onClose: () => void;
8
+ /**
9
+ * Deprecated: Still here for backwards compat.
10
+ *
11
+ * @deprecated
12
+ */
13
+ onInput?: (event: KeyboardEvent) => void;
14
+ /**
15
+ * Deprecated: Still here for backwards compat.
16
+ *
17
+ * @deprecated
18
+ */
19
+ searchButtonRef?: React.RefObject<HTMLButtonElement | null>;
20
+ isAskAiActive: boolean;
21
+ onAskAiToggle: (toggle: boolean) => void;
22
+ keyboardShortcuts?: KeyboardShortcuts;
46
23
  }
47
- declare function useDocSearchKeyboardEvents({ isOpen, isAskAiActive, onAskAiToggle, onClose, onOpen, keyboardShortcuts, }: UseDocSearchKeyboardEventsProps): void;
48
-
49
- export { useDocSearchKeyboardEvents };
50
- export type { UseDocSearchKeyboardEventsProps };
24
+ declare function useDocSearchKeyboardEvents({ isOpen, isAskAiActive, onAskAiToggle, onClose, onOpen, keyboardShortcuts }: UseDocSearchKeyboardEventsProps): void;
25
+ //#endregion
26
+ export { UseDocSearchKeyboardEventsProps, useDocSearchKeyboardEvents };
27
+ //# sourceMappingURL=useDocSearchKeyboardEvents.d.ts.map
@@ -1 +1,42 @@
1
- import e from"react";var t={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function o(o){var n=o.isOpen,r=o.isAskAiActive,i=o.onAskAiToggle,a=o.onClose,c=o.onOpen,d=o.keyboardShortcuts,s=void 0===d?t:d;e.useEffect(function(){function e(e){var t;if(n&&"Escape"===e.code&&r)i(!1);else{var o=s["Ctrl/Cmd+K"]&&"k"===(null===(t=e.key)||void 0===t?void 0:t.toLowerCase())&&(e.metaKey||e.ctrlKey),d=s["/"]&&"/"===e.key;("Escape"===e.code&&n||o||!function(e){var t=e.composedPath()[0],o=t.tagName;return t.isContentEditable||"INPUT"===o||"SELECT"===o||"TEXTAREA"===o||"BUTTON"===o}(e)&&d&&!n)&&(e.preventDefault(),n?a():document.body.classList.contains("DocSearch--active")||c())}}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}},[n,r,s,c,a,i])}export{o as useDocSearchKeyboardEvents};
1
+ import { t as DEFAULT_KEYBOARD_SHORTCUTS } from "./useKeyboardShortcuts-D47pg3fZ.js";
2
+ import React from "react";
3
+
4
+ //#region src/useDocSearchKeyboardEvents.ts
5
+ function isEditingContent(event) {
6
+ const element = event.composedPath()[0];
7
+ const tagName = element.tagName;
8
+ return element.isContentEditable || tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA";
9
+ }
10
+ function useDocSearchKeyboardEvents({ isOpen, isAskAiActive, onAskAiToggle, onClose, onOpen, keyboardShortcuts = DEFAULT_KEYBOARD_SHORTCUTS }) {
11
+ React.useEffect(() => {
12
+ function onKeyDown(event) {
13
+ var _event$key;
14
+ if (isOpen && event.code === "Escape" && isAskAiActive) {
15
+ onAskAiToggle(false);
16
+ return;
17
+ }
18
+ const isCmdK = keyboardShortcuts["Ctrl/Cmd+K"] && ((_event$key = event.key) === null || _event$key === void 0 ? void 0 : _event$key.toLowerCase()) === "k" && (event.metaKey || event.ctrlKey);
19
+ const isSlash = keyboardShortcuts["/"] && event.key === "/";
20
+ if (event.code === "Escape" && isOpen || isCmdK || !isEditingContent(event) && isSlash && !isOpen) {
21
+ event.preventDefault();
22
+ if (isOpen) onClose();
23
+ else if (!document.body.classList.contains("DocSearch--active")) onOpen();
24
+ }
25
+ }
26
+ window.addEventListener("keydown", onKeyDown);
27
+ return () => {
28
+ window.removeEventListener("keydown", onKeyDown);
29
+ };
30
+ }, [
31
+ isOpen,
32
+ isAskAiActive,
33
+ keyboardShortcuts,
34
+ onOpen,
35
+ onClose,
36
+ onAskAiToggle
37
+ ]);
38
+ }
39
+
40
+ //#endregion
41
+ export { useDocSearchKeyboardEvents };
42
+ //# sourceMappingURL=useDocSearchKeyboardEvents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDocSearchKeyboardEvents.js","names":[],"sources":["../../src/useDocSearchKeyboardEvents.ts"],"sourcesContent":["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"],"mappings":";;;;AA4BA,SAAS,iBAAiB,OAA+B;CACvD,MAAM,UAAU,MAAM,aAAa,CAAC,CAAC;CACrC,MAAM,UAAU,QAAQ;CAExB,OACE,QAAQ,qBACR,YAAY,WACZ,YAAY,YACZ,YAAY;AAEhB;AAEA,SAAgB,2BAA2B,EACzC,QACA,eACA,eACA,SACA,QACA,oBAAoB,8BACoB;CACxC,MAAM,gBAAgB;EACpB,SAAS,UAAU,OAA4B;;GAC7C,IAAI,UAAU,MAAM,SAAS,YAAY,eAAe;IACtD,cAAc,KAAK;IACnB;GACF;GAEA,MAAM,SACJ,kBAAkB,gCAClB,MAAM,6DAAK,YAAY,OAAM,QAC5B,MAAM,WAAW,MAAM;GAC1B,MAAM,UAAU,kBAAkB,QAAQ,MAAM,QAAQ;GAExD,IACG,MAAM,SAAS,YAAY,UAC5B,UACC,CAAC,iBAAiB,KAAK,KAAK,WAAW,CAAC,QACzC;IACA,MAAM,eAAe;IAErB,IAAI,QACF,QAAQ;SACH,IAAI,CAAC,SAAS,KAAK,UAAU,SAAS,mBAAmB,GAC9D,OAAO;GAEX;EACF;EAEA,OAAO,iBAAiB,WAAW,SAAS;EAE5C,aAAmB;GACjB,OAAO,oBAAoB,WAAW,SAAS;EACjD;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH"}
@@ -0,0 +1,90 @@
1
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/typeof.js
2
+ function _typeof(o) {
3
+ "@babel/helpers - typeof";
4
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
5
+ return typeof o;
6
+ } : function(o) {
7
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
8
+ }, _typeof(o);
9
+ }
10
+
11
+ //#endregion
12
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPrimitive.js
13
+ function toPrimitive(t, r) {
14
+ if ("object" != _typeof(t) || !t) return t;
15
+ var e = t[Symbol.toPrimitive];
16
+ if (void 0 !== e) {
17
+ var i = e.call(t, r || "default");
18
+ if ("object" != _typeof(i)) return i;
19
+ throw new TypeError("@@toPrimitive must return a primitive value.");
20
+ }
21
+ return ("string" === r ? String : Number)(t);
22
+ }
23
+
24
+ //#endregion
25
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPropertyKey.js
26
+ function toPropertyKey(t) {
27
+ var i = toPrimitive(t, "string");
28
+ return "symbol" == _typeof(i) ? i : i + "";
29
+ }
30
+
31
+ //#endregion
32
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/defineProperty.js
33
+ function _defineProperty(e, r, t) {
34
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
35
+ value: t,
36
+ enumerable: !0,
37
+ configurable: !0,
38
+ writable: !0
39
+ }) : e[r] = t, e;
40
+ }
41
+
42
+ //#endregion
43
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectSpread2.js
44
+ function ownKeys(e, r) {
45
+ var t = Object.keys(e);
46
+ if (Object.getOwnPropertySymbols) {
47
+ var o = Object.getOwnPropertySymbols(e);
48
+ r && (o = o.filter(function(r) {
49
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
50
+ })), t.push.apply(t, o);
51
+ }
52
+ return t;
53
+ }
54
+ function _objectSpread2(e) {
55
+ for (var r = 1; r < arguments.length; r++) {
56
+ var t = null != arguments[r] ? arguments[r] : {};
57
+ r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
58
+ _defineProperty(e, r, t[r]);
59
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
60
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
61
+ });
62
+ }
63
+ return e;
64
+ }
65
+
66
+ //#endregion
67
+ //#region src/useKeyboardShortcuts.ts
68
+ /**
69
+ * Default keyboard shortcuts configuration for DocSearch. These values are used
70
+ * when no keyboardShortcuts prop is provided or when specific shortcuts are not
71
+ * configured.
72
+ */
73
+ const DEFAULT_KEYBOARD_SHORTCUTS = {
74
+ "Ctrl/Cmd+K": true,
75
+ "/": true,
76
+ "Ctrl/Cmd+I": true
77
+ };
78
+ /**
79
+ * Merges user-provided keyboard shortcuts with defaults.
80
+ *
81
+ * @param userShortcuts - Optional user configuration.
82
+ * @returns Complete keyboard shortcuts configuration with defaults applied.
83
+ */
84
+ function useKeyboardShortcuts(userShortcuts) {
85
+ return _objectSpread2(_objectSpread2({}, DEFAULT_KEYBOARD_SHORTCUTS), userShortcuts);
86
+ }
87
+
88
+ //#endregion
89
+ export { useKeyboardShortcuts as n, DEFAULT_KEYBOARD_SHORTCUTS as t };
90
+ //# sourceMappingURL=useKeyboardShortcuts-D47pg3fZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeyboardShortcuts-D47pg3fZ.js","names":[],"sources":["../../src/useKeyboardShortcuts.ts"],"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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,6BAA0D;CACrE,cAAc;CACd,KAAK;CACL,cAAc;AAChB;;;;;;;AAQA,SAAgB,qBACd,eAC6B;CAC7B,yCACK,6BACA,aACL;AACF"}
@@ -1,30 +1,31 @@
1
+ //#region src/useKeyboardShortcuts.d.ts
1
2
  interface DocSearchModalShortcuts {
2
- /**
3
- * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.
4
- *
5
- * @default true
6
- */
7
- 'Ctrl/Cmd+K'?: boolean;
8
- /**
9
- * Enable/disable the / shortcut to open the DocSearch modal.
10
- *
11
- * @default true
12
- */
13
- '/'?: boolean;
3
+ /**
4
+ * Enable/disable the Ctrl/Cmd+K shortcut to toggle the DocSearch modal.
5
+ *
6
+ * @default true
7
+ */
8
+ 'Ctrl/Cmd+K'?: boolean;
9
+ /**
10
+ * Enable/disable the / shortcut to open the DocSearch modal.
11
+ *
12
+ * @default true
13
+ */
14
+ '/'?: boolean;
14
15
  }
15
16
  interface SidepanelShortcuts {
16
- /**
17
- * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.
18
- *
19
- * @default true
20
- */
21
- 'Ctrl/Cmd+I'?: boolean;
17
+ /**
18
+ * Enable/disable the Ctrl/Cmd+I shortcut to toggle the DocSearch sidepanel.
19
+ *
20
+ * @default true
21
+ */
22
+ 'Ctrl/Cmd+I'?: boolean;
22
23
  }
23
24
  type KeyboardShortcuts = DocSearchModalShortcuts & SidepanelShortcuts;
24
25
  /**
25
- * Default keyboard shortcuts configuration for DocSearch.
26
- * These values are used when no keyboardShortcuts prop is provided
27
- * or when specific shortcuts are not configured.
26
+ * Default keyboard shortcuts configuration for DocSearch. These values are used
27
+ * when no keyboardShortcuts prop is provided or when specific shortcuts are not
28
+ * configured.
28
29
  */
29
30
  declare const DEFAULT_KEYBOARD_SHORTCUTS: Required<KeyboardShortcuts>;
30
31
  /**
@@ -34,6 +35,6 @@ declare const DEFAULT_KEYBOARD_SHORTCUTS: Required<KeyboardShortcuts>;
34
35
  * @returns Complete keyboard shortcuts configuration with defaults applied.
35
36
  */
36
37
  declare function useKeyboardShortcuts(userShortcuts?: KeyboardShortcuts): Required<KeyboardShortcuts>;
37
-
38
- export { DEFAULT_KEYBOARD_SHORTCUTS, useKeyboardShortcuts };
39
- export type { DocSearchModalShortcuts, KeyboardShortcuts, SidepanelShortcuts };
38
+ //#endregion
39
+ export { DEFAULT_KEYBOARD_SHORTCUTS, DocSearchModalShortcuts, KeyboardShortcuts, SidepanelShortcuts, useKeyboardShortcuts };
40
+ //# sourceMappingURL=useKeyboardShortcuts.d.ts.map
@@ -1 +1,3 @@
1
- function r(r,e,t){return(e=function(r){var e=function(r,e){if("object"!=typeof r||!r)return r;var t=r[Symbol.toPrimitive];if(void 0!==t){var n=t.call(r,e);if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(r)}(r,"string");return"symbol"==typeof e?e:e+""}(e))in r?Object.defineProperty(r,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):r[e]=t,r}function e(r,e){var t=Object.keys(r);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(r);e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(r,e).enumerable})),t.push.apply(t,n)}return t}function t(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach(function(e){r(t,e,o[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach(function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(o,r))})}return t}var n={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function o(r){return t(t({},n),r)}export{n as DEFAULT_KEYBOARD_SHORTCUTS,o as useKeyboardShortcuts};
1
+ import { n as useKeyboardShortcuts, t as DEFAULT_KEYBOARD_SHORTCUTS } from "./useKeyboardShortcuts-D47pg3fZ.js";
2
+
3
+ export { DEFAULT_KEYBOARD_SHORTCUTS, useKeyboardShortcuts };
@@ -1,8 +1,9 @@
1
+ //#region src/useTheme.d.ts
1
2
  type DocSearchTheme = 'dark' | 'light';
2
3
  interface UseThemeProps {
3
- theme?: DocSearchTheme;
4
+ theme?: DocSearchTheme;
4
5
  }
5
6
  declare const useTheme: ({ theme }: UseThemeProps) => void;
6
-
7
- export { useTheme };
8
- export type { DocSearchTheme, UseThemeProps };
7
+ //#endregion
8
+ export { DocSearchTheme, UseThemeProps, useTheme };
9
+ //# sourceMappingURL=useTheme.d.ts.map
@@ -1 +1,19 @@
1
- import{useEffect as e}from"react";var t=function(t){var m=t.theme;e(function(){if(m){var e=document.documentElement.dataset.theme;if(m!==e)return document.documentElement.dataset.theme=m,function(){void 0===e?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=e}}},[m])};export{t as useTheme};
1
+ import { useEffect } from "react";
2
+
3
+ //#region src/useTheme.ts
4
+ const useTheme = ({ theme }) => {
5
+ useEffect(() => {
6
+ if (!theme) return;
7
+ const previousTheme = document.documentElement.dataset.theme;
8
+ if (theme === previousTheme) return;
9
+ document.documentElement.dataset.theme = theme;
10
+ return () => {
11
+ if (previousTheme === void 0) delete document.documentElement.dataset.theme;
12
+ else document.documentElement.dataset.theme = previousTheme;
13
+ };
14
+ }, [theme]);
15
+ };
16
+
17
+ //#endregion
18
+ export { useTheme };
19
+ //# sourceMappingURL=useTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTheme.js","names":[],"sources":["../../src/useTheme.ts"],"sourcesContent":["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"],"mappings":";;;AAQA,MAAa,YAAY,EAAE,YAAiC;CAC1D,gBAAgB;EACd,IAAI,CAAC,OACH;EAGF,MAAM,gBAAgB,SAAS,gBAAgB,QAAQ;EAEvD,IAAI,UAAU,eACZ;EAGF,SAAS,gBAAgB,QAAQ,QAAQ;EAEzC,aAAmB;GACjB,IAAI,kBAAkB,QACpB,OAAO,SAAS,gBAAgB,QAAQ;QAExC,SAAS,gBAAgB,QAAQ,QAAQ;EAE7C;CACF,GAAG,CAAC,KAAK,CAAC;AACZ"}
package/dist/umd/index.js CHANGED
@@ -1,3 +1,3 @@
1
- /*! @docsearch/core 4.7.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DocSearchCore={},e.React)}(this,function(e,t){"use strict";function n(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function r(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t);if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(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 a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach(function(t){r(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,u=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,0===t);else for(;!(c=(r=a.call(n)).done)&&(u.push(r.value),u.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(l)throw o}}return u}}(e,t)||function(e,t){if(e){if("string"==typeof e)return n(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var u={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};function c(e){return a(a({},u),e)}function l(e){var n=e.isOpen,r=e.isAskAiActive,o=e.onAskAiToggle,a=e.onClose,i=e.onOpen,c=e.keyboardShortcuts,l=void 0===c?u:c;t.useEffect(function(){function e(e){var t;if(n&&"Escape"===e.code&&r)o(!1);else{var u=l["Ctrl/Cmd+K"]&&"k"===(null===(t=e.key)||void 0===t?void 0:t.toLowerCase())&&(e.metaKey||e.ctrlKey),c=l["/"]&&"/"===e.key;("Escape"===e.code&&n||u||!function(e){var t=e.composedPath()[0],n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n||"BUTTON"===n}(e)&&c&&!n)&&(e.preventDefault(),n?a():document.body.classList.contains("DocSearch--active")||i())}}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}},[n,r,l,i,a,o])}var s=function(e){var n=e.theme;t.useEffect(function(){if(n){var e=document.documentElement.dataset.theme;if(n!==e)return document.documentElement.dataset.theme=n,function(){void 0===e?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=e}}},[n])},d=["children","theme","onReady","onOpen","onClose","onSidepanelOpen","onSidepanelClose"],f=t.createContext(void 0);f.displayName="DocSearchContext";var p=t.forwardRef(function(e,n){var r=e.children,o=e.theme,a=e.onReady,u=e.onOpen,p=e.onClose,m=e.onSidepanelOpen,v=e.onSidepanelClose,y=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(-1!==t.indexOf(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],-1===t.indexOf(n)&&{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,d),h=i(t.useState("ready"),2),b=h[0],S=h[1],O=i(t.useState(y.initialQuery||""),2),g=O[0],w=O[1],k=t.useRef(null),A=c(y.keyboardShortcuts),E=i(t.useState(),2),C=E[0],j=E[1],D=i(t.useState(function(){return new Set}),2),P=D[0],T=D[1],x=function(){var e=i(t.useState(!1),2),n=e[0],r=e[1];return t.useEffect(function(){var e=function(){var e=window.matchMedia("(max-width: 768px)");r(e.matches)};return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}},[]),n}(),R=t.useRef("ready"),M=["modal-search","modal-askai"].includes(b),I="modal-askai"===b,L=!x&&P.has("sidepanel"),K="sidepanel"===b;t.useEffect(function(){null==a||a()},[a]),t.useEffect(function(){var e=R.current,t=b;"modal-search"!==t&&"modal-askai"!==t||"modal-search"===e||"modal-askai"===e||null==u||u(),"ready"!==t||"modal-search"!==e&&"modal-askai"!==e||null==p||p(),"sidepanel"===t&&"sidepanel"!==e&&(null==m||m()),"sidepanel"!==t&&"sidepanel"===e&&(null==v||v()),R.current=t},[b,u,p,m,v]);var N=t.useCallback(function(){S("modal-search")},[]),U=t.useCallback(function(){var e,t;S("ready"),null===(e=k.current)||void 0===e||e.focus(),w(null!==(t=y.initialQuery)&&void 0!==t?t:"")},[S,y.initialQuery]),Q=t.useCallback(function(e,t){if(!x&&e&&L)return j(t),void S("sidepanel");S(e?"modal-askai":"modal-search")},[S,x,L]),B=t.useCallback(function(e){P.has("sidepanel")&&(j(e),S("sidepanel"))},[S,P]);t.useCallback(function(e){S("modal-search"),w(e.key)},[S,w]);var H=t.useCallback(function(){j(void 0)},[]),z=t.useCallback(function(e){P.has(e)||T(function(t){var n=new Set(t);return n.add(e),n})},[P]);t.useImperativeHandle(n,function(){return{open:N,close:U,openAskAi:function(e){return Q(!0,e)},openSidepanel:B,get isReady(){return!0},get isOpen(){return M},get isSidepanelOpen(){return K},get isSidepanelSupported(){return L}}},[N,U,Q,B,M,K,L]),s({theme:o}),l({isOpen:M,onOpen:N,onClose:U,onAskAiToggle:Q,isAskAiActive:I,keyboardShortcuts:A});var _=t.useMemo(function(){return{docsearchState:b,setDocsearchState:S,searchButtonRef:k,initialQuery:g,keyboardShortcuts:A,openModal:N,closeModal:U,isAskAiActive:I,isModalActive:M,onAskAiToggle:Q,initialAskAiMessage:C,clearInitialAskAiMessage:H,registerView:z,isHybridModeSupported:L}},[b,k,g,A,N,U,I,M,Q,C,H,z,L]);return t.createElement(f.Provider,{value:_},r)});p.displayName="DocSearch",e.DEFAULT_KEYBOARD_SHORTCUTS=u,e.DocSearch=p,e.useDocSearch=function(){var e=t.useContext(f);if(void 0===e)throw new Error("`useDocSearch` must be used within the `DocSearch` provider");return e},e.useDocSearchKeyboardEvents=l,e.useKeyboardShortcuts=c,e.useTheme=s});
3
- //# sourceMappingURL=index.js.map
1
+ /*! @docsearch/core 5.0.0-beta.1 (UNRELEASED cc75f9a) | 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`,`theme`,`onReady`,`onOpen`,`onClose`,`onSidepanelOpen`,`onSidepanelClose`],w=t.default.createContext(void 0);w.displayName=`DocSearchContext`;function T(e,n){let{children:r,theme:i,onReady:a,onOpen:o,onClose:s,onSidepanelOpen:c,onSidepanelClose:l}=e,u=S(e,C),[d,f]=t.default.useState(`ready`),[p,m]=t.default.useState(u.initialQuery||``),h=t.default.useRef(null),_=g(u.keyboardShortcuts),[x,T]=t.default.useState(),[E,D]=t.default.useState(()=>new Set),O=y(),k=t.default.useRef(`ready`),A=[`modal-search`,`modal-askai`].includes(d),j=d===`modal-askai`,M=!O&&E.has(`sidepanel`),N=d===`sidepanel`;t.default.useEffect(()=>{a==null||a()},[a]),t.default.useEffect(()=>{let e=k.current,t=d;(t===`modal-search`||t===`modal-askai`)&&e!==`modal-search`&&e!==`modal-askai`&&(o==null||o()),t===`ready`&&(e===`modal-search`||e===`modal-askai`)&&(s==null||s()),t===`sidepanel`&&e!==`sidepanel`&&(c==null||c()),t!==`sidepanel`&&e===`sidepanel`&&(l==null||l()),k.current=t},[d,o,s,c,l]);let P=t.default.useCallback(()=>{f(`modal-search`)},[]),F=t.default.useCallback(()=>{var e,t;f(`ready`),(e=h.current)==null||e.focus(),m((t=u.initialQuery)==null?``:t)},[f,u.initialQuery]),I=t.default.useCallback((e,t)=>{if(!O&&e&&M){T(t),f(`sidepanel`);return}f(e?`modal-askai`:`modal-search`)},[f,O,M]),L=t.default.useCallback(e=>{E.has(`sidepanel`)&&(T(e),f(`sidepanel`))},[f,E]),R=t.default.useCallback(e=>{f(`modal-search`),m(e.key)},[f,m]),z=t.default.useCallback(e=>{E.has(e)||D(t=>{let n=new Set(t);return n.add(e),n})},[E]);t.default.useImperativeHandle(n,()=>({open:P,close:F,openAskAi:e=>I(!0,e),openSidepanel:L,get isReady(){return!0},get isOpen(){return A},get isSidepanelOpen(){return N},get isSidepanelSupported(){return M}}),[P,F,I,L,A,N,M]),b({theme:i}),v({isOpen:A,onOpen:P,onClose:F,onAskAiToggle:I,onInput:R,isAskAiActive:j,searchButtonRef:h,keyboardShortcuts:_});let B=t.default.useMemo(()=>({docsearchState:d,setDocsearchState:f,searchButtonRef:h,initialQuery:p,keyboardShortcuts:_,openModal:P,closeModal:F,isAskAiActive:j,isModalActive:A,onAskAiToggle:I,initialAskAiMessage:x,registerView:z,isHybridModeSupported:M}),[d,h,p,_,P,F,j,A,I,x,z,M]);return t.default.createElement(w.Provider,{value:B},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
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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.\n * These values are used when no keyboardShortcuts prop is provided\n * or when specific shortcuts are not 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(userShortcuts?: KeyboardShortcuts): Required<KeyboardShortcuts> {\n return {\n ...DEFAULT_KEYBOARD_SHORTCUTS,\n ...userShortcuts,\n };\n}\n","import React from 'react';\n\nimport { DEFAULT_KEYBOARD_SHORTCUTS, type KeyboardShortcuts } 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 tagName === 'BUTTON'\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'] && event.key?.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey);\n const isSlash = keyboardShortcuts['/'] && event.key === '/';\n\n if ((event.code === 'Escape' && isOpen) || isCmdK || (!isEditingContent(event) && isSlash && !isOpen)) {\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 }, [isOpen, isAskAiActive, keyboardShortcuts, onOpen, onClose, onAskAiToggle]);\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 = 'modal-askai' | 'modal-search' | 'ready' | '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 = (active: boolean, initialMessage?: InitialAskAiMessage) => void;\n\n/**\n * Imperative handle exposed by the DocSearch provider for programmatic control.\n */\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 clearInitialAskAiMessage: () => void;\n registerView: (view: View) => void;\n isHybridModeSupported: boolean;\n}\n\n/**\n * Lifecycle callbacks for DocSearch.\n */\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 { children, theme, onReady, onOpen, onClose, onSidepanelOpen, onSidepanelClose, ...props }: DocSearchProps,\n ref: React.ForwardedRef<DocSearchRef>,\n): JSX.Element {\n const [docsearchState, setDocsearchState] = React.useState<DocSearchState>('ready');\n const [initialQuery, setInitialQuery] = React.useState<string>(props.initialQuery || '');\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const keyboardShortcuts = useKeyboardShortcuts(props.keyboardShortcuts);\n const [initialAskAiMessage, setInitialAskAiMessage] = React.useState<InitialAskAiMessage>();\n const [registeredViews, setRegisteredViews] = React.useState(() => new Set<View>());\n const isMobile = useIsMobile();\n const prevStateRef = React.useRef<DocSearchState>('ready');\n\n const isModalActive = ['modal-search', 'modal-askai'].includes(docsearchState);\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 (currentState === 'ready' && (prevState === 'modal-search' || prevState === 'modal-askai')) {\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 clearInitialAskAiMessage = React.useCallback((): void => {\n setInitialAskAiMessage(undefined);\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 => 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 [openModal, closeModal, onAskAiToggle, openSidepanel, isModalActive, isSidepanelOpen, isHybridModeSupported],\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 clearInitialAskAiMessage,\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 clearInitialAskAiMessage,\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('`useDocSearch` must be used within the `DocSearch` provider');\n }\n\n return ctx;\n}\n"],"names":["DEFAULT_KEYBOARD_SHORTCUTS","useKeyboardShortcuts","userShortcuts","_objectSpread","useDocSearchKeyboardEvents","_ref","isOpen","isAskAiActive","onAskAiToggle","onClose","onOpen","_ref$keyboardShortcut","keyboardShortcuts","React","useEffect","onKeyDown","event","_event$key","code","isCmdK","key","toLowerCase","metaKey","ctrlKey","isSlash","element","composedPath","tagName","isContentEditable","isEditingContent","preventDefault","document","body","classList","contains","window","addEventListener","removeEventListener","useTheme","theme","previousTheme","documentElement","dataset","undefined","Context","createContext","displayName","DocSearch","forwardRef","ref","children","onReady","onSidepanelOpen","onSidepanelClose","props","_objectWithoutProperties","_excluded","_React$useState2","_slicedToArray","useState","docsearchState","setDocsearchState","_React$useState4","initialQuery","setInitialQuery","searchButtonRef","useRef","_React$useState6","initialAskAiMessage","setInitialAskAiMessage","_React$useState8","Set","registeredViews","setRegisteredViews","isMobile","setIsMobile","checkForMobile","isMobileMediaQuery","matchMedia","matches","useIsMobile","prevStateRef","isModalActive","includes","isHybridModeSupported","has","isSidepanelOpen","prevState","current","currentState","openModal","useCallback","closeModal","_searchButtonRef$curr","_props$initialQuery","focus","active","initialMessage","openSidepanel","clearInitialAskAiMessage","registerView","view","prev","newViews","add","useImperativeHandle","open","close","openAskAi","isReady","isSidepanelSupported","value","useMemo","createElement","Provider","ctx","useContext","Error"],"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 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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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@docsearch/core",
3
3
  "description": "Core package logic for DocSearch",
4
- "version": "4.7.0",
4
+ "version": "5.0.0-beta.1",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "homepage": "https://docsearch.algolia.com",
@@ -16,42 +16,32 @@
16
16
  },
17
17
  "sideEffects": false,
18
18
  "files": [
19
- "dist/",
20
- "index.js",
21
- "useTheme.js",
22
- "useDocSearchKeyboardEvents.js",
23
- "useKeyboardShortcuts.js"
19
+ "dist/"
24
20
  ],
25
21
  "exports": {
26
22
  ".": "./dist/esm/index.js",
27
- "./useTheme": "./dist/esm/useTheme.js",
28
23
  "./useDocSearchKeyboardEvents": "./dist/esm/useDocSearchKeyboardEvents.js",
29
- "./useKeyboardShortcuts": "./dist/esm/useKeyboardShortcuts.js"
24
+ "./useKeyboardShortcuts": "./dist/esm/useKeyboardShortcuts.js",
25
+ "./useTheme": "./dist/esm/useTheme.js"
30
26
  },
31
27
  "source": "src/index.ts",
32
- "types": "dist/esm/index.d.ts",
33
- "module": "dist/esm/index.js",
34
- "main": "dist/umd/index.js",
28
+ "types": "./dist/esm/index.d.ts",
29
+ "main": "./dist/esm/index.js",
30
+ "module": "./dist/esm/index.js",
35
31
  "umd:main": "dist/umd/index.js",
36
32
  "unpkg": "dist/umd/index.js",
37
33
  "jsdelivr": "dist/umd/index.js",
38
34
  "scripts": {
39
- "build:clean": "rm -rf ./dist",
40
- "build:clean-types": "rm -rf ./dist/esm/types",
41
- "build:types": "tsc -p ./tsconfig.declaration.json --outDir ./dist/esm/types",
42
- "build:source": "rollup --config --bundleConfigAsCjs",
43
- "build:dts": "rollup --config rollup.dts.config.js --bundleConfigAsCjs",
44
- "build": "yarn build:clean && yarn build:types && yarn build:source && yarn build:dts && yarn build:clean-types",
45
- "on:change": "yarn build",
46
- "watch": "nodemon --watch src --ext ts,tsx,js,jsx,json --ignore dist/ --ignore node_modules/ --verbose --delay 250ms --exec \"yarn on:change\""
35
+ "build": "tsdown",
36
+ "watch": "tsdown --watch"
47
37
  },
48
38
  "devDependencies": {
49
- "@rollup/plugin-replace": "6.0.2",
50
39
  "@testing-library/jest-dom": "6.6.3",
51
40
  "@testing-library/react": "16.2.0",
52
- "nodemon": "^3.1.0",
53
- "rollup-plugin-dts": "^6.2.1",
54
- "vitest": "3.0.9"
41
+ "preact": "11.0.0-beta.0",
42
+ "tsdown": "0.22.7",
43
+ "typescript": "5.7.3",
44
+ "vitest": "3.0.2"
55
45
  },
56
46
  "peerDependencies": {
57
47
  "@types/react": ">= 16.8.0 < 20.0.0",
@@ -1,3 +0,0 @@
1
- /*! @docsearch/core 4.7.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DocSearchCore={},e.React)}(this,function(e,t){"use strict";var o={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};e.useDocSearchKeyboardEvents=function(e){var n=e.isOpen,i=e.isAskAiActive,r=e.onAskAiToggle,c=e.onClose,s=e.onOpen,a=e.keyboardShortcuts,d=void 0===a?o:a;t.useEffect(function(){function e(e){var t;if(n&&"Escape"===e.code&&i)r(!1);else{var o=d["Ctrl/Cmd+K"]&&"k"===(null===(t=e.key)||void 0===t?void 0:t.toLowerCase())&&(e.metaKey||e.ctrlKey),a=d["/"]&&"/"===e.key;("Escape"===e.code&&n||o||!function(e){var t=e.composedPath()[0],o=t.tagName;return t.isContentEditable||"INPUT"===o||"SELECT"===o||"TEXTAREA"===o||"BUTTON"===o}(e)&&a&&!n)&&(e.preventDefault(),n?c():document.body.classList.contains("DocSearch--active")||s())}}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}},[n,i,d,s,c,r])}});
3
- //# sourceMappingURL=useDocSearchKeyboardEvents.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDocSearchKeyboardEvents.js","sources":["../../src/useKeyboardShortcuts.ts","../../src/useDocSearchKeyboardEvents.ts"],"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.\n * These values are used when no keyboardShortcuts prop is provided\n * or when specific shortcuts are not 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(userShortcuts?: KeyboardShortcuts): Required<KeyboardShortcuts> {\n return {\n ...DEFAULT_KEYBOARD_SHORTCUTS,\n ...userShortcuts,\n };\n}\n","import React from 'react';\n\nimport { DEFAULT_KEYBOARD_SHORTCUTS, type KeyboardShortcuts } 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 tagName === 'BUTTON'\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'] && event.key?.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey);\n const isSlash = keyboardShortcuts['/'] && event.key === '/';\n\n if ((event.code === 'Escape' && isOpen) || isCmdK || (!isEditingContent(event) && isSlash && !isOpen)) {\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 }, [isOpen, isAskAiActive, keyboardShortcuts, onOpen, onClose, onAskAiToggle]);\n}\n"],"names":["DEFAULT_KEYBOARD_SHORTCUTS","_ref","isOpen","isAskAiActive","onAskAiToggle","onClose","onOpen","_ref$keyboardShortcut","keyboardShortcuts","React","useEffect","onKeyDown","event","_event$key","code","isCmdK","key","toLowerCase","metaKey","ctrlKey","isSlash","element","composedPath","tagName","isContentEditable","isEditingContent","preventDefault","document","body","classList","contains","window","addEventListener","removeEventListener"],"mappings":";uRA+BO,IAAMA,EAA0D,CACrE,cAAc,EACd,KAAK,EACL,cAAc,gCCIT,SAAmCC,GAOA,IANxCC,EAAMD,EAANC,OACAC,EAAaF,EAAbE,cACAC,EAAaH,EAAbG,cACAC,EAAOJ,EAAPI,QACAC,EAAML,EAANK,OAAMC,EAAAN,EACNO,kBAAAA,OAAiB,IAAAD,EAAGP,EAA0BO,EAE9CE,EAAMC,UAAU,WACd,SAASC,EAAUC,GAA4B,IAAAC,EAC7C,GAAIX,GAAyB,WAAfU,EAAME,MAAqBX,EACvCC,GAAc,OADhB,CAKA,IAAMW,EACJP,EAAkB,eAA8C,OAApB,QAATK,EAAAD,EAAMI,WAAG,IAAAH,OAAA,EAATA,EAAWI,iBAA0BL,EAAMM,SAAWN,EAAMO,SAC3FC,EAAUZ,EAAkB,MAAsB,MAAdI,EAAMI,KAE5B,WAAfJ,EAAME,MAAqBZ,GAAWa,IAhCjD,SAA0BH,GACxB,IAAMS,EAAUT,EAAMU,eAAe,GAC/BC,EAAUF,EAAQE,QAExB,OACEF,EAAQG,mBACI,UAAZD,GACY,WAAZA,GACY,aAAZA,GACY,WAAZA,CAEJ,CAqB6DE,CAAiBb,IAAUQ,IAAYlB,KAC5FU,EAAMc,iBAEFxB,EACFG,IACUsB,SAASC,KAAKC,UAAUC,SAAS,sBAC3CxB,IAZJ,CAeF,CAIA,OAFAyB,OAAOC,iBAAiB,UAAWrB,GAE5B,WACLoB,OAAOE,oBAAoB,UAAWtB,EACxC,CACF,EAAG,CAACT,EAAQC,EAAeK,EAAmBF,EAAQD,EAASD,GACjE"}
@@ -1,3 +0,0 @@
1
- /*! @docsearch/core 4.7.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DocSearchCore={})}(this,function(e){"use strict";function t(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t);if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function r(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function n(e){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?r(Object(o),!0).forEach(function(r){t(e,r,o[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):r(Object(o)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))})}return e}var o={"Ctrl/Cmd+K":!0,"/":!0,"Ctrl/Cmd+I":!0};e.DEFAULT_KEYBOARD_SHORTCUTS=o,e.useKeyboardShortcuts=function(e){return n(n({},o),e)}});
3
- //# sourceMappingURL=useKeyboardShortcuts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useKeyboardShortcuts.js","sources":["../../src/useKeyboardShortcuts.ts"],"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.\n * These values are used when no keyboardShortcuts prop is provided\n * or when specific shortcuts are not 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(userShortcuts?: KeyboardShortcuts): Required<KeyboardShortcuts> {\n return {\n ...DEFAULT_KEYBOARD_SHORTCUTS,\n ...userShortcuts,\n };\n}\n"],"names":["DEFAULT_KEYBOARD_SHORTCUTS","userShortcuts","_objectSpread"],"mappings":";+tCA+BO,IAAMA,EAA0D,CACrE,cAAc,EACd,KAAK,EACL,cAAc,yDAST,SAA8BC,GACnC,OAAAC,EAAAA,EAAA,CAAA,EACKF,GACAC,EAEP"}
@@ -1,3 +0,0 @@
1
- /*! @docsearch/core 4.7.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */
2
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DocSearchCore={},e.React)}(this,function(e,t){"use strict";e.useTheme=function(e){var n=e.theme;t.useEffect(function(){if(n){var e=document.documentElement.dataset.theme;if(n!==e)return document.documentElement.dataset.theme=n,function(){void 0===e?delete document.documentElement.dataset.theme:document.documentElement.dataset.theme=e}}},[n])}});
3
- //# sourceMappingURL=useTheme.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTheme.js","sources":["../../src/useTheme.ts"],"sourcesContent":["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"],"names":["_ref","theme","useEffect","previousTheme","document","documentElement","dataset","undefined"],"mappings":";kSAQwB,SAAHA,GAAuC,IAAjCC,EAAKD,EAALC,MACzBC,EAAAA,UAAU,WACR,GAAKD,EAAL,CAIA,IAAME,EAAgBC,SAASC,gBAAgBC,QAAQL,MAEvD,GAAIA,IAAUE,EAMd,OAFAC,SAASC,gBAAgBC,QAAQL,MAAQA,EAElC,gBACiBM,IAAlBJ,SACKC,SAASC,gBAAgBC,QAAQL,MAExCG,SAASC,gBAAgBC,QAAQL,MAAQE,CAE7C,CAhBA,CAiBF,EAAG,CAACF,GACN"}
package/index.js DELETED
@@ -1 +0,0 @@
1
- export { DocSearch, useDocSearch } from './dist/esm/index.js';
@@ -1 +0,0 @@
1
- export * from './dist/esm/useDocSearchKeyboardEvents.js';
File without changes
package/useTheme.js DELETED
@@ -1 +0,0 @@
1
- export * from './dist/esm/useTheme.js';