spotlight-omni-search 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +391 -0
- package/dist/Spotlight.d.ts +2 -0
- package/dist/actions/commonActions.d.ts +31 -0
- package/dist/adapters/routes.d.ts +23 -0
- package/dist/adapters/useReactRouterItems.d.ts +37 -0
- package/dist/hooks/useRecentItems.d.ts +36 -0
- package/dist/hooks/useSpotlight.d.ts +47 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +3035 -0
- package/dist/index.umd.js +6 -0
- package/dist/lib/fuzzySearch.d.ts +26 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/spotlight-omni-search.css +1 -0
- package/dist/types.d.ts +60 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# spotlight-omni-search 🔍 (v1.0.0)
|
|
2
|
+
|
|
3
|
+
A professional, **Tailwind-Native** Spotlight Search component for React and Next.js. Engineered to blend perfectly into your existing design system without shipping any global CSS resets or side effects.
|
|
4
|
+
|
|
5
|
+
## 🆕 What's New in v1.0.0
|
|
6
|
+
|
|
7
|
+
- **🎯 Fuzzy Search**: Intelligent VS Code-style character matching with relevance scoring
|
|
8
|
+
- **📜 Recent Items**: Automatic tracking and display of recently selected items
|
|
9
|
+
- **⚡ Built-in Actions**: Pre-built actions for theme toggle, navigation, utilities
|
|
10
|
+
- **🔌 Enhanced Router Integration**: Better Next.js and React Router support
|
|
11
|
+
- **⏳ Loading States**: Built-in skeleton loader for async data
|
|
12
|
+
- **⌨️ Keyboard Shortcuts**: Display shortcut hints on items
|
|
13
|
+
- **🎨 Custom Rendering**: Optional custom render function support
|
|
14
|
+
- **🪝 useSpotlight Hook**: Simplified state management with built-in Cmd+K support
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🏛 Architecture
|
|
19
|
+
|
|
20
|
+
This package is "Tailwind-Native". Instead of shipping a giant, compiled CSS file with internal resets, this library uses standard Tailwind classes that are compiled by **YOUR** application's Tailwind build.
|
|
21
|
+
|
|
22
|
+
### Key Benefits:
|
|
23
|
+
|
|
24
|
+
- **Zero Style Leaks**: No bundled resets. Your `body`, `button`, and `h1` styles remain yours.
|
|
25
|
+
- **Microscopic Bundle Size**: Only ships the logic. Your Tailwind build handles the styles.
|
|
26
|
+
- **Perfect Design Parity**: Inherits your fonts, colors, and layout rules natively.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 📦 Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install spotlight-omni-search
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 🛠 Integration (Required)
|
|
37
|
+
|
|
38
|
+
Because v3 uses standard Tailwind classes, you **must** tell Tailwind to scan the library for styles.
|
|
39
|
+
|
|
40
|
+
### 1. Update `tailwind.config.js`
|
|
41
|
+
|
|
42
|
+
Add the library path to your `content` array:
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
/** @type {import('tailwindcss').Config} */
|
|
46
|
+
export default {
|
|
47
|
+
content: [
|
|
48
|
+
"./index.html",
|
|
49
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
50
|
+
"./node_modules/spotlight-omni-search/**/*.{js,ts,jsx,tsx}", // <--- ADD THIS
|
|
51
|
+
],
|
|
52
|
+
// ...
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. (Optional) Import Default Variables
|
|
57
|
+
|
|
58
|
+
If you want to use our default colors, import the minimal variable sheet in your `layout.tsx` or `index.css`:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import "spotlight-omni-search/dist/style.css";
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 🌓 Customization
|
|
67
|
+
|
|
68
|
+
Since we use standard Tailwind, you can customize the theme using CSS variables in your global CSS:
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
:root {
|
|
72
|
+
--spotlight-primary: #3b82f6;
|
|
73
|
+
--spotlight-background: #ffffff;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.dark {
|
|
77
|
+
--spotlight-background: #0f172a;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ✨ Features
|
|
84
|
+
|
|
85
|
+
- **🎯 Fuzzy Search**: Intelligent character-by-character matching (like VS Code's Cmd+P)
|
|
86
|
+
- **⚡ Smart Relevance**: Results sorted by match quality and position
|
|
87
|
+
- **📜 Recent Items**: Automatically tracks and shows recently selected items
|
|
88
|
+
- **⌨️ Keyboard Shortcuts**: Built-in Cmd+K / Ctrl+K support via `useSpotlight()` hook
|
|
89
|
+
- **🎨 Tailwind-Native**: Zero style conflicts, inherits your design system
|
|
90
|
+
- **📦 Tiny Bundle**: Only logic shipped, styles compiled by your Tailwind
|
|
91
|
+
- **🔌 Router Agnostic**: Works with Next.js, React Router, or any navigation system
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🚀 Quick Start (Recommended)
|
|
96
|
+
|
|
97
|
+
The easiest way to use this package is with the `useSpotlight()` hook:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
"use client";
|
|
101
|
+
|
|
102
|
+
import { useSpotlight, Spotlight, SpotlightItem } from "spotlight-omni-search";
|
|
103
|
+
import { useRouter } from "next/navigation";
|
|
104
|
+
import { Home, Settings, User } from "lucide-react";
|
|
105
|
+
|
|
106
|
+
export function MyApp() {
|
|
107
|
+
const router = useRouter();
|
|
108
|
+
const { isOpen, close } = useSpotlight(); // ✨ Handles Cmd+K automatically!
|
|
109
|
+
|
|
110
|
+
const items: SpotlightItem[] = [
|
|
111
|
+
{
|
|
112
|
+
id: "home",
|
|
113
|
+
label: "Home",
|
|
114
|
+
icon: <Home size={20} />,
|
|
115
|
+
type: "page",
|
|
116
|
+
route: "/",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "settings",
|
|
120
|
+
label: "Settings",
|
|
121
|
+
icon: <Settings size={20} />,
|
|
122
|
+
type: "page",
|
|
123
|
+
route: "/settings",
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<Spotlight
|
|
129
|
+
isOpen={isOpen}
|
|
130
|
+
onClose={close}
|
|
131
|
+
items={items}
|
|
132
|
+
onNavigate={(path) => router.push(path)}
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**That's it!** Press `Cmd+K` (Mac) or `Ctrl+K` (Windows/Linux) to open the spotlight.
|
|
139
|
+
|
|
140
|
+
### Hook Options
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
const { isOpen, open, close, toggle } = useSpotlight({
|
|
144
|
+
defaultOpen: false, // Initial state
|
|
145
|
+
shortcut: "cmd+k", // Keyboard shortcut
|
|
146
|
+
enableShortcut: true, // Enable/disable shortcut
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 💡 Manual Setup (Advanced)
|
|
153
|
+
|
|
154
|
+
If you need more control, you can manage state manually:
|
|
155
|
+
|
|
156
|
+
Here is a complete, copy-pasteable example of how to use this in a Next.js app with `lucide-react`.
|
|
157
|
+
|
|
158
|
+
### `components/CommandPalette.tsx`
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
"use client";
|
|
162
|
+
|
|
163
|
+
import { useEffect, useState } from "react";
|
|
164
|
+
import { useRouter } from "next/navigation";
|
|
165
|
+
import { CreditCard, Home, Settings, User, LogOut } from "lucide-react";
|
|
166
|
+
|
|
167
|
+
// Import the component and types
|
|
168
|
+
import { Spotlight, SpotlightItem } from "spotlight-omni-search";
|
|
169
|
+
|
|
170
|
+
export function CommandPalette() {
|
|
171
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
172
|
+
const router = useRouter();
|
|
173
|
+
|
|
174
|
+
// 1. Define your items
|
|
175
|
+
const items: SpotlightItem[] = [
|
|
176
|
+
{
|
|
177
|
+
id: "home",
|
|
178
|
+
label: "Home",
|
|
179
|
+
description: "Go to dashboard",
|
|
180
|
+
icon: <Home size={20} />,
|
|
181
|
+
type: "page",
|
|
182
|
+
group: "Navigation",
|
|
183
|
+
route: "/dashboard",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: "profile",
|
|
187
|
+
label: "Profile",
|
|
188
|
+
description: "Manage your account",
|
|
189
|
+
icon: <User size={20} />,
|
|
190
|
+
type: "page",
|
|
191
|
+
group: "Navigation",
|
|
192
|
+
route: "/profile",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: "billing",
|
|
196
|
+
label: "Billing",
|
|
197
|
+
description: "View invoices and plans",
|
|
198
|
+
icon: <CreditCard size={20} />,
|
|
199
|
+
type: "page",
|
|
200
|
+
group: "Navigation",
|
|
201
|
+
route: "/billing",
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
id: "settings",
|
|
205
|
+
label: "Settings",
|
|
206
|
+
description: "App configuration",
|
|
207
|
+
icon: <Settings size={20} />,
|
|
208
|
+
type: "page",
|
|
209
|
+
group: "Navigation",
|
|
210
|
+
route: "/settings",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: "logout",
|
|
214
|
+
label: "Log Out",
|
|
215
|
+
description: "Sign out of your account",
|
|
216
|
+
icon: <LogOut size={20} />,
|
|
217
|
+
type: "action",
|
|
218
|
+
group: "Actions",
|
|
219
|
+
action: () => {
|
|
220
|
+
console.log("Logging out...");
|
|
221
|
+
// perform logout logic
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
// 2. Handle Keyboard Shortcut (Cmd+K)
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
229
|
+
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
setIsOpen((prev) => !prev);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
235
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
236
|
+
}, []);
|
|
237
|
+
|
|
238
|
+
// 3. Render
|
|
239
|
+
return (
|
|
240
|
+
<Spotlight
|
|
241
|
+
isOpen={isOpen}
|
|
242
|
+
onClose={() => setIsOpen(false)}
|
|
243
|
+
items={items}
|
|
244
|
+
onNavigate={(path) => router.push(path)} // Determine how to navigate
|
|
245
|
+
searchPlaceholder="Type a command or search..."
|
|
246
|
+
/>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Then simply drop `<CommandPalette />` into your root `layout.tsx` or `App.tsx`!
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 🔌 Router Integration
|
|
256
|
+
|
|
257
|
+
### Next.js with Manual Routes
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
import {
|
|
261
|
+
getSpotlightItemsFromRoutes,
|
|
262
|
+
RouteConfig,
|
|
263
|
+
} from "spotlight-omni-search";
|
|
264
|
+
import { Home, Settings, Users } from "lucide-react";
|
|
265
|
+
|
|
266
|
+
const routes: RouteConfig[] = [
|
|
267
|
+
{
|
|
268
|
+
path: "/",
|
|
269
|
+
label: "Home",
|
|
270
|
+
icon: <Home size={20} />,
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
path: "/settings",
|
|
274
|
+
label: "Settings",
|
|
275
|
+
description: "Manage your preferences",
|
|
276
|
+
icon: <Settings size={20} />,
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
path: "/admin",
|
|
280
|
+
label: "Admin Panel",
|
|
281
|
+
hidden: true, // Won't appear in spotlight
|
|
282
|
+
},
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
const spotlightItems = getSpotlightItemsFromRoutes(routes);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### React Router v6
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
import { createBrowserRouter } from "react-router-dom";
|
|
292
|
+
import {
|
|
293
|
+
getSpotlightItemsFromRoutes,
|
|
294
|
+
RouterHandle,
|
|
295
|
+
} from "spotlight-omni-search";
|
|
296
|
+
|
|
297
|
+
const routes = [
|
|
298
|
+
{
|
|
299
|
+
path: "/dashboard",
|
|
300
|
+
element: <Dashboard />,
|
|
301
|
+
handle: {
|
|
302
|
+
spotlight: {
|
|
303
|
+
label: "Dashboard",
|
|
304
|
+
description: "View your dashboard",
|
|
305
|
+
icon: <HomeIcon />,
|
|
306
|
+
keywords: ["home", "overview"],
|
|
307
|
+
},
|
|
308
|
+
} satisfies RouterHandle,
|
|
309
|
+
},
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
const router = createBrowserRouter(routes);
|
|
313
|
+
const spotlightItems = getSpotlightItemsFromRoutes(routes);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## ⚡ Built-in Actions
|
|
319
|
+
|
|
320
|
+
Use pre-built actions for common functionality:
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
import {
|
|
324
|
+
createCommonActions,
|
|
325
|
+
createThemeActions,
|
|
326
|
+
createUtilityActions,
|
|
327
|
+
} from "spotlight-omni-search";
|
|
328
|
+
|
|
329
|
+
// All common actions at once
|
|
330
|
+
const actions = createCommonActions({
|
|
331
|
+
currentTheme: theme,
|
|
332
|
+
onToggle: (newTheme) => setTheme(newTheme),
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Or pick specific action groups
|
|
336
|
+
const themeActions = createThemeActions({
|
|
337
|
+
currentTheme: theme,
|
|
338
|
+
onToggle: setTheme,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const utilityActions = createUtilityActions(); // Copy URL, Print, Reload
|
|
342
|
+
|
|
343
|
+
// Combine with your pages
|
|
344
|
+
const allItems = [...pages, ...actions];
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Available Actions:**
|
|
348
|
+
|
|
349
|
+
- 🌓 Theme toggle (dark/light)
|
|
350
|
+
- ⬅️ Navigate back/forward
|
|
351
|
+
- ⬆️ Scroll to top/bottom
|
|
352
|
+
- 📋 Copy current URL
|
|
353
|
+
- 🖨️ Print page
|
|
354
|
+
- 🔄 Reload page
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## ⏳ Loading States
|
|
359
|
+
|
|
360
|
+
Handle async data loading with built-in loading UI:
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
const [items, setItems] = useState<SpotlightItem[]>([]);
|
|
364
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
365
|
+
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
async function loadItems() {
|
|
368
|
+
setIsLoading(true);
|
|
369
|
+
const data = await fetchItemsFromAPI();
|
|
370
|
+
setItems(data);
|
|
371
|
+
setIsLoading(false);
|
|
372
|
+
}
|
|
373
|
+
loadItems();
|
|
374
|
+
}, []);
|
|
375
|
+
|
|
376
|
+
return (
|
|
377
|
+
<Spotlight
|
|
378
|
+
isOpen={isOpen}
|
|
379
|
+
onClose={close}
|
|
380
|
+
items={items}
|
|
381
|
+
isLoading={isLoading} // Shows skeleton loader
|
|
382
|
+
onNavigate={(path) => router.push(path)}
|
|
383
|
+
/>
|
|
384
|
+
);
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## 📄 License
|
|
390
|
+
|
|
391
|
+
MIT © Dhruv
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SpotlightItem } from '../types';
|
|
2
|
+
export interface ThemeActionsOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Callback when theme is toggled
|
|
5
|
+
*/
|
|
6
|
+
onToggle?: (theme: 'light' | 'dark') => void;
|
|
7
|
+
/**
|
|
8
|
+
* Current theme (to show correct icon)
|
|
9
|
+
*/
|
|
10
|
+
currentTheme?: 'light' | 'dark';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates theme toggle actions
|
|
14
|
+
*/
|
|
15
|
+
export declare function createThemeActions(options?: ThemeActionsOptions): SpotlightItem[];
|
|
16
|
+
/**
|
|
17
|
+
* Creates browser navigation actions
|
|
18
|
+
*/
|
|
19
|
+
export declare function createNavigationActions(): SpotlightItem[];
|
|
20
|
+
/**
|
|
21
|
+
* Creates scroll actions
|
|
22
|
+
*/
|
|
23
|
+
export declare function createScrollActions(): SpotlightItem[];
|
|
24
|
+
/**
|
|
25
|
+
* Creates utility actions
|
|
26
|
+
*/
|
|
27
|
+
export declare function createUtilityActions(): SpotlightItem[];
|
|
28
|
+
/**
|
|
29
|
+
* Creates all common actions
|
|
30
|
+
*/
|
|
31
|
+
export declare function createCommonActions(themeOptions?: ThemeActionsOptions): SpotlightItem[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { SpotlightItem } from "../types";
|
|
3
|
+
export interface RouteConfig {
|
|
4
|
+
path: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
icon?: ReactNode;
|
|
10
|
+
children?: RouteConfig[];
|
|
11
|
+
/**
|
|
12
|
+
* Hide this route from spotlight search
|
|
13
|
+
*/
|
|
14
|
+
hidden?: boolean;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Recursively extracts spotlight items from a route configuration.
|
|
19
|
+
* @param routes The list of routes to traverse.
|
|
20
|
+
* @param baseUrl The base URL for the current level (used for recursion).
|
|
21
|
+
* @param parentGroup The group name to assign (defaults to "Pages").
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSpotlightItemsFromRoutes(routes: RouteConfig[], baseUrl?: string, parentGroup?: string): SpotlightItem[];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RouteObject } from "react-router-dom";
|
|
2
|
+
import { SpotlightItem, SpotlightItemType } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Interface for React Router handle metadata
|
|
5
|
+
* Use this to add spotlight metadata to your routes
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* {
|
|
10
|
+
* path: '/dashboard',
|
|
11
|
+
* element: <Dashboard />,
|
|
12
|
+
* handle: {
|
|
13
|
+
* spotlight: {
|
|
14
|
+
* label: 'Dashboard',
|
|
15
|
+
* description: 'View your dashboard',
|
|
16
|
+
* icon: <HomeIcon />,
|
|
17
|
+
* keywords: ['home', 'overview']
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export interface RouterHandle {
|
|
24
|
+
spotlight?: {
|
|
25
|
+
label: string;
|
|
26
|
+
icon?: React.ReactNode;
|
|
27
|
+
description?: string;
|
|
28
|
+
keywords?: string[];
|
|
29
|
+
type?: SpotlightItemType;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Recursively extracts spotlight items from route configuration
|
|
34
|
+
* @param routes The React Router route definitions
|
|
35
|
+
* @param parentPath The path accumulator for recursion
|
|
36
|
+
*/
|
|
37
|
+
export declare function getSpotlightItemsFromRoutes(routes: RouteObject[], parentPath?: string): SpotlightItem[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SpotlightItem } from '../types';
|
|
2
|
+
export interface UseRecentItemsOptions {
|
|
3
|
+
/**
|
|
4
|
+
* LocalStorage key for persistence
|
|
5
|
+
* @default 'spotlight-recent-items'
|
|
6
|
+
*/
|
|
7
|
+
storageKey?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum number of recent items to track
|
|
10
|
+
* @default 10
|
|
11
|
+
*/
|
|
12
|
+
maxItems?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Enable recent items tracking
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface UseRecentItemsReturn {
|
|
20
|
+
/**
|
|
21
|
+
* List of recent items
|
|
22
|
+
*/
|
|
23
|
+
recentItems: SpotlightItem[];
|
|
24
|
+
/**
|
|
25
|
+
* Add an item to recent history
|
|
26
|
+
*/
|
|
27
|
+
addRecentItem: (item: SpotlightItem) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Clear all recent items
|
|
30
|
+
*/
|
|
31
|
+
clearRecent: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Hook to manage recent items with localStorage persistence
|
|
35
|
+
*/
|
|
36
|
+
export declare function useRecentItems(options?: UseRecentItemsOptions): UseRecentItemsReturn;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface UseSpotlightOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Initial open state
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Keyboard shortcut to toggle spotlight
|
|
9
|
+
* Format: 'cmd+k', 'ctrl+shift+p', etc.
|
|
10
|
+
* @default 'cmd+k' (Mac) / 'ctrl+k' (Windows/Linux)
|
|
11
|
+
*/
|
|
12
|
+
shortcut?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Enable keyboard shortcut
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
enableShortcut?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface UseSpotlightReturn {
|
|
20
|
+
/**
|
|
21
|
+
* Current open state
|
|
22
|
+
*/
|
|
23
|
+
isOpen: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Open the spotlight
|
|
26
|
+
*/
|
|
27
|
+
open: () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Close the spotlight
|
|
30
|
+
*/
|
|
31
|
+
close: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Toggle the spotlight open/closed
|
|
34
|
+
*/
|
|
35
|
+
toggle: () => void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Hook to manage Spotlight state and keyboard shortcuts
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* const { isOpen, open, close, toggle } = useSpotlight();
|
|
43
|
+
*
|
|
44
|
+
* return <Spotlight isOpen={isOpen} onClose={close} ... />;
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function useSpotlight(options?: UseSpotlightOptions): UseSpotlightReturn;
|
package/dist/index.d.ts
ADDED