@upstash/react-redis-browser 0.1.6 → 0.1.8

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