@upstash/react-redis-browser 0.2.12 → 0.2.13-canary

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/dist/index.css +191 -149
  2. package/dist/index.js +1358 -576
  3. package/dist/index.mjs +1610 -828
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -193,7 +193,10 @@ var queryClient = new (0, _reactquery.QueryClient)({
193
193
  }
194
194
  },
195
195
  queryCache: new (0, _reactquery.QueryCache)({
196
- onError: handleError
196
+ onError: (error, query) => {
197
+ if (_optionalChain([query, 'access', _4 => _4.meta, 'optionalAccess', _5 => _5.hideToast])) return;
198
+ handleError(error);
199
+ }
197
200
  }),
198
201
  mutationCache: new (0, _reactquery.MutationCache)({
199
202
  onError: handleError
@@ -263,7 +266,7 @@ var DatabrowserProvider = ({
263
266
  removeItem: () => {
264
267
  }
265
268
  },
266
- version: 5,
269
+ version: 6,
267
270
  migrate: (originalState, version) => {
268
271
  const state = originalState;
269
272
  if (version <= 1) {
@@ -279,6 +282,19 @@ var DatabrowserProvider = ({
279
282
  ];
280
283
  });
281
284
  }
285
+ if (version <= 5) {
286
+ state.tabs = state.tabs.map(([id, data]) => {
287
+ const oldData = data;
288
+ return [
289
+ id,
290
+ {
291
+ ...data,
292
+ valuesSearch: _nullishCoalesce(oldData.valuesSearch, () => ( { index: "", query: "" })),
293
+ isValuesSearchSelected: _nullishCoalesce(oldData.isValuesSearchSelected, () => ( false))
294
+ }
295
+ ];
296
+ });
297
+ }
282
298
  return state;
283
299
  }
284
300
  })
@@ -310,6 +326,8 @@ var storeCreator = (set, get) => ({
310
326
  id,
311
327
  selectedKeys: [],
312
328
  search: { key: "", type: void 0 },
329
+ valuesSearch: { index: "", query: "" },
330
+ isValuesSearchSelected: false,
313
331
  pinned: false
314
332
  };
315
333
  set((old) => ({
@@ -402,7 +420,7 @@ var storeCreator = (set, get) => ({
402
420
  set({ selectedTab: id });
403
421
  },
404
422
  getSelectedKeys: (tabId) => {
405
- return _nullishCoalesce(_optionalChain([get, 'call', _4 => _4(), 'access', _5 => _5.tabs, 'access', _6 => _6.find, 'call', _7 => _7(([id]) => id === tabId), 'optionalAccess', _8 => _8[1], 'optionalAccess', _9 => _9.selectedKeys]), () => ( []));
423
+ return _nullishCoalesce(_optionalChain([get, 'call', _6 => _6(), 'access', _7 => _7.tabs, 'access', _8 => _8.find, 'call', _9 => _9(([id]) => id === tabId), 'optionalAccess', _10 => _10[1], 'optionalAccess', _11 => _11.selectedKeys]), () => ( []));
406
424
  },
407
425
  setSelectedKey: (tabId, key) => {
408
426
  get().setSelectedKeys(tabId, key ? [key] : []);
@@ -469,6 +487,58 @@ var storeCreator = (set, get) => ({
469
487
  return { ...old, tabs: newTabs };
470
488
  });
471
489
  },
490
+ setValuesSearch: (tabId, valuesSearch) => {
491
+ set((old) => {
492
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
493
+ if (tabIndex === -1) return old;
494
+ const newTabs = [...old.tabs];
495
+ const [, tabData] = newTabs[tabIndex];
496
+ newTabs[tabIndex] = [tabId, { ...tabData, valuesSearch }];
497
+ return { ...old, tabs: newTabs };
498
+ });
499
+ },
500
+ setValuesSearchIndex: (tabId, index) => {
501
+ set((old) => {
502
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
503
+ if (tabIndex === -1) return old;
504
+ const newTabs = [...old.tabs];
505
+ const [, tabData] = newTabs[tabIndex];
506
+ newTabs[tabIndex] = [
507
+ tabId,
508
+ {
509
+ ...tabData,
510
+ valuesSearch: { ...tabData.valuesSearch, index }
511
+ }
512
+ ];
513
+ return { ...old, tabs: newTabs };
514
+ });
515
+ },
516
+ setValuesSearchQuery: (tabId, query) => {
517
+ set((old) => {
518
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
519
+ if (tabIndex === -1) return old;
520
+ const newTabs = [...old.tabs];
521
+ const [, tabData] = newTabs[tabIndex];
522
+ newTabs[tabIndex] = [
523
+ tabId,
524
+ {
525
+ ...tabData,
526
+ valuesSearch: { ...tabData.valuesSearch, query }
527
+ }
528
+ ];
529
+ return { ...old, tabs: newTabs };
530
+ });
531
+ },
532
+ setIsValuesSearchSelected: (tabId, isSelected) => {
533
+ set((old) => {
534
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
535
+ if (tabIndex === -1) return old;
536
+ const newTabs = [...old.tabs];
537
+ const [, tabData] = newTabs[tabIndex];
538
+ newTabs[tabIndex] = [tabId, { ...tabData, isValuesSearchSelected: isSelected }];
539
+ return { ...old, tabs: newTabs };
540
+ });
541
+ },
472
542
  searchHistory: [],
473
543
  addSearchHistory: (key) => {
474
544
  set((old) => ({ ...old, searchHistory: [key, ...old.searchHistory] }));
@@ -498,27 +568,37 @@ var useTab = () => {
498
568
  setSelectedListItem,
499
569
  setSearch,
500
570
  setSearchKey,
501
- setSearchType
571
+ setSearchType,
572
+ setValuesSearch,
573
+ setValuesSearchIndex,
574
+ setValuesSearchQuery,
575
+ setIsValuesSearchSelected
502
576
  } = useDatabrowserStore();
503
577
  const tabId = useTabId();
504
- const tabData = _react.useMemo.call(void 0, () => _optionalChain([tabs, 'access', _10 => _10.find, 'call', _11 => _11(([id]) => id === tabId), 'optionalAccess', _12 => _12[1]]), [tabs, tabId]);
578
+ const tabData = _react.useMemo.call(void 0, () => _optionalChain([tabs, 'access', _12 => _12.find, 'call', _13 => _13(([id]) => id === tabId), 'optionalAccess', _14 => _14[1]]), [tabs, tabId]);
505
579
  if (!selectedTab) throw new Error("selectedTab is undefined when using useTab()");
506
580
  if (!tabData) throw new Error("tabData is undefined when using useTab()");
507
581
  return _react.useMemo.call(void 0,
508
582
  () => ({
509
583
  active: selectedTab === tabId,
510
- selectedKey: _optionalChain([tabData, 'access', _13 => _13.selectedKeys, 'optionalAccess', _14 => _14[0]]),
584
+ selectedKey: _optionalChain([tabData, 'access', _15 => _15.selectedKeys, 'optionalAccess', _16 => _16[0]]),
511
585
  // Backwards compatibility - first selected key
512
586
  selectedKeys: _nullishCoalesce(tabData.selectedKeys, () => ( [])),
513
587
  selectedListItem: tabData.selectedListItem,
514
588
  search: tabData.search,
589
+ valuesSearch: tabData.valuesSearch,
590
+ isValuesSearchSelected: tabData.isValuesSearchSelected,
515
591
  pinned: tabData.pinned,
516
592
  setSelectedKey: (key) => setSelectedKey(tabId, key),
517
593
  setSelectedKeys: (keys) => setSelectedKeys(tabId, keys),
518
594
  setSelectedListItem: (item) => setSelectedListItem(tabId, item),
519
595
  setSearch: (search) => setSearch(tabId, search),
520
596
  setSearchKey: (key) => setSearchKey(tabId, key),
521
- setSearchType: (type) => setSearchType(tabId, type)
597
+ setSearchType: (type) => setSearchType(tabId, type),
598
+ setValuesSearch: (search) => setValuesSearch(tabId, search),
599
+ setValuesSearchIndex: (index) => setValuesSearchIndex(tabId, index),
600
+ setValuesSearchQuery: (query) => setValuesSearchQuery(tabId, query),
601
+ setIsValuesSearchSelected: (isSelected) => setIsValuesSearchSelected(tabId, isSelected)
522
602
  }),
523
603
  [selectedTab, tabs, tabId]
524
604
  );
@@ -603,15 +683,15 @@ var getGroupRecursive = (classParts, classPartObject) => {
603
683
  return void 0;
604
684
  }
605
685
  const classRest = classParts.join(CLASS_PART_SEPARATOR);
606
- return _optionalChain([classPartObject, 'access', _15 => _15.validators, 'access', _16 => _16.find, 'call', _17 => _17(({
686
+ return _optionalChain([classPartObject, 'access', _17 => _17.validators, 'access', _18 => _18.find, 'call', _19 => _19(({
607
687
  validator
608
- }) => validator(classRest)), 'optionalAccess', _18 => _18.classGroupId]);
688
+ }) => validator(classRest)), 'optionalAccess', _20 => _20.classGroupId]);
609
689
  };
610
690
  var arbitraryPropertyRegex = /^\[(.+)\]$/;
611
691
  var getGroupIdForArbitraryProperty = (className) => {
612
692
  if (arbitraryPropertyRegex.test(className)) {
613
693
  const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
614
- const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _19 => _19.substring, 'call', _20 => _20(0, arbitraryPropertyClassName.indexOf(":"))]);
694
+ const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _21 => _21.substring, 'call', _22 => _22(0, arbitraryPropertyClassName.indexOf(":"))]);
615
695
  if (property) {
616
696
  return "arbitrary.." + property;
617
697
  }
@@ -3026,9 +3106,14 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
3026
3106
  function cn(...inputs) {
3027
3107
  return twMerge(clsx(inputs));
3028
3108
  }
3029
- function formatNumber(value) {
3030
- const intl = new Intl.NumberFormat("en-US");
3031
- return intl.format(value);
3109
+ function parseJSObjectLiteral(value) {
3110
+ try {
3111
+ let jsonified = value.replaceAll(/([,{]\s*)(\$?[A-Z_a-z]\w*)\s*:/g, '$1"$2":');
3112
+ jsonified = jsonified.replaceAll(/,\s*([\]}])/g, "$1");
3113
+ return JSON.parse(jsonified);
3114
+ } catch (e3) {
3115
+ return;
3116
+ }
3032
3117
  }
3033
3118
  var units = {
3034
3119
  year: 24 * 60 * 60 * 1e3 * 365,
@@ -3062,8 +3147,8 @@ var _reactportal = require('@radix-ui/react-portal');
3062
3147
 
3063
3148
  // src/components/ui/toast.tsx
3064
3149
 
3065
- var _iconsreact = require('@tabler/icons-react');
3066
3150
  var _reacttoast = require('@radix-ui/react-toast'); var ToastPrimitives = _interopRequireWildcard(_reacttoast);
3151
+ var _iconsreact = require('@tabler/icons-react');
3067
3152
 
3068
3153
  // node_modules/class-variance-authority/node_modules/clsx/dist/clsx.mjs
3069
3154
  function r2(e) {
@@ -3242,15 +3327,39 @@ var useFetchKeyType = (key) => {
3242
3327
  });
3243
3328
  };
3244
3329
 
3330
+ // src/components/databrowser/hooks/use-fetch-search-index.tsx
3331
+
3332
+ var FETCH_SEARCH_INDEX_QUERY_KEY = "fetch-search-index";
3333
+ var useFetchSearchIndex = (indexName) => {
3334
+ const { redisNoPipeline: redis } = useRedis();
3335
+ return _reactquery.useQuery.call(void 0, {
3336
+ queryKey: [FETCH_SEARCH_INDEX_QUERY_KEY, indexName],
3337
+ queryFn: async () => {
3338
+ if (!indexName) return;
3339
+ const result = await redis.search.index(indexName).describe();
3340
+ return result;
3341
+ },
3342
+ enabled: Boolean(indexName)
3343
+ });
3344
+ };
3345
+
3245
3346
  // src/components/databrowser/hooks/use-keys.tsx
3246
3347
 
3247
3348
  var KeysContext = _react.createContext.call(void 0, void 0);
3248
3349
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
3249
3350
  var SCAN_COUNTS = [100, 300, 500];
3250
3351
  var KeysProvider = ({ children }) => {
3251
- const { active, search } = useTab();
3352
+ const { active, search, valuesSearch, isValuesSearchSelected } = useTab();
3353
+ const { data: searchIndexDetails, isLoading: isIndexDetailsLoading } = useFetchSearchIndex(
3354
+ valuesSearch.index
3355
+ );
3252
3356
  const { redisNoPipeline: redis } = useRedis();
3253
- const performScan = async (count2, cursor) => {
3357
+ const parsedValueQuery = parseJSObjectLiteral(valuesSearch.query);
3358
+ const isQueryEnabled = active && (isValuesSearchSelected ? Boolean(valuesSearch.index) && Boolean(searchIndexDetails) : true);
3359
+ const redisKeyScan = async ({
3360
+ count: count2,
3361
+ cursor
3362
+ }) => {
3254
3363
  const args = [cursor];
3255
3364
  if (search.key) {
3256
3365
  args.push("MATCH", search.key);
@@ -3260,7 +3369,46 @@ var KeysProvider = ({ children }) => {
3260
3369
  }
3261
3370
  args.push("COUNT", count2.toString());
3262
3371
  if (!search.type) args.push("WITHTYPE");
3263
- return await redis.exec(["SCAN", ...args]);
3372
+ const [newCursor, values] = await redis.exec(["SCAN", ...args]);
3373
+ const keys2 = [];
3374
+ let index = 0;
3375
+ while (true) {
3376
+ if (search.type) {
3377
+ if (index >= values.length) break;
3378
+ keys2.push({ key: values[index], type: search.type });
3379
+ index += 1;
3380
+ } else {
3381
+ if (index + 1 >= values.length) break;
3382
+ keys2.push({ key: values[index], type: values[index + 1] });
3383
+ index += 2;
3384
+ }
3385
+ }
3386
+ return { cursor: newCursor, keys: keys2 };
3387
+ };
3388
+ const redisValueScan = async ({
3389
+ count: count2,
3390
+ cursor
3391
+ }) => {
3392
+ if (!searchIndexDetails) throw new Error("Attempted search while loading the search index");
3393
+ const offset = Number.parseInt(cursor, 10) || 0;
3394
+ const result = await redis.search.index(valuesSearch.index).query({
3395
+ filter: _nullishCoalesce(parsedValueQuery, () => ( {})),
3396
+ limit: count2,
3397
+ offset,
3398
+ select: {}
3399
+ });
3400
+ const keys2 = result.map((doc) => ({
3401
+ key: doc.key,
3402
+ type: searchIndexDetails.dataType
3403
+ }));
3404
+ const hasMore = keys2.length >= count2;
3405
+ const nextCursor = hasMore ? String(offset + keys2.length) : "0";
3406
+ return { cursor: nextCursor, keys: keys2 };
3407
+ };
3408
+ const performScan = async (count2, cursor) => {
3409
+ const scanFunction = isValuesSearchSelected ? redisValueScan : redisKeyScan;
3410
+ const result = await scanFunction({ count: count2, cursor });
3411
+ return [result.cursor, result.keys];
3264
3412
  };
3265
3413
  const scanUntilAvailable = async (cursor) => {
3266
3414
  let i = 0;
@@ -3274,25 +3422,12 @@ var KeysProvider = ({ children }) => {
3274
3422
  }
3275
3423
  };
3276
3424
  const query = _reactquery.useInfiniteQuery.call(void 0, {
3277
- queryKey: [FETCH_KEYS_QUERY_KEY, search],
3278
- // Only fetch when tab is active
3279
- enabled: active,
3425
+ queryKey: [FETCH_KEYS_QUERY_KEY, search, valuesSearch, isValuesSearchSelected],
3426
+ enabled: isQueryEnabled,
3280
3427
  initialPageParam: "0",
3281
3428
  queryFn: async ({ pageParam: lastCursor }) => {
3282
3429
  const [cursor, values] = await scanUntilAvailable(lastCursor);
3283
- const keys2 = [];
3284
- let index = 0;
3285
- while (true) {
3286
- if (search.type) {
3287
- if (index >= values.length) break;
3288
- keys2.push([values[index], search.type]);
3289
- index += 1;
3290
- } else {
3291
- if (index + 1 >= values.length) break;
3292
- keys2.push([values[index], values[index + 1]]);
3293
- index += 2;
3294
- }
3295
- }
3430
+ const keys2 = values.map((value) => [value.key, value.type]);
3296
3431
  for (const [key, type] of keys2) {
3297
3432
  queryClient.setQueryData([FETCH_KEY_TYPE_QUERY_KEY, key], type);
3298
3433
  }
@@ -3302,12 +3437,15 @@ var KeysProvider = ({ children }) => {
3302
3437
  hasNextPage: cursor !== "0"
3303
3438
  };
3304
3439
  },
3440
+ meta: {
3441
+ hideToast: true
3442
+ },
3305
3443
  select: (data) => data,
3306
3444
  getNextPageParam: ({ cursor }) => cursor,
3307
3445
  refetchOnMount: false
3308
3446
  });
3309
3447
  const keys = _react.useMemo.call(void 0, () => {
3310
- const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _21 => _21.data, 'optionalAccess', _22 => _22.pages, 'access', _23 => _23.flatMap, 'call', _24 => _24((page) => page.keys)]), () => ( []));
3448
+ const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _23 => _23.data, 'optionalAccess', _24 => _24.pages, 'access', _25 => _25.flatMap, 'call', _26 => _26((page) => page.keys)]), () => ( []));
3311
3449
  const keysSet = /* @__PURE__ */ new Set();
3312
3450
  const dedupedKeys = [];
3313
3451
  for (const key of keys2) {
@@ -3322,7 +3460,10 @@ var KeysProvider = ({ children }) => {
3322
3460
  {
3323
3461
  value: {
3324
3462
  keys,
3325
- query
3463
+ query: {
3464
+ ...query,
3465
+ isLoading: query.isLoading || isIndexDetailsLoading
3466
+ }
3326
3467
  },
3327
3468
  children
3328
3469
  }
@@ -3338,7 +3479,7 @@ var useKeys = () => {
3338
3479
  var useKeyType = (key) => {
3339
3480
  const { keys } = useKeys();
3340
3481
  const keyTuple = _react.useMemo.call(void 0, () => keys.find(([k, _]) => k === key), [keys, key]);
3341
- return _optionalChain([keyTuple, 'optionalAccess', _25 => _25[1]]);
3482
+ return _optionalChain([keyTuple, 'optionalAccess', _27 => _27[1]]);
3342
3483
  };
3343
3484
 
3344
3485
  // src/components/databrowser/components/display/display-list.tsx
@@ -3350,24 +3491,24 @@ var useKeyType = (key) => {
3350
3491
  var _reactslot = require('@radix-ui/react-slot');
3351
3492
 
3352
3493
  var buttonVariants = cva(
3353
- "inline-flex items-center justify-center rounded-md text-sm ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
3494
+ "inline-flex items-center justify-center rounded-lg text-sm shadow-[0_1px_1px_0_rgba(0,0,0,0.10)]ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-zinc-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
3354
3495
  {
3355
3496
  variants: {
3356
3497
  variant: {
3357
- default: "bg-white text-black border shadow-sm border-zinc-300 hover:bg-white/70",
3498
+ default: "bg-white text-black border border-zinc-300 hover:bg-white/70",
3358
3499
  destructive: "bg-red-500 text-zinc-50 hover:bg-red-500/90",
3359
- outline: "border border-zinc-200 bg-white hover:bg-zinc-100 hover:text-zinc-900",
3360
- primary: "bg-emerald-500 text-white shadow-sm hover:bg-emerald-600",
3500
+ outline: "border border-zinc-300 bg-white hover:bg-zinc-100 hover:text-zinc-900",
3501
+ primary: "bg-emerald-500 text-white hover:bg-emerald-600",
3361
3502
  secondary: "bg-zinc-100 text-zinc-900 hover:bg-zinc-100/80",
3362
3503
  ghost: "hover:bg-black/10",
3363
3504
  link: "text-zinc-900 underline-offset-4 hover:underline"
3364
3505
  },
3365
3506
  size: {
3366
3507
  default: "h-8 px-4 py-2",
3367
- sm: "px-2 h-7 rounded-md",
3508
+ sm: "px-2 h-[26px] rounded-md",
3368
3509
  lg: "h-10 px-8 rounded-md",
3369
3510
  icon: "h-8 w-8",
3370
- "icon-sm": "h-7 w-7",
3511
+ "icon-sm": "h-[26px] w-[26px] rounded-md",
3371
3512
  "icon-xs": "h-5 w-5"
3372
3513
  }
3373
3514
  },
@@ -3387,37 +3528,6 @@ Button.displayName = "Button";
3387
3528
 
3388
3529
  // src/components/databrowser/hooks/use-add-key.ts
3389
3530
 
3390
-
3391
- // src/components/databrowser/components/sidebar/db-size.tsx
3392
-
3393
-
3394
- // src/components/ui/skeleton.tsx
3395
-
3396
- function Skeleton({ className, ...props }) {
3397
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse rounded-md bg-zinc-900/10", className), ...props });
3398
- }
3399
-
3400
- // src/components/databrowser/components/sidebar/db-size.tsx
3401
-
3402
- var FETCH_DB_SIZE_QUERY_KEY = "fetch-db-size";
3403
- var DisplayDbSize = () => {
3404
- const { redis } = useRedis();
3405
- const { data: keyCount } = _reactquery.useQuery.call(void 0, {
3406
- queryKey: [FETCH_DB_SIZE_QUERY_KEY],
3407
- queryFn: async () => {
3408
- return await redis.dbsize();
3409
- }
3410
- });
3411
- if (keyCount === void 0) {
3412
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center gap-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-10 rounded" }) });
3413
- }
3414
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "", children: [
3415
- formatNumber(keyCount),
3416
- " Keys"
3417
- ] });
3418
- };
3419
-
3420
- // src/components/databrowser/hooks/use-add-key.ts
3421
3531
  var useAddKey = () => {
3422
3532
  const { redis } = useRedis();
3423
3533
  const mutation = _reactquery.useMutation.call(void 0, {
@@ -3467,9 +3577,6 @@ var useAddKey = () => {
3467
3577
  }
3468
3578
  },
3469
3579
  onSuccess: (_, { key, type }) => {
3470
- queryClient.invalidateQueries({
3471
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3472
- });
3473
3580
  queryClient.setQueriesData(
3474
3581
  {
3475
3582
  queryKey: [FETCH_KEYS_QUERY_KEY]
@@ -3582,7 +3689,7 @@ var useFetchListItems = ({ dataKey, type }) => {
3582
3689
  // +1 since first message is the last one
3583
3690
  LIST_DISPLAY_PAGE_SIZE + 1
3584
3691
  );
3585
- const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _26 => _26.at, 'call', _27 => _27(-1), 'optionalAccess', _28 => _28[0]]) : void 0;
3692
+ const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _28 => _28.at, 'call', _29 => _29(-1), 'optionalAccess', _30 => _30[0]]) : void 0;
3586
3693
  return {
3587
3694
  cursor: messages.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastMessageId,
3588
3695
  keys: messages.map(([id, fields]) => ({
@@ -3677,9 +3784,6 @@ var useDeleteKey = () => {
3677
3784
  },
3678
3785
  onSuccess: (_, key) => {
3679
3786
  deleteKeyCache(key);
3680
- queryClient.invalidateQueries({
3681
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3682
- });
3683
3787
  }
3684
3788
  });
3685
3789
  return deleteKey;
@@ -3746,7 +3850,7 @@ var useEditListItem = () => {
3746
3850
  }
3747
3851
  case "stream": {
3748
3852
  if (!isNew || !newKey) throw new Error("Stream data type is not mutable");
3749
- const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _29 => _29.split, 'call', _30 => _30("\n")]), () => ( []))).map(
3853
+ const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _31 => _31.split, 'call', _32 => _32("\n")]), () => ( []))).map(
3750
3854
  ({ key, value }) => [key, value]
3751
3855
  );
3752
3856
  pipe.xadd(dataKey, newKey, Object.fromEntries(opts));
@@ -3774,6 +3878,12 @@ var useEditListItem = () => {
3774
3878
 
3775
3879
 
3776
3880
 
3881
+ // src/components/ui/skeleton.tsx
3882
+
3883
+ function Skeleton({ className, ...props }) {
3884
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse rounded-md bg-zinc-900/10", className), ...props });
3885
+ }
3886
+
3777
3887
  // src/components/databrowser/components/display/header-badges.tsx
3778
3888
  var _bytes = require('bytes'); var _bytes2 = _interopRequireDefault(_bytes);
3779
3889
 
@@ -3801,6 +3911,9 @@ var useFetchKeyLength = ({ dataKey, type }) => {
3801
3911
  case "stream": {
3802
3912
  return await redis.xlen(dataKey);
3803
3913
  }
3914
+ case "search": {
3915
+ return null;
3916
+ }
3804
3917
  }
3805
3918
  return null;
3806
3919
  }
@@ -3828,7 +3941,7 @@ var LengthBadge = ({
3828
3941
  content
3829
3942
  }) => {
3830
3943
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3831
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _31 => _31.length]), () => ( data));
3944
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _33 => _33.length]), () => ( data));
3832
3945
  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 });
3833
3946
  };
3834
3947
  var SizeBadge = ({ dataKey }) => {
@@ -3849,8 +3962,8 @@ var HeaderTTLBadge = ({ dataKey }) => {
3849
3962
  }
3850
3963
  );
3851
3964
  };
3852
- var Badge = ({ children, label }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-6 items-center gap-0.5 rounded-md bg-white px-2 text-xs text-zinc-700 dark:bg-zinc-200", children: [
3853
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500 dark:text-zinc-600", children: label }),
3965
+ var Badge = ({ children, label }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-[26px] items-center gap-0.5 whitespace-nowrap rounded-md bg-zinc-200 px-2 text-xs text-zinc-700 dark:bg-zinc-200", children: [
3966
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500 dark:text-zinc-500", children: label }),
3854
3967
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children })
3855
3968
  ] });
3856
3969
 
@@ -3912,7 +4025,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
3912
4025
  {
3913
4026
  ref,
3914
4027
  className: cn(
3915
- "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",
4028
+ "relative flex h-8 w-full items-center justify-between rounded-lg border border-zinc-200 bg-white px-3 py-2 font-medium text-zinc-950 text-sm ring-offset-white placeholder:text-zinc-500 focus:ring-zinc-950 disabled:cursor-not-allowed disabled:opacity-50",
3916
4029
  className
3917
4030
  ),
3918
4031
  ...props,
@@ -3986,7 +4099,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
3986
4099
  ),
3987
4100
  ...props,
3988
4101
  children: [
3989
- /* @__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,
4102
+ /* @__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,
3990
4103
  "svg",
3991
4104
  {
3992
4105
  width: "15",
@@ -4005,7 +4118,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
4005
4118
  }
4006
4119
  )
4007
4120
  }
4008
- ) }) }) }),
4121
+ ) }) }),
4009
4122
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children })
4010
4123
  ]
4011
4124
  }
@@ -4180,9 +4293,9 @@ var TTLBadge = ({
4180
4293
  }, 1e3);
4181
4294
  return () => clearInterval(interval);
4182
4295
  }, [expireAt]);
4183
- 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: [
4184
- ttl === TTL_INFINITE ? "Forever" : formatTime(ttl),
4185
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
4296
+ 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 items-center gap-[2px]", children: [
4297
+ ttl === TTL_INFINITE ? "No" : formatTime(ttl),
4298
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "shrink-0 text-zinc-400", size: 16 })
4186
4299
  ] }) }) });
4187
4300
  };
4188
4301
 
@@ -4252,9 +4365,9 @@ var useSetTTL = () => {
4252
4365
 
4253
4366
  // src/components/databrowser/components/item-context-menu.tsx
4254
4367
 
4255
-
4256
4368
  var _reactcontextmenu = require('@radix-ui/react-context-menu'); var ContextMenuPrimitive = _interopRequireWildcard(_reactcontextmenu);
4257
4369
 
4370
+
4258
4371
  // src/components/ui/context-menu.tsx
4259
4372
 
4260
4373
 
@@ -4466,7 +4579,8 @@ function DeleteAlertDialog({
4466
4579
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
4467
4580
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: isPlural ? `Delete ${count2} ${itemsLabel}` : `Delete ${itemLabel}` }),
4468
4581
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
4469
- "Are you sure you want to delete ",
4582
+ "Are you sure you want to delete",
4583
+ " ",
4470
4584
  isPlural ? `these ${count2} ${deletionType}s` : `this ${deletionType}`,
4471
4585
  "?",
4472
4586
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
@@ -4512,7 +4626,7 @@ var ItemContextMenu = ({
4512
4626
  editItem({
4513
4627
  type,
4514
4628
  dataKey,
4515
- itemKey: _optionalChain([data, 'optionalAccess', _32 => _32.key]),
4629
+ itemKey: _optionalChain([data, 'optionalAccess', _34 => _34.key]),
4516
4630
  // For deletion
4517
4631
  newKey: void 0
4518
4632
  });
@@ -4547,7 +4661,7 @@ var ItemContextMenu = ({
4547
4661
  {
4548
4662
  onClick: () => {
4549
4663
  if (!data) return;
4550
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _33 => _33.key]));
4664
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _35 => _35.key]));
4551
4665
  toast({
4552
4666
  description: "Key copied to clipboard"
4553
4667
  });
@@ -4559,11 +4673,11 @@ var ItemContextMenu = ({
4559
4673
  ]
4560
4674
  }
4561
4675
  ),
4562
- _optionalChain([data, 'optionalAccess', _34 => _34.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4676
+ _optionalChain([data, 'optionalAccess', _36 => _36.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4563
4677
  ContextMenuItem,
4564
4678
  {
4565
4679
  onClick: () => {
4566
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _35 => _35.value]), () => ( "")));
4680
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _37 => _37.value]), () => ( "")));
4567
4681
  toast({
4568
4682
  description: "Value copied to clipboard"
4569
4683
  });
@@ -4620,33 +4734,38 @@ var ItemContextMenu = ({
4620
4734
 
4621
4735
  var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
4622
4736
 
4623
- var ScrollArea = React9.forwardRef(({ className, children, onScroll, disableRoundedInherit = false, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4624
- ScrollAreaPrimitive.Root,
4625
- {
4626
- ref,
4627
- className: cn("relative overflow-hidden", className),
4628
- ...props,
4629
- children: [
4630
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4631
- ScrollAreaPrimitive.Viewport,
4632
- {
4633
- onScroll,
4634
- className: cn("h-full w-full [&>div]:!block", !disableRoundedInherit && "rounded-[inherit]"),
4635
- children
4636
- }
4637
- ),
4638
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, {}),
4639
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4640
- ]
4641
- }
4642
- ));
4737
+ var ScrollArea = React9.forwardRef(
4738
+ ({ className, scrollBarClassName, children, onScroll, disableRoundedInherit = false, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4739
+ ScrollAreaPrimitive.Root,
4740
+ {
4741
+ ref,
4742
+ className: cn("relative overflow-hidden", className),
4743
+ ...props,
4744
+ children: [
4745
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4746
+ ScrollAreaPrimitive.Viewport,
4747
+ {
4748
+ onScroll,
4749
+ className: cn(
4750
+ "h-full w-full [&>div]:!block",
4751
+ !disableRoundedInherit && "rounded-[inherit]"
4752
+ ),
4753
+ children
4754
+ }
4755
+ ),
4756
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, { className: scrollBarClassName }),
4757
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4758
+ ]
4759
+ }
4760
+ )
4761
+ );
4643
4762
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
4644
4763
  var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4645
4764
  ScrollAreaPrimitive.ScrollAreaScrollbar,
4646
4765
  {
4647
4766
  ref,
4648
4767
  orientation: "vertical",
4649
- className: cn("flex h-full w-2 touch-none select-none transition-colors", className),
4768
+ className: cn("mr-1 flex h-full w-2 touch-none select-none transition-colors", className),
4650
4769
  ...props,
4651
4770
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4652
4771
  ScrollAreaPrimitive.ScrollAreaThumb,
@@ -4697,10 +4816,7 @@ var InfiniteScroll = ({
4697
4816
  type: "always",
4698
4817
  onScroll: handleScroll,
4699
4818
  ...props,
4700
- className: cn(
4701
- "block h-full w-full overflow-visible rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all",
4702
- props.className
4703
- ),
4819
+ className: cn("block h-full w-full overflow-visible transition-all", props.className),
4704
4820
  ref: scrollRef,
4705
4821
  children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref: contentRef, children: [
4706
4822
  children,
@@ -4744,7 +4860,16 @@ var SimpleTooltip = ({
4744
4860
  };
4745
4861
 
4746
4862
  // src/types/index.ts
4747
- var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
4863
+ var DATA_TYPES = [
4864
+ "string",
4865
+ "list",
4866
+ "hash",
4867
+ "set",
4868
+ "zset",
4869
+ "json",
4870
+ "stream",
4871
+ "search"
4872
+ ];
4748
4873
  var DATA_TYPE_NAMES = {
4749
4874
  string: "String",
4750
4875
  list: "List",
@@ -4752,7 +4877,8 @@ var DATA_TYPE_NAMES = {
4752
4877
  set: "Set",
4753
4878
  zset: "Sorted Set",
4754
4879
  json: "JSON",
4755
- stream: "Stream"
4880
+ stream: "Stream",
4881
+ search: "Search Index"
4756
4882
  };
4757
4883
 
4758
4884
  // src/components/databrowser/components/type-tag.tsx
@@ -4765,6 +4891,7 @@ var DATA_TYPE_NAMES = {
4765
4891
 
4766
4892
 
4767
4893
 
4894
+
4768
4895
  var iconsMap = {
4769
4896
  string: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconQuote, { size: 15, stroke: 1.2 }),
4770
4897
  set: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLayersIntersect, { size: 15, stroke: 1.2 }),
@@ -4772,7 +4899,8 @@ var iconsMap = {
4772
4899
  json: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCodeDots, { size: 15, stroke: 1.2 }),
4773
4900
  zset: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconArrowsSort, { size: 15, stroke: 1.2 }),
4774
4901
  list: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 }),
4775
- stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 })
4902
+ stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 }),
4903
+ search: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 15, stroke: 1.2 })
4776
4904
  };
4777
4905
  var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-center", {
4778
4906
  variants: {
@@ -4783,11 +4911,12 @@ var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-cent
4783
4911
  zset: "bg-pink-200 text-pink-800",
4784
4912
  json: "bg-purple-200 text-purple-800",
4785
4913
  list: "bg-orange-200 text-orange-800",
4786
- stream: "bg-green-200 text-green-800"
4914
+ stream: "bg-green-200 text-green-800",
4915
+ search: "bg-rose-200 text-rose-800"
4787
4916
  },
4788
4917
  type: {
4789
4918
  icon: "size-5",
4790
- badge: "h-6 px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4919
+ badge: "h-[26px] px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4791
4920
  }
4792
4921
  },
4793
4922
  defaultVariants: {
@@ -4926,7 +5055,13 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4926
5055
  function KeyActions({ dataKey, content }) {
4927
5056
  const { mutateAsync: deleteKey } = useDeleteKey();
4928
5057
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { modal: false, children: [
4929
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", "aria-label": "Key actions", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDotsVertical, { className: "size-4 text-zinc-500 dark:text-zinc-600" }) }) }),
5058
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", "aria-label": "Key actions", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5059
+ _iconsreact.IconDotsVertical,
5060
+ {
5061
+ className: "size-4 text-zinc-500 dark:text-zinc-600",
5062
+ fill: "rgb(var(--color-zinc-500))"
5063
+ }
5064
+ ) }) }),
4930
5065
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { className: "", align: "end", children: [
4931
5066
  content && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4932
5067
  DropdownMenuItem,
@@ -4979,15 +5114,15 @@ var DisplayHeader = ({
4979
5114
  const handleAddItem = () => {
4980
5115
  setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true });
4981
5116
  };
4982
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
4983
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4984
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "grow truncate text-base", children: dataKey.trim() === "" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-semibold", children: dataKey }) }),
5117
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg", children: [
5118
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-[26px] items-center justify-between gap-4", children: [
5119
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "grow truncate text-sm", children: dataKey.trim() === "" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium text-zinc-950", children: dataKey }) }),
4985
5120
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
4986
- type !== "string" && type !== "json" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleAddItem, size: "icon-sm", "aria-label": "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4 text-zinc-500 dark:text-zinc-600" }) }) }),
5121
+ type !== "string" && type !== "json" && type !== "search" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleAddItem, size: "icon-sm", "aria-label": "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4 text-zinc-500 dark:text-zinc-600" }) }) }),
4987
5122
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content })
4988
5123
  ] })
4989
5124
  ] }),
4990
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 flex-wrap items-center gap-1.5", children: [
5125
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-1.5 overflow-scroll", children: [
4991
5126
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }),
4992
5127
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SizeBadge, { dataKey }),
4993
5128
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LengthBadge, { dataKey, type, content }),
@@ -5059,7 +5194,7 @@ var useSetHashTTL = () => {
5059
5194
  var HashFieldTTLBadge = ({ dataKey, field }) => {
5060
5195
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
5061
5196
  const { mutate: setTTL, isPending } = useSetHashTTL();
5062
- const expireAt = _optionalChain([data, 'optionalAccess', _36 => _36[field]]);
5197
+ const expireAt = _optionalChain([data, 'optionalAccess', _38 => _38[field]]);
5063
5198
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5064
5199
  TTLBadge,
5065
5200
  {
@@ -5156,7 +5291,7 @@ var MonacoEditor = ({
5156
5291
  if (!active || !monaco || !editorRef.current) {
5157
5292
  return;
5158
5293
  }
5159
- _optionalChain([monaco, 'optionalAccess', _37 => _37.editor, 'access', _38 => _38.setModelLanguage, 'call', _39 => _39(editorRef.current.getModel(), language)]);
5294
+ _optionalChain([monaco, 'optionalAccess', _39 => _39.editor, 'access', _40 => _40.setModelLanguage, 'call', _41 => _41(editorRef.current.getModel(), language)]);
5160
5295
  }, [monaco, language, active]);
5161
5296
  const editor = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5162
5297
  _react2.Editor,
@@ -5297,7 +5432,7 @@ var checkIsValidJSON = (value) => {
5297
5432
  try {
5298
5433
  JSON.parse(value);
5299
5434
  return true;
5300
- } catch (e3) {
5435
+ } catch (e4) {
5301
5436
  return false;
5302
5437
  }
5303
5438
  };
@@ -5321,7 +5456,7 @@ var ListEditForm = ({
5321
5456
  dataKey
5322
5457
  });
5323
5458
  const findValue = () => {
5324
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _40 => _40.data, 'optionalAccess', _41 => _41.pages]), () => ( []))) {
5459
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _42 => _42.data, 'optionalAccess', _43 => _43.pages]), () => ( []))) {
5325
5460
  const item = page.keys.find((item2) => item2.key === itemKey);
5326
5461
  if (item && "value" in item) return item.value;
5327
5462
  }
@@ -5467,7 +5602,7 @@ var HashFieldTTLInfo = ({
5467
5602
  fields
5468
5603
  }) => {
5469
5604
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
5470
- const expireAt = _optionalChain([data, 'optionalAccess', _42 => _42[field]]);
5605
+ const expireAt = _optionalChain([data, 'optionalAccess', _44 => _44[field]]);
5471
5606
  const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
5472
5607
  _react.useEffect.call(void 0, () => {
5473
5608
  setTTL(calculateTTL(expireAt));
@@ -5495,7 +5630,7 @@ var ListDisplay = ({ dataKey, type }) => {
5495
5630
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: [
5496
5631
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type }),
5497
5632
  selectedListItem && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditDisplay, { dataKey, type, item: selectedListItem }),
5498
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) })
5633
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, className: "rounded-lg border border-zinc-200 bg-white", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) })
5499
5634
  ] });
5500
5635
  };
5501
5636
  var ListItems = ({
@@ -5504,7 +5639,7 @@ var ListItems = ({
5504
5639
  dataKey
5505
5640
  }) => {
5506
5641
  const { setSelectedListItem } = useTab();
5507
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _43 => _43.data, 'optionalAccess', _44 => _44.pages, 'access', _45 => _45.flatMap, 'call', _46 => _46((page) => page.keys)]), () => ( [])), [query.data]);
5642
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _45 => _45.data, 'optionalAccess', _46 => _46.pages, 'access', _47 => _47.flatMap, 'call', _48 => _48((page) => page.keys)]), () => ( [])), [query.data]);
5508
5643
  const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
5509
5644
  const { mutate: editItem } = useEditListItem();
5510
5645
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -5516,7 +5651,7 @@ var ListItems = ({
5516
5651
  setSelectedListItem({ key });
5517
5652
  },
5518
5653
  className: cn(
5519
- "h-10 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100 dark:border-b-zinc-200 dark:hover:bg-zinc-200"
5654
+ "h-9 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100 dark:border-b-zinc-200 dark:hover:bg-zinc-200"
5520
5655
  ),
5521
5656
  children: [
5522
5657
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5580,6 +5715,17 @@ var ListItems = ({
5580
5715
  )) });
5581
5716
  };
5582
5717
 
5718
+ // src/components/databrowser/components/display/display-search.tsx
5719
+
5720
+ var SearchDisplay = ({ dataKey, type }) => {
5721
+ const { data, isLoading } = useFetchSearchIndex(dataKey);
5722
+ const content = data ? JSON.stringify(data, null, 2) : void 0;
5723
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full flex-col gap-2", children: [
5724
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type, content }),
5725
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full grow flex-col gap-2 rounded-md bg-zinc-100", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : data === null || data === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "No data found" }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grow overflow-auto rounded-md border border-zinc-300 bg-white p-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "pre", { className: "whitespace-pre-wrap break-words font-mono text-sm", children: JSON.stringify(data, null, 2) }) }) })
5726
+ ] });
5727
+ };
5728
+
5583
5729
  // src/components/databrowser/components/display/display-simple.tsx
5584
5730
 
5585
5731
 
@@ -5635,7 +5781,55 @@ var DataDisplay = () => {
5635
5781
  const { selectedKey } = useTab();
5636
5782
  const { query } = useKeys();
5637
5783
  const type = useKeyType(selectedKey);
5638
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full p-4", children: !selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : !type ? query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "Loading..." }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: type === "string" || type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5784
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full rounded-xl bg-zinc-100 p-5", children: !selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : !type ? query.isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "Loading..." }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: type === "string" || type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : type === "search" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5785
+ };
5786
+
5787
+ // src/components/ui/segmented.tsx
5788
+
5789
+ var Segmented = ({
5790
+ options,
5791
+ value,
5792
+ onChange
5793
+ }) => {
5794
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex w-fit gap-[2px] rounded-lg bg-zinc-200 p-[2px] text-sm", children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5795
+ "button",
5796
+ {
5797
+ className: cn(
5798
+ "h-7 rounded-md px-3 transition-all",
5799
+ value === option.key ? "bg-white text-zinc-950" : "text-zinc-700"
5800
+ ),
5801
+ onClick: () => {
5802
+ _optionalChain([onChange, 'optionalCall', _49 => _49(option.key)]);
5803
+ },
5804
+ children: option.label
5805
+ },
5806
+ option.key
5807
+ )) });
5808
+ };
5809
+
5810
+ // src/components/databrowser/hooks/use-fetch-search-indexes.tsx
5811
+
5812
+ var FETCH_SEARCH_INDEXES_QUERY_KEY = "fetch-search-indexes";
5813
+ var useFetchSearchIndexes = (match) => {
5814
+ const { redisNoPipeline: redis } = useRedis();
5815
+ return _reactquery.useQuery.call(void 0, {
5816
+ queryKey: [FETCH_SEARCH_INDEXES_QUERY_KEY],
5817
+ queryFn: async () => {
5818
+ let cursor = "0";
5819
+ const finalResult = [];
5820
+ while (true) {
5821
+ const [newCursor, results] = await redis.scan(cursor, {
5822
+ count: 100,
5823
+ type: "search",
5824
+ match
5825
+ });
5826
+ finalResult.push(...results);
5827
+ if (newCursor === "0") break;
5828
+ cursor = newCursor;
5829
+ }
5830
+ return finalResult;
5831
+ }
5832
+ });
5639
5833
  };
5640
5834
 
5641
5835
  // src/components/databrowser/components/add-key-modal.tsx
@@ -5643,6 +5837,7 @@ var DataDisplay = () => {
5643
5837
  var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
5644
5838
 
5645
5839
 
5840
+
5646
5841
  // src/components/ui/dialog.tsx
5647
5842
 
5648
5843
 
@@ -5746,7 +5941,6 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
5746
5941
 
5747
5942
  // src/components/databrowser/components/add-key-modal.tsx
5748
5943
 
5749
-
5750
5944
  function AddKeyModal() {
5751
5945
  const { setSelectedKey } = useTab();
5752
5946
  const [open, setOpen] = _react.useState.call(void 0, false);
@@ -5762,7 +5956,7 @@ function AddKeyModal() {
5762
5956
  setSelectedKey(key);
5763
5957
  setOpen(false);
5764
5958
  setTimeout(() => {
5765
- _optionalChain([window, 'access', _47 => _47.document, 'access', _48 => _48.querySelector, 'call', _49 => _49(`[data-key="${key}"]`), 'optionalAccess', _50 => _50.scrollIntoView, 'call', _51 => _51({
5959
+ _optionalChain([window, 'access', _50 => _50.document, 'access', _51 => _51.querySelector, 'call', _52 => _52(`[data-key="${key}"]`), 'optionalAccess', _53 => _53.scrollIntoView, 'call', _54 => _54({
5766
5960
  behavior: "smooth",
5767
5961
  block: "start",
5768
5962
  inline: "nearest"
@@ -5778,7 +5972,18 @@ function AddKeyModal() {
5778
5972
  setOpen(open2);
5779
5973
  },
5780
5974
  children: [
5781
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add key", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", size: "icon-sm", "data-testid": "add-key-button", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4" }) }) }) }),
5975
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add key", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5976
+ Button,
5977
+ {
5978
+ variant: "primary",
5979
+ "data-testid": "add-key-button",
5980
+ className: "flex h-8 items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
5981
+ children: [
5982
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-5" }),
5983
+ "Key"
5984
+ ]
5985
+ }
5986
+ ) }) }),
5782
5987
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-[400px]", children: [
5783
5988
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new key" }) }),
5784
5989
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactdialog.DialogDescription, { children: "Create new key" }) }),
@@ -5791,7 +5996,7 @@ function AddKeyModal() {
5791
5996
  name: "type",
5792
5997
  render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: field.value, onValueChange: field.onChange, children: [
5793
5998
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-8 w-auto pl-[3px] pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
5794
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: DATA_TYPES.map((type) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }) }, type)) }) })
5999
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: DATA_TYPES.filter((t) => t !== "search").map((type) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }) }, type)) }) })
5795
6000
  ] })
5796
6001
  }
5797
6002
  ),
@@ -5807,7 +6012,7 @@ function AddKeyModal() {
5807
6012
  }
5808
6013
  )
5809
6014
  ] }),
5810
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _52 => _52.errors, 'access', _53 => _53.key, 'optionalAccess', _54 => _54.message]) }),
6015
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _55 => _55.errors, 'access', _56 => _56.key, 'optionalAccess', _57 => _57.message]) }),
5811
6016
  /* @__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" }),
5812
6017
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5813
6018
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5830,219 +6035,35 @@ function AddKeyModal() {
5830
6035
  );
5831
6036
  }
5832
6037
 
5833
- // src/components/databrowser/components/sidebar/empty.tsx
5834
-
5835
- var Empty = () => {
5836
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full w-full items-center justify-center rounded-md border bg-white px-4 py-6 text-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-5", children: [
5837
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-md font-medium", children: "Data on a break" }),
5838
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
5839
- ] }) });
5840
- };
6038
+ // src/components/databrowser/components/sidebar/reload-button.tsx
5841
6039
 
5842
- // src/components/databrowser/components/sidebar/keys-list.tsx
5843
6040
 
5844
6041
 
5845
- // src/components/databrowser/components/sidebar-context-menu.tsx
6042
+ var ReloadButton = ({
6043
+ onClick,
6044
+ isLoading: isLoadingProp
6045
+ }) => {
6046
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
6047
+ const handleClick = () => {
6048
+ setIsLoading(true);
6049
+ onClick();
6050
+ setTimeout(() => {
6051
+ setIsLoading(false);
6052
+ }, 350);
6053
+ };
6054
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Refresh", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6055
+ Button,
6056
+ {
6057
+ variant: "outline",
6058
+ size: "icon",
6059
+ onClick: handleClick,
6060
+ disabled: isLoading || isLoadingProp,
6061
+ children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "size-5 animate-spin text-zinc-500" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { className: "size-5 text-zinc-500 dark:text-zinc-600" })
6062
+ }
6063
+ ) }) });
6064
+ };
5846
6065
 
5847
-
5848
-
5849
-
5850
- var SidebarContextMenu = ({ children }) => {
5851
- const { mutate: deleteKey } = useDeleteKey();
5852
- const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
5853
- const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
5854
- const { addTab, setSelectedKey: setSelectedKeyGlobal, selectTab, setSearch } = useDatabrowserStore();
5855
- const { search: currentSearch, selectedKeys, setSelectedKey } = useTab();
5856
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5857
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5858
- DeleteAlertDialog,
5859
- {
5860
- deletionType: "key",
5861
- count: contextKeys.length,
5862
- open: isAlertOpen,
5863
- onOpenChange: setAlertOpen,
5864
- onDeleteConfirm: (e) => {
5865
- e.stopPropagation();
5866
- for (const key of contextKeys) {
5867
- deleteKey(key);
5868
- }
5869
- setAlertOpen(false);
5870
- }
5871
- }
5872
- ),
5873
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { modal: false, children: [
5874
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5875
- ContextMenuTrigger,
5876
- {
5877
- onContextMenu: (e) => {
5878
- const el = e.target;
5879
- const key = el.closest("[data-key]");
5880
- if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
5881
- const clickedKey = key.dataset.key;
5882
- if (selectedKeys.includes(clickedKey)) {
5883
- setContextKeys(selectedKeys);
5884
- } else {
5885
- setSelectedKey(clickedKey);
5886
- setContextKeys([clickedKey]);
5887
- }
5888
- } else {
5889
- throw new Error("Key not found");
5890
- }
5891
- },
5892
- children
5893
- }
5894
- ),
5895
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
5896
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5897
- ContextMenuItem,
5898
- {
5899
- onClick: () => {
5900
- navigator.clipboard.writeText(contextKeys[0]);
5901
- toast({
5902
- description: "Key copied to clipboard"
5903
- });
5904
- },
5905
- className: "gap-2",
5906
- disabled: contextKeys.length !== 1,
5907
- children: [
5908
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCopy, { size: 16 }),
5909
- "Copy key"
5910
- ]
5911
- }
5912
- ),
5913
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5914
- ContextMenuItem,
5915
- {
5916
- onClick: () => {
5917
- const newTabId = addTab();
5918
- setSelectedKeyGlobal(newTabId, contextKeys[0]);
5919
- setSearch(newTabId, currentSearch);
5920
- selectTab(newTabId);
5921
- },
5922
- className: "gap-2",
5923
- disabled: contextKeys.length !== 1,
5924
- children: [
5925
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 16 }),
5926
- "Open in new tab"
5927
- ]
5928
- }
5929
- ),
5930
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
5931
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuItem, { onClick: () => setAlertOpen(true), className: "gap-2", children: [
5932
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { size: 16 }),
5933
- contextKeys.length > 1 ? `Delete ${contextKeys.length} keys` : "Delete key"
5934
- ] })
5935
- ] })
5936
- ] })
5937
- ] });
5938
- };
5939
-
5940
- // src/components/databrowser/components/sidebar/keys-list.tsx
5941
-
5942
- var KeysList = () => {
5943
- const { keys } = useKeys();
5944
- const lastClickedIndexRef = _react.useRef.call(void 0, null);
5945
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5946
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px" }),
5947
- keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
5948
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5949
- KeyItem,
5950
- {
5951
- index: i,
5952
- data,
5953
- allKeys: keys,
5954
- lastClickedIndexRef
5955
- }
5956
- ),
5957
- i !== keys.length - 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "-z-10 mx-2 h-px bg-zinc-100 dark:bg-zinc-200" })
5958
- ] }, data[0]))
5959
- ] }) });
5960
- };
5961
- var keyStyles = {
5962
- string: "border-sky-400 !bg-sky-50 text-sky-900",
5963
- hash: "border-amber-400 !bg-amber-50 text-amber-900",
5964
- set: "border-indigo-400 !bg-indigo-50 text-indigo-900",
5965
- zset: "border-pink-400 !bg-pink-50 text-pink-900",
5966
- json: "border-purple-400 !bg-purple-50 text-purple-900",
5967
- list: "border-orange-400 !bg-orange-50 text-orange-900",
5968
- stream: "border-green-400 !bg-green-50 text-green-900"
5969
- };
5970
- var KeyItem = ({
5971
- data,
5972
- index,
5973
- allKeys,
5974
- lastClickedIndexRef
5975
- }) => {
5976
- const { selectedKeys, setSelectedKeys, setSelectedKey } = useTab();
5977
- const [dataKey, dataType] = data;
5978
- const isKeySelected = selectedKeys.includes(dataKey);
5979
- const handleClick = (e) => {
5980
- if (e.shiftKey && lastClickedIndexRef.current !== null) {
5981
- const start = Math.min(lastClickedIndexRef.current, index);
5982
- const end = Math.max(lastClickedIndexRef.current, index);
5983
- const rangeKeys = allKeys.slice(start, end + 1).map(([key]) => key);
5984
- setSelectedKeys(rangeKeys);
5985
- } else if (e.metaKey || e.ctrlKey) {
5986
- if (isKeySelected) {
5987
- setSelectedKeys(selectedKeys.filter((k) => k !== dataKey));
5988
- } else {
5989
- setSelectedKeys([...selectedKeys, dataKey]);
5990
- }
5991
- lastClickedIndexRef.current = index;
5992
- } else {
5993
- setSelectedKey(dataKey);
5994
- lastClickedIndexRef.current = index;
5995
- }
5996
- };
5997
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5998
- Button,
5999
- {
6000
- "data-key": dataKey,
6001
- variant: isKeySelected ? "default" : "ghost",
6002
- className: cn(
6003
- "relative flex h-10 w-full items-center justify-start gap-2 px-3 py-0 !ring-0 focus-visible:bg-zinc-50",
6004
- "-my-px select-none border border-transparent text-left",
6005
- isKeySelected && "shadow-sm",
6006
- isKeySelected && keyStyles[dataType]
6007
- ),
6008
- onClick: handleClick,
6009
- children: [
6010
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: dataType, type: "icon" }),
6011
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "truncate whitespace-nowrap", children: dataKey })
6012
- ]
6013
- }
6014
- );
6015
- };
6016
-
6017
- // src/components/databrowser/components/sidebar/reload-button.tsx
6018
-
6019
-
6020
-
6021
- var ReloadButton = ({
6022
- onClick,
6023
- isLoading: isLoadingProp
6024
- }) => {
6025
- const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
6026
- const handleClick = () => {
6027
- setIsLoading(true);
6028
- onClick();
6029
- setTimeout(() => {
6030
- setIsLoading(false);
6031
- }, 350);
6032
- };
6033
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Refresh", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6034
- Button,
6035
- {
6036
- variant: "outline",
6037
- size: "icon-sm",
6038
- onClick: handleClick,
6039
- disabled: isLoading || isLoadingProp,
6040
- children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "animate-spin text-zinc-500", size: 16 }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { className: "text-zinc-500 dark:text-zinc-600", size: 16 })
6041
- }
6042
- ) }) });
6043
- };
6044
-
6045
- // src/components/databrowser/components/sidebar/search-input.tsx
6066
+ // src/components/databrowser/components/sidebar/search-input.tsx
6046
6067
 
6047
6068
 
6048
6069
 
@@ -6081,7 +6102,7 @@ var SearchInput = () => {
6081
6102
  } else if (e.key === "Escape") {
6082
6103
  setState("");
6083
6104
  setFocusedIndex(-1);
6084
- _optionalChain([inputRef, 'access', _55 => _55.current, 'optionalAccess', _56 => _56.blur, 'call', _57 => _57()]);
6105
+ _optionalChain([inputRef, 'access', _58 => _58.current, 'optionalAccess', _59 => _59.blur, 'call', _60 => _60()]);
6085
6106
  } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
6086
6107
  e.preventDefault();
6087
6108
  if (focusedIndex < filteredHistory.length - 1) {
@@ -6095,7 +6116,7 @@ var SearchInput = () => {
6095
6116
  setFocusedIndex(focusedIndex - 1);
6096
6117
  } else if (filteredHistory.length > 0 && focusedIndex === 0) {
6097
6118
  setFocusedIndex(-1);
6098
- _optionalChain([inputRef, 'access', _58 => _58.current, 'optionalAccess', _59 => _59.focus, 'call', _60 => _60()]);
6119
+ _optionalChain([inputRef, 'access', _61 => _61.current, 'optionalAccess', _62 => _62.focus, 'call', _63 => _63()]);
6099
6120
  } else if (filteredHistory.length > 0) {
6100
6121
  setFocusedIndex(filteredHistory.length - 1);
6101
6122
  }
@@ -6103,12 +6124,12 @@ var SearchInput = () => {
6103
6124
  };
6104
6125
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
6105
6126
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
6106
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 rounded-md rounded-l-none border border-zinc-300 font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6127
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 rounded-md border border-zinc-300 font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6107
6128
  Input,
6108
6129
  {
6109
6130
  ref: inputRef,
6110
6131
  placeholder: "Search",
6111
- className: "h-full rounded-l-none border-none pr-6",
6132
+ className: "h-full border-none pr-6",
6112
6133
  onKeyDown: handleKeyDown,
6113
6134
  onChange: (e) => {
6114
6135
  setState(e.currentTarget.value);
@@ -6123,150 +6144,915 @@ var SearchInput = () => {
6123
6144
  }
6124
6145
  ) }) }),
6125
6146
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6126
- PopoverContent,
6147
+ PopoverContent,
6148
+ {
6149
+ className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
6150
+ autoFocus: false,
6151
+ onOpenAutoFocus: (e) => {
6152
+ e.preventDefault();
6153
+ e.stopPropagation();
6154
+ },
6155
+ children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6156
+ "button",
6157
+ {
6158
+ ref: (el) => {
6159
+ historyItemRefs.current[index] = el;
6160
+ },
6161
+ onClick: () => handleSubmit(item),
6162
+ onMouseEnter: () => setFocusedIndex(index),
6163
+ className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
6164
+ children: item
6165
+ }
6166
+ ) }, item))
6167
+ }
6168
+ )
6169
+ ] }),
6170
+ state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6171
+ Button,
6172
+ {
6173
+ type: "button",
6174
+ variant: "link",
6175
+ size: "icon",
6176
+ className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
6177
+ onClick: () => {
6178
+ setSearchKey("");
6179
+ setState("");
6180
+ },
6181
+ children: [
6182
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
6183
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
6184
+ ]
6185
+ }
6186
+ ),
6187
+ " "
6188
+ ] });
6189
+ };
6190
+
6191
+ // src/components/databrowser/components/sidebar/type-selector.tsx
6192
+
6193
+ var ALL_TYPES_KEY = "all";
6194
+ function DataTypeSelector() {
6195
+ const { search, setSearchType } = useTab();
6196
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6197
+ Select,
6198
+ {
6199
+ onValueChange: (type) => {
6200
+ if (type === ALL_TYPES_KEY) {
6201
+ setSearchType(void 0);
6202
+ } else {
6203
+ setSearchType(type);
6204
+ }
6205
+ },
6206
+ value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
6207
+ children: [
6208
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "!w-auto select-none whitespace-nowrap border-zinc-300 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
6209
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: [[ALL_TYPES_KEY, "All Types"], ...Object.entries(DATA_TYPE_NAMES)].map(
6210
+ ([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)
6211
+ ) }) })
6212
+ ]
6213
+ }
6214
+ );
6215
+ }
6216
+
6217
+ // src/components/databrowser/components/header/index.tsx
6218
+
6219
+ var Header = () => {
6220
+ const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
6221
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1.5", children: [
6222
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6223
+ Segmented,
6224
+ {
6225
+ options: [
6226
+ {
6227
+ key: "keys",
6228
+ label: "Keys"
6229
+ },
6230
+ {
6231
+ key: "values",
6232
+ label: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
6233
+ "Values",
6234
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[18px] items-center rounded-md bg-emerald-100 px-[5px] text-[11px] text-emerald-700", children: "NEW" })
6235
+ ] })
6236
+ }
6237
+ ],
6238
+ value: isValuesSearchSelected ? "values" : "keys",
6239
+ onChange: (value) => {
6240
+ setIsValuesSearchSelected(value === "values");
6241
+ }
6242
+ }
6243
+ ),
6244
+ isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IndexSelector, {}) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6245
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, {}),
6246
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
6247
+ ] }),
6248
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RefreshButton, {}),
6249
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
6250
+ ] });
6251
+ };
6252
+ var IndexSelector = () => {
6253
+ const {
6254
+ valuesSearch: { index },
6255
+ setValuesSearchIndex
6256
+ } = useTab();
6257
+ const { data } = useFetchSearchIndexes();
6258
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6259
+ Select,
6260
+ {
6261
+ value: index,
6262
+ onValueChange: (value) => {
6263
+ setValuesSearchIndex(value);
6264
+ },
6265
+ children: [
6266
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "select-none whitespace-nowrap border-zinc-300", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, { placeholder: "Select an index" }) }),
6267
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: _optionalChain([data, 'optionalAccess', _64 => _64.map, 'call', _65 => _65((index2) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: index2, children: index2 }, index2))]) }) })
6268
+ ]
6269
+ }
6270
+ );
6271
+ };
6272
+ var RefreshButton = () => {
6273
+ const { query } = useKeys();
6274
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6275
+ ReloadButton,
6276
+ {
6277
+ onClick: () => {
6278
+ queryClient.invalidateQueries({
6279
+ queryKey: [FETCH_KEYS_QUERY_KEY]
6280
+ });
6281
+ queryClient.invalidateQueries({
6282
+ queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
6283
+ });
6284
+ queryClient.invalidateQueries({
6285
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
6286
+ });
6287
+ queryClient.invalidateQueries({
6288
+ queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
6289
+ });
6290
+ },
6291
+ isLoading: query.isFetching
6292
+ }
6293
+ );
6294
+ };
6295
+
6296
+ // src/components/databrowser/components/header-error.tsx
6297
+
6298
+ var formatUpstashErrorMessage = (error) => {
6299
+ if (error.name !== "UpstashError") return error.message;
6300
+ const commandIndex = error.message.indexOf(", command was:");
6301
+ if (commandIndex !== -1) {
6302
+ return error.message.slice(0, commandIndex);
6303
+ }
6304
+ return error.message;
6305
+ };
6306
+ var HeaderError = () => {
6307
+ const { query } = useKeys();
6308
+ if (!query.error) return null;
6309
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-red-600 dark:text-red-400", children: formatUpstashErrorMessage(query.error) });
6310
+ };
6311
+
6312
+ // src/components/databrowser/components/query-builder.tsx
6313
+
6314
+
6315
+ // src/components/databrowser/components/display/input/query-editor.tsx
6316
+
6317
+
6318
+
6319
+ // src/components/databrowser/components/display/input/generateTypeDefinitions.tsx
6320
+ var generateTypeDefinitions = (schema) => {
6321
+ let schemaFieldsInterface = "";
6322
+ if (schema && Object.keys(schema).length > 0) {
6323
+ const fieldLines = Object.entries(schema).map(([fieldName, fieldDef]) => {
6324
+ const fieldType = fieldDef.type;
6325
+ let operationType;
6326
+ switch (fieldType) {
6327
+ case "TEXT": {
6328
+ operationType = "StringOperations";
6329
+ break;
6330
+ }
6331
+ case "U64":
6332
+ case "I64":
6333
+ case "F64": {
6334
+ operationType = "NumberOperations";
6335
+ break;
6336
+ }
6337
+ case "BOOL": {
6338
+ operationType = "BooleanOperations";
6339
+ break;
6340
+ }
6341
+ case "DATE": {
6342
+ operationType = "DateOperations";
6343
+ break;
6344
+ }
6345
+ default: {
6346
+ operationType = "StringOperations";
6347
+ }
6348
+ }
6349
+ const escapedFieldName = fieldName.includes(".") ? `"${fieldName}"` : fieldName;
6350
+ return ` ${escapedFieldName}?: ${operationType};`;
6351
+ }).join("\n");
6352
+ schemaFieldsInterface = `
6353
+ /** Schema fields for the current index */
6354
+ interface SchemaFields {
6355
+ ${fieldLines}
6356
+ }`;
6357
+ } else {
6358
+ schemaFieldsInterface = `
6359
+ /** Schema fields - no schema available, using dynamic fields */
6360
+ interface SchemaFields {
6361
+ [fieldName: string]: StringOperations | NumberOperations | BooleanOperations | DateOperations;
6362
+ }`;
6363
+ }
6364
+ return `
6365
+ // String operations for TEXT fields
6366
+ type StringOperationMap = {
6367
+ /** Exact match */
6368
+ $eq: string;
6369
+ /** Not equal */
6370
+ $ne: string;
6371
+ /** Match any value in array */
6372
+ $in: string[];
6373
+ /** Fuzzy match with optional distance */
6374
+ $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean };
6375
+ /** Phrase match */
6376
+ $phrase: string;
6377
+ /** Regular expression match */
6378
+ $regex: string;
6379
+ };
6380
+
6381
+ // Number operations for U64, I64, F64 fields
6382
+ type NumberOperationMap = {
6383
+ /** Exact match */
6384
+ $eq: number;
6385
+ /** Not equal */
6386
+ $ne: number;
6387
+ /** Match any value in array */
6388
+ $in: number[];
6389
+ /** Greater than */
6390
+ $gt: number;
6391
+ /** Greater than or equal */
6392
+ $gte: number;
6393
+ /** Less than */
6394
+ $lt: number;
6395
+ /** Less than or equal */
6396
+ $lte: number;
6397
+ };
6398
+
6399
+ // Boolean operations for BOOL fields
6400
+ type BooleanOperationMap = {
6401
+ /** Exact match */
6402
+ $eq: boolean;
6403
+ /** Not equal */
6404
+ $ne: boolean;
6405
+ /** Match any value in array */
6406
+ $in: boolean[];
6407
+ };
6408
+
6409
+ // Date operations for DATE fields
6410
+ type DateOperationMap = {
6411
+ /** Exact match */
6412
+ $eq: string | Date;
6413
+ /** Not equal */
6414
+ $ne: string | Date;
6415
+ /** Match any value in array */
6416
+ $in: (string | Date)[];
6417
+ };
6418
+
6419
+ // String field operations with optional boost
6420
+ type StringOperations =
6421
+ | { $eq: string; $boost?: number }
6422
+ | { $ne: string; $boost?: number }
6423
+ | { $in: string[]; $boost?: number }
6424
+ | { $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean }; $boost?: number }
6425
+ | { $phrase: string; $boost?: number }
6426
+ | { $regex: string; $boost?: number }
6427
+ | string;
6428
+
6429
+ // Number field operations with optional boost
6430
+ type NumberOperations =
6431
+ | { $eq: number; $boost?: number }
6432
+ | { $ne: number; $boost?: number }
6433
+ | { $in: number[]; $boost?: number }
6434
+ | { $gt: number; $boost?: number }
6435
+ | { $gte: number; $boost?: number }
6436
+ | { $lt: number; $boost?: number }
6437
+ | { $lte: number; $boost?: number }
6438
+ | number;
6439
+
6440
+ // Boolean field operations with optional boost
6441
+ type BooleanOperations =
6442
+ | { $eq: boolean; $boost?: number }
6443
+ | { $ne: boolean; $boost?: number }
6444
+ | { $in: boolean[]; $boost?: number }
6445
+ | boolean;
6446
+
6447
+ // Date field operations with optional boost
6448
+ type DateOperations =
6449
+ | { $eq: string | Date; $boost?: number }
6450
+ | { $ne: string | Date; $boost?: number }
6451
+ | { $in: (string | Date)[]; $boost?: number }
6452
+ | string
6453
+ | Date;
6454
+
6455
+ ${schemaFieldsInterface}
6456
+
6457
+ // Query leaf - field conditions without logical operators
6458
+ type QueryLeaf = SchemaFields & {
6459
+ $and?: never;
6460
+ $or?: never;
6461
+ $must?: never;
6462
+ $should?: never;
6463
+ $mustNot?: never;
6464
+ $boost?: never;
6465
+ };
6466
+
6467
+ // Base type for boolean nodes - allows field conditions
6468
+ type BoolBase = SchemaFields;
6469
+
6470
+ // $and: all conditions must match
6471
+ type AndNode = BoolBase & {
6472
+ /** All conditions in this array must match */
6473
+ $and: QueryFilter[];
6474
+ /** Boost score for this node */
6475
+ $boost?: number;
6476
+ $or?: never;
6477
+ $must?: never;
6478
+ $should?: never;
6479
+ $mustNot?: never;
6480
+ };
6481
+
6482
+ // $or: at least one condition must match
6483
+ type OrNode = BoolBase & {
6484
+ /** At least one condition must match */
6485
+ $or: QueryFilter[];
6486
+ /** Boost score for this node */
6487
+ $boost?: number;
6488
+ $and?: never;
6489
+ $must?: never;
6490
+ $should?: never;
6491
+ $mustNot?: never;
6492
+ };
6493
+
6494
+ // $must only (Elasticsearch-style)
6495
+ type MustNode = BoolBase & {
6496
+ /** All conditions must match (similar to $and) */
6497
+ $must: QueryFilter[];
6498
+ /** Boost score for this node */
6499
+ $boost?: number;
6500
+ $and?: never;
6501
+ $or?: never;
6502
+ $should?: never;
6503
+ $mustNot?: never;
6504
+ };
6505
+
6506
+ // $should only (Elasticsearch-style)
6507
+ type ShouldNode = BoolBase & {
6508
+ /** At least one should match (affects scoring) */
6509
+ $should: QueryFilter[];
6510
+ /** Boost score for this node */
6511
+ $boost?: number;
6512
+ $and?: never;
6513
+ $or?: never;
6514
+ $must?: never;
6515
+ $mustNot?: never;
6516
+ };
6517
+
6518
+ // $must + $should combined
6519
+ type MustShouldNode = BoolBase & {
6520
+ /** All these must match */
6521
+ $must: QueryFilter[];
6522
+ /** At least one should match for higher score */
6523
+ $should: QueryFilter[];
6524
+ $and?: never;
6525
+ $or?: never;
6526
+ $mustNot?: never;
6527
+ };
6528
+
6529
+ // $mustNot only
6530
+ type NotNode = BoolBase & {
6531
+ /** None of these conditions should match */
6532
+ $mustNot: QueryFilter[];
6533
+ /** Boost score for this node */
6534
+ $boost?: number;
6535
+ $and?: never;
6536
+ $or?: never;
6537
+ $must?: never;
6538
+ $should?: never;
6539
+ };
6540
+
6541
+ // $and + $mustNot combined
6542
+ type AndNotNode = BoolBase & {
6543
+ $and: QueryFilter[];
6544
+ $mustNot: QueryFilter[];
6545
+ $boost?: number;
6546
+ $or?: never;
6547
+ $must?: never;
6548
+ $should?: never;
6549
+ };
6550
+
6551
+ // $or + $mustNot combined
6552
+ type OrNotNode = BoolBase & {
6553
+ $or: QueryFilter[];
6554
+ $mustNot: QueryFilter[];
6555
+ $boost?: number;
6556
+ $and?: never;
6557
+ $must?: never;
6558
+ $should?: never;
6559
+ };
6560
+
6561
+ // $should + $mustNot combined
6562
+ type ShouldNotNode = BoolBase & {
6563
+ $should: QueryFilter[];
6564
+ $mustNot: QueryFilter[];
6565
+ $boost?: number;
6566
+ $and?: never;
6567
+ $or?: never;
6568
+ $must?: never;
6569
+ };
6570
+
6571
+ // $must + $mustNot combined
6572
+ type MustNotNode = BoolBase & {
6573
+ $must: QueryFilter[];
6574
+ $mustNot: QueryFilter[];
6575
+ $boost?: number;
6576
+ $and?: never;
6577
+ $or?: never;
6578
+ $should?: never;
6579
+ };
6580
+
6581
+ // Full boolean node: $must + $should + $mustNot
6582
+ type BoolNode = BoolBase & {
6583
+ $must: QueryFilter[];
6584
+ $should: QueryFilter[];
6585
+ $mustNot: QueryFilter[];
6586
+ $boost?: number;
6587
+ $and?: never;
6588
+ $or?: never;
6589
+ };
6590
+
6591
+ // Query filter - union of all node types
6592
+ type QueryFilter =
6593
+ | QueryLeaf
6594
+ | AndNode
6595
+ | OrNode
6596
+ | MustNode
6597
+ | ShouldNode
6598
+ | MustShouldNode
6599
+ | NotNode
6600
+ | AndNotNode
6601
+ | OrNotNode
6602
+ | ShouldNotNode
6603
+ | MustNotNode
6604
+ | BoolNode;
6605
+
6606
+ // Root-level $or restriction (no field conditions at root with $or)
6607
+ type RootOrNode = {
6608
+ $or: QueryFilter[];
6609
+ $boost?: number;
6610
+ $and?: never;
6611
+ $must?: never;
6612
+ $should?: never;
6613
+ $mustNot?: never;
6614
+ };
6615
+
6616
+ // Root query filter - restricts $or from mixing with fields at root level
6617
+ type Query =
6618
+ | QueryLeaf
6619
+ | AndNode
6620
+ | RootOrNode
6621
+ | MustNode
6622
+ | ShouldNode
6623
+ | MustShouldNode
6624
+ | NotNode
6625
+ | AndNotNode
6626
+ | ShouldNotNode
6627
+ | MustNotNode
6628
+ | BoolNode;
6629
+ `;
6630
+ };
6631
+
6632
+ // src/components/databrowser/components/display/input/query-editor.tsx
6633
+
6634
+ var QueryEditor = (props) => {
6635
+ if (isTest) {
6636
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TestQueryEditor, { ...props });
6637
+ }
6638
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MonacoQueryEditor, { ...props });
6639
+ };
6640
+ var MonacoQueryEditor = ({ value, onChange, height, schema }) => {
6641
+ const monaco = _react2.useMonaco.call(void 0, );
6642
+ const editorRef = _react.useRef.call(void 0, null);
6643
+ const theme = useTheme();
6644
+ const libDisposableRef = _react.useRef.call(void 0, null);
6645
+ const typeDefinitions = _react.useMemo.call(void 0, () => generateTypeDefinitions(schema), [schema]);
6646
+ _react.useEffect.call(void 0, () => {
6647
+ if (!monaco) return;
6648
+ if (libDisposableRef.current) {
6649
+ libDisposableRef.current.dispose();
6650
+ }
6651
+ libDisposableRef.current = monaco.languages.typescript.typescriptDefaults.addExtraLib(
6652
+ typeDefinitions,
6653
+ "file:///query-types.d.ts"
6654
+ );
6655
+ return () => {
6656
+ if (libDisposableRef.current) {
6657
+ libDisposableRef.current.dispose();
6658
+ }
6659
+ };
6660
+ }, [monaco, typeDefinitions]);
6661
+ const handleBeforeMount = (monaco2) => {
6662
+ monaco2.languages.typescript.typescriptDefaults.setCompilerOptions({
6663
+ target: monaco2.languages.typescript.ScriptTarget.ES2020,
6664
+ allowNonTsExtensions: true,
6665
+ moduleResolution: monaco2.languages.typescript.ModuleResolutionKind.NodeJs,
6666
+ module: monaco2.languages.typescript.ModuleKind.CommonJS,
6667
+ noEmit: true,
6668
+ esModuleInterop: true,
6669
+ strict: true,
6670
+ allowJs: true
6671
+ });
6672
+ libDisposableRef.current = monaco2.languages.typescript.typescriptDefaults.addExtraLib(
6673
+ typeDefinitions,
6674
+ "file:///query-types.d.ts"
6675
+ );
6676
+ monaco2.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
6677
+ noSemanticValidation: false,
6678
+ noSyntaxValidation: false
6679
+ });
6680
+ monaco2.languages.typescript.typescriptDefaults.setEagerModelSync(true);
6681
+ };
6682
+ _react.useEffect.call(void 0, () => {
6683
+ const match = value.startsWith("const query: Query = {");
6684
+ const ending = value.endsWith("}");
6685
+ if (!match || !ending) {
6686
+ onChange("const query: Query = {}");
6687
+ }
6688
+ }, [value, editorRef.current, onChange]);
6689
+ const handleChange = (newValue) => {
6690
+ if (!newValue) {
6691
+ onChange("");
6692
+ return;
6693
+ }
6694
+ const match = newValue.startsWith("const query: Query = {");
6695
+ if (match) {
6696
+ onChange(newValue);
6697
+ } else {
6698
+ const editor = editorRef.current;
6699
+ if (editor) {
6700
+ editor.setValue(value);
6701
+ }
6702
+ }
6703
+ };
6704
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("group/editor relative"), style: { height }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6705
+ _react2.Editor,
6706
+ {
6707
+ theme: theme === "dark" ? "vs-dark" : "light",
6708
+ loading: void 0,
6709
+ beforeMount: handleBeforeMount,
6710
+ onMount: (editor) => {
6711
+ editorRef.current = editor;
6712
+ },
6713
+ value,
6714
+ onChange: handleChange,
6715
+ defaultLanguage: "typescript",
6716
+ path: "query.ts",
6717
+ options: {
6718
+ wordWrap: "on",
6719
+ overviewRulerBorder: false,
6720
+ overviewRulerLanes: 0,
6721
+ formatOnPaste: true,
6722
+ formatOnType: true,
6723
+ renderWhitespace: "none",
6724
+ smoothScrolling: true,
6725
+ scrollbar: {
6726
+ verticalScrollbarSize: 12
6727
+ },
6728
+ autoIndent: "full",
6729
+ guides: { indentation: false },
6730
+ fontSize: 13,
6731
+ cursorBlinking: "smooth",
6732
+ minimap: { enabled: false },
6733
+ folding: true,
6734
+ glyphMargin: false,
6735
+ lineNumbers: "on",
6736
+ parameterHints: { enabled: true },
6737
+ lineDecorationsWidth: 0,
6738
+ automaticLayout: true,
6739
+ scrollBeyondLastLine: false,
6740
+ renderLineHighlight: "line",
6741
+ unusualLineTerminators: "auto",
6742
+ padding: { top: 8, bottom: 8 },
6743
+ quickSuggestions: true,
6744
+ suggest: {
6745
+ showVariables: false,
6746
+ showConstants: false,
6747
+ showFunctions: false,
6748
+ showClasses: false,
6749
+ showInterfaces: false,
6750
+ showModules: false,
6751
+ showKeywords: false
6752
+ },
6753
+ suggestOnTriggerCharacters: true,
6754
+ acceptSuggestionOnEnter: "on",
6755
+ tabCompletion: "on",
6756
+ wordBasedSuggestions: "off",
6757
+ // Disable navigation features
6758
+ gotoLocation: {
6759
+ multiple: "goto",
6760
+ multipleDefinitions: "goto",
6761
+ multipleTypeDefinitions: "goto",
6762
+ multipleDeclarations: "goto",
6763
+ multipleImplementations: "goto",
6764
+ multipleReferences: "goto"
6765
+ },
6766
+ definitionLinkOpensInPeek: false,
6767
+ contextmenu: false
6768
+ },
6769
+ className: "[&_.current-line]:!border-none [&_.current-line]:!bg-emerald-50 [&_.monaco-editor-background]:!bg-transparent [&_.monaco-editor]:!bg-transparent [&_[role='presentation']]:!bg-transparent"
6770
+ }
6771
+ ) });
6772
+ };
6773
+ var TestQueryEditor = ({ value, onChange, height }) => {
6774
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("group/editor relative"), style: { height }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6775
+ "textarea",
6776
+ {
6777
+ "aria-label": "query-editor",
6778
+ value,
6779
+ onChange: (e) => onChange(e.target.value),
6780
+ className: "h-full w-full resize-none bg-transparent p-2 font-mono text-sm"
6781
+ }
6782
+ ) });
6783
+ };
6784
+
6785
+ // src/components/databrowser/components/query-builder.tsx
6786
+
6787
+ var QueryBuilder = () => {
6788
+ const { valuesSearch, setValuesSearchQuery } = useTab();
6789
+ const [value, setValue] = _react.useState.call(void 0, valuesSearch.query);
6790
+ const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
6791
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "rounded-lg border border-zinc-300 bg-white px-[6px] dark:border-zinc-700", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6792
+ QueryEditor,
6793
+ {
6794
+ height: 300,
6795
+ value,
6796
+ onChange: (value2) => {
6797
+ setValue(value2);
6798
+ const sliced = value2.slice(PREFIX.length);
6799
+ const parsed = parseJSObjectLiteral(sliced);
6800
+ const newValue = value2.slice(PREFIX.length);
6801
+ if (parsed && valuesSearch.query !== newValue) {
6802
+ setValuesSearchQuery(newValue);
6803
+ }
6804
+ },
6805
+ schema: _optionalChain([indexDetails, 'optionalAccess', _66 => _66.schema])
6806
+ }
6807
+ ) });
6808
+ };
6809
+
6810
+ // src/components/databrowser/components/sidebar/empty.tsx
6811
+
6812
+ var Empty = () => {
6813
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full w-full items-center justify-center rounded-md border bg-white px-4 py-6 text-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-5", children: [
6814
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-md font-medium", children: "Data on a break" }),
6815
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
6816
+ ] }) });
6817
+ };
6818
+
6819
+ // src/components/databrowser/components/sidebar/keys-list.tsx
6820
+
6821
+
6822
+
6823
+ // src/components/databrowser/components/sidebar-context-menu.tsx
6824
+
6825
+
6826
+
6827
+
6828
+ var SidebarContextMenu = ({ children }) => {
6829
+ const { mutate: deleteKey } = useDeleteKey();
6830
+ const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
6831
+ const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
6832
+ const {
6833
+ addTab,
6834
+ setSelectedKey: setSelectedKeyGlobal,
6835
+ selectTab,
6836
+ setSearch
6837
+ } = useDatabrowserStore();
6838
+ const { search: currentSearch, selectedKeys, setSelectedKey } = useTab();
6839
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6840
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6841
+ DeleteAlertDialog,
6842
+ {
6843
+ deletionType: "key",
6844
+ count: contextKeys.length,
6845
+ open: isAlertOpen,
6846
+ onOpenChange: setAlertOpen,
6847
+ onDeleteConfirm: (e) => {
6848
+ e.stopPropagation();
6849
+ for (const key of contextKeys) {
6850
+ deleteKey(key);
6851
+ }
6852
+ setAlertOpen(false);
6853
+ }
6854
+ }
6855
+ ),
6856
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { modal: false, children: [
6857
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6858
+ ContextMenuTrigger,
6859
+ {
6860
+ onContextMenu: (e) => {
6861
+ const el = e.target;
6862
+ const key = el.closest("[data-key]");
6863
+ if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
6864
+ const clickedKey = key.dataset.key;
6865
+ if (selectedKeys.includes(clickedKey)) {
6866
+ setContextKeys(selectedKeys);
6867
+ } else {
6868
+ setSelectedKey(clickedKey);
6869
+ setContextKeys([clickedKey]);
6870
+ }
6871
+ } else {
6872
+ throw new Error("Key not found");
6873
+ }
6874
+ },
6875
+ children
6876
+ }
6877
+ ),
6878
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
6879
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6880
+ ContextMenuItem,
6881
+ {
6882
+ onClick: () => {
6883
+ navigator.clipboard.writeText(contextKeys[0]);
6884
+ toast({
6885
+ description: "Key copied to clipboard"
6886
+ });
6887
+ },
6888
+ className: "gap-2",
6889
+ disabled: contextKeys.length !== 1,
6890
+ children: [
6891
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCopy, { size: 16 }),
6892
+ "Copy key"
6893
+ ]
6894
+ }
6895
+ ),
6896
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6897
+ ContextMenuItem,
6898
+ {
6899
+ onClick: () => {
6900
+ const newTabId = addTab();
6901
+ setSelectedKeyGlobal(newTabId, contextKeys[0]);
6902
+ setSearch(newTabId, currentSearch);
6903
+ selectTab(newTabId);
6904
+ },
6905
+ className: "gap-2",
6906
+ disabled: contextKeys.length !== 1,
6907
+ children: [
6908
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 16 }),
6909
+ "Open in new tab"
6910
+ ]
6911
+ }
6912
+ ),
6913
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
6914
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuItem, { onClick: () => setAlertOpen(true), className: "gap-2", children: [
6915
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { size: 16 }),
6916
+ contextKeys.length > 1 ? `Delete ${contextKeys.length} keys` : "Delete key"
6917
+ ] })
6918
+ ] })
6919
+ ] })
6920
+ ] });
6921
+ };
6922
+
6923
+ // src/components/databrowser/components/sidebar/keys-list.tsx
6924
+
6925
+ var KeysList = () => {
6926
+ const { keys } = useKeys();
6927
+ const lastClickedIndexRef = _react.useRef.call(void 0, null);
6928
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6929
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px" }),
6930
+ keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
6931
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6932
+ KeyItem,
6127
6933
  {
6128
- className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
6129
- autoFocus: false,
6130
- onOpenAutoFocus: (e) => {
6131
- e.preventDefault();
6132
- e.stopPropagation();
6133
- },
6134
- children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6135
- "button",
6136
- {
6137
- ref: (el) => {
6138
- historyItemRefs.current[index] = el;
6139
- },
6140
- onClick: () => handleSubmit(item),
6141
- onMouseEnter: () => setFocusedIndex(index),
6142
- className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
6143
- children: item
6144
- }
6145
- ) }, item))
6934
+ index: i,
6935
+ data,
6936
+ allKeys: keys,
6937
+ lastClickedIndexRef
6146
6938
  }
6147
- )
6148
- ] }),
6149
- state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6150
- Button,
6151
- {
6152
- type: "button",
6153
- variant: "link",
6154
- size: "icon",
6155
- className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
6156
- onClick: () => {
6157
- setSearchKey("");
6158
- setState("");
6159
- },
6160
- children: [
6161
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
6162
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
6163
- ]
6939
+ ),
6940
+ i !== keys.length - 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "-z-10 mx-[13px] h-px bg-zinc-200 dark:bg-zinc-200" })
6941
+ ] }, data[0]))
6942
+ ] }) });
6943
+ };
6944
+ var KeyItem = ({
6945
+ data,
6946
+ index,
6947
+ allKeys,
6948
+ lastClickedIndexRef
6949
+ }) => {
6950
+ const { selectedKeys, setSelectedKeys, setSelectedKey } = useTab();
6951
+ const [dataKey, dataType] = data;
6952
+ const isKeySelected = selectedKeys.includes(dataKey);
6953
+ const handleClick = (e) => {
6954
+ if (e.shiftKey && lastClickedIndexRef.current !== null) {
6955
+ const start = Math.min(lastClickedIndexRef.current, index);
6956
+ const end = Math.max(lastClickedIndexRef.current, index);
6957
+ const rangeKeys = allKeys.slice(start, end + 1).map(([key]) => key);
6958
+ setSelectedKeys(rangeKeys);
6959
+ } else if (e.metaKey || e.ctrlKey) {
6960
+ if (isKeySelected) {
6961
+ setSelectedKeys(selectedKeys.filter((k) => k !== dataKey));
6962
+ } else {
6963
+ setSelectedKeys([...selectedKeys, dataKey]);
6164
6964
  }
6165
- ),
6166
- " "
6167
- ] });
6965
+ lastClickedIndexRef.current = index;
6966
+ } else {
6967
+ setSelectedKey(dataKey);
6968
+ lastClickedIndexRef.current = index;
6969
+ }
6970
+ };
6971
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6972
+ "button",
6973
+ {
6974
+ "data-key": dataKey,
6975
+ className: cn(
6976
+ "relative flex h-10 w-full items-center justify-start gap-2 rounded-lg px-3 py-0 !ring-0 transition-colors focus-visible:bg-zinc-50",
6977
+ "-my-px select-none border border-transparent text-left",
6978
+ isKeySelected ? "border-zinc-300 bg-white font-medium text-zinc-950 shadow-[0_1px_2px_0_rgba(0,0,0,0.10)]" : "shadow-none hover:bg-zinc-200"
6979
+ ),
6980
+ onClick: handleClick,
6981
+ children: [
6982
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: dataType, type: "icon" }),
6983
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "grow truncate whitespace-nowrap", children: dataKey }),
6984
+ isKeySelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronRight, { className: "shrink-0 text-zinc-500", size: 20 })
6985
+ ]
6986
+ }
6987
+ );
6168
6988
  };
6169
6989
 
6170
6990
  // src/components/databrowser/components/sidebar/skeleton-buttons.tsx
6171
6991
 
6172
6992
  var DEFAULT_SKELETON_COUNT = 6;
6173
- var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "block h-full w-full rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-2 px-3", children: [
6993
+ var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "block h-full w-full rounded-lg bg-zinc-100 p-1 pr-3 transition-all", children: Array.from({ length: DEFAULT_SKELETON_COUNT }).fill(0).map((_, idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-2 px-3", children: [
6174
6994
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "size-5 shrink-0 rounded" }),
6175
6995
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-4 grow rounded" })
6176
6996
  ] }, idx)) });
6177
6997
 
6178
- // src/components/databrowser/components/sidebar/type-selector.tsx
6179
-
6180
- var ALL_TYPES_KEY = "all";
6181
- function DataTypeSelector() {
6182
- const { search, setSearchType } = useTab();
6183
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6184
- Select,
6185
- {
6186
- onValueChange: (type) => {
6187
- if (type === ALL_TYPES_KEY) {
6188
- setSearchType(void 0);
6189
- } else {
6190
- setSearchType(type);
6191
- }
6192
- },
6193
- value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
6194
- children: [
6195
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "!w-auto select-none whitespace-nowrap rounded-r-none border-r-0 border-zinc-300 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
6196
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: [[ALL_TYPES_KEY, "All Types"], ...Object.entries(DATA_TYPE_NAMES)].map(
6197
- ([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)
6198
- ) }) })
6199
- ]
6200
- }
6201
- );
6202
- }
6203
-
6204
6998
  // src/components/databrowser/components/sidebar/index.tsx
6205
6999
 
6206
7000
  function Sidebar() {
6207
7001
  const { keys, query } = useKeys();
6208
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2 p-4", children: [
6209
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
6210
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center justify-between pl-1", children: [
6211
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayDbSize, {}),
6212
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-1", children: [
6213
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6214
- ReloadButton,
6215
- {
6216
- onClick: () => {
6217
- queryClient.invalidateQueries({
6218
- queryKey: [FETCH_KEYS_QUERY_KEY]
6219
- });
6220
- queryClient.invalidateQueries({
6221
- queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
6222
- });
6223
- queryClient.invalidateQueries({
6224
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
6225
- });
6226
- queryClient.invalidateQueries({
6227
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
6228
- });
6229
- queryClient.invalidateQueries({
6230
- queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
6231
- });
6232
- },
6233
- isLoading: query.isFetching
6234
- }
6235
- ),
6236
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
6237
- ] })
6238
- ] }),
6239
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center", children: [
6240
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, {}),
6241
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
6242
- ] })
6243
- ] }),
6244
- query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
6245
- // Infinite scroll already has a loader at the bottom
6246
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, disableRoundedInherit: true, className: "min-h-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) })
6247
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {})
6248
- ] });
7002
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
7003
+ // Infinite scroll already has a loader at the bottom
7004
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7005
+ InfiniteScroll,
7006
+ {
7007
+ query,
7008
+ disableRoundedInherit: true,
7009
+ className: "min-h-0 rounded-xl bg-zinc-100 px-2 py-5 pr-4",
7010
+ scrollBarClassName: "py-5",
7011
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {})
7012
+ }
7013
+ )
7014
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {}) });
6249
7015
  }
6250
7016
 
6251
7017
  // src/components/databrowser/components/databrowser-instance.tsx
6252
7018
 
7019
+ var PREFIX = "const query: Query = ";
6253
7020
  var DatabrowserInstance = ({ hidden }) => {
6254
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("min-h-0 grow rounded-md bg-zinc-100", hidden && "hidden"), children: [
6255
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6256
- _reactresizablepanels.PanelGroup,
6257
- {
6258
- autoSaveId: "persistence",
6259
- direction: "horizontal",
6260
- className: "h-full w-full gap-0.5 text-sm antialiased",
6261
- children: [
6262
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
6263
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "group flex h-full w-3 justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full border-r border-dashed border-zinc-200 transition-colors group-hover:border-zinc-500" }) }),
6264
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
6265
- ]
6266
- }
6267
- ),
6268
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Toaster, {})
6269
- ] }) });
7021
+ const { isValuesSearchSelected } = useTab();
7022
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7023
+ "div",
7024
+ {
7025
+ className: cn(
7026
+ "flex min-h-0 grow flex-col rounded-md bg-white px-5 pb-5",
7027
+ hidden && "hidden"
7028
+ ),
7029
+ children: [
7030
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3 py-5", children: [
7031
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Header, {}),
7032
+ isValuesSearchSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {}),
7033
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderError, {})
7034
+ ] }),
7035
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7036
+ _reactresizablepanels.PanelGroup,
7037
+ {
7038
+ autoSaveId: "persistence",
7039
+ direction: "horizontal",
7040
+ className: "h-full w-full text-sm antialiased",
7041
+ children: [
7042
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
7043
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "group mx-[2px] flex h-full flex-col items-center justify-center gap-1 rounded-md px-[8px] transition-colors hover:bg-zinc-300/10", children: [
7044
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
7045
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
7046
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" })
7047
+ ] }),
7048
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
7049
+ ]
7050
+ }
7051
+ ),
7052
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Toaster, {})
7053
+ ]
7054
+ }
7055
+ ) });
6270
7056
  };
6271
7057
 
6272
7058
  // src/components/databrowser/components/databrowser-tabs.tsx
@@ -6286,8 +7072,8 @@ var _utilities = require('@dnd-kit/utilities');
6286
7072
 
6287
7073
  // src/components/ui/command.tsx
6288
7074
 
6289
- var _cmdk = require('cmdk');
6290
7075
 
7076
+ var _cmdk = require('cmdk');
6291
7077
 
6292
7078
  var Command = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6293
7079
  _cmdk.Command,
@@ -6375,15 +7161,6 @@ CommandShortcut.displayName = "CommandShortcut";
6375
7161
 
6376
7162
 
6377
7163
 
6378
- // src/components/databrowser/components/tab-type-icon.tsx
6379
-
6380
- function TabTypeIcon({ selectedKey }) {
6381
- const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
6382
- if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-5 rounded" });
6383
- if (!keyType || keyType === "none") return;
6384
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
6385
- }
6386
-
6387
7164
  // src/hooks/use-overflow.ts
6388
7165
 
6389
7166
  var useOverflow = () => {
@@ -6396,7 +7173,7 @@ var useOverflow = () => {
6396
7173
  }
6397
7174
  if (!node) return;
6398
7175
  observerRef.current = new ResizeObserver((entries) => {
6399
- const el = _optionalChain([entries, 'access', _61 => _61.at, 'call', _62 => _62(0), 'optionalAccess', _63 => _63.target]);
7176
+ const el = _optionalChain([entries, 'access', _67 => _67.at, 'call', _68 => _68(0), 'optionalAccess', _69 => _69.target]);
6400
7177
  if (!el) return;
6401
7178
  setIsOverflow(el.scrollWidth > el.clientWidth);
6402
7179
  });
@@ -6404,16 +7181,25 @@ var useOverflow = () => {
6404
7181
  }, []);
6405
7182
  _react.useEffect.call(void 0, () => {
6406
7183
  return () => {
6407
- _optionalChain([observerRef, 'access', _64 => _64.current, 'optionalAccess', _65 => _65.disconnect, 'call', _66 => _66()]);
7184
+ _optionalChain([observerRef, 'access', _70 => _70.current, 'optionalAccess', _71 => _71.disconnect, 'call', _72 => _72()]);
6408
7185
  };
6409
7186
  }, []);
6410
7187
  return { ref, isOverflow };
6411
7188
  };
6412
7189
 
7190
+ // src/components/databrowser/components/tab-type-icon.tsx
7191
+
7192
+ function TabTypeIcon({ selectedKey }) {
7193
+ const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
7194
+ if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-5 rounded" });
7195
+ if (!keyType || keyType === "none") return;
7196
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
7197
+ }
7198
+
6413
7199
  // src/components/databrowser/components/tab.tsx
6414
7200
 
6415
7201
  var Tab = ({ id, isList }) => {
6416
- const { active, search, selectedKey, pinned } = useTab();
7202
+ const { active, search, selectedKey, valuesSearch, pinned, isValuesSearchSelected } = useTab();
6417
7203
  const {
6418
7204
  selectTab,
6419
7205
  removeTab,
@@ -6426,21 +7212,20 @@ var Tab = ({ id, isList }) => {
6426
7212
  } = useDatabrowserStore();
6427
7213
  const hasPinnedTabs = tabs.some(([, data]) => data.pinned);
6428
7214
  const { ref, isOverflow } = useOverflow();
6429
- const label = search.key || selectedKey;
6430
- const iconNode = search.key ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 15 }) : selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabTypeIcon, { selectedKey }) : void 0;
7215
+ const label = isValuesSearchSelected ? valuesSearch.index : search.key || selectedKey;
7216
+ const iconNode = isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[20px] w-[20px] items-center justify-center rounded-md bg-emerald-200 text-emerald-800", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 14 }) }) : search.key ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[20px] w-[20px] items-center justify-center rounded-md bg-zinc-100 text-zinc-600", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 14 }) }) : selectedKey ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabTypeIcon, { selectedKey }) : void 0;
6431
7217
  const tabNode = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6432
7218
  "div",
6433
7219
  {
6434
7220
  id: isList ? `list-tab-${id}` : `tab-${id}`,
6435
7221
  onClick: () => selectTab(id),
6436
7222
  className: cn(
6437
- "flex h-9 w-full cursor-pointer items-center gap-2 px-3 text-[13px] transition-colors",
7223
+ "flex h-[40px] w-full cursor-pointer items-center gap-2 rounded-t-lg px-3 text-[13px] transition-colors",
6438
7224
  isList && "max-w-[370px]",
6439
- !isList && "rounded-t-lg border border-zinc-200",
6440
- !isList && (active ? "border-b-white bg-white text-zinc-900" : "bg-zinc-100 hover:bg-zinc-50")
7225
+ !isList && (active ? "bg-white text-zinc-950" : "bg-zinc-200 text-zinc-600 hover:bg-zinc-100")
6441
7226
  ),
6442
7227
  children: [
6443
- iconNode,
7228
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(!active && "transition-colors"), children: iconNode }),
6444
7229
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6445
7230
  "span",
6446
7231
  {
@@ -6457,7 +7242,7 @@ var Tab = ({ id, isList }) => {
6457
7242
  e.stopPropagation();
6458
7243
  removeTab(id);
6459
7244
  },
6460
- className: "p-1 text-zinc-300 transition-colors hover:text-zinc-500 dark:text-zinc-400",
7245
+ className: "p-[2px] text-zinc-400 transition-colors hover:text-zinc-500",
6461
7246
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
6462
7247
  }
6463
7248
  )
@@ -6514,8 +7299,8 @@ var SortableTab = ({ id }) => {
6514
7299
  const [originalWidth, setOriginalWidth] = _react.useState.call(void 0, null);
6515
7300
  const textRef = _react.useRef.call(void 0, null);
6516
7301
  const { tabs } = useDatabrowserStore();
6517
- const tabData = _optionalChain([tabs, 'access', _67 => _67.find, 'call', _68 => _68(([tabId]) => tabId === id), 'optionalAccess', _69 => _69[1]]);
6518
- const isPinned = _optionalChain([tabData, 'optionalAccess', _70 => _70.pinned]);
7302
+ const tabData = _optionalChain([tabs, 'access', _73 => _73.find, 'call', _74 => _74(([tabId]) => tabId === id), 'optionalAccess', _75 => _75[1]]);
7303
+ const isPinned = _optionalChain([tabData, 'optionalAccess', _76 => _76.pinned]);
6519
7304
  const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = _sortable.useSortable.call(void 0, {
6520
7305
  id,
6521
7306
  disabled: isPinned,
@@ -6660,73 +7445,70 @@ var DatabrowserTabs = ({ onFullScreenClick }) => {
6660
7445
  reorderTabs(oldIndex, newIndex);
6661
7446
  }
6662
7447
  };
6663
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative mb-2 shrink-0", children: [
6664
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-0 left-0 right-0 -z-10 h-[1px] w-full bg-zinc-200" }),
6665
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex translate-y-[1px] items-center gap-1", children: [
6666
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative min-w-0 flex-1", children: [
6667
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6668
- "div",
6669
- {
6670
- className: `tabs-shadow-left pointer-events-none absolute left-0 top-0 z-10 h-full w-6 transition-opacity duration-200 ${hasLeftShadow ? "opacity-100" : "opacity-0"}`
6671
- }
6672
- ),
6673
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6674
- "div",
6675
- {
6676
- className: `tabs-shadow-right pointer-events-none absolute right-0 top-0 z-10 h-full w-6 transition-opacity duration-200 ${hasRightShadow ? "opacity-100" : "opacity-0"}`
6677
- }
6678
- ),
6679
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6680
- "div",
6681
- {
6682
- ref: scrollRef,
6683
- onScroll: recomputeShadows,
6684
- className: "scrollbar-hide flex min-w-0 flex-1 items-center gap-1 overflow-x-auto pb-[1px] [&::-webkit-scrollbar]:hidden",
6685
- children: [
6686
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6687
- _core.DndContext,
6688
- {
6689
- sensors,
6690
- collisionDetection: _core.closestCenter,
6691
- onDragEnd: handleDragEnd,
6692
- modifiers: [_modifiers.restrictToHorizontalAxis],
6693
- measuring: {
6694
- droppable: {
6695
- strategy: _core.MeasuringStrategy.Always
6696
- }
6697
- },
6698
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6699
- _sortable.SortableContext,
6700
- {
6701
- items: sortedTabs.map(([id]) => id),
6702
- strategy: _sortable.horizontalListSortingStrategy,
6703
- children: selectedTab && sortedTabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SortableTab, { id }, id))
6704
- }
6705
- )
6706
- }
6707
- ),
6708
- !isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-1 pl-1 pr-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}) })
6709
- ]
6710
- }
6711
- )
6712
- ] }),
6713
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 pl-1", children: [
6714
- isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}),
6715
- tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsListButton, { tabs, onSelectTab: selectTab }),
6716
- onFullScreenClick && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6717
- Button,
6718
- {
6719
- "aria-label": "Toggle fullscreen",
6720
- variant: "secondary",
6721
- size: "icon-sm",
6722
- onClick: onFullScreenClick,
6723
- className: "flex-shrink-0 bg-blue-100 hover:bg-blue-600 hover:text-white",
6724
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconMaximize, { size: 16 })
6725
- }
6726
- )
6727
- ] })
7448
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative shrink-0 overflow-hidden rounded-t-lg bg-zinc-300", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
7449
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative min-w-0 flex-1", children: [
7450
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7451
+ "div",
7452
+ {
7453
+ className: `tabs-shadow-left pointer-events-none absolute left-0 top-0 z-10 h-full w-6 transition-opacity duration-200 ${hasLeftShadow ? "opacity-100" : "opacity-0"}`
7454
+ }
7455
+ ),
7456
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7457
+ "div",
7458
+ {
7459
+ className: `tabs-shadow-right pointer-events-none absolute right-0 top-0 z-10 h-full w-6 transition-opacity duration-200 ${hasRightShadow ? "opacity-100" : "opacity-0"}`
7460
+ }
7461
+ ),
7462
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7463
+ "div",
7464
+ {
7465
+ ref: scrollRef,
7466
+ onScroll: recomputeShadows,
7467
+ className: "scrollbar-hide flex min-w-0 flex-1 items-center gap-1 overflow-x-auto [&::-webkit-scrollbar]:hidden",
7468
+ children: [
7469
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7470
+ _core.DndContext,
7471
+ {
7472
+ sensors,
7473
+ collisionDetection: _core.closestCenter,
7474
+ onDragEnd: handleDragEnd,
7475
+ modifiers: [_modifiers.restrictToHorizontalAxis],
7476
+ measuring: {
7477
+ droppable: {
7478
+ strategy: _core.MeasuringStrategy.Always
7479
+ }
7480
+ },
7481
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7482
+ _sortable.SortableContext,
7483
+ {
7484
+ items: sortedTabs.map(([id]) => id),
7485
+ strategy: _sortable.horizontalListSortingStrategy,
7486
+ children: selectedTab && sortedTabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SortableTab, { id }, id))
7487
+ }
7488
+ )
7489
+ }
7490
+ ),
7491
+ !isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-1 pl-1 pr-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}) })
7492
+ ]
7493
+ }
7494
+ )
7495
+ ] }),
7496
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 pl-1", children: [
7497
+ isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}),
7498
+ tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsListButton, { tabs, onSelectTab: selectTab }),
7499
+ onFullScreenClick && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7500
+ Button,
7501
+ {
7502
+ "aria-label": "Toggle fullscreen",
7503
+ variant: "secondary",
7504
+ size: "icon-sm",
7505
+ onClick: onFullScreenClick,
7506
+ className: "flex-shrink-0 bg-white text-zinc-500 dark:bg-zinc-100",
7507
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconWindowMaximize, { size: 16 })
7508
+ }
7509
+ )
6728
7510
  ] })
6729
- ] });
7511
+ ] }) });
6730
7512
  };
6731
7513
  function AddTabButton() {
6732
7514
  const { addTab, selectTab } = useDatabrowserStore();
@@ -6735,7 +7517,7 @@ function AddTabButton() {
6735
7517
  const tabsId = addTab();
6736
7518
  selectTab(tabsId);
6737
7519
  setTimeout(() => {
6738
- const tab = _optionalChain([rootRef, 'optionalAccess', _71 => _71.current, 'optionalAccess', _72 => _72.querySelector, 'call', _73 => _73(`#tab-${tabsId}`)]);
7520
+ const tab = _optionalChain([rootRef, 'optionalAccess', _77 => _77.current, 'optionalAccess', _78 => _78.querySelector, 'call', _79 => _79(`#tab-${tabsId}`)]);
6739
7521
  if (!tab) return;
6740
7522
  tab.scrollIntoView({ behavior: "smooth" });
6741
7523
  }, 20);
@@ -6747,8 +7529,8 @@ function AddTabButton() {
6747
7529
  variant: "secondary",
6748
7530
  size: "icon-sm",
6749
7531
  onClick: handleAddTab,
6750
- className: "flex-shrink-0 dark:bg-zinc-200",
6751
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-500 dark:text-zinc-600", size: 16 })
7532
+ className: "flex-shrink-0 bg-zinc-200 ",
7533
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-600", size: 16 })
6752
7534
  }
6753
7535
  );
6754
7536
  }
@@ -6769,7 +7551,7 @@ function TabsListButton({
6769
7551
  onSelectTab(id);
6770
7552
  setOpen(false);
6771
7553
  setTimeout(() => {
6772
- const tab = _optionalChain([rootRef, 'optionalAccess', _74 => _74.current, 'optionalAccess', _75 => _75.querySelector, 'call', _76 => _76(`#tab-${id}`)]);
7554
+ const tab = _optionalChain([rootRef, 'optionalAccess', _80 => _80.current, 'optionalAccess', _81 => _81.querySelector, 'call', _82 => _82(`#tab-${id}`)]);
6773
7555
  if (!tab) return;
6774
7556
  tab.scrollIntoView({ behavior: "smooth" });
6775
7557
  }, 20);
@@ -6780,7 +7562,7 @@ function TabsListButton({
6780
7562
  {
6781
7563
  variant: "secondary",
6782
7564
  size: "sm",
6783
- className: "h-7 gap-1 px-2",
7565
+ className: "gap-1 bg-white px-2",
6784
7566
  "aria-label": "Search in tabs",
6785
7567
  children: [
6786
7568
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs text-zinc-600", children: tabs.length }),
@@ -6851,7 +7633,7 @@ var RedisBrowserRoot = ({
6851
7633
  className: `ups-db ${theme === "dark" ? "dark" : ""}`,
6852
7634
  style: { height: "100%" },
6853
7635
  ref: rootRef,
6854
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col text-zinc-700", children: [
7636
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col overflow-hidden rounded-[14px] border-[4px] border-zinc-300 text-zinc-700", children: [
6855
7637
  !hideTabs && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserTabs, { onFullScreenClick }),
6856
7638
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, {})
6857
7639
  ] })