@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.js CHANGED
@@ -1,12 +1,100 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/components/databrowser/index.tsx
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/databrowser/index.tsx
2
2
  var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); var React6 = _interopRequireWildcard(_react); var React7 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react); var React9 = _interopRequireWildcard(_react); var React10 = _interopRequireWildcard(_react); var React11 = _interopRequireWildcard(_react); var React12 = _interopRequireWildcard(_react);
3
3
 
4
4
  // src/store.tsx
5
5
 
6
6
  var _zustand = require('zustand');
7
+ var _jsxruntime = require('react/jsx-runtime');
8
+ var DatabrowserContext = _react.createContext.call(void 0, void 0);
9
+ var DatabrowserProvider = ({ children }) => {
10
+ const store = _react.useMemo.call(void 0, () => createDatabrowserStore(), []);
11
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserContext.Provider, { value: { store }, children });
12
+ };
13
+ var useDatabrowser = () => {
14
+ const context = _react.useContext.call(void 0, 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 _zustand.useStore.call(void 0, store);
23
+ };
24
+ var createDatabrowserStore = () => _zustand.create.call(void 0, (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 _optionalChain([get, 'call', _2 => _2(), 'access', _3 => _3.tabs, 'access', _4 => _4[tabId], 'optionalAccess', _5 => _5.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
+ }));
7
91
 
8
- // src/lib/clients.ts
92
+ // src/components/databrowser/index.tsx
93
+ var _reacttooltip = require('@radix-ui/react-tooltip'); var TooltipPrimitive = _interopRequireWildcard(_reacttooltip);
9
94
  var _reactquery = require('@tanstack/react-query');
95
+
96
+ // src/lib/clients.ts
97
+
10
98
  var _redis = require('@upstash/redis');
11
99
 
12
100
  // src/components/ui/use-toast.ts
@@ -136,8 +224,8 @@ var redisClient = ({
136
224
  credentials,
137
225
  pipelining
138
226
  }) => {
139
- const token = _optionalChain([credentials, 'optionalAccess', _2 => _2.token]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
140
- const url = _optionalChain([credentials, 'optionalAccess', _3 => _3.url]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
227
+ const token = _optionalChain([credentials, 'optionalAccess', _6 => _6.token]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
228
+ const url = _optionalChain([credentials, 'optionalAccess', _7 => _7.url]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
141
229
  if (!url) {
142
230
  throw new Error("Redis URL is missing!");
143
231
  }
@@ -180,140 +268,53 @@ var queryClient = new (0, _reactquery.QueryClient)({
180
268
  })
181
269
  });
182
270
 
183
- // src/store.tsx
184
- var _jsxruntime = require('react/jsx-runtime');
185
- var DatabrowserContext = _react.createContext.call(void 0, void 0);
186
- var DatabrowserProvider = ({
271
+ // src/redis-context.tsx
272
+
273
+
274
+ var RedisContext = _react.createContext.call(void 0, void 0);
275
+ var RedisProvider = ({
187
276
  children,
188
277
  redisCredentials
189
278
  }) => {
190
- const redisInstance = _react.useMemo.call(void 0, () => redisClient({ credentials: redisCredentials, pipelining: true }), [redisCredentials]);
191
- const redisInstanceNoPipeline = _react.useMemo.call(void 0, () => redisClient({ credentials: redisCredentials, pipelining: false }), [redisCredentials]);
192
- const [store] = _react.useState.call(void 0, () => {
193
- return createDatabrowserStore();
194
- });
195
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserContext.Provider, { value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline, store }, children });
279
+ const redisInstance = _react.useMemo.call(void 0,
280
+ () => redisClient({ credentials: redisCredentials, pipelining: true }),
281
+ [redisCredentials]
282
+ );
283
+ const redisInstanceNoPipeline = _react.useMemo.call(void 0,
284
+ () => redisClient({ credentials: redisCredentials, pipelining: false }),
285
+ [redisCredentials]
286
+ );
287
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
288
+ RedisContext.Provider,
289
+ {
290
+ value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline },
291
+ children
292
+ }
293
+ );
196
294
  };
197
- var useDatabrowser = () => {
198
- const context = _react.useContext.call(void 0, DatabrowserContext);
295
+ var useRedis = () => {
296
+ const context = _react.useContext.call(void 0, 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 _zustand.useStore.call(void 0, store);
207
- };
208
- var createDatabrowserStore = () => _zustand.create.call(void 0, (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
-
223
- // src/components/databrowser/index.tsx
224
- var _reacttooltip = require('@radix-ui/react-tooltip'); var TooltipPrimitive = _interopRequireWildcard(_reacttooltip);
225
- var _iconsreact = require('@tabler/icons-react');
226
302
 
303
+ // src/components/databrowser/components/databrowser-instance.tsx
227
304
  var _reactresizablepanels = require('react-resizable-panels');
228
305
 
229
- // src/components/ui/toaster.tsx
230
- var _reactportal = require('@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 = _nullishCoalesce(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
-
245
- var _reacticons = require('@radix-ui/react-icons');
246
- var _reacttoast = require('@radix-ui/react-toast'); var ToastPrimitives = _interopRequireWildcard(_reacttoast);
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
 
@@ -358,15 +359,15 @@ var getGroupRecursive = (classParts, classPartObject) => {
358
359
  return void 0;
359
360
  }
360
361
  const classRest = classParts.join(CLASS_PART_SEPARATOR);
361
- return _optionalChain([classPartObject, 'access', _4 => _4.validators, 'access', _5 => _5.find, 'call', _6 => _6(({
362
+ return _optionalChain([classPartObject, 'access', _8 => _8.validators, 'access', _9 => _9.find, 'call', _10 => _10(({
362
363
  validator
363
- }) => validator(classRest)), 'optionalAccess', _7 => _7.classGroupId]);
364
+ }) => validator(classRest)), 'optionalAccess', _11 => _11.classGroupId]);
364
365
  };
365
366
  var arbitraryPropertyRegex = /^\[(.+)\]$/;
366
367
  var getGroupIdForArbitraryProperty = (className) => {
367
368
  if (arbitraryPropertyRegex.test(className)) {
368
369
  const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
369
- const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _8 => _8.substring, 'call', _9 => _9(0, arbitraryPropertyClassName.indexOf(":"))]);
370
+ const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _12 => _12.substring, 'call', _13 => _13(0, arbitraryPropertyClassName.indexOf(":"))]);
370
371
  if (property) {
371
372
  return "arbitrary.." + property;
372
373
  }
@@ -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,6 +2812,82 @@ function formatTime(seconds) {
2811
2812
  return parts.slice(0, 1).join(" ");
2812
2813
  }
2813
2814
 
2815
+ // src/components/ui/toaster.tsx
2816
+ var _reactportal = require('@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 = _nullishCoalesce(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
+
2829
+ // src/components/ui/toast.tsx
2830
+
2831
+ var _reacticons = require('@radix-ui/react-icons');
2832
+ var _reacttoast = require('@radix-ui/react-toast'); var ToastPrimitives = _interopRequireWildcard(_reacttoast);
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
+
2814
2891
  // src/components/ui/toast.tsx
2815
2892
 
2816
2893
  var ToastProvider = ToastPrimitives.Provider;
@@ -2917,17 +2994,44 @@ function Toaster() {
2917
2994
 
2918
2995
 
2919
2996
 
2997
+ // src/tab-provider.tsx
2920
2998
 
2921
2999
 
3000
+ var TabIdContext = _react.createContext.call(void 0, void 0);
3001
+ var TabIdProvider = ({ children, value }) => {
3002
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 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 _react.useMemo.call(void 0,
3016
+ () => ({
3017
+ selectedKey: _optionalChain([tabs, 'access', _14 => _14[selectedTab], 'optionalAccess', _15 => _15.selectedKey]),
3018
+ selectedListItem: _optionalChain([tabs, 'access', _16 => _16[selectedTab], 'optionalAccess', _17 => _17.selectedListItem]),
3019
+ search: _optionalChain([tabs, 'access', _18 => _18[selectedTab], 'optionalAccess', _19 => _19.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
+ };
2922
3029
 
2923
-
2924
-
2925
-
2926
- // src/components/databrowser/hooks/use-fetch-key-type.tsx
3030
+ // src/components/databrowser/hooks/use-fetch-key-type.ts
2927
3031
 
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 _reactquery.useQuery.call(void 0, {
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
-
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 = _react.useRef.call(void 0, );
2961
- const lastKey = _react.useRef.call(void 0, );
2962
- const fetchKeys = _react.useCallback.call(void 0, () => {
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 = _react.useCallback.call(void 0, () => {
2971
- cache.current = void 0;
2972
- lastKey.current = void 0;
2973
- }, []);
2974
- return {
2975
- fetchKeys,
2976
- resetCache
2977
- };
2978
- };
2979
- var PaginationCache = (_class = class {
2980
- constructor(redis, searchTerm, typeFilter) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
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
- __init() {this.cache = Object.fromEntries(
2990
- DATA_TYPES.map((type) => [type, { cursor: "0", keys: [] }])
2991
- )}
2992
- __init2() {this.targetCount = 0}
2993
- __init3() {this.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
- __init4() {this.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
- }, _class);
3060
-
3061
3044
  // src/components/databrowser/hooks/use-keys.tsx
3062
3045
 
3063
3046
  var KeysContext = _react.createContext.call(void 0, 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 = _react.useRef.call(void 0, 0);
3050
+ const { search } = useTab();
3051
+ const { redisNoPipeline: redis } = useRedis();
3071
3052
  const query = _reactquery.useInfiniteQuery.call(void 0, {
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 = _react.useCallback.call(void 0, () => {
3087
- resetCache();
3088
- query.refetch();
3089
- }, [query, resetCache]);
3090
3092
  const keys = _react.useMemo.call(void 0, () => {
3091
- const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.pages, 'access', _12 => _12.flatMap, 'call', _13 => _13((page) => page.keys)]), () => ( []));
3092
- if (exactMatchType && exactMatchType !== "none" && (search.type === void 0 || search.type === exactMatchType)) {
3093
- keys2.push([cleanSearchKey, exactMatchType]);
3094
- }
3093
+ const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _20 => _20.data, 'optionalAccess', _21 => _21.pages, 'access', _22 => _22.flatMap, 'call', _23 => _23((page) => page.keys)]), () => ( []));
3095
3094
  const keysSet = /* @__PURE__ */ new Set();
3096
3095
  const dedupedKeys = [];
3097
3096
  for (const key of keys2) {
@@ -3100,19 +3099,13 @@ var KeysProvider = ({ children }) => {
3100
3099
  dedupedKeys.push(key);
3101
3100
  }
3102
3101
  return dedupedKeys;
3103
- }, [query.data, cleanSearchKey, exactMatchType]);
3102
+ }, [query.data]);
3104
3103
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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
  }
@@ -3128,19 +3121,19 @@ var useKeys = () => {
3128
3121
  var useKeyType = (key) => {
3129
3122
  const { keys } = useKeys();
3130
3123
  const keyTuple = _react.useMemo.call(void 0, () => keys.find(([k, _]) => k === key), [keys, key]);
3131
- return _optionalChain([keyTuple, 'optionalAccess', _14 => _14[1]]);
3124
+ return _optionalChain([keyTuple, 'optionalAccess', _24 => _24[1]]);
3132
3125
  };
3133
3126
 
3134
3127
  // src/components/databrowser/components/display/display-list.tsx
3135
3128
 
3136
-
3129
+ var _iconsreact = require('@tabler/icons-react');
3137
3130
 
3138
3131
  // src/components/ui/button.tsx
3139
3132
 
3140
3133
  var _reactslot = require('@radix-ui/react-slot');
3141
3134
 
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: {
@@ -3197,7 +3190,7 @@ function Skeleton({ className, ...props }) {
3197
3190
 
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 } = _reactquery.useQuery.call(void 0, {
3202
3195
  queryKey: [FETCH_DB_SIZE_QUERY_KEY],
3203
3196
  queryFn: async () => {
@@ -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 = _reactquery.useMutation.call(void 0, {
3220
3213
  mutationFn: async ({ key, type }) => {
3221
3214
  if (await redis.exists(key)) throw new Error(`Key "${key}" already exists`);
@@ -3300,7 +3293,7 @@ var useAddKey = () => {
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 = _reactquery.useInfiniteQuery.call(void 0, {
3305
3298
  enabled: type === "set",
3306
3299
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "set"],
@@ -3379,7 +3372,7 @@ var useFetchListItems = ({ dataKey, type }) => {
3379
3372
  // +1 since first message is the last one
3380
3373
  LIST_DISPLAY_PAGE_SIZE + 1
3381
3374
  );
3382
- const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _15 => _15.at, 'call', _16 => _16(-1), 'optionalAccess', _17 => _17[0]]) : void 0;
3375
+ const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _25 => _25.at, 'call', _26 => _26(-1), 'optionalAccess', _27 => _27[0]]) : void 0;
3383
3376
  return {
3384
3377
  cursor: messages.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastMessageId,
3385
3378
  keys: messages.map(([id, fields]) => ({
@@ -3415,7 +3408,7 @@ function transformArray(inputArray) {
3415
3408
 
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 _reactquery.useQuery.call(void 0, {
3421
3414
  queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
@@ -3442,8 +3435,7 @@ 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();
3438
+ const { setSelectedKey } = useTab();
3447
3439
  const deleteKeyCache = _react.useCallback.call(void 0,
3448
3440
  (key) => {
3449
3441
  setSelectedKey(void 0);
@@ -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 = _reactquery.useMutation.call(void 0, {
3474
3465
  mutationFn: async (key) => {
@@ -3487,7 +3478,7 @@ var useDeleteKey = () => {
3487
3478
  // src/components/databrowser/hooks/use-edit-list-item.tsx
3488
3479
 
3489
3480
  var useEditListItem = () => {
3490
- const { redis } = useDatabrowser();
3481
+ const { redis } = useRedis();
3491
3482
  return _reactquery.useMutation.call(void 0, {
3492
3483
  mutationFn: async ({
3493
3484
  type,
@@ -3545,7 +3536,7 @@ var useEditListItem = () => {
3545
3536
  }
3546
3537
  case "stream": {
3547
3538
  if (!isNew || !newKey) throw new Error("Stream data type is not mutable");
3548
- const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _18 => _18.split, 'call', _19 => _19("\n")]), () => ( []))).map(
3539
+ const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _28 => _28.split, 'call', _29 => _29("\n")]), () => ( []))).map(
3549
3540
  ({ key, value }) => [key, value]
3550
3541
  );
3551
3542
  pipe.xadd(dataKey, newKey, Object.fromEntries(opts));
@@ -3580,7 +3571,7 @@ var _bytes = require('bytes'); var _bytes2 = _interopRequireDefault(_bytes);
3580
3571
 
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 _reactquery.useQuery.call(void 0, {
3585
3576
  queryKey: [FETCH_KEY_LENGTH_QUERY_KEY, dataKey],
3586
3577
  queryFn: async () => {
@@ -3610,7 +3601,7 @@ var useFetchKeyLength = ({ dataKey, type }) => {
3610
3601
 
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 _reactquery.useQuery.call(void 0, {
3615
3606
  queryKey: [FETCH_KEY_SIZE_QUERY_KEY, dataKey],
3616
3607
  queryFn: async () => {
@@ -3627,7 +3618,7 @@ var LengthBadge = ({
3627
3618
  content
3628
3619
  }) => {
3629
3620
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3630
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _20 => _20.length]), () => ( data));
3621
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _30 => _30.length]), () => ( data));
3631
3622
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label: "Length:", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : length });
3632
3623
  };
3633
3624
  var SizeBadge = ({ dataKey }) => {
@@ -3637,7 +3628,7 @@ var SizeBadge = ({ dataKey }) => {
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
3633
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3643
3634
  TTLBadge,
@@ -3987,8 +3978,8 @@ var TTLBadge = ({
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 } = _reactquery.useQuery.call(void 0, {
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
 
4011
4002
  var useSetSimpleKey = (dataKey, type) => {
4012
- const { redis } = useDatabrowser();
4003
+ const { redis } = useRedis();
4013
4004
  return _reactquery.useMutation.call(void 0, {
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
 
4034
4025
  var useSetTTL = () => {
4035
- const { redis } = useDatabrowser();
4026
+ const { redis } = useRedis();
4036
4027
  const updateTTL = _reactquery.useMutation.call(void 0, {
4037
4028
  mutationFn: async ({ dataKey, ttl }) => {
4038
4029
  await (ttl === void 0 || ttl === TTL_INFINITE ? redis.persist(dataKey) : redis.expire(dataKey, ttl));
@@ -4318,7 +4309,7 @@ var ItemContextMenu = ({
4318
4309
  editItem({
4319
4310
  type,
4320
4311
  dataKey,
4321
- itemKey: _optionalChain([data, 'optionalAccess', _21 => _21.key]),
4312
+ itemKey: _optionalChain([data, 'optionalAccess', _31 => _31.key]),
4322
4313
  // For deletion
4323
4314
  newKey: void 0
4324
4315
  });
@@ -4353,7 +4344,7 @@ var ItemContextMenu = ({
4353
4344
  {
4354
4345
  onClick: () => {
4355
4346
  if (!data) return;
4356
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _22 => _22.key]));
4347
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _32 => _32.key]));
4357
4348
  toast({
4358
4349
  description: "Key copied to clipboard"
4359
4350
  });
@@ -4361,11 +4352,11 @@ var ItemContextMenu = ({
4361
4352
  children: "Copy key"
4362
4353
  }
4363
4354
  ),
4364
- _optionalChain([data, 'optionalAccess', _23 => _23.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4355
+ _optionalChain([data, 'optionalAccess', _33 => _33.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4365
4356
  ContextMenuItem,
4366
4357
  {
4367
4358
  onClick: () => {
4368
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _24 => _24.value]), () => ( "")));
4359
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _34 => _34.value]), () => ( "")));
4369
4360
  toast({
4370
4361
  description: "Value copied to clipboard"
4371
4362
  });
@@ -4387,7 +4378,7 @@ var ItemContextMenu = ({
4387
4378
 
4388
4379
  var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
4389
4380
 
4390
- var ScrollArea = React9.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4381
+ var ScrollArea = React9.forwardRef(({ className, children, onScroll, roundedInherit = true, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4391
4382
  ScrollAreaPrimitive.Root,
4392
4383
  {
4393
4384
  ref,
@@ -4398,7 +4389,7 @@ var ScrollArea = React9.forwardRef(({ className, children, onScroll, ...props },
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
  ),
@@ -4429,7 +4420,8 @@ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
4429
4420
 
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,8 +4436,9 @@ 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
4444
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[100px] justify-center py-2 text-zinc-300", children: query.isFetching && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "animate-spin", size: 16 }) })
@@ -4457,6 +4450,18 @@ var InfiniteScroll = ({
4457
4450
  // src/components/databrowser/components/display/display-header.tsx
4458
4451
 
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
 
4462
4467
 
@@ -4516,14 +4521,14 @@ 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__ */ _jsxruntime.jsx.call(void 0, _reacticons.ChevronRightIcon, { className: "ml-auto size-4" })
4531
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.ChevronRightIcon, { className: "ml-auto" })
4527
4532
  ]
4528
4533
  }
4529
4534
  ));
@@ -4533,7 +4538,7 @@ var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) =
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
@@ -4546,8 +4551,8 @@ var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...pr
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
@@ -4578,7 +4583,7 @@ var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checke
4578
4583
  checked,
4579
4584
  ...props,
4580
4585
  children: [
4581
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.CheckIcon, { className: "size-4" }) }) }),
4586
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.CheckIcon, { className: "h-4 w-4" }) }) }),
4582
4587
  children
4583
4588
  ]
4584
4589
  }
@@ -4594,7 +4599,7 @@ var DropdownMenuRadioItem = React10.forwardRef(({ className, children, ...props
4594
4599
  ),
4595
4600
  ...props,
4596
4601
  children: [
4597
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.DotFilledIcon, { className: "size-4 fill-current" }) }) }),
4602
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.DotFilledIcon, { className: "h-2 w-2 fill-current" }) }) }),
4598
4603
  children
4599
4604
  ]
4600
4605
  }
@@ -4661,11 +4666,11 @@ var DisplayHeader = ({
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
4673
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
4669
4674
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4670
4675
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "grow truncate text-base", children: dataKey.trim() === "" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-semibold", children: dataKey }) }),
4671
4676
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
@@ -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 _reactquery.useQuery.call(void 0, {
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
 
4755
4760
  var useSetHashTTL = () => {
4756
- const { redis } = useDatabrowser();
4761
+ const { redis } = useRedis();
4757
4762
  return _reactquery.useMutation.call(void 0, {
4758
4763
  mutationFn: async ({
4759
4764
  dataKey,
@@ -4775,7 +4780,7 @@ var useSetHashTTL = () => {
4775
4780
  var HashFieldTTLBadge = ({ dataKey, field }) => {
4776
4781
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
4777
4782
  const { mutate: setTTL, isPending } = useSetHashTTL();
4778
- const expireAt = _optionalChain([data, 'optionalAccess', _25 => _25[field]]);
4783
+ const expireAt = _optionalChain([data, 'optionalAccess', _35 => _35[field]]);
4779
4784
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4780
4785
  TTLBadge,
4781
4786
  {
@@ -4864,7 +4869,7 @@ var CustomEditor = ({
4864
4869
  if (!monaco || !editorRef.current) {
4865
4870
  return;
4866
4871
  }
4867
- _optionalChain([monaco, 'optionalAccess', _26 => _26.editor, 'access', _27 => _27.setModelLanguage, 'call', _28 => _28(editorRef.current.getModel(), language)]);
4872
+ _optionalChain([monaco, 'optionalAccess', _36 => _36.editor, 'access', _37 => _37.setModelLanguage, 'call', _38 => _38(editorRef.current.getModel(), language)]);
4868
4873
  }, [monaco, language]);
4869
4874
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4870
4875
  "div",
@@ -4999,7 +5004,7 @@ var ListEditDisplay = ({
4999
5004
  type,
5000
5005
  item
5001
5006
  }) => {
5002
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grow rounded-md bg-zinc-100 p-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditForm, { item, type, dataKey }, item.key) });
5007
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grow rounded-md bg-zinc-100", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditForm, { item, type, dataKey }, item.key) });
5003
5008
  };
5004
5009
  var ListEditForm = ({
5005
5010
  type,
@@ -5011,7 +5016,7 @@ var ListEditForm = ({
5011
5016
  dataKey
5012
5017
  });
5013
5018
  const findValue = () => {
5014
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _29 => _29.data, 'optionalAccess', _30 => _30.pages]), () => ( []))) {
5019
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _39 => _39.data, 'optionalAccess', _40 => _40.pages]), () => ( []))) {
5015
5020
  const item = page.keys.find((item2) => item2.key === itemKey);
5016
5021
  if (item && "value" in item) return item.value;
5017
5022
  }
@@ -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({
@@ -5157,7 +5162,7 @@ var HashFieldTTLInfo = ({
5157
5162
  fields
5158
5163
  }) => {
5159
5164
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
5160
- const expireAt = _optionalChain([data, 'optionalAccess', _31 => _31[field]]);
5165
+ const expireAt = _optionalChain([data, 'optionalAccess', _41 => _41[field]]);
5161
5166
  const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
5162
5167
  _react.useEffect.call(void 0, () => {
5163
5168
  setTTL(calculateTTL(expireAt));
@@ -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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: [
5186
5191
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type }),
5187
5192
  selectedListItem && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditDisplay, { dataKey, type, item: selectedListItem }),
5188
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) }) })
5193
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) })
5189
5194
  ] });
5190
5195
  };
5191
5196
  var ListItems = ({
@@ -5193,8 +5198,8 @@ var ListItems = ({
5193
5198
  type,
5194
5199
  dataKey
5195
5200
  }) => {
5196
- const { setSelectedListItem } = useDatabrowserStore();
5197
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _32 => _32.data, 'optionalAccess', _33 => _33.pages, 'access', _34 => _34.flatMap, 'call', _35 => _35((page) => page.keys)]), () => ( [])), [query.data]);
5201
+ const { setSelectedListItem } = useTab();
5202
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _42 => _42.data, 'optionalAccess', _43 => _43.pages, 'access', _44 => _44.flatMap, 'call', _45 => _45((page) => page.keys)]), () => ( [])), [query.data]);
5198
5203
  const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
5199
5204
  const { mutate: editItem } = useEditListItem();
5200
5205
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -5205,7 +5210,7 @@ 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
5215
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5211
5216
  "td",
@@ -5276,13 +5281,7 @@ var EditorDisplay = ({ dataKey, type }) => {
5276
5281
  const { data } = useFetchSimpleKey(dataKey, type);
5277
5282
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full flex-col gap-2", children: [
5278
5283
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type, content: _nullishCoalesce(data, () => ( void 0)) }),
5279
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : data === null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplayForm, { dataKey, type, data }, dataKey)
5284
- }
5285
- )
5284
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full grow flex-col gap-2 rounded-md bg-zinc-100", children: data === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : data === null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplayForm, { dataKey, type, data }, dataKey) })
5286
5285
  ] });
5287
5286
  };
5288
5287
  var EditorDisplayForm = ({
@@ -5326,10 +5325,10 @@ var EditorDisplayForm = ({
5326
5325
  // src/components/databrowser/components/display/index.tsx
5327
5326
 
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full rounded-xl border bg-white p-1", children: !selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : !type ? query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-gray-500", children: "Loading..." }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: type === "string" || type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5331
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full p-4", children: !selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : !type ? query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-gray-500", children: "Loading..." }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: type === "string" || type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5333
5332
  };
5334
5333
 
5335
5334
  // src/components/databrowser/components/sidebar/index.tsx
@@ -5445,7 +5444,7 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
5445
5444
  // src/components/databrowser/components/add-key-modal.tsx
5446
5445
 
5447
5446
  function AddKeyModal() {
5448
- const { setSelectedKey } = useDatabrowserStore();
5447
+ const { setSelectedKey } = useTab();
5449
5448
  const [open, setOpen] = _react.useState.call(void 0, false);
5450
5449
  const { mutateAsync: addKey, isPending } = useAddKey();
5451
5450
  const { control, handleSubmit, formState, reset } = _reacthookform.useForm.call(void 0, {
@@ -5459,7 +5458,7 @@ function AddKeyModal() {
5459
5458
  setSelectedKey(key);
5460
5459
  setOpen(false);
5461
5460
  setTimeout(() => {
5462
- _optionalChain([window, 'access', _36 => _36.document, 'access', _37 => _37.querySelector, 'call', _38 => _38(`[data-key="${key}"]`), 'optionalAccess', _39 => _39.scrollIntoView, 'call', _40 => _40({
5461
+ _optionalChain([window, 'access', _46 => _46.document, 'access', _47 => _47.querySelector, 'call', _48 => _48(`[data-key="${key}"]`), 'optionalAccess', _49 => _49.scrollIntoView, 'call', _50 => _50({
5463
5462
  behavior: "smooth",
5464
5463
  block: "start",
5465
5464
  inline: "nearest"
@@ -5504,7 +5503,7 @@ function AddKeyModal() {
5504
5503
  }
5505
5504
  )
5506
5505
  ] }),
5507
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _41 => _41.errors, 'access', _42 => _42.key, 'optionalAccess', _43 => _43.message]) }),
5506
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _51 => _51.errors, 'access', _52 => _52.key, 'optionalAccess', _53 => _53.message]) }),
5508
5507
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-zinc-500", children: "After creating the key, you can edit the value" }),
5509
5508
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5510
5509
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5598,7 +5597,7 @@ var SidebarContextMenu = ({ children }) => {
5598
5597
 
5599
5598
  var KeysList = () => {
5600
5599
  const { keys } = useKeys();
5601
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _44 => _44.at, 'call', _45 => _45(i + 1), 'optionalAccess', _46 => _46[0]]), () => ( "")), data }, data[0])) }) }) });
5600
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _54 => _54.at, 'call', _55 => _55(i + 1), 'optionalAccess', _56 => _56[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,7 +5619,7 @@ 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]
@@ -5639,30 +5638,106 @@ var KeyItem = ({ data, nextKey }) => {
5639
5638
 
5640
5639
 
5641
5640
 
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();
5650
+ const { setSearchKey, search } = useTab();
5651
+ const { searchHistory, addSearchHistory } = useDatabrowserStore();
5644
5652
  const [state, setState] = _react.useState.call(void 0, search.key);
5645
- const submit = (value) => {
5653
+ const [isFocus, setIsFocus] = _react.useState.call(void 0, false);
5654
+ const [focusedIndex, setFocusedIndex] = _react.useState.call(void 0, -1);
5655
+ const inputRef = _react.useRef.call(void 0, null);
5656
+ const historyItemRefs = _react.useRef.call(void 0, []);
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
5651
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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
+ _react.useEffect.call(void 0, () => {
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
+ _optionalChain([inputRef, 'access', _57 => _57.current, 'optionalAccess', _58 => _58.blur, 'call', _59 => _59()]);
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
+ _optionalChain([inputRef, 'access', _60 => _60.current, 'optionalAccess', _61 => _61.focus, 'call', _62 => _62()]);
5691
+ } else if (filteredHistory.length > 0) {
5692
+ setFocusedIndex(filteredHistory.length - 1);
5693
+ }
5694
+ }
5695
+ };
5696
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
5697
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
5698
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsxs.call(void 0,
5667
5742
  Button,
5668
5743
  {
@@ -5679,7 +5754,8 @@ var SearchInput = () => {
5679
5754
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
5680
5755
  ]
5681
5756
  }
5682
- )
5757
+ ),
5758
+ " "
5683
5759
  ] });
5684
5760
  };
5685
5761
 
@@ -5695,7 +5771,7 @@ var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div",
5695
5771
 
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__ */ _jsxruntime.jsxs.call(void 0,
5700
5776
  Select,
5701
5777
  {
@@ -5709,7 +5785,7 @@ function DataTypeSelector() {
5709
5785
  value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
5710
5786
  children: [
5711
5787
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "!w-auto select-none whitespace-nowrap rounded-r-none border-r-0 border-zinc-300 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
5712
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: Object.entries(DATA_TYPE_NAMES).map(
5788
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: [[ALL_TYPES_KEY, "All Types"], ...Object.entries(DATA_TYPE_NAMES)].map(
5713
5789
  ([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)
5714
5790
  ) }) })
5715
5791
  ]
@@ -5720,9 +5796,9 @@ function DataTypeSelector() {
5720
5796
  // src/components/databrowser/components/sidebar/index.tsx
5721
5797
 
5722
5798
  function Sidebar() {
5723
- const { keys, query, refetch } = useKeys();
5724
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2 rounded-xl border bg-white p-1", children: [
5725
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
5799
+ const { keys, query } = useKeys();
5800
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2 p-4", children: [
5801
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
5726
5802
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center justify-between pl-1", children: [
5727
5803
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayDbSize, {}),
5728
5804
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-1", children: [
@@ -5731,7 +5807,9 @@ function Sidebar() {
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
  });
@@ -5758,19 +5836,15 @@ function Sidebar() {
5758
5836
  ] }),
5759
5837
  query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
5760
5838
  // Infinite scroll already has a loader at the bottom
5761
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) })
5839
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, roundedInherit: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) })
5762
5840
  ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {})
5763
5841
  ] });
5764
5842
  }
5765
5843
 
5766
- // src/components/databrowser/index.tsx
5844
+ // src/components/databrowser/components/databrowser-instance.tsx
5767
5845
 
5768
- var RedisBrowser = ({ token, url }) => {
5769
- const credentials = _react.useMemo.call(void 0, () => ({ token, url }), [token, url]);
5770
- _react.useEffect.call(void 0, () => {
5771
- queryClient.resetQueries();
5772
- }, [credentials.url]);
5773
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactquery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacttooltip.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserProvider, { redisCredentials: credentials, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "ups-db", style: { height: "100%" }, children: [
5846
+ var DatabrowserInstance = ({ hidden }) => {
5847
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("h-full rounded-md bg-zinc-100", hidden && "hidden"), children: [
5774
5848
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5775
5849
  _reactresizablepanels.PanelGroup,
5776
5850
  {
@@ -5779,21 +5853,96 @@ var RedisBrowser = ({ token, url }) => {
5779
5853
  className: "h-full w-full gap-0.5 text-sm antialiased",
5780
5854
  children: [
5781
5855
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
5782
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "h-fullm flex w-1.5 items-center justify-center rounded-full hover:bg-zinc-300/20", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5783
- _iconsreact.IconDotsVertical,
5784
- {
5785
- size: 16,
5786
- stroke: 1,
5787
- className: "pointer-events-none shrink-0 opacity-20"
5788
- }
5789
- ) }),
5856
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "group flex h-full w-1.5 justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full border-r border-dashed border-zinc-200 transition-colors group-hover:border-zinc-300" }) }),
5790
5857
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
5791
5858
  ]
5792
5859
  }
5793
5860
  ),
5794
5861
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Toaster, {})
5862
+ ] }) });
5863
+ };
5864
+
5865
+ // src/components/databrowser/components/databrowser-tabs.tsx
5866
+
5867
+
5868
+ // src/components/databrowser/components/tab-type-icon.tsx
5869
+
5870
+ function TabTypeIcon({ selectedKey }) {
5871
+ const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
5872
+ if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-5 rounded" });
5873
+ if (!keyType || keyType === "none") return;
5874
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
5875
+ }
5876
+
5877
+ // src/components/databrowser/components/databrowser-tabs.tsx
5878
+
5879
+ var Tab = ({ id }) => {
5880
+ const { selectTab, selectedTab, tabs, removeTab } = useDatabrowserStore();
5881
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
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__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5891
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabTypeIcon, { selectedKey: tabs[id].selectedKey }),
5892
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "max-w-32 truncate", children: tabs[id].selectedKey })
5893
+ ] }) : "New Tab",
5894
+ Object.keys(tabs).length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
5903
+ }
5904
+ )
5905
+ ]
5906
+ }
5907
+ );
5908
+ };
5909
+ var DatabrowserTabs = () => {
5910
+ const { tabs, addTab } = useDatabrowserStore();
5911
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mb-2 flex items-center gap-1 border-b border-zinc-200", children: [
5912
+ Object.keys(tabs).map((id) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Tab, { id }, id)),
5913
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
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__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-500", size: 16 })
5922
+ }
5923
+ )
5924
+ ] });
5925
+ };
5926
+
5927
+ // src/components/databrowser/index.tsx
5928
+
5929
+ var RedisBrowser = ({ token, url }) => {
5930
+ const credentials = _react.useMemo.call(void 0, () => ({ token, url }), [token, url]);
5931
+ _react.useEffect.call(void 0, () => {
5932
+ queryClient.resetQueries();
5933
+ }, [credentials.url]);
5934
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactquery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RedisProvider, { redisCredentials: credentials, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserProvider, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacttooltip.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "ups-db", style: { height: "100%" }, children: [
5935
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserTabs, {}),
5936
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, {})
5795
5937
  ] }) }) }) }) });
5796
5938
  };
5939
+ var DatabrowserInstances = () => {
5940
+ const { tabs, selectedTab, addTab } = useDatabrowserStore();
5941
+ _react.useEffect.call(void 0, () => {
5942
+ if (Object.keys(tabs).length === 0) addTab();
5943
+ }, [tabs]);
5944
+ return Object.entries(tabs).map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdProvider, { value: id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstance, { hidden: id !== selectedTab }) }, id));
5945
+ };
5797
5946
 
5798
5947
 
5799
5948
  exports.RedisBrowser = RedisBrowser;