@wallarm-org/design-system 1.5.1-rc-fix-switch.1 → 1.6.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.
Files changed (48) hide show
  1. package/dist/components/AppShell/story-content/_storyHeaderActions.js +2 -18
  2. package/dist/components/AppShell/story-content/_storySearchModal.d.ts +1 -0
  3. package/dist/components/AppShell/story-content/_storySearchModal.js +251 -0
  4. package/dist/components/Badge/Badge.js +1 -1
  5. package/dist/components/Card/CardFooter.js +4 -1
  6. package/dist/components/Card/CardHeader.js +1 -1
  7. package/dist/components/Card/classes.js +1 -1
  8. package/dist/components/SearchModal/SearchModal.d.ts +9 -0
  9. package/dist/components/SearchModal/SearchModal.js +50 -0
  10. package/dist/components/SearchModal/SearchModalBody.d.ts +6 -0
  11. package/dist/components/SearchModal/SearchModalBody.js +21 -0
  12. package/dist/components/SearchModal/SearchModalContent.d.ts +6 -0
  13. package/dist/components/SearchModal/SearchModalContent.js +64 -0
  14. package/dist/components/SearchModal/SearchModalContext/SearchModalContext.d.ts +2 -0
  15. package/dist/components/SearchModal/SearchModalContext/SearchModalContext.js +3 -0
  16. package/dist/components/SearchModal/SearchModalContext/SearchModalProvider.d.ts +9 -0
  17. package/dist/components/SearchModal/SearchModalContext/SearchModalProvider.js +51 -0
  18. package/dist/components/SearchModal/SearchModalContext/index.d.ts +4 -0
  19. package/dist/components/SearchModal/SearchModalContext/index.js +3 -0
  20. package/dist/components/SearchModal/SearchModalContext/types.d.ts +11 -0
  21. package/dist/components/SearchModal/SearchModalContext/types.js +0 -0
  22. package/dist/components/SearchModal/SearchModalContext/useSearchModalContext.d.ts +1 -0
  23. package/dist/components/SearchModal/SearchModalContext/useSearchModalContext.js +8 -0
  24. package/dist/components/SearchModal/SearchModalEmpty.d.ts +6 -0
  25. package/dist/components/SearchModal/SearchModalEmpty.js +16 -0
  26. package/dist/components/SearchModal/SearchModalFooter.d.ts +6 -0
  27. package/dist/components/SearchModal/SearchModalFooter.js +51 -0
  28. package/dist/components/SearchModal/SearchModalGroup.d.ts +6 -0
  29. package/dist/components/SearchModal/SearchModalGroup.js +17 -0
  30. package/dist/components/SearchModal/SearchModalGroupLabel.d.ts +6 -0
  31. package/dist/components/SearchModal/SearchModalGroupLabel.js +17 -0
  32. package/dist/components/SearchModal/SearchModalInput.d.ts +7 -0
  33. package/dist/components/SearchModal/SearchModalInput.js +42 -0
  34. package/dist/components/SearchModal/SearchModalItem.d.ts +14 -0
  35. package/dist/components/SearchModal/SearchModalItem.js +54 -0
  36. package/dist/components/SearchModal/SearchModalTrigger.d.ts +10 -0
  37. package/dist/components/SearchModal/SearchModalTrigger.js +16 -0
  38. package/dist/components/SearchModal/classes.d.ts +9 -0
  39. package/dist/components/SearchModal/classes.js +24 -0
  40. package/dist/components/SearchModal/index.d.ts +11 -0
  41. package/dist/components/SearchModal/index.js +11 -0
  42. package/dist/components/SegmentedControl/classes.js +1 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.js +1 -0
  45. package/dist/metadata/components.json +2846 -69
  46. package/dist/utils/mergeRefs.d.ts +2 -0
  47. package/dist/utils/mergeRefs.js +7 -0
  48. package/package.json +1 -1
@@ -2,30 +2,14 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Bell, ChevronUpDown } from "../../../icons/index.js";
3
3
  import { Button } from "../../Button/index.js";
4
4
  import { Code } from "../../Code/index.js";
5
- import { Kbd } from "../../Kbd/index.js";
6
5
  import { Text } from "../../Text/index.js";
7
6
  import { Tooltip, TooltipContent, TooltipTrigger } from "../../Tooltip/index.js";
8
7
  import { TopHeaderSeparator } from "../../TopHeader/index.js";
9
8
  import { QuickHelpDropdown } from "./_storyQuickHelpDropdown.js";
9
+ import { StorySearchModal } from "./_storySearchModal.js";
10
10
  const HeaderActions = ()=>/*#__PURE__*/ jsxs(Fragment, {
11
11
  children: [
12
- /*#__PURE__*/ jsxs(Button, {
13
- variant: "ghost",
14
- size: "small",
15
- color: "neutral",
16
- className: "p-4 gap-6 rounded-6",
17
- children: [
18
- /*#__PURE__*/ jsx(Code, {
19
- size: "s",
20
- color: "secondary",
21
- children: "Search Wallarm"
22
- }),
23
- /*#__PURE__*/ jsx(Kbd, {
24
- size: "xsmall",
25
- children: "⌘ K"
26
- })
27
- ]
28
- }),
12
+ /*#__PURE__*/ jsx(StorySearchModal, {}),
29
13
  /*#__PURE__*/ jsx(TopHeaderSeparator, {}),
30
14
  /*#__PURE__*/ jsxs(Button, {
31
15
  variant: "ghost",
@@ -0,0 +1 @@
1
+ export declare const StorySearchModal: () => import("react").JSX.Element;
@@ -0,0 +1,251 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Building, LoaderCircle, Plus } from "../../../icons/index.js";
4
+ import { Button } from "../../Button/index.js";
5
+ import { Code } from "../../Code/index.js";
6
+ import { EmptyState, EmptyStateDescription, EmptyStateMessage } from "../../EmptyState/index.js";
7
+ import { Kbd } from "../../Kbd/index.js";
8
+ import { SearchModal, SearchModalBody, SearchModalContent, SearchModalEmpty, SearchModalFooter, SearchModalGroup, SearchModalGroupLabel, SearchModalInput, SearchModalItem, SearchModalTrigger } from "../../SearchModal/index.js";
9
+ import { Text } from "../../Text/index.js";
10
+ const recentItems = [
11
+ {
12
+ page: 'Attacks',
13
+ product: 'Cloud WAF',
14
+ date: '2 hours ago',
15
+ href: '/attacks'
16
+ },
17
+ {
18
+ page: 'Rules',
19
+ product: 'Cloud WAF',
20
+ date: '5 hours ago',
21
+ href: '/rules'
22
+ },
23
+ {
24
+ page: 'Endpoints',
25
+ product: 'US East',
26
+ dataPlane: true,
27
+ productExtra: 'API Discovery',
28
+ date: 'Yesterday',
29
+ href: '/endpoints'
30
+ },
31
+ {
32
+ page: 'Dashboards',
33
+ product: 'Cloud WAF',
34
+ date: '2 days ago',
35
+ href: '/dashboards'
36
+ },
37
+ {
38
+ page: 'Triggers',
39
+ product: 'Cloud WAF',
40
+ date: '3 days ago',
41
+ href: '/triggers'
42
+ }
43
+ ];
44
+ const jumpToItems = [
45
+ {
46
+ name: 'Cloud WAF',
47
+ href: '/cloud-waf'
48
+ },
49
+ {
50
+ name: 'API Discovery',
51
+ href: '/api-discovery'
52
+ }
53
+ ];
54
+ const filterRecent = (query)=>{
55
+ if (!query) return recentItems;
56
+ return recentItems.filter((item)=>{
57
+ const text = `${item.page} ${item.product} ${item.productExtra ?? ''}`.toLowerCase();
58
+ return text.includes(query);
59
+ });
60
+ };
61
+ const filterJumpTo = (query)=>{
62
+ if (!query) return jumpToItems;
63
+ return jumpToItems.filter((item)=>item.name.toLowerCase().includes(query));
64
+ };
65
+ const StorySearchModal = ()=>{
66
+ const [open, setOpen] = useState(false);
67
+ const [query, setQuery] = useState('');
68
+ const lowerQuery = query.toLowerCase();
69
+ const filteredRecent = filterRecent(lowerQuery);
70
+ const filteredJumpTo = filterJumpTo(lowerQuery);
71
+ const hasResults = filteredRecent.length > 0 || filteredJumpTo.length > 0 || !lowerQuery;
72
+ const handleOpenChange = (nextOpen)=>{
73
+ setOpen(nextOpen);
74
+ if (!nextOpen) setQuery('');
75
+ };
76
+ return /*#__PURE__*/ jsxs(SearchModal, {
77
+ open: open,
78
+ onOpenChange: handleOpenChange,
79
+ onQueryChange: setQuery,
80
+ children: [
81
+ /*#__PURE__*/ jsx(SearchModalTrigger, {
82
+ asChild: true,
83
+ children: /*#__PURE__*/ jsxs(Button, {
84
+ variant: "ghost",
85
+ size: "small",
86
+ color: "neutral",
87
+ className: "p-4 gap-6 rounded-6",
88
+ "data-slot": "top-header-search",
89
+ children: [
90
+ /*#__PURE__*/ jsx(Code, {
91
+ size: "s",
92
+ color: "secondary",
93
+ children: "Search Wallarm"
94
+ }),
95
+ /*#__PURE__*/ jsx(Kbd, {
96
+ size: "xsmall",
97
+ children: "⌘ K"
98
+ })
99
+ ]
100
+ })
101
+ }),
102
+ /*#__PURE__*/ jsxs(SearchModalContent, {
103
+ children: [
104
+ /*#__PURE__*/ jsx(SearchModalInput, {
105
+ placeholder: "Search products, features, and more..."
106
+ }),
107
+ lowerQuery && !hasResults && /*#__PURE__*/ jsx(SearchModalEmpty, {
108
+ children: /*#__PURE__*/ jsx(EmptyState, {
109
+ type: "no-results",
110
+ className: "pb-8",
111
+ children: /*#__PURE__*/ jsx(EmptyStateMessage, {
112
+ children: /*#__PURE__*/ jsx(EmptyStateDescription, {
113
+ children: "No results"
114
+ })
115
+ })
116
+ })
117
+ }),
118
+ /*#__PURE__*/ jsxs(SearchModalBody, {
119
+ children: [
120
+ /*#__PURE__*/ jsxs(SearchModalGroup, {
121
+ children: [
122
+ /*#__PURE__*/ jsx(SearchModalGroupLabel, {
123
+ children: /*#__PURE__*/ jsx(Text, {
124
+ size: "xs",
125
+ color: "secondary",
126
+ weight: "medium",
127
+ children: "Quick actions"
128
+ })
129
+ }),
130
+ /*#__PURE__*/ jsxs(SearchModalItem, {
131
+ onSelect: ()=>{},
132
+ children: [
133
+ /*#__PURE__*/ jsx("span", {
134
+ className: "text-lg",
135
+ children: "\uD83D\uDC36"
136
+ }),
137
+ /*#__PURE__*/ jsx(Text, {
138
+ size: "sm",
139
+ children: "Ask Wally"
140
+ })
141
+ ]
142
+ }),
143
+ !lowerQuery && /*#__PURE__*/ jsxs(Fragment, {
144
+ children: [
145
+ /*#__PURE__*/ jsxs(SearchModalItem, {
146
+ onSelect: ()=>{},
147
+ children: [
148
+ /*#__PURE__*/ jsx(Building, {
149
+ className: "text-text-secondary !icon-md"
150
+ }),
151
+ /*#__PURE__*/ jsx(Text, {
152
+ size: "sm",
153
+ children: "Switch tenant"
154
+ })
155
+ ]
156
+ }),
157
+ /*#__PURE__*/ jsxs(SearchModalItem, {
158
+ onSelect: ()=>{},
159
+ children: [
160
+ /*#__PURE__*/ jsx(Plus, {
161
+ className: "text-text-secondary !icon-md"
162
+ }),
163
+ /*#__PURE__*/ jsx(Text, {
164
+ size: "sm",
165
+ children: "Create..."
166
+ })
167
+ ]
168
+ })
169
+ ]
170
+ })
171
+ ]
172
+ }),
173
+ filteredRecent.length > 0 && /*#__PURE__*/ jsxs(SearchModalGroup, {
174
+ children: [
175
+ /*#__PURE__*/ jsx(SearchModalGroupLabel, {
176
+ children: /*#__PURE__*/ jsx(Text, {
177
+ size: "xs",
178
+ color: "secondary",
179
+ weight: "medium",
180
+ children: "Recent"
181
+ })
182
+ }),
183
+ filteredRecent.map((item)=>/*#__PURE__*/ jsxs(SearchModalItem, {
184
+ onSelect: ()=>{},
185
+ children: [
186
+ /*#__PURE__*/ jsx(LoaderCircle, {
187
+ className: "text-text-tertiary shrink-0 !icon-md"
188
+ }),
189
+ /*#__PURE__*/ jsxs(Text, {
190
+ size: "sm",
191
+ grow: true,
192
+ truncate: true,
193
+ children: [
194
+ item.page,
195
+ /*#__PURE__*/ jsxs(Text, {
196
+ size: "sm",
197
+ color: "secondary",
198
+ inline: true,
199
+ children: [
200
+ ' ',
201
+ "— ",
202
+ item.dataPlane ? `${item.productExtra} · ${item.product}` : item.product
203
+ ]
204
+ })
205
+ ]
206
+ }),
207
+ /*#__PURE__*/ jsx("span", {
208
+ className: "shrink-0",
209
+ children: /*#__PURE__*/ jsx(Text, {
210
+ size: "xs",
211
+ color: "secondary",
212
+ children: item.date
213
+ })
214
+ })
215
+ ]
216
+ }, `${item.page}-${item.product}`))
217
+ ]
218
+ }),
219
+ filteredJumpTo.length > 0 && /*#__PURE__*/ jsxs(SearchModalGroup, {
220
+ children: [
221
+ /*#__PURE__*/ jsx(SearchModalGroupLabel, {
222
+ children: /*#__PURE__*/ jsx(Text, {
223
+ size: "xs",
224
+ color: "secondary",
225
+ weight: "medium",
226
+ children: "Jump to"
227
+ })
228
+ }),
229
+ filteredJumpTo.map((item)=>/*#__PURE__*/ jsxs(SearchModalItem, {
230
+ onSelect: ()=>{},
231
+ children: [
232
+ /*#__PURE__*/ jsx(LoaderCircle, {
233
+ className: "text-text-tertiary shrink-0 !icon-md"
234
+ }),
235
+ /*#__PURE__*/ jsx(Text, {
236
+ size: "sm",
237
+ children: item.name
238
+ })
239
+ ]
240
+ }, item.href))
241
+ ]
242
+ })
243
+ ]
244
+ }),
245
+ /*#__PURE__*/ jsx(SearchModalFooter, {})
246
+ ]
247
+ })
248
+ ]
249
+ });
250
+ };
251
+ export { StorySearchModal };
@@ -13,7 +13,7 @@ const Badge = ({ ref, className, variant = 'default', size = 'medium', type = 's
13
13
  textVariant,
14
14
  isIconOnly: isIconOnly(children),
15
15
  isClickable: !!onClick
16
- }), className);
16
+ }), onClick ? 'cursor-pointer' : '', className);
17
17
  const handleClick = onClick ? (event)=>{
18
18
  event.stopPropagation();
19
19
  onClick(event);
@@ -1,16 +1,19 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
+ import { Children } from "react";
2
3
  import { Slot } from "@radix-ui/react-slot";
3
4
  import { cn } from "../../utils/cn.js";
4
5
  import { useTestId } from "../../utils/testId.js";
5
6
  const CardFooter = ({ ref, asChild = false, className, children, ...props })=>{
6
7
  const Comp = asChild ? Slot : 'div';
7
8
  const testId = useTestId('footer');
9
+ const childCount = Children.count(children);
10
+ const justifyClass = childCount > 1 ? 'justify-between' : 'justify-end';
8
11
  return /*#__PURE__*/ jsx(Comp, {
9
12
  ...props,
10
13
  ref: ref,
11
14
  "data-slot": "card-footer",
12
15
  "data-testid": testId,
13
- className: cn('mt-auto flex items-center justify-end gap-12 px-16', className),
16
+ className: cn('mt-auto flex items-center gap-12 px-16', justifyClass, className),
14
17
  children: children
15
18
  });
16
19
  };
@@ -10,7 +10,7 @@ const CardHeader = ({ ref, asChild = false, className, children, ...props })=>{
10
10
  ref: ref,
11
11
  "data-slot": "card-header",
12
12
  "data-testid": testId,
13
- className: cn('flex items-center justify-between gap-8 px-16', className),
13
+ className: cn('flex items-center justify-between gap-8 px-16 text-base', className),
14
14
  children: children
15
15
  });
16
16
  };
@@ -1,5 +1,5 @@
1
1
  import { cva } from "class-variance-authority";
2
- const cardVariants = cva('flex flex-col gap-8 rounded-8 border-1 shadow-sm min-w-[120px] overflow-hidden py-16 transition-colors duration-200 h-full', {
2
+ const cardVariants = cva('flex flex-col gap-8 rounded-8 border-1 shadow-sm min-w-[240px] overflow-hidden py-16 transition-colors duration-200 h-full text-sm', {
3
3
  variants: {
4
4
  color: {
5
5
  primary: 'bg-bg-surface-1 border-border-primary-light',
@@ -0,0 +1,9 @@
1
+ import type { FC, ReactNode } from 'react';
2
+ import type { TestableProps } from '../../utils/testId';
3
+ export interface SearchModalProps extends TestableProps {
4
+ children: ReactNode;
5
+ open?: boolean;
6
+ onOpenChange?: (open: boolean) => void;
7
+ onQueryChange?: (query: string) => void;
8
+ }
9
+ export declare const SearchModal: FC<SearchModalProps>;
@@ -0,0 +1,50 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef } from "react";
3
+ import { Dialog } from "@ark-ui/react/dialog";
4
+ import { TestIdProvider } from "../../utils/testId.js";
5
+ import { SearchModalProvider } from "./SearchModalContext/index.js";
6
+ const SearchModal = ({ children, open, onOpenChange, onQueryChange, 'data-testid': testId })=>{
7
+ const onOpenChangeRef = useRef(onOpenChange);
8
+ onOpenChangeRef.current = onOpenChange;
9
+ const openRef = useRef(open);
10
+ openRef.current = open;
11
+ const handleOpenChange = useCallback(({ open })=>{
12
+ onOpenChangeRef.current?.(open);
13
+ }, []);
14
+ const handleClose = useCallback(()=>{
15
+ onOpenChangeRef.current?.(false);
16
+ }, []);
17
+ useEffect(()=>{
18
+ const handleKeyDown = (e)=>{
19
+ if ('k' === e.key && (e.metaKey || e.ctrlKey)) {
20
+ e.preventDefault();
21
+ onOpenChangeRef.current?.(!openRef.current);
22
+ }
23
+ };
24
+ document.addEventListener('keydown', handleKeyDown);
25
+ return ()=>document.removeEventListener('keydown', handleKeyDown);
26
+ }, []);
27
+ return /*#__PURE__*/ jsx(TestIdProvider, {
28
+ value: testId,
29
+ children: /*#__PURE__*/ jsx("div", {
30
+ "data-slot": "search-modal",
31
+ "data-testid": testId,
32
+ children: /*#__PURE__*/ jsx(Dialog.Root, {
33
+ open: open,
34
+ onOpenChange: handleOpenChange,
35
+ closeOnEscape: true,
36
+ closeOnInteractOutside: true,
37
+ lazyMount: true,
38
+ unmountOnExit: true,
39
+ children: /*#__PURE__*/ jsx(SearchModalProvider, {
40
+ open: open,
41
+ onQueryChange: onQueryChange,
42
+ onClose: handleClose,
43
+ children: children
44
+ })
45
+ })
46
+ })
47
+ });
48
+ };
49
+ SearchModal.displayName = 'SearchModal';
50
+ export { SearchModal };
@@ -0,0 +1,6 @@
1
+ import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
2
+ export interface SearchModalBodyProps extends HTMLAttributes<HTMLDivElement> {
3
+ ref?: Ref<HTMLDivElement>;
4
+ children: ReactNode;
5
+ }
6
+ export declare const SearchModalBody: FC<SearchModalBodyProps>;
@@ -0,0 +1,21 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../utils/cn.js";
3
+ import { mergeRefs } from "../../utils/mergeRefs.js";
4
+ import { useTestId } from "../../utils/testId.js";
5
+ import { searchModalBodyVariants } from "./classes.js";
6
+ import { useSearchModalContext } from "./SearchModalContext/index.js";
7
+ const SearchModalBody = ({ ref, children, className, ...props })=>{
8
+ const testId = useTestId('body');
9
+ const { listRef } = useSearchModalContext();
10
+ return /*#__PURE__*/ jsx("div", {
11
+ ...props,
12
+ ref: mergeRefs(listRef, ref),
13
+ "data-slot": "search-modal-body",
14
+ "data-testid": testId,
15
+ role: "listbox",
16
+ className: cn(searchModalBodyVariants(), className),
17
+ children: children
18
+ });
19
+ };
20
+ SearchModalBody.displayName = 'SearchModalBody';
21
+ export { SearchModalBody };
@@ -0,0 +1,6 @@
1
+ import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
2
+ export interface SearchModalContentProps extends HTMLAttributes<HTMLDivElement> {
3
+ ref?: Ref<HTMLDivElement>;
4
+ children: ReactNode;
5
+ }
6
+ export declare const SearchModalContent: FC<SearchModalContentProps>;
@@ -0,0 +1,64 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from "react";
3
+ import { Dialog } from "@ark-ui/react/dialog";
4
+ import { Portal } from "@ark-ui/react/portal";
5
+ import { cn } from "../../utils/cn.js";
6
+ import { useTestId } from "../../utils/testId.js";
7
+ import { Overlay } from "../Overlay/index.js";
8
+ import { searchModalContentVariants } from "./classes.js";
9
+ import { useSearchModalContext } from "./SearchModalContext/index.js";
10
+ const SearchModalContent = ({ ref, children, className, ...props })=>{
11
+ const testId = useTestId('content');
12
+ const { activeIndex, setActiveIndex, getItems, inputRef } = useSearchModalContext();
13
+ useEffect(()=>{
14
+ requestAnimationFrame(()=>{
15
+ inputRef.current?.focus();
16
+ });
17
+ }, [
18
+ inputRef
19
+ ]);
20
+ useEffect(()=>{
21
+ if (activeIndex >= 0) {
22
+ const items = getItems();
23
+ items[activeIndex]?.scrollIntoView({
24
+ block: 'nearest'
25
+ });
26
+ }
27
+ }, [
28
+ activeIndex,
29
+ getItems
30
+ ]);
31
+ const handleKeyDown = (e)=>{
32
+ if ('ArrowDown' === e.key || 'ArrowUp' === e.key) {
33
+ e.preventDefault();
34
+ const totalItems = getItems().length;
35
+ if (0 === totalItems) return;
36
+ 'ArrowDown' === e.key ? setActiveIndex(activeIndex + 1 >= totalItems ? 0 : activeIndex + 1) : setActiveIndex(activeIndex - 1 < 0 ? totalItems - 1 : activeIndex - 1);
37
+ } else if ('Enter' === e.key && activeIndex >= 0) {
38
+ e.preventDefault();
39
+ getItems()[activeIndex]?.click();
40
+ }
41
+ };
42
+ return /*#__PURE__*/ jsxs(Portal, {
43
+ children: [
44
+ /*#__PURE__*/ jsx(Dialog.Backdrop, {
45
+ asChild: true,
46
+ children: /*#__PURE__*/ jsx(Overlay, {})
47
+ }),
48
+ /*#__PURE__*/ jsx(Dialog.Positioner, {
49
+ className: "fixed inset-0 z-[calc(var(--drawer-overlay-z-index)+1)] flex items-start justify-center pt-[10vh]",
50
+ children: /*#__PURE__*/ jsx(Dialog.Content, {
51
+ ...props,
52
+ ref: ref,
53
+ "data-slot": "search-modal-content",
54
+ "data-testid": testId,
55
+ className: cn(searchModalContentVariants(), className),
56
+ onKeyDown: handleKeyDown,
57
+ children: children
58
+ })
59
+ })
60
+ ]
61
+ });
62
+ };
63
+ SearchModalContent.displayName = 'SearchModalContent';
64
+ export { SearchModalContent };
@@ -0,0 +1,2 @@
1
+ import type { SearchModalContextValue } from './types';
2
+ export declare const SearchModalContext: import("react").Context<SearchModalContextValue | null>;
@@ -0,0 +1,3 @@
1
+ import { createContext } from "react";
2
+ const SearchModalContext = createContext(null);
3
+ export { SearchModalContext };
@@ -0,0 +1,9 @@
1
+ import { type FC, type ReactNode } from 'react';
2
+ interface SearchModalProviderProps {
3
+ children: ReactNode;
4
+ open?: boolean;
5
+ onQueryChange?: (query: string) => void;
6
+ onClose: () => void;
7
+ }
8
+ export declare const SearchModalProvider: FC<SearchModalProviderProps>;
9
+ export {};
@@ -0,0 +1,51 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { SearchModalContext } from "./SearchModalContext.js";
4
+ const SearchModalProvider = ({ children, open, onQueryChange, onClose })=>{
5
+ const [query, setQueryState] = useState('');
6
+ const [activeIndex, setActiveIndex] = useState(0);
7
+ const inputRef = useRef(null);
8
+ const listRef = useRef(null);
9
+ const onQueryChangeRef = useRef(onQueryChange);
10
+ onQueryChangeRef.current = onQueryChange;
11
+ const onCloseRef = useRef(onClose);
12
+ onCloseRef.current = onClose;
13
+ useEffect(()=>{
14
+ if (open) {
15
+ setQueryState('');
16
+ setActiveIndex(0);
17
+ }
18
+ }, [
19
+ open
20
+ ]);
21
+ const setQuery = useCallback((value)=>{
22
+ setQueryState(value);
23
+ setActiveIndex(0);
24
+ onQueryChangeRef.current?.(value);
25
+ }, []);
26
+ const close = useCallback(()=>{
27
+ onCloseRef.current();
28
+ }, []);
29
+ const getItems = useCallback(()=>listRef.current ? Array.from(listRef.current.querySelectorAll('[data-search-item]:not([disabled])')) : [], []);
30
+ const contextValue = useMemo(()=>({
31
+ query,
32
+ setQuery,
33
+ activeIndex,
34
+ setActiveIndex,
35
+ close,
36
+ getItems,
37
+ inputRef,
38
+ listRef
39
+ }), [
40
+ query,
41
+ activeIndex,
42
+ setQuery,
43
+ close,
44
+ getItems
45
+ ]);
46
+ return /*#__PURE__*/ jsx(SearchModalContext.Provider, {
47
+ value: contextValue,
48
+ children: children
49
+ });
50
+ };
51
+ export { SearchModalProvider };
@@ -0,0 +1,4 @@
1
+ export { SearchModalContext } from './SearchModalContext';
2
+ export { SearchModalProvider } from './SearchModalProvider';
3
+ export type { SearchModalContextValue } from './types';
4
+ export { useSearchModalContext } from './useSearchModalContext';
@@ -0,0 +1,3 @@
1
+ export { SearchModalContext } from "./SearchModalContext.js";
2
+ export { SearchModalProvider } from "./SearchModalProvider.js";
3
+ export { useSearchModalContext } from "./useSearchModalContext.js";
@@ -0,0 +1,11 @@
1
+ import type { RefObject } from 'react';
2
+ export interface SearchModalContextValue {
3
+ query: string;
4
+ setQuery: (query: string) => void;
5
+ activeIndex: number;
6
+ setActiveIndex: (index: number) => void;
7
+ close: () => void;
8
+ getItems: () => HTMLElement[];
9
+ inputRef: RefObject<HTMLInputElement | null>;
10
+ listRef: RefObject<HTMLDivElement | null>;
11
+ }
@@ -0,0 +1 @@
1
+ export declare const useSearchModalContext: () => import("./types").SearchModalContextValue;
@@ -0,0 +1,8 @@
1
+ import { useContext } from "react";
2
+ import { SearchModalContext } from "./SearchModalContext.js";
3
+ const useSearchModalContext = ()=>{
4
+ const context = useContext(SearchModalContext);
5
+ if (!context) throw new Error('useSearchModalContext must be used within a SearchModal');
6
+ return context;
7
+ };
8
+ export { useSearchModalContext };
@@ -0,0 +1,6 @@
1
+ import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
2
+ export interface SearchModalEmptyProps extends HTMLAttributes<HTMLDivElement> {
3
+ ref?: Ref<HTMLDivElement>;
4
+ children: ReactNode;
5
+ }
6
+ export declare const SearchModalEmpty: FC<SearchModalEmptyProps>;
@@ -0,0 +1,16 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../utils/cn.js";
3
+ import { useTestId } from "../../utils/testId.js";
4
+ const SearchModalEmpty = ({ ref, children, className, ...props })=>{
5
+ const testId = useTestId('empty');
6
+ return /*#__PURE__*/ jsx("div", {
7
+ ...props,
8
+ ref: ref,
9
+ "data-slot": "search-modal-empty",
10
+ "data-testid": testId,
11
+ className: cn('pb-8', className),
12
+ children: children
13
+ });
14
+ };
15
+ SearchModalEmpty.displayName = 'SearchModalEmpty';
16
+ export { SearchModalEmpty };
@@ -0,0 +1,6 @@
1
+ import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
2
+ export interface SearchModalFooterProps extends HTMLAttributes<HTMLDivElement> {
3
+ ref?: Ref<HTMLDivElement>;
4
+ children?: ReactNode;
5
+ }
6
+ export declare const SearchModalFooter: FC<SearchModalFooterProps>;