@upstash/react-redis-browser 0.1.11-canary-2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,101 +1,12 @@
1
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
- // src/store.tsx
5
-
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
- }));
4
+ // src/redis-context.tsx
91
5
 
92
- // src/components/databrowser/index.tsx
93
- var _reacttooltip = require('@radix-ui/react-tooltip'); var TooltipPrimitive = _interopRequireWildcard(_reacttooltip);
94
- var _reactquery = require('@tanstack/react-query');
95
6
 
96
7
  // src/lib/clients.ts
97
-
98
- var _redis = require('@upstash/redis');
8
+ var _reactquery = require('@tanstack/react-query');
9
+ var _cloudflare = require('@upstash/redis/cloudflare');
99
10
 
100
11
  // src/components/ui/use-toast.ts
101
12
 
@@ -224,15 +135,16 @@ var redisClient = ({
224
135
  credentials,
225
136
  pipelining
226
137
  }) => {
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;
138
+ const safeProcess = typeof process === "undefined" ? { env: {} } : process;
139
+ const token = _optionalChain([credentials, 'optionalAccess', _2 => _2.token]) || safeProcess.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
140
+ const url = _optionalChain([credentials, 'optionalAccess', _3 => _3.url]) || safeProcess.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
229
141
  if (!url) {
230
142
  throw new Error("Redis URL is missing!");
231
143
  }
232
144
  if (!token) {
233
145
  throw new Error("Redis TOKEN is missing!");
234
146
  }
235
- const redis = new (0, _redis.Redis)({
147
+ const redis = new (0, _cloudflare.Redis)({
236
148
  url,
237
149
  token,
238
150
  enableAutoPipelining: pipelining,
@@ -269,8 +181,7 @@ var queryClient = new (0, _reactquery.QueryClient)({
269
181
  });
270
182
 
271
183
  // src/redis-context.tsx
272
-
273
-
184
+ var _jsxruntime = require('react/jsx-runtime');
274
185
  var RedisContext = _react.createContext.call(void 0, void 0);
275
186
  var RedisProvider = ({
276
187
  children,
@@ -300,6 +211,209 @@ var useRedis = () => {
300
211
  return context;
301
212
  };
302
213
 
214
+ // src/store.tsx
215
+
216
+ var _zustand = require('zustand');
217
+ var _middleware = require('zustand/middleware');
218
+
219
+ var DatabrowserContext = _react.createContext.call(void 0, void 0);
220
+ var DatabrowserProvider = ({
221
+ children,
222
+ storage
223
+ }) => {
224
+ const store = _react.useMemo.call(void 0, () => {
225
+ if (!storage) return _zustand.create.call(void 0, storeCreator);
226
+ return _zustand.create.call(void 0, )(
227
+ _middleware.persist.call(void 0, storeCreator, {
228
+ name: "redis-browser-data",
229
+ storage: {
230
+ getItem: () => {
231
+ const data = storage.get();
232
+ if (!data) return null;
233
+ try {
234
+ return JSON.parse(data);
235
+ } catch (e2) {
236
+ console.error("Error while parsing stored data.");
237
+ return null;
238
+ }
239
+ },
240
+ setItem: (_name, value) => storage.set(JSON.stringify(value)),
241
+ removeItem: () => {
242
+ }
243
+ },
244
+ version: 1,
245
+ // @ts-expect-error Reset the store for < v1
246
+ migrate: (state, version) => {
247
+ if (version === 0) {
248
+ return;
249
+ }
250
+ return state;
251
+ }
252
+ })
253
+ );
254
+ }, []);
255
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserContext.Provider, { value: { store }, children });
256
+ };
257
+ var useDatabrowser = () => {
258
+ const context = _react.useContext.call(void 0, DatabrowserContext);
259
+ if (!context) {
260
+ throw new Error("useDatabrowser must be used within a DatabrowserProvider");
261
+ }
262
+ return context;
263
+ };
264
+ var useDatabrowserStore = () => {
265
+ const { store } = useDatabrowser();
266
+ return _zustand.useStore.call(void 0, store);
267
+ };
268
+ var storeCreator = (set, get) => ({
269
+ selectedTab: void 0,
270
+ tabs: [],
271
+ addTab: () => {
272
+ const id = crypto.randomUUID();
273
+ const newTabData = {
274
+ selectedKey: void 0,
275
+ search: { key: "", type: void 0 }
276
+ };
277
+ set((old) => ({
278
+ tabs: [...old.tabs, [id, newTabData]],
279
+ selectedTab: id
280
+ }));
281
+ },
282
+ removeTab: (id) => {
283
+ set((old) => {
284
+ const tabIndex = old.tabs.findIndex(([tabId]) => tabId === id);
285
+ if (tabIndex === -1) return old;
286
+ const newTabs = [...old.tabs];
287
+ newTabs.splice(tabIndex, 1);
288
+ let selectedTab = old.selectedTab;
289
+ if (selectedTab === id) {
290
+ const [newId] = _nullishCoalesce(newTabs[tabIndex - 1], () => ( newTabs[tabIndex]));
291
+ selectedTab = newTabs.length > 0 ? newId : void 0;
292
+ }
293
+ return { tabs: newTabs, selectedTab };
294
+ });
295
+ },
296
+ selectTab: (id) => {
297
+ set({ selectedTab: id });
298
+ },
299
+ getSelectedKey: (tabId) => {
300
+ return _optionalChain([get, 'call', _4 => _4(), 'access', _5 => _5.tabs, 'access', _6 => _6.find, 'call', _7 => _7(([id]) => id === tabId), 'optionalAccess', _8 => _8[1], 'optionalAccess', _9 => _9.selectedKey]);
301
+ },
302
+ setSelectedKey: (tabId, key) => {
303
+ set((old) => {
304
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
305
+ if (tabIndex === -1) return old;
306
+ const newTabs = [...old.tabs];
307
+ const [, tabData] = newTabs[tabIndex];
308
+ newTabs[tabIndex] = [tabId, { ...tabData, selectedKey: key, selectedListItem: void 0 }];
309
+ return { ...old, tabs: newTabs };
310
+ });
311
+ },
312
+ setSelectedListItem: (tabId, item) => {
313
+ set((old) => {
314
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
315
+ if (tabIndex === -1) return old;
316
+ const newTabs = [...old.tabs];
317
+ const [, tabData] = newTabs[tabIndex];
318
+ newTabs[tabIndex] = [tabId, { ...tabData, selectedListItem: item }];
319
+ return { ...old, tabs: newTabs };
320
+ });
321
+ },
322
+ setSearch: (tabId, search) => {
323
+ set((old) => {
324
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
325
+ if (tabIndex === -1) return old;
326
+ const newTabs = [...old.tabs];
327
+ const [, tabData] = newTabs[tabIndex];
328
+ newTabs[tabIndex] = [tabId, { ...tabData, search }];
329
+ return { ...old, tabs: newTabs };
330
+ });
331
+ },
332
+ setSearchKey: (tabId, key) => {
333
+ set((old) => {
334
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
335
+ if (tabIndex === -1) return old;
336
+ const newTabs = [...old.tabs];
337
+ const [, tabData] = newTabs[tabIndex];
338
+ newTabs[tabIndex] = [
339
+ tabId,
340
+ {
341
+ ...tabData,
342
+ search: { ...tabData.search, key }
343
+ }
344
+ ];
345
+ return { ...old, tabs: newTabs };
346
+ });
347
+ },
348
+ setSearchType: (tabId, type) => {
349
+ set((old) => {
350
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
351
+ if (tabIndex === -1) return old;
352
+ const newTabs = [...old.tabs];
353
+ const [, tabData] = newTabs[tabIndex];
354
+ newTabs[tabIndex] = [
355
+ tabId,
356
+ {
357
+ ...tabData,
358
+ search: { ...tabData.search, type }
359
+ }
360
+ ];
361
+ return { ...old, tabs: newTabs };
362
+ });
363
+ },
364
+ searchHistory: [],
365
+ addSearchHistory: (key) => {
366
+ set((old) => ({ ...old, searchHistory: [key, ...old.searchHistory] }));
367
+ }
368
+ });
369
+
370
+ // src/tab-provider.tsx
371
+
372
+
373
+ var TabIdContext = _react.createContext.call(void 0, void 0);
374
+ var TabIdProvider = ({ children, value }) => {
375
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdContext.Provider, { value, children });
376
+ };
377
+ var useTabId = () => {
378
+ const tabId = _react.useContext.call(void 0, TabIdContext);
379
+ if (!tabId) {
380
+ throw new Error("useTabId must be used within a TabProvider");
381
+ }
382
+ return tabId;
383
+ };
384
+ var useTab = () => {
385
+ const {
386
+ selectedTab,
387
+ tabs,
388
+ setSelectedKey,
389
+ setSelectedListItem,
390
+ setSearch,
391
+ setSearchKey,
392
+ setSearchType
393
+ } = useDatabrowserStore();
394
+ const tabId = useTabId();
395
+ const tabData = _react.useMemo.call(void 0, () => _optionalChain([tabs, 'access', _10 => _10.find, 'call', _11 => _11(([id]) => id === tabId), 'optionalAccess', _12 => _12[1]]), [tabs, tabId]);
396
+ if (!selectedTab || !tabData) throw new Error("selectedTab is undefined when using useTab()");
397
+ return _react.useMemo.call(void 0,
398
+ () => ({
399
+ active: selectedTab === tabId,
400
+ selectedKey: tabData.selectedKey,
401
+ selectedListItem: tabData.selectedListItem,
402
+ search: tabData.search,
403
+ setSelectedKey: (key) => setSelectedKey(tabId, key),
404
+ setSelectedListItem: (item) => setSelectedListItem(tabId, item),
405
+ setSearch: (search) => setSearch(tabId, search),
406
+ setSearchKey: (key) => setSearchKey(tabId, key),
407
+ setSearchType: (type) => setSearchType(tabId, type)
408
+ }),
409
+ [selectedTab, tabs, tabId]
410
+ );
411
+ };
412
+
413
+ // src/components/databrowser/index.tsx
414
+ var _reacttooltip = require('@radix-ui/react-tooltip'); var TooltipPrimitive = _interopRequireWildcard(_reacttooltip);
415
+
416
+
303
417
  // src/components/databrowser/components/databrowser-instance.tsx
304
418
  var _reactresizablepanels = require('react-resizable-panels');
305
419
 
@@ -359,15 +473,15 @@ var getGroupRecursive = (classParts, classPartObject) => {
359
473
  return void 0;
360
474
  }
361
475
  const classRest = classParts.join(CLASS_PART_SEPARATOR);
362
- return _optionalChain([classPartObject, 'access', _8 => _8.validators, 'access', _9 => _9.find, 'call', _10 => _10(({
476
+ return _optionalChain([classPartObject, 'access', _13 => _13.validators, 'access', _14 => _14.find, 'call', _15 => _15(({
363
477
  validator
364
- }) => validator(classRest)), 'optionalAccess', _11 => _11.classGroupId]);
478
+ }) => validator(classRest)), 'optionalAccess', _16 => _16.classGroupId]);
365
479
  };
366
480
  var arbitraryPropertyRegex = /^\[(.+)\]$/;
367
481
  var getGroupIdForArbitraryProperty = (className) => {
368
482
  if (arbitraryPropertyRegex.test(className)) {
369
483
  const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
370
- const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _12 => _12.substring, 'call', _13 => _13(0, arbitraryPropertyClassName.indexOf(":"))]);
484
+ const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _17 => _17.substring, 'call', _18 => _18(0, arbitraryPropertyClassName.indexOf(":"))]);
371
485
  if (property) {
372
486
  return "arbitrary.." + property;
373
487
  }
@@ -2811,6 +2925,7 @@ function formatTime(seconds) {
2811
2925
  }
2812
2926
  return parts.slice(0, 1).join(" ");
2813
2927
  }
2928
+ var isTest = typeof window !== "undefined" && window.__PLAYWRIGHT__ === true;
2814
2929
 
2815
2930
  // src/components/ui/toaster.tsx
2816
2931
  var _reactportal = require('@radix-ui/react-portal');
@@ -2994,39 +3109,6 @@ function Toaster() {
2994
3109
 
2995
3110
 
2996
3111
 
2997
- // src/tab-provider.tsx
2998
-
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
- };
3029
-
3030
3112
  // src/components/databrowser/hooks/use-fetch-key-type.ts
3031
3113
 
3032
3114
  var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
@@ -3045,24 +3127,40 @@ var useFetchKeyType = (key) => {
3045
3127
 
3046
3128
  var KeysContext = _react.createContext.call(void 0, void 0);
3047
3129
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
3048
- var SCAN_COUNT = 100;
3130
+ var SCAN_COUNTS = [100, 300, 500];
3049
3131
  var KeysProvider = ({ children }) => {
3050
- const { search } = useTab();
3132
+ const { active, search } = useTab();
3051
3133
  const { redisNoPipeline: redis } = useRedis();
3134
+ const performScan = async (count2, cursor) => {
3135
+ const args = [cursor];
3136
+ if (search.key) {
3137
+ args.push("MATCH", search.key);
3138
+ }
3139
+ if (search.type) {
3140
+ args.push("TYPE", search.type);
3141
+ }
3142
+ args.push("COUNT", count2.toString());
3143
+ if (!search.type) args.push("WITHTYPE");
3144
+ return await redis.exec(["SCAN", ...args]);
3145
+ };
3146
+ const scanUntilAvailable = async (cursor) => {
3147
+ let i = 0;
3148
+ while (true) {
3149
+ const [newCursor, values] = await performScan(_nullishCoalesce(SCAN_COUNTS[i], () => ( SCAN_COUNTS.at(-1))), cursor);
3150
+ cursor = newCursor;
3151
+ i++;
3152
+ if (values.length > 0 || cursor === "0") {
3153
+ return [cursor, values];
3154
+ }
3155
+ }
3156
+ };
3052
3157
  const query = _reactquery.useInfiniteQuery.call(void 0, {
3053
3158
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3159
+ // Only fetch when tab is active
3160
+ enabled: active,
3054
3161
  initialPageParam: "0",
3055
3162
  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]);
3163
+ const [cursor, values] = await scanUntilAvailable(lastCursor);
3066
3164
  const keys2 = [];
3067
3165
  let index = 0;
3068
3166
  while (true) {
@@ -3090,7 +3188,7 @@ var KeysProvider = ({ children }) => {
3090
3188
  refetchOnMount: false
3091
3189
  });
3092
3190
  const keys = _react.useMemo.call(void 0, () => {
3093
- const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _20 => _20.data, 'optionalAccess', _21 => _21.pages, 'access', _22 => _22.flatMap, 'call', _23 => _23((page) => page.keys)]), () => ( []));
3191
+ const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _19 => _19.data, 'optionalAccess', _20 => _20.pages, 'access', _21 => _21.flatMap, 'call', _22 => _22((page) => page.keys)]), () => ( []));
3094
3192
  const keysSet = /* @__PURE__ */ new Set();
3095
3193
  const dedupedKeys = [];
3096
3194
  for (const key of keys2) {
@@ -3121,7 +3219,7 @@ var useKeys = () => {
3121
3219
  var useKeyType = (key) => {
3122
3220
  const { keys } = useKeys();
3123
3221
  const keyTuple = _react.useMemo.call(void 0, () => keys.find(([k, _]) => k === key), [keys, key]);
3124
- return _optionalChain([keyTuple, 'optionalAccess', _24 => _24[1]]);
3222
+ return _optionalChain([keyTuple, 'optionalAccess', _23 => _23[1]]);
3125
3223
  };
3126
3224
 
3127
3225
  // src/components/databrowser/components/display/display-list.tsx
@@ -3265,7 +3363,7 @@ var useAddKey = () => {
3265
3363
  queryKey: [FETCH_KEYS_QUERY_KEY]
3266
3364
  },
3267
3365
  (data) => {
3268
- if (!data) throw new Error("Data is undefined");
3366
+ if (!data) return;
3269
3367
  return {
3270
3368
  ...data,
3271
3369
  pages: data.pages.map(
@@ -3372,7 +3470,7 @@ var useFetchListItems = ({ dataKey, type }) => {
3372
3470
  // +1 since first message is the last one
3373
3471
  LIST_DISPLAY_PAGE_SIZE + 1
3374
3472
  );
3375
- const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _25 => _25.at, 'call', _26 => _26(-1), 'optionalAccess', _27 => _27[0]]) : void 0;
3473
+ const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _24 => _24.at, 'call', _25 => _25(-1), 'optionalAccess', _26 => _26[0]]) : void 0;
3376
3474
  return {
3377
3475
  cursor: messages.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastMessageId,
3378
3476
  keys: messages.map(([id, fields]) => ({
@@ -3536,7 +3634,7 @@ var useEditListItem = () => {
3536
3634
  }
3537
3635
  case "stream": {
3538
3636
  if (!isNew || !newKey) throw new Error("Stream data type is not mutable");
3539
- const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _28 => _28.split, 'call', _29 => _29("\n")]), () => ( []))).map(
3637
+ const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _27 => _27.split, 'call', _28 => _28("\n")]), () => ( []))).map(
3540
3638
  ({ key, value }) => [key, value]
3541
3639
  );
3542
3640
  pipe.xadd(dataKey, newKey, Object.fromEntries(opts));
@@ -3618,7 +3716,7 @@ var LengthBadge = ({
3618
3716
  content
3619
3717
  }) => {
3620
3718
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3621
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _30 => _30.length]), () => ( data));
3719
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _29 => _29.length]), () => ( data));
3622
3720
  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 });
3623
3721
  };
3624
3722
  var SizeBadge = ({ dataKey }) => {
@@ -4309,7 +4407,7 @@ var ItemContextMenu = ({
4309
4407
  editItem({
4310
4408
  type,
4311
4409
  dataKey,
4312
- itemKey: _optionalChain([data, 'optionalAccess', _31 => _31.key]),
4410
+ itemKey: _optionalChain([data, 'optionalAccess', _30 => _30.key]),
4313
4411
  // For deletion
4314
4412
  newKey: void 0
4315
4413
  });
@@ -4344,7 +4442,7 @@ var ItemContextMenu = ({
4344
4442
  {
4345
4443
  onClick: () => {
4346
4444
  if (!data) return;
4347
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _32 => _32.key]));
4445
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _31 => _31.key]));
4348
4446
  toast({
4349
4447
  description: "Key copied to clipboard"
4350
4448
  });
@@ -4352,11 +4450,11 @@ var ItemContextMenu = ({
4352
4450
  children: "Copy key"
4353
4451
  }
4354
4452
  ),
4355
- _optionalChain([data, 'optionalAccess', _33 => _33.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4453
+ _optionalChain([data, 'optionalAccess', _32 => _32.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4356
4454
  ContextMenuItem,
4357
4455
  {
4358
4456
  onClick: () => {
4359
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _34 => _34.value]), () => ( "")));
4457
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _33 => _33.value]), () => ( "")));
4360
4458
  toast({
4361
4459
  description: "Value copied to clipboard"
4362
4460
  });
@@ -4374,6 +4472,7 @@ var ItemContextMenu = ({
4374
4472
  // src/components/databrowser/components/sidebar/infinite-scroll.tsx
4375
4473
 
4376
4474
 
4475
+
4377
4476
  // src/components/ui/scroll-area.tsx
4378
4477
 
4379
4478
  var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
@@ -4423,6 +4522,9 @@ var InfiniteScroll = ({
4423
4522
  children,
4424
4523
  ...props
4425
4524
  }) => {
4525
+ const { active } = useTab();
4526
+ const scrollRef = _react.useRef.call(void 0, null);
4527
+ const contentRef = _react.useRef.call(void 0, null);
4426
4528
  const handleScroll = (e) => {
4427
4529
  const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
4428
4530
  if (scrollTop + clientHeight > scrollHeight - 100) {
@@ -4432,7 +4534,21 @@ var InfiniteScroll = ({
4432
4534
  query.fetchNextPage();
4433
4535
  }
4434
4536
  };
4435
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4537
+ const checkAndFetchMore = () => {
4538
+ if (!scrollRef.current || !contentRef.current) return;
4539
+ const viewportHeight = scrollRef.current.clientHeight;
4540
+ const contentHeight = contentRef.current.clientHeight;
4541
+ const overflowThreshold = viewportHeight + 100;
4542
+ if (contentHeight < overflowThreshold && query.hasNextPage && !query.isFetching) {
4543
+ query.fetchNextPage();
4544
+ }
4545
+ };
4546
+ _react.useEffect.call(void 0, () => {
4547
+ if (!active) return;
4548
+ const timer = setTimeout(checkAndFetchMore, 100);
4549
+ return () => clearTimeout(timer);
4550
+ }, [active, query.data]);
4551
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4436
4552
  ScrollArea,
4437
4553
  {
4438
4554
  type: "always",
@@ -4442,10 +4558,11 @@ var InfiniteScroll = ({
4442
4558
  "block h-full w-full overflow-visible rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all",
4443
4559
  props.className
4444
4560
  ),
4445
- children: [
4561
+ ref: scrollRef,
4562
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref: contentRef, children: [
4446
4563
  children,
4447
4564
  /* @__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 }) })
4448
- ]
4565
+ ] })
4449
4566
  }
4450
4567
  );
4451
4568
  };
@@ -4635,8 +4752,8 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4635
4752
 
4636
4753
  function KeyActions({ dataKey, content }) {
4637
4754
  const { mutateAsync: deleteKey } = useDeleteKey();
4638
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { children: [
4639
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDotsVertical, { className: "size-4 text-zinc-500" }) }) }),
4755
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { modal: false, children: [
4756
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", "aria-label": "Key actions", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDotsVertical, { className: "size-4 text-zinc-500" }) }) }),
4640
4757
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { className: "", align: "end", children: [
4641
4758
  content && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4642
4759
  DropdownMenuItem,
@@ -4650,12 +4767,28 @@ function KeyActions({ dataKey, content }) {
4650
4767
  children: "Copy content"
4651
4768
  }
4652
4769
  ),
4770
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4771
+ DropdownMenuItem,
4772
+ {
4773
+ onClick: () => {
4774
+ navigator.clipboard.writeText(dataKey);
4775
+ },
4776
+ children: "Copy key"
4777
+ }
4778
+ ),
4653
4779
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4654
4780
  DeleteAlertDialog,
4655
4781
  {
4656
4782
  deletionType: "key",
4657
4783
  onDeleteConfirm: async () => await deleteKey(dataKey),
4658
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onSelect: (e) => e.preventDefault(), children: "Delete key" })
4784
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4785
+ DropdownMenuItem,
4786
+ {
4787
+ className: "text-red-500 focus:bg-red-500 focus:text-white",
4788
+ onSelect: (e) => e.preventDefault(),
4789
+ children: "Delete key"
4790
+ }
4791
+ )
4659
4792
  }
4660
4793
  )
4661
4794
  ] })
@@ -4677,7 +4810,7 @@ var DisplayHeader = ({
4677
4810
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4678
4811
  /* @__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 }) }),
4679
4812
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
4680
- type !== "string" && type !== "json" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleAddItem, size: "icon-sm", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4 text-zinc-500" }) }),
4813
+ type !== "string" && type !== "json" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleAddItem, size: "icon-sm", "aria-label": "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4 text-zinc-500" }) }),
4681
4814
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content })
4682
4815
  ] })
4683
4816
  ] }),
@@ -4699,7 +4832,7 @@ var DisplayHeader = ({
4699
4832
 
4700
4833
  var Tooltip = TooltipPrimitive.Root;
4701
4834
  var TooltipTrigger = TooltipPrimitive.Trigger;
4702
- var TooltipContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4835
+ var TooltipContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4703
4836
  TooltipPrimitive.Content,
4704
4837
  {
4705
4838
  ref,
@@ -4710,7 +4843,7 @@ var TooltipContent = React11.forwardRef(({ className, sideOffset = 4, ...props }
4710
4843
  ),
4711
4844
  ...props
4712
4845
  }
4713
- ));
4846
+ ) }));
4714
4847
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
4715
4848
  var SimpleTooltip = ({
4716
4849
  content,
@@ -4719,7 +4852,7 @@ var SimpleTooltip = ({
4719
4852
  if (!content) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
4720
4853
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 400, children: [
4721
4854
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children }) }),
4722
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { children: content })
4855
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "top", children: content })
4723
4856
  ] });
4724
4857
  };
4725
4858
 
@@ -4783,7 +4916,7 @@ var useSetHashTTL = () => {
4783
4916
  var HashFieldTTLBadge = ({ dataKey, field }) => {
4784
4917
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
4785
4918
  const { mutate: setTTL, isPending } = useSetHashTTL();
4786
- const expireAt = _optionalChain([data, 'optionalAccess', _35 => _35[field]]);
4919
+ const expireAt = _optionalChain([data, 'optionalAccess', _34 => _34[field]]);
4787
4920
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4788
4921
  TTLBadge,
4789
4922
  {
@@ -4866,63 +4999,59 @@ var CustomEditor = ({
4866
4999
  showCopyButton,
4867
5000
  readOnly
4868
5001
  }) => {
5002
+ const { active } = useTab();
4869
5003
  const monaco = _react2.useMonaco.call(void 0, );
4870
5004
  const editorRef = _react.useRef.call(void 0, );
4871
5005
  _react.useEffect.call(void 0, () => {
4872
- if (!monaco || !editorRef.current) {
5006
+ if (!active || !monaco || !editorRef.current) {
4873
5007
  return;
4874
5008
  }
4875
- _optionalChain([monaco, 'optionalAccess', _36 => _36.editor, 'access', _37 => _37.setModelLanguage, 'call', _38 => _38(editorRef.current.getModel(), language)]);
4876
- }, [monaco, language]);
5009
+ _optionalChain([monaco, 'optionalAccess', _35 => _35.editor, 'access', _36 => _36.setModelLanguage, 'call', _37 => _37(editorRef.current.getModel(), language)]);
5010
+ }, [monaco, language, active]);
5011
+ const editor = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5012
+ _react2.Editor,
5013
+ {
5014
+ loading: void 0,
5015
+ onMount: (editor2) => {
5016
+ editorRef.current = editor2;
5017
+ },
5018
+ value,
5019
+ onChange: (value2) => {
5020
+ onChange(_nullishCoalesce(value2, () => ( "")));
5021
+ },
5022
+ defaultLanguage: language,
5023
+ options: {
5024
+ readOnly,
5025
+ wordWrap: "on",
5026
+ overviewRulerBorder: false,
5027
+ overviewRulerLanes: 0,
5028
+ formatOnPaste: true,
5029
+ formatOnType: true,
5030
+ renderWhitespace: "none",
5031
+ smoothScrolling: true,
5032
+ autoIndent: "full",
5033
+ guides: { indentation: false },
5034
+ fontSize: 13,
5035
+ cursorBlinking: "smooth",
5036
+ minimap: { enabled: false },
5037
+ folding: false,
5038
+ glyphMargin: false,
5039
+ lineNumbers: "off",
5040
+ parameterHints: { enabled: false },
5041
+ lineDecorationsWidth: 0,
5042
+ automaticLayout: true,
5043
+ scrollBeyondLastLine: false,
5044
+ renderLineHighlight: "none"
5045
+ }
5046
+ }
5047
+ );
4877
5048
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4878
5049
  "div",
4879
5050
  {
4880
5051
  className: cn("group/editor relative", height === void 0 && "h-full p-2"),
4881
- style: {
4882
- height
4883
- },
5052
+ style: { height },
4884
5053
  children: [
4885
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4886
- _react2.Editor,
4887
- {
4888
- loading: void 0,
4889
- onMount: (editor) => {
4890
- editorRef.current = editor;
4891
- },
4892
- value,
4893
- onChange: (value2) => {
4894
- onChange(_nullishCoalesce(value2, () => ( "")));
4895
- },
4896
- defaultLanguage: language,
4897
- options: {
4898
- readOnly,
4899
- wordWrap: "on",
4900
- overviewRulerBorder: false,
4901
- overviewRulerLanes: 0,
4902
- formatOnPaste: true,
4903
- formatOnType: true,
4904
- renderWhitespace: "none",
4905
- smoothScrolling: true,
4906
- autoIndent: "full",
4907
- guides: {
4908
- indentation: false
4909
- },
4910
- fontSize: 13,
4911
- cursorBlinking: "smooth",
4912
- minimap: {
4913
- enabled: false
4914
- },
4915
- folding: false,
4916
- glyphMargin: false,
4917
- lineNumbers: "off",
4918
- parameterHints: { enabled: false },
4919
- lineDecorationsWidth: 0,
4920
- automaticLayout: true,
4921
- scrollBeyondLastLine: false,
4922
- renderLineHighlight: "none"
4923
- }
4924
- }
4925
- ),
5054
+ isTest ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "input", { "aria-label": "editor", value, onChange: (e) => onChange(e.target.value) }) : editor,
4926
5055
  showCopyButton && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4927
5056
  CopyButton,
4928
5057
  {
@@ -4995,7 +5124,7 @@ var checkIsValidJSON = (value) => {
4995
5124
  try {
4996
5125
  JSON.parse(value);
4997
5126
  return true;
4998
- } catch (e2) {
5127
+ } catch (e3) {
4999
5128
  return false;
5000
5129
  }
5001
5130
  };
@@ -5019,7 +5148,7 @@ var ListEditForm = ({
5019
5148
  dataKey
5020
5149
  });
5021
5150
  const findValue = () => {
5022
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _39 => _39.data, 'optionalAccess', _40 => _40.pages]), () => ( []))) {
5151
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _38 => _38.data, 'optionalAccess', _39 => _39.pages]), () => ( []))) {
5023
5152
  const item = page.keys.find((item2) => item2.key === itemKey);
5024
5153
  if (item && "value" in item) return item.value;
5025
5154
  }
@@ -5165,7 +5294,7 @@ var HashFieldTTLInfo = ({
5165
5294
  fields
5166
5295
  }) => {
5167
5296
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
5168
- const expireAt = _optionalChain([data, 'optionalAccess', _41 => _41[field]]);
5297
+ const expireAt = _optionalChain([data, 'optionalAccess', _40 => _40[field]]);
5169
5298
  const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
5170
5299
  _react.useEffect.call(void 0, () => {
5171
5300
  setTTL(calculateTTL(expireAt));
@@ -5202,7 +5331,7 @@ var ListItems = ({
5202
5331
  dataKey
5203
5332
  }) => {
5204
5333
  const { setSelectedListItem } = useTab();
5205
- 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]);
5334
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _41 => _41.data, 'optionalAccess', _42 => _42.pages, 'access', _43 => _43.flatMap, 'call', _44 => _44((page) => page.keys)]), () => ( [])), [query.data]);
5206
5335
  const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
5207
5336
  const { mutate: editItem } = useEditListItem();
5208
5337
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -5461,7 +5590,7 @@ function AddKeyModal() {
5461
5590
  setSelectedKey(key);
5462
5591
  setOpen(false);
5463
5592
  setTimeout(() => {
5464
- _optionalChain([window, 'access', _46 => _46.document, 'access', _47 => _47.querySelector, 'call', _48 => _48(`[data-key="${key}"]`), 'optionalAccess', _49 => _49.scrollIntoView, 'call', _50 => _50({
5593
+ _optionalChain([window, 'access', _45 => _45.document, 'access', _46 => _46.querySelector, 'call', _47 => _47(`[data-key="${key}"]`), 'optionalAccess', _48 => _48.scrollIntoView, 'call', _49 => _49({
5465
5594
  behavior: "smooth",
5466
5595
  block: "start",
5467
5596
  inline: "nearest"
@@ -5477,7 +5606,7 @@ function AddKeyModal() {
5477
5606
  setOpen(open2);
5478
5607
  },
5479
5608
  children: [
5480
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", size: "icon-sm", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.PlusIcon, { className: "size-4" }) }) }),
5609
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", size: "icon-sm", "aria-label": "Add key", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.PlusIcon, { className: "size-4" }) }) }),
5481
5610
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-[400px]", children: [
5482
5611
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new key" }) }),
5483
5612
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactdialog.DialogDescription, { children: "Create new key" }) }),
@@ -5506,7 +5635,7 @@ function AddKeyModal() {
5506
5635
  }
5507
5636
  )
5508
5637
  ] }),
5509
- 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]) }),
5638
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _50 => _50.errors, 'access', _51 => _51.key, 'optionalAccess', _52 => _52.message]) }),
5510
5639
  /* @__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" }),
5511
5640
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5512
5641
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5532,7 +5661,7 @@ function AddKeyModal() {
5532
5661
  // src/components/databrowser/components/sidebar/empty.tsx
5533
5662
 
5534
5663
  var Empty = () => {
5535
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full w-full items-center justify-center rounded-md border border-dashed px-4 py-6 text-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-5", children: [
5664
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full w-full items-center justify-center rounded-md border bg-white px-4 py-6 text-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-5", children: [
5536
5665
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-md font-medium", children: "Data on a break" }),
5537
5666
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
5538
5667
  ] }) });
@@ -5600,7 +5729,7 @@ var SidebarContextMenu = ({ children }) => {
5600
5729
 
5601
5730
  var KeysList = () => {
5602
5731
  const { keys } = useKeys();
5603
- 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])) }) });
5732
+ 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', _53 => _53.at, 'call', _54 => _54(i + 1), 'optionalAccess', _55 => _55[0]]), () => ( "")), data }, data[0])) }) });
5604
5733
  };
5605
5734
  var keyStyles = {
5606
5735
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5676,7 +5805,7 @@ var SearchInput = () => {
5676
5805
  } else if (e.key === "Escape") {
5677
5806
  setState("");
5678
5807
  setFocusedIndex(-1);
5679
- _optionalChain([inputRef, 'access', _57 => _57.current, 'optionalAccess', _58 => _58.blur, 'call', _59 => _59()]);
5808
+ _optionalChain([inputRef, 'access', _56 => _56.current, 'optionalAccess', _57 => _57.blur, 'call', _58 => _58()]);
5680
5809
  } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
5681
5810
  e.preventDefault();
5682
5811
  if (focusedIndex < filteredHistory.length - 1) {
@@ -5690,7 +5819,7 @@ var SearchInput = () => {
5690
5819
  setFocusedIndex(focusedIndex - 1);
5691
5820
  } else if (filteredHistory.length > 0 && focusedIndex === 0) {
5692
5821
  setFocusedIndex(-1);
5693
- _optionalChain([inputRef, 'access', _60 => _60.current, 'optionalAccess', _61 => _61.focus, 'call', _62 => _62()]);
5822
+ _optionalChain([inputRef, 'access', _59 => _59.current, 'optionalAccess', _60 => _60.focus, 'call', _61 => _61()]);
5694
5823
  } else if (filteredHistory.length > 0) {
5695
5824
  setFocusedIndex(filteredHistory.length - 1);
5696
5825
  }
@@ -5734,7 +5863,7 @@ var SearchInput = () => {
5734
5863
  },
5735
5864
  onClick: () => handleSubmit(item),
5736
5865
  onMouseEnter: () => setFocusedIndex(index),
5737
- className: `block w-full rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
5866
+ className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
5738
5867
  children: item
5739
5868
  }
5740
5869
  ) }, item))
@@ -5765,7 +5894,7 @@ var SearchInput = () => {
5765
5894
  // src/components/databrowser/components/sidebar/skeleton-buttons.tsx
5766
5895
 
5767
5896
  var DEFAULT_SKELETON_COUNT = 6;
5768
- var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grid", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-2 px-3", children: [
5897
+ var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "block h-full w-full rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-2 px-3", children: [
5769
5898
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "size-5 shrink-0 rounded" }),
5770
5899
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-4 grow rounded" })
5771
5900
  ] }, idx)) });
@@ -5808,6 +5937,7 @@ function Sidebar() {
5808
5937
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5809
5938
  Button,
5810
5939
  {
5940
+ "aria-label": "Refresh",
5811
5941
  className: "h-7 w-7 px-0",
5812
5942
  onClick: () => {
5813
5943
  queryClient.invalidateQueries({
@@ -5856,7 +5986,7 @@ var DatabrowserInstance = ({ hidden }) => {
5856
5986
  className: "h-full w-full gap-0.5 text-sm antialiased",
5857
5987
  children: [
5858
5988
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
5859
- /* @__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" }) }),
5989
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "group flex h-full w-3 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-500" }) }),
5860
5990
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
5861
5991
  ]
5862
5992
  }
@@ -5868,6 +5998,9 @@ var DatabrowserInstance = ({ hidden }) => {
5868
5998
  // src/components/databrowser/components/databrowser-tabs.tsx
5869
5999
 
5870
6000
 
6001
+ // src/components/databrowser/components/tab.tsx
6002
+
6003
+
5871
6004
  // src/components/databrowser/components/tab-type-icon.tsx
5872
6005
 
5873
6006
  function TabTypeIcon({ selectedKey }) {
@@ -5877,24 +6010,52 @@ function TabTypeIcon({ selectedKey }) {
5877
6010
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
5878
6011
  }
5879
6012
 
5880
- // src/components/databrowser/components/databrowser-tabs.tsx
6013
+ // src/hooks/use-overflow.ts
6014
+
6015
+ var useOverflow = () => {
6016
+ const [isOverflow, setIsOverflow] = _react.useState.call(void 0, false);
6017
+ const observerRef = _react.useRef.call(void 0, null);
6018
+ const ref = _react.useCallback.call(void 0, (node) => {
6019
+ if (observerRef.current) {
6020
+ observerRef.current.disconnect();
6021
+ observerRef.current = null;
6022
+ }
6023
+ if (!node) return;
6024
+ observerRef.current = new ResizeObserver((entries) => {
6025
+ const el = _optionalChain([entries, 'access', _62 => _62.at, 'call', _63 => _63(0), 'optionalAccess', _64 => _64.target]);
6026
+ if (!el) return;
6027
+ setIsOverflow(el.scrollWidth > el.clientWidth);
6028
+ });
6029
+ observerRef.current.observe(node);
6030
+ }, []);
6031
+ _react.useEffect.call(void 0, () => {
6032
+ return () => {
6033
+ _optionalChain([observerRef, 'access', _65 => _65.current, 'optionalAccess', _66 => _66.disconnect, 'call', _67 => _67()]);
6034
+ };
6035
+ }, []);
6036
+ return { ref, isOverflow };
6037
+ };
6038
+
6039
+ // src/components/databrowser/components/tab.tsx
5881
6040
 
5882
6041
  var Tab = ({ id }) => {
5883
- const { selectTab, selectedTab, tabs, removeTab } = useDatabrowserStore();
5884
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6042
+ const { active, search, selectedKey } = useTab();
6043
+ const { selectTab, removeTab, tabs } = useDatabrowserStore();
6044
+ const { ref, isOverflow } = useOverflow();
6045
+ const label = search.key || selectedKey;
6046
+ const iconNode = search.key ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 15 }) : selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabTypeIcon, { selectedKey }) : void 0;
6047
+ const tabNode = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5885
6048
  "div",
5886
6049
  {
5887
6050
  onClick: () => selectTab(id),
5888
6051
  className: cn(
5889
6052
  "flex h-9 cursor-pointer items-center gap-2 rounded-t-lg border border-zinc-200 px-3 text-[13px] transition-colors",
5890
- id === selectedTab ? "border-b-white bg-white text-zinc-900" : "bg-zinc-100 hover:bg-zinc-50"
6053
+ active ? "border-b-white bg-white text-zinc-900" : "bg-zinc-100 hover:bg-zinc-50"
5891
6054
  ),
5892
6055
  children: [
5893
- tabs[id].selectedKey ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5894
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabTypeIcon, { selectedKey: tabs[id].selectedKey }),
5895
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "max-w-32 truncate whitespace-nowrap", children: tabs[id].selectedKey })
5896
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "whitespace-nowrap", children: "New Tab" }),
5897
- Object.keys(tabs).length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6056
+ iconNode,
6057
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { ref, className: "max-w-32 truncate whitespace-nowrap", children: label || "New Tab" }),
6058
+ tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5898
6059
  "button",
5899
6060
  {
5900
6061
  onClick: (e) => {
@@ -5908,13 +6069,17 @@ var Tab = ({ id }) => {
5908
6069
  ]
5909
6070
  }
5910
6071
  );
6072
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: isOverflow ? label : void 0, children: tabNode });
5911
6073
  };
6074
+
6075
+ // src/components/databrowser/components/databrowser-tabs.tsx
6076
+
5912
6077
  var DatabrowserTabs = () => {
5913
6078
  const { tabs, addTab } = useDatabrowserStore();
5914
6079
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative mb-2 shrink-0", children: [
5915
6080
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-0 left-0 right-0 -z-10 h-[1px] w-full bg-zinc-200" }),
5916
6081
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "scrollbar-hide flex translate-y-[1px] items-center gap-1 overflow-x-scroll pb-[1px] [&::-webkit-scrollbar]:hidden", children: [
5917
- Object.keys(tabs).map((id) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Tab, { id }, id)),
6082
+ tabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdProvider, { value: id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Tab, { id }) }, id)),
5918
6083
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5919
6084
  Button,
5920
6085
  {
@@ -5935,13 +6100,14 @@ var DatabrowserTabs = () => {
5935
6100
  var RedisBrowser = ({
5936
6101
  token,
5937
6102
  url,
5938
- hideTabs
6103
+ hideTabs,
6104
+ storage
5939
6105
  }) => {
5940
6106
  const credentials = _react.useMemo.call(void 0, () => ({ token, url }), [token, url]);
5941
6107
  _react.useEffect.call(void 0, () => {
5942
6108
  queryClient.resetQueries();
5943
6109
  }, [credentials.url]);
5944
- 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,
6110
+ 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, { storage, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacttooltip.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5945
6111
  "div",
5946
6112
  {
5947
6113
  className: "ups-db",
@@ -5956,9 +6122,9 @@ var RedisBrowser = ({
5956
6122
  var DatabrowserInstances = () => {
5957
6123
  const { tabs, selectedTab, addTab } = useDatabrowserStore();
5958
6124
  _react.useEffect.call(void 0, () => {
5959
- if (Object.keys(tabs).length === 0) addTab();
6125
+ if (tabs.length === 0) addTab();
5960
6126
  }, [tabs]);
5961
- 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));
6127
+ return tabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdProvider, { value: id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstance, { hidden: id !== selectedTab }) }, id));
5962
6128
  };
5963
6129
 
5964
6130