@upstash/react-redis-browser 0.2.8 → 0.2.10

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
@@ -260,18 +260,20 @@ var DatabrowserProvider = ({
260
260
  removeItem: () => {
261
261
  }
262
262
  },
263
- version: 2,
264
- // @ts-expect-error Reset the store for < v1
263
+ version: 4,
265
264
  migrate: (originalState, version) => {
266
265
  const state = originalState;
267
- if (version === 0) {
268
- return;
266
+ if (version <= 1) {
267
+ state.tabs = state.tabs.map(([id, data]) => [id, { ...data, id }]);
269
268
  }
270
- if (version === 1) {
271
- return {
272
- ...state,
273
- tabs: state.tabs.map(([id, data]) => [id, { ...data, id }])
274
- };
269
+ if (version <= 2) {
270
+ state.tabs = state.tabs.map(([id, data]) => {
271
+ const oldData = data;
272
+ return [
273
+ id,
274
+ { ...data, selectedKeys: oldData.selectedKey ? [oldData.selectedKey] : [] }
275
+ ];
276
+ });
275
277
  }
276
278
  return state;
277
279
  }
@@ -302,7 +304,7 @@ var storeCreator = (set, get) => ({
302
304
  const id = crypto.randomUUID();
303
305
  const newTabData = {
304
306
  id,
305
- selectedKey: void 0,
307
+ selectedKeys: [],
306
308
  search: { key: "", type: void 0 },
307
309
  pinned: false
308
310
  };
@@ -395,16 +397,19 @@ var storeCreator = (set, get) => ({
395
397
  selectTab: (id) => {
396
398
  set({ selectedTab: id });
397
399
  },
398
- getSelectedKey: (tabId) => {
399
- 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]);
400
+ getSelectedKeys: (tabId) => {
401
+ return _nullishCoalesce(_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.selectedKeys]), () => ( []));
400
402
  },
401
403
  setSelectedKey: (tabId, key) => {
404
+ get().setSelectedKeys(tabId, key ? [key] : []);
405
+ },
406
+ setSelectedKeys: (tabId, keys) => {
402
407
  set((old) => {
403
408
  const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
404
409
  if (tabIndex === -1) return old;
405
410
  const newTabs = [...old.tabs];
406
411
  const [, tabData] = newTabs[tabIndex];
407
- newTabs[tabIndex] = [tabId, { ...tabData, selectedKey: key, selectedListItem: void 0 }];
412
+ newTabs[tabIndex] = [tabId, { ...tabData, selectedKeys: keys, selectedListItem: void 0 }];
408
413
  return { ...old, tabs: newTabs };
409
414
  });
410
415
  },
@@ -485,6 +490,7 @@ var useTab = () => {
485
490
  selectedTab,
486
491
  tabs,
487
492
  setSelectedKey,
493
+ setSelectedKeys,
488
494
  setSelectedListItem,
489
495
  setSearch,
490
496
  setSearchKey,
@@ -497,11 +503,14 @@ var useTab = () => {
497
503
  return _react.useMemo.call(void 0,
498
504
  () => ({
499
505
  active: selectedTab === tabId,
500
- selectedKey: tabData.selectedKey,
506
+ selectedKey: tabData.selectedKeys[0],
507
+ // Backwards compatibility - first selected key
508
+ selectedKeys: tabData.selectedKeys,
501
509
  selectedListItem: tabData.selectedListItem,
502
510
  search: tabData.search,
503
511
  pinned: tabData.pinned,
504
512
  setSelectedKey: (key) => setSelectedKey(tabId, key),
513
+ setSelectedKeys: (keys) => setSelectedKeys(tabId, keys),
505
514
  setSelectedListItem: (item) => setSelectedListItem(tabId, item),
506
515
  setSearch: (search) => setSearch(tabId, search),
507
516
  setSearchKey: (key) => setSearchKey(tabId, key),
@@ -3836,8 +3845,8 @@ var HeaderTTLBadge = ({ dataKey }) => {
3836
3845
  }
3837
3846
  );
3838
3847
  };
3839
- var Badge = ({ children, label }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-6 items-center gap-0.5 rounded-md bg-white px-2 text-xs text-zinc-700", children: [
3840
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: label }),
3848
+ var Badge = ({ children, label }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-6 items-center gap-0.5 rounded-md bg-white px-2 text-xs text-zinc-700 dark:bg-zinc-200", children: [
3849
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500 dark:text-zinc-600", children: label }),
3841
3850
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children })
3842
3851
  ] });
3843
3852
 
@@ -4441,16 +4450,20 @@ function DeleteAlertDialog({
4441
4450
  onDeleteConfirm,
4442
4451
  open,
4443
4452
  onOpenChange,
4444
- deletionType
4453
+ deletionType,
4454
+ count: count2 = 1
4445
4455
  }) {
4456
+ const isPlural = count2 > 1;
4457
+ const itemLabel = deletionType === "item" ? "Item" : "Key";
4458
+ const itemsLabel = deletionType === "item" ? "Items" : "Keys";
4446
4459
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialog, { open, onOpenChange, children: [
4447
4460
  children && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTrigger, { asChild: true, children }),
4448
4461
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogContent, { children: [
4449
4462
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
4450
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: deletionType === "item" ? "Delete Item" : "Delete Key" }),
4463
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: isPlural ? `Delete ${count2} ${itemsLabel}` : `Delete ${itemLabel}` }),
4451
4464
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
4452
- "Are you sure you want to delete this ",
4453
- deletionType,
4465
+ "Are you sure you want to delete ",
4466
+ isPlural ? `these ${count2} ${deletionType}s` : `this ${deletionType}`,
4454
4467
  "?",
4455
4468
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
4456
4469
  "This action cannot be undone."
@@ -4696,6 +4709,36 @@ var InfiniteScroll = ({
4696
4709
  // src/components/databrowser/components/display/display-header.tsx
4697
4710
 
4698
4711
 
4712
+ // src/components/ui/tooltip.tsx
4713
+
4714
+
4715
+
4716
+ var Tooltip = TooltipPrimitive.Root;
4717
+ var TooltipTrigger = TooltipPrimitive.Trigger;
4718
+ var TooltipContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4719
+ TooltipPrimitive.Content,
4720
+ {
4721
+ ref,
4722
+ sideOffset,
4723
+ className: cn(
4724
+ "z-50 overflow-hidden rounded-md bg-zinc-900 px-3 py-1.5 text-xs text-zinc-50 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4725
+ className
4726
+ ),
4727
+ ...props
4728
+ }
4729
+ ) }));
4730
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
4731
+ var SimpleTooltip = ({
4732
+ content,
4733
+ children
4734
+ }) => {
4735
+ if (!content) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
4736
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 400, children: [
4737
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children }) }),
4738
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "top", children: content })
4739
+ ] });
4740
+ };
4741
+
4699
4742
  // src/types/index.ts
4700
4743
  var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
4701
4744
  var DATA_TYPE_NAMES = {
@@ -4762,7 +4805,7 @@ var _reactdropdownmenu = require('@radix-ui/react-dropdown-menu'); var DropdownM
4762
4805
 
4763
4806
  var DropdownMenu = DropdownMenuPrimitive.Root;
4764
4807
  var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
4765
- var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4808
+ var DropdownMenuSubTrigger = React11.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4766
4809
  DropdownMenuPrimitive.SubTrigger,
4767
4810
  {
4768
4811
  ref,
@@ -4779,7 +4822,7 @@ var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, .
4779
4822
  }
4780
4823
  ));
4781
4824
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
4782
- var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4825
+ var DropdownMenuSubContent = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4783
4826
  DropdownMenuPrimitive.SubContent,
4784
4827
  {
4785
4828
  ref,
@@ -4791,7 +4834,7 @@ var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) =
4791
4834
  }
4792
4835
  ));
4793
4836
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
4794
- var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4837
+ var DropdownMenuContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4795
4838
  DropdownMenuPrimitive.Content,
4796
4839
  {
4797
4840
  ref,
@@ -4805,12 +4848,12 @@ var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...pr
4805
4848
  }
4806
4849
  ) }));
4807
4850
  DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
4808
- var DropdownMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4851
+ var DropdownMenuItem = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4809
4852
  DropdownMenuPrimitive.Item,
4810
4853
  {
4811
4854
  ref,
4812
4855
  className: cn(
4813
- "data-[disabled]:opacity-50[&>svg]:size-4 relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none [&>svg]:shrink-0",
4856
+ "data-[disabled]:opacity-50[&>svg]:size-4 relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none [&>svg]:shrink-0",
4814
4857
  inset && "pl-8",
4815
4858
  className
4816
4859
  ),
@@ -4818,7 +4861,7 @@ var DropdownMenuItem = React10.forwardRef(({ className, inset, ...props }, ref)
4818
4861
  }
4819
4862
  ));
4820
4863
  DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
4821
- var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4864
+ var DropdownMenuCheckboxItem = React11.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4822
4865
  DropdownMenuPrimitive.CheckboxItem,
4823
4866
  {
4824
4867
  ref,
@@ -4835,7 +4878,7 @@ var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checke
4835
4878
  }
4836
4879
  ));
4837
4880
  DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
4838
- var DropdownMenuRadioItem = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4881
+ var DropdownMenuRadioItem = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4839
4882
  DropdownMenuPrimitive.RadioItem,
4840
4883
  {
4841
4884
  ref,
@@ -4851,7 +4894,7 @@ var DropdownMenuRadioItem = React10.forwardRef(({ className, children, ...props
4851
4894
  }
4852
4895
  ));
4853
4896
  DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
4854
- var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4897
+ var DropdownMenuLabel = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4855
4898
  DropdownMenuPrimitive.Label,
4856
4899
  {
4857
4900
  ref,
@@ -4860,7 +4903,7 @@ var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref)
4860
4903
  }
4861
4904
  ));
4862
4905
  DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
4863
- var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4906
+ var DropdownMenuSeparator = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4864
4907
  DropdownMenuPrimitive.Separator,
4865
4908
  {
4866
4909
  ref,
@@ -4879,7 +4922,7 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4879
4922
  function KeyActions({ dataKey, content }) {
4880
4923
  const { mutateAsync: deleteKey } = useDeleteKey();
4881
4924
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { modal: false, children: [
4882
- /* @__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" }) }) }),
4925
+ /* @__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 dark:text-zinc-600" }) }) }),
4883
4926
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { className: "", align: "end", children: [
4884
4927
  content && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4885
4928
  DropdownMenuItem,
@@ -4936,7 +4979,7 @@ var DisplayHeader = ({
4936
4979
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4937
4980
  /* @__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 }) }),
4938
4981
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
4939
- 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" }) }),
4982
+ type !== "string" && type !== "json" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add item", children: /* @__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 dark:text-zinc-600" }) }) }),
4940
4983
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content })
4941
4984
  ] })
4942
4985
  ] }),
@@ -4952,36 +4995,6 @@ var DisplayHeader = ({
4952
4995
  // src/components/databrowser/components/display/display-list-edit.tsx
4953
4996
 
4954
4997
 
4955
- // src/components/ui/tooltip.tsx
4956
-
4957
-
4958
-
4959
- var Tooltip = TooltipPrimitive.Root;
4960
- var TooltipTrigger = TooltipPrimitive.Trigger;
4961
- 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,
4962
- TooltipPrimitive.Content,
4963
- {
4964
- ref,
4965
- sideOffset,
4966
- className: cn(
4967
- "z-50 overflow-hidden rounded-md bg-zinc-900 px-3 py-1.5 text-xs text-zinc-50 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4968
- className
4969
- ),
4970
- ...props
4971
- }
4972
- ) }));
4973
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
4974
- var SimpleTooltip = ({
4975
- content,
4976
- children
4977
- }) => {
4978
- if (!content) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
4979
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 400, children: [
4980
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children }) }),
4981
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "top", children: content })
4982
- ] });
4983
- };
4984
-
4985
4998
  // src/components/databrowser/hooks/use-fetch-hash-ttl.ts
4986
4999
 
4987
5000
  var FETCH_HASH_FIELD_TTLS_QUERY_KEY = "fetch-hash-field-ttls";
@@ -5473,7 +5486,9 @@ var ListItems = ({
5473
5486
  onClick: () => {
5474
5487
  setSelectedListItem({ key });
5475
5488
  },
5476
- className: cn("h-10 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100"),
5489
+ className: cn(
5490
+ "h-10 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100 dark:border-b-zinc-200 dark:hover:bg-zinc-200"
5491
+ ),
5477
5492
  children: [
5478
5493
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5479
5494
  "td",
@@ -5495,7 +5510,7 @@ var ListItems = ({
5495
5510
  type !== "stream" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5496
5511
  "td",
5497
5512
  {
5498
- className: "w-0 min-w-0 p-0",
5513
+ className: "w-0 min-w-0 p-0 pr-2",
5499
5514
  onClick: (e) => {
5500
5515
  e.stopPropagation();
5501
5516
  },
@@ -5594,9 +5609,6 @@ var DataDisplay = () => {
5594
5609
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full p-4", children: !selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : !type ? query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "Loading..." }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: type === "string" || type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5595
5610
  };
5596
5611
 
5597
- // src/components/databrowser/components/sidebar/index.tsx
5598
-
5599
-
5600
5612
  // src/components/databrowser/components/add-key-modal.tsx
5601
5613
 
5602
5614
  var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
@@ -5737,7 +5749,7 @@ function AddKeyModal() {
5737
5749
  setOpen(open2);
5738
5750
  },
5739
5751
  children: [
5740
- /* @__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" }) }) }),
5752
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add key", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", size: "icon-sm", "data-testid": "add-key-button", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.PlusIcon, { className: "size-4" }) }) }) }),
5741
5753
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-[400px]", children: [
5742
5754
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new key" }) }),
5743
5755
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactdialog.DialogDescription, { children: "Create new key" }) }),
@@ -5798,6 +5810,9 @@ var Empty = () => {
5798
5810
  ] }) });
5799
5811
  };
5800
5812
 
5813
+ // src/components/databrowser/components/sidebar/keys-list.tsx
5814
+
5815
+
5801
5816
  // src/components/databrowser/components/sidebar-context-menu.tsx
5802
5817
 
5803
5818
 
@@ -5806,19 +5821,22 @@ var Empty = () => {
5806
5821
  var SidebarContextMenu = ({ children }) => {
5807
5822
  const { mutate: deleteKey } = useDeleteKey();
5808
5823
  const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
5809
- const [dataKey, setDataKey] = _react.useState.call(void 0, "");
5810
- const { addTab, setSelectedKey, selectTab, setSearch } = useDatabrowserStore();
5811
- const { search: currentSearch } = useTab();
5824
+ const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
5825
+ const { addTab, setSelectedKey: setSelectedKeyGlobal, selectTab, setSearch } = useDatabrowserStore();
5826
+ const { search: currentSearch, selectedKeys, setSelectedKey } = useTab();
5812
5827
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5813
5828
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5814
5829
  DeleteAlertDialog,
5815
5830
  {
5816
5831
  deletionType: "key",
5832
+ count: contextKeys.length,
5817
5833
  open: isAlertOpen,
5818
5834
  onOpenChange: setAlertOpen,
5819
5835
  onDeleteConfirm: (e) => {
5820
5836
  e.stopPropagation();
5821
- deleteKey(dataKey);
5837
+ for (const key of contextKeys) {
5838
+ deleteKey(key);
5839
+ }
5822
5840
  setAlertOpen(false);
5823
5841
  }
5824
5842
  }
@@ -5831,7 +5849,13 @@ var SidebarContextMenu = ({ children }) => {
5831
5849
  const el = e.target;
5832
5850
  const key = el.closest("[data-key]");
5833
5851
  if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
5834
- setDataKey(key.dataset.key);
5852
+ const clickedKey = key.dataset.key;
5853
+ if (selectedKeys.includes(clickedKey)) {
5854
+ setContextKeys(selectedKeys);
5855
+ } else {
5856
+ setSelectedKey(clickedKey);
5857
+ setContextKeys([clickedKey]);
5858
+ }
5835
5859
  } else {
5836
5860
  throw new Error("Key not found");
5837
5861
  }
@@ -5844,12 +5868,13 @@ var SidebarContextMenu = ({ children }) => {
5844
5868
  ContextMenuItem,
5845
5869
  {
5846
5870
  onClick: () => {
5847
- navigator.clipboard.writeText(dataKey);
5871
+ navigator.clipboard.writeText(contextKeys[0]);
5848
5872
  toast({
5849
5873
  description: "Key copied to clipboard"
5850
5874
  });
5851
5875
  },
5852
5876
  className: "gap-2",
5877
+ disabled: contextKeys.length !== 1,
5853
5878
  children: [
5854
5879
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCopy, { size: 16 }),
5855
5880
  "Copy key"
@@ -5861,11 +5886,12 @@ var SidebarContextMenu = ({ children }) => {
5861
5886
  {
5862
5887
  onClick: () => {
5863
5888
  const newTabId = addTab();
5864
- setSelectedKey(newTabId, dataKey);
5889
+ setSelectedKeyGlobal(newTabId, contextKeys[0]);
5865
5890
  setSearch(newTabId, currentSearch);
5866
5891
  selectTab(newTabId);
5867
5892
  },
5868
5893
  className: "gap-2",
5894
+ disabled: contextKeys.length !== 1,
5869
5895
  children: [
5870
5896
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 16 }),
5871
5897
  "Open in new tab"
@@ -5875,7 +5901,7 @@ var SidebarContextMenu = ({ children }) => {
5875
5901
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
5876
5902
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuItem, { onClick: () => setAlertOpen(true), className: "gap-2", children: [
5877
5903
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { size: 16 }),
5878
- "Delete key"
5904
+ contextKeys.length > 1 ? `Delete ${contextKeys.length} keys` : "Delete key"
5879
5905
  ] })
5880
5906
  ] })
5881
5907
  ] })
@@ -5886,7 +5912,23 @@ var SidebarContextMenu = ({ children }) => {
5886
5912
 
5887
5913
  var KeysList = () => {
5888
5914
  const { keys } = useKeys();
5889
- 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])) }) });
5915
+ const lastClickedIndexRef = _react.useRef.call(void 0, null);
5916
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5917
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px" }),
5918
+ keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5919
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5920
+ KeyItem,
5921
+ {
5922
+ index: i,
5923
+ data,
5924
+ allKeys: keys,
5925
+ lastClickedIndexRef
5926
+ },
5927
+ data[0]
5928
+ ),
5929
+ i !== keys.length - 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "-z-10 mx-2 h-px bg-zinc-100 dark:bg-zinc-200" })
5930
+ ] }))
5931
+ ] }) });
5890
5932
  };
5891
5933
  var keyStyles = {
5892
5934
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5897,11 +5939,33 @@ var keyStyles = {
5897
5939
  list: "border-orange-400 !bg-orange-50 text-orange-900",
5898
5940
  stream: "border-green-400 !bg-green-50 text-green-900"
5899
5941
  };
5900
- var KeyItem = ({ data, nextKey }) => {
5901
- const { selectedKey, setSelectedKey } = useTab();
5942
+ var KeyItem = ({
5943
+ data,
5944
+ index,
5945
+ allKeys,
5946
+ lastClickedIndexRef
5947
+ }) => {
5948
+ const { selectedKeys, setSelectedKeys, setSelectedKey } = useTab();
5902
5949
  const [dataKey, dataType] = data;
5903
- const isKeySelected = selectedKey === dataKey;
5904
- const isNextKeySelected = selectedKey === nextKey;
5950
+ const isKeySelected = selectedKeys.includes(dataKey);
5951
+ const handleClick = (e) => {
5952
+ if (e.shiftKey && lastClickedIndexRef.current !== null) {
5953
+ const start = Math.min(lastClickedIndexRef.current, index);
5954
+ const end = Math.max(lastClickedIndexRef.current, index);
5955
+ const rangeKeys = allKeys.slice(start, end + 1).map(([key]) => key);
5956
+ setSelectedKeys(rangeKeys);
5957
+ } else if (e.metaKey || e.ctrlKey) {
5958
+ if (isKeySelected) {
5959
+ setSelectedKeys(selectedKeys.filter((k) => k !== dataKey));
5960
+ } else {
5961
+ setSelectedKeys([...selectedKeys, dataKey]);
5962
+ }
5963
+ lastClickedIndexRef.current = index;
5964
+ } else {
5965
+ setSelectedKey(dataKey);
5966
+ lastClickedIndexRef.current = index;
5967
+ }
5968
+ };
5905
5969
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5906
5970
  Button,
5907
5971
  {
@@ -5909,20 +5973,47 @@ var KeyItem = ({ data, nextKey }) => {
5909
5973
  variant: isKeySelected ? "default" : "ghost",
5910
5974
  className: cn(
5911
5975
  "relative flex h-10 w-full items-center justify-start gap-2 px-3 py-0 !ring-0 focus-visible:bg-zinc-50",
5912
- "select-none border border-transparent text-left",
5976
+ "-my-px select-none border border-transparent text-left",
5913
5977
  isKeySelected && "shadow-sm",
5914
5978
  isKeySelected && keyStyles[dataType]
5915
5979
  ),
5916
- onClick: () => setSelectedKey(dataKey),
5980
+ onClick: handleClick,
5917
5981
  children: [
5918
5982
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: dataType, type: "icon" }),
5919
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "truncate whitespace-nowrap", children: dataKey }),
5920
- !isKeySelected && !isNextKeySelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute -bottom-px left-3 right-3 h-px bg-zinc-100" })
5983
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "truncate whitespace-nowrap", children: dataKey })
5921
5984
  ]
5922
5985
  }
5923
5986
  );
5924
5987
  };
5925
5988
 
5989
+ // src/components/databrowser/components/sidebar/reload-button.tsx
5990
+
5991
+
5992
+
5993
+ var ReloadButton = ({
5994
+ onClick,
5995
+ isLoading: isLoadingProp
5996
+ }) => {
5997
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
5998
+ const handleClick = () => {
5999
+ setIsLoading(true);
6000
+ onClick();
6001
+ setTimeout(() => {
6002
+ setIsLoading(false);
6003
+ }, 350);
6004
+ };
6005
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Refresh", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6006
+ Button,
6007
+ {
6008
+ variant: "outline",
6009
+ size: "icon-sm",
6010
+ onClick: handleClick,
6011
+ disabled: isLoading || isLoadingProp,
6012
+ children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "animate-spin text-zinc-500", size: 16 }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { className: "text-zinc-500 dark:text-zinc-600", size: 16 })
6013
+ }
6014
+ ) }) });
6015
+ };
6016
+
5926
6017
  // src/components/databrowser/components/sidebar/search-input.tsx
5927
6018
 
5928
6019
 
@@ -5962,7 +6053,7 @@ var SearchInput = () => {
5962
6053
  } else if (e.key === "Escape") {
5963
6054
  setState("");
5964
6055
  setFocusedIndex(-1);
5965
- _optionalChain([inputRef, 'access', _56 => _56.current, 'optionalAccess', _57 => _57.blur, 'call', _58 => _58()]);
6056
+ _optionalChain([inputRef, 'access', _53 => _53.current, 'optionalAccess', _54 => _54.blur, 'call', _55 => _55()]);
5966
6057
  } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
5967
6058
  e.preventDefault();
5968
6059
  if (focusedIndex < filteredHistory.length - 1) {
@@ -5976,7 +6067,7 @@ var SearchInput = () => {
5976
6067
  setFocusedIndex(focusedIndex - 1);
5977
6068
  } else if (filteredHistory.length > 0 && focusedIndex === 0) {
5978
6069
  setFocusedIndex(-1);
5979
- _optionalChain([inputRef, 'access', _59 => _59.current, 'optionalAccess', _60 => _60.focus, 'call', _61 => _61()]);
6070
+ _optionalChain([inputRef, 'access', _56 => _56.current, 'optionalAccess', _57 => _57.focus, 'call', _58 => _58()]);
5980
6071
  } else if (filteredHistory.length > 0) {
5981
6072
  setFocusedIndex(filteredHistory.length - 1);
5982
6073
  }
@@ -5984,12 +6075,12 @@ var SearchInput = () => {
5984
6075
  };
5985
6076
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
5986
6077
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
5987
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6078
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 rounded-md rounded-l-none border border-zinc-300 font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5988
6079
  Input,
5989
6080
  {
5990
6081
  ref: inputRef,
5991
6082
  placeholder: "Search",
5992
- className: "rounded-l-none border-zinc-300 font-normal",
6083
+ className: "h-full rounded-l-none border-none pr-6",
5993
6084
  onKeyDown: handleKeyDown,
5994
6085
  onChange: (e) => {
5995
6086
  setState(e.currentTarget.value);
@@ -6092,10 +6183,8 @@ function Sidebar() {
6092
6183
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayDbSize, {}),
6093
6184
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-1", children: [
6094
6185
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6095
- Button,
6186
+ ReloadButton,
6096
6187
  {
6097
- "aria-label": "Refresh",
6098
- className: "h-7 w-7 px-0 text-zinc-500",
6099
6188
  onClick: () => {
6100
6189
  queryClient.invalidateQueries({
6101
6190
  queryKey: [FETCH_KEYS_QUERY_KEY]
@@ -6113,7 +6202,7 @@ function Sidebar() {
6113
6202
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
6114
6203
  });
6115
6204
  },
6116
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: query.isFetching, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { size: 16 }) })
6205
+ isLoading: query.isFetching
6117
6206
  }
6118
6207
  ),
6119
6208
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
@@ -6279,7 +6368,7 @@ var useOverflow = () => {
6279
6368
  }
6280
6369
  if (!node) return;
6281
6370
  observerRef.current = new ResizeObserver((entries) => {
6282
- const el = _optionalChain([entries, 'access', _62 => _62.at, 'call', _63 => _63(0), 'optionalAccess', _64 => _64.target]);
6371
+ const el = _optionalChain([entries, 'access', _59 => _59.at, 'call', _60 => _60(0), 'optionalAccess', _61 => _61.target]);
6283
6372
  if (!el) return;
6284
6373
  setIsOverflow(el.scrollWidth > el.clientWidth);
6285
6374
  });
@@ -6287,7 +6376,7 @@ var useOverflow = () => {
6287
6376
  }, []);
6288
6377
  _react.useEffect.call(void 0, () => {
6289
6378
  return () => {
6290
- _optionalChain([observerRef, 'access', _65 => _65.current, 'optionalAccess', _66 => _66.disconnect, 'call', _67 => _67()]);
6379
+ _optionalChain([observerRef, 'access', _62 => _62.current, 'optionalAccess', _63 => _63.disconnect, 'call', _64 => _64()]);
6291
6380
  };
6292
6381
  }, []);
6293
6382
  return { ref, isOverflow };
@@ -6340,7 +6429,7 @@ var Tab = ({ id, isList }) => {
6340
6429
  e.stopPropagation();
6341
6430
  removeTab(id);
6342
6431
  },
6343
- className: "p-1 text-zinc-300 transition-colors hover:text-zinc-500",
6432
+ className: "p-1 text-zinc-300 transition-colors hover:text-zinc-500 dark:text-zinc-400",
6344
6433
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
6345
6434
  }
6346
6435
  )
@@ -6397,8 +6486,8 @@ var SortableTab = ({ id }) => {
6397
6486
  const [originalWidth, setOriginalWidth] = _react.useState.call(void 0, null);
6398
6487
  const textRef = _react.useRef.call(void 0, null);
6399
6488
  const { tabs } = useDatabrowserStore();
6400
- const tabData = _optionalChain([tabs, 'access', _68 => _68.find, 'call', _69 => _69(([tabId]) => tabId === id), 'optionalAccess', _70 => _70[1]]);
6401
- const isPinned = _optionalChain([tabData, 'optionalAccess', _71 => _71.pinned]);
6489
+ const tabData = _optionalChain([tabs, 'access', _65 => _65.find, 'call', _66 => _66(([tabId]) => tabId === id), 'optionalAccess', _67 => _67[1]]);
6490
+ const isPinned = _optionalChain([tabData, 'optionalAccess', _68 => _68.pinned]);
6402
6491
  const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = _sortable.useSortable.call(void 0, {
6403
6492
  id,
6404
6493
  disabled: isPinned,
@@ -6618,7 +6707,7 @@ function AddTabButton() {
6618
6707
  const tabsId = addTab();
6619
6708
  selectTab(tabsId);
6620
6709
  setTimeout(() => {
6621
- const tab = _optionalChain([rootRef, 'optionalAccess', _72 => _72.current, 'optionalAccess', _73 => _73.querySelector, 'call', _74 => _74(`#tab-${tabsId}`)]);
6710
+ const tab = _optionalChain([rootRef, 'optionalAccess', _69 => _69.current, 'optionalAccess', _70 => _70.querySelector, 'call', _71 => _71(`#tab-${tabsId}`)]);
6622
6711
  if (!tab) return;
6623
6712
  tab.scrollIntoView({ behavior: "smooth" });
6624
6713
  }, 20);
@@ -6630,8 +6719,8 @@ function AddTabButton() {
6630
6719
  variant: "secondary",
6631
6720
  size: "icon-sm",
6632
6721
  onClick: handleAddTab,
6633
- className: "flex-shrink-0",
6634
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-500", size: 16 })
6722
+ className: "flex-shrink-0 dark:bg-zinc-200",
6723
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-500 dark:text-zinc-600", size: 16 })
6635
6724
  }
6636
6725
  );
6637
6726
  }
@@ -6652,7 +6741,7 @@ function TabsListButton({
6652
6741
  onSelectTab(id);
6653
6742
  setOpen(false);
6654
6743
  setTimeout(() => {
6655
- const tab = _optionalChain([rootRef, 'optionalAccess', _75 => _75.current, 'optionalAccess', _76 => _76.querySelector, 'call', _77 => _77(`#tab-${id}`)]);
6744
+ const tab = _optionalChain([rootRef, 'optionalAccess', _72 => _72.current, 'optionalAccess', _73 => _73.querySelector, 'call', _74 => _74(`#tab-${id}`)]);
6656
6745
  if (!tab) return;
6657
6746
  tab.scrollIntoView({ behavior: "smooth" });
6658
6747
  }, 20);