@upstash/react-redis-browser 0.1.9 → 0.1.11-canary

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,9 +1,97 @@
1
1
  // src/components/databrowser/index.tsx
2
- import { useEffect as useEffect10, useMemo as useMemo6 } from "react";
2
+ import { useEffect as useEffect11, useMemo as useMemo8 } from "react";
3
3
 
4
4
  // src/store.tsx
5
- import { createContext, useContext, useMemo, useState as useState2 } from "react";
5
+ import { createContext, useContext, useMemo } from "react";
6
6
  import { create, useStore } from "zustand";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var DatabrowserContext = createContext(void 0);
9
+ var DatabrowserProvider = ({ children }) => {
10
+ const store = useMemo(() => createDatabrowserStore(), []);
11
+ return /* @__PURE__ */ jsx(DatabrowserContext.Provider, { value: { store }, children });
12
+ };
13
+ var useDatabrowser = () => {
14
+ const context = useContext(DatabrowserContext);
15
+ if (!context) {
16
+ throw new Error("useDatabrowser must be used within a DatabrowserProvider");
17
+ }
18
+ return context;
19
+ };
20
+ var useDatabrowserStore = () => {
21
+ const { store } = useDatabrowser();
22
+ return useStore(store);
23
+ };
24
+ var createDatabrowserStore = () => create((set, get) => ({
25
+ selectedTab: void 0,
26
+ tabs: {},
27
+ addTab: () => {
28
+ const id = crypto.randomUUID();
29
+ const newTabData = {
30
+ selectedKey: void 0,
31
+ search: { key: "", type: void 0 }
32
+ };
33
+ set((old) => ({
34
+ tabs: { ...old.tabs, [id]: newTabData },
35
+ selectedTab: old.selectedTab === void 0 ? id : old.selectedTab
36
+ }));
37
+ },
38
+ removeTab: (id) => {
39
+ set((old) => {
40
+ const newTabs = { ...old.tabs };
41
+ delete newTabs[id];
42
+ let selectedTab = old.selectedTab;
43
+ if (selectedTab === id) {
44
+ const tabIds = Object.keys(newTabs);
45
+ selectedTab = tabIds.length > 0 ? tabIds[0] : void 0;
46
+ }
47
+ return { tabs: newTabs, selectedTab };
48
+ });
49
+ },
50
+ selectTab: (id) => {
51
+ set({ selectedTab: id });
52
+ },
53
+ getSelectedKey: (tabId) => {
54
+ return get().tabs[tabId]?.selectedKey;
55
+ },
56
+ setSelectedKey: (tabId, key) => {
57
+ set((old) => ({
58
+ ...old,
59
+ tabs: {
60
+ ...old.tabs,
61
+ [tabId]: { ...old.tabs[tabId], selectedKey: key, selectedListItem: void 0 }
62
+ }
63
+ }));
64
+ },
65
+ setSelectedListItem: (tabId, item) => {
66
+ set((old) => ({
67
+ ...old,
68
+ tabs: { ...old.tabs, [tabId]: { ...old.tabs[tabId], selectedListItem: item } }
69
+ }));
70
+ },
71
+ setSearch: (tabId, search) => set((old) => ({ ...old, tabs: { ...old.tabs, [tabId]: { ...old.tabs[tabId], search } } })),
72
+ setSearchKey: (tabId, key) => set((old) => ({
73
+ ...old,
74
+ tabs: {
75
+ ...old.tabs,
76
+ [tabId]: { ...old.tabs[tabId], search: { ...old.tabs[tabId].search, key } }
77
+ }
78
+ })),
79
+ setSearchType: (tabId, type) => set((old) => ({
80
+ ...old,
81
+ tabs: {
82
+ ...old.tabs,
83
+ [tabId]: { ...old.tabs[tabId], search: { ...old.tabs[tabId].search, type } }
84
+ }
85
+ })),
86
+ searchHistory: [],
87
+ addSearchHistory: (key) => {
88
+ set((old) => ({ ...old, searchHistory: [key, ...old.searchHistory] }));
89
+ }
90
+ }));
91
+
92
+ // src/components/databrowser/index.tsx
93
+ import { TooltipProvider } from "@radix-ui/react-tooltip";
94
+ import { QueryClientProvider } from "@tanstack/react-query";
7
95
 
8
96
  // src/lib/clients.ts
9
97
  import { MutationCache, QueryCache, QueryClient } from "@tanstack/react-query";
@@ -180,140 +268,53 @@ var queryClient = new QueryClient({
180
268
  })
181
269
  });
182
270
 
183
- // src/store.tsx
184
- import { jsx } from "react/jsx-runtime";
185
- var DatabrowserContext = createContext(void 0);
186
- var DatabrowserProvider = ({
271
+ // src/redis-context.tsx
272
+ import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
273
+ import { jsx as jsx2 } from "react/jsx-runtime";
274
+ var RedisContext = createContext2(void 0);
275
+ var RedisProvider = ({
187
276
  children,
188
277
  redisCredentials
189
278
  }) => {
190
- const redisInstance = useMemo(() => redisClient({ credentials: redisCredentials, pipelining: true }), [redisCredentials]);
191
- const redisInstanceNoPipeline = useMemo(() => redisClient({ credentials: redisCredentials, pipelining: false }), [redisCredentials]);
192
- const [store] = useState2(() => {
193
- return createDatabrowserStore();
194
- });
195
- return /* @__PURE__ */ jsx(DatabrowserContext.Provider, { value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline, store }, children });
279
+ const redisInstance = useMemo2(
280
+ () => redisClient({ credentials: redisCredentials, pipelining: true }),
281
+ [redisCredentials]
282
+ );
283
+ const redisInstanceNoPipeline = useMemo2(
284
+ () => redisClient({ credentials: redisCredentials, pipelining: false }),
285
+ [redisCredentials]
286
+ );
287
+ return /* @__PURE__ */ jsx2(
288
+ RedisContext.Provider,
289
+ {
290
+ value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline },
291
+ children
292
+ }
293
+ );
196
294
  };
197
- var useDatabrowser = () => {
198
- const context = useContext(DatabrowserContext);
295
+ var useRedis = () => {
296
+ const context = useContext2(RedisContext);
199
297
  if (!context) {
200
- throw new Error("useDatabrowser must be used within a DatabrowserProvider");
298
+ throw new Error("useRedis must be used within a RedisProvider");
201
299
  }
202
300
  return context;
203
301
  };
204
- var useDatabrowserStore = () => {
205
- const { store } = useDatabrowser();
206
- return useStore(store);
207
- };
208
- var createDatabrowserStore = () => create((set) => ({
209
- selectedKey: void 0,
210
- setSelectedKey: (key) => {
211
- set((old) => ({ ...old, selectedKey: key, selectedListItem: void 0 }));
212
- },
213
- selectedListItem: void 0,
214
- setSelectedListItem: (item) => {
215
- set((old) => ({ ...old, selectedListItem: item }));
216
- },
217
- search: { key: "", type: "string" },
218
- setSearch: (search) => set({ search }),
219
- setSearchKey: (key) => set((state) => ({ search: { ...state.search, key } })),
220
- setSearchType: (type) => set((state) => ({ search: { ...state.search, type } }))
221
- }));
222
302
 
223
- // src/components/databrowser/index.tsx
224
- import { TooltipProvider } from "@radix-ui/react-tooltip";
225
- import { IconDotsVertical as IconDotsVertical2 } from "@tabler/icons-react";
226
- import { QueryClientProvider } from "@tanstack/react-query";
303
+ // src/components/databrowser/components/databrowser-instance.tsx
227
304
  import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
228
305
 
229
- // src/components/ui/toaster.tsx
230
- import { Portal } from "@radix-ui/react-portal";
231
-
232
- // src/lib/portal-root.ts
233
- var root;
234
- if (typeof document !== "undefined") {
235
- const id = "react-redis-browser-portal-root";
236
- root = document.querySelector(`#${id}`) ?? document.createElement("div");
237
- root.classList.add("ups-db");
238
- root.id = "react-redis-browser-portal-root";
239
- document.body.append(root);
240
- }
241
- var portalRoot = root;
242
-
243
- // src/components/ui/toast.tsx
244
- import * as React2 from "react";
245
- import { Cross2Icon } from "@radix-ui/react-icons";
246
- import * as ToastPrimitives from "@radix-ui/react-toast";
247
-
248
- // node_modules/class-variance-authority/node_modules/clsx/dist/clsx.mjs
249
- function r(e) {
250
- var t, f, n = "";
251
- if ("string" == typeof e || "number" == typeof e) n += e;
252
- else if ("object" == typeof e) if (Array.isArray(e)) for (t = 0; t < e.length; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
253
- else for (t in e) e[t] && (n && (n += " "), n += t);
254
- return n;
255
- }
256
- function clsx() {
257
- for (var e, t, f = 0, n = ""; f < arguments.length; ) (e = arguments[f++]) && (t = r(e)) && (n && (n += " "), n += t);
258
- return n;
259
- }
260
-
261
- // node_modules/class-variance-authority/dist/index.mjs
262
- var falsyToString = (value) => typeof value === "boolean" ? "".concat(value) : value === 0 ? "0" : value;
263
- var cx = clsx;
264
- var cva = (base, config) => {
265
- return (props) => {
266
- var ref;
267
- if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
268
- const { variants, defaultVariants } = config;
269
- const getVariantClassNames = Object.keys(variants).map((variant) => {
270
- const variantProp = props === null || props === void 0 ? void 0 : props[variant];
271
- const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
272
- if (variantProp === null) return null;
273
- const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
274
- return variants[variant][variantKey];
275
- });
276
- const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
277
- let [key, value] = param;
278
- if (value === void 0) {
279
- return acc;
280
- }
281
- acc[key] = value;
282
- return acc;
283
- }, {});
284
- const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (ref = config.compoundVariants) === null || ref === void 0 ? void 0 : ref.reduce((acc, param1) => {
285
- let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param1;
286
- return Object.entries(compoundVariantOptions).every((param) => {
287
- let [key, value] = param;
288
- return Array.isArray(value) ? value.includes({
289
- ...defaultVariants,
290
- ...propsWithoutUndefined
291
- }[key]) : {
292
- ...defaultVariants,
293
- ...propsWithoutUndefined
294
- }[key] === value;
295
- }) ? [
296
- ...acc,
297
- cvClass,
298
- cvClassName
299
- ] : acc;
300
- }, []);
301
- return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
302
- };
303
- };
304
-
305
306
  // node_modules/clsx/dist/clsx.mjs
306
- function r2(e) {
307
+ function r(e) {
307
308
  var t, f, n = "";
308
309
  if ("string" == typeof e || "number" == typeof e) n += e;
309
310
  else if ("object" == typeof e) if (Array.isArray(e)) {
310
311
  var o = e.length;
311
- for (t = 0; t < o; t++) e[t] && (f = r2(e[t])) && (n && (n += " "), n += f);
312
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
312
313
  } else for (f in e) e[f] && (n && (n += " "), n += f);
313
314
  return n;
314
315
  }
315
- function clsx2() {
316
- for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r2(e)) && (n && (n += " "), n += t);
316
+ function clsx() {
317
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
317
318
  return n;
318
319
  }
319
320
 
@@ -2779,7 +2780,7 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
2779
2780
 
2780
2781
  // src/lib/utils.ts
2781
2782
  function cn(...inputs) {
2782
- return twMerge(clsx2(inputs));
2783
+ return twMerge(clsx(inputs));
2783
2784
  }
2784
2785
  function formatNumber(value) {
2785
2786
  const intl = new Intl.NumberFormat("en-US");
@@ -2811,10 +2812,86 @@ function formatTime(seconds) {
2811
2812
  return parts.slice(0, 1).join(" ");
2812
2813
  }
2813
2814
 
2815
+ // src/components/ui/toaster.tsx
2816
+ import { Portal } from "@radix-ui/react-portal";
2817
+
2818
+ // src/lib/portal-root.ts
2819
+ var root;
2820
+ if (typeof document !== "undefined") {
2821
+ const id = "react-redis-browser-portal-root";
2822
+ root = document.querySelector(`#${id}`) ?? document.createElement("div");
2823
+ root.classList.add("ups-db");
2824
+ root.id = "react-redis-browser-portal-root";
2825
+ document.body.append(root);
2826
+ }
2827
+ var portalRoot = root;
2828
+
2814
2829
  // src/components/ui/toast.tsx
2815
- import { jsx as jsx2 } from "react/jsx-runtime";
2830
+ import * as React2 from "react";
2831
+ import { Cross2Icon } from "@radix-ui/react-icons";
2832
+ import * as ToastPrimitives from "@radix-ui/react-toast";
2833
+
2834
+ // node_modules/class-variance-authority/node_modules/clsx/dist/clsx.mjs
2835
+ function r2(e) {
2836
+ var t, f, n = "";
2837
+ if ("string" == typeof e || "number" == typeof e) n += e;
2838
+ else if ("object" == typeof e) if (Array.isArray(e)) for (t = 0; t < e.length; t++) e[t] && (f = r2(e[t])) && (n && (n += " "), n += f);
2839
+ else for (t in e) e[t] && (n && (n += " "), n += t);
2840
+ return n;
2841
+ }
2842
+ function clsx2() {
2843
+ for (var e, t, f = 0, n = ""; f < arguments.length; ) (e = arguments[f++]) && (t = r2(e)) && (n && (n += " "), n += t);
2844
+ return n;
2845
+ }
2846
+
2847
+ // node_modules/class-variance-authority/dist/index.mjs
2848
+ var falsyToString = (value) => typeof value === "boolean" ? "".concat(value) : value === 0 ? "0" : value;
2849
+ var cx = clsx2;
2850
+ var cva = (base, config) => {
2851
+ return (props) => {
2852
+ var ref;
2853
+ if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
2854
+ const { variants, defaultVariants } = config;
2855
+ const getVariantClassNames = Object.keys(variants).map((variant) => {
2856
+ const variantProp = props === null || props === void 0 ? void 0 : props[variant];
2857
+ const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
2858
+ if (variantProp === null) return null;
2859
+ const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
2860
+ return variants[variant][variantKey];
2861
+ });
2862
+ const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
2863
+ let [key, value] = param;
2864
+ if (value === void 0) {
2865
+ return acc;
2866
+ }
2867
+ acc[key] = value;
2868
+ return acc;
2869
+ }, {});
2870
+ const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (ref = config.compoundVariants) === null || ref === void 0 ? void 0 : ref.reduce((acc, param1) => {
2871
+ let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param1;
2872
+ return Object.entries(compoundVariantOptions).every((param) => {
2873
+ let [key, value] = param;
2874
+ return Array.isArray(value) ? value.includes({
2875
+ ...defaultVariants,
2876
+ ...propsWithoutUndefined
2877
+ }[key]) : {
2878
+ ...defaultVariants,
2879
+ ...propsWithoutUndefined
2880
+ }[key] === value;
2881
+ }) ? [
2882
+ ...acc,
2883
+ cvClass,
2884
+ cvClassName
2885
+ ] : acc;
2886
+ }, []);
2887
+ return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
2888
+ };
2889
+ };
2890
+
2891
+ // src/components/ui/toast.tsx
2892
+ import { jsx as jsx3 } from "react/jsx-runtime";
2816
2893
  var ToastProvider = ToastPrimitives.Provider;
2817
- var ToastViewport = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
2894
+ var ToastViewport = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
2818
2895
  ToastPrimitives.Viewport,
2819
2896
  {
2820
2897
  ref,
@@ -2841,7 +2918,7 @@ var toastVariants = cva(
2841
2918
  }
2842
2919
  );
2843
2920
  var Toast = React2.forwardRef(({ className, variant, ...props }, ref) => {
2844
- return /* @__PURE__ */ jsx2(
2921
+ return /* @__PURE__ */ jsx3(
2845
2922
  ToastPrimitives.Root,
2846
2923
  {
2847
2924
  ref,
@@ -2851,7 +2928,7 @@ var Toast = React2.forwardRef(({ className, variant, ...props }, ref) => {
2851
2928
  );
2852
2929
  });
2853
2930
  Toast.displayName = ToastPrimitives.Root.displayName;
2854
- var ToastAction = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
2931
+ var ToastAction = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
2855
2932
  ToastPrimitives.Action,
2856
2933
  {
2857
2934
  ref,
@@ -2863,7 +2940,7 @@ var ToastAction = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
2863
2940
  }
2864
2941
  ));
2865
2942
  ToastAction.displayName = ToastPrimitives.Action.displayName;
2866
- var ToastClose = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
2943
+ var ToastClose = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
2867
2944
  ToastPrimitives.Close,
2868
2945
  {
2869
2946
  ref,
@@ -2873,11 +2950,11 @@ var ToastClose = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE_
2873
2950
  ),
2874
2951
  "toast-close": "",
2875
2952
  ...props,
2876
- children: /* @__PURE__ */ jsx2(Cross2Icon, { className: "size-4" })
2953
+ children: /* @__PURE__ */ jsx3(Cross2Icon, { className: "size-4" })
2877
2954
  }
2878
2955
  ));
2879
2956
  ToastClose.displayName = ToastPrimitives.Close.displayName;
2880
- var ToastTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
2957
+ var ToastTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
2881
2958
  ToastPrimitives.Title,
2882
2959
  {
2883
2960
  ref,
@@ -2886,7 +2963,7 @@ var ToastTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE_
2886
2963
  }
2887
2964
  ));
2888
2965
  ToastTitle.displayName = ToastPrimitives.Title.displayName;
2889
- var ToastDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
2966
+ var ToastDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
2890
2967
  ToastPrimitives.Description,
2891
2968
  {
2892
2969
  ref,
@@ -2897,37 +2974,64 @@ var ToastDescription = React2.forwardRef(({ className, ...props }, ref) => /* @_
2897
2974
  ToastDescription.displayName = ToastPrimitives.Description.displayName;
2898
2975
 
2899
2976
  // src/components/ui/toaster.tsx
2900
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
2977
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
2901
2978
  function Toaster() {
2902
2979
  const { toasts } = useToast();
2903
- return /* @__PURE__ */ jsx3(Portal, { container: portalRoot, children: /* @__PURE__ */ jsxs(ToastProvider, { children: [
2980
+ return /* @__PURE__ */ jsx4(Portal, { container: portalRoot, children: /* @__PURE__ */ jsxs(ToastProvider, { children: [
2904
2981
  toasts.map(({ id, title, description, action, ...props }) => /* @__PURE__ */ jsxs(Toast, { ...props, children: [
2905
2982
  /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
2906
- title && /* @__PURE__ */ jsx3(ToastTitle, { children: title }),
2907
- description && /* @__PURE__ */ jsx3(ToastDescription, { children: description })
2983
+ title && /* @__PURE__ */ jsx4(ToastTitle, { children: title }),
2984
+ description && /* @__PURE__ */ jsx4(ToastDescription, { children: description })
2908
2985
  ] }),
2909
2986
  action,
2910
- /* @__PURE__ */ jsx3(ToastClose, {})
2987
+ /* @__PURE__ */ jsx4(ToastClose, {})
2911
2988
  ] }, id)),
2912
- /* @__PURE__ */ jsx3(ToastViewport, {})
2989
+ /* @__PURE__ */ jsx4(ToastViewport, {})
2913
2990
  ] }) });
2914
2991
  }
2915
2992
 
2916
2993
  // src/components/databrowser/hooks/use-keys.tsx
2917
- import {
2918
- createContext as createContext2,
2919
- useCallback as useCallback2,
2920
- useContext as useContext2,
2921
- useMemo as useMemo2,
2922
- useRef as useRef2
2923
- } from "react";
2994
+ import { createContext as createContext4, useContext as useContext4, useMemo as useMemo4 } from "react";
2924
2995
  import { useInfiniteQuery } from "@tanstack/react-query";
2925
2996
 
2926
- // src/components/databrowser/hooks/use-fetch-key-type.tsx
2997
+ // src/tab-provider.tsx
2998
+ import { createContext as createContext3, useContext as useContext3, useMemo as useMemo3 } from "react";
2999
+ import { jsx as jsx5 } from "react/jsx-runtime";
3000
+ var TabIdContext = createContext3(void 0);
3001
+ var TabIdProvider = ({ children, value }) => {
3002
+ return /* @__PURE__ */ jsx5(TabIdContext.Provider, { value, children });
3003
+ };
3004
+ var useTab = () => {
3005
+ const {
3006
+ selectedTab,
3007
+ tabs,
3008
+ setSelectedKey,
3009
+ setSelectedListItem,
3010
+ setSearch,
3011
+ setSearchKey,
3012
+ setSearchType
3013
+ } = useDatabrowserStore();
3014
+ if (!selectedTab) throw new Error("selectedTab is undefined when using useTab()");
3015
+ return useMemo3(
3016
+ () => ({
3017
+ selectedKey: tabs[selectedTab]?.selectedKey,
3018
+ selectedListItem: tabs[selectedTab]?.selectedListItem,
3019
+ search: tabs[selectedTab]?.search,
3020
+ setSelectedKey: (key) => setSelectedKey(selectedTab, key),
3021
+ setSelectedListItem: (item) => setSelectedListItem(selectedTab, item),
3022
+ setSearch: (search) => setSearch(selectedTab, search),
3023
+ setSearchKey: (key) => setSearchKey(selectedTab, key),
3024
+ setSearchType: (type) => setSearchType(selectedTab, type)
3025
+ }),
3026
+ [selectedTab, tabs]
3027
+ );
3028
+ };
3029
+
3030
+ // src/components/databrowser/hooks/use-fetch-key-type.ts
2927
3031
  import { useQuery } from "@tanstack/react-query";
2928
3032
  var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
2929
3033
  var useFetchKeyType = (key) => {
2930
- const { redisNoPipeline: redis } = useDatabrowser();
3034
+ const { redis } = useRedis();
2931
3035
  return useQuery({
2932
3036
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key],
2933
3037
  queryFn: async () => {
@@ -2937,161 +3041,56 @@ var useFetchKeyType = (key) => {
2937
3041
  });
2938
3042
  };
2939
3043
 
2940
- // src/components/databrowser/hooks/use-fetch-keys.ts
2941
- import { useCallback, useRef } from "react";
2942
-
2943
- // src/types/index.ts
2944
- var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
2945
- var DATA_TYPE_NAMES = {
2946
- string: "String",
2947
- list: "List",
2948
- hash: "Hash",
2949
- set: "Set",
2950
- zset: "Sorted Set",
2951
- json: "JSON",
2952
- stream: "Stream"
2953
- };
2954
-
2955
- // src/components/databrowser/hooks/use-fetch-keys.ts
2956
- var PAGE_SIZE = 30;
2957
- var FETCH_COUNTS = [100, 200, 400, 800];
2958
- var useFetchKeys = (search) => {
2959
- const { redisNoPipeline: redis } = useDatabrowser();
2960
- const cache = useRef();
2961
- const lastKey = useRef();
2962
- const fetchKeys = useCallback(() => {
2963
- const newKey = JSON.stringify(search);
2964
- if (!cache.current || lastKey.current !== newKey) {
2965
- cache.current = new PaginationCache(redis, search.key, search.type);
2966
- lastKey.current = newKey;
2967
- }
2968
- return cache.current.fetchNewKeys();
2969
- }, [search]);
2970
- const resetCache = useCallback(() => {
2971
- cache.current = void 0;
2972
- lastKey.current = void 0;
2973
- }, []);
2974
- return {
2975
- fetchKeys,
2976
- resetCache
2977
- };
2978
- };
2979
- var PaginationCache = class {
2980
- constructor(redis, searchTerm, typeFilter) {
2981
- this.redis = redis;
2982
- this.searchTerm = searchTerm;
2983
- this.typeFilter = typeFilter;
2984
- if (typeFilter && !DATA_TYPES.includes(typeFilter)) {
2985
- throw new Error(`Invalid type filter: ${typeFilter}`);
2986
- }
2987
- }
2988
- // Cursor is 0 initially, then it is set to -1 when we reach the end
2989
- cache = Object.fromEntries(
2990
- DATA_TYPES.map((type) => [type, { cursor: "0", keys: [] }])
2991
- );
2992
- targetCount = 0;
2993
- isFetching = false;
2994
- async fetchNewKeys() {
2995
- const initialKeys = new Set(this.getKeys().map(([key]) => key));
2996
- this.targetCount = this.getKeys().length + PAGE_SIZE;
2997
- void this.startFetch();
2998
- await new Promise((resolve) => {
2999
- const interval = setInterval(() => {
3000
- if (this.getLength() >= this.targetCount || this.isAllEnded()) {
3001
- clearInterval(interval);
3002
- resolve();
3003
- }
3004
- }, 100);
3005
- });
3006
- const hasNextPage = !this.isAllEnded();
3007
- return {
3008
- keys: this.getKeys().filter(([key]) => !initialKeys.has(key)),
3009
- hasNextPage
3010
- };
3011
- }
3012
- getLength() {
3013
- return Object.values(this.cache).reduce((acc, curr) => acc + curr.keys.length, 0);
3014
- }
3015
- getKeys() {
3016
- const keys = Object.entries(this.cache).flatMap(([type, { keys: keys2 }]) => {
3017
- return keys2.map((key) => [key, type]);
3018
- });
3019
- const sorted = keys.sort((a, b) => a[0].localeCompare(b[0]));
3020
- return sorted;
3021
- }
3022
- async startFetch() {
3023
- if (this.isFetching) {
3024
- return;
3025
- }
3026
- this.isFetching = true;
3027
- try {
3028
- await this.fetch();
3029
- } finally {
3030
- this.isFetching = false;
3031
- }
3032
- }
3033
- fetchForType = async (type) => {
3034
- let i = 0;
3035
- while (true) {
3036
- const cursor = this.cache[type].cursor;
3037
- if (cursor === "-1" || this.getLength() >= this.targetCount) {
3038
- break;
3039
- }
3040
- const fetchCount = FETCH_COUNTS[Math.min(i, FETCH_COUNTS.length - 1)];
3041
- const [nextCursor, newKeys] = await this.redis.scan(cursor, {
3042
- count: fetchCount,
3043
- match: this.searchTerm,
3044
- type
3045
- });
3046
- this.cache[type].keys = [...this.cache[type].keys, ...newKeys];
3047
- this.cache[type].cursor = nextCursor === "0" ? "-1" : nextCursor;
3048
- i++;
3049
- }
3050
- };
3051
- async fetch() {
3052
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3053
- await Promise.all(types.map(this.fetchForType));
3054
- }
3055
- isAllEnded() {
3056
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3057
- return types.every((type) => this.cache[type] && this.cache[type].cursor === "-1");
3058
- }
3059
- };
3060
-
3061
3044
  // src/components/databrowser/hooks/use-keys.tsx
3062
- import { jsx as jsx4 } from "react/jsx-runtime";
3063
- var KeysContext = createContext2(void 0);
3045
+ import { jsx as jsx6 } from "react/jsx-runtime";
3046
+ var KeysContext = createContext4(void 0);
3064
3047
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
3048
+ var SCAN_COUNT = 100;
3065
3049
  var KeysProvider = ({ children }) => {
3066
- const { search } = useDatabrowserStore();
3067
- const cleanSearchKey = search.key.replace("*", "");
3068
- const { data: exactMatchType, isFetching, isLoading } = useFetchKeyType(cleanSearchKey);
3069
- const { fetchKeys, resetCache } = useFetchKeys(search);
3070
- const pageRef = useRef2(0);
3050
+ const { search } = useTab();
3051
+ const { redisNoPipeline: redis } = useRedis();
3071
3052
  const query = useInfiniteQuery({
3072
3053
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3073
- initialPageParam: 0,
3074
- queryFn: async ({ pageParam: page }) => {
3075
- if (pageRef.current >= page) resetCache();
3076
- pageRef.current = page;
3077
- return await fetchKeys();
3054
+ initialPageParam: "0",
3055
+ queryFn: async ({ pageParam: lastCursor }) => {
3056
+ const args = [lastCursor];
3057
+ if (search.key) {
3058
+ args.push("MATCH", search.key);
3059
+ }
3060
+ if (search.type) {
3061
+ args.push("TYPE", search.type);
3062
+ }
3063
+ args.push("COUNT", SCAN_COUNT.toString());
3064
+ if (!search.type) args.push("WITHTYPE");
3065
+ const [cursor, values] = await redis.exec(["SCAN", ...args]);
3066
+ const keys2 = [];
3067
+ let index = 0;
3068
+ while (true) {
3069
+ if (search.type) {
3070
+ if (index >= values.length) break;
3071
+ keys2.push([values[index], search.type]);
3072
+ index += 1;
3073
+ } else {
3074
+ if (index + 1 >= values.length) break;
3075
+ keys2.push([values[index], values[index + 1]]);
3076
+ index += 2;
3077
+ }
3078
+ }
3079
+ for (const [key, type] of keys2) {
3080
+ queryClient.setQueryData([FETCH_KEY_TYPE_QUERY_KEY, key], type);
3081
+ }
3082
+ return {
3083
+ cursor: cursor === "0" ? void 0 : cursor,
3084
+ keys: keys2,
3085
+ hasNextPage: cursor !== "0"
3086
+ };
3078
3087
  },
3079
3088
  select: (data) => data,
3080
- getNextPageParam: (lastPage, __, lastPageIndex) => {
3081
- return lastPage.hasNextPage ? lastPageIndex + 1 : void 0;
3082
- },
3083
- enabled: !isFetching,
3089
+ getNextPageParam: ({ cursor }) => cursor,
3084
3090
  refetchOnMount: false
3085
3091
  });
3086
- const refetch = useCallback2(() => {
3087
- resetCache();
3088
- query.refetch();
3089
- }, [query, resetCache]);
3090
- const keys = useMemo2(() => {
3092
+ const keys = useMemo4(() => {
3091
3093
  const keys2 = query.data?.pages.flatMap((page) => page.keys) ?? [];
3092
- if (exactMatchType && exactMatchType !== "none" && (search.type === void 0 || search.type === exactMatchType)) {
3093
- keys2.push([cleanSearchKey, exactMatchType]);
3094
- }
3095
3094
  const keysSet = /* @__PURE__ */ new Set();
3096
3095
  const dedupedKeys = [];
3097
3096
  for (const key of keys2) {
@@ -3100,26 +3099,20 @@ var KeysProvider = ({ children }) => {
3100
3099
  dedupedKeys.push(key);
3101
3100
  }
3102
3101
  return dedupedKeys;
3103
- }, [query.data, cleanSearchKey, exactMatchType]);
3104
- return /* @__PURE__ */ jsx4(
3102
+ }, [query.data]);
3103
+ return /* @__PURE__ */ jsx6(
3105
3104
  KeysContext.Provider,
3106
3105
  {
3107
3106
  value: {
3108
3107
  keys,
3109
- // @ts-expect-error Ignore the error with spread syntax
3110
- query: {
3111
- ...query,
3112
- isLoading: isLoading || query.isLoading,
3113
- isFetching: isFetching || query.isFetching
3114
- },
3115
- refetch
3108
+ query
3116
3109
  },
3117
3110
  children
3118
3111
  }
3119
3112
  );
3120
3113
  };
3121
3114
  var useKeys = () => {
3122
- const context = useContext2(KeysContext);
3115
+ const context = useContext4(KeysContext);
3123
3116
  if (!context) {
3124
3117
  throw new Error("useKeys must be used within a KeysProvider");
3125
3118
  }
@@ -3127,20 +3120,20 @@ var useKeys = () => {
3127
3120
  };
3128
3121
  var useKeyType = (key) => {
3129
3122
  const { keys } = useKeys();
3130
- const keyTuple = useMemo2(() => keys.find(([k, _]) => k === key), [keys, key]);
3123
+ const keyTuple = useMemo4(() => keys.find(([k, _]) => k === key), [keys, key]);
3131
3124
  return keyTuple?.[1];
3132
3125
  };
3133
3126
 
3134
3127
  // src/components/databrowser/components/display/display-list.tsx
3135
- import { useMemo as useMemo5 } from "react";
3128
+ import { useMemo as useMemo7 } from "react";
3136
3129
  import { IconTrash } from "@tabler/icons-react";
3137
3130
 
3138
3131
  // src/components/ui/button.tsx
3139
3132
  import * as React3 from "react";
3140
3133
  import { Slot } from "@radix-ui/react-slot";
3141
- import { jsx as jsx5 } from "react/jsx-runtime";
3134
+ import { jsx as jsx7 } from "react/jsx-runtime";
3142
3135
  var buttonVariants = cva(
3143
- "inline-flex items-center justify-center rounded-md text-sm ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-zinc-950 dark:focus-visible:ring-zinc-300",
3136
+ "inline-flex items-center justify-center rounded-md text-sm ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-zinc-950 dark:focus-visible:ring-zinc-300",
3144
3137
  {
3145
3138
  variants: {
3146
3139
  variant: {
@@ -3170,7 +3163,7 @@ var buttonVariants = cva(
3170
3163
  var Button = React3.forwardRef(
3171
3164
  ({ className, variant, size, asChild = false, ...props }, ref) => {
3172
3165
  const Comp = asChild ? Slot : "button";
3173
- return /* @__PURE__ */ jsx5(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
3166
+ return /* @__PURE__ */ jsx7(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
3174
3167
  }
3175
3168
  );
3176
3169
  Button.displayName = "Button";
@@ -3182,9 +3175,9 @@ import { useMutation } from "@tanstack/react-query";
3182
3175
  import { useQuery as useQuery2 } from "@tanstack/react-query";
3183
3176
 
3184
3177
  // src/components/ui/skeleton.tsx
3185
- import { jsx as jsx6 } from "react/jsx-runtime";
3178
+ import { jsx as jsx8 } from "react/jsx-runtime";
3186
3179
  function Skeleton({ className, ...props }) {
3187
- return /* @__PURE__ */ jsx6(
3180
+ return /* @__PURE__ */ jsx8(
3188
3181
  "div",
3189
3182
  {
3190
3183
  className: cn("animate-pulse rounded-md bg-zinc-900/10 dark:bg-zinc-50/10", className),
@@ -3194,10 +3187,10 @@ function Skeleton({ className, ...props }) {
3194
3187
  }
3195
3188
 
3196
3189
  // src/components/databrowser/components/sidebar/db-size.tsx
3197
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
3190
+ import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
3198
3191
  var FETCH_DB_SIZE_QUERY_KEY = "fetch-db-size";
3199
3192
  var DisplayDbSize = () => {
3200
- const { redis } = useDatabrowser();
3193
+ const { redis } = useRedis();
3201
3194
  const { data: keyCount } = useQuery2({
3202
3195
  queryKey: [FETCH_DB_SIZE_QUERY_KEY],
3203
3196
  queryFn: async () => {
@@ -3205,7 +3198,7 @@ var DisplayDbSize = () => {
3205
3198
  }
3206
3199
  });
3207
3200
  if (keyCount === void 0) {
3208
- return /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center gap-1", children: /* @__PURE__ */ jsx7(Skeleton, { className: "h-5 w-10 rounded" }) });
3201
+ return /* @__PURE__ */ jsx9("div", { className: "flex items-center justify-center gap-1", children: /* @__PURE__ */ jsx9(Skeleton, { className: "h-5 w-10 rounded" }) });
3209
3202
  }
3210
3203
  return /* @__PURE__ */ jsxs2("div", { className: "", children: [
3211
3204
  formatNumber(keyCount),
@@ -3215,7 +3208,7 @@ var DisplayDbSize = () => {
3215
3208
 
3216
3209
  // src/components/databrowser/hooks/use-add-key.ts
3217
3210
  var useAddKey = () => {
3218
- const { redis } = useDatabrowser();
3211
+ const { redis } = useRedis();
3219
3212
  const mutation = useMutation({
3220
3213
  mutationFn: async ({ key, type }) => {
3221
3214
  if (await redis.exists(key)) throw new Error(`Key "${key}" already exists`);
@@ -3287,20 +3280,20 @@ var useAddKey = () => {
3287
3280
  };
3288
3281
 
3289
3282
  // src/components/databrowser/hooks/use-debounce.ts
3290
- import { useEffect as useEffect2, useState as useState3 } from "react";
3283
+ import { useEffect as useEffect2, useState as useState2 } from "react";
3291
3284
 
3292
3285
  // src/components/databrowser/hooks/use-delete-key.ts
3293
3286
  import { useMutation as useMutation2 } from "@tanstack/react-query";
3294
3287
 
3295
3288
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3296
- import { useCallback as useCallback3 } from "react";
3289
+ import { useCallback } from "react";
3297
3290
 
3298
3291
  // src/components/databrowser/hooks/use-fetch-list-items.tsx
3299
3292
  import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
3300
3293
  var LIST_DISPLAY_PAGE_SIZE = 50;
3301
3294
  var FETCH_LIST_ITEMS_QUERY_KEY = "use-fetch-list-items";
3302
3295
  var useFetchListItems = ({ dataKey, type }) => {
3303
- const { redisNoPipeline: redis } = useDatabrowser();
3296
+ const { redisNoPipeline: redis } = useRedis();
3304
3297
  const setQuery = useInfiniteQuery2({
3305
3298
  enabled: type === "set",
3306
3299
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "set"],
@@ -3415,7 +3408,7 @@ function transformArray(inputArray) {
3415
3408
  import { useQuery as useQuery3 } from "@tanstack/react-query";
3416
3409
  var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
3417
3410
  var useFetchSimpleKey = (dataKey, type) => {
3418
- const { redisNoPipeline: redis } = useDatabrowser();
3411
+ const { redisNoPipeline: redis } = useRedis();
3419
3412
  const { deleteKeyCache } = useDeleteKeyCache();
3420
3413
  return useQuery3({
3421
3414
  queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
@@ -3442,9 +3435,8 @@ var sortObject = (obj) => {
3442
3435
 
3443
3436
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3444
3437
  var useDeleteKeyCache = () => {
3445
- const { setSelectedKey } = useDatabrowserStore();
3446
- const { refetch } = useKeys();
3447
- const deleteKeyCache = useCallback3(
3438
+ const { setSelectedKey } = useTab();
3439
+ const deleteKeyCache = useCallback(
3448
3440
  (key) => {
3449
3441
  setSelectedKey(void 0);
3450
3442
  queryClient.invalidateQueries({
@@ -3459,16 +3451,15 @@ var useDeleteKeyCache = () => {
3459
3451
  queryClient.invalidateQueries({
3460
3452
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key]
3461
3453
  });
3462
- refetch();
3463
3454
  },
3464
- [setSelectedKey, refetch]
3455
+ [setSelectedKey]
3465
3456
  );
3466
3457
  return { deleteKeyCache };
3467
3458
  };
3468
3459
 
3469
3460
  // src/components/databrowser/hooks/use-delete-key.ts
3470
3461
  var useDeleteKey = () => {
3471
- const { redis } = useDatabrowser();
3462
+ const { redis } = useRedis();
3472
3463
  const { deleteKeyCache } = useDeleteKeyCache();
3473
3464
  const deleteKey = useMutation2({
3474
3465
  mutationFn: async (key) => {
@@ -3487,7 +3478,7 @@ var useDeleteKey = () => {
3487
3478
  // src/components/databrowser/hooks/use-edit-list-item.tsx
3488
3479
  import { useMutation as useMutation3 } from "@tanstack/react-query";
3489
3480
  var useEditListItem = () => {
3490
- const { redis } = useDatabrowser();
3481
+ const { redis } = useRedis();
3491
3482
  return useMutation3({
3492
3483
  mutationFn: async ({
3493
3484
  type,
@@ -3570,7 +3561,7 @@ import { useEffect as useEffect5 } from "react";
3570
3561
  import { useQuery as useQuery6 } from "@tanstack/react-query";
3571
3562
 
3572
3563
  // src/components/databrowser/components/display/ttl-badge.tsx
3573
- import { useEffect as useEffect4, useState as useState5 } from "react";
3564
+ import { useEffect as useEffect4, useState as useState4 } from "react";
3574
3565
  import { IconChevronDown } from "@tabler/icons-react";
3575
3566
 
3576
3567
  // src/components/databrowser/components/display/header-badges.tsx
@@ -3580,7 +3571,7 @@ import bytes from "bytes";
3580
3571
  import { useQuery as useQuery4 } from "@tanstack/react-query";
3581
3572
  var FETCH_KEY_LENGTH_QUERY_KEY = "fetch-key-length";
3582
3573
  var useFetchKeyLength = ({ dataKey, type }) => {
3583
- const { redis } = useDatabrowser();
3574
+ const { redis } = useRedis();
3584
3575
  return useQuery4({
3585
3576
  queryKey: [FETCH_KEY_LENGTH_QUERY_KEY, dataKey],
3586
3577
  queryFn: async () => {
@@ -3610,7 +3601,7 @@ var useFetchKeyLength = ({ dataKey, type }) => {
3610
3601
  import { useQuery as useQuery5 } from "@tanstack/react-query";
3611
3602
  var FETCH_KEY_SIZE_QUERY_KEY = "fetch-key-size";
3612
3603
  var useFetchKeySize = (dataKey) => {
3613
- const { redis } = useDatabrowser();
3604
+ const { redis } = useRedis();
3614
3605
  return useQuery5({
3615
3606
  queryKey: [FETCH_KEY_SIZE_QUERY_KEY, dataKey],
3616
3607
  queryFn: async () => {
@@ -3620,7 +3611,7 @@ var useFetchKeySize = (dataKey) => {
3620
3611
  };
3621
3612
 
3622
3613
  // src/components/databrowser/components/display/header-badges.tsx
3623
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
3614
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
3624
3615
  var LengthBadge = ({
3625
3616
  dataKey,
3626
3617
  type,
@@ -3628,18 +3619,18 @@ var LengthBadge = ({
3628
3619
  }) => {
3629
3620
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3630
3621
  const length = content?.length ?? data;
3631
- return /* @__PURE__ */ jsx8(Badge, { label: "Length:", children: isLoading ? /* @__PURE__ */ jsx8(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : length });
3622
+ return /* @__PURE__ */ jsx10(Badge, { label: "Length:", children: isLoading ? /* @__PURE__ */ jsx10(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : length });
3632
3623
  };
3633
3624
  var SizeBadge = ({ dataKey }) => {
3634
3625
  const { data: size } = useFetchKeySize(dataKey);
3635
- return /* @__PURE__ */ jsx8(Badge, { label: "Size:", children: size === void 0 || size === null ? /* @__PURE__ */ jsx8(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : bytes(size, {
3626
+ return /* @__PURE__ */ jsx10(Badge, { label: "Size:", children: size === void 0 || size === null ? /* @__PURE__ */ jsx10(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : bytes(size, {
3636
3627
  unitSeparator: " "
3637
3628
  }) });
3638
3629
  };
3639
3630
  var HeaderTTLBadge = ({ dataKey }) => {
3640
- const { data: expireAt } = useFetchKeyExpire(dataKey);
3631
+ const { data: expireAt } = useFetchTTL(dataKey);
3641
3632
  const { mutate: setTTL, isPending } = useSetTTL();
3642
- return /* @__PURE__ */ jsx8(
3633
+ return /* @__PURE__ */ jsx10(
3643
3634
  TTLBadge,
3644
3635
  {
3645
3636
  expireAt,
@@ -3649,20 +3640,20 @@ var HeaderTTLBadge = ({ dataKey }) => {
3649
3640
  );
3650
3641
  };
3651
3642
  var Badge = ({ children, label }) => /* @__PURE__ */ jsxs3("div", { className: "flex h-6 items-center gap-0.5 rounded-md bg-white px-2 text-xs text-zinc-700", children: [
3652
- /* @__PURE__ */ jsx8("span", { className: "text-zinc-500", children: label }),
3653
- /* @__PURE__ */ jsx8("span", { className: "font-medium", children })
3643
+ /* @__PURE__ */ jsx10("span", { className: "text-zinc-500", children: label }),
3644
+ /* @__PURE__ */ jsx10("span", { className: "font-medium", children })
3654
3645
  ] });
3655
3646
 
3656
3647
  // src/components/databrowser/components/display/ttl-popover.tsx
3657
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState4 } from "react";
3648
+ import { useEffect as useEffect3, useMemo as useMemo5, useState as useState3 } from "react";
3658
3649
  import { Controller, useForm } from "react-hook-form";
3659
3650
 
3660
3651
  // src/components/ui/input.tsx
3661
3652
  import * as React4 from "react";
3662
- import { jsx as jsx9 } from "react/jsx-runtime";
3653
+ import { jsx as jsx11 } from "react/jsx-runtime";
3663
3654
  var Input = React4.forwardRef(
3664
3655
  ({ className, type, ...props }, ref) => {
3665
- return /* @__PURE__ */ jsx9(
3656
+ return /* @__PURE__ */ jsx11(
3666
3657
  "input",
3667
3658
  {
3668
3659
  type,
@@ -3681,10 +3672,10 @@ Input.displayName = "Input";
3681
3672
  // src/components/ui/popover.tsx
3682
3673
  import * as React5 from "react";
3683
3674
  import * as PopoverPrimitive from "@radix-ui/react-popover";
3684
- import { jsx as jsx10 } from "react/jsx-runtime";
3675
+ import { jsx as jsx12 } from "react/jsx-runtime";
3685
3676
  var Popover = PopoverPrimitive.Root;
3686
3677
  var PopoverTrigger = PopoverPrimitive.Trigger;
3687
- var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx10(PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx10(
3678
+ var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx12(PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx12(
3688
3679
  PopoverPrimitive.Content,
3689
3680
  {
3690
3681
  ref,
@@ -3702,7 +3693,7 @@ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
3702
3693
  // src/components/ui/select.tsx
3703
3694
  import * as React6 from "react";
3704
3695
  import * as SelectPrimitive from "@radix-ui/react-select";
3705
- import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
3696
+ import { jsx as jsx13, jsxs as jsxs4 } from "react/jsx-runtime";
3706
3697
  var Select = SelectPrimitive.Root;
3707
3698
  var SelectGroup = SelectPrimitive.Group;
3708
3699
  var SelectValue = SelectPrimitive.Value;
@@ -3717,7 +3708,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
3717
3708
  ...props,
3718
3709
  children: [
3719
3710
  children,
3720
- /* @__PURE__ */ jsx11(SelectPrimitive.Icon, { asChild: true, className: "absolute right-2", children: /* @__PURE__ */ jsx11(
3711
+ /* @__PURE__ */ jsx13(SelectPrimitive.Icon, { asChild: true, className: "absolute right-2", children: /* @__PURE__ */ jsx13(
3721
3712
  "svg",
3722
3713
  {
3723
3714
  width: "16",
@@ -3725,7 +3716,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
3725
3716
  viewBox: "0 0 16 16",
3726
3717
  fill: "none",
3727
3718
  xmlns: "http://www.w3.org/2000/svg",
3728
- children: /* @__PURE__ */ jsx11(
3719
+ children: /* @__PURE__ */ jsx13(
3729
3720
  "path",
3730
3721
  {
3731
3722
  d: "M4 6L8 10L12 6",
@@ -3742,7 +3733,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
3742
3733
  }
3743
3734
  ));
3744
3735
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
3745
- var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx11(SelectPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx11(
3736
+ var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx13(SelectPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx13(
3746
3737
  SelectPrimitive.Content,
3747
3738
  {
3748
3739
  ref,
@@ -3753,7 +3744,7 @@ var SelectContent = React6.forwardRef(({ className, children, position = "popper
3753
3744
  ),
3754
3745
  position,
3755
3746
  ...props,
3756
- children: /* @__PURE__ */ jsx11(
3747
+ children: /* @__PURE__ */ jsx13(
3757
3748
  SelectPrimitive.Viewport,
3758
3749
  {
3759
3750
  className: cn(
@@ -3766,7 +3757,7 @@ var SelectContent = React6.forwardRef(({ className, children, position = "popper
3766
3757
  }
3767
3758
  ) }));
3768
3759
  SelectContent.displayName = SelectPrimitive.Content.displayName;
3769
- var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
3760
+ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
3770
3761
  SelectPrimitive.Label,
3771
3762
  {
3772
3763
  ref,
@@ -3785,7 +3776,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
3785
3776
  ),
3786
3777
  ...props,
3787
3778
  children: [
3788
- /* @__PURE__ */ jsx11("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx11(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx11(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx11(
3779
+ /* @__PURE__ */ jsx13("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx13(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx13(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx13(
3789
3780
  "svg",
3790
3781
  {
3791
3782
  width: "15",
@@ -3794,7 +3785,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
3794
3785
  fill: "none",
3795
3786
  xmlns: "http://www.w3.org/2000/svg",
3796
3787
  className: "h-4 w-4",
3797
- children: /* @__PURE__ */ jsx11(
3788
+ children: /* @__PURE__ */ jsx13(
3798
3789
  "path",
3799
3790
  {
3800
3791
  d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
@@ -3805,12 +3796,12 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
3805
3796
  )
3806
3797
  }
3807
3798
  ) }) }) }),
3808
- /* @__PURE__ */ jsx11(SelectPrimitive.ItemText, { children })
3799
+ /* @__PURE__ */ jsx13(SelectPrimitive.ItemText, { children })
3809
3800
  ]
3810
3801
  }
3811
3802
  ));
3812
3803
  SelectItem.displayName = SelectPrimitive.Item.displayName;
3813
- var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
3804
+ var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
3814
3805
  SelectPrimitive.Separator,
3815
3806
  {
3816
3807
  ref,
@@ -3821,16 +3812,16 @@ var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__
3821
3812
  SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
3822
3813
 
3823
3814
  // src/components/ui/spinner.tsx
3824
- import { Fragment, jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
3815
+ import { Fragment, jsx as jsx14, jsxs as jsxs5 } from "react/jsx-runtime";
3825
3816
  var Spinner = ({
3826
3817
  isLoading,
3827
3818
  className,
3828
3819
  isLoadingText,
3829
3820
  children
3830
3821
  }) => {
3831
- return /* @__PURE__ */ jsx12("div", { className: className ?? "flex items-center", children: isLoading ? /* @__PURE__ */ jsxs5(Fragment, { children: [
3822
+ return /* @__PURE__ */ jsx14("div", { className: className ?? "flex items-center", children: isLoading ? /* @__PURE__ */ jsxs5(Fragment, { children: [
3832
3823
  isLoadingText,
3833
- /* @__PURE__ */ jsx12(
3824
+ /* @__PURE__ */ jsx14(
3834
3825
  "svg",
3835
3826
  {
3836
3827
  xmlns: "http://www.w3.org/2000/svg",
@@ -3843,14 +3834,14 @@ var Spinner = ({
3843
3834
  strokeLinecap: "round",
3844
3835
  strokeLinejoin: "round",
3845
3836
  className: cn("h-4 w-4 animate-spin", isLoadingText ? "ml-2" : ""),
3846
- children: /* @__PURE__ */ jsx12("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3837
+ children: /* @__PURE__ */ jsx14("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3847
3838
  }
3848
3839
  )
3849
3840
  ] }) : children });
3850
3841
  };
3851
3842
 
3852
3843
  // src/components/databrowser/components/display/ttl-popover.tsx
3853
- import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
3844
+ import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
3854
3845
  var timeUnits = [
3855
3846
  { label: "Seconds", value: 1 },
3856
3847
  { label: "Minutes", value: 60 },
@@ -3863,8 +3854,8 @@ function TTLPopover({
3863
3854
  setTTL,
3864
3855
  isPending
3865
3856
  }) {
3866
- const [open, setOpen] = useState4(false);
3867
- const defaultValues = useMemo3(() => {
3857
+ const [open, setOpen] = useState3(false);
3858
+ const defaultValues = useMemo5(() => {
3868
3859
  return { type: "Seconds", value: ttl };
3869
3860
  }, [ttl]);
3870
3861
  const { control, handleSubmit, formState, reset } = useForm({
@@ -3892,8 +3883,8 @@ function TTLPopover({
3892
3883
  setOpen(isOpen);
3893
3884
  },
3894
3885
  children: [
3895
- /* @__PURE__ */ jsx13(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx13("button", { children }) }),
3896
- /* @__PURE__ */ jsx13(PopoverContent, { className: "w-[300px]", align: "end", children: /* @__PURE__ */ jsxs6(
3886
+ /* @__PURE__ */ jsx15(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx15("button", { children }) }),
3887
+ /* @__PURE__ */ jsx15(PopoverContent, { className: "w-[300px]", align: "end", children: /* @__PURE__ */ jsxs6(
3897
3888
  "form",
3898
3889
  {
3899
3890
  className: "space-y-4",
@@ -3902,10 +3893,10 @@ function TTLPopover({
3902
3893
  e.stopPropagation();
3903
3894
  },
3904
3895
  children: [
3905
- /* @__PURE__ */ jsx13("h4", { className: "font-medium leading-none", children: "Expiration" }),
3896
+ /* @__PURE__ */ jsx15("h4", { className: "font-medium leading-none", children: "Expiration" }),
3906
3897
  /* @__PURE__ */ jsxs6("div", { children: [
3907
3898
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center", children: [
3908
- /* @__PURE__ */ jsx13(
3899
+ /* @__PURE__ */ jsx15(
3909
3900
  Controller,
3910
3901
  {
3911
3902
  rules: {
@@ -3914,26 +3905,26 @@ function TTLPopover({
3914
3905
  },
3915
3906
  control,
3916
3907
  name: "value",
3917
- render: ({ field }) => /* @__PURE__ */ jsx13(Input, { min: "-1", ...field, className: "grow rounded-r-none" })
3908
+ render: ({ field }) => /* @__PURE__ */ jsx15(Input, { min: "-1", ...field, className: "grow rounded-r-none" })
3918
3909
  }
3919
3910
  ),
3920
- /* @__PURE__ */ jsx13(
3911
+ /* @__PURE__ */ jsx15(
3921
3912
  Controller,
3922
3913
  {
3923
3914
  control,
3924
3915
  name: "type",
3925
3916
  render: ({ field }) => /* @__PURE__ */ jsxs6(Select, { value: field.value, onValueChange: field.onChange, children: [
3926
- /* @__PURE__ */ jsx13(SelectTrigger, { className: "w-auto rounded-l-none border-l-0 pr-8", children: /* @__PURE__ */ jsx13(SelectValue, {}) }),
3927
- /* @__PURE__ */ jsx13(SelectContent, { children: timeUnits.map((unit) => /* @__PURE__ */ jsx13(SelectItem, { value: unit.label, children: unit.label }, unit.label)) })
3917
+ /* @__PURE__ */ jsx15(SelectTrigger, { className: "w-auto rounded-l-none border-l-0 pr-8", children: /* @__PURE__ */ jsx15(SelectValue, {}) }),
3918
+ /* @__PURE__ */ jsx15(SelectContent, { children: timeUnits.map((unit) => /* @__PURE__ */ jsx15(SelectItem, { value: unit.label, children: unit.label }, unit.label)) })
3928
3919
  ] })
3929
3920
  }
3930
3921
  )
3931
3922
  ] }),
3932
- formState.errors.value && /* @__PURE__ */ jsx13("p", { className: "mt-2 text-xs text-red-500", children: formState.errors.value.message }),
3933
- /* @__PURE__ */ jsx13("p", { className: "mt-2 text-xs text-zinc-500", children: "TTL sets a timer to automatically delete keys after a defined period." })
3923
+ formState.errors.value && /* @__PURE__ */ jsx15("p", { className: "mt-2 text-xs text-red-500", children: formState.errors.value.message }),
3924
+ /* @__PURE__ */ jsx15("p", { className: "mt-2 text-xs text-zinc-500", children: "TTL sets a timer to automatically delete keys after a defined period." })
3934
3925
  ] }),
3935
3926
  /* @__PURE__ */ jsxs6("div", { className: "flex justify-between", children: [
3936
- /* @__PURE__ */ jsx13(
3927
+ /* @__PURE__ */ jsx15(
3937
3928
  Button,
3938
3929
  {
3939
3930
  type: "button",
@@ -3944,8 +3935,8 @@ function TTLPopover({
3944
3935
  }
3945
3936
  ),
3946
3937
  /* @__PURE__ */ jsxs6("div", { className: "flex gap-2", children: [
3947
- /* @__PURE__ */ jsx13(Button, { variant: "outline", onClick: () => setOpen(false), type: "button", children: "Cancel" }),
3948
- /* @__PURE__ */ jsx13(Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ jsx13(Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" }) })
3938
+ /* @__PURE__ */ jsx15(Button, { variant: "outline", onClick: () => setOpen(false), type: "button", children: "Cancel" }),
3939
+ /* @__PURE__ */ jsx15(Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ jsx15(Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" }) })
3949
3940
  ] })
3950
3941
  ] })
3951
3942
  ]
@@ -3957,7 +3948,7 @@ function TTLPopover({
3957
3948
  }
3958
3949
 
3959
3950
  // src/components/databrowser/components/display/ttl-badge.tsx
3960
- import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
3951
+ import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
3961
3952
  var TTL_INFINITE = -1;
3962
3953
  var TTL_NOT_FOUND = -2;
3963
3954
  var calculateTTL = (expireAt) => {
@@ -3971,7 +3962,7 @@ var TTLBadge = ({
3971
3962
  setTTL,
3972
3963
  isPending
3973
3964
  }) => {
3974
- const [ttl, setTTLLabel] = useState5(() => calculateTTL(expireAt));
3965
+ const [ttl, setTTLLabel] = useState4(() => calculateTTL(expireAt));
3975
3966
  useEffect4(() => {
3976
3967
  setTTLLabel(calculateTTL(expireAt));
3977
3968
  const interval = setInterval(() => {
@@ -3979,16 +3970,16 @@ var TTLBadge = ({
3979
3970
  }, 1e3);
3980
3971
  return () => clearInterval(interval);
3981
3972
  }, [expireAt]);
3982
- return /* @__PURE__ */ jsx14(Badge, { label, children: ttl === void 0 ? /* @__PURE__ */ jsx14(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : /* @__PURE__ */ jsx14(TTLPopover, { ttl, setTTL, isPending, children: /* @__PURE__ */ jsxs7("div", { className: "flex gap-[2px]", children: [
3973
+ return /* @__PURE__ */ jsx16(Badge, { label, children: ttl === void 0 ? /* @__PURE__ */ jsx16(Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : /* @__PURE__ */ jsx16(TTLPopover, { ttl, setTTL, isPending, children: /* @__PURE__ */ jsxs7("div", { className: "flex gap-[2px]", children: [
3983
3974
  ttl === TTL_INFINITE ? "Forever" : formatTime(ttl),
3984
- /* @__PURE__ */ jsx14(IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
3975
+ /* @__PURE__ */ jsx16(IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
3985
3976
  ] }) }) });
3986
3977
  };
3987
3978
 
3988
3979
  // src/components/databrowser/hooks/use-fetch-ttl.ts
3989
3980
  var FETCH_TTL_QUERY_KEY = "fetch-ttl";
3990
- var useFetchKeyExpire = (dataKey) => {
3991
- const { redis } = useDatabrowser();
3981
+ var useFetchTTL = (dataKey) => {
3982
+ const { redis } = useRedis();
3992
3983
  const { isLoading, error, data } = useQuery6({
3993
3984
  queryKey: [FETCH_TTL_QUERY_KEY, dataKey],
3994
3985
  queryFn: async () => {
@@ -4009,7 +4000,7 @@ var useFetchKeyExpire = (dataKey) => {
4009
4000
  // src/components/databrowser/hooks/use-set-simple-key.tsx
4010
4001
  import { useMutation as useMutation4 } from "@tanstack/react-query";
4011
4002
  var useSetSimpleKey = (dataKey, type) => {
4012
- const { redis } = useDatabrowser();
4003
+ const { redis } = useRedis();
4013
4004
  return useMutation4({
4014
4005
  mutationFn: async (value) => {
4015
4006
  if (type === "string") {
@@ -4032,7 +4023,7 @@ var useSetSimpleKey = (dataKey, type) => {
4032
4023
  // src/components/databrowser/hooks/use-set-ttl.ts
4033
4024
  import { useMutation as useMutation5 } from "@tanstack/react-query";
4034
4025
  var useSetTTL = () => {
4035
- const { redis } = useDatabrowser();
4026
+ const { redis } = useRedis();
4036
4027
  const updateTTL = useMutation5({
4037
4028
  mutationFn: async ({ dataKey, ttl }) => {
4038
4029
  await (ttl === void 0 || ttl === TTL_INFINITE ? redis.persist(dataKey) : redis.expire(dataKey, ttl));
@@ -4050,14 +4041,14 @@ var useSetTTL = () => {
4050
4041
  };
4051
4042
 
4052
4043
  // src/components/databrowser/components/item-context-menu.tsx
4053
- import { useState as useState6 } from "react";
4044
+ import { useState as useState5 } from "react";
4054
4045
  import { ContextMenuSeparator as ContextMenuSeparator2 } from "@radix-ui/react-context-menu";
4055
4046
 
4056
4047
  // src/components/ui/context-menu.tsx
4057
4048
  import * as React7 from "react";
4058
4049
  import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
4059
4050
  import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "@radix-ui/react-icons";
4060
- import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
4051
+ import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
4061
4052
  var ContextMenu = ContextMenuPrimitive.Root;
4062
4053
  var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
4063
4054
  var ContextMenuSubTrigger = React7.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs8(
@@ -4072,12 +4063,12 @@ var ContextMenuSubTrigger = React7.forwardRef(({ className, inset, children, ...
4072
4063
  ...props,
4073
4064
  children: [
4074
4065
  children,
4075
- /* @__PURE__ */ jsx15(ChevronRightIcon, { className: "ml-auto h-4 w-4" })
4066
+ /* @__PURE__ */ jsx17(ChevronRightIcon, { className: "ml-auto h-4 w-4" })
4076
4067
  ]
4077
4068
  }
4078
4069
  ));
4079
4070
  ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
4080
- var ContextMenuSubContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(
4071
+ var ContextMenuSubContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(
4081
4072
  ContextMenuPrimitive.SubContent,
4082
4073
  {
4083
4074
  ref,
@@ -4089,7 +4080,7 @@ var ContextMenuSubContent = React7.forwardRef(({ className, ...props }, ref) =>
4089
4080
  }
4090
4081
  ));
4091
4082
  ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
4092
- var ContextMenuContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx15(
4083
+ var ContextMenuContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx17(
4093
4084
  ContextMenuPrimitive.Content,
4094
4085
  {
4095
4086
  ref,
@@ -4101,7 +4092,7 @@ var ContextMenuContent = React7.forwardRef(({ className, ...props }, ref) => /*
4101
4092
  }
4102
4093
  ) }));
4103
4094
  ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
4104
- var ContextMenuItem = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx15(
4095
+ var ContextMenuItem = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx17(
4105
4096
  ContextMenuPrimitive.Item,
4106
4097
  {
4107
4098
  ref,
@@ -4125,7 +4116,7 @@ var ContextMenuCheckboxItem = React7.forwardRef(({ className, children, checked,
4125
4116
  checked,
4126
4117
  ...props,
4127
4118
  children: [
4128
- /* @__PURE__ */ jsx15("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx15(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx15(CheckIcon, { className: "h-4 w-4" }) }) }),
4119
+ /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17(CheckIcon, { className: "h-4 w-4" }) }) }),
4129
4120
  children
4130
4121
  ]
4131
4122
  }
@@ -4141,13 +4132,13 @@ var ContextMenuRadioItem = React7.forwardRef(({ className, children, ...props },
4141
4132
  ),
4142
4133
  ...props,
4143
4134
  children: [
4144
- /* @__PURE__ */ jsx15("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx15(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx15(DotFilledIcon, { className: "h-4 w-4 fill-current" }) }) }),
4135
+ /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx17(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx17(DotFilledIcon, { className: "h-4 w-4 fill-current" }) }) }),
4145
4136
  children
4146
4137
  ]
4147
4138
  }
4148
4139
  ));
4149
4140
  ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
4150
- var ContextMenuLabel = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx15(
4141
+ var ContextMenuLabel = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx17(
4151
4142
  ContextMenuPrimitive.Label,
4152
4143
  {
4153
4144
  ref,
@@ -4160,7 +4151,7 @@ var ContextMenuLabel = React7.forwardRef(({ className, inset, ...props }, ref) =
4160
4151
  }
4161
4152
  ));
4162
4153
  ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
4163
- var ContextMenuSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(
4154
+ var ContextMenuSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx17(
4164
4155
  ContextMenuPrimitive.Separator,
4165
4156
  {
4166
4157
  ref,
@@ -4170,7 +4161,7 @@ var ContextMenuSeparator = React7.forwardRef(({ className, ...props }, ref) => /
4170
4161
  ));
4171
4162
  ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
4172
4163
  var ContextMenuShortcut = ({ className, ...props }) => {
4173
- return /* @__PURE__ */ jsx15(
4164
+ return /* @__PURE__ */ jsx17(
4174
4165
  "span",
4175
4166
  {
4176
4167
  className: cn(
@@ -4186,12 +4177,12 @@ ContextMenuShortcut.displayName = "ContextMenuShortcut";
4186
4177
  // src/components/ui/alert-dialog.tsx
4187
4178
  import * as React8 from "react";
4188
4179
  import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
4189
- import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
4180
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
4190
4181
  var AlertDialog = AlertDialogPrimitive.Root;
4191
4182
  var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
4192
- var AlertDialogPortal = ({ ...props }) => /* @__PURE__ */ jsx16(AlertDialogPrimitive.Portal, { container: portalRoot, ...props });
4183
+ var AlertDialogPortal = ({ ...props }) => /* @__PURE__ */ jsx18(AlertDialogPrimitive.Portal, { container: portalRoot, ...props });
4193
4184
  AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
4194
- var AlertDialogOverlay = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
4185
+ var AlertDialogOverlay = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
4195
4186
  AlertDialogPrimitive.Overlay,
4196
4187
  {
4197
4188
  className: cn(
@@ -4204,8 +4195,8 @@ var AlertDialogOverlay = React8.forwardRef(({ className, ...props }, ref) => /*
4204
4195
  ));
4205
4196
  AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
4206
4197
  var AlertDialogContent = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs9(AlertDialogPortal, { children: [
4207
- /* @__PURE__ */ jsx16(AlertDialogOverlay, {}),
4208
- /* @__PURE__ */ jsx16(
4198
+ /* @__PURE__ */ jsx18(AlertDialogOverlay, {}),
4199
+ /* @__PURE__ */ jsx18(
4209
4200
  AlertDialogPrimitive.Content,
4210
4201
  {
4211
4202
  ref,
@@ -4218,9 +4209,9 @@ var AlertDialogContent = React8.forwardRef(({ className, ...props }, ref) => /*
4218
4209
  )
4219
4210
  ] }));
4220
4211
  AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
4221
- var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx16("div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
4212
+ var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx18("div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
4222
4213
  AlertDialogHeader.displayName = "AlertDialogHeader";
4223
- var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx16(
4214
+ var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx18(
4224
4215
  "div",
4225
4216
  {
4226
4217
  className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
@@ -4228,7 +4219,7 @@ var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx16(
4228
4219
  }
4229
4220
  );
4230
4221
  AlertDialogFooter.displayName = "AlertDialogFooter";
4231
- var AlertDialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
4222
+ var AlertDialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
4232
4223
  AlertDialogPrimitive.Title,
4233
4224
  {
4234
4225
  ref,
@@ -4237,7 +4228,7 @@ var AlertDialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @_
4237
4228
  }
4238
4229
  ));
4239
4230
  AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
4240
- var AlertDialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
4231
+ var AlertDialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
4241
4232
  AlertDialogPrimitive.Description,
4242
4233
  {
4243
4234
  ref,
@@ -4246,9 +4237,9 @@ var AlertDialogDescription = React8.forwardRef(({ className, ...props }, ref) =>
4246
4237
  }
4247
4238
  ));
4248
4239
  AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
4249
- var AlertDialogAction = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
4240
+ var AlertDialogAction = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
4250
4241
  AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
4251
- var AlertDialogCancel = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
4242
+ var AlertDialogCancel = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
4252
4243
  AlertDialogPrimitive.Cancel,
4253
4244
  {
4254
4245
  ref,
@@ -4259,7 +4250,7 @@ var AlertDialogCancel = React8.forwardRef(({ className, ...props }, ref) => /* @
4259
4250
  AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
4260
4251
 
4261
4252
  // src/components/databrowser/components/display/delete-alert-dialog.tsx
4262
- import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
4253
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
4263
4254
  function DeleteAlertDialog({
4264
4255
  children,
4265
4256
  onDeleteConfirm,
@@ -4268,21 +4259,21 @@ function DeleteAlertDialog({
4268
4259
  deletionType
4269
4260
  }) {
4270
4261
  return /* @__PURE__ */ jsxs10(AlertDialog, { open, onOpenChange, children: [
4271
- children && /* @__PURE__ */ jsx17(AlertDialogTrigger, { asChild: true, children }),
4262
+ children && /* @__PURE__ */ jsx19(AlertDialogTrigger, { asChild: true, children }),
4272
4263
  /* @__PURE__ */ jsxs10(AlertDialogContent, { children: [
4273
4264
  /* @__PURE__ */ jsxs10(AlertDialogHeader, { children: [
4274
- /* @__PURE__ */ jsx17(AlertDialogTitle, { children: deletionType === "item" ? "Delete Item" : "Delete Key" }),
4265
+ /* @__PURE__ */ jsx19(AlertDialogTitle, { children: deletionType === "item" ? "Delete Item" : "Delete Key" }),
4275
4266
  /* @__PURE__ */ jsxs10(AlertDialogDescription, { className: "mt-5", children: [
4276
4267
  "Are you sure you want to delete this ",
4277
4268
  deletionType,
4278
4269
  "?",
4279
- /* @__PURE__ */ jsx17("br", {}),
4270
+ /* @__PURE__ */ jsx19("br", {}),
4280
4271
  "This action cannot be undone."
4281
4272
  ] })
4282
4273
  ] }),
4283
4274
  /* @__PURE__ */ jsxs10(AlertDialogFooter, { children: [
4284
- /* @__PURE__ */ jsx17(AlertDialogCancel, { type: "button", children: "Cancel" }),
4285
- /* @__PURE__ */ jsx17(
4275
+ /* @__PURE__ */ jsx19(AlertDialogCancel, { type: "button", children: "Cancel" }),
4276
+ /* @__PURE__ */ jsx19(
4286
4277
  AlertDialogAction,
4287
4278
  {
4288
4279
  className: "bg-red-500 text-gray-50 hover:bg-red-600",
@@ -4296,17 +4287,17 @@ function DeleteAlertDialog({
4296
4287
  }
4297
4288
 
4298
4289
  // src/components/databrowser/components/item-context-menu.tsx
4299
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
4290
+ import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
4300
4291
  var ItemContextMenu = ({
4301
4292
  children,
4302
4293
  dataKey,
4303
4294
  type
4304
4295
  }) => {
4305
4296
  const { mutate: editItem } = useEditListItem();
4306
- const [isAlertOpen, setAlertOpen] = useState6(false);
4307
- const [data, setData] = useState6();
4297
+ const [isAlertOpen, setAlertOpen] = useState5(false);
4298
+ const [data, setData] = useState5();
4308
4299
  return /* @__PURE__ */ jsxs11(Fragment2, { children: [
4309
- /* @__PURE__ */ jsx18(
4300
+ /* @__PURE__ */ jsx20(
4310
4301
  DeleteAlertDialog,
4311
4302
  {
4312
4303
  deletionType: "item",
@@ -4328,7 +4319,7 @@ var ItemContextMenu = ({
4328
4319
  }
4329
4320
  ),
4330
4321
  /* @__PURE__ */ jsxs11(ContextMenu, { children: [
4331
- /* @__PURE__ */ jsx18(
4322
+ /* @__PURE__ */ jsx20(
4332
4323
  ContextMenuTrigger,
4333
4324
  {
4334
4325
  asChild: true,
@@ -4348,7 +4339,7 @@ var ItemContextMenu = ({
4348
4339
  }
4349
4340
  ),
4350
4341
  /* @__PURE__ */ jsxs11(ContextMenuContent, { children: [
4351
- /* @__PURE__ */ jsx18(
4342
+ /* @__PURE__ */ jsx20(
4352
4343
  ContextMenuItem,
4353
4344
  {
4354
4345
  onClick: () => {
@@ -4361,7 +4352,7 @@ var ItemContextMenu = ({
4361
4352
  children: "Copy key"
4362
4353
  }
4363
4354
  ),
4364
- data?.value && /* @__PURE__ */ jsx18(
4355
+ data?.value && /* @__PURE__ */ jsx20(
4365
4356
  ContextMenuItem,
4366
4357
  {
4367
4358
  onClick: () => {
@@ -4373,8 +4364,8 @@ var ItemContextMenu = ({
4373
4364
  children: "Copy value"
4374
4365
  }
4375
4366
  ),
4376
- /* @__PURE__ */ jsx18(ContextMenuSeparator2, {}),
4377
- /* @__PURE__ */ jsx18(ContextMenuItem, { disabled: type === "stream", onClick: () => setAlertOpen(true), children: "Delete item" })
4367
+ /* @__PURE__ */ jsx20(ContextMenuSeparator2, {}),
4368
+ /* @__PURE__ */ jsx20(ContextMenuItem, { disabled: type === "stream", onClick: () => setAlertOpen(true), children: "Delete item" })
4378
4369
  ] })
4379
4370
  ] })
4380
4371
  ] });
@@ -4386,36 +4377,36 @@ import { IconLoader2 } from "@tabler/icons-react";
4386
4377
  // src/components/ui/scroll-area.tsx
4387
4378
  import * as React9 from "react";
4388
4379
  import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
4389
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
4390
- var ScrollArea = React9.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ jsxs12(
4380
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
4381
+ var ScrollArea = React9.forwardRef(({ className, children, onScroll, roundedInherit = true, ...props }, ref) => /* @__PURE__ */ jsxs12(
4391
4382
  ScrollAreaPrimitive.Root,
4392
4383
  {
4393
4384
  ref,
4394
4385
  className: cn("relative overflow-hidden", className),
4395
4386
  ...props,
4396
4387
  children: [
4397
- /* @__PURE__ */ jsx19(
4388
+ /* @__PURE__ */ jsx21(
4398
4389
  ScrollAreaPrimitive.Viewport,
4399
4390
  {
4400
4391
  onScroll,
4401
- className: "h-full w-full rounded-[inherit] [&>div]:!block",
4392
+ className: cn("h-full w-full [&>div]:!block", roundedInherit && "rounded-[inherit]"),
4402
4393
  children
4403
4394
  }
4404
4395
  ),
4405
- /* @__PURE__ */ jsx19(ScrollBar, {}),
4406
- /* @__PURE__ */ jsx19(ScrollAreaPrimitive.Corner, {})
4396
+ /* @__PURE__ */ jsx21(ScrollBar, {}),
4397
+ /* @__PURE__ */ jsx21(ScrollAreaPrimitive.Corner, {})
4407
4398
  ]
4408
4399
  }
4409
4400
  ));
4410
4401
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
4411
- var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(
4402
+ var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx21(
4412
4403
  ScrollAreaPrimitive.ScrollAreaScrollbar,
4413
4404
  {
4414
4405
  ref,
4415
4406
  orientation: "vertical",
4416
4407
  className: cn("flex h-full w-2 touch-none select-none transition-colors", className),
4417
4408
  ...props,
4418
- children: /* @__PURE__ */ jsx19(
4409
+ children: /* @__PURE__ */ jsx21(
4419
4410
  ScrollAreaPrimitive.ScrollAreaThumb,
4420
4411
  {
4421
4412
  className: cn("relative flex-1 rounded-full bg-neutral-200/70 dark:bg-neutral-800")
@@ -4426,10 +4417,11 @@ var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__
4426
4417
  ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
4427
4418
 
4428
4419
  // src/components/databrowser/components/sidebar/infinite-scroll.tsx
4429
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
4420
+ import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
4430
4421
  var InfiniteScroll = ({
4431
4422
  query,
4432
- children
4423
+ children,
4424
+ ...props
4433
4425
  }) => {
4434
4426
  const handleScroll = (e) => {
4435
4427
  const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
@@ -4444,11 +4436,12 @@ var InfiniteScroll = ({
4444
4436
  ScrollArea,
4445
4437
  {
4446
4438
  type: "always",
4447
- className: "block h-full w-full transition-all",
4439
+ className: "block h-full w-full overflow-visible rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all",
4448
4440
  onScroll: handleScroll,
4441
+ ...props,
4449
4442
  children: [
4450
4443
  children,
4451
- /* @__PURE__ */ jsx20("div", { className: "flex h-[100px] justify-center py-2 text-zinc-300", children: query.isFetching && /* @__PURE__ */ jsx20(IconLoader2, { className: "animate-spin", size: 16 }) })
4444
+ /* @__PURE__ */ jsx22("div", { className: "flex h-[100px] justify-center py-2 text-zinc-300", children: query.isFetching && /* @__PURE__ */ jsx22(IconLoader2, { className: "animate-spin", size: 16 }) })
4452
4445
  ]
4453
4446
  }
4454
4447
  );
@@ -4457,6 +4450,18 @@ var InfiniteScroll = ({
4457
4450
  // src/components/databrowser/components/display/display-header.tsx
4458
4451
  import { IconPlus } from "@tabler/icons-react";
4459
4452
 
4453
+ // src/types/index.ts
4454
+ var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
4455
+ var DATA_TYPE_NAMES = {
4456
+ string: "String",
4457
+ list: "List",
4458
+ hash: "Hash",
4459
+ set: "Set",
4460
+ zset: "Sorted Set",
4461
+ json: "JSON",
4462
+ stream: "Stream"
4463
+ };
4464
+
4460
4465
  // src/components/databrowser/components/type-tag.tsx
4461
4466
  import {
4462
4467
  IconArrowsSort,
@@ -4466,15 +4471,15 @@ import {
4466
4471
  IconList,
4467
4472
  IconQuote
4468
4473
  } from "@tabler/icons-react";
4469
- import { jsx as jsx21 } from "react/jsx-runtime";
4474
+ import { jsx as jsx23 } from "react/jsx-runtime";
4470
4475
  var iconsMap = {
4471
- string: /* @__PURE__ */ jsx21(IconQuote, { size: 15, stroke: 1.3 }),
4472
- set: /* @__PURE__ */ jsx21(IconLayersIntersect, { size: 15, stroke: 1.3 }),
4473
- hash: /* @__PURE__ */ jsx21(IconHash, { size: 15, stroke: 1.3 }),
4474
- json: /* @__PURE__ */ jsx21(IconCodeDots, { size: 15, stroke: 1.3 }),
4475
- zset: /* @__PURE__ */ jsx21(IconArrowsSort, { size: 15, stroke: 1.3 }),
4476
- list: /* @__PURE__ */ jsx21(IconList, { size: 15, stroke: 1.3 }),
4477
- stream: /* @__PURE__ */ jsx21(IconList, { size: 15, stroke: 1.3 })
4476
+ string: /* @__PURE__ */ jsx23(IconQuote, { size: 15, stroke: 1.3 }),
4477
+ set: /* @__PURE__ */ jsx23(IconLayersIntersect, { size: 15, stroke: 1.3 }),
4478
+ hash: /* @__PURE__ */ jsx23(IconHash, { size: 15, stroke: 1.3 }),
4479
+ json: /* @__PURE__ */ jsx23(IconCodeDots, { size: 15, stroke: 1.3 }),
4480
+ zset: /* @__PURE__ */ jsx23(IconArrowsSort, { size: 15, stroke: 1.3 }),
4481
+ list: /* @__PURE__ */ jsx23(IconList, { size: 15, stroke: 1.3 }),
4482
+ stream: /* @__PURE__ */ jsx23(IconList, { size: 15, stroke: 1.3 })
4478
4483
  };
4479
4484
  var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-center", {
4480
4485
  variants: {
@@ -4498,7 +4503,7 @@ var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-cent
4498
4503
  }
4499
4504
  });
4500
4505
  function TypeTag({ className, variant, type }) {
4501
- return /* @__PURE__ */ jsx21("span", { className: cn(tagVariants({ variant, type, className })), children: type === "icon" ? iconsMap[variant] : DATA_TYPE_NAMES[variant] });
4506
+ return /* @__PURE__ */ jsx23("span", { className: cn(tagVariants({ variant, type, className })), children: type === "icon" ? iconsMap[variant] : DATA_TYPE_NAMES[variant] });
4502
4507
  }
4503
4508
 
4504
4509
  // src/components/databrowser/components/display/key-actions.tsx
@@ -4508,7 +4513,7 @@ import { IconDotsVertical } from "@tabler/icons-react";
4508
4513
  import * as React10 from "react";
4509
4514
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
4510
4515
  import { CheckIcon as CheckIcon2, ChevronRightIcon as ChevronRightIcon2, DotFilledIcon as DotFilledIcon2 } from "@radix-ui/react-icons";
4511
- import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
4516
+ import { jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
4512
4517
  var DropdownMenu = DropdownMenuPrimitive.Root;
4513
4518
  var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
4514
4519
  var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs14(
@@ -4516,45 +4521,45 @@ var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, .
4516
4521
  {
4517
4522
  ref,
4518
4523
  className: cn(
4519
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-zinc-100 data-[state=open]:bg-zinc-100 dark:focus:bg-zinc-800 dark:data-[state=open]:bg-zinc-800",
4524
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-neutral-100 data-[state=open]:bg-neutral-100 dark:focus:bg-neutral-800 dark:data-[state=open]:bg-neutral-800 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
4520
4525
  inset && "pl-8",
4521
4526
  className
4522
4527
  ),
4523
4528
  ...props,
4524
4529
  children: [
4525
4530
  children,
4526
- /* @__PURE__ */ jsx22(ChevronRightIcon2, { className: "ml-auto size-4" })
4531
+ /* @__PURE__ */ jsx24(ChevronRightIcon2, { className: "ml-auto" })
4527
4532
  ]
4528
4533
  }
4529
4534
  ));
4530
4535
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
4531
- var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
4536
+ var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
4532
4537
  DropdownMenuPrimitive.SubContent,
4533
4538
  {
4534
4539
  ref,
4535
4540
  className: cn(
4536
- "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4541
+ "z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4537
4542
  className
4538
4543
  ),
4539
4544
  ...props
4540
4545
  }
4541
4546
  ));
4542
4547
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
4543
- var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx22(DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx22(
4548
+ var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx24(DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ jsx24(
4544
4549
  DropdownMenuPrimitive.Content,
4545
4550
  {
4546
4551
  ref,
4547
4552
  sideOffset,
4548
4553
  className: cn(
4549
- "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4550
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4554
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4555
+ "origin-[--radix-dropdown-menu-content-transform-origin] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4551
4556
  className
4552
4557
  ),
4553
4558
  ...props
4554
4559
  }
4555
4560
  ) }));
4556
4561
  DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
4557
- var DropdownMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx22(
4562
+ var DropdownMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx24(
4558
4563
  DropdownMenuPrimitive.Item,
4559
4564
  {
4560
4565
  ref,
@@ -4578,7 +4583,7 @@ var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checke
4578
4583
  checked,
4579
4584
  ...props,
4580
4585
  children: [
4581
- /* @__PURE__ */ jsx22("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx22(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx22(CheckIcon2, { className: "size-4" }) }) }),
4586
+ /* @__PURE__ */ jsx24("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx24(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx24(CheckIcon2, { className: "h-4 w-4" }) }) }),
4582
4587
  children
4583
4588
  ]
4584
4589
  }
@@ -4594,13 +4599,13 @@ var DropdownMenuRadioItem = React10.forwardRef(({ className, children, ...props
4594
4599
  ),
4595
4600
  ...props,
4596
4601
  children: [
4597
- /* @__PURE__ */ jsx22("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx22(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx22(DotFilledIcon2, { className: "size-4 fill-current" }) }) }),
4602
+ /* @__PURE__ */ jsx24("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx24(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx24(DotFilledIcon2, { className: "h-2 w-2 fill-current" }) }) }),
4598
4603
  children
4599
4604
  ]
4600
4605
  }
4601
4606
  ));
4602
4607
  DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
4603
- var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx22(
4608
+ var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx24(
4604
4609
  DropdownMenuPrimitive.Label,
4605
4610
  {
4606
4611
  ref,
@@ -4609,7 +4614,7 @@ var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref)
4609
4614
  }
4610
4615
  ));
4611
4616
  DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
4612
- var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
4617
+ var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
4613
4618
  DropdownMenuPrimitive.Separator,
4614
4619
  {
4615
4620
  ref,
@@ -4619,18 +4624,18 @@ var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) =>
4619
4624
  ));
4620
4625
  DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
4621
4626
  var DropdownMenuShortcut = ({ className, ...props }) => {
4622
- return /* @__PURE__ */ jsx22("span", { className: cn("ml-auto text-xs tracking-widest opacity-60", className), ...props });
4627
+ return /* @__PURE__ */ jsx24("span", { className: cn("ml-auto text-xs tracking-widest opacity-60", className), ...props });
4623
4628
  };
4624
4629
  DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4625
4630
 
4626
4631
  // src/components/databrowser/components/display/key-actions.tsx
4627
- import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
4632
+ import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
4628
4633
  function KeyActions({ dataKey, content }) {
4629
4634
  const { mutateAsync: deleteKey } = useDeleteKey();
4630
4635
  return /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
4631
- /* @__PURE__ */ jsx23(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(Button, { size: "icon-sm", children: /* @__PURE__ */ jsx23(IconDotsVertical, { className: "size-4 text-zinc-500" }) }) }),
4636
+ /* @__PURE__ */ jsx25(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { size: "icon-sm", children: /* @__PURE__ */ jsx25(IconDotsVertical, { className: "size-4 text-zinc-500" }) }) }),
4632
4637
  /* @__PURE__ */ jsxs15(DropdownMenuContent, { className: "", align: "end", children: [
4633
- content && /* @__PURE__ */ jsx23(
4638
+ content && /* @__PURE__ */ jsx25(
4634
4639
  DropdownMenuItem,
4635
4640
  {
4636
4641
  onClick: () => {
@@ -4642,12 +4647,12 @@ function KeyActions({ dataKey, content }) {
4642
4647
  children: "Copy content"
4643
4648
  }
4644
4649
  ),
4645
- /* @__PURE__ */ jsx23(
4650
+ /* @__PURE__ */ jsx25(
4646
4651
  DeleteAlertDialog,
4647
4652
  {
4648
4653
  deletionType: "key",
4649
4654
  onDeleteConfirm: async () => await deleteKey(dataKey),
4650
- children: /* @__PURE__ */ jsx23(DropdownMenuItem, { onSelect: (e) => e.preventDefault(), children: "Delete key" })
4655
+ children: /* @__PURE__ */ jsx25(DropdownMenuItem, { onSelect: (e) => e.preventDefault(), children: "Delete key" })
4651
4656
  }
4652
4657
  )
4653
4658
  ] })
@@ -4655,29 +4660,29 @@ function KeyActions({ dataKey, content }) {
4655
4660
  }
4656
4661
 
4657
4662
  // src/components/databrowser/components/display/display-header.tsx
4658
- import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
4663
+ import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
4659
4664
  var DisplayHeader = ({
4660
4665
  dataKey,
4661
4666
  type,
4662
4667
  content
4663
4668
  }) => {
4664
- const { setSelectedListItem } = useDatabrowserStore();
4669
+ const { setSelectedListItem } = useTab();
4665
4670
  const handleAddItem = () => {
4666
4671
  setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true });
4667
4672
  };
4668
- return /* @__PURE__ */ jsxs16("div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
4673
+ return /* @__PURE__ */ jsxs16("div", { className: "rounded-lg bg-zinc-100", children: [
4669
4674
  /* @__PURE__ */ jsxs16("div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4670
- /* @__PURE__ */ jsx24("h2", { className: "grow truncate text-base", children: dataKey.trim() === "" ? /* @__PURE__ */ jsx24("span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ jsx24("span", { className: "font-semibold", children: dataKey }) }),
4675
+ /* @__PURE__ */ jsx26("h2", { className: "grow truncate text-base", children: dataKey.trim() === "" ? /* @__PURE__ */ jsx26("span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ jsx26("span", { className: "font-semibold", children: dataKey }) }),
4671
4676
  /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
4672
- type !== "string" && type !== "json" && /* @__PURE__ */ jsx24(Button, { onClick: handleAddItem, size: "icon-sm", children: /* @__PURE__ */ jsx24(IconPlus, { className: "size-4 text-zinc-500" }) }),
4673
- /* @__PURE__ */ jsx24(KeyActions, { dataKey, content })
4677
+ type !== "string" && type !== "json" && /* @__PURE__ */ jsx26(Button, { onClick: handleAddItem, size: "icon-sm", children: /* @__PURE__ */ jsx26(IconPlus, { className: "size-4 text-zinc-500" }) }),
4678
+ /* @__PURE__ */ jsx26(KeyActions, { dataKey, content })
4674
4679
  ] })
4675
4680
  ] }),
4676
4681
  /* @__PURE__ */ jsxs16("div", { className: "flex h-10 flex-wrap items-center gap-1.5", children: [
4677
- /* @__PURE__ */ jsx24(TypeTag, { variant: type, type: "badge" }),
4678
- /* @__PURE__ */ jsx24(SizeBadge, { dataKey }),
4679
- /* @__PURE__ */ jsx24(LengthBadge, { dataKey, type, content }),
4680
- /* @__PURE__ */ jsx24(HeaderTTLBadge, { dataKey })
4682
+ /* @__PURE__ */ jsx26(TypeTag, { variant: type, type: "badge" }),
4683
+ /* @__PURE__ */ jsx26(SizeBadge, { dataKey }),
4684
+ /* @__PURE__ */ jsx26(LengthBadge, { dataKey, type, content }),
4685
+ /* @__PURE__ */ jsx26(HeaderTTLBadge, { dataKey })
4681
4686
  ] })
4682
4687
  ] });
4683
4688
  };
@@ -4688,10 +4693,10 @@ import { Controller as Controller2, FormProvider, useForm as useForm2, useFormCo
4688
4693
  // src/components/ui/tooltip.tsx
4689
4694
  import * as React11 from "react";
4690
4695
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
4691
- import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
4696
+ import { Fragment as Fragment3, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
4692
4697
  var Tooltip = TooltipPrimitive.Root;
4693
4698
  var TooltipTrigger = TooltipPrimitive.Trigger;
4694
- var TooltipContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx25(
4699
+ var TooltipContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx27(
4695
4700
  TooltipPrimitive.Content,
4696
4701
  {
4697
4702
  ref,
@@ -4708,10 +4713,10 @@ var SimpleTooltip = ({
4708
4713
  content,
4709
4714
  children
4710
4715
  }) => {
4711
- if (!content) return /* @__PURE__ */ jsx25(Fragment3, { children });
4716
+ if (!content) return /* @__PURE__ */ jsx27(Fragment3, { children });
4712
4717
  return /* @__PURE__ */ jsxs17(Tooltip, { delayDuration: 400, children: [
4713
- /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25("div", { children }) }),
4714
- /* @__PURE__ */ jsx25(TooltipContent, { children: content })
4718
+ /* @__PURE__ */ jsx27(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx27("div", { children }) }),
4719
+ /* @__PURE__ */ jsx27(TooltipContent, { children: content })
4715
4720
  ] });
4716
4721
  };
4717
4722
 
@@ -4722,7 +4727,7 @@ var useFetchHashFieldExpires = ({
4722
4727
  dataKey,
4723
4728
  fields
4724
4729
  }) => {
4725
- const { redis } = useDatabrowser();
4730
+ const { redis } = useRedis();
4726
4731
  return useQuery7({
4727
4732
  queryKey: [FETCH_HASH_FIELD_TTLS_QUERY_KEY, dataKey, fields],
4728
4733
  queryFn: async () => {
@@ -4753,7 +4758,7 @@ var useFetchHashFieldExpires = ({
4753
4758
  // src/components/databrowser/hooks/use-set-hash-ttl.ts
4754
4759
  import { useMutation as useMutation6 } from "@tanstack/react-query";
4755
4760
  var useSetHashTTL = () => {
4756
- const { redis } = useDatabrowser();
4761
+ const { redis } = useRedis();
4757
4762
  return useMutation6({
4758
4763
  mutationFn: async ({
4759
4764
  dataKey,
@@ -4771,12 +4776,12 @@ var useSetHashTTL = () => {
4771
4776
  };
4772
4777
 
4773
4778
  // src/components/databrowser/components/display/hash/hash-field-ttl-badge.tsx
4774
- import { jsx as jsx26 } from "react/jsx-runtime";
4779
+ import { jsx as jsx28 } from "react/jsx-runtime";
4775
4780
  var HashFieldTTLBadge = ({ dataKey, field }) => {
4776
4781
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
4777
4782
  const { mutate: setTTL, isPending } = useSetHashTTL();
4778
4783
  const expireAt = data?.[field];
4779
- return /* @__PURE__ */ jsx26(
4784
+ return /* @__PURE__ */ jsx28(
4780
4785
  TTLBadge,
4781
4786
  {
4782
4787
  label: "Field TTL:",
@@ -4788,38 +4793,38 @@ var HashFieldTTLBadge = ({ dataKey, field }) => {
4788
4793
  };
4789
4794
 
4790
4795
  // src/components/databrowser/components/display/input/use-field.tsx
4791
- import { useEffect as useEffect7, useState as useState8 } from "react";
4796
+ import { useEffect as useEffect7, useState as useState7 } from "react";
4792
4797
  import { useController } from "react-hook-form";
4793
4798
 
4794
4799
  // src/components/databrowser/components/display/input/content-type-select.tsx
4795
- import { useMemo as useMemo4 } from "react";
4796
- import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
4800
+ import { useMemo as useMemo6 } from "react";
4801
+ import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
4797
4802
  var ContentTypeSelect = ({
4798
4803
  value,
4799
4804
  onChange,
4800
4805
  data
4801
4806
  }) => {
4802
- const isValidJSON = useMemo4(() => checkIsValidJSON(data), [data]);
4807
+ const isValidJSON = useMemo6(() => checkIsValidJSON(data), [data]);
4803
4808
  return /* @__PURE__ */ jsxs18(Select, { value, onValueChange: onChange, children: [
4804
- /* @__PURE__ */ jsx27(SelectTrigger, { className: "h-6 w-auto border-none bg-transparent pl-0 pr-6 text-xs text-zinc-500", children: /* @__PURE__ */ jsx27(SelectValue, { placeholder: "Text" }) }),
4805
- /* @__PURE__ */ jsx27(SelectContent, { children: /* @__PURE__ */ jsxs18(SelectGroup, { children: [
4806
- /* @__PURE__ */ jsx27(SelectItem, { value: "Text", children: "Text" }),
4807
- /* @__PURE__ */ jsx27(SelectItem, { disabled: !isValidJSON, value: "JSON", children: "JSON" })
4809
+ /* @__PURE__ */ jsx29(SelectTrigger, { className: "h-6 w-auto border-none bg-transparent pl-0 pr-6 text-xs text-zinc-500", children: /* @__PURE__ */ jsx29(SelectValue, { placeholder: "Text" }) }),
4810
+ /* @__PURE__ */ jsx29(SelectContent, { children: /* @__PURE__ */ jsxs18(SelectGroup, { children: [
4811
+ /* @__PURE__ */ jsx29(SelectItem, { value: "Text", children: "Text" }),
4812
+ /* @__PURE__ */ jsx29(SelectItem, { disabled: !isValidJSON, value: "JSON", children: "JSON" })
4808
4813
  ] }) })
4809
4814
  ] });
4810
4815
  };
4811
4816
 
4812
4817
  // src/components/databrowser/components/display/input/custom-editor.tsx
4813
- import { useEffect as useEffect6, useRef as useRef3 } from "react";
4818
+ import { useEffect as useEffect6, useRef } from "react";
4814
4819
  import { Editor, useMonaco } from "@monaco-editor/react";
4815
4820
 
4816
4821
  // src/components/databrowser/copy-button.tsx
4817
- import { useState as useState7 } from "react";
4822
+ import { useState as useState6 } from "react";
4818
4823
  import { IconCheck, IconCopy } from "@tabler/icons-react";
4819
- import { jsx as jsx28 } from "react/jsx-runtime";
4824
+ import { jsx as jsx30 } from "react/jsx-runtime";
4820
4825
  function CopyButton({ value, ...props }) {
4821
- const [copied, setCopied] = useState7(false);
4822
- return /* @__PURE__ */ jsx28(
4826
+ const [copied, setCopied] = useState6(false);
4827
+ return /* @__PURE__ */ jsx30(
4823
4828
  Button,
4824
4829
  {
4825
4830
  onClick: (e) => {
@@ -4836,7 +4841,7 @@ function CopyButton({ value, ...props }) {
4836
4841
  variant: "secondary",
4837
4842
  size: "icon-sm",
4838
4843
  ...props,
4839
- children: copied ? /* @__PURE__ */ jsx28(IconCheck, { className: "size-4 text-green-500" }) : /* @__PURE__ */ jsx28(IconCopy, { className: "size-4 text-zinc-500" })
4844
+ children: copied ? /* @__PURE__ */ jsx30(IconCheck, { className: "size-4 text-green-500" }) : /* @__PURE__ */ jsx30(IconCopy, { className: "size-4 text-zinc-500" })
4840
4845
  }
4841
4846
  );
4842
4847
  }
@@ -4849,7 +4854,7 @@ var handleCopyClick = async (textToCopy) => {
4849
4854
  };
4850
4855
 
4851
4856
  // src/components/databrowser/components/display/input/custom-editor.tsx
4852
- import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
4857
+ import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
4853
4858
  var CustomEditor = ({
4854
4859
  language,
4855
4860
  value,
@@ -4859,7 +4864,7 @@ var CustomEditor = ({
4859
4864
  readOnly
4860
4865
  }) => {
4861
4866
  const monaco = useMonaco();
4862
- const editorRef = useRef3();
4867
+ const editorRef = useRef();
4863
4868
  useEffect6(() => {
4864
4869
  if (!monaco || !editorRef.current) {
4865
4870
  return;
@@ -4874,7 +4879,7 @@ var CustomEditor = ({
4874
4879
  height
4875
4880
  },
4876
4881
  children: [
4877
- /* @__PURE__ */ jsx29(
4882
+ /* @__PURE__ */ jsx31(
4878
4883
  Editor,
4879
4884
  {
4880
4885
  loading: void 0,
@@ -4915,7 +4920,7 @@ var CustomEditor = ({
4915
4920
  }
4916
4921
  }
4917
4922
  ),
4918
- showCopyButton && /* @__PURE__ */ jsx29(
4923
+ showCopyButton && /* @__PURE__ */ jsx31(
4919
4924
  CopyButton,
4920
4925
  {
4921
4926
  value,
@@ -4928,7 +4933,7 @@ var CustomEditor = ({
4928
4933
  };
4929
4934
 
4930
4935
  // src/components/databrowser/components/display/input/use-field.tsx
4931
- import { Fragment as Fragment4, jsx as jsx30 } from "react/jsx-runtime";
4936
+ import { Fragment as Fragment4, jsx as jsx32 } from "react/jsx-runtime";
4932
4937
  var useField = ({
4933
4938
  name,
4934
4939
  form,
@@ -4941,7 +4946,7 @@ var useField = ({
4941
4946
  name,
4942
4947
  control: form.control
4943
4948
  });
4944
- const [contentType, setContentType] = useState8(
4949
+ const [contentType, setContentType] = useState7(
4945
4950
  () => checkIsValidJSON(field.value) ? "JSON" : "Text"
4946
4951
  );
4947
4952
  useEffect7(() => {
@@ -4968,8 +4973,8 @@ var useField = ({
4968
4973
  }
4969
4974
  };
4970
4975
  return {
4971
- selector: /* @__PURE__ */ jsx30(ContentTypeSelect, { value: contentType, onChange: handleTypeChange, data: field.value }),
4972
- editor: /* @__PURE__ */ jsx30(Fragment4, { children: /* @__PURE__ */ jsx30(
4976
+ selector: /* @__PURE__ */ jsx32(ContentTypeSelect, { value: contentType, onChange: handleTypeChange, data: field.value }),
4977
+ editor: /* @__PURE__ */ jsx32(Fragment4, { children: /* @__PURE__ */ jsx32(
4973
4978
  CustomEditor,
4974
4979
  {
4975
4980
  language: contentType === "JSON" ? "json" : "plaintext",
@@ -4993,13 +4998,13 @@ var checkIsValidJSON = (value) => {
4993
4998
  };
4994
4999
 
4995
5000
  // src/components/databrowser/components/display/display-list-edit.tsx
4996
- import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
5001
+ import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
4997
5002
  var ListEditDisplay = ({
4998
5003
  dataKey,
4999
5004
  type,
5000
5005
  item
5001
5006
  }) => {
5002
- return /* @__PURE__ */ jsx31("div", { className: "grow rounded-md bg-zinc-100 p-3", children: /* @__PURE__ */ jsx31(ListEditForm, { item, type, dataKey }, item.key) });
5007
+ return /* @__PURE__ */ jsx33("div", { className: "grow rounded-md bg-zinc-100", children: /* @__PURE__ */ jsx33(ListEditForm, { item, type, dataKey }, item.key) });
5003
5008
  };
5004
5009
  var ListEditForm = ({
5005
5010
  type,
@@ -5025,7 +5030,7 @@ var ListEditForm = ({
5025
5030
  }
5026
5031
  });
5027
5032
  const { mutateAsync: editItem, isPending } = useEditListItem();
5028
- const { setSelectedListItem } = useDatabrowserStore();
5033
+ const { setSelectedListItem } = useTab();
5029
5034
  const [keyLabel, valueLabel] = headerLabels[type];
5030
5035
  const onSubmit = form.handleSubmit(async ({ key, value }) => {
5031
5036
  await editItem({
@@ -5038,9 +5043,9 @@ var ListEditForm = ({
5038
5043
  });
5039
5044
  setSelectedListItem(void 0);
5040
5045
  });
5041
- return /* @__PURE__ */ jsx31(FormProvider, { ...form, children: /* @__PURE__ */ jsxs20("form", { onSubmit, className: "flex flex-col gap-2", children: [
5046
+ return /* @__PURE__ */ jsx33(FormProvider, { ...form, children: /* @__PURE__ */ jsxs20("form", { onSubmit, className: "flex flex-col gap-2", children: [
5042
5047
  /* @__PURE__ */ jsxs20("div", { className: "flex grow flex-col gap-2", children: [
5043
- type !== "list" && /* @__PURE__ */ jsx31(
5048
+ type !== "list" && /* @__PURE__ */ jsx33(
5044
5049
  FormItem,
5045
5050
  {
5046
5051
  readOnly: type === "stream",
@@ -5050,7 +5055,7 @@ var ListEditForm = ({
5050
5055
  data: itemKey
5051
5056
  }
5052
5057
  ),
5053
- type === "zset" ? /* @__PURE__ */ jsx31(NumberFormItem, { name: "value", label: valueLabel }) : type !== "set" && /* @__PURE__ */ jsx31(
5058
+ type === "zset" ? /* @__PURE__ */ jsx33(NumberFormItem, { name: "value", label: valueLabel }) : type !== "set" && /* @__PURE__ */ jsx33(
5054
5059
  FormItem,
5055
5060
  {
5056
5061
  readOnly: type === "stream",
@@ -5069,9 +5074,9 @@ var ListEditForm = ({
5069
5074
  type === "hash" && itemKey !== "" ? "justify-between" : "justify-end"
5070
5075
  ),
5071
5076
  children: [
5072
- type === "hash" && itemKey !== "" && /* @__PURE__ */ jsx31(HashFieldTTLBadge, { dataKey, field: itemKey }),
5077
+ type === "hash" && itemKey !== "" && /* @__PURE__ */ jsx33(HashFieldTTLBadge, { dataKey, field: itemKey }),
5073
5078
  /* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
5074
- /* @__PURE__ */ jsx31(
5079
+ /* @__PURE__ */ jsx33(
5075
5080
  Button,
5076
5081
  {
5077
5082
  type: "button",
@@ -5081,17 +5086,17 @@ var ListEditForm = ({
5081
5086
  children: "Cancel"
5082
5087
  }
5083
5088
  ),
5084
- /* @__PURE__ */ jsx31(
5089
+ /* @__PURE__ */ jsx33(
5085
5090
  SimpleTooltip,
5086
5091
  {
5087
5092
  content: type === "stream" && !isNew ? "Streams are not mutable" : void 0,
5088
- children: /* @__PURE__ */ jsx31(
5093
+ children: /* @__PURE__ */ jsx33(
5089
5094
  Button,
5090
5095
  {
5091
5096
  variant: "primary",
5092
5097
  type: "submit",
5093
5098
  disabled: !form.formState.isValid || !form.formState.isDirty || type === "stream" && !isNew,
5094
- children: /* @__PURE__ */ jsx31(Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" })
5099
+ children: /* @__PURE__ */ jsx33(Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" })
5095
5100
  }
5096
5101
  )
5097
5102
  }
@@ -5104,12 +5109,12 @@ var ListEditForm = ({
5104
5109
  };
5105
5110
  var NumberFormItem = ({ name, label }) => {
5106
5111
  return /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1", children: [
5107
- /* @__PURE__ */ jsx31("div", { className: "flex", children: /* @__PURE__ */ jsx31("span", { className: "text-xs font-medium text-zinc-700", children: label }) }),
5108
- /* @__PURE__ */ jsx31(
5112
+ /* @__PURE__ */ jsx33("div", { className: "flex", children: /* @__PURE__ */ jsx33("span", { className: "text-xs font-medium text-zinc-700", children: label }) }),
5113
+ /* @__PURE__ */ jsx33(
5109
5114
  Controller2,
5110
5115
  {
5111
5116
  name,
5112
- render: ({ field }) => /* @__PURE__ */ jsx31(
5117
+ render: ({ field }) => /* @__PURE__ */ jsx33(
5113
5118
  "input",
5114
5119
  {
5115
5120
  className: "plain-input rounded-md border border-zinc-300 px-3 py-1 shadow-sm",
@@ -5139,18 +5144,18 @@ var FormItem = ({
5139
5144
  });
5140
5145
  return /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1", children: [
5141
5146
  /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1 text-xs", children: [
5142
- /* @__PURE__ */ jsx31("span", { className: "font-medium text-zinc-700", children: label }),
5147
+ /* @__PURE__ */ jsx33("span", { className: "font-medium text-zinc-700", children: label }),
5143
5148
  " ",
5144
- /* @__PURE__ */ jsx31("span", { className: "text-zinc-300", children: "/" }),
5149
+ /* @__PURE__ */ jsx33("span", { className: "text-zinc-300", children: "/" }),
5145
5150
  selector
5146
5151
  ] }),
5147
- /* @__PURE__ */ jsx31("div", { className: "overflow-hidden rounded-md border border-zinc-300 bg-white p-2 shadow-sm", children: editor })
5152
+ /* @__PURE__ */ jsx33("div", { className: "overflow-hidden rounded-md border border-zinc-300 bg-white p-2 shadow-sm", children: editor })
5148
5153
  ] });
5149
5154
  };
5150
5155
 
5151
5156
  // src/components/databrowser/components/display/hash/hash-field-ttl-info.tsx
5152
- import { useEffect as useEffect8, useState as useState9 } from "react";
5153
- import { jsx as jsx32 } from "react/jsx-runtime";
5157
+ import { useEffect as useEffect8, useState as useState8 } from "react";
5158
+ import { jsx as jsx34 } from "react/jsx-runtime";
5154
5159
  var HashFieldTTLInfo = ({
5155
5160
  dataKey,
5156
5161
  field,
@@ -5158,7 +5163,7 @@ var HashFieldTTLInfo = ({
5158
5163
  }) => {
5159
5164
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
5160
5165
  const expireAt = data?.[field];
5161
- const [ttl, setTTL] = useState9(() => calculateTTL(expireAt));
5166
+ const [ttl, setTTL] = useState8(() => calculateTTL(expireAt));
5162
5167
  useEffect8(() => {
5163
5168
  setTTL(calculateTTL(expireAt));
5164
5169
  const interval = setInterval(() => {
@@ -5167,11 +5172,11 @@ var HashFieldTTLInfo = ({
5167
5172
  return () => clearInterval(interval);
5168
5173
  }, [expireAt]);
5169
5174
  if (!expireAt || expireAt === TTL_NOT_FOUND || expireAt === TTL_INFINITE) return;
5170
- return /* @__PURE__ */ jsx32("span", { className: "block min-w-[30px] whitespace-nowrap text-right text-red-600", children: formatTime(ttl ?? 0) });
5175
+ return /* @__PURE__ */ jsx34("span", { className: "block min-w-[30px] whitespace-nowrap text-right text-red-600", children: formatTime(ttl ?? 0) });
5171
5176
  };
5172
5177
 
5173
5178
  // src/components/databrowser/components/display/display-list.tsx
5174
- import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
5179
+ import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
5175
5180
  var headerLabels = {
5176
5181
  list: ["Index", "Content"],
5177
5182
  hash: ["Field", "Value"],
@@ -5180,12 +5185,12 @@ var headerLabels = {
5180
5185
  set: ["Value", ""]
5181
5186
  };
5182
5187
  var ListDisplay = ({ dataKey, type }) => {
5183
- const { selectedListItem } = useDatabrowserStore();
5188
+ const { selectedListItem } = useTab();
5184
5189
  const query = useFetchListItems({ dataKey, type });
5185
5190
  return /* @__PURE__ */ jsxs21("div", { className: "flex h-full flex-col gap-2", children: [
5186
- /* @__PURE__ */ jsx33(DisplayHeader, { dataKey, type }),
5187
- selectedListItem && /* @__PURE__ */ jsx33(ListEditDisplay, { dataKey, type, item: selectedListItem }),
5188
- /* @__PURE__ */ jsx33("div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ jsx33(InfiniteScroll, { query, children: /* @__PURE__ */ jsx33("div", { className: "pr-3", children: /* @__PURE__ */ jsx33("table", { className: "w-full", children: /* @__PURE__ */ jsx33(ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ jsx33("tbody", { children: /* @__PURE__ */ jsx33(ListItems, { dataKey, type, query }) }) }) }) }) }) })
5191
+ /* @__PURE__ */ jsx35(DisplayHeader, { dataKey, type }),
5192
+ selectedListItem && /* @__PURE__ */ jsx35(ListEditDisplay, { dataKey, type, item: selectedListItem }),
5193
+ /* @__PURE__ */ jsx35("div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ jsx35(InfiniteScroll, { query, children: /* @__PURE__ */ jsx35("table", { className: "w-full", children: /* @__PURE__ */ jsx35(ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ jsx35("tbody", { children: /* @__PURE__ */ jsx35(ListItems, { dataKey, type, query }) }) }) }) }) })
5189
5194
  ] });
5190
5195
  };
5191
5196
  var ListItems = ({
@@ -5193,11 +5198,11 @@ var ListItems = ({
5193
5198
  type,
5194
5199
  dataKey
5195
5200
  }) => {
5196
- const { setSelectedListItem } = useDatabrowserStore();
5197
- const keys = useMemo5(() => query.data?.pages.flatMap((page) => page.keys) ?? [], [query.data]);
5198
- const fields = useMemo5(() => keys.map((key) => key.key), [keys]);
5201
+ const { setSelectedListItem } = useTab();
5202
+ const keys = useMemo7(() => query.data?.pages.flatMap((page) => page.keys) ?? [], [query.data]);
5203
+ const fields = useMemo7(() => keys.map((key) => key.key), [keys]);
5199
5204
  const { mutate: editItem } = useEditListItem();
5200
- return /* @__PURE__ */ jsx33(Fragment5, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ jsxs21(
5205
+ return /* @__PURE__ */ jsx35(Fragment5, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ jsxs21(
5201
5206
  "tr",
5202
5207
  {
5203
5208
  "data-item-key": key,
@@ -5205,9 +5210,9 @@ var ListItems = ({
5205
5210
  onClick: () => {
5206
5211
  setSelectedListItem({ key });
5207
5212
  },
5208
- className: cn("h-10 border-b border-b-zinc-100 hover:bg-zinc-100 "),
5213
+ className: cn("h-10 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100"),
5209
5214
  children: [
5210
- /* @__PURE__ */ jsx33(
5215
+ /* @__PURE__ */ jsx35(
5211
5216
  "td",
5212
5217
  {
5213
5218
  className: cn(
@@ -5217,14 +5222,14 @@ var ListItems = ({
5217
5222
  children: key
5218
5223
  }
5219
5224
  ),
5220
- value !== void 0 && /* @__PURE__ */ jsx33(
5225
+ value !== void 0 && /* @__PURE__ */ jsx35(
5221
5226
  "td",
5222
5227
  {
5223
5228
  className: cn("cursor-pointer truncate px-3", type === "zset" ? "w-24" : "max-w-0"),
5224
5229
  children: value
5225
5230
  }
5226
5231
  ),
5227
- type !== "stream" && /* @__PURE__ */ jsx33(
5232
+ type !== "stream" && /* @__PURE__ */ jsx35(
5228
5233
  "td",
5229
5234
  {
5230
5235
  className: "w-0 min-w-0 p-0",
@@ -5232,8 +5237,8 @@ var ListItems = ({
5232
5237
  e.stopPropagation();
5233
5238
  },
5234
5239
  children: /* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-end gap-2", children: [
5235
- type === "hash" && /* @__PURE__ */ jsx33(HashFieldTTLInfo, { dataKey, field: key, fields }),
5236
- /* @__PURE__ */ jsx33(
5240
+ type === "hash" && /* @__PURE__ */ jsx35(HashFieldTTLInfo, { dataKey, field: key, fields }),
5241
+ /* @__PURE__ */ jsx35(
5237
5242
  DeleteAlertDialog,
5238
5243
  {
5239
5244
  deletionType: "item",
@@ -5247,14 +5252,14 @@ var ListItems = ({
5247
5252
  newKey: void 0
5248
5253
  });
5249
5254
  },
5250
- children: /* @__PURE__ */ jsx33(
5255
+ children: /* @__PURE__ */ jsx35(
5251
5256
  Button,
5252
5257
  {
5253
5258
  className: "",
5254
5259
  size: "icon-sm",
5255
5260
  variant: "secondary",
5256
5261
  onClick: (e) => e.stopPropagation(),
5257
- children: /* @__PURE__ */ jsx33(IconTrash, { className: "size-4 text-zinc-500" })
5262
+ children: /* @__PURE__ */ jsx35(IconTrash, { className: "size-4 text-zinc-500" })
5258
5263
  }
5259
5264
  )
5260
5265
  }
@@ -5271,18 +5276,12 @@ var ListItems = ({
5271
5276
  // src/components/databrowser/components/display/display-simple.tsx
5272
5277
  import { useEffect as useEffect9 } from "react";
5273
5278
  import { useForm as useForm3 } from "react-hook-form";
5274
- import { Fragment as Fragment6, jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
5279
+ import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs22 } from "react/jsx-runtime";
5275
5280
  var EditorDisplay = ({ dataKey, type }) => {
5276
5281
  const { data } = useFetchSimpleKey(dataKey, type);
5277
5282
  return /* @__PURE__ */ jsxs22("div", { className: "flex h-full w-full flex-col gap-2", children: [
5278
- /* @__PURE__ */ jsx34(DisplayHeader, { dataKey, type, content: data ?? void 0 }),
5279
- /* @__PURE__ */ jsx34(
5280
- "div",
5281
- {
5282
- className: "flex h-full grow flex-col gap-2\n rounded-md bg-zinc-100 p-3",
5283
- children: data === void 0 ? /* @__PURE__ */ jsx34(Spinner, { isLoadingText: "", isLoading: true }) : data === null ? /* @__PURE__ */ jsx34(Fragment6, {}) : /* @__PURE__ */ jsx34(EditorDisplayForm, { dataKey, type, data }, dataKey)
5284
- }
5285
- )
5283
+ /* @__PURE__ */ jsx36(DisplayHeader, { dataKey, type, content: data ?? void 0 }),
5284
+ /* @__PURE__ */ jsx36("div", { className: "flex h-full grow flex-col gap-2 rounded-md bg-zinc-100", children: data === void 0 ? /* @__PURE__ */ jsx36(Spinner, { isLoadingText: "", isLoading: true }) : data === null ? /* @__PURE__ */ jsx36(Fragment6, {}) : /* @__PURE__ */ jsx36(EditorDisplayForm, { dataKey, type, data }, dataKey) })
5286
5285
  ] });
5287
5286
  };
5288
5287
  var EditorDisplayForm = ({
@@ -5303,12 +5302,12 @@ var EditorDisplayForm = ({
5303
5302
  };
5304
5303
  return /* @__PURE__ */ jsxs22(Fragment6, { children: [
5305
5304
  /* @__PURE__ */ jsxs22("div", { className: "flex grow flex-col gap-1", children: [
5306
- /* @__PURE__ */ jsx34("div", { className: "flex shrink-0 items-center gap-2", children: type === "json" ? /* @__PURE__ */ jsx34("div", {}) : selector }),
5307
- /* @__PURE__ */ jsx34("div", { className: "grow rounded-md border border-zinc-300 bg-white p-1", children: editor })
5305
+ /* @__PURE__ */ jsx36("div", { className: "flex shrink-0 items-center gap-2", children: type === "json" ? /* @__PURE__ */ jsx36("div", {}) : selector }),
5306
+ /* @__PURE__ */ jsx36("div", { className: "grow rounded-md border border-zinc-300 bg-white p-1", children: editor })
5308
5307
  ] }),
5309
- /* @__PURE__ */ jsx34("div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ jsxs22("div", { className: "ml-auto flex gap-2", children: [
5310
- form.formState.isDirty && /* @__PURE__ */ jsx34(Button, { onClick: handleCancel, children: "Cancel" }),
5311
- /* @__PURE__ */ jsx34(
5308
+ /* @__PURE__ */ jsx36("div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ jsxs22("div", { className: "ml-auto flex gap-2", children: [
5309
+ form.formState.isDirty && /* @__PURE__ */ jsx36(Button, { onClick: handleCancel, children: "Cancel" }),
5310
+ /* @__PURE__ */ jsx36(
5312
5311
  Button,
5313
5312
  {
5314
5313
  variant: "primary",
@@ -5316,7 +5315,7 @@ var EditorDisplayForm = ({
5316
5315
  await setKey(value);
5317
5316
  }),
5318
5317
  disabled: !form.formState.isValid || !form.formState.isDirty,
5319
- children: /* @__PURE__ */ jsx34(Spinner, { isLoading: isSettingKey, isLoadingText: "Saving", children: "Save" })
5318
+ children: /* @__PURE__ */ jsx36(Spinner, { isLoading: isSettingKey, isLoadingText: "Saving", children: "Save" })
5320
5319
  }
5321
5320
  )
5322
5321
  ] }) })
@@ -5324,19 +5323,19 @@ var EditorDisplayForm = ({
5324
5323
  };
5325
5324
 
5326
5325
  // src/components/databrowser/components/display/index.tsx
5327
- import { Fragment as Fragment7, jsx as jsx35 } from "react/jsx-runtime";
5326
+ import { Fragment as Fragment7, jsx as jsx37 } from "react/jsx-runtime";
5328
5327
  var DataDisplay = () => {
5329
- const { selectedKey } = useDatabrowserStore();
5328
+ const { selectedKey } = useTab();
5330
5329
  const { query } = useKeys();
5331
5330
  const type = useKeyType(selectedKey);
5332
- return /* @__PURE__ */ jsx35("div", { className: "h-full rounded-xl border bg-white p-1", children: !selectedKey ? /* @__PURE__ */ jsx35("div", {}) : !type ? query.isLoading ? /* @__PURE__ */ jsx35("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx35("span", { className: "text-gray-500", children: "Loading..." }) }) : /* @__PURE__ */ jsx35("div", {}) : /* @__PURE__ */ jsx35(Fragment7, { children: type === "string" || type === "json" ? /* @__PURE__ */ jsx35(EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ jsx35(ListDisplay, { dataKey: selectedKey, type }) }) });
5331
+ return /* @__PURE__ */ jsx37("div", { className: "h-full p-4", children: !selectedKey ? /* @__PURE__ */ jsx37("div", {}) : !type ? query.isLoading ? /* @__PURE__ */ jsx37("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx37("span", { className: "text-gray-500", children: "Loading..." }) }) : /* @__PURE__ */ jsx37("div", {}) : /* @__PURE__ */ jsx37(Fragment7, { children: type === "string" || type === "json" ? /* @__PURE__ */ jsx37(EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ jsx37(ListDisplay, { dataKey: selectedKey, type }) }) });
5333
5332
  };
5334
5333
 
5335
5334
  // src/components/databrowser/components/sidebar/index.tsx
5336
5335
  import { IconRefresh } from "@tabler/icons-react";
5337
5336
 
5338
5337
  // src/components/databrowser/components/add-key-modal.tsx
5339
- import { useState as useState10 } from "react";
5338
+ import { useState as useState9 } from "react";
5340
5339
  import { DialogDescription as DialogDescription2 } from "@radix-ui/react-dialog";
5341
5340
  import { PlusIcon } from "@radix-ui/react-icons";
5342
5341
  import { Controller as Controller3, useForm as useForm4 } from "react-hook-form";
@@ -5344,12 +5343,12 @@ import { Controller as Controller3, useForm as useForm4 } from "react-hook-form"
5344
5343
  // src/components/ui/dialog.tsx
5345
5344
  import * as React12 from "react";
5346
5345
  import * as DialogPrimitive from "@radix-ui/react-dialog";
5347
- import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
5346
+ import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
5348
5347
  var Dialog = DialogPrimitive.Root;
5349
5348
  var DialogTrigger = DialogPrimitive.Trigger;
5350
- var DialogPortal = (props) => /* @__PURE__ */ jsx36(DialogPrimitive.Portal, { container: portalRoot, ...props });
5349
+ var DialogPortal = (props) => /* @__PURE__ */ jsx38(DialogPrimitive.Portal, { container: portalRoot, ...props });
5351
5350
  DialogPortal.displayName = DialogPrimitive.Portal.displayName;
5352
- var DialogOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx36(
5351
+ var DialogOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
5353
5352
  DialogPrimitive.Overlay,
5354
5353
  {
5355
5354
  ref,
@@ -5364,7 +5363,7 @@ var DialogOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__P
5364
5363
  ));
5365
5364
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
5366
5365
  var DialogContent = React12.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs23(DialogPortal, { children: [
5367
- /* @__PURE__ */ jsx36(DialogOverlay, {}),
5366
+ /* @__PURE__ */ jsx38(DialogOverlay, {}),
5368
5367
  /* @__PURE__ */ jsxs23(
5369
5368
  DialogPrimitive.Content,
5370
5369
  {
@@ -5386,7 +5385,7 @@ var DialogContent = React12.forwardRef(({ className, children, ...props }, ref)
5386
5385
  children: [
5387
5386
  children,
5388
5387
  /* @__PURE__ */ jsxs23(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-zinc-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-zinc-100 data-[state=open]:text-zinc-500 dark:ring-offset-zinc-950 dark:focus:ring-zinc-300 dark:data-[state=open]:bg-zinc-800 dark:data-[state=open]:text-zinc-400", children: [
5389
- /* @__PURE__ */ jsx36(
5388
+ /* @__PURE__ */ jsx38(
5390
5389
  "svg",
5391
5390
  {
5392
5391
  width: "15",
@@ -5395,7 +5394,7 @@ var DialogContent = React12.forwardRef(({ className, children, ...props }, ref)
5395
5394
  fill: "none",
5396
5395
  xmlns: "http://www.w3.org/2000/svg",
5397
5396
  className: "h-4 w-4",
5398
- children: /* @__PURE__ */ jsx36(
5397
+ children: /* @__PURE__ */ jsx38(
5399
5398
  "path",
5400
5399
  {
5401
5400
  d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z",
@@ -5406,16 +5405,16 @@ var DialogContent = React12.forwardRef(({ className, children, ...props }, ref)
5406
5405
  )
5407
5406
  }
5408
5407
  ),
5409
- /* @__PURE__ */ jsx36("span", { className: "sr-only", children: "Close" })
5408
+ /* @__PURE__ */ jsx38("span", { className: "sr-only", children: "Close" })
5410
5409
  ] })
5411
5410
  ]
5412
5411
  }
5413
5412
  )
5414
5413
  ] }));
5415
5414
  DialogContent.displayName = DialogPrimitive.Content.displayName;
5416
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx36("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
5415
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx38("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
5417
5416
  DialogHeader.displayName = "DialogHeader";
5418
- var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx36(
5417
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx38(
5419
5418
  "div",
5420
5419
  {
5421
5420
  className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
@@ -5423,7 +5422,7 @@ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx36(
5423
5422
  }
5424
5423
  );
5425
5424
  DialogFooter.displayName = "DialogFooter";
5426
- var DialogTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx36(
5425
+ var DialogTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
5427
5426
  DialogPrimitive.Title,
5428
5427
  {
5429
5428
  ref,
@@ -5432,7 +5431,7 @@ var DialogTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PUR
5432
5431
  }
5433
5432
  ));
5434
5433
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
5435
- var DialogDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx36(
5434
+ var DialogDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
5436
5435
  DialogPrimitive.Description,
5437
5436
  {
5438
5437
  ref,
@@ -5443,10 +5442,10 @@ var DialogDescription = React12.forwardRef(({ className, ...props }, ref) => /*
5443
5442
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
5444
5443
 
5445
5444
  // src/components/databrowser/components/add-key-modal.tsx
5446
- import { jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
5445
+ import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
5447
5446
  function AddKeyModal() {
5448
- const { setSelectedKey } = useDatabrowserStore();
5449
- const [open, setOpen] = useState10(false);
5447
+ const { setSelectedKey } = useTab();
5448
+ const [open, setOpen] = useState9(false);
5450
5449
  const { mutateAsync: addKey, isPending } = useAddKey();
5451
5450
  const { control, handleSubmit, formState, reset } = useForm4({
5452
5451
  defaultValues: {
@@ -5475,24 +5474,24 @@ function AddKeyModal() {
5475
5474
  setOpen(open2);
5476
5475
  },
5477
5476
  children: [
5478
- /* @__PURE__ */ jsx37(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(Button, { variant: "primary", size: "icon-sm", children: /* @__PURE__ */ jsx37(PlusIcon, { className: "size-4" }) }) }),
5477
+ /* @__PURE__ */ jsx39(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsx39(Button, { variant: "primary", size: "icon-sm", children: /* @__PURE__ */ jsx39(PlusIcon, { className: "size-4" }) }) }),
5479
5478
  /* @__PURE__ */ jsxs24(DialogContent, { className: "max-w-[400px]", children: [
5480
- /* @__PURE__ */ jsx37(DialogHeader, { children: /* @__PURE__ */ jsx37(DialogTitle, { children: "Create new key" }) }),
5481
- /* @__PURE__ */ jsx37("div", { className: "sr-only", children: /* @__PURE__ */ jsx37(DialogDescription2, { children: "Create new key" }) }),
5479
+ /* @__PURE__ */ jsx39(DialogHeader, { children: /* @__PURE__ */ jsx39(DialogTitle, { children: "Create new key" }) }),
5480
+ /* @__PURE__ */ jsx39("div", { className: "sr-only", children: /* @__PURE__ */ jsx39(DialogDescription2, { children: "Create new key" }) }),
5482
5481
  /* @__PURE__ */ jsxs24("form", { className: "mt-4", onSubmit, children: [
5483
5482
  /* @__PURE__ */ jsxs24("div", { className: "flex gap-1", children: [
5484
- /* @__PURE__ */ jsx37(
5483
+ /* @__PURE__ */ jsx39(
5485
5484
  Controller3,
5486
5485
  {
5487
5486
  control,
5488
5487
  name: "type",
5489
5488
  render: ({ field }) => /* @__PURE__ */ jsxs24(Select, { value: field.value, onValueChange: field.onChange, children: [
5490
- /* @__PURE__ */ jsx37(SelectTrigger, { className: "h-8 w-auto pl-[3px] pr-8", children: /* @__PURE__ */ jsx37(SelectValue, {}) }),
5491
- /* @__PURE__ */ jsx37(SelectContent, { children: /* @__PURE__ */ jsx37(SelectGroup, { children: DATA_TYPES.map((type) => /* @__PURE__ */ jsx37(SelectItem, { value: type, children: /* @__PURE__ */ jsx37(TypeTag, { variant: type, type: "badge" }) }, type)) }) })
5489
+ /* @__PURE__ */ jsx39(SelectTrigger, { className: "h-8 w-auto pl-[3px] pr-8", children: /* @__PURE__ */ jsx39(SelectValue, {}) }),
5490
+ /* @__PURE__ */ jsx39(SelectContent, { children: /* @__PURE__ */ jsx39(SelectGroup, { children: DATA_TYPES.map((type) => /* @__PURE__ */ jsx39(SelectItem, { value: type, children: /* @__PURE__ */ jsx39(TypeTag, { variant: type, type: "badge" }) }, type)) }) })
5492
5491
  ] })
5493
5492
  }
5494
5493
  ),
5495
- /* @__PURE__ */ jsx37(
5494
+ /* @__PURE__ */ jsx39(
5496
5495
  Controller3,
5497
5496
  {
5498
5497
  rules: {
@@ -5500,14 +5499,14 @@ function AddKeyModal() {
5500
5499
  },
5501
5500
  control,
5502
5501
  name: "key",
5503
- render: ({ field }) => /* @__PURE__ */ jsx37(Input, { placeholder: "mykey", ...field, className: "h-8 grow" })
5502
+ render: ({ field }) => /* @__PURE__ */ jsx39(Input, { placeholder: "mykey", ...field, className: "h-8 grow" })
5504
5503
  }
5505
5504
  )
5506
5505
  ] }),
5507
- formState.errors.key && /* @__PURE__ */ jsx37("p", { className: "mb-3 mt-2 text-xs text-red-500", children: formState.errors.key?.message }),
5508
- /* @__PURE__ */ jsx37("p", { className: "mt-2 text-xs text-zinc-500", children: "After creating the key, you can edit the value" }),
5506
+ formState.errors.key && /* @__PURE__ */ jsx39("p", { className: "mb-3 mt-2 text-xs text-red-500", children: formState.errors.key?.message }),
5507
+ /* @__PURE__ */ jsx39("p", { className: "mt-2 text-xs text-zinc-500", children: "After creating the key, you can edit the value" }),
5509
5508
  /* @__PURE__ */ jsxs24("div", { className: "mt-6 flex justify-end gap-2", children: [
5510
- /* @__PURE__ */ jsx37(
5509
+ /* @__PURE__ */ jsx39(
5511
5510
  Button,
5512
5511
  {
5513
5512
  type: "button",
@@ -5518,7 +5517,7 @@ function AddKeyModal() {
5518
5517
  children: "Cancel"
5519
5518
  }
5520
5519
  ),
5521
- /* @__PURE__ */ jsx37(Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ jsx37(Spinner, { isLoading: isPending, isLoadingText: "Creating", children: "Create" }) })
5520
+ /* @__PURE__ */ jsx39(Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ jsx39(Spinner, { isLoading: isPending, isLoadingText: "Creating", children: "Create" }) })
5522
5521
  ] })
5523
5522
  ] })
5524
5523
  ] })
@@ -5528,24 +5527,24 @@ function AddKeyModal() {
5528
5527
  }
5529
5528
 
5530
5529
  // src/components/databrowser/components/sidebar/empty.tsx
5531
- import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
5530
+ import { jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
5532
5531
  var Empty = () => {
5533
- return /* @__PURE__ */ jsx38("div", { className: "flex h-full w-full items-center justify-center rounded-md border border-dashed px-4 py-6 text-center", children: /* @__PURE__ */ jsxs25("div", { className: "space-y-5", children: [
5534
- /* @__PURE__ */ jsx38("p", { className: "text-md font-medium", children: "Data on a break" }),
5535
- /* @__PURE__ */ jsx38("p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
5532
+ return /* @__PURE__ */ jsx40("div", { className: "flex h-full w-full items-center justify-center rounded-md border border-dashed px-4 py-6 text-center", children: /* @__PURE__ */ jsxs25("div", { className: "space-y-5", children: [
5533
+ /* @__PURE__ */ jsx40("p", { className: "text-md font-medium", children: "Data on a break" }),
5534
+ /* @__PURE__ */ jsx40("p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
5536
5535
  ] }) });
5537
5536
  };
5538
5537
 
5539
5538
  // src/components/databrowser/components/sidebar-context-menu.tsx
5540
- import { useState as useState11 } from "react";
5539
+ import { useState as useState10 } from "react";
5541
5540
  import { ContextMenuSeparator as ContextMenuSeparator3 } from "@radix-ui/react-context-menu";
5542
- import { Fragment as Fragment8, jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
5541
+ import { Fragment as Fragment8, jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
5543
5542
  var SidebarContextMenu = ({ children }) => {
5544
5543
  const { mutate: deleteKey } = useDeleteKey();
5545
- const [isAlertOpen, setAlertOpen] = useState11(false);
5546
- const [dataKey, setDataKey] = useState11("");
5544
+ const [isAlertOpen, setAlertOpen] = useState10(false);
5545
+ const [dataKey, setDataKey] = useState10("");
5547
5546
  return /* @__PURE__ */ jsxs26(Fragment8, { children: [
5548
- /* @__PURE__ */ jsx39(
5547
+ /* @__PURE__ */ jsx41(
5549
5548
  DeleteAlertDialog,
5550
5549
  {
5551
5550
  deletionType: "key",
@@ -5559,7 +5558,7 @@ var SidebarContextMenu = ({ children }) => {
5559
5558
  }
5560
5559
  ),
5561
5560
  /* @__PURE__ */ jsxs26(ContextMenu, { children: [
5562
- /* @__PURE__ */ jsx39(
5561
+ /* @__PURE__ */ jsx41(
5563
5562
  ContextMenuTrigger,
5564
5563
  {
5565
5564
  onContextMenu: (e) => {
@@ -5575,7 +5574,7 @@ var SidebarContextMenu = ({ children }) => {
5575
5574
  }
5576
5575
  ),
5577
5576
  /* @__PURE__ */ jsxs26(ContextMenuContent, { children: [
5578
- /* @__PURE__ */ jsx39(
5577
+ /* @__PURE__ */ jsx41(
5579
5578
  ContextMenuItem,
5580
5579
  {
5581
5580
  onClick: () => {
@@ -5587,18 +5586,18 @@ var SidebarContextMenu = ({ children }) => {
5587
5586
  children: "Copy key"
5588
5587
  }
5589
5588
  ),
5590
- /* @__PURE__ */ jsx39(ContextMenuSeparator3, {}),
5591
- /* @__PURE__ */ jsx39(ContextMenuItem, { onClick: () => setAlertOpen(true), children: "Delete key" })
5589
+ /* @__PURE__ */ jsx41(ContextMenuSeparator3, {}),
5590
+ /* @__PURE__ */ jsx41(ContextMenuItem, { onClick: () => setAlertOpen(true), children: "Delete key" })
5592
5591
  ] })
5593
5592
  ] })
5594
5593
  ] });
5595
5594
  };
5596
5595
 
5597
5596
  // src/components/databrowser/components/sidebar/keys-list.tsx
5598
- import { Fragment as Fragment9, jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
5597
+ import { Fragment as Fragment9, jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
5599
5598
  var KeysList = () => {
5600
5599
  const { keys } = useKeys();
5601
- return /* @__PURE__ */ jsx40("div", { className: "pr-3", children: /* @__PURE__ */ jsx40(SidebarContextMenu, { children: /* @__PURE__ */ jsx40(Fragment9, { children: keys.map((data, i) => /* @__PURE__ */ jsx40(KeyItem, { nextKey: keys.at(i + 1)?.[0] ?? "", data }, data[0])) }) }) });
5600
+ return /* @__PURE__ */ jsx42(SidebarContextMenu, { children: /* @__PURE__ */ jsx42(Fragment9, { children: keys.map((data, i) => /* @__PURE__ */ jsx42(KeyItem, { nextKey: keys.at(i + 1)?.[0] ?? "", data }, data[0])) }) });
5602
5601
  };
5603
5602
  var keyStyles = {
5604
5603
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5610,7 +5609,7 @@ var keyStyles = {
5610
5609
  stream: "border-green-400 !bg-green-50 text-green-900"
5611
5610
  };
5612
5611
  var KeyItem = ({ data, nextKey }) => {
5613
- const { selectedKey, setSelectedKey } = useDatabrowserStore();
5612
+ const { selectedKey, setSelectedKey } = useTab();
5614
5613
  const [dataKey, dataType] = data;
5615
5614
  const isKeySelected = selectedKey === dataKey;
5616
5615
  const isNextKeySelected = selectedKey === nextKey;
@@ -5620,49 +5619,125 @@ var KeyItem = ({ data, nextKey }) => {
5620
5619
  "data-key": dataKey,
5621
5620
  variant: isKeySelected ? "default" : "ghost",
5622
5621
  className: cn(
5623
- "relative flex h-10 w-full items-center justify-start gap-2 px-3 py-0 ",
5622
+ "relative flex h-10 w-full items-center justify-start gap-2 px-3 py-0 !ring-0 focus-visible:bg-zinc-50",
5624
5623
  "select-none border border-transparent text-left",
5625
5624
  isKeySelected && "shadow-sm",
5626
5625
  isKeySelected && keyStyles[dataType]
5627
5626
  ),
5628
5627
  onClick: () => setSelectedKey(dataKey),
5629
5628
  children: [
5630
- /* @__PURE__ */ jsx40(TypeTag, { variant: dataType, type: "icon" }),
5631
- /* @__PURE__ */ jsx40("p", { className: "truncate whitespace-nowrap", children: dataKey }),
5632
- !isKeySelected && !isNextKeySelected && /* @__PURE__ */ jsx40("span", { className: "absolute -bottom-px left-3 right-3 h-px bg-zinc-100" })
5629
+ /* @__PURE__ */ jsx42(TypeTag, { variant: dataType, type: "icon" }),
5630
+ /* @__PURE__ */ jsx42("p", { className: "truncate whitespace-nowrap", children: dataKey }),
5631
+ !isKeySelected && !isNextKeySelected && /* @__PURE__ */ jsx42("span", { className: "absolute -bottom-px left-3 right-3 h-px bg-zinc-100" })
5633
5632
  ]
5634
5633
  }
5635
5634
  );
5636
5635
  };
5637
5636
 
5638
5637
  // src/components/databrowser/components/sidebar/search-input.tsx
5639
- import { useState as useState12 } from "react";
5638
+ import { useState as useState11, useRef as useRef2, useEffect as useEffect10 } from "react";
5640
5639
  import { IconX } from "@tabler/icons-react";
5641
- import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
5640
+ import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
5641
+ var dedupeSearchHistory = (history) => {
5642
+ const seen = /* @__PURE__ */ new Set();
5643
+ return history.filter((item) => {
5644
+ if (!item || seen.has(item)) return false;
5645
+ seen.add(item);
5646
+ return true;
5647
+ });
5648
+ };
5642
5649
  var SearchInput = () => {
5643
- const { setSearchKey, search } = useDatabrowserStore();
5644
- const [state, setState] = useState12(search.key);
5645
- const submit = (value) => {
5650
+ const { setSearchKey, search } = useTab();
5651
+ const { searchHistory, addSearchHistory } = useDatabrowserStore();
5652
+ const [state, setState] = useState11(search.key);
5653
+ const [isFocus, setIsFocus] = useState11(false);
5654
+ const [focusedIndex, setFocusedIndex] = useState11(-1);
5655
+ const inputRef = useRef2(null);
5656
+ const historyItemRefs = useRef2([]);
5657
+ const handleSubmit = (value) => {
5646
5658
  if (value.trim() !== "" && !value.includes("*")) value = `${value}*`;
5659
+ addSearchHistory(value);
5647
5660
  setSearchKey(value);
5648
5661
  setState(value);
5649
5662
  };
5650
- return /* @__PURE__ */ jsxs28("div", { className: "relative grow", children: [
5651
- /* @__PURE__ */ jsx41(
5652
- Input,
5653
- {
5654
- placeholder: "Search",
5655
- className: "rounded-l-none border-zinc-300 font-normal",
5656
- onKeyDown: (e) => {
5657
- if (e.key === "Enter") submit(e.currentTarget.value);
5658
- },
5659
- onChange: (e) => {
5660
- setState(e.currentTarget.value);
5661
- if (e.currentTarget.value.trim() === "") submit("");
5662
- },
5663
- value: state
5663
+ const filteredHistory = dedupeSearchHistory(
5664
+ searchHistory.filter((item) => item.includes(state) && item !== state)
5665
+ ).slice(0, 5).map((item) => item.endsWith("*") ? item.slice(0, -1) : item);
5666
+ useEffect10(() => {
5667
+ setFocusedIndex(-1);
5668
+ }, [filteredHistory.length]);
5669
+ const handleKeyDown = (e) => {
5670
+ if (e.key === "Enter") {
5671
+ const text = focusedIndex >= 0 && focusedIndex < filteredHistory.length ? filteredHistory[focusedIndex] : e.currentTarget.value;
5672
+ handleSubmit(text);
5673
+ } else if (e.key === "Escape") {
5674
+ setState("");
5675
+ setFocusedIndex(-1);
5676
+ inputRef.current?.blur();
5677
+ } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
5678
+ e.preventDefault();
5679
+ if (focusedIndex < filteredHistory.length - 1) {
5680
+ setFocusedIndex(focusedIndex + 1);
5681
+ } else if (filteredHistory.length > 0) {
5682
+ setFocusedIndex(0);
5664
5683
  }
5665
- ),
5684
+ } else if (e.key === "ArrowUp" || e.key === "Tab" && e.shiftKey) {
5685
+ e.preventDefault();
5686
+ if (focusedIndex > 0) {
5687
+ setFocusedIndex(focusedIndex - 1);
5688
+ } else if (filteredHistory.length > 0 && focusedIndex === 0) {
5689
+ setFocusedIndex(-1);
5690
+ inputRef.current?.focus();
5691
+ } else if (filteredHistory.length > 0) {
5692
+ setFocusedIndex(filteredHistory.length - 1);
5693
+ }
5694
+ }
5695
+ };
5696
+ return /* @__PURE__ */ jsxs28("div", { className: "relative grow", children: [
5697
+ /* @__PURE__ */ jsxs28(Popover, { open: isFocus && filteredHistory.length > 0, children: [
5698
+ /* @__PURE__ */ jsx43(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx43("div", { children: /* @__PURE__ */ jsx43(
5699
+ Input,
5700
+ {
5701
+ ref: inputRef,
5702
+ placeholder: "Search",
5703
+ className: "rounded-l-none border-zinc-300 font-normal",
5704
+ onKeyDown: handleKeyDown,
5705
+ onChange: (e) => {
5706
+ setState(e.currentTarget.value);
5707
+ if (e.currentTarget.value.trim() === "") handleSubmit("");
5708
+ },
5709
+ value: state,
5710
+ onFocus: () => {
5711
+ setIsFocus(true);
5712
+ setFocusedIndex(-1);
5713
+ },
5714
+ onBlur: () => setIsFocus(false)
5715
+ }
5716
+ ) }) }),
5717
+ /* @__PURE__ */ jsx43(
5718
+ PopoverContent,
5719
+ {
5720
+ className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
5721
+ autoFocus: false,
5722
+ onOpenAutoFocus: (e) => {
5723
+ e.preventDefault();
5724
+ e.stopPropagation();
5725
+ },
5726
+ children: filteredHistory.map((item, index) => /* @__PURE__ */ jsx43("div", { className: "w-full py-[3px]", children: /* @__PURE__ */ jsx43(
5727
+ "button",
5728
+ {
5729
+ ref: (el) => {
5730
+ historyItemRefs.current[index] = el;
5731
+ },
5732
+ onClick: () => handleSubmit(item),
5733
+ onMouseEnter: () => setFocusedIndex(index),
5734
+ className: `block w-full rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
5735
+ children: item
5736
+ }
5737
+ ) }, item))
5738
+ }
5739
+ )
5740
+ ] }),
5666
5741
  state && /* @__PURE__ */ jsxs28(
5667
5742
  Button,
5668
5743
  {
@@ -5675,27 +5750,28 @@ var SearchInput = () => {
5675
5750
  setState("");
5676
5751
  },
5677
5752
  children: [
5678
- /* @__PURE__ */ jsx41(IconX, { size: 16 }),
5679
- /* @__PURE__ */ jsx41("span", { className: "sr-only", children: "Clear" })
5753
+ /* @__PURE__ */ jsx43(IconX, { size: 16 }),
5754
+ /* @__PURE__ */ jsx43("span", { className: "sr-only", children: "Clear" })
5680
5755
  ]
5681
5756
  }
5682
- )
5757
+ ),
5758
+ " "
5683
5759
  ] });
5684
5760
  };
5685
5761
 
5686
5762
  // src/components/databrowser/components/sidebar/skeleton-buttons.tsx
5687
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
5763
+ import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
5688
5764
  var DEFAULT_SKELETON_COUNT = 6;
5689
- var LoadingSkeleton = () => /* @__PURE__ */ jsx42("div", { className: "grid", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ jsxs29("div", { className: "flex h-10 items-center gap-2 px-3", children: [
5690
- /* @__PURE__ */ jsx42(Skeleton, { className: "size-5 shrink-0 rounded" }),
5691
- /* @__PURE__ */ jsx42(Skeleton, { className: "h-4 grow rounded" })
5765
+ var LoadingSkeleton = () => /* @__PURE__ */ jsx44("div", { className: "grid", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ jsxs29("div", { className: "flex h-10 items-center gap-2 px-3", children: [
5766
+ /* @__PURE__ */ jsx44(Skeleton, { className: "size-5 shrink-0 rounded" }),
5767
+ /* @__PURE__ */ jsx44(Skeleton, { className: "h-4 grow rounded" })
5692
5768
  ] }, idx)) });
5693
5769
 
5694
5770
  // src/components/databrowser/components/sidebar/type-selector.tsx
5695
- import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
5771
+ import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
5696
5772
  var ALL_TYPES_KEY = "all";
5697
5773
  function DataTypeSelector() {
5698
- const { search, setSearchType } = useDatabrowserStore();
5774
+ const { search, setSearchType } = useTab();
5699
5775
  return /* @__PURE__ */ jsxs30(
5700
5776
  Select,
5701
5777
  {
@@ -5708,9 +5784,9 @@ function DataTypeSelector() {
5708
5784
  },
5709
5785
  value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
5710
5786
  children: [
5711
- /* @__PURE__ */ jsx43(SelectTrigger, { className: "!w-auto select-none whitespace-nowrap rounded-r-none border-r-0 border-zinc-300 pr-8", children: /* @__PURE__ */ jsx43(SelectValue, {}) }),
5712
- /* @__PURE__ */ jsx43(SelectContent, { children: /* @__PURE__ */ jsx43(SelectGroup, { children: Object.entries(DATA_TYPE_NAMES).map(
5713
- ([key, value]) => /* @__PURE__ */ jsx43(SelectItem, { value: key, children: value }, key)
5787
+ /* @__PURE__ */ jsx45(SelectTrigger, { className: "!w-auto select-none whitespace-nowrap rounded-r-none border-r-0 border-zinc-300 pr-8", children: /* @__PURE__ */ jsx45(SelectValue, {}) }),
5788
+ /* @__PURE__ */ jsx45(SelectContent, { children: /* @__PURE__ */ jsx45(SelectGroup, { children: [[ALL_TYPES_KEY, "All Types"], ...Object.entries(DATA_TYPE_NAMES)].map(
5789
+ ([key, value]) => /* @__PURE__ */ jsx45(SelectItem, { value: key, children: value }, key)
5714
5790
  ) }) })
5715
5791
  ]
5716
5792
  }
@@ -5718,20 +5794,22 @@ function DataTypeSelector() {
5718
5794
  }
5719
5795
 
5720
5796
  // src/components/databrowser/components/sidebar/index.tsx
5721
- import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
5797
+ import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
5722
5798
  function Sidebar() {
5723
- const { keys, query, refetch } = useKeys();
5724
- return /* @__PURE__ */ jsxs31("div", { className: "flex h-full flex-col gap-2 rounded-xl border bg-white p-1", children: [
5725
- /* @__PURE__ */ jsxs31("div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
5799
+ const { keys, query } = useKeys();
5800
+ return /* @__PURE__ */ jsxs31("div", { className: "flex h-full flex-col gap-2 p-4", children: [
5801
+ /* @__PURE__ */ jsxs31("div", { className: "rounded-lg bg-zinc-100", children: [
5726
5802
  /* @__PURE__ */ jsxs31("div", { className: "flex h-10 items-center justify-between pl-1", children: [
5727
- /* @__PURE__ */ jsx44(DisplayDbSize, {}),
5803
+ /* @__PURE__ */ jsx46(DisplayDbSize, {}),
5728
5804
  /* @__PURE__ */ jsxs31("div", { className: "flex gap-1", children: [
5729
- /* @__PURE__ */ jsx44(
5805
+ /* @__PURE__ */ jsx46(
5730
5806
  Button,
5731
5807
  {
5732
5808
  className: "h-7 w-7 px-0",
5733
5809
  onClick: () => {
5734
- refetch();
5810
+ queryClient.invalidateQueries({
5811
+ queryKey: [FETCH_KEYS_QUERY_KEY]
5812
+ });
5735
5813
  queryClient.invalidateQueries({
5736
5814
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
5737
5815
  });
@@ -5745,32 +5823,28 @@ function Sidebar() {
5745
5823
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
5746
5824
  });
5747
5825
  },
5748
- children: /* @__PURE__ */ jsx44(Spinner, { isLoading: query.isFetching, children: /* @__PURE__ */ jsx44(IconRefresh, { size: 16 }) })
5826
+ children: /* @__PURE__ */ jsx46(Spinner, { isLoading: query.isFetching, children: /* @__PURE__ */ jsx46(IconRefresh, { size: 16 }) })
5749
5827
  }
5750
5828
  ),
5751
- /* @__PURE__ */ jsx44(AddKeyModal, {})
5829
+ /* @__PURE__ */ jsx46(AddKeyModal, {})
5752
5830
  ] })
5753
5831
  ] }),
5754
5832
  /* @__PURE__ */ jsxs31("div", { className: "flex h-10 items-center", children: [
5755
- /* @__PURE__ */ jsx44(DataTypeSelector, {}),
5756
- /* @__PURE__ */ jsx44(SearchInput, {})
5833
+ /* @__PURE__ */ jsx46(DataTypeSelector, {}),
5834
+ /* @__PURE__ */ jsx46(SearchInput, {})
5757
5835
  ] })
5758
5836
  ] }),
5759
- query.isLoading && keys.length === 0 ? /* @__PURE__ */ jsx44(LoadingSkeleton, {}) : keys.length > 0 ? (
5837
+ query.isLoading && keys.length === 0 ? /* @__PURE__ */ jsx46(LoadingSkeleton, {}) : keys.length > 0 ? (
5760
5838
  // Infinite scroll already has a loader at the bottom
5761
- /* @__PURE__ */ jsx44(InfiniteScroll, { query, children: /* @__PURE__ */ jsx44(KeysList, {}) })
5762
- ) : /* @__PURE__ */ jsx44(Empty, {})
5839
+ /* @__PURE__ */ jsx46(InfiniteScroll, { query, roundedInherit: false, children: /* @__PURE__ */ jsx46(KeysList, {}) })
5840
+ ) : /* @__PURE__ */ jsx46(Empty, {})
5763
5841
  ] });
5764
5842
  }
5765
5843
 
5766
- // src/components/databrowser/index.tsx
5767
- import { jsx as jsx45, jsxs as jsxs32 } from "react/jsx-runtime";
5768
- var RedisBrowser = ({ token, url }) => {
5769
- const credentials = useMemo6(() => ({ token, url }), [token, url]);
5770
- useEffect10(() => {
5771
- queryClient.resetQueries();
5772
- }, [credentials.url]);
5773
- return /* @__PURE__ */ jsx45(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx45(TooltipProvider, { children: /* @__PURE__ */ jsx45(DatabrowserProvider, { redisCredentials: credentials, children: /* @__PURE__ */ jsx45(KeysProvider, { children: /* @__PURE__ */ jsxs32("div", { className: "ups-db", style: { height: "100%" }, children: [
5844
+ // src/components/databrowser/components/databrowser-instance.tsx
5845
+ import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
5846
+ var DatabrowserInstance = ({ hidden }) => {
5847
+ return /* @__PURE__ */ jsx47(KeysProvider, { children: /* @__PURE__ */ jsxs32("div", { className: cn("h-full rounded-md bg-zinc-100", hidden && "hidden"), children: [
5774
5848
  /* @__PURE__ */ jsxs32(
5775
5849
  PanelGroup,
5776
5850
  {
@@ -5778,22 +5852,97 @@ var RedisBrowser = ({ token, url }) => {
5778
5852
  direction: "horizontal",
5779
5853
  className: "h-full w-full gap-0.5 text-sm antialiased",
5780
5854
  children: [
5781
- /* @__PURE__ */ jsx45(Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ jsx45(Sidebar, {}) }),
5782
- /* @__PURE__ */ jsx45(PanelResizeHandle, { className: "h-fullm flex w-1.5 items-center justify-center rounded-full hover:bg-zinc-300/20", children: /* @__PURE__ */ jsx45(
5783
- IconDotsVertical2,
5784
- {
5785
- size: 16,
5786
- stroke: 1,
5787
- className: "pointer-events-none shrink-0 opacity-20"
5788
- }
5789
- ) }),
5790
- /* @__PURE__ */ jsx45(Panel, { minSize: 40, children: /* @__PURE__ */ jsx45(DataDisplay, {}) })
5855
+ /* @__PURE__ */ jsx47(Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ jsx47(Sidebar, {}) }),
5856
+ /* @__PURE__ */ jsx47(PanelResizeHandle, { className: "group flex h-full w-1.5 justify-center", children: /* @__PURE__ */ jsx47("div", { className: "h-full border-r border-dashed border-zinc-200 transition-colors group-hover:border-zinc-300" }) }),
5857
+ /* @__PURE__ */ jsx47(Panel, { minSize: 40, children: /* @__PURE__ */ jsx47(DataDisplay, {}) })
5791
5858
  ]
5792
5859
  }
5793
5860
  ),
5794
- /* @__PURE__ */ jsx45(Toaster, {})
5861
+ /* @__PURE__ */ jsx47(Toaster, {})
5862
+ ] }) });
5863
+ };
5864
+
5865
+ // src/components/databrowser/components/databrowser-tabs.tsx
5866
+ import { IconPlus as IconPlus2, IconX as IconX2 } from "@tabler/icons-react";
5867
+
5868
+ // src/components/databrowser/components/tab-type-icon.tsx
5869
+ import { jsx as jsx48 } from "react/jsx-runtime";
5870
+ function TabTypeIcon({ selectedKey }) {
5871
+ const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
5872
+ if (isLoading) return /* @__PURE__ */ jsx48(Skeleton, { className: "h-5 w-5 rounded" });
5873
+ if (!keyType || keyType === "none") return;
5874
+ return /* @__PURE__ */ jsx48(TypeTag, { variant: keyType, type: "icon" });
5875
+ }
5876
+
5877
+ // src/components/databrowser/components/databrowser-tabs.tsx
5878
+ import { Fragment as Fragment10, jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
5879
+ var Tab = ({ id }) => {
5880
+ const { selectTab, selectedTab, tabs, removeTab } = useDatabrowserStore();
5881
+ return /* @__PURE__ */ jsxs33(
5882
+ "div",
5883
+ {
5884
+ onClick: () => selectTab(id),
5885
+ className: cn(
5886
+ "flex h-9 translate-y-[1px] cursor-pointer items-center gap-2 rounded-t-lg border border-zinc-200 px-3 text-[13px] transition-colors",
5887
+ id === selectedTab ? "border-b-white bg-white text-zinc-900" : "bg-zinc-100 hover:bg-zinc-50"
5888
+ ),
5889
+ children: [
5890
+ tabs[id].selectedKey ? /* @__PURE__ */ jsxs33(Fragment10, { children: [
5891
+ /* @__PURE__ */ jsx49(TabTypeIcon, { selectedKey: tabs[id].selectedKey }),
5892
+ /* @__PURE__ */ jsx49("span", { className: "max-w-32 truncate", children: tabs[id].selectedKey })
5893
+ ] }) : "New Tab",
5894
+ Object.keys(tabs).length > 1 && /* @__PURE__ */ jsx49(
5895
+ "button",
5896
+ {
5897
+ onClick: (e) => {
5898
+ e.stopPropagation();
5899
+ removeTab(id);
5900
+ },
5901
+ className: "p-1 text-zinc-300 transition-colors hover:text-zinc-500",
5902
+ children: /* @__PURE__ */ jsx49(IconX2, { size: 16 })
5903
+ }
5904
+ )
5905
+ ]
5906
+ }
5907
+ );
5908
+ };
5909
+ var DatabrowserTabs = () => {
5910
+ const { tabs, addTab } = useDatabrowserStore();
5911
+ return /* @__PURE__ */ jsxs33("div", { className: "mb-2 flex items-center gap-1 border-b border-zinc-200", children: [
5912
+ Object.keys(tabs).map((id) => /* @__PURE__ */ jsx49(Tab, { id }, id)),
5913
+ /* @__PURE__ */ jsx49(
5914
+ Button,
5915
+ {
5916
+ variant: "secondary",
5917
+ size: "icon-sm",
5918
+ onClick: addTab,
5919
+ className: "mr-1 flex-shrink-0",
5920
+ title: "Add new tab",
5921
+ children: /* @__PURE__ */ jsx49(IconPlus2, { className: "text-zinc-500", size: 16 })
5922
+ }
5923
+ )
5924
+ ] });
5925
+ };
5926
+
5927
+ // src/components/databrowser/index.tsx
5928
+ import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
5929
+ var RedisBrowser = ({ token, url }) => {
5930
+ const credentials = useMemo8(() => ({ token, url }), [token, url]);
5931
+ useEffect11(() => {
5932
+ queryClient.resetQueries();
5933
+ }, [credentials.url]);
5934
+ return /* @__PURE__ */ jsx50(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx50(RedisProvider, { redisCredentials: credentials, children: /* @__PURE__ */ jsx50(DatabrowserProvider, { children: /* @__PURE__ */ jsx50(TooltipProvider, { children: /* @__PURE__ */ jsxs34("div", { className: "ups-db", style: { height: "100%" }, children: [
5935
+ /* @__PURE__ */ jsx50(DatabrowserTabs, {}),
5936
+ /* @__PURE__ */ jsx50(DatabrowserInstances, {})
5795
5937
  ] }) }) }) }) });
5796
5938
  };
5939
+ var DatabrowserInstances = () => {
5940
+ const { tabs, selectedTab, addTab } = useDatabrowserStore();
5941
+ useEffect11(() => {
5942
+ if (Object.keys(tabs).length === 0) addTab();
5943
+ }, [tabs]);
5944
+ return Object.entries(tabs).map(([id]) => /* @__PURE__ */ jsx50(TabIdProvider, { value: id, children: /* @__PURE__ */ jsx50(DatabrowserInstance, { hidden: id !== selectedTab }) }, id));
5945
+ };
5797
5946
  export {
5798
5947
  RedisBrowser
5799
5948
  };