@shipfox/react-ui 0.30.0 → 0.31.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 (26) hide show
  1. package/dist/components/code-block/code-content.js +5 -2
  2. package/dist/components/dashboard/components/kpi-card.js +2 -2
  3. package/dist/components/shipql-editor/index.d.ts +1 -1
  4. package/dist/components/shipql-editor/index.js +1 -1
  5. package/dist/components/shipql-editor/lexical/leaf-close-overlay.js +65 -2
  6. package/dist/components/shipql-editor/lexical/shipql-plugin.js +10 -1
  7. package/dist/components/shipql-editor/shipql-editor-inner.d.ts +1 -1
  8. package/dist/components/shipql-editor/shipql-editor-inner.js +148 -41
  9. package/dist/components/shipql-editor/shipql-editor.d.ts +12 -0
  10. package/dist/components/shipql-editor/shipql-editor.js +1 -1
  11. package/dist/components/shipql-editor/suggestions/generate-suggestions.d.ts +22 -0
  12. package/dist/components/shipql-editor/suggestions/generate-suggestions.js +170 -0
  13. package/dist/components/shipql-editor/suggestions/shipql-range-facet-panel.d.ts +9 -0
  14. package/dist/components/shipql-editor/suggestions/shipql-range-facet-panel.js +376 -0
  15. package/dist/components/shipql-editor/suggestions/shipql-suggestion-item.d.ts +11 -0
  16. package/dist/components/shipql-editor/suggestions/shipql-suggestion-item.js +40 -0
  17. package/dist/components/shipql-editor/suggestions/shipql-suggestions-dropdown.d.ts +19 -0
  18. package/dist/components/shipql-editor/suggestions/shipql-suggestions-dropdown.js +128 -0
  19. package/dist/components/shipql-editor/suggestions/shipql-suggestions-footer.d.ts +11 -0
  20. package/dist/components/shipql-editor/suggestions/shipql-suggestions-footer.js +123 -0
  21. package/dist/components/shipql-editor/suggestions/shipql-suggestions-plugin.d.ts +27 -0
  22. package/dist/components/shipql-editor/suggestions/shipql-suggestions-plugin.js +407 -0
  23. package/dist/components/shipql-editor/suggestions/types.d.ts +20 -0
  24. package/dist/components/shipql-editor/suggestions/types.js +3 -0
  25. package/dist/styles.css +1 -1
  26. package/package.json +3 -3
@@ -0,0 +1,376 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Button } from '../../../components/button/index.js';
3
+ import { Icon } from '../../../components/icon/index.js';
4
+ import { Slider } from '../../../components/slider/index.js';
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
+ import { cn } from '../../../utils/cn.js';
7
+ const RECENT_MAX = 5;
8
+ const INPUT_CLASSES = 'w-40 shrink-0 rounded-4 border border-border-neutral-base-component bg-background-field-base shadow-button-neutral transition-[color,box-shadow] outline-none px-4 py-2 text-center text-xs text-foreground-neutral-base focus-visible:shadow-border-interactive-with-active [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none';
9
+ function getRecentKey(facetName) {
10
+ return `shipql-range-recent-${facetName}`;
11
+ }
12
+ function loadRecent(facetName) {
13
+ try {
14
+ const raw = localStorage.getItem(getRecentKey(facetName));
15
+ if (!raw) return [];
16
+ return JSON.parse(raw);
17
+ } catch {
18
+ return [];
19
+ }
20
+ }
21
+ function saveRecent(facetName, value) {
22
+ const existing = loadRecent(facetName).filter((v)=>v !== value);
23
+ const next = [
24
+ value,
25
+ ...existing
26
+ ].slice(0, RECENT_MAX);
27
+ try {
28
+ localStorage.setItem(getRecentKey(facetName), JSON.stringify(next));
29
+ } catch {
30
+ // ignore storage errors
31
+ }
32
+ }
33
+ function clearRecent(facetName) {
34
+ try {
35
+ localStorage.removeItem(getRecentKey(facetName));
36
+ } catch {
37
+ // ignore storage errors
38
+ }
39
+ }
40
+ function PresetRow({ value, onClick, isRecent, isHighlighted, rowRef }) {
41
+ return /*#__PURE__*/ _jsxs("button", {
42
+ ref: rowRef,
43
+ type: "button",
44
+ className: cn('flex w-full items-center gap-12 rounded-none px-8 py-6 h-28 text-left transition-colors duration-75 cursor-pointer', isHighlighted ? 'bg-background-button-transparent-hover' : 'hover:bg-background-button-transparent-hover'),
45
+ onMouseDown: (e)=>{
46
+ e.preventDefault();
47
+ onClick(value);
48
+ },
49
+ children: [
50
+ /*#__PURE__*/ _jsx(Icon, {
51
+ name: isRecent ? 'timeLine' : 'arrowRightLongFill',
52
+ className: "size-16 shrink-0 text-foreground-neutral-subtle"
53
+ }),
54
+ /*#__PURE__*/ _jsx("span", {
55
+ className: "flex-1 truncate text-sm text-foreground-neutral-subtle",
56
+ children: value
57
+ })
58
+ ]
59
+ });
60
+ }
61
+ export function ShipQLRangeFacetPanel({ facetName, config, onApply, isSelectingRef }) {
62
+ const absMin = Number(config.min);
63
+ const absMax = Number(config.max);
64
+ const [sliderValues, setSliderValues] = useState([
65
+ absMin,
66
+ absMax
67
+ ]);
68
+ const [recentValues, setRecentValues] = useState(()=>loadRecent(facetName));
69
+ const [selectedPresetIndex, setSelectedPresetIndex] = useState(-1);
70
+ const selectedPresetIndexRef = useRef(-1);
71
+ selectedPresetIndexRef.current = selectedPresetIndex;
72
+ const presetRowRefs = useRef([]);
73
+ // Local string state for inputs so mid-edit typing isn't clamped
74
+ const [minText, setMinText] = useState(String(absMin));
75
+ const [maxText, setMaxText] = useState(String(absMax));
76
+ const [lo, hi] = sliderValues;
77
+ // Keep input text in sync when slider moves
78
+ useEffect(()=>{
79
+ setMinText(String(lo));
80
+ }, [
81
+ lo
82
+ ]);
83
+ useEffect(()=>{
84
+ setMaxText(String(hi));
85
+ }, [
86
+ hi
87
+ ]);
88
+ // Hold dropdown open for any pointer interaction inside the panel
89
+ const panelRef = useRef(null);
90
+ useEffect(()=>{
91
+ const el = panelRef.current;
92
+ if (!el) return;
93
+ const onDown = ()=>{
94
+ isSelectingRef.current = true;
95
+ };
96
+ const onUp = ()=>{
97
+ // Small delay so the blur handler fires first and sees isSelectingRef=true
98
+ setTimeout(()=>{
99
+ isSelectingRef.current = false;
100
+ }, 150);
101
+ };
102
+ el.addEventListener('pointerdown', onDown);
103
+ window.addEventListener('pointerup', onUp);
104
+ return ()=>{
105
+ el.removeEventListener('pointerdown', onDown);
106
+ window.removeEventListener('pointerup', onUp);
107
+ };
108
+ }, [
109
+ isSelectingRef
110
+ ]);
111
+ const addLabel = useMemo(()=>{
112
+ if (lo === absMin && hi === absMax) return `Add ">=${lo},<=${hi}"`;
113
+ if (lo === absMin) return `Add "<=${hi}"`;
114
+ if (hi === absMax) return `Add ">=${lo}"`;
115
+ return `Add ">=${lo},<=${hi}"`;
116
+ }, [
117
+ lo,
118
+ hi,
119
+ absMin,
120
+ absMax
121
+ ]);
122
+ const buildValue = useCallback(()=>{
123
+ if (lo === absMin && hi === absMax) return `[${lo} TO ${hi}]`;
124
+ if (lo === absMin) return `<=${hi}`;
125
+ if (hi === absMax) return `>=${lo}`;
126
+ return `[${lo} TO ${hi}]`;
127
+ }, [
128
+ lo,
129
+ hi,
130
+ absMin,
131
+ absMax
132
+ ]);
133
+ const handleApplyRange = useCallback(()=>{
134
+ const value = buildValue();
135
+ saveRecent(facetName, value);
136
+ setRecentValues(loadRecent(facetName));
137
+ onApply(value);
138
+ }, [
139
+ buildValue,
140
+ facetName,
141
+ onApply
142
+ ]);
143
+ const handlePreset = useCallback((preset)=>{
144
+ saveRecent(facetName, preset);
145
+ setRecentValues(loadRecent(facetName));
146
+ onApply(preset);
147
+ }, [
148
+ facetName,
149
+ onApply
150
+ ]);
151
+ const handleClearRecent = useCallback((e)=>{
152
+ e.preventDefault();
153
+ clearRecent(facetName);
154
+ setRecentValues([]);
155
+ }, [
156
+ facetName
157
+ ]);
158
+ // Build flat list of navigable preset values (recent + common)
159
+ const navigableItems = useMemo(()=>{
160
+ const items = [];
161
+ for (const v of recentValues.slice(0, 3))items.push(v);
162
+ if (config.presets) {
163
+ for (const v of config.presets)items.push(v);
164
+ }
165
+ return items;
166
+ }, [
167
+ recentValues,
168
+ config.presets
169
+ ]);
170
+ // Keyboard navigation for preset/recent items (capture phase to fire before Lexical)
171
+ useEffect(()=>{
172
+ if (navigableItems.length === 0) return;
173
+ const handleKeyDown = (e)=>{
174
+ // Don't intercept when user is editing min/max inputs
175
+ if (document.activeElement instanceof HTMLInputElement) return;
176
+ if (e.key === 'ArrowDown') {
177
+ e.preventDefault();
178
+ e.stopPropagation();
179
+ setSelectedPresetIndex((prev)=>prev + 1 >= navigableItems.length ? 0 : prev + 1);
180
+ } else if (e.key === 'ArrowUp') {
181
+ e.preventDefault();
182
+ e.stopPropagation();
183
+ setSelectedPresetIndex((prev)=>prev - 1 < 0 ? navigableItems.length - 1 : prev - 1);
184
+ } else if (e.key === 'Enter') {
185
+ const idx = selectedPresetIndexRef.current;
186
+ if (idx < 0) return;
187
+ e.preventDefault();
188
+ e.stopPropagation();
189
+ const value = navigableItems[idx];
190
+ if (value) handlePreset(value);
191
+ }
192
+ };
193
+ window.addEventListener('keydown', handleKeyDown, true);
194
+ return ()=>window.removeEventListener('keydown', handleKeyDown, true);
195
+ }, [
196
+ navigableItems,
197
+ handlePreset
198
+ ]);
199
+ // Scroll selected preset into view
200
+ useEffect(()=>{
201
+ const el = presetRowRefs.current[selectedPresetIndex];
202
+ if (el) el.scrollIntoView({
203
+ behavior: 'smooth',
204
+ block: 'nearest'
205
+ });
206
+ }, [
207
+ selectedPresetIndex
208
+ ]);
209
+ // Commit min input on blur or Enter
210
+ const commitMin = useCallback(()=>{
211
+ const v = Number(minText);
212
+ if (!Number.isNaN(v)) {
213
+ const clamped = Math.min(Math.max(v, absMin), hi);
214
+ setSliderValues([
215
+ clamped,
216
+ hi
217
+ ]);
218
+ setMinText(String(clamped));
219
+ } else {
220
+ setMinText(String(lo));
221
+ }
222
+ }, [
223
+ minText,
224
+ absMin,
225
+ hi,
226
+ lo
227
+ ]);
228
+ // Commit max input on blur or Enter
229
+ const commitMax = useCallback(()=>{
230
+ const v = Number(maxText);
231
+ if (!Number.isNaN(v)) {
232
+ const clamped = Math.max(Math.min(v, absMax), lo);
233
+ setSliderValues([
234
+ lo,
235
+ clamped
236
+ ]);
237
+ setMaxText(String(clamped));
238
+ } else {
239
+ setMaxText(String(hi));
240
+ }
241
+ }, [
242
+ maxText,
243
+ absMax,
244
+ lo,
245
+ hi
246
+ ]);
247
+ return /*#__PURE__*/ _jsxs("div", {
248
+ ref: panelRef,
249
+ className: "flex flex-col",
250
+ children: [
251
+ /*#__PURE__*/ _jsx("div", {
252
+ className: "flex w-full items-center px-8 h-30 shrink-0 border-b border-border-neutral-base-component",
253
+ children: /*#__PURE__*/ _jsx("span", {
254
+ className: "text-xs font-normal uppercase text-foreground-neutral-muted",
255
+ children: facetName
256
+ })
257
+ }),
258
+ /*#__PURE__*/ _jsxs("div", {
259
+ className: "p-8 space-y-2",
260
+ children: [
261
+ /*#__PURE__*/ _jsxs("div", {
262
+ className: "flex items-center gap-12",
263
+ children: [
264
+ /*#__PURE__*/ _jsx("input", {
265
+ type: "number",
266
+ value: minText,
267
+ onChange: (e)=>setMinText(e.target.value),
268
+ onBlur: commitMin,
269
+ onKeyDown: (e)=>{
270
+ if (e.key === 'Enter') commitMin();
271
+ },
272
+ className: INPUT_CLASSES
273
+ }),
274
+ /*#__PURE__*/ _jsx(Slider, {
275
+ className: "flex-1",
276
+ min: absMin,
277
+ max: absMax,
278
+ value: sliderValues,
279
+ onValueChange: (vals)=>{
280
+ const newLo = vals[0];
281
+ const newHi = vals[1];
282
+ if (newLo !== undefined && newHi !== undefined) {
283
+ setSliderValues([
284
+ newLo,
285
+ newHi
286
+ ]);
287
+ }
288
+ }
289
+ }),
290
+ /*#__PURE__*/ _jsx("input", {
291
+ type: "number",
292
+ value: maxText,
293
+ onChange: (e)=>setMaxText(e.target.value),
294
+ onBlur: commitMax,
295
+ onKeyDown: (e)=>{
296
+ if (e.key === 'Enter') commitMax();
297
+ },
298
+ className: INPUT_CLASSES
299
+ })
300
+ ]
301
+ }),
302
+ /*#__PURE__*/ _jsx(Button, {
303
+ type: "button",
304
+ onMouseDown: (e)=>{
305
+ e.preventDefault();
306
+ handleApplyRange();
307
+ },
308
+ variant: "secondary",
309
+ size: "sm",
310
+ className: "mt-6 w-full justify-start shadow-none rounded-4!",
311
+ iconLeft: "addLine",
312
+ children: addLabel
313
+ })
314
+ ]
315
+ }),
316
+ (recentValues.length > 0 || config.presets && config.presets.length > 0) && /*#__PURE__*/ _jsxs("div", {
317
+ className: "border-t border-border-neutral-base-component",
318
+ children: [
319
+ recentValues.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
320
+ children: [
321
+ /*#__PURE__*/ _jsxs("div", {
322
+ className: "flex w-full items-center px-8 h-30 shrink-0",
323
+ children: [
324
+ /*#__PURE__*/ _jsx("span", {
325
+ className: "flex-1 text-xs font-normal uppercase text-foreground-neutral-muted",
326
+ children: "Recent"
327
+ }),
328
+ /*#__PURE__*/ _jsx(Button, {
329
+ type: "button",
330
+ variant: "transparentMuted",
331
+ size: "xs",
332
+ onMouseDown: handleClearRecent,
333
+ children: "Clear"
334
+ })
335
+ ]
336
+ }),
337
+ recentValues.slice(0, 3).map((v, i)=>/*#__PURE__*/ _jsx(PresetRow, {
338
+ value: v,
339
+ onClick: handlePreset,
340
+ isRecent: true,
341
+ isHighlighted: selectedPresetIndex === i,
342
+ rowRef: (el)=>{
343
+ presetRowRefs.current[i] = el;
344
+ }
345
+ }, v))
346
+ ]
347
+ }),
348
+ config.presets && config.presets.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
349
+ children: [
350
+ /*#__PURE__*/ _jsx("div", {
351
+ className: "flex w-full items-center px-8 h-30 shrink-0",
352
+ children: /*#__PURE__*/ _jsx("span", {
353
+ className: "text-xs font-normal uppercase text-foreground-neutral-muted",
354
+ children: "Common"
355
+ })
356
+ }),
357
+ config.presets.map((v, i)=>{
358
+ const idx = recentValues.slice(0, 3).length + i;
359
+ return /*#__PURE__*/ _jsx(PresetRow, {
360
+ value: v,
361
+ onClick: handlePreset,
362
+ isHighlighted: selectedPresetIndex === idx,
363
+ rowRef: (el)=>{
364
+ presetRowRefs.current[idx] = el;
365
+ }
366
+ }, v);
367
+ })
368
+ ]
369
+ })
370
+ ]
371
+ })
372
+ ]
373
+ });
374
+ }
375
+
376
+ //# sourceMappingURL=shipql-range-facet-panel.js.map
@@ -0,0 +1,11 @@
1
+ import type { SuggestionItem } from './types';
2
+ interface ShipQLSuggestionItemProps {
3
+ item: SuggestionItem;
4
+ isHighlighted: boolean;
5
+ isNegated?: boolean;
6
+ onMouseDown: (value: string) => void;
7
+ itemRef?: (el: HTMLButtonElement | null) => void;
8
+ }
9
+ export declare function ShipQLSuggestionItem({ item, isHighlighted, isNegated, onMouseDown, itemRef, }: ShipQLSuggestionItemProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=shipql-suggestion-item.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../../utils/cn.js';
3
+ export function ShipQLSuggestionItem({ item, isHighlighted, isNegated, onMouseDown, itemRef }) {
4
+ if (item.type === 'section-header') {
5
+ return /*#__PURE__*/ _jsx("div", {
6
+ className: "flex w-full items-center px-8 h-30 shrink-0",
7
+ children: /*#__PURE__*/ _jsx("span", {
8
+ className: "text-xs font-normal uppercase text-foreground-neutral-muted",
9
+ children: item.label
10
+ })
11
+ });
12
+ }
13
+ return /*#__PURE__*/ _jsxs("button", {
14
+ ref: itemRef,
15
+ type: "button",
16
+ onMouseDown: (e)=>{
17
+ e.preventDefault();
18
+ onMouseDown(item.value);
19
+ },
20
+ className: cn('flex w-full items-center gap-12 rounded-none px-8 py-6 h-24 text-left transition-colors duration-75 cursor-pointer', isHighlighted ? 'bg-background-button-transparent-hover' : 'hover:bg-background-button-transparent-hover'),
21
+ children: [
22
+ /*#__PURE__*/ _jsxs("div", {
23
+ className: "flex min-w-0 flex-1 items-center gap-12",
24
+ children: [
25
+ item.icon,
26
+ /*#__PURE__*/ _jsx("span", {
27
+ className: cn('flex-1 truncate text-sm', isNegated ? 'text-foreground-highlights-interactive' : item.selected ? 'text-foreground-neutral-base' : 'text-foreground-neutral-subtle'),
28
+ children: isNegated ? `-${item.label}` : item.label
29
+ })
30
+ ]
31
+ }),
32
+ isHighlighted && /*#__PURE__*/ _jsx("span", {
33
+ className: "shrink-0 text-xs text-foreground-neutral-muted font-medium select-none",
34
+ children: "↵"
35
+ })
36
+ ]
37
+ });
38
+ }
39
+
40
+ //# sourceMappingURL=shipql-suggestion-item.js.map
@@ -0,0 +1,19 @@
1
+ import { type SyntaxHintMode } from './shipql-suggestions-footer';
2
+ import type { SuggestionItem } from './types';
3
+ interface ShipQLSuggestionsDropdownProps {
4
+ items: SuggestionItem[];
5
+ selectedIndex: number;
6
+ isSelectingRef: React.RefObject<boolean>;
7
+ onSelect: (value: string) => void;
8
+ isLoading?: boolean;
9
+ isNegated: boolean;
10
+ onToggleNegate: (negated: boolean) => void;
11
+ showValueActions: boolean;
12
+ showSyntaxHelp: boolean;
13
+ onToggleSyntaxHelp: () => void;
14
+ isError?: boolean;
15
+ syntaxHintMode: SyntaxHintMode;
16
+ }
17
+ export declare function ShipQLSuggestionsDropdown({ items, selectedIndex, isSelectingRef, onSelect, isLoading, isNegated, onToggleNegate, showValueActions, showSyntaxHelp, onToggleSyntaxHelp, isError, syntaxHintMode, }: ShipQLSuggestionsDropdownProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=shipql-suggestions-dropdown.d.ts.map
@@ -0,0 +1,128 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PopoverContent } from '../../../components/popover/index.js';
3
+ import { ScrollArea } from '../../../components/scroll-area/index.js';
4
+ import { Skeleton } from '../../../components/skeleton/index.js';
5
+ import { useCallback, useEffect, useRef } from 'react';
6
+ import { ShipQLRangeFacetPanel } from './shipql-range-facet-panel.js';
7
+ import { ShipQLSuggestionItem } from './shipql-suggestion-item.js';
8
+ import { ShipQLSuggestionsFooter } from './shipql-suggestions-footer.js';
9
+ export function ShipQLSuggestionsDropdown({ items, selectedIndex, isSelectingRef, onSelect, isLoading, isNegated, onToggleNegate, showValueActions, showSyntaxHelp, onToggleSyntaxHelp, isError, syntaxHintMode }) {
10
+ const itemRefs = useRef([]);
11
+ useEffect(()=>{
12
+ const el = itemRefs.current[selectedIndex];
13
+ if (el) el.scrollIntoView({
14
+ behavior: 'smooth',
15
+ block: 'nearest'
16
+ });
17
+ }, [
18
+ selectedIndex
19
+ ]);
20
+ // Shift key toggles negation while dropdown is visible
21
+ useEffect(()=>{
22
+ if (!showValueActions) return;
23
+ const handleKeyDown = (e)=>{
24
+ if (e.key === 'Shift') onToggleNegate(true);
25
+ };
26
+ const handleKeyUp = (e)=>{
27
+ if (e.key === 'Shift') onToggleNegate(false);
28
+ };
29
+ window.addEventListener('keydown', handleKeyDown);
30
+ window.addEventListener('keyup', handleKeyUp);
31
+ return ()=>{
32
+ window.removeEventListener('keydown', handleKeyDown);
33
+ window.removeEventListener('keyup', handleKeyUp);
34
+ };
35
+ }, [
36
+ showValueActions,
37
+ onToggleNegate
38
+ ]);
39
+ // Reset negation when showValueActions turns off
40
+ useEffect(()=>{
41
+ if (!showValueActions) onToggleNegate(false);
42
+ }, [
43
+ showValueActions,
44
+ onToggleNegate
45
+ ]);
46
+ const handleMouseDown = useCallback((value)=>{
47
+ isSelectingRef.current = true;
48
+ onSelect(value);
49
+ setTimeout(()=>{
50
+ isSelectingRef.current = false;
51
+ }, 150);
52
+ }, [
53
+ isSelectingRef,
54
+ onSelect
55
+ ]);
56
+ const firstItem = items.length === 1 ? items[0] : undefined;
57
+ const rangeItem = firstItem?.type === 'range-slider' && firstItem.facetName && firstItem.rangeFacetConfig ? firstItem : null;
58
+ const popoverContent = rangeItem ? /*#__PURE__*/ _jsxs("div", {
59
+ className: "flex flex-col overflow-hidden rounded-8 bg-background-neutral-base shadow-tooltip",
60
+ children: [
61
+ /*#__PURE__*/ _jsx(ScrollArea, {
62
+ className: "flex-1 min-h-0 overflow-y-auto scrollbar",
63
+ children: /*#__PURE__*/ _jsx(ShipQLRangeFacetPanel, {
64
+ facetName: rangeItem.facetName,
65
+ config: rangeItem.rangeFacetConfig,
66
+ isSelectingRef: isSelectingRef,
67
+ onApply: onSelect
68
+ })
69
+ }),
70
+ /*#__PURE__*/ _jsx(ShipQLSuggestionsFooter, {
71
+ showValueActions: false,
72
+ showSyntaxHelp: showSyntaxHelp,
73
+ onToggleSyntaxHelp: onToggleSyntaxHelp,
74
+ isError: isError,
75
+ syntaxHintMode: "range"
76
+ })
77
+ ]
78
+ }) : /*#__PURE__*/ _jsxs("div", {
79
+ className: "flex flex-col overflow-hidden rounded-8 bg-background-neutral-base shadow-tooltip max-h-[min(70vh,320px)] min-h-0",
80
+ children: [
81
+ /*#__PURE__*/ _jsx(ScrollArea, {
82
+ className: "flex-1 min-h-0 overflow-y-auto scrollbar",
83
+ children: /*#__PURE__*/ _jsx("div", {
84
+ className: "flex flex-col",
85
+ children: isLoading && items.length === 0 ? /*#__PURE__*/ _jsx("div", {
86
+ className: "px-8 py-6 flex items-center",
87
+ children: /*#__PURE__*/ _jsx(Skeleton, {
88
+ className: "w-60 h-20"
89
+ })
90
+ }) : items.length === 0 ? /*#__PURE__*/ _jsx("div", {
91
+ className: "px-8 py-6 text-sm text-foreground-neutral-muted",
92
+ children: "No suggestions found"
93
+ }) : items.map((item, index)=>/*#__PURE__*/ _jsx(ShipQLSuggestionItem, {
94
+ item: item,
95
+ isHighlighted: selectedIndex === index,
96
+ isNegated: isNegated && showValueActions,
97
+ onMouseDown: handleMouseDown,
98
+ itemRef: (el)=>{
99
+ itemRefs.current[index] = el;
100
+ }
101
+ }, item.value))
102
+ })
103
+ }),
104
+ /*#__PURE__*/ _jsx(ShipQLSuggestionsFooter, {
105
+ showValueActions: showValueActions,
106
+ showSyntaxHelp: showSyntaxHelp,
107
+ onToggleSyntaxHelp: onToggleSyntaxHelp,
108
+ isError: isError,
109
+ syntaxHintMode: syntaxHintMode
110
+ })
111
+ ]
112
+ });
113
+ return /*#__PURE__*/ _jsx(PopoverContent, {
114
+ align: "start",
115
+ sideOffset: 4,
116
+ className: "p-0 w-(--radix-popover-trigger-width) rounded-8",
117
+ onOpenAutoFocus: (e)=>e.preventDefault(),
118
+ onInteractOutside: (e)=>{
119
+ if (isSelectingRef.current) e.preventDefault();
120
+ },
121
+ onPointerDownOutside: (e)=>{
122
+ if (isSelectingRef.current) e.preventDefault();
123
+ },
124
+ children: popoverContent
125
+ });
126
+ }
127
+
128
+ //# sourceMappingURL=shipql-suggestions-dropdown.js.map
@@ -0,0 +1,11 @@
1
+ export type SyntaxHintMode = 'value' | 'range';
2
+ interface ShipQLSuggestionsFooterProps {
3
+ showValueActions: boolean;
4
+ showSyntaxHelp: boolean;
5
+ onToggleSyntaxHelp: () => void;
6
+ isError?: boolean;
7
+ syntaxHintMode: SyntaxHintMode;
8
+ }
9
+ export declare function ShipQLSuggestionsFooter({ showValueActions, showSyntaxHelp, onToggleSyntaxHelp, isError, syntaxHintMode, }: ShipQLSuggestionsFooterProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=shipql-suggestions-footer.d.ts.map