@upstash/react-redis-browser 0.1.2-canary-5 → 0.1.2-canary-6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +151 -119
  2. package/dist/index.mjs +150 -118
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2891,6 +2891,12 @@ function Toaster() {
2891
2891
 
2892
2892
 
2893
2893
 
2894
+
2895
+
2896
+
2897
+
2898
+
2899
+
2894
2900
  // src/components/databrowser/hooks/use-fetch-keys.ts
2895
2901
 
2896
2902
 
@@ -2908,35 +2914,28 @@ var DATA_TYPE_NAMES = {
2908
2914
 
2909
2915
  // src/components/databrowser/hooks/use-fetch-keys.ts
2910
2916
  var PAGE_SIZE = 30;
2911
- var INITIAL_FETCH_COUNT = 100;
2912
- var MAX_FETCH_COUNT = 1e3;
2917
+ var FETCH_COUNTS = [100, 200, 400, 800];
2913
2918
  var useFetchKeys = (search) => {
2914
2919
  const { redis } = useDatabrowser();
2915
2920
  const cache = _react.useRef.call(void 0, );
2916
2921
  const lastKey = _react.useRef.call(void 0, );
2917
- const getPage = _react.useCallback.call(void 0,
2918
- (page) => {
2919
- const newKey = JSON.stringify(search);
2920
- if (!cache.current || lastKey.current !== newKey) {
2921
- cache.current = new PaginationCache(redis, search.key, search.type);
2922
- lastKey.current = newKey;
2923
- }
2924
- return cache.current.getPage(page);
2925
- },
2926
- [search]
2927
- );
2922
+ const fetchKeys = _react.useCallback.call(void 0, () => {
2923
+ const newKey = JSON.stringify(search);
2924
+ if (!cache.current || lastKey.current !== newKey) {
2925
+ cache.current = new PaginationCache(redis, search.key, search.type);
2926
+ lastKey.current = newKey;
2927
+ }
2928
+ return cache.current.fetchNewKeys();
2929
+ }, [search]);
2928
2930
  const resetCache = _react.useCallback.call(void 0, () => {
2929
2931
  cache.current = void 0;
2930
2932
  lastKey.current = void 0;
2931
2933
  }, []);
2932
2934
  return {
2933
- getPage,
2935
+ fetchKeys,
2934
2936
  resetCache
2935
2937
  };
2936
2938
  };
2937
- function slicePage(keys, page) {
2938
- return keys.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);
2939
- }
2940
2939
  var PaginationCache = (_class = class {
2941
2940
  constructor(redis, searchTerm, typeFilter) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
2942
2941
  this.redis = redis;
@@ -2952,8 +2951,9 @@ var PaginationCache = (_class = class {
2952
2951
  )}
2953
2952
  __init2() {this.targetCount = 0}
2954
2953
  __init3() {this.isFetching = false}
2955
- async getPage(page) {
2956
- this.targetCount = (page + 1) * PAGE_SIZE + 1;
2954
+ async fetchNewKeys() {
2955
+ const initialKeys = new Set(this.getKeys().map(([key]) => key));
2956
+ this.targetCount = this.getKeys().length + PAGE_SIZE;
2957
2957
  void this.startFetch();
2958
2958
  await new Promise((resolve) => {
2959
2959
  const interval = setInterval(() => {
@@ -2963,10 +2963,9 @@ var PaginationCache = (_class = class {
2963
2963
  }
2964
2964
  }, 100);
2965
2965
  });
2966
- const hasEnoughForNextPage = this.getLength() > (page + 1) * PAGE_SIZE;
2967
- const hasNextPage = !this.isAllEnded() || hasEnoughForNextPage;
2966
+ const hasNextPage = !this.isAllEnded();
2968
2967
  return {
2969
- keys: slicePage(this.getKeys(), page),
2968
+ keys: this.getKeys().filter(([key]) => !initialKeys.has(key)),
2970
2969
  hasNextPage
2971
2970
  };
2972
2971
  }
@@ -2992,33 +2991,29 @@ var PaginationCache = (_class = class {
2992
2991
  }
2993
2992
  }
2994
2993
  __init4() {this.fetchForType = async (type) => {
2995
- let fetchCount = INITIAL_FETCH_COUNT;
2994
+ let i = 0;
2996
2995
  while (true) {
2997
2996
  const cursor = this.cache[type].cursor;
2998
2997
  if (cursor === "-1" || this.getLength() >= this.targetCount) {
2999
2998
  break;
3000
2999
  }
3000
+ const fetchCount = FETCH_COUNTS[Math.min(i, FETCH_COUNTS.length - 1)];
3001
3001
  const [nextCursor, newKeys] = await this.redis.scan(cursor, {
3002
3002
  count: fetchCount,
3003
3003
  match: this.searchTerm,
3004
3004
  type
3005
3005
  });
3006
- fetchCount = Math.min(fetchCount * 2, MAX_FETCH_COUNT);
3007
- const dedupedSet = /* @__PURE__ */ new Set([...this.cache[type].keys, ...newKeys]);
3008
- this.cache[type].keys = [...dedupedSet];
3006
+ this.cache[type].keys = [...this.cache[type].keys, ...newKeys];
3009
3007
  this.cache[type].cursor = nextCursor === "0" ? "-1" : nextCursor;
3008
+ i++;
3010
3009
  }
3011
3010
  }}
3012
3011
  async fetch() {
3013
3012
  const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3014
3013
  await Promise.all(types.map(this.fetchForType));
3015
3014
  }
3016
- // TODO: Yusuf, implement this function
3017
3015
  isAllEnded() {
3018
3016
  const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3019
- if (!Array.isArray(types)) {
3020
- throw new TypeError("types is not an array");
3021
- }
3022
3017
  return types.every((type) => this.cache[type] && this.cache[type].cursor === "-1");
3023
3018
  }
3024
3019
  }, _class);
@@ -3036,17 +3031,21 @@ var KeysProvider = ({ children }) => {
3036
3031
  }),
3037
3032
  [searchState]
3038
3033
  );
3039
- const { getPage, resetCache } = useFetchKeys(search);
3034
+ const { fetchKeys, resetCache } = useFetchKeys(search);
3035
+ const pageRef = _react.useRef.call(void 0, 0);
3040
3036
  const query = _reactquery.useInfiniteQuery.call(void 0, {
3041
3037
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3042
3038
  initialPageParam: 0,
3043
- queryFn: async ({ pageParam: pageIndex }) => {
3044
- return getPage(pageIndex);
3039
+ queryFn: async ({ pageParam: page }) => {
3040
+ if (pageRef.current > page) resetCache();
3041
+ pageRef.current = page;
3042
+ return await fetchKeys();
3045
3043
  },
3046
3044
  select: (data) => data,
3047
3045
  getNextPageParam: (lastPage, __, lastPageIndex) => {
3048
3046
  return lastPage.hasNextPage ? lastPageIndex + 1 : void 0;
3049
- }
3047
+ },
3048
+ refetchOnMount: false
3050
3049
  });
3051
3050
  const refetch = _react.useCallback.call(void 0, () => {
3052
3051
  resetCache();
@@ -3054,8 +3053,14 @@ var KeysProvider = ({ children }) => {
3054
3053
  }, [query, resetCache]);
3055
3054
  const keys = _react.useMemo.call(void 0, () => {
3056
3055
  const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.pages, 'access', _12 => _12.flatMap, 'call', _13 => _13((page) => page.keys)]), () => ( []));
3057
- const keysSet = new Set(keys2.map(([key, _]) => key));
3058
- return keys2.filter(([key, _]) => keysSet.has(key));
3056
+ const keysSet = /* @__PURE__ */ new Set();
3057
+ const dedupedKeys = [];
3058
+ for (const key of keys2) {
3059
+ if (keysSet.has(key[0])) continue;
3060
+ keysSet.add(key[0]);
3061
+ dedupedKeys.push(key);
3062
+ }
3063
+ return dedupedKeys;
3059
3064
  }, [query.data]);
3060
3065
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3061
3066
  KeysContext.Provider,
@@ -3802,7 +3807,9 @@ function DeleteAlertDialog({
3802
3807
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
3803
3808
  "Are you sure you want to delete this ",
3804
3809
  deletionType,
3805
- "? This action cannot be undone."
3810
+ "?",
3811
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
3812
+ "This action cannot be undone."
3806
3813
  ] })
3807
3814
  ] }),
3808
3815
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogFooter, { children: [
@@ -3825,12 +3832,11 @@ function DeleteAlertDialog({
3825
3832
  var ItemContextMenu = ({
3826
3833
  children,
3827
3834
  dataKey,
3828
- itemKey,
3829
- itemValue,
3830
3835
  type
3831
3836
  }) => {
3832
3837
  const { mutate: editItem } = useEditListItem();
3833
3838
  const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
3839
+ const [data, setData] = _react.useState.call(void 0, );
3834
3840
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3835
3841
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3836
3842
  DeleteAlertDialog,
@@ -3840,25 +3846,46 @@ var ItemContextMenu = ({
3840
3846
  onOpenChange: setAlertOpen,
3841
3847
  onDeleteConfirm: (e) => {
3842
3848
  e.stopPropagation();
3843
- editItem({
3844
- type,
3845
- dataKey,
3846
- itemKey,
3847
- // For deletion
3848
- newKey: void 0
3849
- });
3849
+ if (data) {
3850
+ editItem({
3851
+ type,
3852
+ dataKey,
3853
+ itemKey: _optionalChain([data, 'optionalAccess', _20 => _20.key]),
3854
+ // For deletion
3855
+ newKey: void 0
3856
+ });
3857
+ }
3850
3858
  setAlertOpen(false);
3851
3859
  }
3852
3860
  }
3853
3861
  ),
3854
3862
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { children: [
3855
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuTrigger, { asChild: true, children }),
3863
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3864
+ ContextMenuTrigger,
3865
+ {
3866
+ asChild: true,
3867
+ onContextMenu: (e) => {
3868
+ const el = e.target;
3869
+ const item = el.closest("[data-item-key]");
3870
+ if (item && item instanceof HTMLElement && item.dataset.itemKey !== void 0) {
3871
+ setData({
3872
+ key: item.dataset.itemKey,
3873
+ value: item.dataset.itemValue
3874
+ });
3875
+ } else {
3876
+ throw new Error("Key not found");
3877
+ }
3878
+ },
3879
+ children
3880
+ }
3881
+ ),
3856
3882
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
3857
3883
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3858
3884
  ContextMenuItem,
3859
3885
  {
3860
3886
  onClick: () => {
3861
- navigator.clipboard.writeText(itemKey);
3887
+ if (!data) return;
3888
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _21 => _21.key]));
3862
3889
  toast({
3863
3890
  description: "Key copied to clipboard"
3864
3891
  });
@@ -3866,11 +3893,11 @@ var ItemContextMenu = ({
3866
3893
  children: "Copy key"
3867
3894
  }
3868
3895
  ),
3869
- itemValue !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3896
+ _optionalChain([data, 'optionalAccess', _22 => _22.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3870
3897
  ContextMenuItem,
3871
3898
  {
3872
3899
  onClick: () => {
3873
- navigator.clipboard.writeText(itemValue);
3900
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _23 => _23.value]), () => ( "")));
3874
3901
  toast({
3875
3902
  description: "Value copied to clipboard"
3876
3903
  });
@@ -4362,7 +4389,7 @@ var LengthBadge = ({
4362
4389
  content
4363
4390
  }) => {
4364
4391
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
4365
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _20 => _20.length]), () => ( data));
4392
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _24 => _24.length]), () => ( data));
4366
4393
  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 });
4367
4394
  };
4368
4395
  var SizeBadge = ({ dataKey }) => {
@@ -4682,7 +4709,7 @@ var CustomEditor = ({
4682
4709
  if (!monaco || !editorRef.current) {
4683
4710
  return;
4684
4711
  }
4685
- _optionalChain([monaco, 'optionalAccess', _21 => _21.editor, 'access', _22 => _22.setModelLanguage, 'call', _23 => _23(editorRef.current.getModel(), language)]);
4712
+ _optionalChain([monaco, 'optionalAccess', _25 => _25.editor, 'access', _26 => _26.setModelLanguage, 'call', _27 => _27(editorRef.current.getModel(), language)]);
4686
4713
  }, [monaco, language]);
4687
4714
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4688
4715
  "div",
@@ -4928,7 +4955,7 @@ var ListDisplay = ({ dataKey, type }) => {
4928
4955
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: [
4929
4956
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type }),
4930
4957
  selectedListItem && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditDisplay, { dataKey, type, item: selectedListItem }),
4931
- /* @__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, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) })
4958
+ /* @__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 }) }) }) }) }) }) })
4932
4959
  ] });
4933
4960
  };
4934
4961
  var ListItems = ({
@@ -4937,70 +4964,63 @@ var ListItems = ({
4937
4964
  dataKey
4938
4965
  }) => {
4939
4966
  const { setSelectedListItem } = useDatabrowserStore();
4940
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _24 => _24.data, 'optionalAccess', _25 => _25.pages, 'access', _26 => _26.flatMap, 'call', _27 => _27((page) => page.keys)]), () => ( [])), [query.data]);
4967
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _28 => _28.data, 'optionalAccess', _29 => _29.pages, 'access', _30 => _30.flatMap, 'call', _31 => _31((page) => page.keys)]), () => ( [])), [query.data]);
4941
4968
  const { mutate: editItem } = useEditListItem();
4942
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4943
- ItemContextMenu,
4969
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4970
+ "tr",
4944
4971
  {
4945
- dataKey,
4946
- type,
4947
- itemKey: key,
4948
- itemValue: value,
4949
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4950
- "tr",
4951
- {
4952
- onClick: () => {
4953
- setSelectedListItem({ key, value });
4954
- },
4955
- className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
4956
- children: [
4957
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4958
- "td",
4959
- {
4960
- className: cn(
4961
- "cursor-pointer truncate px-3",
4962
- type === "list" || type === "stream" ? "w-32 min-w-24" : "max-w-0"
4963
- ),
4964
- children: key
4965
- }
4966
- ),
4967
- value !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4968
- "td",
4969
- {
4970
- className: cn("cursor-pointer truncate px-3", type === "zset" ? "w-24" : "max-w-0"),
4971
- children: value
4972
- }
4972
+ "data-item-key": key,
4973
+ "data-item-value": value,
4974
+ onClick: () => {
4975
+ setSelectedListItem({ key, value });
4976
+ },
4977
+ className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
4978
+ children: [
4979
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4980
+ "td",
4981
+ {
4982
+ className: cn(
4983
+ "cursor-pointer truncate px-3",
4984
+ type === "list" || type === "stream" ? "w-32 min-w-24" : "max-w-0"
4973
4985
  ),
4974
- type !== "stream" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4975
- "td",
4986
+ children: key
4987
+ }
4988
+ ),
4989
+ value !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4990
+ "td",
4991
+ {
4992
+ className: cn("cursor-pointer truncate px-3", type === "zset" ? "w-24" : "max-w-0"),
4993
+ children: value
4994
+ }
4995
+ ),
4996
+ type !== "stream" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4997
+ "td",
4998
+ {
4999
+ width: 20,
5000
+ className: "px-3",
5001
+ onClick: (e) => {
5002
+ e.stopPropagation();
5003
+ },
5004
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5005
+ DeleteAlertDialog,
4976
5006
  {
4977
- width: 20,
4978
- className: "px-3",
4979
- onClick: (e) => {
5007
+ deletionType: "item",
5008
+ onDeleteConfirm: (e) => {
4980
5009
  e.stopPropagation();
5010
+ editItem({
5011
+ type,
5012
+ dataKey,
5013
+ itemKey: key,
5014
+ // For deletion
5015
+ newKey: void 0
5016
+ });
4981
5017
  },
4982
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4983
- DeleteAlertDialog,
4984
- {
4985
- deletionType: "item",
4986
- onDeleteConfirm: (e) => {
4987
- e.stopPropagation();
4988
- editItem({
4989
- type,
4990
- dataKey,
4991
- itemKey: key,
4992
- // For deletion
4993
- newKey: void 0
4994
- });
4995
- },
4996
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", variant: "secondary", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { className: "size-4 text-zinc-500" }) })
4997
- }
4998
- )
5018
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", variant: "secondary", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { className: "size-4 text-zinc-500" }) })
4999
5019
  }
5000
5020
  )
5001
- ]
5002
- }
5003
- )
5021
+ }
5022
+ )
5023
+ ]
5004
5024
  },
5005
5025
  `${dataKey}-${key}-${i}`
5006
5026
  )) });
@@ -5199,7 +5219,7 @@ function AddKeyModal() {
5199
5219
  setSelectedKey(key);
5200
5220
  setOpen(false);
5201
5221
  setTimeout(() => {
5202
- _optionalChain([window, 'access', _28 => _28.document, 'access', _29 => _29.querySelector, 'call', _30 => _30(`[data-key="${key}"]`), 'optionalAccess', _31 => _31.scrollIntoView, 'call', _32 => _32({
5222
+ _optionalChain([window, 'access', _32 => _32.document, 'access', _33 => _33.querySelector, 'call', _34 => _34(`[data-key="${key}"]`), 'optionalAccess', _35 => _35.scrollIntoView, 'call', _36 => _36({
5203
5223
  behavior: "smooth",
5204
5224
  block: "start",
5205
5225
  inline: "nearest"
@@ -5250,7 +5270,7 @@ function AddKeyModal() {
5250
5270
  }
5251
5271
  )
5252
5272
  ] }),
5253
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _33 => _33.errors, 'access', _34 => _34.key, 'optionalAccess', _35 => _35.message]) }),
5273
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _37 => _37.errors, 'access', _38 => _38.key, 'optionalAccess', _39 => _39.message]) }),
5254
5274
  /* @__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" }),
5255
5275
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5256
5276
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5286,12 +5306,10 @@ var Empty = () => {
5286
5306
 
5287
5307
 
5288
5308
 
5289
- var SidebarContextMenu = ({
5290
- children,
5291
- dataKey
5292
- }) => {
5309
+ var SidebarContextMenu = ({ children }) => {
5293
5310
  const { mutate: deleteKey } = useDeleteKey();
5294
5311
  const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
5312
+ const [dataKey, setDataKey] = _react.useState.call(void 0, "");
5295
5313
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5296
5314
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5297
5315
  DeleteAlertDialog,
@@ -5307,7 +5325,21 @@ var SidebarContextMenu = ({
5307
5325
  }
5308
5326
  ),
5309
5327
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { children: [
5310
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuTrigger, { asChild: true, children }),
5328
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5329
+ ContextMenuTrigger,
5330
+ {
5331
+ onContextMenu: (e) => {
5332
+ const el = e.target;
5333
+ const key = el.closest("[data-key]");
5334
+ if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
5335
+ setDataKey(key.dataset.key);
5336
+ } else {
5337
+ throw new Error("Key not found");
5338
+ }
5339
+ },
5340
+ children
5341
+ }
5342
+ ),
5311
5343
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
5312
5344
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5313
5345
  ContextMenuItem,
@@ -5332,7 +5364,7 @@ var SidebarContextMenu = ({
5332
5364
 
5333
5365
  var KeysList = () => {
5334
5366
  const { keys } = useKeys();
5335
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _36 => _36.at, 'call', _37 => _37(i + 1), 'optionalAccess', _38 => _38[0]]), () => ( "")), data }, data[0])) });
5367
+ 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', _40 => _40.at, 'call', _41 => _41(i + 1), 'optionalAccess', _42 => _42[0]]), () => ( "")), data }, data[0])) }) }) });
5336
5368
  };
5337
5369
  var keyStyles = {
5338
5370
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5348,7 +5380,7 @@ var KeyItem = ({ data, nextKey }) => {
5348
5380
  const [dataKey, dataType] = data;
5349
5381
  const isKeySelected = selectedKey === dataKey;
5350
5382
  const isNextKeySelected = selectedKey === nextKey;
5351
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { dataKey, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5383
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5352
5384
  Button,
5353
5385
  {
5354
5386
  "data-key": dataKey,
@@ -5366,7 +5398,7 @@ var KeyItem = ({ data, nextKey }) => {
5366
5398
  !isKeySelected && !isNextKeySelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute -bottom-px left-3 right-3 h-px bg-zinc-100" })
5367
5399
  ]
5368
5400
  }
5369
- ) }, dataKey);
5401
+ );
5370
5402
  };
5371
5403
 
5372
5404
  // src/components/databrowser/components/sidebar/search-input.tsx
package/dist/index.mjs CHANGED
@@ -2888,7 +2888,13 @@ function Toaster() {
2888
2888
  }
2889
2889
 
2890
2890
  // src/components/databrowser/hooks/use-keys.tsx
2891
- import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useMemo as useMemo2 } from "react";
2891
+ import {
2892
+ createContext as createContext2,
2893
+ useCallback as useCallback2,
2894
+ useContext as useContext2,
2895
+ useMemo as useMemo2,
2896
+ useRef as useRef2
2897
+ } from "react";
2892
2898
  import { useInfiniteQuery } from "@tanstack/react-query";
2893
2899
 
2894
2900
  // src/components/databrowser/hooks/use-fetch-keys.ts
@@ -2908,35 +2914,28 @@ var DATA_TYPE_NAMES = {
2908
2914
 
2909
2915
  // src/components/databrowser/hooks/use-fetch-keys.ts
2910
2916
  var PAGE_SIZE = 30;
2911
- var INITIAL_FETCH_COUNT = 100;
2912
- var MAX_FETCH_COUNT = 1e3;
2917
+ var FETCH_COUNTS = [100, 200, 400, 800];
2913
2918
  var useFetchKeys = (search) => {
2914
2919
  const { redis } = useDatabrowser();
2915
2920
  const cache = useRef();
2916
2921
  const lastKey = useRef();
2917
- const getPage = useCallback(
2918
- (page) => {
2919
- const newKey = JSON.stringify(search);
2920
- if (!cache.current || lastKey.current !== newKey) {
2921
- cache.current = new PaginationCache(redis, search.key, search.type);
2922
- lastKey.current = newKey;
2923
- }
2924
- return cache.current.getPage(page);
2925
- },
2926
- [search]
2927
- );
2922
+ const fetchKeys = useCallback(() => {
2923
+ const newKey = JSON.stringify(search);
2924
+ if (!cache.current || lastKey.current !== newKey) {
2925
+ cache.current = new PaginationCache(redis, search.key, search.type);
2926
+ lastKey.current = newKey;
2927
+ }
2928
+ return cache.current.fetchNewKeys();
2929
+ }, [search]);
2928
2930
  const resetCache = useCallback(() => {
2929
2931
  cache.current = void 0;
2930
2932
  lastKey.current = void 0;
2931
2933
  }, []);
2932
2934
  return {
2933
- getPage,
2935
+ fetchKeys,
2934
2936
  resetCache
2935
2937
  };
2936
2938
  };
2937
- function slicePage(keys, page) {
2938
- return keys.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);
2939
- }
2940
2939
  var PaginationCache = class {
2941
2940
  constructor(redis, searchTerm, typeFilter) {
2942
2941
  this.redis = redis;
@@ -2952,8 +2951,9 @@ var PaginationCache = class {
2952
2951
  );
2953
2952
  targetCount = 0;
2954
2953
  isFetching = false;
2955
- async getPage(page) {
2956
- this.targetCount = (page + 1) * PAGE_SIZE + 1;
2954
+ async fetchNewKeys() {
2955
+ const initialKeys = new Set(this.getKeys().map(([key]) => key));
2956
+ this.targetCount = this.getKeys().length + PAGE_SIZE;
2957
2957
  void this.startFetch();
2958
2958
  await new Promise((resolve) => {
2959
2959
  const interval = setInterval(() => {
@@ -2963,10 +2963,9 @@ var PaginationCache = class {
2963
2963
  }
2964
2964
  }, 100);
2965
2965
  });
2966
- const hasEnoughForNextPage = this.getLength() > (page + 1) * PAGE_SIZE;
2967
- const hasNextPage = !this.isAllEnded() || hasEnoughForNextPage;
2966
+ const hasNextPage = !this.isAllEnded();
2968
2967
  return {
2969
- keys: slicePage(this.getKeys(), page),
2968
+ keys: this.getKeys().filter(([key]) => !initialKeys.has(key)),
2970
2969
  hasNextPage
2971
2970
  };
2972
2971
  }
@@ -2992,33 +2991,29 @@ var PaginationCache = class {
2992
2991
  }
2993
2992
  }
2994
2993
  fetchForType = async (type) => {
2995
- let fetchCount = INITIAL_FETCH_COUNT;
2994
+ let i = 0;
2996
2995
  while (true) {
2997
2996
  const cursor = this.cache[type].cursor;
2998
2997
  if (cursor === "-1" || this.getLength() >= this.targetCount) {
2999
2998
  break;
3000
2999
  }
3000
+ const fetchCount = FETCH_COUNTS[Math.min(i, FETCH_COUNTS.length - 1)];
3001
3001
  const [nextCursor, newKeys] = await this.redis.scan(cursor, {
3002
3002
  count: fetchCount,
3003
3003
  match: this.searchTerm,
3004
3004
  type
3005
3005
  });
3006
- fetchCount = Math.min(fetchCount * 2, MAX_FETCH_COUNT);
3007
- const dedupedSet = /* @__PURE__ */ new Set([...this.cache[type].keys, ...newKeys]);
3008
- this.cache[type].keys = [...dedupedSet];
3006
+ this.cache[type].keys = [...this.cache[type].keys, ...newKeys];
3009
3007
  this.cache[type].cursor = nextCursor === "0" ? "-1" : nextCursor;
3008
+ i++;
3010
3009
  }
3011
3010
  };
3012
3011
  async fetch() {
3013
3012
  const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3014
3013
  await Promise.all(types.map(this.fetchForType));
3015
3014
  }
3016
- // TODO: Yusuf, implement this function
3017
3015
  isAllEnded() {
3018
3016
  const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3019
- if (!Array.isArray(types)) {
3020
- throw new TypeError("types is not an array");
3021
- }
3022
3017
  return types.every((type) => this.cache[type] && this.cache[type].cursor === "-1");
3023
3018
  }
3024
3019
  };
@@ -3036,17 +3031,21 @@ var KeysProvider = ({ children }) => {
3036
3031
  }),
3037
3032
  [searchState]
3038
3033
  );
3039
- const { getPage, resetCache } = useFetchKeys(search);
3034
+ const { fetchKeys, resetCache } = useFetchKeys(search);
3035
+ const pageRef = useRef2(0);
3040
3036
  const query = useInfiniteQuery({
3041
3037
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3042
3038
  initialPageParam: 0,
3043
- queryFn: async ({ pageParam: pageIndex }) => {
3044
- return getPage(pageIndex);
3039
+ queryFn: async ({ pageParam: page }) => {
3040
+ if (pageRef.current > page) resetCache();
3041
+ pageRef.current = page;
3042
+ return await fetchKeys();
3045
3043
  },
3046
3044
  select: (data) => data,
3047
3045
  getNextPageParam: (lastPage, __, lastPageIndex) => {
3048
3046
  return lastPage.hasNextPage ? lastPageIndex + 1 : void 0;
3049
- }
3047
+ },
3048
+ refetchOnMount: false
3050
3049
  });
3051
3050
  const refetch = useCallback2(() => {
3052
3051
  resetCache();
@@ -3054,8 +3053,14 @@ var KeysProvider = ({ children }) => {
3054
3053
  }, [query, resetCache]);
3055
3054
  const keys = useMemo2(() => {
3056
3055
  const keys2 = query.data?.pages.flatMap((page) => page.keys) ?? [];
3057
- const keysSet = new Set(keys2.map(([key, _]) => key));
3058
- return keys2.filter(([key, _]) => keysSet.has(key));
3056
+ const keysSet = /* @__PURE__ */ new Set();
3057
+ const dedupedKeys = [];
3058
+ for (const key of keys2) {
3059
+ if (keysSet.has(key[0])) continue;
3060
+ keysSet.add(key[0]);
3061
+ dedupedKeys.push(key);
3062
+ }
3063
+ return dedupedKeys;
3059
3064
  }, [query.data]);
3060
3065
  return /* @__PURE__ */ jsx4(
3061
3066
  KeysContext.Provider,
@@ -3802,7 +3807,9 @@ function DeleteAlertDialog({
3802
3807
  /* @__PURE__ */ jsxs5(AlertDialogDescription, { className: "mt-5", children: [
3803
3808
  "Are you sure you want to delete this ",
3804
3809
  deletionType,
3805
- "? This action cannot be undone."
3810
+ "?",
3811
+ /* @__PURE__ */ jsx10("br", {}),
3812
+ "This action cannot be undone."
3806
3813
  ] })
3807
3814
  ] }),
3808
3815
  /* @__PURE__ */ jsxs5(AlertDialogFooter, { children: [
@@ -3825,12 +3832,11 @@ import { Fragment, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
3825
3832
  var ItemContextMenu = ({
3826
3833
  children,
3827
3834
  dataKey,
3828
- itemKey,
3829
- itemValue,
3830
3835
  type
3831
3836
  }) => {
3832
3837
  const { mutate: editItem } = useEditListItem();
3833
3838
  const [isAlertOpen, setAlertOpen] = useState4(false);
3839
+ const [data, setData] = useState4();
3834
3840
  return /* @__PURE__ */ jsxs6(Fragment, { children: [
3835
3841
  /* @__PURE__ */ jsx11(
3836
3842
  DeleteAlertDialog,
@@ -3840,25 +3846,46 @@ var ItemContextMenu = ({
3840
3846
  onOpenChange: setAlertOpen,
3841
3847
  onDeleteConfirm: (e) => {
3842
3848
  e.stopPropagation();
3843
- editItem({
3844
- type,
3845
- dataKey,
3846
- itemKey,
3847
- // For deletion
3848
- newKey: void 0
3849
- });
3849
+ if (data) {
3850
+ editItem({
3851
+ type,
3852
+ dataKey,
3853
+ itemKey: data?.key,
3854
+ // For deletion
3855
+ newKey: void 0
3856
+ });
3857
+ }
3850
3858
  setAlertOpen(false);
3851
3859
  }
3852
3860
  }
3853
3861
  ),
3854
3862
  /* @__PURE__ */ jsxs6(ContextMenu, { children: [
3855
- /* @__PURE__ */ jsx11(ContextMenuTrigger, { asChild: true, children }),
3863
+ /* @__PURE__ */ jsx11(
3864
+ ContextMenuTrigger,
3865
+ {
3866
+ asChild: true,
3867
+ onContextMenu: (e) => {
3868
+ const el = e.target;
3869
+ const item = el.closest("[data-item-key]");
3870
+ if (item && item instanceof HTMLElement && item.dataset.itemKey !== void 0) {
3871
+ setData({
3872
+ key: item.dataset.itemKey,
3873
+ value: item.dataset.itemValue
3874
+ });
3875
+ } else {
3876
+ throw new Error("Key not found");
3877
+ }
3878
+ },
3879
+ children
3880
+ }
3881
+ ),
3856
3882
  /* @__PURE__ */ jsxs6(ContextMenuContent, { children: [
3857
3883
  /* @__PURE__ */ jsx11(
3858
3884
  ContextMenuItem,
3859
3885
  {
3860
3886
  onClick: () => {
3861
- navigator.clipboard.writeText(itemKey);
3887
+ if (!data) return;
3888
+ navigator.clipboard.writeText(data?.key);
3862
3889
  toast({
3863
3890
  description: "Key copied to clipboard"
3864
3891
  });
@@ -3866,11 +3893,11 @@ var ItemContextMenu = ({
3866
3893
  children: "Copy key"
3867
3894
  }
3868
3895
  ),
3869
- itemValue !== void 0 && /* @__PURE__ */ jsx11(
3896
+ data?.value && /* @__PURE__ */ jsx11(
3870
3897
  ContextMenuItem,
3871
3898
  {
3872
3899
  onClick: () => {
3873
- navigator.clipboard.writeText(itemValue);
3900
+ navigator.clipboard.writeText(data?.value ?? "");
3874
3901
  toast({
3875
3902
  description: "Value copied to clipboard"
3876
3903
  });
@@ -4629,7 +4656,7 @@ var ContentTypeSelect = ({
4629
4656
  };
4630
4657
 
4631
4658
  // src/components/databrowser/components/display/input/custom-editor.tsx
4632
- import { useEffect as useEffect6, useRef as useRef2 } from "react";
4659
+ import { useEffect as useEffect6, useRef as useRef3 } from "react";
4633
4660
  import { Editor, useMonaco } from "@monaco-editor/react";
4634
4661
 
4635
4662
  // src/components/databrowser/copy-button.tsx
@@ -4677,7 +4704,7 @@ var CustomEditor = ({
4677
4704
  showCopyButton
4678
4705
  }) => {
4679
4706
  const monaco = useMonaco();
4680
- const editorRef = useRef2();
4707
+ const editorRef = useRef3();
4681
4708
  useEffect6(() => {
4682
4709
  if (!monaco || !editorRef.current) {
4683
4710
  return;
@@ -4928,7 +4955,7 @@ var ListDisplay = ({ dataKey, type }) => {
4928
4955
  return /* @__PURE__ */ jsxs20("div", { className: "flex h-full flex-col gap-2", children: [
4929
4956
  /* @__PURE__ */ jsx30(DisplayHeader, { dataKey, type }),
4930
4957
  selectedListItem && /* @__PURE__ */ jsx30(ListEditDisplay, { dataKey, type, item: selectedListItem }),
4931
- /* @__PURE__ */ jsx30("div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ jsx30(InfiniteScroll, { query, children: /* @__PURE__ */ jsx30("div", { className: "pr-3", children: /* @__PURE__ */ jsx30("table", { className: "w-full", children: /* @__PURE__ */ jsx30("tbody", { children: /* @__PURE__ */ jsx30(ListItems, { dataKey, type, query }) }) }) }) }) })
4958
+ /* @__PURE__ */ jsx30("div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ jsx30(InfiniteScroll, { query, children: /* @__PURE__ */ jsx30("div", { className: "pr-3", children: /* @__PURE__ */ jsx30("table", { className: "w-full", children: /* @__PURE__ */ jsx30(ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ jsx30("tbody", { children: /* @__PURE__ */ jsx30(ListItems, { dataKey, type, query }) }) }) }) }) }) })
4932
4959
  ] });
4933
4960
  };
4934
4961
  var ListItems = ({
@@ -4939,68 +4966,61 @@ var ListItems = ({
4939
4966
  const { setSelectedListItem } = useDatabrowserStore();
4940
4967
  const keys = useMemo5(() => query.data?.pages.flatMap((page) => page.keys) ?? [], [query.data]);
4941
4968
  const { mutate: editItem } = useEditListItem();
4942
- return /* @__PURE__ */ jsx30(Fragment5, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ jsx30(
4943
- ItemContextMenu,
4969
+ return /* @__PURE__ */ jsx30(Fragment5, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ jsxs20(
4970
+ "tr",
4944
4971
  {
4945
- dataKey,
4946
- type,
4947
- itemKey: key,
4948
- itemValue: value,
4949
- children: /* @__PURE__ */ jsxs20(
4950
- "tr",
4951
- {
4952
- onClick: () => {
4953
- setSelectedListItem({ key, value });
4954
- },
4955
- className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
4956
- children: [
4957
- /* @__PURE__ */ jsx30(
4958
- "td",
4959
- {
4960
- className: cn(
4961
- "cursor-pointer truncate px-3",
4962
- type === "list" || type === "stream" ? "w-32 min-w-24" : "max-w-0"
4963
- ),
4964
- children: key
4965
- }
4966
- ),
4967
- value !== void 0 && /* @__PURE__ */ jsx30(
4968
- "td",
4969
- {
4970
- className: cn("cursor-pointer truncate px-3", type === "zset" ? "w-24" : "max-w-0"),
4971
- children: value
4972
- }
4972
+ "data-item-key": key,
4973
+ "data-item-value": value,
4974
+ onClick: () => {
4975
+ setSelectedListItem({ key, value });
4976
+ },
4977
+ className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
4978
+ children: [
4979
+ /* @__PURE__ */ jsx30(
4980
+ "td",
4981
+ {
4982
+ className: cn(
4983
+ "cursor-pointer truncate px-3",
4984
+ type === "list" || type === "stream" ? "w-32 min-w-24" : "max-w-0"
4973
4985
  ),
4974
- type !== "stream" && /* @__PURE__ */ jsx30(
4975
- "td",
4986
+ children: key
4987
+ }
4988
+ ),
4989
+ value !== void 0 && /* @__PURE__ */ jsx30(
4990
+ "td",
4991
+ {
4992
+ className: cn("cursor-pointer truncate px-3", type === "zset" ? "w-24" : "max-w-0"),
4993
+ children: value
4994
+ }
4995
+ ),
4996
+ type !== "stream" && /* @__PURE__ */ jsx30(
4997
+ "td",
4998
+ {
4999
+ width: 20,
5000
+ className: "px-3",
5001
+ onClick: (e) => {
5002
+ e.stopPropagation();
5003
+ },
5004
+ children: /* @__PURE__ */ jsx30(
5005
+ DeleteAlertDialog,
4976
5006
  {
4977
- width: 20,
4978
- className: "px-3",
4979
- onClick: (e) => {
5007
+ deletionType: "item",
5008
+ onDeleteConfirm: (e) => {
4980
5009
  e.stopPropagation();
5010
+ editItem({
5011
+ type,
5012
+ dataKey,
5013
+ itemKey: key,
5014
+ // For deletion
5015
+ newKey: void 0
5016
+ });
4981
5017
  },
4982
- children: /* @__PURE__ */ jsx30(
4983
- DeleteAlertDialog,
4984
- {
4985
- deletionType: "item",
4986
- onDeleteConfirm: (e) => {
4987
- e.stopPropagation();
4988
- editItem({
4989
- type,
4990
- dataKey,
4991
- itemKey: key,
4992
- // For deletion
4993
- newKey: void 0
4994
- });
4995
- },
4996
- children: /* @__PURE__ */ jsx30(Button, { size: "icon-sm", variant: "secondary", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx30(IconTrash, { className: "size-4 text-zinc-500" }) })
4997
- }
4998
- )
5018
+ children: /* @__PURE__ */ jsx30(Button, { size: "icon-sm", variant: "secondary", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx30(IconTrash, { className: "size-4 text-zinc-500" }) })
4999
5019
  }
5000
5020
  )
5001
- ]
5002
- }
5003
- )
5021
+ }
5022
+ )
5023
+ ]
5004
5024
  },
5005
5025
  `${dataKey}-${key}-${i}`
5006
5026
  )) });
@@ -5286,12 +5306,10 @@ var Empty = () => {
5286
5306
  import { useState as useState9 } from "react";
5287
5307
  import { ContextMenuSeparator as ContextMenuSeparator3 } from "@radix-ui/react-context-menu";
5288
5308
  import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
5289
- var SidebarContextMenu = ({
5290
- children,
5291
- dataKey
5292
- }) => {
5309
+ var SidebarContextMenu = ({ children }) => {
5293
5310
  const { mutate: deleteKey } = useDeleteKey();
5294
5311
  const [isAlertOpen, setAlertOpen] = useState9(false);
5312
+ const [dataKey, setDataKey] = useState9("");
5295
5313
  return /* @__PURE__ */ jsxs25(Fragment8, { children: [
5296
5314
  /* @__PURE__ */ jsx36(
5297
5315
  DeleteAlertDialog,
@@ -5307,7 +5325,21 @@ var SidebarContextMenu = ({
5307
5325
  }
5308
5326
  ),
5309
5327
  /* @__PURE__ */ jsxs25(ContextMenu, { children: [
5310
- /* @__PURE__ */ jsx36(ContextMenuTrigger, { asChild: true, children }),
5328
+ /* @__PURE__ */ jsx36(
5329
+ ContextMenuTrigger,
5330
+ {
5331
+ onContextMenu: (e) => {
5332
+ const el = e.target;
5333
+ const key = el.closest("[data-key]");
5334
+ if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
5335
+ setDataKey(key.dataset.key);
5336
+ } else {
5337
+ throw new Error("Key not found");
5338
+ }
5339
+ },
5340
+ children
5341
+ }
5342
+ ),
5311
5343
  /* @__PURE__ */ jsxs25(ContextMenuContent, { children: [
5312
5344
  /* @__PURE__ */ jsx36(
5313
5345
  ContextMenuItem,
@@ -5329,10 +5361,10 @@ var SidebarContextMenu = ({
5329
5361
  };
5330
5362
 
5331
5363
  // src/components/databrowser/components/sidebar/keys-list.tsx
5332
- import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
5364
+ import { Fragment as Fragment9, jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
5333
5365
  var KeysList = () => {
5334
5366
  const { keys } = useKeys();
5335
- return /* @__PURE__ */ jsx37("div", { className: "pr-3", children: keys.map((data, i) => /* @__PURE__ */ jsx37(KeyItem, { nextKey: keys.at(i + 1)?.[0] ?? "", data }, data[0])) });
5367
+ return /* @__PURE__ */ jsx37("div", { className: "pr-3", children: /* @__PURE__ */ jsx37(SidebarContextMenu, { children: /* @__PURE__ */ jsx37(Fragment9, { children: keys.map((data, i) => /* @__PURE__ */ jsx37(KeyItem, { nextKey: keys.at(i + 1)?.[0] ?? "", data }, data[0])) }) }) });
5336
5368
  };
5337
5369
  var keyStyles = {
5338
5370
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5348,7 +5380,7 @@ var KeyItem = ({ data, nextKey }) => {
5348
5380
  const [dataKey, dataType] = data;
5349
5381
  const isKeySelected = selectedKey === dataKey;
5350
5382
  const isNextKeySelected = selectedKey === nextKey;
5351
- return /* @__PURE__ */ jsx37(SidebarContextMenu, { dataKey, children: /* @__PURE__ */ jsxs26(
5383
+ return /* @__PURE__ */ jsxs26(
5352
5384
  Button,
5353
5385
  {
5354
5386
  "data-key": dataKey,
@@ -5366,7 +5398,7 @@ var KeyItem = ({ data, nextKey }) => {
5366
5398
  !isKeySelected && !isNextKeySelected && /* @__PURE__ */ jsx37("span", { className: "absolute -bottom-px left-3 right-3 h-px bg-zinc-100" })
5367
5399
  ]
5368
5400
  }
5369
- ) }, dataKey);
5401
+ );
5370
5402
  };
5371
5403
 
5372
5404
  // src/components/databrowser/components/sidebar/search-input.tsx
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@upstash/react-redis-browser", "version": "v0.1.2-canary-5", "main": "./dist/index.js", "types": "./dist/index.d.ts", "license": "MIT", "private": false, "publishConfig": { "access": "public" }, "bugs": { "url": "https://github.com/upstash/react-redis-browser/issues" }, "homepage": "https://github.com/upstash/react-redis-browser", "files": [ "./dist/**" ], "scripts": { "build": "tsup", "dev": "vite", "lint": "tsc && eslint", "fmt": "prettier --write ." }, "lint-staged": { "**/*.{js,ts,tsx}": [ "prettier --write", "eslint --fix" ] }, "dependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.4.0", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-context-menu": "^2.2.2", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "1.3.0", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "@tabler/icons-react": "^3.19.0", "@tanstack/react-query": "^5.32.0", "@types/bytes": "^3.1.4", "@upstash/redis": "^1.31.6", "bytes": "^3.1.2", "react-hook-form": "^7.53.0", "react-resizable-panels": "^2.1.4", "zustand": "5.0.0" }, "devDependencies": { "postcss-prefix-selector": "^2.1.0", "@types/node": "^22.8.4", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@vitejs/plugin-react": "^4.1.0", "autoprefixer": "^10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", "postcss": "^8.4.31", "prettier": "^3.0.3", "prettier-plugin-tailwindcss": "^0.5.5", "react": "^18.3.1", "react-dom": "^18.3.1", "tailwind-merge": "^2.5.4", "tailwindcss": "^3.4.14", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.5", "typescript": "^5.0.4", "vite": "^5.4.10", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { "react": "^18.2.0 || ^19", "react-dom": "^18.2.0 || ^19" } }
1
+ { "name": "@upstash/react-redis-browser", "version": "v0.1.2-canary-6", "main": "./dist/index.js", "types": "./dist/index.d.ts", "license": "MIT", "private": false, "publishConfig": { "access": "public" }, "bugs": { "url": "https://github.com/upstash/react-redis-browser/issues" }, "homepage": "https://github.com/upstash/react-redis-browser", "files": [ "./dist/**" ], "scripts": { "build": "tsup", "dev": "vite", "lint": "tsc && eslint", "fmt": "prettier --write ." }, "lint-staged": { "**/*.{js,ts,tsx}": [ "prettier --write", "eslint --fix" ] }, "dependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.4.0", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-context-menu": "^2.2.2", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "1.3.0", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "@tabler/icons-react": "^3.19.0", "@tanstack/react-query": "^5.32.0", "@types/bytes": "^3.1.4", "@upstash/redis": "^1.31.6", "bytes": "^3.1.2", "react-hook-form": "^7.53.0", "react-resizable-panels": "^2.1.4", "zustand": "5.0.0" }, "devDependencies": { "postcss-prefix-selector": "^2.1.0", "@types/node": "^22.8.4", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@vitejs/plugin-react": "^4.1.0", "autoprefixer": "^10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", "postcss": "^8.4.31", "prettier": "^3.0.3", "prettier-plugin-tailwindcss": "^0.5.5", "react": "^18.3.1", "react-dom": "^18.3.1", "tailwind-merge": "^2.5.4", "tailwindcss": "^3.4.14", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.5", "typescript": "^5.0.4", "vite": "^5.4.10", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { "react": "^18.2.0 || ^19", "react-dom": "^18.2.0 || ^19" } }