@upstash/react-redis-browser 0.1.6 → 0.1.7

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
@@ -2808,7 +2808,7 @@ function formatTime(seconds) {
2808
2808
  if (parts.length === 0) {
2809
2809
  parts.push("0s");
2810
2810
  }
2811
- return parts.slice(0, 2).join(" ");
2811
+ return parts.slice(0, 1).join(" ");
2812
2812
  }
2813
2813
 
2814
2814
  // src/components/ui/toast.tsx
@@ -2923,6 +2923,20 @@ function Toaster() {
2923
2923
 
2924
2924
 
2925
2925
 
2926
+ // src/components/databrowser/hooks/use-fetch-key-type.tsx
2927
+
2928
+ var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
2929
+ var useFetchKeyType = (key) => {
2930
+ const { redisNoPipeline: redis } = useDatabrowser();
2931
+ return _reactquery.useQuery.call(void 0, {
2932
+ queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key],
2933
+ queryFn: async () => {
2934
+ if (!key) return "none";
2935
+ return await redis.type(key);
2936
+ }
2937
+ });
2938
+ };
2939
+
2926
2940
  // src/components/databrowser/hooks/use-fetch-keys.ts
2927
2941
 
2928
2942
 
@@ -3050,6 +3064,8 @@ var KeysContext = _react.createContext.call(void 0, void 0);
3050
3064
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
3051
3065
  var KeysProvider = ({ children }) => {
3052
3066
  const { search } = useDatabrowserStore();
3067
+ const cleanSearchKey = search.key.replace("*", "");
3068
+ const { data: exactMatchType } = useFetchKeyType(cleanSearchKey);
3053
3069
  const { fetchKeys, resetCache } = useFetchKeys(search);
3054
3070
  const pageRef = _react.useRef.call(void 0, 0);
3055
3071
  const query = _reactquery.useInfiniteQuery.call(void 0, {
@@ -3072,6 +3088,9 @@ var KeysProvider = ({ children }) => {
3072
3088
  }, [query, resetCache]);
3073
3089
  const keys = _react.useMemo.call(void 0, () => {
3074
3090
  const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.pages, 'access', _12 => _12.flatMap, 'call', _13 => _13((page) => page.keys)]), () => ( []));
3091
+ if (exactMatchType && exactMatchType !== "none" && (search.type === void 0 || search.type === exactMatchType)) {
3092
+ keys2.push([cleanSearchKey, exactMatchType]);
3093
+ }
3075
3094
  const keysSet = /* @__PURE__ */ new Set();
3076
3095
  const dedupedKeys = [];
3077
3096
  for (const key of keys2) {
@@ -3080,7 +3099,7 @@ var KeysProvider = ({ children }) => {
3080
3099
  dedupedKeys.push(key);
3081
3100
  }
3082
3101
  return dedupedKeys;
3083
- }, [query.data]);
3102
+ }, [query.data, cleanSearchKey, exactMatchType]);
3084
3103
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3085
3104
  KeysContext.Provider,
3086
3105
  {
@@ -3270,76 +3289,6 @@ var useAddKey = () => {
3270
3289
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3271
3290
 
3272
3291
 
3273
- // src/components/databrowser/hooks/use-fetch-simple-key.tsx
3274
-
3275
- var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
3276
- var useFetchSimpleKey = (dataKey, type) => {
3277
- const { redisNoPipeline: redis } = useDatabrowser();
3278
- const { deleteKeyCache } = useDeleteKeyCache();
3279
- return _reactquery.useQuery.call(void 0, {
3280
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
3281
- queryFn: async () => {
3282
- let result;
3283
- if (type === "string") result = await redis.get(dataKey);
3284
- else if (type === "json") result = await redis.json.get(dataKey);
3285
- else throw new Error(`Invalid type when fetching simple key: ${type}`);
3286
- if (type === "json" && result !== null)
3287
- result = JSON.stringify(sortObject(JSON.parse(result)));
3288
- if (result === null) deleteKeyCache(dataKey);
3289
- return result;
3290
- }
3291
- });
3292
- };
3293
- var sortObject = (obj) => {
3294
- if (typeof obj !== "object" || obj === null) return obj;
3295
- return Object.fromEntries(
3296
- Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])).map(
3297
- ([key, value]) => typeof value === "object" && !Array.isArray(value) && value !== null ? [key, sortObject(value)] : [key, value]
3298
- )
3299
- );
3300
- };
3301
-
3302
- // src/components/databrowser/hooks/use-delete-key-cache.ts
3303
- var useDeleteKeyCache = () => {
3304
- const { setSelectedKey } = useDatabrowserStore();
3305
- const { refetch } = useKeys();
3306
- const deleteKeyCache = _react.useCallback.call(void 0,
3307
- (key) => {
3308
- setSelectedKey(void 0);
3309
- queryClient.invalidateQueries({
3310
- queryKey: [FETCH_KEYS_QUERY_KEY]
3311
- });
3312
- queryClient.invalidateQueries({
3313
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, key]
3314
- });
3315
- refetch();
3316
- },
3317
- [setSelectedKey, refetch]
3318
- );
3319
- return { deleteKeyCache };
3320
- };
3321
-
3322
- // src/components/databrowser/hooks/use-delete-key.ts
3323
- var useDeleteKey = () => {
3324
- const { redis } = useDatabrowser();
3325
- const { deleteKeyCache } = useDeleteKeyCache();
3326
- const deleteKey = _reactquery.useMutation.call(void 0, {
3327
- mutationFn: async (key) => {
3328
- return Boolean(await redis.del(key));
3329
- },
3330
- onSuccess: (_, key) => {
3331
- deleteKeyCache(key);
3332
- queryClient.invalidateQueries({
3333
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3334
- });
3335
- }
3336
- });
3337
- return deleteKey;
3338
- };
3339
-
3340
- // src/components/databrowser/hooks/use-edit-list-item.tsx
3341
-
3342
-
3343
3292
  // src/components/databrowser/hooks/use-fetch-list-items.tsx
3344
3293
 
3345
3294
  var LIST_DISPLAY_PAGE_SIZE = 50;
@@ -3365,13 +3314,15 @@ var useFetchListItems = ({ dataKey, type }) => {
3365
3314
  enabled: type === "zset",
3366
3315
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "zset"],
3367
3316
  initialPageParam: 0,
3368
- queryFn: async ({ pageParam: lastIndex }) => {
3369
- const res = await redis.zrange(dataKey, lastIndex, lastIndex + LIST_DISPLAY_PAGE_SIZE - 1, {
3317
+ queryFn: async ({ pageParam: page }) => {
3318
+ const start = page * LIST_DISPLAY_PAGE_SIZE;
3319
+ const end = start + LIST_DISPLAY_PAGE_SIZE - 1;
3320
+ const res = await redis.zrange(dataKey, start, end, {
3370
3321
  withScores: true,
3371
3322
  rev: true
3372
3323
  });
3373
3324
  return {
3374
- cursor: res.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastIndex + LIST_DISPLAY_PAGE_SIZE,
3325
+ cursor: res.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : page + 1,
3375
3326
  keys: transformArray(res)
3376
3327
  };
3377
3328
  },
@@ -3396,13 +3347,14 @@ var useFetchListItems = ({ dataKey, type }) => {
3396
3347
  enabled: type === "list",
3397
3348
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "list"],
3398
3349
  initialPageParam: 0,
3399
- queryFn: async ({ pageParam }) => {
3400
- const lastIndex = Number(pageParam);
3401
- const values = await redis.lrange(dataKey, lastIndex, lastIndex + LIST_DISPLAY_PAGE_SIZE);
3350
+ queryFn: async ({ pageParam: page }) => {
3351
+ const start = page * LIST_DISPLAY_PAGE_SIZE;
3352
+ const end = start + LIST_DISPLAY_PAGE_SIZE - 1;
3353
+ const values = await redis.lrange(dataKey, start, end);
3402
3354
  return {
3403
- cursor: values.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastIndex + LIST_DISPLAY_PAGE_SIZE,
3355
+ cursor: values.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : page + 1,
3404
3356
  keys: values.map((value, i) => ({
3405
- key: (lastIndex + i).toString(),
3357
+ key: (start + i).toString(),
3406
3358
  value
3407
3359
  }))
3408
3360
  };
@@ -3453,7 +3405,81 @@ function transformArray(inputArray) {
3453
3405
  }, []);
3454
3406
  }
3455
3407
 
3408
+ // src/components/databrowser/hooks/use-fetch-simple-key.tsx
3409
+
3410
+ var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
3411
+ var useFetchSimpleKey = (dataKey, type) => {
3412
+ const { redisNoPipeline: redis } = useDatabrowser();
3413
+ const { deleteKeyCache } = useDeleteKeyCache();
3414
+ return _reactquery.useQuery.call(void 0, {
3415
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
3416
+ queryFn: async () => {
3417
+ let result;
3418
+ if (type === "string") result = await redis.get(dataKey);
3419
+ else if (type === "json") result = await redis.json.get(dataKey);
3420
+ else throw new Error(`Invalid type when fetching simple key: ${type}`);
3421
+ if (type === "json" && result !== null)
3422
+ result = JSON.stringify(sortObject(JSON.parse(result)));
3423
+ if (result === null) deleteKeyCache(dataKey);
3424
+ return result;
3425
+ }
3426
+ });
3427
+ };
3428
+ var sortObject = (obj) => {
3429
+ if (typeof obj !== "object" || obj === null) return obj;
3430
+ return Object.fromEntries(
3431
+ Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])).map(
3432
+ ([key, value]) => typeof value === "object" && !Array.isArray(value) && value !== null ? [key, sortObject(value)] : [key, value]
3433
+ )
3434
+ );
3435
+ };
3436
+
3437
+ // src/components/databrowser/hooks/use-delete-key-cache.ts
3438
+ var useDeleteKeyCache = () => {
3439
+ const { setSelectedKey } = useDatabrowserStore();
3440
+ const { refetch } = useKeys();
3441
+ const deleteKeyCache = _react.useCallback.call(void 0,
3442
+ (key) => {
3443
+ setSelectedKey(void 0);
3444
+ queryClient.invalidateQueries({
3445
+ queryKey: [FETCH_KEYS_QUERY_KEY]
3446
+ });
3447
+ queryClient.invalidateQueries({
3448
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, key]
3449
+ });
3450
+ queryClient.invalidateQueries({
3451
+ queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, key]
3452
+ });
3453
+ queryClient.invalidateQueries({
3454
+ queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key]
3455
+ });
3456
+ refetch();
3457
+ },
3458
+ [setSelectedKey, refetch]
3459
+ );
3460
+ return { deleteKeyCache };
3461
+ };
3462
+
3463
+ // src/components/databrowser/hooks/use-delete-key.ts
3464
+ var useDeleteKey = () => {
3465
+ const { redis } = useDatabrowser();
3466
+ const { deleteKeyCache } = useDeleteKeyCache();
3467
+ const deleteKey = _reactquery.useMutation.call(void 0, {
3468
+ mutationFn: async (key) => {
3469
+ return Boolean(await redis.del(key));
3470
+ },
3471
+ onSuccess: (_, key) => {
3472
+ deleteKeyCache(key);
3473
+ queryClient.invalidateQueries({
3474
+ queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3475
+ });
3476
+ }
3477
+ });
3478
+ return deleteKey;
3479
+ };
3480
+
3456
3481
  // src/components/databrowser/hooks/use-edit-list-item.tsx
3482
+
3457
3483
  var useEditListItem = () => {
3458
3484
  const { redis } = useDatabrowser();
3459
3485
  return _reactquery.useMutation.call(void 0, {
@@ -3536,912 +3562,938 @@ var useEditListItem = () => {
3536
3562
  // src/components/databrowser/hooks/use-fetch-ttl.ts
3537
3563
 
3538
3564
 
3539
- var FETCH_TTL_QUERY_KEY = "fetch-ttl";
3540
- var useFetchTTL = (dataKey) => {
3565
+
3566
+ // src/components/databrowser/components/display/ttl-badge.tsx
3567
+
3568
+
3569
+
3570
+ // src/components/databrowser/components/display/header-badges.tsx
3571
+ var _bytes = require('bytes'); var _bytes2 = _interopRequireDefault(_bytes);
3572
+
3573
+ // src/components/databrowser/hooks/use-fetch-key-length.ts
3574
+
3575
+ var FETCH_KEY_LENGTH_QUERY_KEY = "fetch-key-length";
3576
+ var useFetchKeyLength = ({ dataKey, type }) => {
3541
3577
  const { redis } = useDatabrowser();
3542
- const { isLoading, error, data } = _reactquery.useQuery.call(void 0, {
3543
- queryKey: [FETCH_TTL_QUERY_KEY, dataKey],
3578
+ return _reactquery.useQuery.call(void 0, {
3579
+ queryKey: [FETCH_KEY_LENGTH_QUERY_KEY, dataKey],
3544
3580
  queryFn: async () => {
3545
- return await redis.ttl(dataKey);
3581
+ switch (type) {
3582
+ case "set": {
3583
+ return await redis.scard(dataKey);
3584
+ }
3585
+ case "zset": {
3586
+ return await redis.zcard(dataKey);
3587
+ }
3588
+ case "list": {
3589
+ return await redis.llen(dataKey);
3590
+ }
3591
+ case "hash": {
3592
+ return await redis.hlen(dataKey);
3593
+ }
3594
+ case "stream": {
3595
+ return await redis.xlen(dataKey);
3596
+ }
3597
+ }
3598
+ return null;
3546
3599
  }
3547
3600
  });
3548
- _react.useEffect.call(void 0, () => {
3549
- if (data === -2) {
3550
- queryClient.invalidateQueries({
3551
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
3552
- });
3553
- }
3554
- }, [data === -2]);
3555
- return { isLoading, error, data };
3556
3601
  };
3557
3602
 
3558
- // src/components/databrowser/hooks/use-set-simple-key.tsx
3603
+ // src/components/databrowser/hooks/use-fetch-key-size.ts
3559
3604
 
3560
- var useSetSimpleKey = (dataKey, type) => {
3605
+ var FETCH_KEY_SIZE_QUERY_KEY = "fetch-key-size";
3606
+ var useFetchKeySize = (dataKey) => {
3561
3607
  const { redis } = useDatabrowser();
3562
- return _reactquery.useMutation.call(void 0, {
3563
- mutationFn: async (value) => {
3564
- if (type === "string") {
3565
- await redis.set(dataKey, value);
3566
- } else if (type === "json") {
3567
- await redis.json.set(dataKey, "$", JSON.parse(value));
3568
- } else {
3569
- throw new Error(`Invalid type when setting simple key: ${type}`);
3570
- }
3571
- },
3572
- onSuccess: (_, value) => {
3573
- queryClient.setQueryData([FETCH_SIMPLE_KEY_QUERY_KEY, dataKey], value);
3574
- queryClient.invalidateQueries({
3575
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
3576
- });
3608
+ return _reactquery.useQuery.call(void 0, {
3609
+ queryKey: [FETCH_KEY_SIZE_QUERY_KEY, dataKey],
3610
+ queryFn: async () => {
3611
+ return await redis.eval(`return redis.call("MEMORY", "USAGE", KEYS[1])`, [dataKey], []);
3577
3612
  }
3578
3613
  });
3579
3614
  };
3580
3615
 
3581
- // src/components/databrowser/hooks/use-set-ttl.ts
3616
+ // src/components/databrowser/components/display/header-badges.tsx
3582
3617
 
3583
- var useSetTTL = () => {
3584
- const { redis } = useDatabrowser();
3585
- const updateTTL = _reactquery.useMutation.call(void 0, {
3586
- mutationFn: async ({ dataKey, ttl }) => {
3587
- await (ttl === void 0 ? redis.persist(dataKey) : redis.expire(dataKey, ttl));
3588
- },
3589
- onSuccess: (_, { dataKey }) => {
3590
- queryClient.invalidateQueries({
3591
- queryKey: [FETCH_TTL_QUERY_KEY, dataKey]
3592
- });
3593
- queryClient.invalidateQueries({
3594
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
3595
- });
3618
+ var LengthBadge = ({
3619
+ dataKey,
3620
+ type,
3621
+ content
3622
+ }) => {
3623
+ const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3624
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _20 => _20.length]), () => ( data));
3625
+ 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 });
3626
+ };
3627
+ var SizeBadge = ({ dataKey }) => {
3628
+ const { data: size } = useFetchKeySize(dataKey);
3629
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label: "Size:", children: size === void 0 || size === null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : _bytes2.default.call(void 0, size, {
3630
+ unitSeparator: " "
3631
+ }) });
3632
+ };
3633
+ var HeaderTTLBadge = ({ dataKey }) => {
3634
+ const { data: expireAt } = useFetchKeyExpire(dataKey);
3635
+ const { mutate: setTTL, isPending } = useSetTTL();
3636
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3637
+ TTLBadge,
3638
+ {
3639
+ expireAt,
3640
+ setTTL: (ttl) => setTTL({ dataKey, ttl }),
3641
+ isPending
3596
3642
  }
3597
- });
3598
- return updateTTL;
3643
+ );
3599
3644
  };
3645
+ 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: [
3646
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: label }),
3647
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children })
3648
+ ] });
3600
3649
 
3601
- // src/components/databrowser/components/item-context-menu.tsx
3650
+ // src/components/databrowser/components/display/ttl-popover.tsx
3602
3651
 
3603
- var _reactcontextmenu = require('@radix-ui/react-context-menu'); var ContextMenuPrimitive = _interopRequireWildcard(_reactcontextmenu);
3652
+ var _reacthookform = require('react-hook-form');
3604
3653
 
3605
- // src/components/ui/context-menu.tsx
3654
+ // src/components/ui/input.tsx
3606
3655
 
3607
3656
 
3657
+ var Input = React4.forwardRef(
3658
+ ({ className, type, ...props }, ref) => {
3659
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3660
+ "input",
3661
+ {
3662
+ type,
3663
+ className: cn(
3664
+ "flex h-8 w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-zinc-950 disabled:cursor-not-allowed disabled:opacity-50",
3665
+ className
3666
+ ),
3667
+ ref,
3668
+ ...props
3669
+ }
3670
+ );
3671
+ }
3672
+ );
3673
+ Input.displayName = "Input";
3608
3674
 
3675
+ // src/components/ui/popover.tsx
3609
3676
 
3610
- var ContextMenu = ContextMenuPrimitive.Root;
3611
- var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
3612
- var ContextMenuSubTrigger = React4.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3613
- ContextMenuPrimitive.SubTrigger,
3614
- {
3615
- ref,
3616
- className: cn(
3617
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[state=open]:bg-neutral-100 data-[state=open]:text-neutral-900 dark:focus:bg-neutral-800 dark:focus:text-neutral-50 dark:data-[state=open]:bg-neutral-800 dark:data-[state=open]:text-neutral-50",
3618
- inset && "pl-8",
3619
- className
3620
- ),
3621
- ...props,
3622
- children: [
3623
- children,
3624
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.ChevronRightIcon, { className: "ml-auto h-4 w-4" })
3625
- ]
3626
- }
3627
- ));
3628
- ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
3629
- var ContextMenuSubContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3630
- ContextMenuPrimitive.SubContent,
3631
- {
3632
- ref,
3633
- className: cn(
3634
- "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
3635
- className
3636
- ),
3637
- ...props
3638
- }
3639
- ));
3640
- ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
3641
- var ContextMenuContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3642
- ContextMenuPrimitive.Content,
3677
+ var _reactpopover = require('@radix-ui/react-popover'); var PopoverPrimitive = _interopRequireWildcard(_reactpopover);
3678
+
3679
+ var Popover = PopoverPrimitive.Root;
3680
+ var PopoverTrigger = PopoverPrimitive.Trigger;
3681
+ var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3682
+ PopoverPrimitive.Content,
3643
3683
  {
3644
3684
  ref,
3685
+ align,
3686
+ sideOffset,
3645
3687
  className: cn(
3646
- "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
3688
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border border-zinc-200 bg-white p-4 text-zinc-950 shadow-md outline-none dark:border-zinc-800 mt-0.5 dark:bg-zinc-950 dark:text-zinc-50",
3647
3689
  className
3648
3690
  ),
3649
3691
  ...props
3650
3692
  }
3651
3693
  ) }));
3652
- ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
3653
- var ContextMenuItem = React4.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3654
- ContextMenuPrimitive.Item,
3655
- {
3656
- ref,
3657
- className: cn(
3658
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
3659
- inset && "pl-8",
3660
- className
3661
- ),
3662
- ...props
3663
- }
3664
- ));
3665
- ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
3666
- var ContextMenuCheckboxItem = React4.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3667
- ContextMenuPrimitive.CheckboxItem,
3694
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
3695
+
3696
+ // src/components/ui/select.tsx
3697
+
3698
+ var _reactselect = require('@radix-ui/react-select'); var SelectPrimitive = _interopRequireWildcard(_reactselect);
3699
+
3700
+ var Select = SelectPrimitive.Root;
3701
+ var SelectGroup = SelectPrimitive.Group;
3702
+ var SelectValue = SelectPrimitive.Value;
3703
+ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3704
+ SelectPrimitive.Trigger,
3668
3705
  {
3669
3706
  ref,
3670
3707
  className: cn(
3671
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
3708
+ "relative flex h-8 w-full items-center justify-between rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm ring-offset-white placeholder:text-zinc-500 focus:ring-zinc-950 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-800 dark:bg-zinc-950 dark:ring-offset-zinc-950 dark:placeholder:text-zinc-400 dark:focus:ring-zinc-300",
3672
3709
  className
3673
3710
  ),
3674
- checked,
3675
3711
  ...props,
3676
3712
  children: [
3677
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.CheckIcon, { className: "h-4 w-4" }) }) }),
3678
- children
3713
+ children,
3714
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.Icon, { asChild: true, className: "absolute right-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3715
+ "svg",
3716
+ {
3717
+ width: "16",
3718
+ height: "16",
3719
+ viewBox: "0 0 16 16",
3720
+ fill: "none",
3721
+ xmlns: "http://www.w3.org/2000/svg",
3722
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3723
+ "path",
3724
+ {
3725
+ d: "M4 6L8 10L12 6",
3726
+ stroke: "black",
3727
+ strokeOpacity: "0.4",
3728
+ strokeWidth: "1.4",
3729
+ strokeLinecap: "round",
3730
+ strokeLinejoin: "round"
3731
+ }
3732
+ )
3733
+ }
3734
+ ) })
3679
3735
  ]
3680
3736
  }
3681
3737
  ));
3682
- ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
3683
- var ContextMenuRadioItem = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3684
- ContextMenuPrimitive.RadioItem,
3738
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
3739
+ var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3740
+ SelectPrimitive.Content,
3685
3741
  {
3686
3742
  ref,
3687
3743
  className: cn(
3688
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
3744
+ "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white text-zinc-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-zinc-800 dark:bg-zinc-950 dark:text-neutral-50",
3745
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
3689
3746
  className
3690
3747
  ),
3748
+ position,
3691
3749
  ...props,
3692
- children: [
3693
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.DotFilledIcon, { className: "h-4 w-4 fill-current" }) }) }),
3694
- children
3695
- ]
3750
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3751
+ SelectPrimitive.Viewport,
3752
+ {
3753
+ className: cn(
3754
+ "p-1",
3755
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
3756
+ ),
3757
+ children
3758
+ }
3759
+ )
3696
3760
  }
3697
- ));
3698
- ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
3699
- var ContextMenuLabel = React4.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3700
- ContextMenuPrimitive.Label,
3761
+ ) }));
3762
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
3763
+ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3764
+ SelectPrimitive.Label,
3701
3765
  {
3702
3766
  ref,
3703
- className: cn(
3704
- "px-2 py-1.5 text-sm font-semibold text-neutral-950 dark:text-neutral-50",
3705
- inset && "pl-8",
3706
- className
3707
- ),
3767
+ className: cn("px-2 py-1.5 text-sm font-semibold", className),
3708
3768
  ...props
3709
3769
  }
3710
3770
  ));
3711
- ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
3712
- var ContextMenuSeparator = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3713
- ContextMenuPrimitive.Separator,
3771
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
3772
+ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3773
+ SelectPrimitive.Item,
3714
3774
  {
3715
3775
  ref,
3716
- className: cn("-mx-1 my-1 h-px bg-neutral-200 dark:bg-neutral-800", className),
3717
- ...props
3718
- }
3719
- ));
3720
- ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
3721
- var ContextMenuShortcut = ({ className, ...props }) => {
3722
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3723
- "span",
3724
- {
3725
- className: cn(
3726
- "ml-auto text-xs tracking-widest text-neutral-500 dark:text-neutral-400",
3727
- className
3728
- ),
3729
- ...props
3730
- }
3731
- );
3732
- };
3733
- ContextMenuShortcut.displayName = "ContextMenuShortcut";
3734
-
3735
- // src/components/ui/alert-dialog.tsx
3736
-
3737
- var _reactalertdialog = require('@radix-ui/react-alert-dialog'); var AlertDialogPrimitive = _interopRequireWildcard(_reactalertdialog);
3738
-
3739
- var AlertDialog = AlertDialogPrimitive.Root;
3740
- var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
3741
- var AlertDialogPortal = ({ ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Portal, { container: portalRoot, ...props });
3742
- AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
3743
- var AlertDialogOverlay = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3744
- AlertDialogPrimitive.Overlay,
3745
- {
3746
3776
  className: cn(
3747
- "fixed inset-0 z-50 bg-white/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 dark:bg-zinc-950/80",
3777
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
3748
3778
  className
3749
3779
  ),
3750
3780
  ...props,
3751
- ref
3752
- }
3753
- ));
3754
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
3755
- var AlertDialogContent = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogPortal, { children: [
3756
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogOverlay, {}),
3757
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3758
- AlertDialogPrimitive.Content,
3759
- {
3760
- ref,
3761
- className: cn(
3762
- "antialiased data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-zinc-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] dark:border-zinc-800 dark:bg-zinc-950 sm:rounded-lg md:w-full",
3763
- className
3764
- ),
3765
- ...props
3766
- }
3767
- )
3768
- ] }));
3769
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
3770
- var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
3771
- AlertDialogHeader.displayName = "AlertDialogHeader";
3772
- var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3773
- "div",
3774
- {
3775
- className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
3776
- ...props
3777
- }
3778
- );
3779
- AlertDialogFooter.displayName = "AlertDialogFooter";
3780
- var AlertDialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3781
- AlertDialogPrimitive.Title,
3782
- {
3783
- ref,
3784
- className: cn("text-lg font-semibold", className),
3785
- ...props
3786
- }
3787
- ));
3788
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
3789
- var AlertDialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3790
- AlertDialogPrimitive.Description,
3791
- {
3792
- ref,
3793
- className: cn("text-sm text-zinc-500 dark:text-zinc-400", className),
3794
- ...props
3781
+ children: [
3782
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3783
+ "svg",
3784
+ {
3785
+ width: "15",
3786
+ height: "15",
3787
+ viewBox: "0 0 15 15",
3788
+ fill: "none",
3789
+ xmlns: "http://www.w3.org/2000/svg",
3790
+ className: "h-4 w-4",
3791
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3792
+ "path",
3793
+ {
3794
+ d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
3795
+ fill: "currentColor",
3796
+ fillRule: "evenodd",
3797
+ clipRule: "evenodd"
3798
+ }
3799
+ )
3800
+ }
3801
+ ) }) }) }),
3802
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children })
3803
+ ]
3795
3804
  }
3796
3805
  ));
3797
- AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
3798
- var AlertDialogAction = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
3799
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
3800
- var AlertDialogCancel = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3801
- AlertDialogPrimitive.Cancel,
3806
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
3807
+ var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3808
+ SelectPrimitive.Separator,
3802
3809
  {
3803
3810
  ref,
3804
- className: cn(buttonVariants({ variant: "outline" }), "mt-2 sm:!mt-0", className),
3811
+ className: cn("-mx-1 my-1 h-px bg-neutral-100 dark:bg-neutral-800", className),
3805
3812
  ...props
3806
3813
  }
3807
3814
  ));
3808
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
3815
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
3809
3816
 
3810
- // src/components/databrowser/components/display/delete-alert-dialog.tsx
3817
+ // src/components/ui/spinner.tsx
3811
3818
 
3812
- function DeleteAlertDialog({
3813
- children,
3814
- onDeleteConfirm,
3815
- open,
3816
- onOpenChange,
3817
- deletionType
3818
- }) {
3819
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialog, { open, onOpenChange, children: [
3820
- children && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTrigger, { asChild: true, children }),
3821
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogContent, { children: [
3822
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
3823
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: deletionType === "item" ? "Delete Item" : "Delete Key" }),
3824
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
3825
- "Are you sure you want to delete this ",
3826
- deletionType,
3827
- "?",
3828
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
3829
- "This action cannot be undone."
3830
- ] })
3831
- ] }),
3832
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogFooter, { children: [
3833
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogCancel, { type: "button", children: "Cancel" }),
3834
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3835
- AlertDialogAction,
3836
- {
3837
- className: "bg-red-500 text-gray-50 hover:bg-red-600",
3838
- onClick: onDeleteConfirm,
3839
- children: "Yes, Delete"
3840
- }
3841
- )
3842
- ] })
3843
- ] })
3844
- ] });
3845
- }
3846
-
3847
- // src/components/databrowser/components/item-context-menu.tsx
3848
-
3849
- var ItemContextMenu = ({
3850
- children,
3851
- dataKey,
3852
- type
3819
+ var Spinner = ({
3820
+ isLoading,
3821
+ className,
3822
+ isLoadingText,
3823
+ children
3853
3824
  }) => {
3854
- const { mutate: editItem } = useEditListItem();
3855
- const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
3856
- const [data, setData] = _react.useState.call(void 0, );
3857
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3825
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _nullishCoalesce(className, () => ( "flex items-center")), children: isLoading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
3826
+ isLoadingText,
3858
3827
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3859
- DeleteAlertDialog,
3860
- {
3861
- deletionType: "item",
3862
- open: isAlertOpen,
3863
- onOpenChange: setAlertOpen,
3864
- onDeleteConfirm: (e) => {
3865
- e.stopPropagation();
3866
- if (data) {
3867
- editItem({
3868
- type,
3869
- dataKey,
3870
- itemKey: _optionalChain([data, 'optionalAccess', _20 => _20.key]),
3871
- // For deletion
3872
- newKey: void 0
3873
- });
3874
- }
3875
- setAlertOpen(false);
3876
- }
3877
- }
3878
- ),
3879
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { children: [
3880
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3881
- ContextMenuTrigger,
3882
- {
3883
- asChild: true,
3884
- onContextMenu: (e) => {
3885
- const el = e.target;
3886
- const item = el.closest("[data-item-key]");
3887
- if (item && item instanceof HTMLElement && item.dataset.itemKey !== void 0) {
3888
- setData({
3889
- key: item.dataset.itemKey,
3890
- value: item.dataset.itemValue
3891
- });
3892
- } else {
3893
- throw new Error("Key not found");
3894
- }
3895
- },
3896
- children
3897
- }
3898
- ),
3899
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
3900
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3901
- ContextMenuItem,
3902
- {
3903
- onClick: () => {
3904
- if (!data) return;
3905
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _21 => _21.key]));
3906
- toast({
3907
- description: "Key copied to clipboard"
3908
- });
3909
- },
3910
- children: "Copy key"
3911
- }
3912
- ),
3913
- _optionalChain([data, 'optionalAccess', _22 => _22.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3914
- ContextMenuItem,
3915
- {
3916
- onClick: () => {
3917
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _23 => _23.value]), () => ( "")));
3918
- toast({
3919
- description: "Value copied to clipboard"
3920
- });
3921
- },
3922
- children: "Copy value"
3923
- }
3924
- ),
3925
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
3926
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuItem, { disabled: type === "stream", onClick: () => setAlertOpen(true), children: "Delete item" })
3927
- ] })
3928
- ] })
3929
- ] });
3930
- };
3931
-
3932
- // src/components/databrowser/components/sidebar/infinite-scroll.tsx
3933
-
3934
-
3935
- // src/components/ui/scroll-area.tsx
3936
-
3937
- var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
3938
-
3939
- var ScrollArea = React6.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3940
- ScrollAreaPrimitive.Root,
3941
- {
3942
- ref,
3943
- className: cn("relative overflow-hidden", className),
3944
- ...props,
3945
- children: [
3946
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3947
- ScrollAreaPrimitive.Viewport,
3948
- {
3949
- onScroll,
3950
- className: "h-full w-full rounded-[inherit] [&>div]:!block",
3951
- children
3952
- }
3953
- ),
3954
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, {}),
3955
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
3956
- ]
3957
- }
3958
- ));
3959
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
3960
- var ScrollBar = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3961
- ScrollAreaPrimitive.ScrollAreaScrollbar,
3962
- {
3963
- ref,
3964
- orientation: "vertical",
3965
- className: cn("flex h-full w-2 touch-none select-none transition-colors", className),
3966
- ...props,
3967
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3968
- ScrollAreaPrimitive.ScrollAreaThumb,
3828
+ "svg",
3969
3829
  {
3970
- className: cn("relative flex-1 rounded-full bg-neutral-200/70 dark:bg-neutral-800")
3830
+ xmlns: "http://www.w3.org/2000/svg",
3831
+ width: "24",
3832
+ height: "24",
3833
+ viewBox: "0 0 24 24",
3834
+ fill: "none",
3835
+ stroke: "currentColor",
3836
+ strokeWidth: "2",
3837
+ strokeLinecap: "round",
3838
+ strokeLinejoin: "round",
3839
+ className: cn("h-4 w-4 animate-spin", isLoadingText ? "ml-2" : ""),
3840
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3971
3841
  }
3972
3842
  )
3973
- }
3974
- ));
3975
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
3843
+ ] }) : children });
3844
+ };
3976
3845
 
3977
- // src/components/databrowser/components/sidebar/infinite-scroll.tsx
3846
+ // src/components/databrowser/components/display/ttl-popover.tsx
3978
3847
 
3979
- var InfiniteScroll = ({
3980
- query,
3981
- children
3982
- }) => {
3983
- const handleScroll = (e) => {
3984
- const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
3985
- if (scrollTop + clientHeight > scrollHeight - 100) {
3986
- if (query.isFetching || !query.hasNextPage) {
3987
- return;
3988
- }
3989
- query.fetchNextPage();
3990
- }
3848
+ var timeUnits = [
3849
+ { label: "Seconds", value: 1 },
3850
+ { label: "Minutes", value: 60 },
3851
+ { label: "Hours", value: 60 * 60 },
3852
+ { label: "Days", value: 60 * 60 * 24 }
3853
+ ];
3854
+ function TTLPopover({
3855
+ children,
3856
+ ttl,
3857
+ setTTL,
3858
+ isPending
3859
+ }) {
3860
+ const [open, setOpen] = _react.useState.call(void 0, false);
3861
+ const defaultValues = _react.useMemo.call(void 0, () => {
3862
+ return { type: "Seconds", value: ttl };
3863
+ }, [ttl]);
3864
+ const { control, handleSubmit, formState, reset } = _reacthookform.useForm.call(void 0, {
3865
+ defaultValues
3866
+ });
3867
+ _react.useEffect.call(void 0, () => {
3868
+ reset(defaultValues, {
3869
+ keepValues: true
3870
+ });
3871
+ }, [defaultValues]);
3872
+ const onSubmit = handleSubmit(async ({ value, type }) => {
3873
+ await setTTL(value * timeUnits.find((unit) => unit.label === type).value);
3874
+ setOpen(false);
3875
+ });
3876
+ const handlePersist = async () => {
3877
+ await setTTL(TTL_INFINITE);
3878
+ setOpen(false);
3991
3879
  };
3992
3880
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3993
- ScrollArea,
3881
+ Popover,
3994
3882
  {
3995
- type: "always",
3996
- className: "block h-full w-full transition-all",
3997
- onScroll: handleScroll,
3883
+ open,
3884
+ onOpenChange: (isOpen) => {
3885
+ if (isOpen) reset();
3886
+ setOpen(isOpen);
3887
+ },
3998
3888
  children: [
3999
- children,
4000
- /* @__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 }) })
3889
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { children }) }),
3890
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverContent, { className: "w-[300px]", align: "end", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3891
+ "form",
3892
+ {
3893
+ className: "space-y-4",
3894
+ onSubmit: (e) => {
3895
+ onSubmit(e);
3896
+ e.stopPropagation();
3897
+ },
3898
+ children: [
3899
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "font-medium leading-none", children: "Expiration" }),
3900
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3901
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center", children: [
3902
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3903
+ _reacthookform.Controller,
3904
+ {
3905
+ rules: {
3906
+ required: "Please enter an expiration time",
3907
+ min: { value: -1, message: "TTL can't be lower than -1" }
3908
+ },
3909
+ control,
3910
+ name: "value",
3911
+ render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Input, { min: "-1", ...field, className: "grow rounded-r-none" })
3912
+ }
3913
+ ),
3914
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3915
+ _reacthookform.Controller,
3916
+ {
3917
+ control,
3918
+ name: "type",
3919
+ render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: field.value, onValueChange: field.onChange, children: [
3920
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "w-auto rounded-l-none border-l-0 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
3921
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: timeUnits.map((unit) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: unit.label, children: unit.label }, unit.label)) })
3922
+ ] })
3923
+ }
3924
+ )
3925
+ ] }),
3926
+ formState.errors.value && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-red-500", children: formState.errors.value.message }),
3927
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-zinc-500", children: "TTL sets a timer to automatically delete keys after a defined period." })
3928
+ ] }),
3929
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex justify-between", children: [
3930
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3931
+ Button,
3932
+ {
3933
+ type: "button",
3934
+ variant: "outline",
3935
+ disabled: ttl === TTL_INFINITE,
3936
+ onClick: handlePersist,
3937
+ children: "Persist"
3938
+ }
3939
+ ),
3940
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [
3941
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", onClick: () => setOpen(false), type: "button", children: "Cancel" }),
3942
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" }) })
3943
+ ] })
3944
+ ] })
3945
+ ]
3946
+ }
3947
+ ) })
4001
3948
  ]
4002
3949
  }
4003
3950
  );
4004
- };
4005
-
4006
- // src/components/databrowser/components/display/display-header.tsx
4007
-
4008
-
4009
- // src/components/databrowser/components/type-tag.tsx
4010
-
4011
-
4012
-
4013
-
4014
-
4015
-
4016
-
4017
-
4018
-
4019
- var iconsMap = {
4020
- string: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconQuote, { size: 15, stroke: 1.3 }),
4021
- set: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLayersIntersect, { size: 15, stroke: 1.3 }),
4022
- hash: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconHash, { size: 15, stroke: 1.3 }),
4023
- json: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCodeDots, { size: 15, stroke: 1.3 }),
4024
- zset: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconArrowsSort, { size: 15, stroke: 1.3 }),
4025
- list: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.3 }),
4026
- stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.3 })
4027
- };
4028
- var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-center", {
4029
- variants: {
4030
- variant: {
4031
- string: "bg-sky-200 text-sky-800",
4032
- hash: "bg-amber-200 text-amber-800",
4033
- set: "bg-indigo-200 text-indigo-800",
4034
- zset: "bg-pink-200 text-pink-800",
4035
- json: "bg-purple-200 text-purple-800",
4036
- list: "bg-orange-200 text-orange-800",
4037
- stream: "bg-green-200 text-green-800"
4038
- },
4039
- type: {
4040
- icon: "size-5",
4041
- badge: "h-6 px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4042
- }
4043
- },
4044
- defaultVariants: {
4045
- variant: "string",
4046
- type: "icon"
4047
- }
4048
- });
4049
- function TypeTag({ className, variant, type }) {
4050
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: cn(tagVariants({ variant, type, className })), children: type === "icon" ? iconsMap[variant] : DATA_TYPE_NAMES[variant] });
4051
3951
  }
4052
3952
 
4053
- // src/components/databrowser/components/display/header-badges.tsx
3953
+ // src/components/databrowser/components/display/ttl-badge.tsx
4054
3954
 
3955
+ var TTL_INFINITE = -1;
3956
+ var TTL_NOT_FOUND = -2;
3957
+ var calculateTTL = (expireAt) => {
3958
+ if (!expireAt) return;
3959
+ if (expireAt === TTL_INFINITE) return TTL_INFINITE;
3960
+ return Math.max(0, Math.floor((expireAt - Date.now()) / 1e3));
3961
+ };
3962
+ var TTLBadge = ({
3963
+ label = "TTL:",
3964
+ expireAt,
3965
+ setTTL,
3966
+ isPending
3967
+ }) => {
3968
+ const [ttl, setTTLLabel] = _react.useState.call(void 0, () => calculateTTL(expireAt));
3969
+ _react.useEffect.call(void 0, () => {
3970
+ setTTLLabel(calculateTTL(expireAt));
3971
+ const interval = setInterval(() => {
3972
+ setTTLLabel(calculateTTL(expireAt));
3973
+ }, 1e3);
3974
+ return () => clearInterval(interval);
3975
+ }, [expireAt]);
3976
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label, children: ttl === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TTLPopover, { ttl, setTTL, isPending, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-[2px]", children: [
3977
+ ttl === TTL_INFINITE ? "Forever" : formatTime(ttl),
3978
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
3979
+ ] }) }) });
3980
+ };
4055
3981
 
4056
- var _bytes = require('bytes'); var _bytes2 = _interopRequireDefault(_bytes);
3982
+ // src/components/databrowser/hooks/use-fetch-ttl.ts
3983
+ var FETCH_TTL_QUERY_KEY = "fetch-ttl";
3984
+ var useFetchKeyExpire = (dataKey) => {
3985
+ const { redis } = useDatabrowser();
3986
+ const { isLoading, error, data } = _reactquery.useQuery.call(void 0, {
3987
+ queryKey: [FETCH_TTL_QUERY_KEY, dataKey],
3988
+ queryFn: async () => {
3989
+ const ttl = await redis.ttl(dataKey);
3990
+ return ttl === TTL_INFINITE || ttl === TTL_NOT_FOUND ? ttl : Date.now() + ttl * 1e3;
3991
+ }
3992
+ });
3993
+ _react.useEffect.call(void 0, () => {
3994
+ if (data === TTL_NOT_FOUND) {
3995
+ queryClient.invalidateQueries({
3996
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
3997
+ });
3998
+ }
3999
+ }, [data === TTL_NOT_FOUND]);
4000
+ return { isLoading, error, data };
4001
+ };
4057
4002
 
4058
- // src/components/databrowser/hooks/use-fetch-key-length.ts
4003
+ // src/components/databrowser/hooks/use-set-simple-key.tsx
4059
4004
 
4060
- var FETCH_KEY_LENGTH_QUERY_KEY = "fetch-key-length";
4061
- var useFetchKeyLength = ({ dataKey, type }) => {
4005
+ var useSetSimpleKey = (dataKey, type) => {
4062
4006
  const { redis } = useDatabrowser();
4063
- return _reactquery.useQuery.call(void 0, {
4064
- queryKey: [FETCH_KEY_LENGTH_QUERY_KEY, dataKey],
4065
- queryFn: async () => {
4066
- switch (type) {
4067
- case "set": {
4068
- return await redis.scard(dataKey);
4069
- }
4070
- case "zset": {
4071
- return await redis.zcard(dataKey);
4072
- }
4073
- case "list": {
4074
- return await redis.llen(dataKey);
4075
- }
4076
- case "hash": {
4077
- return await redis.hlen(dataKey);
4078
- }
4079
- case "stream": {
4080
- return await redis.xlen(dataKey);
4081
- }
4007
+ return _reactquery.useMutation.call(void 0, {
4008
+ mutationFn: async (value) => {
4009
+ if (type === "string") {
4010
+ await redis.set(dataKey, value);
4011
+ } else if (type === "json") {
4012
+ await redis.json.set(dataKey, "$", JSON.parse(value));
4013
+ } else {
4014
+ throw new Error(`Invalid type when setting simple key: ${type}`);
4082
4015
  }
4083
- return null;
4016
+ },
4017
+ onSuccess: (_, value) => {
4018
+ queryClient.setQueryData([FETCH_SIMPLE_KEY_QUERY_KEY, dataKey], value);
4019
+ queryClient.invalidateQueries({
4020
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
4021
+ });
4084
4022
  }
4085
4023
  });
4086
4024
  };
4087
4025
 
4088
- // src/components/databrowser/hooks/use-fetch-key-size.ts
4026
+ // src/components/databrowser/hooks/use-set-ttl.ts
4089
4027
 
4090
- var FETCH_KEY_SIZE_QUERY_KEY = "fetch-key-size";
4091
- var useFetchKeySize = (dataKey) => {
4028
+ var useSetTTL = () => {
4092
4029
  const { redis } = useDatabrowser();
4093
- return _reactquery.useQuery.call(void 0, {
4094
- queryKey: [FETCH_KEY_SIZE_QUERY_KEY, dataKey],
4095
- queryFn: async () => {
4096
- return await redis.eval(`return redis.call("MEMORY", "USAGE", KEYS[1])`, [dataKey], []);
4030
+ const updateTTL = _reactquery.useMutation.call(void 0, {
4031
+ mutationFn: async ({ dataKey, ttl }) => {
4032
+ await (ttl === void 0 || ttl === TTL_INFINITE ? redis.persist(dataKey) : redis.expire(dataKey, ttl));
4033
+ },
4034
+ onSuccess: (_, { dataKey }) => {
4035
+ queryClient.removeQueries({
4036
+ queryKey: [FETCH_TTL_QUERY_KEY, dataKey]
4037
+ });
4038
+ queryClient.invalidateQueries({
4039
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey]
4040
+ });
4097
4041
  }
4098
4042
  });
4043
+ return updateTTL;
4099
4044
  };
4100
4045
 
4101
- // src/components/databrowser/components/display/ttl-popover.tsx
4102
-
4103
- var _reacthookform = require('react-hook-form');
4046
+ // src/components/databrowser/components/item-context-menu.tsx
4104
4047
 
4105
- // src/components/ui/input.tsx
4048
+ var _reactcontextmenu = require('@radix-ui/react-context-menu'); var ContextMenuPrimitive = _interopRequireWildcard(_reactcontextmenu);
4106
4049
 
4050
+ // src/components/ui/context-menu.tsx
4107
4051
 
4108
- var Input = React7.forwardRef(
4109
- ({ className, type, ...props }, ref) => {
4110
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4111
- "input",
4112
- {
4113
- type,
4114
- className: cn(
4115
- "flex h-8 w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-zinc-950 disabled:cursor-not-allowed disabled:opacity-50",
4116
- className
4117
- ),
4118
- ref,
4119
- ...props
4120
- }
4121
- );
4122
- }
4123
- );
4124
- Input.displayName = "Input";
4125
4052
 
4126
- // src/components/ui/popover.tsx
4127
4053
 
4128
- var _reactpopover = require('@radix-ui/react-popover'); var PopoverPrimitive = _interopRequireWildcard(_reactpopover);
4129
4054
 
4130
- var Popover = PopoverPrimitive.Root;
4131
- var PopoverTrigger = PopoverPrimitive.Trigger;
4132
- var PopoverContent = React8.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4133
- PopoverPrimitive.Content,
4055
+ var ContextMenu = ContextMenuPrimitive.Root;
4056
+ var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
4057
+ var ContextMenuSubTrigger = React7.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4058
+ ContextMenuPrimitive.SubTrigger,
4134
4059
  {
4135
4060
  ref,
4136
- align,
4137
- sideOffset,
4138
4061
  className: cn(
4139
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border border-zinc-200 bg-white p-4 text-zinc-950 shadow-md outline-none dark:border-zinc-800 mt-0.5 dark:bg-zinc-950 dark:text-zinc-50",
4062
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[state=open]:bg-neutral-100 data-[state=open]:text-neutral-900 dark:focus:bg-neutral-800 dark:focus:text-neutral-50 dark:data-[state=open]:bg-neutral-800 dark:data-[state=open]:text-neutral-50",
4063
+ inset && "pl-8",
4064
+ className
4065
+ ),
4066
+ ...props,
4067
+ children: [
4068
+ children,
4069
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.ChevronRightIcon, { className: "ml-auto h-4 w-4" })
4070
+ ]
4071
+ }
4072
+ ));
4073
+ ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
4074
+ var ContextMenuSubContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4075
+ ContextMenuPrimitive.SubContent,
4076
+ {
4077
+ ref,
4078
+ className: cn(
4079
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4080
+ className
4081
+ ),
4082
+ ...props
4083
+ }
4084
+ ));
4085
+ ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
4086
+ var ContextMenuContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4087
+ ContextMenuPrimitive.Content,
4088
+ {
4089
+ ref,
4090
+ className: cn(
4091
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-neutral-200 bg-white p-1 text-neutral-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-50",
4140
4092
  className
4141
4093
  ),
4142
4094
  ...props
4143
4095
  }
4144
4096
  ) }));
4145
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
4146
-
4147
- // src/components/ui/select.tsx
4148
-
4149
- var _reactselect = require('@radix-ui/react-select'); var SelectPrimitive = _interopRequireWildcard(_reactselect);
4150
-
4151
- var Select = SelectPrimitive.Root;
4152
- var SelectGroup = SelectPrimitive.Group;
4153
- var SelectValue = SelectPrimitive.Value;
4154
- var SelectTrigger = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4155
- SelectPrimitive.Trigger,
4097
+ ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
4098
+ var ContextMenuItem = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4099
+ ContextMenuPrimitive.Item,
4156
4100
  {
4157
4101
  ref,
4158
4102
  className: cn(
4159
- "relative flex h-8 w-full items-center justify-between rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm ring-offset-white placeholder:text-zinc-500 focus:ring-zinc-950 disabled:cursor-not-allowed disabled:opacity-50 dark:border-zinc-800 dark:bg-zinc-950 dark:ring-offset-zinc-950 dark:placeholder:text-zinc-400 dark:focus:ring-zinc-300",
4103
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
4104
+ inset && "pl-8",
4105
+ className
4106
+ ),
4107
+ ...props
4108
+ }
4109
+ ));
4110
+ ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
4111
+ var ContextMenuCheckboxItem = React7.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4112
+ ContextMenuPrimitive.CheckboxItem,
4113
+ {
4114
+ ref,
4115
+ className: cn(
4116
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
4160
4117
  className
4161
4118
  ),
4119
+ checked,
4162
4120
  ...props,
4163
4121
  children: [
4164
- children,
4165
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.Icon, { asChild: true, className: "absolute right-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4166
- "svg",
4167
- {
4168
- width: "16",
4169
- height: "16",
4170
- viewBox: "0 0 16 16",
4171
- fill: "none",
4172
- xmlns: "http://www.w3.org/2000/svg",
4173
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4174
- "path",
4175
- {
4176
- d: "M4 6L8 10L12 6",
4177
- stroke: "black",
4178
- strokeOpacity: "0.4",
4179
- strokeWidth: "1.4",
4180
- strokeLinecap: "round",
4181
- strokeLinejoin: "round"
4182
- }
4183
- )
4184
- }
4185
- ) })
4122
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.CheckIcon, { className: "h-4 w-4" }) }) }),
4123
+ children
4186
4124
  ]
4187
4125
  }
4188
4126
  ));
4189
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
4190
- var SelectContent = React9.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4191
- SelectPrimitive.Content,
4127
+ ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
4128
+ var ContextMenuRadioItem = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4129
+ ContextMenuPrimitive.RadioItem,
4192
4130
  {
4193
4131
  ref,
4194
4132
  className: cn(
4195
- "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-zinc-200 bg-white text-zinc-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-zinc-800 dark:bg-zinc-950 dark:text-neutral-50",
4196
- position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
4133
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
4197
4134
  className
4198
4135
  ),
4199
- position,
4200
4136
  ...props,
4201
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4202
- SelectPrimitive.Viewport,
4203
- {
4204
- className: cn(
4205
- "p-1",
4206
- position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
4207
- ),
4208
- children
4209
- }
4210
- )
4137
+ children: [
4138
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacticons.DotFilledIcon, { className: "h-4 w-4 fill-current" }) }) }),
4139
+ children
4140
+ ]
4141
+ }
4142
+ ));
4143
+ ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
4144
+ var ContextMenuLabel = React7.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4145
+ ContextMenuPrimitive.Label,
4146
+ {
4147
+ ref,
4148
+ className: cn(
4149
+ "px-2 py-1.5 text-sm font-semibold text-neutral-950 dark:text-neutral-50",
4150
+ inset && "pl-8",
4151
+ className
4152
+ ),
4153
+ ...props
4154
+ }
4155
+ ));
4156
+ ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
4157
+ var ContextMenuSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4158
+ ContextMenuPrimitive.Separator,
4159
+ {
4160
+ ref,
4161
+ className: cn("-mx-1 my-1 h-px bg-neutral-200 dark:bg-neutral-800", className),
4162
+ ...props
4163
+ }
4164
+ ));
4165
+ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
4166
+ var ContextMenuShortcut = ({ className, ...props }) => {
4167
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4168
+ "span",
4169
+ {
4170
+ className: cn(
4171
+ "ml-auto text-xs tracking-widest text-neutral-500 dark:text-neutral-400",
4172
+ className
4173
+ ),
4174
+ ...props
4175
+ }
4176
+ );
4177
+ };
4178
+ ContextMenuShortcut.displayName = "ContextMenuShortcut";
4179
+
4180
+ // src/components/ui/alert-dialog.tsx
4181
+
4182
+ var _reactalertdialog = require('@radix-ui/react-alert-dialog'); var AlertDialogPrimitive = _interopRequireWildcard(_reactalertdialog);
4183
+
4184
+ var AlertDialog = AlertDialogPrimitive.Root;
4185
+ var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
4186
+ var AlertDialogPortal = ({ ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Portal, { container: portalRoot, ...props });
4187
+ AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
4188
+ var AlertDialogOverlay = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4189
+ AlertDialogPrimitive.Overlay,
4190
+ {
4191
+ className: cn(
4192
+ "fixed inset-0 z-50 bg-white/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 dark:bg-zinc-950/80",
4193
+ className
4194
+ ),
4195
+ ...props,
4196
+ ref
4197
+ }
4198
+ ));
4199
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
4200
+ var AlertDialogContent = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogPortal, { children: [
4201
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogOverlay, {}),
4202
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4203
+ AlertDialogPrimitive.Content,
4204
+ {
4205
+ ref,
4206
+ className: cn(
4207
+ "antialiased data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-zinc-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] dark:border-zinc-800 dark:bg-zinc-950 sm:rounded-lg md:w-full",
4208
+ className
4209
+ ),
4210
+ ...props
4211
+ }
4212
+ )
4213
+ ] }));
4214
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
4215
+ var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
4216
+ AlertDialogHeader.displayName = "AlertDialogHeader";
4217
+ var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4218
+ "div",
4219
+ {
4220
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
4221
+ ...props
4211
4222
  }
4212
- ) }));
4213
- SelectContent.displayName = SelectPrimitive.Content.displayName;
4214
- var SelectLabel = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4215
- SelectPrimitive.Label,
4223
+ );
4224
+ AlertDialogFooter.displayName = "AlertDialogFooter";
4225
+ var AlertDialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4226
+ AlertDialogPrimitive.Title,
4216
4227
  {
4217
4228
  ref,
4218
- className: cn("px-2 py-1.5 text-sm font-semibold", className),
4229
+ className: cn("text-lg font-semibold", className),
4219
4230
  ...props
4220
4231
  }
4221
4232
  ));
4222
- SelectLabel.displayName = SelectPrimitive.Label.displayName;
4223
- var SelectItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4224
- SelectPrimitive.Item,
4233
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
4234
+ var AlertDialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4235
+ AlertDialogPrimitive.Description,
4225
4236
  {
4226
4237
  ref,
4227
- className: cn(
4228
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-neutral-100 focus:text-neutral-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-neutral-800 dark:focus:text-neutral-50",
4229
- className
4230
- ),
4231
- ...props,
4232
- children: [
4233
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4234
- "svg",
4235
- {
4236
- width: "15",
4237
- height: "15",
4238
- viewBox: "0 0 15 15",
4239
- fill: "none",
4240
- xmlns: "http://www.w3.org/2000/svg",
4241
- className: "h-4 w-4",
4242
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4243
- "path",
4244
- {
4245
- d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
4246
- fill: "currentColor",
4247
- fillRule: "evenodd",
4248
- clipRule: "evenodd"
4249
- }
4250
- )
4251
- }
4252
- ) }) }) }),
4253
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children })
4254
- ]
4238
+ className: cn("text-sm text-zinc-500 dark:text-zinc-400", className),
4239
+ ...props
4255
4240
  }
4256
4241
  ));
4257
- SelectItem.displayName = SelectPrimitive.Item.displayName;
4258
- var SelectSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4259
- SelectPrimitive.Separator,
4242
+ AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
4243
+ var AlertDialogAction = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
4244
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
4245
+ var AlertDialogCancel = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4246
+ AlertDialogPrimitive.Cancel,
4260
4247
  {
4261
4248
  ref,
4262
- className: cn("-mx-1 my-1 h-px bg-neutral-100 dark:bg-neutral-800", className),
4249
+ className: cn(buttonVariants({ variant: "outline" }), "mt-2 sm:!mt-0", className),
4263
4250
  ...props
4264
4251
  }
4265
4252
  ));
4266
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
4253
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
4267
4254
 
4268
- // src/components/ui/spinner.tsx
4255
+ // src/components/databrowser/components/display/delete-alert-dialog.tsx
4269
4256
 
4270
- var Spinner = ({
4271
- isLoading,
4272
- className,
4273
- isLoadingText,
4274
- children
4257
+ function DeleteAlertDialog({
4258
+ children,
4259
+ onDeleteConfirm,
4260
+ open,
4261
+ onOpenChange,
4262
+ deletionType
4263
+ }) {
4264
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialog, { open, onOpenChange, children: [
4265
+ children && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTrigger, { asChild: true, children }),
4266
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogContent, { children: [
4267
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
4268
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: deletionType === "item" ? "Delete Item" : "Delete Key" }),
4269
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
4270
+ "Are you sure you want to delete this ",
4271
+ deletionType,
4272
+ "?",
4273
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
4274
+ "This action cannot be undone."
4275
+ ] })
4276
+ ] }),
4277
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogFooter, { children: [
4278
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogCancel, { type: "button", children: "Cancel" }),
4279
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4280
+ AlertDialogAction,
4281
+ {
4282
+ className: "bg-red-500 text-gray-50 hover:bg-red-600",
4283
+ onClick: onDeleteConfirm,
4284
+ children: "Yes, Delete"
4285
+ }
4286
+ )
4287
+ ] })
4288
+ ] })
4289
+ ] });
4290
+ }
4291
+
4292
+ // src/components/databrowser/components/item-context-menu.tsx
4293
+
4294
+ var ItemContextMenu = ({
4295
+ children,
4296
+ dataKey,
4297
+ type
4275
4298
  }) => {
4276
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _nullishCoalesce(className, () => ( "flex items-center")), children: isLoading ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
4277
- isLoadingText,
4299
+ const { mutate: editItem } = useEditListItem();
4300
+ const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
4301
+ const [data, setData] = _react.useState.call(void 0, );
4302
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
4278
4303
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4279
- "svg",
4304
+ DeleteAlertDialog,
4280
4305
  {
4281
- xmlns: "http://www.w3.org/2000/svg",
4282
- width: "24",
4283
- height: "24",
4284
- viewBox: "0 0 24 24",
4285
- fill: "none",
4286
- stroke: "currentColor",
4287
- strokeWidth: "2",
4288
- strokeLinecap: "round",
4289
- strokeLinejoin: "round",
4290
- className: cn("h-4 w-4 animate-spin", isLoadingText ? "ml-2" : ""),
4291
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
4306
+ deletionType: "item",
4307
+ open: isAlertOpen,
4308
+ onOpenChange: setAlertOpen,
4309
+ onDeleteConfirm: (e) => {
4310
+ e.stopPropagation();
4311
+ if (data) {
4312
+ editItem({
4313
+ type,
4314
+ dataKey,
4315
+ itemKey: _optionalChain([data, 'optionalAccess', _21 => _21.key]),
4316
+ // For deletion
4317
+ newKey: void 0
4318
+ });
4319
+ }
4320
+ setAlertOpen(false);
4321
+ }
4292
4322
  }
4293
- )
4294
- ] }) : children });
4323
+ ),
4324
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { children: [
4325
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4326
+ ContextMenuTrigger,
4327
+ {
4328
+ asChild: true,
4329
+ onContextMenu: (e) => {
4330
+ const el = e.target;
4331
+ const item = el.closest("[data-item-key]");
4332
+ if (item && item instanceof HTMLElement && item.dataset.itemKey !== void 0) {
4333
+ setData({
4334
+ key: item.dataset.itemKey,
4335
+ value: item.dataset.itemValue
4336
+ });
4337
+ } else {
4338
+ throw new Error("Key not found");
4339
+ }
4340
+ },
4341
+ children
4342
+ }
4343
+ ),
4344
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
4345
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4346
+ ContextMenuItem,
4347
+ {
4348
+ onClick: () => {
4349
+ if (!data) return;
4350
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _22 => _22.key]));
4351
+ toast({
4352
+ description: "Key copied to clipboard"
4353
+ });
4354
+ },
4355
+ children: "Copy key"
4356
+ }
4357
+ ),
4358
+ _optionalChain([data, 'optionalAccess', _23 => _23.value]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4359
+ ContextMenuItem,
4360
+ {
4361
+ onClick: () => {
4362
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _24 => _24.value]), () => ( "")));
4363
+ toast({
4364
+ description: "Value copied to clipboard"
4365
+ });
4366
+ },
4367
+ children: "Copy value"
4368
+ }
4369
+ ),
4370
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
4371
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuItem, { disabled: type === "stream", onClick: () => setAlertOpen(true), children: "Delete item" })
4372
+ ] })
4373
+ ] })
4374
+ ] });
4295
4375
  };
4296
4376
 
4297
- // src/components/databrowser/components/display/ttl-popover.tsx
4377
+ // src/components/databrowser/components/sidebar/infinite-scroll.tsx
4298
4378
 
4299
- var PERSISTED_KEY = -1;
4300
- var timeUnits = [
4301
- { label: "Seconds", value: 1 },
4302
- { label: "Minutes", value: 60 },
4303
- { label: "Hours", value: 60 * 60 },
4304
- { label: "Days", value: 60 * 60 * 24 }
4305
- ];
4306
- function TTLPopover({
4307
- children,
4308
- ttl,
4309
- dataKey
4310
- }) {
4311
- const [open, setOpen] = _react.useState.call(void 0, false);
4312
- const { mutateAsync: setTTL, isPending } = useSetTTL();
4313
- const defaultValues = _react.useMemo.call(void 0, () => {
4314
- return { type: "Seconds", value: ttl };
4315
- }, [ttl]);
4316
- const { control, handleSubmit, formState, reset } = _reacthookform.useForm.call(void 0, {
4317
- defaultValues
4318
- });
4319
- _react.useEffect.call(void 0, () => {
4320
- reset(defaultValues, {
4321
- keepValues: true
4322
- });
4323
- }, [defaultValues]);
4324
- const onSubmit = handleSubmit(async ({ value, type }) => {
4325
- await setTTL({
4326
- dataKey,
4327
- ttl: value * timeUnits.find((unit) => unit.label === type).value
4328
- });
4329
- setOpen(false);
4330
- });
4331
- const handlePersist = async () => {
4332
- await setTTL({
4333
- dataKey,
4334
- ttl: void 0
4335
- });
4336
- setOpen(false);
4379
+
4380
+ // src/components/ui/scroll-area.tsx
4381
+
4382
+ var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
4383
+
4384
+ var ScrollArea = React9.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4385
+ ScrollAreaPrimitive.Root,
4386
+ {
4387
+ ref,
4388
+ className: cn("relative overflow-hidden", className),
4389
+ ...props,
4390
+ children: [
4391
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4392
+ ScrollAreaPrimitive.Viewport,
4393
+ {
4394
+ onScroll,
4395
+ className: "h-full w-full rounded-[inherit] [&>div]:!block",
4396
+ children
4397
+ }
4398
+ ),
4399
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, {}),
4400
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4401
+ ]
4402
+ }
4403
+ ));
4404
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
4405
+ var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4406
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
4407
+ {
4408
+ ref,
4409
+ orientation: "vertical",
4410
+ className: cn("flex h-full w-2 touch-none select-none transition-colors", className),
4411
+ ...props,
4412
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4413
+ ScrollAreaPrimitive.ScrollAreaThumb,
4414
+ {
4415
+ className: cn("relative flex-1 rounded-full bg-neutral-200/70 dark:bg-neutral-800")
4416
+ }
4417
+ )
4418
+ }
4419
+ ));
4420
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
4421
+
4422
+ // src/components/databrowser/components/sidebar/infinite-scroll.tsx
4423
+
4424
+ var InfiniteScroll = ({
4425
+ query,
4426
+ children
4427
+ }) => {
4428
+ const handleScroll = (e) => {
4429
+ const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
4430
+ if (scrollTop + clientHeight > scrollHeight - 100) {
4431
+ if (query.isFetching || !query.hasNextPage) {
4432
+ return;
4433
+ }
4434
+ query.fetchNextPage();
4435
+ }
4337
4436
  };
4338
4437
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4339
- Popover,
4438
+ ScrollArea,
4340
4439
  {
4341
- open,
4342
- onOpenChange: (isOpen) => {
4343
- if (isOpen) reset();
4344
- setOpen(isOpen);
4345
- },
4440
+ type: "always",
4441
+ className: "block h-full w-full transition-all",
4442
+ onScroll: handleScroll,
4346
4443
  children: [
4347
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { children }) }),
4348
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverContent, { className: "w-[300px]", align: "end", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "space-y-4", onSubmit, children: [
4349
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "font-medium leading-none", children: "Expiration" }),
4350
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
4351
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center", children: [
4352
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4353
- _reacthookform.Controller,
4354
- {
4355
- rules: {
4356
- required: "Please enter an expiration time",
4357
- min: { value: -1, message: "TTL can't be lower than -1" }
4358
- },
4359
- control,
4360
- name: "value",
4361
- render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Input, { min: "-1", ...field, className: "grow rounded-r-none" })
4362
- }
4363
- ),
4364
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4365
- _reacthookform.Controller,
4366
- {
4367
- control,
4368
- name: "type",
4369
- render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: field.value, onValueChange: field.onChange, children: [
4370
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "w-auto rounded-l-none border-l-0 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
4371
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: timeUnits.map((unit) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: unit.label, children: unit.label }, unit.label)) })
4372
- ] })
4373
- }
4374
- )
4375
- ] }),
4376
- formState.errors.value && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-red-500", children: formState.errors.value.message }),
4377
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-zinc-500", children: "TTL sets a timer to automatically delete keys after a defined period." })
4378
- ] }),
4379
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex justify-between", children: [
4380
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4381
- Button,
4382
- {
4383
- type: "button",
4384
- variant: "outline",
4385
- disabled: ttl === PERSISTED_KEY,
4386
- onClick: handlePersist,
4387
- children: "Persist"
4388
- }
4389
- ),
4390
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [
4391
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", onClick: () => setOpen(false), type: "button", children: "Cancel" }),
4392
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", type: "submit", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" }) })
4393
- ] })
4394
- ] })
4395
- ] }) })
4444
+ children,
4445
+ /* @__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 }) })
4396
4446
  ]
4397
4447
  }
4398
4448
  );
4399
- }
4449
+ };
4400
4450
 
4401
- // src/components/databrowser/components/display/header-badges.tsx
4451
+ // src/components/databrowser/components/display/display-header.tsx
4402
4452
 
4403
- var LengthBadge = ({
4404
- dataKey,
4405
- type,
4406
- content
4407
- }) => {
4408
- const { data, isLoading } = useFetchKeyLength({ dataKey, type });
4409
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _24 => _24.length]), () => ( data));
4410
- 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 });
4411
- };
4412
- var SizeBadge = ({ dataKey }) => {
4413
- const { data: size } = useFetchKeySize(dataKey);
4414
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label: "Size:", children: size === void 0 || size === null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : _bytes2.default.call(void 0, size, {
4415
- unitSeparator: " "
4416
- }) });
4417
- };
4418
- var TTL_INFINITE = -1;
4419
- var TTL_NOT_FOUND = -2;
4420
- var TTLBadge = ({ dataKey }) => {
4421
- const { data: ttl } = useFetchTTL(dataKey);
4422
- const { deleteKeyCache } = useDeleteKeyCache();
4423
- _react.useEffect.call(void 0, () => {
4424
- const interval = setInterval(() => {
4425
- queryClient.setQueryData([FETCH_TTL_QUERY_KEY, dataKey], (ttl2) => {
4426
- if (ttl2 === void 0 || ttl2 === TTL_INFINITE) return ttl2;
4427
- if (ttl2 <= 1) {
4428
- deleteKeyCache(dataKey);
4429
- return TTL_NOT_FOUND;
4430
- }
4431
- return ttl2 - 1;
4432
- });
4433
- }, 1e3);
4434
- return () => clearInterval(interval);
4435
- }, []);
4436
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label: "TTL:", children: ttl === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TTLPopover, { dataKey, ttl, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-[2px]", children: [
4437
- ttl === TTL_INFINITE ? "Forever" : formatTime(ttl),
4438
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
4439
- ] }) }) });
4453
+
4454
+ // src/components/databrowser/components/type-tag.tsx
4455
+
4456
+
4457
+
4458
+
4459
+
4460
+
4461
+
4462
+
4463
+
4464
+ var iconsMap = {
4465
+ string: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconQuote, { size: 15, stroke: 1.3 }),
4466
+ set: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLayersIntersect, { size: 15, stroke: 1.3 }),
4467
+ hash: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconHash, { size: 15, stroke: 1.3 }),
4468
+ json: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCodeDots, { size: 15, stroke: 1.3 }),
4469
+ zset: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconArrowsSort, { size: 15, stroke: 1.3 }),
4470
+ list: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.3 }),
4471
+ stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.3 })
4440
4472
  };
4441
- 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: [
4442
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: label }),
4443
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children })
4444
- ] });
4473
+ var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-center", {
4474
+ variants: {
4475
+ variant: {
4476
+ string: "bg-sky-200 text-sky-800",
4477
+ hash: "bg-amber-200 text-amber-800",
4478
+ set: "bg-indigo-200 text-indigo-800",
4479
+ zset: "bg-pink-200 text-pink-800",
4480
+ json: "bg-purple-200 text-purple-800",
4481
+ list: "bg-orange-200 text-orange-800",
4482
+ stream: "bg-green-200 text-green-800"
4483
+ },
4484
+ type: {
4485
+ icon: "size-5",
4486
+ badge: "h-6 px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4487
+ }
4488
+ },
4489
+ defaultVariants: {
4490
+ variant: "string",
4491
+ type: "icon"
4492
+ }
4493
+ });
4494
+ function TypeTag({ className, variant, type }) {
4495
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: cn(tagVariants({ variant, type, className })), children: type === "icon" ? iconsMap[variant] : DATA_TYPE_NAMES[variant] });
4496
+ }
4445
4497
 
4446
4498
  // src/components/databrowser/components/display/key-actions.tsx
4447
4499
 
@@ -4619,7 +4671,7 @@ var DisplayHeader = ({
4619
4671
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }),
4620
4672
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SizeBadge, { dataKey }),
4621
4673
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LengthBadge, { dataKey, type, content }),
4622
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TTLBadge, { dataKey })
4674
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderTTLBadge, { dataKey })
4623
4675
  ] })
4624
4676
  ] });
4625
4677
  };
@@ -4627,7 +4679,6 @@ var DisplayHeader = ({
4627
4679
  // src/components/databrowser/components/display/display-list-edit.tsx
4628
4680
 
4629
4681
 
4630
-
4631
4682
  // src/components/ui/tooltip.tsx
4632
4683
 
4633
4684
 
@@ -4658,6 +4709,78 @@ var SimpleTooltip = ({
4658
4709
  ] });
4659
4710
  };
4660
4711
 
4712
+ // src/components/databrowser/hooks/use-fetch-hash-ttl.ts
4713
+
4714
+ var FETCH_HASH_FIELD_TTLS_QUERY_KEY = "fetch-hash-field-ttls";
4715
+ var useFetchHashFieldExpires = ({
4716
+ dataKey,
4717
+ fields
4718
+ }) => {
4719
+ const { redis } = useDatabrowser();
4720
+ return _reactquery.useQuery.call(void 0, {
4721
+ queryKey: [FETCH_HASH_FIELD_TTLS_QUERY_KEY, dataKey, fields],
4722
+ queryFn: async () => {
4723
+ const cachedExpires = /* @__PURE__ */ new Map();
4724
+ for (const field of fields) {
4725
+ const expireAt = queryClient.getQueryData([
4726
+ FETCH_HASH_FIELD_TTLS_QUERY_KEY,
4727
+ dataKey,
4728
+ field
4729
+ ]);
4730
+ if (expireAt !== void 0) cachedExpires.set(field, expireAt);
4731
+ }
4732
+ const filteredFields = fields.filter((field) => !cachedExpires.has(field));
4733
+ if (filteredFields.length === 0) return Object.fromEntries(cachedExpires.entries());
4734
+ const res = await redis.httl(dataKey, filteredFields);
4735
+ const expireAts = res.map(
4736
+ (ttl) => ttl === TTL_INFINITE || ttl === TTL_NOT_FOUND ? ttl : Date.now() + ttl * 1e3
4737
+ );
4738
+ for (const [i, field] of filteredFields.entries()) {
4739
+ queryClient.setQueryData([FETCH_HASH_FIELD_TTLS_QUERY_KEY, dataKey, field], expireAts[i]);
4740
+ }
4741
+ const newExpiresArray = expireAts.map((expireAt, i) => [filteredFields[i], expireAt]);
4742
+ return Object.fromEntries([...cachedExpires.entries(), ...newExpiresArray]);
4743
+ }
4744
+ });
4745
+ };
4746
+
4747
+ // src/components/databrowser/hooks/use-set-hash-ttl.ts
4748
+
4749
+ var useSetHashTTL = () => {
4750
+ const { redis } = useDatabrowser();
4751
+ return _reactquery.useMutation.call(void 0, {
4752
+ mutationFn: async ({
4753
+ dataKey,
4754
+ field,
4755
+ ttl
4756
+ }) => {
4757
+ await (ttl === void 0 || ttl === TTL_INFINITE ? redis.hpersist(dataKey, field) : redis.hexpire(dataKey, field, ttl));
4758
+ },
4759
+ onSuccess: (_, { dataKey }) => {
4760
+ queryClient.removeQueries({
4761
+ queryKey: [FETCH_HASH_FIELD_TTLS_QUERY_KEY, dataKey]
4762
+ });
4763
+ }
4764
+ });
4765
+ };
4766
+
4767
+ // src/components/databrowser/components/display/hash/hash-field-ttl-badge.tsx
4768
+
4769
+ var HashFieldTTLBadge = ({ dataKey, field }) => {
4770
+ const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
4771
+ const { mutate: setTTL, isPending } = useSetHashTTL();
4772
+ const expireAt = _optionalChain([data, 'optionalAccess', _25 => _25[field]]);
4773
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4774
+ TTLBadge,
4775
+ {
4776
+ label: "Field TTL:",
4777
+ expireAt,
4778
+ setTTL: (ttl) => setTTL({ dataKey, field, ttl }),
4779
+ isPending
4780
+ }
4781
+ );
4782
+ };
4783
+
4661
4784
  // src/components/databrowser/components/display/input/use-field.tsx
4662
4785
 
4663
4786
 
@@ -4735,7 +4858,7 @@ var CustomEditor = ({
4735
4858
  if (!monaco || !editorRef.current) {
4736
4859
  return;
4737
4860
  }
4738
- _optionalChain([monaco, 'optionalAccess', _25 => _25.editor, 'access', _26 => _26.setModelLanguage, 'call', _27 => _27(editorRef.current.getModel(), language)]);
4861
+ _optionalChain([monaco, 'optionalAccess', _26 => _26.editor, 'access', _27 => _27.setModelLanguage, 'call', _28 => _28(editorRef.current.getModel(), language)]);
4739
4862
  }, [monaco, language]);
4740
4863
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4741
4864
  "div",
@@ -4816,12 +4939,15 @@ var useField = ({
4816
4939
  () => checkIsValidJSON(field.value) ? "JSON" : "Text"
4817
4940
  );
4818
4941
  _react.useEffect.call(void 0, () => {
4819
- if (!checkIsValidJSON(data)) {
4820
- return;
4942
+ if (contentType === "JSON" && checkIsValidJSON(data)) {
4943
+ form.setValue(name, formatJSON(data), {
4944
+ shouldDirty: false
4945
+ });
4946
+ } else {
4947
+ form.setValue(name, data, {
4948
+ shouldDirty: false
4949
+ });
4821
4950
  }
4822
- form.setValue(name, formatJSON(data), {
4823
- shouldDirty: false
4824
- });
4825
4951
  }, [data]);
4826
4952
  const handleTypeChange = (type) => {
4827
4953
  setContentType(type);
@@ -4879,7 +5005,7 @@ var ListEditForm = ({
4879
5005
  dataKey
4880
5006
  });
4881
5007
  const findValue = () => {
4882
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _28 => _28.data, 'optionalAccess', _29 => _29.pages]), () => ( []))) {
5008
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _29 => _29.data, 'optionalAccess', _30 => _30.pages]), () => ( []))) {
4883
5009
  const item = page.keys.find((item2) => item2.key === itemKey);
4884
5010
  if (item && "value" in item) return item.value;
4885
5011
  }
@@ -4892,12 +5018,6 @@ var ListEditForm = ({
4892
5018
  value: itemValue
4893
5019
  }
4894
5020
  });
4895
- _react.useEffect.call(void 0, () => {
4896
- form.reset({
4897
- key: itemKey,
4898
- value: itemValue
4899
- });
4900
- }, [itemKey, itemValue]);
4901
5021
  const { mutateAsync: editItem, isPending } = useEditListItem();
4902
5022
  const { setSelectedListItem } = useDatabrowserStore();
4903
5023
  const [keyLabel, valueLabel] = headerLabels[type];
@@ -4935,33 +5055,45 @@ var ListEditForm = ({
4935
5055
  }
4936
5056
  )
4937
5057
  ] }),
4938
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex justify-end gap-2", children: [
4939
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4940
- Button,
4941
- {
4942
- type: "button",
4943
- onClick: () => {
4944
- setSelectedListItem(void 0);
4945
- },
4946
- children: "Cancel"
4947
- }
4948
- ),
4949
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4950
- SimpleTooltip,
4951
- {
4952
- content: type === "stream" && !isNew ? "Streams are not mutable" : void 0,
4953
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4954
- Button,
4955
- {
4956
- variant: "primary",
4957
- type: "submit",
4958
- disabled: !form.formState.isValid || !form.formState.isDirty || type === "stream" && !isNew,
4959
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" })
4960
- }
4961
- )
4962
- }
4963
- )
4964
- ] })
5058
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5059
+ "div",
5060
+ {
5061
+ className: cn(
5062
+ "flex items-center",
5063
+ type === "hash" && itemKey !== "" ? "justify-between" : "justify-end"
5064
+ ),
5065
+ children: [
5066
+ type === "hash" && itemKey !== "" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HashFieldTTLBadge, { dataKey, field: itemKey }),
5067
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [
5068
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5069
+ Button,
5070
+ {
5071
+ type: "button",
5072
+ onClick: () => {
5073
+ setSelectedListItem(void 0);
5074
+ },
5075
+ children: "Cancel"
5076
+ }
5077
+ ),
5078
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5079
+ SimpleTooltip,
5080
+ {
5081
+ content: type === "stream" && !isNew ? "Streams are not mutable" : void 0,
5082
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5083
+ Button,
5084
+ {
5085
+ variant: "primary",
5086
+ type: "submit",
5087
+ disabled: !form.formState.isValid || !form.formState.isDirty || type === "stream" && !isNew,
5088
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: isPending, isLoadingText: "Saving", children: "Save" })
5089
+ }
5090
+ )
5091
+ }
5092
+ )
5093
+ ] })
5094
+ ]
5095
+ }
5096
+ )
4965
5097
  ] }) });
4966
5098
  };
4967
5099
  var NumberFormItem = ({ name, label }) => {
@@ -5010,6 +5142,28 @@ var FormItem = ({
5010
5142
  ] });
5011
5143
  };
5012
5144
 
5145
+ // src/components/databrowser/components/display/hash/hash-field-ttl-info.tsx
5146
+
5147
+
5148
+ var HashFieldTTLInfo = ({
5149
+ dataKey,
5150
+ field,
5151
+ fields
5152
+ }) => {
5153
+ const { data } = useFetchHashFieldExpires({ dataKey, fields });
5154
+ const expireAt = _optionalChain([data, 'optionalAccess', _31 => _31[field]]);
5155
+ const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
5156
+ _react.useEffect.call(void 0, () => {
5157
+ setTTL(calculateTTL(expireAt));
5158
+ const interval = setInterval(() => {
5159
+ setTTL(calculateTTL(expireAt));
5160
+ }, 1e3);
5161
+ return () => clearInterval(interval);
5162
+ }, [expireAt]);
5163
+ if (!expireAt || expireAt === TTL_NOT_FOUND || expireAt === TTL_INFINITE) return;
5164
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "block min-w-[30px] whitespace-nowrap text-right text-red-600", children: formatTime(_nullishCoalesce(ttl, () => ( 0))) });
5165
+ };
5166
+
5013
5167
  // src/components/databrowser/components/display/display-list.tsx
5014
5168
 
5015
5169
  var headerLabels = {
@@ -5034,7 +5188,8 @@ var ListItems = ({
5034
5188
  dataKey
5035
5189
  }) => {
5036
5190
  const { setSelectedListItem } = useDatabrowserStore();
5037
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _30 => _30.data, 'optionalAccess', _31 => _31.pages, 'access', _32 => _32.flatMap, 'call', _33 => _33((page) => page.keys)]), () => ( [])), [query.data]);
5191
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _32 => _32.data, 'optionalAccess', _33 => _33.pages, 'access', _34 => _34.flatMap, 'call', _35 => _35((page) => page.keys)]), () => ( [])), [query.data]);
5192
+ const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
5038
5193
  const { mutate: editItem } = useEditListItem();
5039
5194
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5040
5195
  "tr",
@@ -5044,7 +5199,7 @@ var ListItems = ({
5044
5199
  onClick: () => {
5045
5200
  setSelectedListItem({ key });
5046
5201
  },
5047
- className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
5202
+ className: cn("h-10 border-b border-b-zinc-100 hover:bg-zinc-100 "),
5048
5203
  children: [
5049
5204
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5050
5205
  "td",
@@ -5066,28 +5221,39 @@ var ListItems = ({
5066
5221
  type !== "stream" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5067
5222
  "td",
5068
5223
  {
5069
- width: 20,
5070
- className: "px-3",
5224
+ className: "w-0 min-w-0 p-0",
5071
5225
  onClick: (e) => {
5072
5226
  e.stopPropagation();
5073
5227
  },
5074
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5075
- DeleteAlertDialog,
5076
- {
5077
- deletionType: "item",
5078
- onDeleteConfirm: (e) => {
5079
- e.stopPropagation();
5080
- editItem({
5081
- type,
5082
- dataKey,
5083
- itemKey: key,
5084
- // For deletion
5085
- newKey: void 0
5086
- });
5087
- },
5088
- 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" }) })
5089
- }
5090
- )
5228
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-end gap-2", children: [
5229
+ type === "hash" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HashFieldTTLInfo, { dataKey, field: key, fields }),
5230
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5231
+ DeleteAlertDialog,
5232
+ {
5233
+ deletionType: "item",
5234
+ onDeleteConfirm: (e) => {
5235
+ e.stopPropagation();
5236
+ editItem({
5237
+ type,
5238
+ dataKey,
5239
+ itemKey: key,
5240
+ // For deletion
5241
+ newKey: void 0
5242
+ });
5243
+ },
5244
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5245
+ Button,
5246
+ {
5247
+ className: "",
5248
+ size: "icon-sm",
5249
+ variant: "secondary",
5250
+ onClick: (e) => e.stopPropagation(),
5251
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { className: "size-4 text-zinc-500" })
5252
+ }
5253
+ )
5254
+ }
5255
+ )
5256
+ ] })
5091
5257
  }
5092
5258
  )
5093
5259
  ]
@@ -5122,17 +5288,12 @@ var EditorDisplayForm = ({
5122
5288
  defaultValues: { value: data }
5123
5289
  });
5124
5290
  _react.useEffect.call(void 0, () => {
5125
- form.reset(
5126
- { value: data },
5127
- {
5128
- keepValues: false
5129
- }
5130
- );
5291
+ form.reset({ value: data });
5131
5292
  }, [data]);
5132
5293
  const { editor, selector } = useField({ name: "value", form, data });
5133
5294
  const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
5134
5295
  const handleCancel = () => {
5135
- form.reset();
5296
+ form.reset({ value: data });
5136
5297
  };
5137
5298
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5138
5299
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow flex-col gap-1", children: [
@@ -5292,7 +5453,7 @@ function AddKeyModal() {
5292
5453
  setSelectedKey(key);
5293
5454
  setOpen(false);
5294
5455
  setTimeout(() => {
5295
- _optionalChain([window, 'access', _34 => _34.document, 'access', _35 => _35.querySelector, 'call', _36 => _36(`[data-key="${key}"]`), 'optionalAccess', _37 => _37.scrollIntoView, 'call', _38 => _38({
5456
+ _optionalChain([window, 'access', _36 => _36.document, 'access', _37 => _37.querySelector, 'call', _38 => _38(`[data-key="${key}"]`), 'optionalAccess', _39 => _39.scrollIntoView, 'call', _40 => _40({
5296
5457
  behavior: "smooth",
5297
5458
  block: "start",
5298
5459
  inline: "nearest"
@@ -5337,7 +5498,7 @@ function AddKeyModal() {
5337
5498
  }
5338
5499
  )
5339
5500
  ] }),
5340
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _39 => _39.errors, 'access', _40 => _40.key, 'optionalAccess', _41 => _41.message]) }),
5501
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _41 => _41.errors, 'access', _42 => _42.key, 'optionalAccess', _43 => _43.message]) }),
5341
5502
  /* @__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" }),
5342
5503
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5343
5504
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5431,7 +5592,7 @@ var SidebarContextMenu = ({ children }) => {
5431
5592
 
5432
5593
  var KeysList = () => {
5433
5594
  const { keys } = useKeys();
5434
- 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', _42 => _42.at, 'call', _43 => _43(i + 1), 'optionalAccess', _44 => _44[0]]), () => ( "")), data }, data[0])) }) }) });
5595
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _44 => _44.at, 'call', _45 => _45(i + 1), 'optionalAccess', _46 => _46[0]]), () => ( "")), data }, data[0])) }) }) });
5435
5596
  };
5436
5597
  var keyStyles = {
5437
5598
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5496,7 +5657,7 @@ var SearchInput = () => {
5496
5657
  value: state
5497
5658
  }
5498
5659
  ),
5499
- search.key && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5660
+ state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5500
5661
  Button,
5501
5662
  {
5502
5663
  type: "button",
@@ -5505,6 +5666,7 @@ var SearchInput = () => {
5505
5666
  className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100",
5506
5667
  onClick: () => {
5507
5668
  setSearchKey("");
5669
+ setState("");
5508
5670
  },
5509
5671
  children: [
5510
5672
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
@@ -5573,6 +5735,9 @@ function Sidebar() {
5573
5735
  queryClient.invalidateQueries({
5574
5736
  queryKey: [FETCH_DB_SIZE_QUERY_KEY]
5575
5737
  });
5738
+ queryClient.invalidateQueries({
5739
+ queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
5740
+ });
5576
5741
  },
5577
5742
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: query.isFetching, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { size: 16 }) })
5578
5743
  }
@@ -5585,7 +5750,10 @@ function Sidebar() {
5585
5750
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
5586
5751
  ] })
5587
5752
  ] }),
5588
- query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {})
5753
+ query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
5754
+ // Infinite scroll already has a loader at the bottom
5755
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) })
5756
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {})
5589
5757
  ] });
5590
5758
  }
5591
5759