@upstash/react-redis-browser 0.2.13 → 0.2.14-rc.1

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 +566 -144
  2. package/dist/index.js +2836 -621
  3. package/dist/index.mjs +3035 -820
  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
  );
@@ -545,6 +625,7 @@ var portalRoot = root;
545
625
  var portalWrapper = wrapper;
546
626
 
547
627
  // src/components/databrowser/components/databrowser-instance.tsx
628
+
548
629
  var _reactresizablepanels = require('react-resizable-panels');
549
630
 
550
631
  // node_modules/clsx/dist/clsx.mjs
@@ -603,15 +684,15 @@ var getGroupRecursive = (classParts, classPartObject) => {
603
684
  return void 0;
604
685
  }
605
686
  const classRest = classParts.join(CLASS_PART_SEPARATOR);
606
- return _optionalChain([classPartObject, 'access', _15 => _15.validators, 'access', _16 => _16.find, 'call', _17 => _17(({
687
+ return _optionalChain([classPartObject, 'access', _17 => _17.validators, 'access', _18 => _18.find, 'call', _19 => _19(({
607
688
  validator
608
- }) => validator(classRest)), 'optionalAccess', _18 => _18.classGroupId]);
689
+ }) => validator(classRest)), 'optionalAccess', _20 => _20.classGroupId]);
609
690
  };
610
691
  var arbitraryPropertyRegex = /^\[(.+)\]$/;
611
692
  var getGroupIdForArbitraryProperty = (className) => {
612
693
  if (arbitraryPropertyRegex.test(className)) {
613
694
  const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
614
- const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _19 => _19.substring, 'call', _20 => _20(0, arbitraryPropertyClassName.indexOf(":"))]);
695
+ const property = _optionalChain([arbitraryPropertyClassName, 'optionalAccess', _21 => _21.substring, 'call', _22 => _22(0, arbitraryPropertyClassName.indexOf(":"))]);
615
696
  if (property) {
616
697
  return "arbitrary.." + property;
617
698
  }
@@ -1717,7 +1798,7 @@ var getDefaultConfig = () => {
1717
1798
  * Font Variant Numeric
1718
1799
  * @see https://tailwindcss.com/docs/font-variant-numeric
1719
1800
  */
1720
- "fvn-fraction": ["diagonal-fractions", "stacked-fractions"],
1801
+ "fvn-fraction": ["diagonal-fractions", "stacked-fractons"],
1721
1802
  /**
1722
1803
  * Letter Spacing
1723
1804
  * @see https://tailwindcss.com/docs/letter-spacing
@@ -3026,9 +3107,14 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
3026
3107
  function cn(...inputs) {
3027
3108
  return twMerge(clsx(inputs));
3028
3109
  }
3029
- function formatNumber(value) {
3030
- const intl = new Intl.NumberFormat("en-US");
3031
- return intl.format(value);
3110
+ function parseJSObjectLiteral(value) {
3111
+ try {
3112
+ let jsonified = value.replaceAll(/([,{]\s*)(\$?[A-Z_a-z]\w*)\s*:/g, '$1"$2":');
3113
+ jsonified = jsonified.replaceAll(/,\s*([\]}])/g, "$1");
3114
+ return JSON.parse(jsonified);
3115
+ } catch (e3) {
3116
+ return;
3117
+ }
3032
3118
  }
3033
3119
  var units = {
3034
3120
  year: 24 * 60 * 60 * 1e3 * 365,
@@ -3057,54 +3143,104 @@ function formatTime(seconds) {
3057
3143
  }
3058
3144
  var isTest = typeof window !== "undefined" && window.__PLAYWRIGHT__ === true;
3059
3145
 
3146
+ // src/components/ui/segmented.tsx
3147
+
3148
+ var Segmented = ({
3149
+ options,
3150
+ value,
3151
+ onChange,
3152
+ className,
3153
+ buttonClassName
3154
+ }) => {
3155
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3156
+ "div",
3157
+ {
3158
+ className: cn(
3159
+ "flex w-fit gap-[2px] rounded-lg bg-zinc-200 p-[2px] text-sm dark:bg-zinc-700",
3160
+ className
3161
+ ),
3162
+ children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3163
+ "button",
3164
+ {
3165
+ className: cn(
3166
+ "h-7 rounded-md px-3 transition-all",
3167
+ value === option.key ? "bg-white text-zinc-950 dark:bg-zinc-800 dark:text-zinc-100" : "text-zinc-700 dark:text-zinc-400",
3168
+ buttonClassName
3169
+ ),
3170
+ onClick: () => {
3171
+ _optionalChain([onChange, 'optionalCall', _23 => _23(option.key)]);
3172
+ },
3173
+ children: option.label
3174
+ },
3175
+ option.key
3176
+ ))
3177
+ }
3178
+ );
3179
+ };
3180
+
3060
3181
  // src/components/ui/toaster.tsx
3061
3182
  var _reactportal = require('@radix-ui/react-portal');
3062
3183
 
3063
3184
  // src/components/ui/toast.tsx
3064
3185
 
3065
- var _iconsreact = require('@tabler/icons-react');
3066
3186
  var _reacttoast = require('@radix-ui/react-toast'); var ToastPrimitives = _interopRequireWildcard(_reacttoast);
3187
+ var _iconsreact = require('@tabler/icons-react');
3188
+
3189
+ // node_modules/class-variance-authority/node_modules/clsx/dist/clsx.mjs
3190
+ function r2(e) {
3191
+ var t, f, n = "";
3192
+ if ("string" == typeof e || "number" == typeof e) n += e;
3193
+ else if ("object" == typeof e) if (Array.isArray(e)) for (t = 0; t < e.length; t++) e[t] && (f = r2(e[t])) && (n && (n += " "), n += f);
3194
+ else for (t in e) e[t] && (n && (n += " "), n += t);
3195
+ return n;
3196
+ }
3197
+ function clsx2() {
3198
+ for (var e, t, f = 0, n = ""; f < arguments.length; ) (e = arguments[f++]) && (t = r2(e)) && (n && (n += " "), n += t);
3199
+ return n;
3200
+ }
3067
3201
 
3068
3202
  // node_modules/class-variance-authority/dist/index.mjs
3069
- var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
3070
- var cx = clsx;
3071
- var cva = (base, config) => (props) => {
3072
- var _config_compoundVariants;
3073
- if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3074
- const { variants, defaultVariants } = config;
3075
- const getVariantClassNames = Object.keys(variants).map((variant) => {
3076
- const variantProp = props === null || props === void 0 ? void 0 : props[variant];
3077
- const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
3078
- if (variantProp === null) return null;
3079
- const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
3080
- return variants[variant][variantKey];
3081
- });
3082
- const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
3083
- let [key, value] = param;
3084
- if (value === void 0) {
3203
+ var falsyToString = (value) => typeof value === "boolean" ? "".concat(value) : value === 0 ? "0" : value;
3204
+ var cx = clsx2;
3205
+ var cva = (base, config) => {
3206
+ return (props) => {
3207
+ var ref;
3208
+ if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3209
+ const { variants, defaultVariants } = config;
3210
+ const getVariantClassNames = Object.keys(variants).map((variant) => {
3211
+ const variantProp = props === null || props === void 0 ? void 0 : props[variant];
3212
+ const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
3213
+ if (variantProp === null) return null;
3214
+ const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
3215
+ return variants[variant][variantKey];
3216
+ });
3217
+ const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
3218
+ let [key, value] = param;
3219
+ if (value === void 0) {
3220
+ return acc;
3221
+ }
3222
+ acc[key] = value;
3085
3223
  return acc;
3086
- }
3087
- acc[key] = value;
3088
- return acc;
3089
- }, {});
3090
- const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param) => {
3091
- let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;
3092
- return Object.entries(compoundVariantOptions).every((param2) => {
3093
- let [key, value] = param2;
3094
- return Array.isArray(value) ? value.includes({
3095
- ...defaultVariants,
3096
- ...propsWithoutUndefined
3097
- }[key]) : {
3098
- ...defaultVariants,
3099
- ...propsWithoutUndefined
3100
- }[key] === value;
3101
- }) ? [
3102
- ...acc,
3103
- cvClass,
3104
- cvClassName
3105
- ] : acc;
3106
- }, []);
3107
- return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3224
+ }, {});
3225
+ const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (ref = config.compoundVariants) === null || ref === void 0 ? void 0 : ref.reduce((acc, param1) => {
3226
+ let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param1;
3227
+ return Object.entries(compoundVariantOptions).every((param) => {
3228
+ let [key, value] = param;
3229
+ return Array.isArray(value) ? value.includes({
3230
+ ...defaultVariants,
3231
+ ...propsWithoutUndefined
3232
+ }[key]) : {
3233
+ ...defaultVariants,
3234
+ ...propsWithoutUndefined
3235
+ }[key] === value;
3236
+ }) ? [
3237
+ ...acc,
3238
+ cvClass,
3239
+ cvClassName
3240
+ ] : acc;
3241
+ }, []);
3242
+ return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
3243
+ };
3108
3244
  };
3109
3245
 
3110
3246
  // src/components/ui/toast.tsx
@@ -3209,18 +3345,30 @@ function Toaster() {
3209
3345
  ] }) });
3210
3346
  }
3211
3347
 
3212
- // src/types/index.ts
3213
- var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
3214
- var DATA_TYPE_NAMES = {
3215
- string: "String",
3216
- list: "List",
3217
- hash: "Hash",
3218
- set: "Set",
3219
- zset: "Sorted Set",
3220
- json: "JSON",
3221
- stream: "Stream"
3348
+ // src/components/databrowser/hooks/use-fetch-search-indexes.tsx
3349
+
3350
+ var FETCH_SEARCH_INDEXES_QUERY_KEY = "fetch-search-indexes";
3351
+ var useFetchSearchIndexes = (match) => {
3352
+ const { redisNoPipeline: redis } = useRedis();
3353
+ return _reactquery.useQuery.call(void 0, {
3354
+ queryKey: [FETCH_SEARCH_INDEXES_QUERY_KEY],
3355
+ queryFn: async () => {
3356
+ let cursor = "0";
3357
+ const finalResult = [];
3358
+ while (true) {
3359
+ const [newCursor, results] = await redis.scan(cursor, {
3360
+ count: 100,
3361
+ type: "search",
3362
+ match
3363
+ });
3364
+ finalResult.push(...results);
3365
+ if (newCursor === "0") break;
3366
+ cursor = newCursor;
3367
+ }
3368
+ return finalResult;
3369
+ }
3370
+ });
3222
3371
  };
3223
- var SIMPLE_DATA_TYPES = ["string", "json"];
3224
3372
 
3225
3373
  // src/components/databrowser/hooks/use-keys.tsx
3226
3374
 
@@ -3240,15 +3388,41 @@ var useFetchKeyType = (key) => {
3240
3388
  });
3241
3389
  };
3242
3390
 
3391
+ // src/components/databrowser/hooks/use-fetch-search-index.tsx
3392
+
3393
+ var FETCH_SEARCH_INDEX_QUERY_KEY = "fetch-search-index";
3394
+ var useFetchSearchIndex = (indexName) => {
3395
+ const { redisNoPipeline: redis } = useRedis();
3396
+ return _reactquery.useQuery.call(void 0, {
3397
+ queryKey: [FETCH_SEARCH_INDEX_QUERY_KEY, indexName],
3398
+ queryFn: async () => {
3399
+ if (!indexName) return;
3400
+ const result = await redis.search.index({
3401
+ name: indexName
3402
+ }).describe();
3403
+ return result;
3404
+ },
3405
+ enabled: Boolean(indexName)
3406
+ });
3407
+ };
3408
+
3243
3409
  // src/components/databrowser/hooks/use-keys.tsx
3244
3410
 
3245
3411
  var KeysContext = _react.createContext.call(void 0, void 0);
3246
3412
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
3247
3413
  var SCAN_COUNTS = [100, 300, 500];
3248
3414
  var KeysProvider = ({ children }) => {
3249
- const { active, search } = useTab();
3415
+ const { active, search, valuesSearch, isValuesSearchSelected } = useTab();
3416
+ const { data: searchIndexDetails, isLoading: isIndexDetailsLoading } = useFetchSearchIndex(
3417
+ valuesSearch.index
3418
+ );
3250
3419
  const { redisNoPipeline: redis } = useRedis();
3251
- const performScan = async (count2, cursor) => {
3420
+ const parsedValueQuery = parseJSObjectLiteral(valuesSearch.query);
3421
+ const isQueryEnabled = active && (isValuesSearchSelected ? Boolean(valuesSearch.index) && Boolean(searchIndexDetails) : true);
3422
+ const redisKeyScan = async ({
3423
+ count: count2,
3424
+ cursor
3425
+ }) => {
3252
3426
  const args = [cursor];
3253
3427
  if (search.key) {
3254
3428
  args.push("MATCH", search.key);
@@ -3258,7 +3432,48 @@ var KeysProvider = ({ children }) => {
3258
3432
  }
3259
3433
  args.push("COUNT", count2.toString());
3260
3434
  if (!search.type) args.push("WITHTYPE");
3261
- return await redis.exec(["SCAN", ...args]);
3435
+ const [newCursor, values] = await redis.exec(["SCAN", ...args]);
3436
+ const keys2 = [];
3437
+ let index = 0;
3438
+ while (true) {
3439
+ if (search.type) {
3440
+ if (index >= values.length) break;
3441
+ keys2.push({ key: values[index], type: search.type });
3442
+ index += 1;
3443
+ } else {
3444
+ if (index + 1 >= values.length) break;
3445
+ keys2.push({ key: values[index], type: values[index + 1] });
3446
+ index += 2;
3447
+ }
3448
+ }
3449
+ return { cursor: newCursor, keys: keys2 };
3450
+ };
3451
+ const redisValueScan = async ({
3452
+ count: count2,
3453
+ cursor
3454
+ }) => {
3455
+ if (!searchIndexDetails) throw new Error("Attempted search while loading the search index");
3456
+ const offset = Number.parseInt(cursor, 10) || 0;
3457
+ const result = await redis.search.index({
3458
+ name: valuesSearch.index
3459
+ }).query({
3460
+ filter: _nullishCoalesce(parsedValueQuery, () => ( {})),
3461
+ limit: count2,
3462
+ offset,
3463
+ select: {}
3464
+ });
3465
+ const keys2 = result.map((doc) => ({
3466
+ key: doc.key,
3467
+ type: searchIndexDetails.dataType
3468
+ }));
3469
+ const hasMore = keys2.length >= count2;
3470
+ const nextCursor = hasMore ? String(offset + keys2.length) : "0";
3471
+ return { cursor: nextCursor, keys: keys2 };
3472
+ };
3473
+ const performScan = async (count2, cursor) => {
3474
+ const scanFunction = isValuesSearchSelected ? redisValueScan : redisKeyScan;
3475
+ const result = await scanFunction({ count: count2, cursor });
3476
+ return [result.cursor, result.keys];
3262
3477
  };
3263
3478
  const scanUntilAvailable = async (cursor) => {
3264
3479
  let i = 0;
@@ -3272,25 +3487,12 @@ var KeysProvider = ({ children }) => {
3272
3487
  }
3273
3488
  };
3274
3489
  const query = _reactquery.useInfiniteQuery.call(void 0, {
3275
- queryKey: [FETCH_KEYS_QUERY_KEY, search],
3276
- // Only fetch when tab is active
3277
- enabled: active,
3490
+ queryKey: [FETCH_KEYS_QUERY_KEY, search, valuesSearch, isValuesSearchSelected],
3491
+ enabled: isQueryEnabled,
3278
3492
  initialPageParam: "0",
3279
3493
  queryFn: async ({ pageParam: lastCursor }) => {
3280
3494
  const [cursor, values] = await scanUntilAvailable(lastCursor);
3281
- const keys2 = [];
3282
- let index = 0;
3283
- while (true) {
3284
- if (search.type) {
3285
- if (index >= values.length) break;
3286
- keys2.push([values[index], search.type]);
3287
- index += 1;
3288
- } else {
3289
- if (index + 1 >= values.length) break;
3290
- keys2.push([values[index], values[index + 1]]);
3291
- index += 2;
3292
- }
3293
- }
3495
+ const keys2 = values.map((value) => [value.key, value.type]);
3294
3496
  for (const [key, type] of keys2) {
3295
3497
  queryClient.setQueryData([FETCH_KEY_TYPE_QUERY_KEY, key], type);
3296
3498
  }
@@ -3300,12 +3502,15 @@ var KeysProvider = ({ children }) => {
3300
3502
  hasNextPage: cursor !== "0"
3301
3503
  };
3302
3504
  },
3505
+ meta: {
3506
+ hideToast: true
3507
+ },
3303
3508
  select: (data) => data,
3304
3509
  getNextPageParam: ({ cursor }) => cursor,
3305
3510
  refetchOnMount: false
3306
3511
  });
3307
3512
  const keys = _react.useMemo.call(void 0, () => {
3308
- const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _21 => _21.data, 'optionalAccess', _22 => _22.pages, 'access', _23 => _23.flatMap, 'call', _24 => _24((page) => page.keys)]), () => ( []));
3513
+ const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _24 => _24.data, 'optionalAccess', _25 => _25.pages, 'access', _26 => _26.flatMap, 'call', _27 => _27((page) => page.keys)]), () => ( []));
3309
3514
  const keysSet = /* @__PURE__ */ new Set();
3310
3515
  const dedupedKeys = [];
3311
3516
  for (const key of keys2) {
@@ -3320,7 +3525,10 @@ var KeysProvider = ({ children }) => {
3320
3525
  {
3321
3526
  value: {
3322
3527
  keys,
3323
- query
3528
+ query: {
3529
+ ...query,
3530
+ isLoading: query.isLoading || isIndexDetailsLoading
3531
+ }
3324
3532
  },
3325
3533
  children
3326
3534
  }
@@ -3336,8 +3544,31 @@ var useKeys = () => {
3336
3544
  var useKeyType = (key) => {
3337
3545
  const { keys } = useKeys();
3338
3546
  const keyTuple = _react.useMemo.call(void 0, () => keys.find(([k, _]) => k === key), [keys, key]);
3339
- return _optionalChain([keyTuple, 'optionalAccess', _25 => _25[1]]);
3547
+ return _optionalChain([keyTuple, 'optionalAccess', _28 => _28[1]]);
3548
+ };
3549
+
3550
+ // src/types/index.ts
3551
+ var DATA_TYPES = [
3552
+ "string",
3553
+ "list",
3554
+ "hash",
3555
+ "set",
3556
+ "zset",
3557
+ "json",
3558
+ "stream",
3559
+ "search"
3560
+ ];
3561
+ var DATA_TYPE_NAMES = {
3562
+ string: "String",
3563
+ list: "List",
3564
+ hash: "Hash",
3565
+ set: "Set",
3566
+ zset: "Sorted Set",
3567
+ json: "JSON",
3568
+ stream: "Stream",
3569
+ search: "Search Index"
3340
3570
  };
3571
+ var SIMPLE_DATA_TYPES = ["string", "json"];
3341
3572
 
3342
3573
  // src/components/databrowser/components/display/display-list.tsx
3343
3574
 
@@ -3348,24 +3579,24 @@ var useKeyType = (key) => {
3348
3579
  var _reactslot = require('@radix-ui/react-slot');
3349
3580
 
3350
3581
  var buttonVariants = cva(
3351
- "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",
3582
+ "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",
3352
3583
  {
3353
3584
  variants: {
3354
3585
  variant: {
3355
- default: "bg-white text-black border shadow-sm border-zinc-300 hover:bg-white/70",
3586
+ default: "bg-white text-black border border-zinc-300 hover:bg-white/70",
3356
3587
  destructive: "bg-red-500 text-zinc-50 hover:bg-red-500/90",
3357
- outline: "border border-zinc-200 bg-white hover:bg-zinc-100 hover:text-zinc-900",
3358
- primary: "bg-emerald-500 text-white shadow-sm hover:bg-emerald-600",
3588
+ outline: "border border-zinc-300 bg-white hover:bg-zinc-100 hover:text-zinc-900",
3589
+ primary: "bg-emerald-500 text-white hover:bg-emerald-600",
3359
3590
  secondary: "bg-zinc-100 text-zinc-900 hover:bg-zinc-100/80",
3360
3591
  ghost: "hover:bg-black/10",
3361
3592
  link: "text-zinc-900 underline-offset-4 hover:underline"
3362
3593
  },
3363
3594
  size: {
3364
3595
  default: "h-8 px-4 py-2",
3365
- sm: "px-2 h-7 rounded-md",
3596
+ sm: "px-2 h-[26px] rounded-md",
3366
3597
  lg: "h-10 px-8 rounded-md",
3367
3598
  icon: "h-8 w-8",
3368
- "icon-sm": "h-7 w-7",
3599
+ "icon-sm": "h-[26px] w-[26px] rounded-md",
3369
3600
  "icon-xs": "h-5 w-5"
3370
3601
  }
3371
3602
  },
@@ -3385,37 +3616,6 @@ Button.displayName = "Button";
3385
3616
 
3386
3617
  // src/components/databrowser/hooks/use-add-key.ts
3387
3618
 
3388
-
3389
- // src/components/databrowser/components/sidebar/db-size.tsx
3390
-
3391
-
3392
- // src/components/ui/skeleton.tsx
3393
-
3394
- function Skeleton({ className, ...props }) {
3395
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse rounded-md bg-zinc-900/10", className), ...props });
3396
- }
3397
-
3398
- // src/components/databrowser/components/sidebar/db-size.tsx
3399
-
3400
- var FETCH_DB_SIZE_QUERY_KEY = "fetch-db-size";
3401
- var DisplayDbSize = () => {
3402
- const { redis } = useRedis();
3403
- const { data: keyCount } = _reactquery.useQuery.call(void 0, {
3404
- queryKey: [FETCH_DB_SIZE_QUERY_KEY],
3405
- queryFn: async () => {
3406
- return await redis.dbsize();
3407
- }
3408
- });
3409
- if (keyCount === void 0) {
3410
- 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" }) });
3411
- }
3412
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "", children: [
3413
- formatNumber(keyCount),
3414
- " Keys"
3415
- ] });
3416
- };
3417
-
3418
- // src/components/databrowser/hooks/use-add-key.ts
3419
3619
  var useAddKey = () => {
3420
3620
  const { redis } = useRedis();
3421
3621
  const mutation = _reactquery.useMutation.call(void 0, {
@@ -3465,9 +3665,6 @@ var useAddKey = () => {
3465
3665
  }
3466
3666
  },
3467
3667
  onSuccess: (_, { key, type }) => {
3468
- queryClient.invalidateQueries({
3469
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3470
- });
3471
3668
  queryClient.setQueriesData(
3472
3669
  {
3473
3670
  queryKey: [FETCH_KEYS_QUERY_KEY]
@@ -3580,7 +3777,7 @@ var useFetchListItems = ({ dataKey, type }) => {
3580
3777
  // +1 since first message is the last one
3581
3778
  LIST_DISPLAY_PAGE_SIZE + 1
3582
3779
  );
3583
- const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _26 => _26.at, 'call', _27 => _27(-1), 'optionalAccess', _28 => _28[0]]) : void 0;
3780
+ const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _29 => _29.at, 'call', _30 => _30(-1), 'optionalAccess', _31 => _31[0]]) : void 0;
3584
3781
  return {
3585
3782
  cursor: messages.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastMessageId,
3586
3783
  keys: messages.map(([id, fields]) => ({
@@ -3675,9 +3872,6 @@ var useDeleteKey = () => {
3675
3872
  },
3676
3873
  onSuccess: (_, key) => {
3677
3874
  deleteKeyCache(key);
3678
- queryClient.invalidateQueries({
3679
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
3680
- });
3681
3875
  }
3682
3876
  });
3683
3877
  return deleteKey;
@@ -3744,7 +3938,7 @@ var useEditListItem = () => {
3744
3938
  }
3745
3939
  case "stream": {
3746
3940
  if (!isNew || !newKey) throw new Error("Stream data type is not mutable");
3747
- const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _29 => _29.split, 'call', _30 => _30("\n")]), () => ( []))).map(
3941
+ const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _32 => _32.split, 'call', _33 => _33("\n")]), () => ( []))).map(
3748
3942
  ({ key, value }) => [key, value]
3749
3943
  );
3750
3944
  pipe.xadd(dataKey, newKey, Object.fromEntries(opts));
@@ -3772,6 +3966,12 @@ var useEditListItem = () => {
3772
3966
 
3773
3967
 
3774
3968
 
3969
+ // src/components/ui/skeleton.tsx
3970
+
3971
+ function Skeleton({ className, ...props }) {
3972
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("animate-pulse rounded-md bg-zinc-900/10", className), ...props });
3973
+ }
3974
+
3775
3975
  // src/components/databrowser/components/display/header-badges.tsx
3776
3976
  var _bytes = require('bytes'); var _bytes2 = _interopRequireDefault(_bytes);
3777
3977
 
@@ -3799,6 +3999,9 @@ var useFetchKeyLength = ({ dataKey, type }) => {
3799
3999
  case "stream": {
3800
4000
  return await redis.xlen(dataKey);
3801
4001
  }
4002
+ case "search": {
4003
+ return null;
4004
+ }
3802
4005
  }
3803
4006
  return null;
3804
4007
  }
@@ -3826,7 +4029,7 @@ var LengthBadge = ({
3826
4029
  content
3827
4030
  }) => {
3828
4031
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
3829
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _31 => _31.length]), () => ( data));
4032
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _34 => _34.length]), () => ( data));
3830
4033
  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 });
3831
4034
  };
3832
4035
  var SizeBadge = ({ dataKey }) => {
@@ -3847,8 +4050,8 @@ var HeaderTTLBadge = ({ dataKey }) => {
3847
4050
  }
3848
4051
  );
3849
4052
  };
3850
- 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: [
3851
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500 dark:text-zinc-600", children: label }),
4053
+ 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: [
4054
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500 dark:text-zinc-500", children: label }),
3852
4055
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children })
3853
4056
  ] });
3854
4057
 
@@ -3910,7 +4113,7 @@ var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =
3910
4113
  {
3911
4114
  ref,
3912
4115
  className: cn(
3913
- "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",
4116
+ "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",
3914
4117
  className
3915
4118
  ),
3916
4119
  ...props,
@@ -3984,7 +4187,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
3984
4187
  ),
3985
4188
  ...props,
3986
4189
  children: [
3987
- /* @__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,
4190
+ /* @__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,
3988
4191
  "svg",
3989
4192
  {
3990
4193
  width: "15",
@@ -4003,7 +4206,7 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
4003
4206
  }
4004
4207
  )
4005
4208
  }
4006
- ) }) }) }),
4209
+ ) }) }),
4007
4210
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children })
4008
4211
  ]
4009
4212
  }
@@ -4178,9 +4381,9 @@ var TTLBadge = ({
4178
4381
  }, 1e3);
4179
4382
  return () => clearInterval(interval);
4180
4383
  }, [expireAt]);
4181
- 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: [
4182
- ttl === TTL_INFINITE ? "Forever" : formatTime(ttl),
4183
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "mt-[1px] text-zinc-400", size: 12 })
4384
+ 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: [
4385
+ ttl === TTL_INFINITE ? "No" : formatTime(ttl),
4386
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "shrink-0 text-zinc-400", size: 16 })
4184
4387
  ] }) }) });
4185
4388
  };
4186
4389
 
@@ -4250,9 +4453,9 @@ var useSetTTL = () => {
4250
4453
 
4251
4454
  // src/components/databrowser/components/item-context-menu.tsx
4252
4455
 
4253
-
4254
4456
  var _reactcontextmenu = require('@radix-ui/react-context-menu'); var ContextMenuPrimitive = _interopRequireWildcard(_reactcontextmenu);
4255
4457
 
4458
+
4256
4459
  // src/components/ui/context-menu.tsx
4257
4460
 
4258
4461
 
@@ -4464,7 +4667,8 @@ function DeleteAlertDialog({
4464
4667
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
4465
4668
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: isPlural ? `Delete ${count2} ${itemsLabel}` : `Delete ${itemLabel}` }),
4466
4669
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
4467
- "Are you sure you want to delete ",
4670
+ "Are you sure you want to delete",
4671
+ " ",
4468
4672
  isPlural ? `these ${count2} ${deletionType}s` : `this ${deletionType}`,
4469
4673
  "?",
4470
4674
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
@@ -4510,7 +4714,7 @@ var ItemContextMenu = ({
4510
4714
  editItem({
4511
4715
  type,
4512
4716
  dataKey,
4513
- itemKey: _optionalChain([data, 'optionalAccess', _32 => _32.key]),
4717
+ itemKey: _optionalChain([data, 'optionalAccess', _35 => _35.key]),
4514
4718
  // For deletion
4515
4719
  newKey: void 0
4516
4720
  });
@@ -4545,7 +4749,7 @@ var ItemContextMenu = ({
4545
4749
  {
4546
4750
  onClick: () => {
4547
4751
  if (!data) return;
4548
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _33 => _33.key]));
4752
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _36 => _36.key]));
4549
4753
  toast({
4550
4754
  description: "Key copied to clipboard"
4551
4755
  });
@@ -4557,11 +4761,11 @@ var ItemContextMenu = ({
4557
4761
  ]
4558
4762
  }
4559
4763
  ),
4560
- _optionalChain([data, 'optionalAccess', _34 => _34.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4764
+ _optionalChain([data, 'optionalAccess', _37 => _37.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4561
4765
  ContextMenuItem,
4562
4766
  {
4563
4767
  onClick: () => {
4564
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _35 => _35.value]), () => ( "")));
4768
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _38 => _38.value]), () => ( "")));
4565
4769
  toast({
4566
4770
  description: "Value copied to clipboard"
4567
4771
  });
@@ -4618,33 +4822,38 @@ var ItemContextMenu = ({
4618
4822
 
4619
4823
  var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
4620
4824
 
4621
- var ScrollArea = React9.forwardRef(({ className, children, onScroll, disableRoundedInherit = false, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4622
- ScrollAreaPrimitive.Root,
4623
- {
4624
- ref,
4625
- className: cn("relative overflow-hidden", className),
4626
- ...props,
4627
- children: [
4628
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4629
- ScrollAreaPrimitive.Viewport,
4630
- {
4631
- onScroll,
4632
- className: cn("h-full w-full [&>div]:!block", !disableRoundedInherit && "rounded-[inherit]"),
4633
- children
4634
- }
4635
- ),
4636
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, {}),
4637
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4638
- ]
4639
- }
4640
- ));
4825
+ var ScrollArea = React9.forwardRef(
4826
+ ({ className, scrollBarClassName, children, onScroll, disableRoundedInherit = false, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4827
+ ScrollAreaPrimitive.Root,
4828
+ {
4829
+ ref,
4830
+ className: cn("relative overflow-hidden", className),
4831
+ ...props,
4832
+ children: [
4833
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4834
+ ScrollAreaPrimitive.Viewport,
4835
+ {
4836
+ onScroll,
4837
+ className: cn(
4838
+ "h-full w-full [&>div]:!block",
4839
+ !disableRoundedInherit && "rounded-[inherit]"
4840
+ ),
4841
+ children
4842
+ }
4843
+ ),
4844
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, { className: scrollBarClassName }),
4845
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4846
+ ]
4847
+ }
4848
+ )
4849
+ );
4641
4850
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
4642
4851
  var ScrollBar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4643
4852
  ScrollAreaPrimitive.ScrollAreaScrollbar,
4644
4853
  {
4645
4854
  ref,
4646
4855
  orientation: "vertical",
4647
- className: cn("flex h-full w-2 touch-none select-none transition-colors", className),
4856
+ className: cn("mr-1 flex h-full w-2 touch-none select-none transition-colors", className),
4648
4857
  ...props,
4649
4858
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4650
4859
  ScrollAreaPrimitive.ScrollAreaThumb,
@@ -4695,10 +4904,7 @@ var InfiniteScroll = ({
4695
4904
  type: "always",
4696
4905
  onScroll: handleScroll,
4697
4906
  ...props,
4698
- className: cn(
4699
- "block h-full w-full overflow-visible rounded-lg border border-zinc-200 bg-white p-1 pr-3 transition-all",
4700
- props.className
4701
- ),
4907
+ className: cn("block h-full w-full overflow-visible transition-all", props.className),
4702
4908
  ref: scrollRef,
4703
4909
  children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref: contentRef, children: [
4704
4910
  children,
@@ -4752,6 +4958,7 @@ var SimpleTooltip = ({
4752
4958
 
4753
4959
 
4754
4960
 
4961
+
4755
4962
  var iconsMap = {
4756
4963
  string: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconQuote, { size: 15, stroke: 1.2 }),
4757
4964
  set: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLayersIntersect, { size: 15, stroke: 1.2 }),
@@ -4759,7 +4966,8 @@ var iconsMap = {
4759
4966
  json: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCodeDots, { size: 15, stroke: 1.2 }),
4760
4967
  zset: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconArrowsSort, { size: 15, stroke: 1.2 }),
4761
4968
  list: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 }),
4762
- stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 })
4969
+ stream: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconList, { size: 15, stroke: 1.2 }),
4970
+ search: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 15, stroke: 1.2 })
4763
4971
  };
4764
4972
  var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-center", {
4765
4973
  variants: {
@@ -4771,11 +4979,12 @@ var tagVariants = cva("inline-flex shrink-0 items-center rounded-md justify-cent
4771
4979
  json: "bg-purple-200 text-purple-800",
4772
4980
  list: "bg-orange-200 text-orange-800",
4773
4981
  stream: "bg-green-200 text-green-800",
4982
+ search: "bg-rose-200 text-rose-800",
4774
4983
  default: "bg-gray-200 text-gray-800"
4775
4984
  },
4776
4985
  type: {
4777
4986
  icon: "size-5",
4778
- badge: "h-6 px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4987
+ badge: "h-[26px] px-2 uppercase whitespace-nowrap text-xs font-medium leading-none tracking-wide"
4779
4988
  }
4780
4989
  },
4781
4990
  defaultVariants: {
@@ -4916,7 +5125,13 @@ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4916
5125
  function KeyActions({ dataKey, content }) {
4917
5126
  const { mutateAsync: deleteKey } = useDeleteKey();
4918
5127
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { modal: false, children: [
4919
- /* @__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" }) }) }),
5128
+ /* @__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,
5129
+ _iconsreact.IconDotsVertical,
5130
+ {
5131
+ className: "size-4 text-zinc-500 dark:text-zinc-600",
5132
+ fill: "rgb(var(--color-zinc-500))"
5133
+ }
5134
+ ) }) }),
4920
5135
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { className: "", align: "end", children: [
4921
5136
  content && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4922
5137
  DropdownMenuItem,
@@ -4969,15 +5184,15 @@ var DisplayHeader = ({
4969
5184
  const handleAddItem = () => {
4970
5185
  setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true });
4971
5186
  };
4972
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
4973
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
4974
- /* @__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 }) }),
5187
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg", children: [
5188
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-[26px] items-center justify-between gap-4", children: [
5189
+ /* @__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 }) }),
4975
5190
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
4976
- 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" }) }) }),
5191
+ 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" }) }) }),
4977
5192
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content })
4978
5193
  ] })
4979
5194
  ] }),
4980
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 flex-wrap items-center gap-1.5", children: [
5195
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-1.5 overflow-scroll", children: [
4981
5196
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }),
4982
5197
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SizeBadge, { dataKey }),
4983
5198
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LengthBadge, { dataKey, type, content }),
@@ -5049,7 +5264,7 @@ var useSetHashTTL = () => {
5049
5264
  var HashFieldTTLBadge = ({ dataKey, field }) => {
5050
5265
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
5051
5266
  const { mutate: setTTL, isPending } = useSetHashTTL();
5052
- const expireAt = _optionalChain([data, 'optionalAccess', _36 => _36[field]]);
5267
+ const expireAt = _optionalChain([data, 'optionalAccess', _39 => _39[field]]);
5053
5268
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5054
5269
  TTLBadge,
5055
5270
  {
@@ -5146,7 +5361,7 @@ var MonacoEditor = ({
5146
5361
  if (!active || !monaco || !editorRef.current) {
5147
5362
  return;
5148
5363
  }
5149
- _optionalChain([monaco, 'optionalAccess', _37 => _37.editor, 'access', _38 => _38.setModelLanguage, 'call', _39 => _39(editorRef.current.getModel(), language)]);
5364
+ _optionalChain([monaco, 'optionalAccess', _40 => _40.editor, 'access', _41 => _41.setModelLanguage, 'call', _42 => _42(editorRef.current.getModel(), language)]);
5150
5365
  }, [monaco, language, active]);
5151
5366
  const editor = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5152
5367
  _react2.Editor,
@@ -5287,7 +5502,7 @@ var checkIsValidJSON = (value) => {
5287
5502
  try {
5288
5503
  JSON.parse(value);
5289
5504
  return true;
5290
- } catch (e3) {
5505
+ } catch (e4) {
5291
5506
  return false;
5292
5507
  }
5293
5508
  };
@@ -5311,7 +5526,7 @@ var ListEditForm = ({
5311
5526
  dataKey
5312
5527
  });
5313
5528
  const findValue = () => {
5314
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _40 => _40.data, 'optionalAccess', _41 => _41.pages]), () => ( []))) {
5529
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _43 => _43.data, 'optionalAccess', _44 => _44.pages]), () => ( []))) {
5315
5530
  const item = page.keys.find((item2) => item2.key === itemKey);
5316
5531
  if (item && "value" in item) return item.value;
5317
5532
  }
@@ -5457,7 +5672,7 @@ var HashFieldTTLInfo = ({
5457
5672
  fields
5458
5673
  }) => {
5459
5674
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
5460
- const expireAt = _optionalChain([data, 'optionalAccess', _42 => _42[field]]);
5675
+ const expireAt = _optionalChain([data, 'optionalAccess', _45 => _45[field]]);
5461
5676
  const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
5462
5677
  _react.useEffect.call(void 0, () => {
5463
5678
  setTTL(calculateTTL(expireAt));
@@ -5485,7 +5700,7 @@ var ListDisplay = ({ dataKey, type }) => {
5485
5700
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: [
5486
5701
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type }),
5487
5702
  selectedListItem && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditDisplay, { dataKey, type, item: selectedListItem }),
5488
- /* @__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 }) }) }) }) }) })
5703
+ /* @__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 }) }) }) }) }) })
5489
5704
  ] });
5490
5705
  };
5491
5706
  var ListItems = ({
@@ -5494,7 +5709,7 @@ var ListItems = ({
5494
5709
  dataKey
5495
5710
  }) => {
5496
5711
  const { setSelectedListItem } = useTab();
5497
- 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]);
5712
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _46 => _46.data, 'optionalAccess', _47 => _47.pages, 'access', _48 => _48.flatMap, 'call', _49 => _49((page) => page.keys)]), () => ( [])), [query.data]);
5498
5713
  const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
5499
5714
  const { mutate: editItem } = useEditListItem();
5500
5715
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -5506,7 +5721,7 @@ var ListItems = ({
5506
5721
  setSelectedListItem({ key });
5507
5722
  },
5508
5723
  className: cn(
5509
- "h-10 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100 dark:border-b-zinc-200 dark:hover:bg-zinc-200"
5724
+ "h-9 border-b border-b-zinc-100 transition-colors hover:bg-zinc-100 dark:border-b-zinc-200 dark:hover:bg-zinc-200"
5510
5725
  ),
5511
5726
  children: [
5512
5727
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5570,6 +5785,17 @@ var ListItems = ({
5570
5785
  )) });
5571
5786
  };
5572
5787
 
5788
+ // src/components/databrowser/components/display/display-search.tsx
5789
+
5790
+ var SearchDisplay = ({ dataKey, type }) => {
5791
+ const { data, isLoading } = useFetchSearchIndex(dataKey);
5792
+ const content = data ? JSON.stringify(data, null, 2) : void 0;
5793
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full flex-col gap-2", children: [
5794
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type, content }),
5795
+ /* @__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) }) }) })
5796
+ ] });
5797
+ };
5798
+
5573
5799
  // src/components/databrowser/components/display/display-simple.tsx
5574
5800
 
5575
5801
 
@@ -5625,10 +5851,10 @@ var DataDisplay = () => {
5625
5851
  const { selectedKey } = useTab();
5626
5852
  const { query } = useKeys();
5627
5853
  const type = useKeyType(selectedKey);
5628
- 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", {}) : !DATA_TYPES.includes(type) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "text-zinc-500", children: [
5854
+ 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", {}) : !DATA_TYPES.includes(type) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "text-zinc-500", children: [
5629
5855
  "Unrecognized key type: ",
5630
5856
  type
5631
- ] }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: SIMPLE_DATA_TYPES.includes(type) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplay, { dataKey: selectedKey, type }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListDisplay, { dataKey: selectedKey, type }) }) });
5857
+ ] }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: SIMPLE_DATA_TYPES.includes(type) ? /* @__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 }) }) });
5632
5858
  };
5633
5859
 
5634
5860
  // src/components/databrowser/components/add-key-modal.tsx
@@ -5636,6 +5862,7 @@ var DataDisplay = () => {
5636
5862
  var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
5637
5863
 
5638
5864
 
5865
+
5639
5866
  // src/components/ui/dialog.tsx
5640
5867
 
5641
5868
 
@@ -5739,7 +5966,6 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
5739
5966
 
5740
5967
  // src/components/databrowser/components/add-key-modal.tsx
5741
5968
 
5742
-
5743
5969
  function AddKeyModal() {
5744
5970
  const { setSelectedKey } = useTab();
5745
5971
  const [open, setOpen] = _react.useState.call(void 0, false);
@@ -5755,7 +5981,7 @@ function AddKeyModal() {
5755
5981
  setSelectedKey(key);
5756
5982
  setOpen(false);
5757
5983
  setTimeout(() => {
5758
- _optionalChain([window, 'access', _47 => _47.document, 'access', _48 => _48.querySelector, 'call', _49 => _49(`[data-key="${key}"]`), 'optionalAccess', _50 => _50.scrollIntoView, 'call', _51 => _51({
5984
+ _optionalChain([window, 'access', _50 => _50.document, 'access', _51 => _51.querySelector, 'call', _52 => _52(`[data-key="${key}"]`), 'optionalAccess', _53 => _53.scrollIntoView, 'call', _54 => _54({
5759
5985
  behavior: "smooth",
5760
5986
  block: "start",
5761
5987
  inline: "nearest"
@@ -5771,7 +5997,18 @@ function AddKeyModal() {
5771
5997
  setOpen(open2);
5772
5998
  },
5773
5999
  children: [
5774
- /* @__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" }) }) }) }),
6000
+ /* @__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,
6001
+ Button,
6002
+ {
6003
+ variant: "primary",
6004
+ "data-testid": "add-key-button",
6005
+ className: "flex h-8 items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
6006
+ children: [
6007
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-5" }),
6008
+ "Key"
6009
+ ]
6010
+ }
6011
+ ) }) }),
5775
6012
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-[400px]", children: [
5776
6013
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new key" }) }),
5777
6014
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactdialog.DialogDescription, { children: "Create new key" }) }),
@@ -5784,7 +6021,7 @@ function AddKeyModal() {
5784
6021
  name: "type",
5785
6022
  render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: field.value, onValueChange: field.onChange, children: [
5786
6023
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-8 w-auto pl-[3px] pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
5787
- /* @__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)) }) })
6024
+ /* @__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)) }) })
5788
6025
  ] })
5789
6026
  }
5790
6027
  ),
@@ -5800,7 +6037,7 @@ function AddKeyModal() {
5800
6037
  }
5801
6038
  )
5802
6039
  ] }),
5803
- 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]) }),
6040
+ 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]) }),
5804
6041
  /* @__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" }),
5805
6042
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5806
6043
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5823,191 +6060,7 @@ function AddKeyModal() {
5823
6060
  );
5824
6061
  }
5825
6062
 
5826
- // src/components/databrowser/components/sidebar/empty.tsx
5827
-
5828
- var Empty = () => {
5829
- 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: [
5830
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-md font-medium", children: "Data on a break" }),
5831
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
5832
- ] }) });
5833
- };
5834
-
5835
- // src/components/databrowser/components/sidebar/keys-list.tsx
5836
-
5837
-
5838
- // src/components/databrowser/components/sidebar-context-menu.tsx
5839
-
5840
-
5841
-
5842
-
5843
- var SidebarContextMenu = ({ children }) => {
5844
- const { mutate: deleteKey } = useDeleteKey();
5845
- const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
5846
- const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
5847
- const { addTab, setSelectedKey: setSelectedKeyGlobal, selectTab, setSearch } = useDatabrowserStore();
5848
- const { search: currentSearch, selectedKeys } = useTab();
5849
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5850
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5851
- DeleteAlertDialog,
5852
- {
5853
- deletionType: "key",
5854
- count: contextKeys.length,
5855
- open: isAlertOpen,
5856
- onOpenChange: setAlertOpen,
5857
- onDeleteConfirm: (e) => {
5858
- e.stopPropagation();
5859
- for (const key of contextKeys) {
5860
- deleteKey(key);
5861
- }
5862
- setAlertOpen(false);
5863
- }
5864
- }
5865
- ),
5866
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { modal: false, children: [
5867
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5868
- ContextMenuTrigger,
5869
- {
5870
- onContextMenu: (e) => {
5871
- const el = e.target;
5872
- const key = el.closest("[data-key]");
5873
- if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
5874
- const clickedKey = key.dataset.key;
5875
- if (selectedKeys.includes(clickedKey)) {
5876
- setContextKeys(selectedKeys);
5877
- } else {
5878
- setContextKeys([clickedKey]);
5879
- }
5880
- } else {
5881
- throw new Error("Key not found");
5882
- }
5883
- },
5884
- children
5885
- }
5886
- ),
5887
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
5888
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5889
- ContextMenuItem,
5890
- {
5891
- onClick: () => {
5892
- navigator.clipboard.writeText(contextKeys[0]);
5893
- toast({
5894
- description: "Key copied to clipboard"
5895
- });
5896
- },
5897
- className: "gap-2",
5898
- disabled: contextKeys.length !== 1,
5899
- children: [
5900
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCopy, { size: 16 }),
5901
- "Copy key"
5902
- ]
5903
- }
5904
- ),
5905
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5906
- ContextMenuItem,
5907
- {
5908
- onClick: () => {
5909
- const newTabId = addTab();
5910
- setSelectedKeyGlobal(newTabId, contextKeys[0]);
5911
- setSearch(newTabId, currentSearch);
5912
- selectTab(newTabId);
5913
- },
5914
- className: "gap-2",
5915
- disabled: contextKeys.length !== 1,
5916
- children: [
5917
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 16 }),
5918
- "Open in new tab"
5919
- ]
5920
- }
5921
- ),
5922
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
5923
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuItem, { onClick: () => setAlertOpen(true), className: "gap-2", children: [
5924
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { size: 16 }),
5925
- contextKeys.length > 1 ? `Delete ${contextKeys.length} keys` : "Delete key"
5926
- ] })
5927
- ] })
5928
- ] })
5929
- ] });
5930
- };
5931
-
5932
- // src/components/databrowser/components/sidebar/keys-list.tsx
5933
-
5934
- var KeysList = () => {
5935
- const { keys } = useKeys();
5936
- const lastClickedIndexRef = _react.useRef.call(void 0, null);
5937
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5938
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px" }),
5939
- keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
5940
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5941
- KeyItem,
5942
- {
5943
- index: i,
5944
- data,
5945
- allKeys: keys,
5946
- lastClickedIndexRef
5947
- }
5948
- ),
5949
- 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" })
5950
- ] }, data[0]))
5951
- ] }) });
5952
- };
5953
- var keyStyles = {
5954
- string: "border-sky-400 !bg-sky-50 text-sky-900",
5955
- hash: "border-amber-400 !bg-amber-50 text-amber-900",
5956
- set: "border-indigo-400 !bg-indigo-50 text-indigo-900",
5957
- zset: "border-pink-400 !bg-pink-50 text-pink-900",
5958
- json: "border-purple-400 !bg-purple-50 text-purple-900",
5959
- list: "border-orange-400 !bg-orange-50 text-orange-900",
5960
- stream: "border-green-400 !bg-green-50 text-green-900"
5961
- };
5962
- var defaultKeyStyle = "border-gray-400 !bg-gray-50 text-gray-900";
5963
- var KeyItem = ({
5964
- data,
5965
- index,
5966
- allKeys,
5967
- lastClickedIndexRef
5968
- }) => {
5969
- const { selectedKeys, setSelectedKeys, setSelectedKey } = useTab();
5970
- const [dataKey, dataType] = data;
5971
- const isKeySelected = selectedKeys.includes(dataKey);
5972
- const handleClick = (e) => {
5973
- if (e.shiftKey && lastClickedIndexRef.current !== null) {
5974
- const start = Math.min(lastClickedIndexRef.current, index);
5975
- const end = Math.max(lastClickedIndexRef.current, index);
5976
- const rangeKeys = allKeys.slice(start, end + 1).map(([key]) => key);
5977
- setSelectedKeys(rangeKeys);
5978
- } else if (e.metaKey || e.ctrlKey) {
5979
- if (isKeySelected) {
5980
- setSelectedKeys(selectedKeys.filter((k) => k !== dataKey));
5981
- } else {
5982
- setSelectedKeys([...selectedKeys, dataKey]);
5983
- }
5984
- lastClickedIndexRef.current = index;
5985
- } else {
5986
- setSelectedKey(dataKey);
5987
- lastClickedIndexRef.current = index;
5988
- }
5989
- };
5990
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5991
- Button,
5992
- {
5993
- "data-key": dataKey,
5994
- variant: isKeySelected ? "default" : "ghost",
5995
- className: cn(
5996
- "relative flex h-10 w-full items-center justify-start gap-2 px-3 py-0 !ring-0 focus-visible:bg-zinc-50",
5997
- "-my-px select-none border border-transparent text-left",
5998
- isKeySelected && "shadow-sm",
5999
- isKeySelected && (_nullishCoalesce(keyStyles[dataType], () => ( defaultKeyStyle)))
6000
- ),
6001
- onClick: handleClick,
6002
- children: [
6003
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: dataType, type: "icon" }),
6004
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "truncate whitespace-nowrap", children: dataKey })
6005
- ]
6006
- }
6007
- );
6008
- };
6009
-
6010
- // src/components/databrowser/components/sidebar/reload-button.tsx
6063
+ // src/components/databrowser/components/sidebar/reload-button.tsx
6011
6064
 
6012
6065
 
6013
6066
 
@@ -6027,10 +6080,10 @@ var ReloadButton = ({
6027
6080
  Button,
6028
6081
  {
6029
6082
  variant: "outline",
6030
- size: "icon-sm",
6083
+ size: "icon",
6031
6084
  onClick: handleClick,
6032
6085
  disabled: isLoading || isLoadingProp,
6033
- 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 })
6086
+ 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" })
6034
6087
  }
6035
6088
  ) }) });
6036
6089
  };
@@ -6074,7 +6127,7 @@ var SearchInput = () => {
6074
6127
  } else if (e.key === "Escape") {
6075
6128
  setState("");
6076
6129
  setFocusedIndex(-1);
6077
- _optionalChain([inputRef, 'access', _55 => _55.current, 'optionalAccess', _56 => _56.blur, 'call', _57 => _57()]);
6130
+ _optionalChain([inputRef, 'access', _58 => _58.current, 'optionalAccess', _59 => _59.blur, 'call', _60 => _60()]);
6078
6131
  } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
6079
6132
  e.preventDefault();
6080
6133
  if (focusedIndex < filteredHistory.length - 1) {
@@ -6088,7 +6141,7 @@ var SearchInput = () => {
6088
6141
  setFocusedIndex(focusedIndex - 1);
6089
6142
  } else if (filteredHistory.length > 0 && focusedIndex === 0) {
6090
6143
  setFocusedIndex(-1);
6091
- _optionalChain([inputRef, 'access', _58 => _58.current, 'optionalAccess', _59 => _59.focus, 'call', _60 => _60()]);
6144
+ _optionalChain([inputRef, 'access', _61 => _61.current, 'optionalAccess', _62 => _62.focus, 'call', _63 => _63()]);
6092
6145
  } else if (filteredHistory.length > 0) {
6093
6146
  setFocusedIndex(filteredHistory.length - 1);
6094
6147
  }
@@ -6096,170 +6149,2336 @@ var SearchInput = () => {
6096
6149
  };
6097
6150
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
6098
6151
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
6099
- /* @__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,
6152
+ /* @__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,
6100
6153
  Input,
6101
6154
  {
6102
- ref: inputRef,
6103
- placeholder: "Search",
6104
- className: "h-full rounded-l-none border-none pr-6",
6105
- onKeyDown: handleKeyDown,
6106
- onChange: (e) => {
6107
- setState(e.currentTarget.value);
6108
- if (e.currentTarget.value.trim() === "") handleSubmit("");
6109
- },
6110
- value: state,
6111
- onFocus: () => {
6112
- setIsFocus(true);
6113
- setFocusedIndex(-1);
6114
- },
6115
- onBlur: () => setIsFocus(false)
6155
+ ref: inputRef,
6156
+ placeholder: "Search",
6157
+ className: "h-full border-none pr-6",
6158
+ onKeyDown: handleKeyDown,
6159
+ onChange: (e) => {
6160
+ setState(e.currentTarget.value);
6161
+ if (e.currentTarget.value.trim() === "") handleSubmit("");
6162
+ },
6163
+ value: state,
6164
+ onFocus: () => {
6165
+ setIsFocus(true);
6166
+ setFocusedIndex(-1);
6167
+ },
6168
+ onBlur: () => setIsFocus(false)
6169
+ }
6170
+ ) }) }),
6171
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6172
+ PopoverContent,
6173
+ {
6174
+ className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
6175
+ autoFocus: false,
6176
+ onOpenAutoFocus: (e) => {
6177
+ e.preventDefault();
6178
+ e.stopPropagation();
6179
+ },
6180
+ children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6181
+ "button",
6182
+ {
6183
+ ref: (el) => {
6184
+ historyItemRefs.current[index] = el;
6185
+ },
6186
+ onClick: () => handleSubmit(item),
6187
+ onMouseEnter: () => setFocusedIndex(index),
6188
+ className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
6189
+ children: item
6190
+ }
6191
+ ) }, item))
6192
+ }
6193
+ )
6194
+ ] }),
6195
+ state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6196
+ Button,
6197
+ {
6198
+ type: "button",
6199
+ variant: "link",
6200
+ size: "icon",
6201
+ className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
6202
+ onClick: () => {
6203
+ setSearchKey("");
6204
+ setState("");
6205
+ },
6206
+ children: [
6207
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
6208
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
6209
+ ]
6210
+ }
6211
+ ),
6212
+ " "
6213
+ ] });
6214
+ };
6215
+
6216
+ // src/components/databrowser/components/sidebar/type-selector.tsx
6217
+
6218
+ var ALL_TYPES_KEY = "all";
6219
+ function DataTypeSelector() {
6220
+ const { search, setSearchType } = useTab();
6221
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6222
+ Select,
6223
+ {
6224
+ onValueChange: (type) => {
6225
+ if (type === ALL_TYPES_KEY) {
6226
+ setSearchType(void 0);
6227
+ } else {
6228
+ setSearchType(type);
6229
+ }
6230
+ },
6231
+ value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
6232
+ children: [
6233
+ /* @__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, {}) }),
6234
+ /* @__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(
6235
+ ([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)
6236
+ ) }) })
6237
+ ]
6238
+ }
6239
+ );
6240
+ }
6241
+
6242
+ // src/components/databrowser/components/header/index.tsx
6243
+
6244
+ var Header = () => {
6245
+ const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
6246
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-1.5", children: [
6247
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow items-center gap-1.5", children: [
6248
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6249
+ Segmented,
6250
+ {
6251
+ options: [
6252
+ {
6253
+ key: "keys",
6254
+ label: "Keys"
6255
+ },
6256
+ {
6257
+ key: "values",
6258
+ label: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
6259
+ "Search",
6260
+ /* @__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" })
6261
+ ] })
6262
+ }
6263
+ ],
6264
+ value: isValuesSearchSelected ? "values" : "keys",
6265
+ onChange: (value) => {
6266
+ setIsValuesSearchSelected(value === "values");
6267
+ }
6268
+ }
6269
+ ),
6270
+ isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IndexSelector, {}) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6271
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, {}),
6272
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
6273
+ ] })
6274
+ ] }),
6275
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1.5", children: [
6276
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RefreshButton, {}),
6277
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
6278
+ ] })
6279
+ ] });
6280
+ };
6281
+ var IndexSelector = () => {
6282
+ const {
6283
+ valuesSearch: { index },
6284
+ setValuesSearchIndex
6285
+ } = useTab();
6286
+ const { data } = useFetchSearchIndexes();
6287
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex", children: [
6288
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center rounded-l-lg border border-r-0 border-zinc-300 bg-white px-3 text-sm text-zinc-700", children: "Index" }),
6289
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6290
+ Select,
6291
+ {
6292
+ value: index,
6293
+ onValueChange: (value) => {
6294
+ setValuesSearchIndex(value);
6295
+ },
6296
+ children: [
6297
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "w-auto select-none whitespace-nowrap rounded-l-none border-zinc-300 bg-emerald-50 pr-8 text-sm font-medium text-emerald-800", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, { placeholder: "Select an index" }) }),
6298
+ /* @__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))]) }) })
6299
+ ]
6300
+ }
6301
+ )
6302
+ ] });
6303
+ };
6304
+ var RefreshButton = () => {
6305
+ const { query } = useKeys();
6306
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6307
+ ReloadButton,
6308
+ {
6309
+ onClick: () => {
6310
+ queryClient.invalidateQueries({
6311
+ queryKey: [FETCH_KEYS_QUERY_KEY]
6312
+ });
6313
+ queryClient.invalidateQueries({
6314
+ queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
6315
+ });
6316
+ queryClient.invalidateQueries({
6317
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
6318
+ });
6319
+ queryClient.invalidateQueries({
6320
+ queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
6321
+ });
6322
+ },
6323
+ isLoading: query.isFetching
6324
+ }
6325
+ );
6326
+ };
6327
+
6328
+ // src/components/databrowser/components/header-error.tsx
6329
+
6330
+ var formatUpstashErrorMessage = (error) => {
6331
+ if (error.name !== "UpstashError") return error.message;
6332
+ const commandIndex = error.message.indexOf(", command was:");
6333
+ if (commandIndex !== -1) {
6334
+ return error.message.slice(0, commandIndex);
6335
+ }
6336
+ return error.message;
6337
+ };
6338
+ var HeaderError = () => {
6339
+ const { query } = useKeys();
6340
+ if (!query.error) return null;
6341
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-red-600 dark:text-red-400", children: formatUpstashErrorMessage(query.error) });
6342
+ };
6343
+
6344
+ // src/components/databrowser/components/search/query-editor.tsx
6345
+
6346
+
6347
+
6348
+ // src/components/databrowser/components/search/generate-type-definitions.tsx
6349
+ var generateTypeDefinitions = (schema) => {
6350
+ let schemaFieldsInterface = "";
6351
+ const schemaFields = _optionalChain([schema, 'optionalAccess', _66 => _66.schema]);
6352
+ if (schemaFields && Object.keys(schemaFields).length > 0) {
6353
+ const fieldLines = Object.entries(schemaFields).map(([fieldName, fieldDef]) => {
6354
+ const fieldType = fieldDef.type;
6355
+ let operationType;
6356
+ switch (fieldType) {
6357
+ case "TEXT": {
6358
+ operationType = "StringOperations";
6359
+ break;
6360
+ }
6361
+ case "U64":
6362
+ case "I64":
6363
+ case "F64": {
6364
+ operationType = "NumberOperations";
6365
+ break;
6366
+ }
6367
+ case "BOOL": {
6368
+ operationType = "BooleanOperations";
6369
+ break;
6370
+ }
6371
+ case "DATE": {
6372
+ operationType = "DateOperations";
6373
+ break;
6374
+ }
6375
+ default: {
6376
+ operationType = "StringOperations";
6377
+ }
6378
+ }
6379
+ const escapedFieldName = fieldName.includes(".") ? `"${fieldName}"` : fieldName;
6380
+ return ` ${escapedFieldName}?: ${operationType};`;
6381
+ }).join("\n");
6382
+ schemaFieldsInterface = `
6383
+ /** Schema fields for the current index */
6384
+ interface SchemaFields {
6385
+ ${fieldLines}
6386
+ }`;
6387
+ } else {
6388
+ schemaFieldsInterface = `
6389
+ /** Schema fields - no schema available, using dynamic fields */
6390
+ interface SchemaFields {
6391
+ [fieldName: string]: StringOperations | NumberOperations | BooleanOperations | DateOperations;
6392
+ }`;
6393
+ }
6394
+ return `
6395
+ // String operations for TEXT fields
6396
+ type StringOperationMap = {
6397
+ /** Exact match */
6398
+ $eq: string;
6399
+ /** Not equal */
6400
+ $ne: string;
6401
+ /** Match any value in array */
6402
+ $in: string[];
6403
+ /** Fuzzy match with optional distance */
6404
+ $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean };
6405
+ /** Phrase match with optional slop or prefix */
6406
+ $phrase: string | { value: string } | { value: string; slop: number; prefix?: never } | { value: string; prefix: boolean; slop?: never };
6407
+ /** Regular expression match */
6408
+ $regex: string;
6409
+ };
6410
+
6411
+ // Number operations for U64, I64, F64 fields
6412
+ type NumberOperationMap = {
6413
+ /** Exact match */
6414
+ $eq: number;
6415
+ /** Not equal */
6416
+ $ne: number;
6417
+ /** Match any value in array */
6418
+ $in: number[];
6419
+ /** Greater than */
6420
+ $gt: number;
6421
+ /** Greater than or equal */
6422
+ $gte: number;
6423
+ /** Less than */
6424
+ $lt: number;
6425
+ /** Less than or equal */
6426
+ $lte: number;
6427
+ };
6428
+
6429
+ // Boolean operations for BOOL fields
6430
+ type BooleanOperationMap = {
6431
+ /** Exact match */
6432
+ $eq: boolean;
6433
+ /** Not equal */
6434
+ $ne: boolean;
6435
+ /** Match any value in array */
6436
+ $in: boolean[];
6437
+ };
6438
+
6439
+ // Date operations for DATE fields
6440
+ type DateOperationMap = {
6441
+ /** Exact match */
6442
+ $eq: string | Date;
6443
+ /** Not equal */
6444
+ $ne: string | Date;
6445
+ /** Match any value in array */
6446
+ $in: (string | Date)[];
6447
+ /** Greater than */
6448
+ $gt: string | Date;
6449
+ /** Greater than or equal */
6450
+ $gte: string | Date;
6451
+ /** Less than */
6452
+ $lt: string | Date;
6453
+ /** Less than or equal */
6454
+ $lte: string | Date;
6455
+ };
6456
+
6457
+ // String field operations with optional boost
6458
+ type StringOperations =
6459
+ | { $eq: string; $boost?: number }
6460
+ | { $ne: string; $boost?: number }
6461
+ | { $in: string[]; $boost?: number }
6462
+ | { $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean }; $boost?: number }
6463
+ | { $phrase: string | { value: string } | { value: string; slop: number; prefix?: never } | { value: string; prefix: boolean; slop?: never }; $boost?: number }
6464
+ | { $regex: string; $boost?: number }
6465
+ | string;
6466
+
6467
+ // Number field operations with optional boost
6468
+ type NumberOperations =
6469
+ | { $eq: number; $boost?: number }
6470
+ | { $ne: number; $boost?: number }
6471
+ | { $in: number[]; $boost?: number }
6472
+ | { $gt: number; $boost?: number }
6473
+ | { $gte: number; $boost?: number }
6474
+ | { $lt: number; $boost?: number }
6475
+ | { $lte: number; $boost?: number }
6476
+ | number;
6477
+
6478
+ // Boolean field operations with optional boost
6479
+ type BooleanOperations =
6480
+ | { $eq: boolean; $boost?: number }
6481
+ | { $ne: boolean; $boost?: number }
6482
+ | { $in: boolean[]; $boost?: number }
6483
+ | boolean;
6484
+
6485
+ // Date field operations with optional boost
6486
+ type DateOperations =
6487
+ | { $eq: string | Date; $boost?: number }
6488
+ | { $ne: string | Date; $boost?: number }
6489
+ | { $in: (string | Date)[]; $boost?: number }
6490
+ | { $gt: string | Date; $boost?: number }
6491
+ | { $gte: string | Date; $boost?: number }
6492
+ | { $lt: string | Date; $boost?: number }
6493
+ | { $lte: string | Date; $boost?: number }
6494
+ | string
6495
+ | Date;
6496
+
6497
+ ${schemaFieldsInterface}
6498
+
6499
+ // Query leaf - field conditions without logical operators
6500
+ type QueryLeaf = SchemaFields & {
6501
+ $and?: never;
6502
+ $or?: never;
6503
+ $must?: never;
6504
+ $should?: never;
6505
+ $mustNot?: never;
6506
+ $boost?: never;
6507
+ };
6508
+
6509
+ // Base type for boolean nodes - allows field conditions
6510
+ type BoolBase = SchemaFields;
6511
+
6512
+ // $and: all conditions must match
6513
+ type AndNode = BoolBase & {
6514
+ /** All conditions in this array must match */
6515
+ $and: QueryFilter | QueryFilter[];
6516
+ /** Boost score for this node */
6517
+ $boost?: number;
6518
+ $or?: never;
6519
+ $must?: never;
6520
+ $should?: never;
6521
+ $mustNot?: never;
6522
+ };
6523
+
6524
+ // $or: at least one condition must match
6525
+ type OrNode = BoolBase & {
6526
+ /** At least one condition must match */
6527
+ $or: QueryFilter | QueryFilter[];
6528
+ /** Boost score for this node */
6529
+ $boost?: number;
6530
+ $and?: never;
6531
+ $must?: never;
6532
+ $should?: never;
6533
+ $mustNot?: never;
6534
+ };
6535
+
6536
+ // $must only (Elasticsearch-style)
6537
+ type MustNode = BoolBase & {
6538
+ /** All conditions must match (similar to $and) */
6539
+ $must: QueryFilter | QueryFilter[];
6540
+ /** Boost score for this node */
6541
+ $boost?: number;
6542
+ $and?: never;
6543
+ $or?: never;
6544
+ $should?: never;
6545
+ $mustNot?: never;
6546
+ };
6547
+
6548
+ // $should only (Elasticsearch-style)
6549
+ type ShouldNode = BoolBase & {
6550
+ /** At least one should match (affects scoring) */
6551
+ $should: QueryFilter | QueryFilter[];
6552
+ /** Boost score for this node */
6553
+ $boost?: number;
6554
+ $and?: never;
6555
+ $or?: never;
6556
+ $must?: never;
6557
+ $mustNot?: never;
6558
+ };
6559
+
6560
+ // $must + $should combined
6561
+ type MustShouldNode = BoolBase & {
6562
+ /** All these must match */
6563
+ $must: QueryFilter | QueryFilter[];
6564
+ /** At least one should match for higher score */
6565
+ $should: QueryFilter | QueryFilter[];
6566
+ $and?: never;
6567
+ $or?: never;
6568
+ $mustNot?: never;
6569
+ };
6570
+
6571
+ // $mustNot only
6572
+ type NotNode = BoolBase & {
6573
+ /** None of these conditions should match */
6574
+ $mustNot: QueryFilter | QueryFilter[];
6575
+ /** Boost score for this node */
6576
+ $boost?: number;
6577
+ $and?: never;
6578
+ $or?: never;
6579
+ $must?: never;
6580
+ $should?: never;
6581
+ };
6582
+
6583
+ // $and + $mustNot combined
6584
+ type AndNotNode = BoolBase & {
6585
+ $and: QueryFilter | QueryFilter[];
6586
+ $mustNot: QueryFilter | QueryFilter[];
6587
+ $boost?: number;
6588
+ $or?: never;
6589
+ $must?: never;
6590
+ $should?: never;
6591
+ };
6592
+
6593
+ // $or + $mustNot combined
6594
+ type OrNotNode = BoolBase & {
6595
+ $or: QueryFilter | QueryFilter[];
6596
+ $mustNot: QueryFilter | QueryFilter[];
6597
+ $boost?: number;
6598
+ $and?: never;
6599
+ $must?: never;
6600
+ $should?: never;
6601
+ };
6602
+
6603
+ // $should + $mustNot combined
6604
+ type ShouldNotNode = BoolBase & {
6605
+ $should: QueryFilter | QueryFilter[];
6606
+ $mustNot: QueryFilter | QueryFilter[];
6607
+ $boost?: number;
6608
+ $and?: never;
6609
+ $or?: never;
6610
+ $must?: never;
6611
+ };
6612
+
6613
+ // $must + $mustNot combined
6614
+ type MustNotNode = BoolBase & {
6615
+ $must: QueryFilter | QueryFilter[];
6616
+ $mustNot: QueryFilter | QueryFilter[];
6617
+ $boost?: number;
6618
+ $and?: never;
6619
+ $or?: never;
6620
+ $should?: never;
6621
+ };
6622
+
6623
+ // Full boolean node: $must + $should + $mustNot
6624
+ type BoolNode = BoolBase & {
6625
+ $must: QueryFilter | QueryFilter[];
6626
+ $should: QueryFilter | QueryFilter[];
6627
+ $mustNot: QueryFilter | QueryFilter[];
6628
+ $boost?: number;
6629
+ $and?: never;
6630
+ $or?: never;
6631
+ };
6632
+
6633
+ // Query filter - union of all node types
6634
+ type QueryFilter =
6635
+ | QueryLeaf
6636
+ | AndNode
6637
+ | OrNode
6638
+ | MustNode
6639
+ | ShouldNode
6640
+ | MustShouldNode
6641
+ | NotNode
6642
+ | AndNotNode
6643
+ | OrNotNode
6644
+ | ShouldNotNode
6645
+ | MustNotNode
6646
+ | BoolNode;
6647
+
6648
+ // Root-level $or restriction (no field conditions at root with $or)
6649
+ type RootOrNode = {
6650
+ $or: QueryFilter | QueryFilter[];
6651
+ $boost?: number;
6652
+ $and?: never;
6653
+ $must?: never;
6654
+ $should?: never;
6655
+ $mustNot?: never;
6656
+ };
6657
+
6658
+ // Root query filter - restricts $or from mixing with fields at root level
6659
+ type Query =
6660
+ | QueryLeaf
6661
+ | AndNode
6662
+ | RootOrNode
6663
+ | MustNode
6664
+ | ShouldNode
6665
+ | MustShouldNode
6666
+ | NotNode
6667
+ | AndNotNode
6668
+ | ShouldNotNode
6669
+ | MustNotNode
6670
+ | BoolNode;
6671
+ `;
6672
+ };
6673
+
6674
+ // src/components/databrowser/components/search/query-editor.tsx
6675
+
6676
+ var QueryEditor = (props) => {
6677
+ return isTest ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TestQueryEditor, { ...props }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MonacoQueryEditor, { ...props });
6678
+ };
6679
+ var MonacoQueryEditor = ({ value, onChange, height, schema }) => {
6680
+ const monaco = _react2.useMonaco.call(void 0, );
6681
+ const editorRef = _react.useRef.call(void 0, null);
6682
+ const theme = useTheme();
6683
+ const typeDefinitions = _react.useMemo.call(void 0, () => generateTypeDefinitions(schema), [schema]);
6684
+ const extraLibRef = _react.useRef.call(void 0, null);
6685
+ _react.useEffect.call(void 0, () => {
6686
+ if (!monaco) return;
6687
+ if (extraLibRef.current) extraLibRef.current.dispose();
6688
+ extraLibRef.current = monaco.languages.typescript.typescriptDefaults.addExtraLib(
6689
+ typeDefinitions,
6690
+ "file:///query-types.d.ts"
6691
+ );
6692
+ }, [monaco, typeDefinitions]);
6693
+ const handleChange = (newValue = "") => {
6694
+ const match = isQueryStringValid(newValue);
6695
+ if (match) {
6696
+ onChange(newValue);
6697
+ } else {
6698
+ _optionalChain([editorRef, 'access', _67 => _67.current, 'optionalAccess', _68 => _68.setValue, 'optionalCall', _69 => _69(value)]);
6699
+ }
6700
+ };
6701
+ _react.useEffect.call(void 0, () => {
6702
+ if (!isQueryStringValid(value)) onChange("const query: Query = {}");
6703
+ }, [value, editorRef.current, onChange]);
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: 6
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 isQueryStringValid = (value) => {
6774
+ return value.startsWith("const query: Query = {") && value.endsWith("}");
6775
+ };
6776
+ var handleBeforeMount = (monaco) => {
6777
+ monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
6778
+ target: monaco.languages.typescript.ScriptTarget.ES2020,
6779
+ allowNonTsExtensions: true,
6780
+ moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
6781
+ module: monaco.languages.typescript.ModuleKind.CommonJS,
6782
+ noEmit: true,
6783
+ esModuleInterop: true,
6784
+ strict: true,
6785
+ allowJs: true
6786
+ });
6787
+ monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
6788
+ noSemanticValidation: false,
6789
+ noSyntaxValidation: false
6790
+ });
6791
+ monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
6792
+ };
6793
+ var TestQueryEditor = ({ value, onChange, height }) => {
6794
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("group/editor relative"), style: { height }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6795
+ "textarea",
6796
+ {
6797
+ "aria-label": "query-editor",
6798
+ value,
6799
+ onChange: (e) => onChange(e.target.value),
6800
+ className: "h-full w-full resize-none bg-transparent p-2 font-mono text-sm"
6801
+ }
6802
+ ) });
6803
+ };
6804
+
6805
+ // src/components/databrowser/components/query-builder.tsx
6806
+
6807
+ var QueryBuilder = () => {
6808
+ const { valuesSearch, setValuesSearchQuery } = useTab();
6809
+ const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
6810
+ const editorValue = PREFIX + (valuesSearch.query || "{}");
6811
+ 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,
6812
+ QueryEditor,
6813
+ {
6814
+ height: 300,
6815
+ value: editorValue,
6816
+ onChange: (value) => {
6817
+ const queryPart = value.slice(PREFIX.length);
6818
+ setValuesSearchQuery(queryPart);
6819
+ },
6820
+ schema: indexDetails
6821
+ }
6822
+ ) });
6823
+ };
6824
+
6825
+ // src/components/databrowser/components/search-empty-state.tsx
6826
+
6827
+
6828
+ var SearchEmptyState = () => {
6829
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-8 rounded-xl border border-zinc-200 bg-gradient-to-b from-zinc-50 to-white p-8", children: [
6830
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1", children: [
6831
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "mb-2 text-lg font-semibold text-zinc-900", children: "Redis Search" }),
6832
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-6 max-w-md text-sm leading-relaxed text-zinc-600", children: "Redis Search allows you to create indexes on your existing keys and perform fast, full-text searches across your data." }),
6833
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3", children: [
6834
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-xs font-medium uppercase tracking-wider text-zinc-400", children: "How it works" }),
6835
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-2.5", children: [
6836
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
6837
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-emerald-100 text-emerald-600", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDatabase, { size: 16 }) }),
6838
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
6839
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "text-sm font-medium text-zinc-900", children: "Store your data" }),
6840
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-zinc-500", children: "Add documents as JSON, Hash, or String keys (string content must be valid JSON)." })
6841
+ ] })
6842
+ ] }),
6843
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
6844
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-emerald-100 text-emerald-600", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCode, { size: 16 }) }),
6845
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
6846
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "text-sm font-medium text-zinc-900", children: "Create an index" }),
6847
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-zinc-500", children: "Define a search index specifying which fields to search on." })
6848
+ ] })
6849
+ ] }),
6850
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
6851
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-emerald-100 text-emerald-600", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { size: 16 }) }),
6852
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
6853
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h4", { className: "text-sm font-medium text-zinc-900", children: "Search your data" }),
6854
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-zinc-500", children: "Query with filters, full-text search, and sorted results." })
6855
+ ] })
6856
+ ] })
6857
+ ] })
6858
+ ] }),
6859
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6860
+ "a",
6861
+ {
6862
+ href: "https://upstash.com/docs/redis/sdks/ts/commands/search",
6863
+ target: "_blank",
6864
+ rel: "noopener noreferrer",
6865
+ className: "mt-5 inline-block text-sm text-emerald-600 underline-offset-2 hover:underline",
6866
+ children: "Learn more about Redis Search \u2192"
6867
+ }
6868
+ )
6869
+ ] }),
6870
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-72 flex-col items-center justify-center rounded-lg border border-dashed border-zinc-300 bg-white p-6", children: [
6871
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-100 text-zinc-500", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDownload, { size: 24 }) }),
6872
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "mb-1 text-sm font-medium text-zinc-900", children: "Get started quickly" }),
6873
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-4 text-center text-xs text-zinc-500", children: "Import a sample dataset to try out Redis Search" }),
6874
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6875
+ "button",
6876
+ {
6877
+ onClick: () => {
6878
+ },
6879
+ className: "rounded-lg bg-zinc-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-zinc-800",
6880
+ children: "Import a sample dataset"
6881
+ }
6882
+ )
6883
+ ] })
6884
+ ] });
6885
+ };
6886
+
6887
+ // src/components/databrowser/components/sidebar/empty.tsx
6888
+
6889
+ var Empty = () => {
6890
+ 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: [
6891
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-md font-medium", children: "Data on a break" }),
6892
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-balance text-center", children: '"Quick, lure it back with some CLI magic!"' })
6893
+ ] }) });
6894
+ };
6895
+
6896
+ // src/components/databrowser/components/sidebar/keys-list.tsx
6897
+
6898
+
6899
+
6900
+ // src/components/databrowser/components/sidebar-context-menu.tsx
6901
+
6902
+
6903
+
6904
+
6905
+ var SidebarContextMenu = ({ children }) => {
6906
+ const { mutate: deleteKey } = useDeleteKey();
6907
+ const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
6908
+ const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
6909
+ const {
6910
+ addTab,
6911
+ setSelectedKey: setSelectedKeyGlobal,
6912
+ selectTab,
6913
+ setSearch
6914
+ } = useDatabrowserStore();
6915
+ const { search: currentSearch, selectedKeys } = useTab();
6916
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6917
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6918
+ DeleteAlertDialog,
6919
+ {
6920
+ deletionType: "key",
6921
+ count: contextKeys.length,
6922
+ open: isAlertOpen,
6923
+ onOpenChange: setAlertOpen,
6924
+ onDeleteConfirm: (e) => {
6925
+ e.stopPropagation();
6926
+ for (const key of contextKeys) {
6927
+ deleteKey(key);
6928
+ }
6929
+ setAlertOpen(false);
6930
+ }
6931
+ }
6932
+ ),
6933
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenu, { modal: false, children: [
6934
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6935
+ ContextMenuTrigger,
6936
+ {
6937
+ onContextMenu: (e) => {
6938
+ const el = e.target;
6939
+ const key = el.closest("[data-key]");
6940
+ if (key && key instanceof HTMLElement && key.dataset.key !== void 0) {
6941
+ const clickedKey = key.dataset.key;
6942
+ if (selectedKeys.includes(clickedKey)) {
6943
+ setContextKeys(selectedKeys);
6944
+ } else {
6945
+ setContextKeys([clickedKey]);
6946
+ }
6947
+ } else {
6948
+ throw new Error("Key not found");
6949
+ }
6950
+ },
6951
+ children
6952
+ }
6953
+ ),
6954
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuContent, { children: [
6955
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6956
+ ContextMenuItem,
6957
+ {
6958
+ onClick: () => {
6959
+ navigator.clipboard.writeText(contextKeys[0]);
6960
+ toast({
6961
+ description: "Key copied to clipboard"
6962
+ });
6963
+ },
6964
+ className: "gap-2",
6965
+ disabled: contextKeys.length !== 1,
6966
+ children: [
6967
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCopy, { size: 16 }),
6968
+ "Copy key"
6969
+ ]
6970
+ }
6971
+ ),
6972
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6973
+ ContextMenuItem,
6974
+ {
6975
+ onClick: () => {
6976
+ const newTabId = addTab();
6977
+ setSelectedKeyGlobal(newTabId, contextKeys[0]);
6978
+ setSearch(newTabId, currentSearch);
6979
+ selectTab(newTabId);
6980
+ },
6981
+ className: "gap-2",
6982
+ disabled: contextKeys.length !== 1,
6983
+ children: [
6984
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 16 }),
6985
+ "Open in new tab"
6986
+ ]
6987
+ }
6988
+ ),
6989
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactcontextmenu.ContextMenuSeparator, {}),
6990
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, ContextMenuItem, { onClick: () => setAlertOpen(true), className: "gap-2", children: [
6991
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconTrash, { size: 16 }),
6992
+ contextKeys.length > 1 ? `Delete ${contextKeys.length} keys` : "Delete key"
6993
+ ] })
6994
+ ] })
6995
+ ] })
6996
+ ] });
6997
+ };
6998
+
6999
+ // src/components/databrowser/components/sidebar/keys-list.tsx
7000
+
7001
+ var KeysList = () => {
7002
+ const { keys } = useKeys();
7003
+ const lastClickedIndexRef = _react.useRef.call(void 0, null);
7004
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7005
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px" }),
7006
+ keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
7007
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7008
+ KeyItem,
7009
+ {
7010
+ index: i,
7011
+ data,
7012
+ allKeys: keys,
7013
+ lastClickedIndexRef
7014
+ }
7015
+ ),
7016
+ 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" })
7017
+ ] }, data[0]))
7018
+ ] }) });
7019
+ };
7020
+ var keyStyles = {
7021
+ string: "border-sky-400 !bg-sky-50 text-sky-900",
7022
+ hash: "border-amber-400 !bg-amber-50 text-amber-900",
7023
+ set: "border-indigo-400 !bg-indigo-50 text-indigo-900",
7024
+ zset: "border-pink-400 !bg-pink-50 text-pink-900",
7025
+ json: "border-purple-400 !bg-purple-50 text-purple-900",
7026
+ list: "border-orange-400 !bg-orange-50 text-orange-900",
7027
+ stream: "border-green-400 !bg-green-50 text-green-900",
7028
+ search: "border-rose-400 !bg-rose-50 text-rose-900"
7029
+ };
7030
+ var defaultKeyStyle = "border-gray-400 !bg-gray-50 text-gray-900";
7031
+ var KeyItem = ({
7032
+ data,
7033
+ index,
7034
+ allKeys,
7035
+ lastClickedIndexRef
7036
+ }) => {
7037
+ const { selectedKeys, setSelectedKeys, setSelectedKey } = useTab();
7038
+ const [dataKey, dataType] = data;
7039
+ const isKeySelected = selectedKeys.includes(dataKey);
7040
+ const handleClick = (e) => {
7041
+ if (e.shiftKey && lastClickedIndexRef.current !== null) {
7042
+ const start = Math.min(lastClickedIndexRef.current, index);
7043
+ const end = Math.max(lastClickedIndexRef.current, index);
7044
+ const rangeKeys = allKeys.slice(start, end + 1).map(([key]) => key);
7045
+ setSelectedKeys(rangeKeys);
7046
+ } else if (e.metaKey || e.ctrlKey) {
7047
+ if (isKeySelected) {
7048
+ setSelectedKeys(selectedKeys.filter((k) => k !== dataKey));
7049
+ } else {
7050
+ setSelectedKeys([...selectedKeys, dataKey]);
7051
+ }
7052
+ lastClickedIndexRef.current = index;
7053
+ } else {
7054
+ setSelectedKey(dataKey);
7055
+ lastClickedIndexRef.current = index;
7056
+ }
7057
+ };
7058
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7059
+ "button",
7060
+ {
7061
+ "data-key": dataKey,
7062
+ className: cn(
7063
+ "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",
7064
+ "-my-px select-none border border-transparent text-left",
7065
+ isKeySelected && "shadow-sm",
7066
+ isKeySelected && (_nullishCoalesce(keyStyles[dataType], () => ( defaultKeyStyle)))
7067
+ ),
7068
+ onClick: handleClick,
7069
+ children: [
7070
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: dataType, type: "icon" }),
7071
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "grow truncate whitespace-nowrap", children: dataKey }),
7072
+ isKeySelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronRight, { className: "shrink-0 text-zinc-500", size: 20 })
7073
+ ]
7074
+ }
7075
+ );
7076
+ };
7077
+
7078
+ // src/components/databrowser/components/sidebar/skeleton-buttons.tsx
7079
+
7080
+ var DEFAULT_SKELETON_COUNT = 6;
7081
+ 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: [
7082
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "size-5 shrink-0 rounded" }),
7083
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-4 grow rounded" })
7084
+ ] }, idx)) });
7085
+
7086
+ // src/components/databrowser/components/sidebar/index.tsx
7087
+
7088
+ function Sidebar() {
7089
+ const { keys, query } = useKeys();
7090
+ 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 ? (
7091
+ // Infinite scroll already has a loader at the bottom
7092
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7093
+ InfiniteScroll,
7094
+ {
7095
+ query,
7096
+ disableRoundedInherit: true,
7097
+ className: "min-h-0 rounded-xl bg-zinc-100 px-2 py-5 pr-4",
7098
+ scrollBarClassName: "py-5",
7099
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {})
7100
+ }
7101
+ )
7102
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {}) });
7103
+ }
7104
+
7105
+ // src/components/databrowser/components/ui-query-builder/query-builder-context.tsx
7106
+
7107
+
7108
+ // src/components/databrowser/components/ui-query-builder/types.ts
7109
+ var STRING_OPERATORS = ["eq", "ne", "in", "contains", "fuzzy"];
7110
+ var NUMBER_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
7111
+ var BOOLEAN_OPERATORS = ["eq", "ne"];
7112
+ var DATE_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
7113
+ var ALL_OPERATORS = [
7114
+ "eq",
7115
+ "ne",
7116
+ "gt",
7117
+ "gte",
7118
+ "lt",
7119
+ "lte",
7120
+ "in",
7121
+ "contains",
7122
+ "fuzzy"
7123
+ ];
7124
+ var OPERATOR_OPTIONS = [
7125
+ { value: "eq", label: "eq" },
7126
+ { value: "ne", label: "ne" },
7127
+ { value: "gt", label: "gt" },
7128
+ { value: "gte", label: "gte" },
7129
+ { value: "lt", label: "lt" },
7130
+ { value: "lte", label: "lte" },
7131
+ { value: "in", label: "in" },
7132
+ { value: "contains", label: "contains" },
7133
+ { value: "fuzzy", label: "fuzzy" }
7134
+ ];
7135
+ var getOperatorsForFieldType = (fieldType) => {
7136
+ switch (fieldType) {
7137
+ case "string": {
7138
+ return STRING_OPERATORS;
7139
+ }
7140
+ case "number": {
7141
+ return NUMBER_OPERATORS;
7142
+ }
7143
+ case "boolean": {
7144
+ return BOOLEAN_OPERATORS;
7145
+ }
7146
+ case "date": {
7147
+ return DATE_OPERATORS;
7148
+ }
7149
+ default: {
7150
+ return ALL_OPERATORS;
7151
+ }
7152
+ }
7153
+ };
7154
+ var generateId = () => {
7155
+ return Math.random().toString(36).slice(2, 11);
7156
+ };
7157
+
7158
+ // src/components/databrowser/components/ui-query-builder/query-stringify.ts
7159
+ var jsonToJsLiteral = (json) => {
7160
+ return json.replaceAll(/"([$A-Z_a-z][\w$]*)"\s*:/g, "$1:");
7161
+ };
7162
+ var toJsLiteral = (obj) => {
7163
+ return jsonToJsLiteral(JSON.stringify(obj, null, 2));
7164
+ };
7165
+ var buildOperatorValue = (operator, value, fuzzyDistance) => {
7166
+ if (operator === "fuzzy" && fuzzyDistance) {
7167
+ return { value, distance: fuzzyDistance };
7168
+ }
7169
+ return value;
7170
+ };
7171
+ var conditionToObject = (node) => {
7172
+ const { field, operator, value, boost: conditionBoost, fuzzyDistance } = node.condition;
7173
+ const effectiveBoost = _nullishCoalesce(node.boost, () => ( conditionBoost));
7174
+ if (operator === "eq" && !effectiveBoost && !node.not) {
7175
+ return { [field]: value };
7176
+ }
7177
+ const fieldCondition = {
7178
+ [`$${operator}`]: buildOperatorValue(operator, value, fuzzyDistance)
7179
+ };
7180
+ if (conditionBoost && conditionBoost !== 1 && !node.boost) {
7181
+ fieldCondition.$boost = conditionBoost;
7182
+ }
7183
+ const condition = { [field]: fieldCondition };
7184
+ if (node.boost && node.boost !== 1) {
7185
+ condition.$boost = node.boost;
7186
+ }
7187
+ if (node.not) {
7188
+ return { $mustNot: [condition] };
7189
+ }
7190
+ return condition;
7191
+ };
7192
+ var canMergeChildren = (children) => {
7193
+ return children.every(
7194
+ (child) => child.type === "condition" && !child.not && !child.boost && child.condition.operator === "eq" && !child.condition.boost
7195
+ );
7196
+ };
7197
+ var mergeConditions = (children, boost) => {
7198
+ const merged = {};
7199
+ for (const child of children) {
7200
+ if (child.type === "condition") {
7201
+ merged[child.condition.field] = child.condition.value;
7202
+ }
7203
+ }
7204
+ if (boost && boost !== 1) {
7205
+ merged.$boost = boost;
7206
+ }
7207
+ return merged;
7208
+ };
7209
+ var groupToObject = (node, isRoot) => {
7210
+ const { groupOperator, children, boost, not } = node;
7211
+ if (isRoot && groupOperator === "and" && children.length === 1 && !not && !boost) {
7212
+ return queryNodeToObject(children[0], false);
7213
+ }
7214
+ if (children.length > 0 && !not && canMergeChildren(children)) {
7215
+ const merged = mergeConditions(children, boost);
7216
+ if (isRoot && groupOperator === "and") {
7217
+ return merged;
7218
+ }
7219
+ const result = { [`$${groupOperator}`]: merged };
7220
+ if (boost && boost !== 1) {
7221
+ result.$boost = boost;
7222
+ }
7223
+ return result;
7224
+ }
7225
+ const childObjects = children.map((child) => queryNodeToObject(child, false));
7226
+ const group = { [`$${groupOperator}`]: childObjects };
7227
+ if (boost && boost !== 1) {
7228
+ group.$boost = boost;
7229
+ }
7230
+ if (not) {
7231
+ if (groupOperator === "or" && !boost) {
7232
+ return { $mustNot: childObjects };
7233
+ }
7234
+ return { $mustNot: [group] };
7235
+ }
7236
+ return group;
7237
+ };
7238
+ var queryNodeToObject = (node, isRoot = false) => {
7239
+ if (node.type === "condition") {
7240
+ return conditionToObject(node);
7241
+ }
7242
+ if (node.type === "group") {
7243
+ return groupToObject(node, isRoot);
7244
+ }
7245
+ return {};
7246
+ };
7247
+ var stringifyQueryState = (state) => {
7248
+ const obj = queryNodeToObject(state.root, true);
7249
+ return toJsLiteral(obj);
7250
+ };
7251
+
7252
+ // src/components/databrowser/components/ui-query-builder/query-parser.ts
7253
+ var isOperatorKey = (key) => key.startsWith("$");
7254
+ var isFieldConditionObject = (obj) => {
7255
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
7256
+ const keys = Object.keys(obj);
7257
+ return keys.some((key) => ALL_OPERATORS.some((op) => key === `$${op}`));
7258
+ };
7259
+ var parseFieldCondition = (field, fieldValue) => {
7260
+ if (!isFieldConditionObject(fieldValue)) {
7261
+ return {
7262
+ id: generateId(),
7263
+ type: "condition",
7264
+ condition: {
7265
+ field,
7266
+ operator: "eq",
7267
+ value: fieldValue
7268
+ }
7269
+ };
7270
+ }
7271
+ const fieldObj = fieldValue;
7272
+ let operator = "eq";
7273
+ let value = "";
7274
+ let fuzzyDistance;
7275
+ let boost;
7276
+ for (const op of ALL_OPERATORS) {
7277
+ const key = `$${op}`;
7278
+ if (key in fieldObj) {
7279
+ operator = op;
7280
+ value = fieldObj[key];
7281
+ if (op === "fuzzy" && typeof value === "object" && value !== null) {
7282
+ const fuzzyObj = value;
7283
+ value = _nullishCoalesce(fuzzyObj.value, () => ( ""));
7284
+ fuzzyDistance = _nullishCoalesce(fuzzyObj.distance, () => ( 1));
7285
+ }
7286
+ break;
7287
+ }
7288
+ }
7289
+ if ("$boost" in fieldObj) {
7290
+ boost = fieldObj.$boost;
7291
+ }
7292
+ return {
7293
+ id: generateId(),
7294
+ type: "condition",
7295
+ condition: {
7296
+ field,
7297
+ operator,
7298
+ value,
7299
+ fuzzyDistance,
7300
+ boost
7301
+ }
7302
+ };
7303
+ };
7304
+ var parseMultiFieldObject = (obj, operator) => {
7305
+ const children = [];
7306
+ let boost;
7307
+ for (const [key, value] of Object.entries(obj)) {
7308
+ if (key === "$boost") {
7309
+ boost = value;
7310
+ } else if (!isOperatorKey(key)) {
7311
+ children.push(parseFieldCondition(key, value));
7312
+ }
7313
+ }
7314
+ return { id: generateId(), type: "group", groupOperator: operator, children, boost };
7315
+ };
7316
+ var parseMustNot = (notValue) => {
7317
+ if (Array.isArray(notValue)) {
7318
+ if (notValue.length === 0) return null;
7319
+ if (notValue.length === 1) {
7320
+ const innerNode = objectToQueryNode(notValue[0]);
7321
+ if (innerNode) innerNode.not = true;
7322
+ return innerNode;
7323
+ }
7324
+ const children = notValue.map((child) => objectToQueryNode(child)).filter((n) => n !== null);
7325
+ if (children.length === 0) return null;
7326
+ return { id: generateId(), type: "group", groupOperator: "or", children, not: true };
7327
+ }
7328
+ if (typeof notValue === "object" && notValue !== null) {
7329
+ const innerNode = objectToQueryNode(notValue);
7330
+ if (innerNode) innerNode.not = true;
7331
+ return innerNode;
7332
+ }
7333
+ return null;
7334
+ };
7335
+ var parseGroup = (groupValue, operator, boost) => {
7336
+ if (Array.isArray(groupValue)) {
7337
+ return {
7338
+ id: generateId(),
7339
+ type: "group",
7340
+ groupOperator: operator,
7341
+ children: groupValue.map((child) => objectToQueryNode(child)).filter((n) => n !== null),
7342
+ boost
7343
+ };
7344
+ }
7345
+ if (typeof groupValue === "object" && groupValue !== null) {
7346
+ const group = parseMultiFieldObject(groupValue, operator);
7347
+ if (boost !== void 0) group.boost = boost;
7348
+ return group;
7349
+ }
7350
+ return null;
7351
+ };
7352
+ var objectToQueryNode = (obj) => {
7353
+ if (!obj || typeof obj !== "object") return null;
7354
+ const keys = Object.keys(obj);
7355
+ if (keys.length === 0) return null;
7356
+ if ("$mustNot" in obj) {
7357
+ return parseMustNot(obj.$mustNot);
7358
+ }
7359
+ if ("$and" in obj || "$or" in obj) {
7360
+ const operator = "$and" in obj ? "and" : "or";
7361
+ const groupValue = _nullishCoalesce(obj["$and"], () => ( obj["$or"]));
7362
+ const boost = "$boost" in obj ? obj.$boost : void 0;
7363
+ return parseGroup(groupValue, operator, boost);
7364
+ }
7365
+ const nonOperatorKeys = keys.filter((key) => !isOperatorKey(key));
7366
+ if (nonOperatorKeys.length === 0) return null;
7367
+ const nodeBoost = "$boost" in obj ? obj.$boost : void 0;
7368
+ if (nonOperatorKeys.length === 1) {
7369
+ const field = nonOperatorKeys[0];
7370
+ const condition = parseFieldCondition(field, obj[field]);
7371
+ if (nodeBoost !== void 0) condition.boost = nodeBoost;
7372
+ return condition;
7373
+ }
7374
+ return parseMultiFieldObject(obj, "and");
7375
+ };
7376
+ var parseQueryString = (queryString) => {
7377
+ if (!queryString || queryString.trim() === "" || queryString.trim() === "{}") {
7378
+ return createInitialQueryState();
7379
+ }
7380
+ try {
7381
+ const obj = parseJSObjectLiteral(queryString);
7382
+ if (!obj) return null;
7383
+ const root2 = objectToQueryNode(obj);
7384
+ if (root2) {
7385
+ if (root2.type === "condition") {
7386
+ return {
7387
+ root: {
7388
+ id: generateId(),
7389
+ type: "group",
7390
+ groupOperator: "and",
7391
+ children: [root2]
7392
+ }
7393
+ };
7394
+ }
7395
+ return { root: root2 };
7396
+ }
7397
+ } catch (e5) {
7398
+ }
7399
+ return null;
7400
+ };
7401
+ var createEmptyCondition = (field) => ({
7402
+ id: generateId(),
7403
+ type: "condition",
7404
+ condition: { field: field || "", operator: "eq", value: "" }
7405
+ });
7406
+ var createEmptyGroup = (operator = "and") => ({
7407
+ id: generateId(),
7408
+ type: "group",
7409
+ groupOperator: operator,
7410
+ children: []
7411
+ });
7412
+ var createInitialQueryState = () => ({
7413
+ root: {
7414
+ id: generateId(),
7415
+ type: "group",
7416
+ groupOperator: "and",
7417
+ children: [createEmptyCondition()]
7418
+ }
7419
+ });
7420
+
7421
+ // src/components/databrowser/components/ui-query-builder/query-builder-context.tsx
7422
+
7423
+ var QueryBuilderUIContext = _react.createContext.call(void 0, null);
7424
+ var QueryBuilderUIProvider = ({
7425
+ children,
7426
+ fieldInfos,
7427
+ setQueryState
7428
+ }) => {
7429
+ const updateNode = _react.useCallback.call(void 0,
7430
+ (nodeId, updates) => {
7431
+ setQueryState((state) => ({
7432
+ ...state,
7433
+ root: updateNodeInTree(state.root, nodeId, updates)
7434
+ }));
7435
+ },
7436
+ [setQueryState]
7437
+ );
7438
+ const deleteNode = _react.useCallback.call(void 0,
7439
+ (nodeId) => {
7440
+ setQueryState((state) => {
7441
+ const newRoot = deleteNodeFromTree(state.root, nodeId);
7442
+ return {
7443
+ ...state,
7444
+ root: newRoot || createInitialQueryState().root
7445
+ };
7446
+ });
7447
+ },
7448
+ [setQueryState]
7449
+ );
7450
+ const addChildToGroup = _react.useCallback.call(void 0,
7451
+ (groupId, child) => {
7452
+ setQueryState((state) => ({
7453
+ ...state,
7454
+ root: addChildToGroupInTree(state.root, groupId, child)
7455
+ }));
7456
+ },
7457
+ [setQueryState]
7458
+ );
7459
+ const moveNode = _react.useCallback.call(void 0,
7460
+ (nodeId, newParentId, newIndex) => {
7461
+ setQueryState((state) => ({
7462
+ ...state,
7463
+ root: moveNodeInTree(state.root, nodeId, newParentId, newIndex)
7464
+ }));
7465
+ },
7466
+ [setQueryState]
7467
+ );
7468
+ const value = _react.useMemo.call(void 0,
7469
+ () => ({
7470
+ fieldInfos,
7471
+ updateNode,
7472
+ deleteNode,
7473
+ addChildToGroup,
7474
+ moveNode
7475
+ }),
7476
+ [fieldInfos, updateNode, deleteNode, addChildToGroup, moveNode]
7477
+ );
7478
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderUIContext.Provider, { value, children });
7479
+ };
7480
+ var useQueryBuilderUI = () => {
7481
+ const context = _react.useContext.call(void 0, QueryBuilderUIContext);
7482
+ if (!context) {
7483
+ throw new Error("useQueryBuilderUI must be used within a QueryBuilderUIProvider");
7484
+ }
7485
+ return context;
7486
+ };
7487
+ var updateNodeInTree = (node, nodeId, updates) => {
7488
+ if (node.id === nodeId) {
7489
+ return { ...node, ...updates };
7490
+ }
7491
+ if (node.type === "group") {
7492
+ return {
7493
+ ...node,
7494
+ children: node.children.map((child) => updateNodeInTree(child, nodeId, updates))
7495
+ };
7496
+ }
7497
+ return node;
7498
+ };
7499
+ var deleteNodeFromTree = (node, nodeId) => {
7500
+ if (node.id === nodeId) {
7501
+ return null;
7502
+ }
7503
+ if (node.type === "group") {
7504
+ const newChildren = node.children.map((child) => deleteNodeFromTree(child, nodeId)).filter((n) => n !== null);
7505
+ return { ...node, children: newChildren };
7506
+ }
7507
+ return node;
7508
+ };
7509
+ var addChildToGroupInTree = (node, groupId, child) => {
7510
+ if (node.id === groupId && node.type === "group") {
7511
+ return { ...node, children: [...node.children, child] };
7512
+ }
7513
+ if (node.type === "group") {
7514
+ return {
7515
+ ...node,
7516
+ children: node.children.map((c) => addChildToGroupInTree(c, groupId, child))
7517
+ };
7518
+ }
7519
+ return node;
7520
+ };
7521
+ var moveNodeInTree = (root2, nodeId, newParentId, newIndex) => {
7522
+ let movedNode = null;
7523
+ const removeNode = (node) => {
7524
+ if (node.type === "group") {
7525
+ const newChildren = [];
7526
+ for (const child of node.children) {
7527
+ if (child.id === nodeId) {
7528
+ movedNode = child;
7529
+ } else {
7530
+ newChildren.push(removeNode(child));
7531
+ }
7532
+ }
7533
+ return { ...node, children: newChildren };
7534
+ }
7535
+ return node;
7536
+ };
7537
+ const addNodeToParent = (node) => {
7538
+ if (node.id === newParentId && node.type === "group" && movedNode) {
7539
+ const newChildren = [...node.children];
7540
+ newChildren.splice(newIndex, 0, movedNode);
7541
+ return { ...node, children: newChildren };
7542
+ }
7543
+ if (node.type === "group") {
7544
+ return {
7545
+ ...node,
7546
+ children: node.children.map((element) => addNodeToParent(element))
7547
+ };
7548
+ }
7549
+ return node;
7550
+ };
7551
+ const afterRemove = removeNode(root2);
7552
+ return addNodeToParent(afterRemove);
7553
+ };
7554
+
7555
+ // src/components/databrowser/components/ui-query-builder/query-group.tsx
7556
+
7557
+
7558
+
7559
+ // src/components/databrowser/components/ui-query-builder/condition-common.tsx
7560
+
7561
+
7562
+
7563
+ // src/components/databrowser/components/ui-query-builder/dynamic-width-input.tsx
7564
+
7565
+
7566
+ var measureContext = null;
7567
+ var getTextWidth = (text, font) => {
7568
+ if (!measureContext) {
7569
+ const canvas = document.createElement("canvas");
7570
+ measureContext = canvas.getContext("2d");
7571
+ }
7572
+ if (measureContext) {
7573
+ measureContext.font = font;
7574
+ return measureContext.measureText(text).width;
7575
+ }
7576
+ return 0;
7577
+ };
7578
+ var DynamicWidthInput = ({
7579
+ value,
7580
+ onChange,
7581
+ onFocus,
7582
+ onBlur,
7583
+ className = "",
7584
+ minWidth = 20,
7585
+ placeholder
7586
+ }) => {
7587
+ const inputRef = _react.useRef.call(void 0, null);
7588
+ const [width, setWidth] = _react.useState.call(void 0, minWidth);
7589
+ _react.useLayoutEffect.call(void 0, () => {
7590
+ if (inputRef.current) {
7591
+ const computedStyle = window.getComputedStyle(inputRef.current);
7592
+ const font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
7593
+ const textWidth = getTextWidth(value || placeholder || "", font);
7594
+ setWidth(Math.max(Math.ceil(textWidth), minWidth));
7595
+ }
7596
+ }, [value, minWidth, placeholder]);
7597
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7598
+ "input",
7599
+ {
7600
+ ref: inputRef,
7601
+ type: "text",
7602
+ value,
7603
+ onChange: (e) => onChange(e.target.value),
7604
+ onFocus,
7605
+ onBlur,
7606
+ placeholder,
7607
+ style: { width },
7608
+ className: `border-none bg-transparent text-center focus:outline-none ${className}`
7609
+ }
7610
+ );
7611
+ };
7612
+
7613
+ // src/components/databrowser/components/ui-query-builder/condition-common.tsx
7614
+
7615
+ var BoostBadge = ({
7616
+ node,
7617
+ static: isStatic
7618
+ }) => {
7619
+ const { updateNode } = useQueryBuilderUI();
7620
+ const [localValue, setLocalValue] = _react.useState.call(void 0, String(_nullishCoalesce(node.boost, () => ( 0))));
7621
+ const [isFocused, setIsFocused] = _react.useState.call(void 0, false);
7622
+ const boostStr = String(_nullishCoalesce(node.boost, () => ( 0)));
7623
+ if (!isFocused && localValue !== boostStr) {
7624
+ setLocalValue(boostStr);
7625
+ }
7626
+ const handleChange = (value) => {
7627
+ setLocalValue(value);
7628
+ const numValue = Number(value);
7629
+ if (!Number.isNaN(numValue) && value !== "" && value !== "-") {
7630
+ updateNode(node.id, { boost: numValue });
7631
+ }
7632
+ };
7633
+ const handleBlur = () => {
7634
+ setIsFocused(false);
7635
+ const numValue = Number(localValue);
7636
+ if (Number.isNaN(numValue) || localValue === "" || localValue === "-") {
7637
+ setLocalValue(String(_nullishCoalesce(node.boost, () => ( 0))));
7638
+ }
7639
+ };
7640
+ const isNegative = (_nullishCoalesce(node.boost, () => ( 0))) < 0;
7641
+ const labelBg = isNegative ? "bg-red-50" : "bg-purple-50";
7642
+ const textColor = isNegative ? "text-red-800" : "text-purple-800";
7643
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "relative flex h-[26px] items-center overflow-hidden rounded-md border border-zinc-300 text-sm font-medium", children: [
7644
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `flex h-full items-center px-2 ${labelBg} ${textColor}`, children: isNegative ? "Demote" : "Boost" }),
7645
+ isStatic ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `px-2 ${textColor}`, children: node.boost }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex h-full items-center bg-white px-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7646
+ DynamicWidthInput,
7647
+ {
7648
+ value: localValue,
7649
+ onChange: handleChange,
7650
+ onFocus: () => setIsFocused(true),
7651
+ onBlur: handleBlur,
7652
+ className: `text-sm ${textColor}`,
7653
+ minWidth: 8
7654
+ }
7655
+ ) })
7656
+ ] });
7657
+ };
7658
+ var NotBadge = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex h-[26px] items-center rounded-md border border-zinc-300 bg-amber-50 px-2 text-sm font-medium text-amber-800", children: "Not" });
7659
+ var NodeActionsMenu = ({ node }) => {
7660
+ const { updateNode } = useQueryBuilderUI();
7661
+ const [open, setOpen] = _react.useState.call(void 0, false);
7662
+ const handleToggleBoost = () => {
7663
+ updateNode(node.id, { boost: node.boost ? void 0 : 2 });
7664
+ };
7665
+ const handleToggleNot = () => {
7666
+ updateNode(node.id, { not: !node.not });
7667
+ };
7668
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { open, onOpenChange: setOpen, children: [
7669
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7670
+ "button",
7671
+ {
7672
+ type: "button",
7673
+ className: "flex h-[26px] w-[26px] items-center justify-center rounded-md border border-zinc-300 text-zinc-500 transition-colors hover:text-zinc-700",
7674
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconDots, { size: 16 })
7675
+ }
7676
+ ) }),
7677
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { align: "end", children: [
7678
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onClick: handleToggleBoost, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
7679
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7680
+ "div",
7681
+ {
7682
+ className: `h-4 w-8 rounded-full transition-colors ${node.boost === void 0 ? "bg-zinc-200" : "bg-emerald-500"}`,
7683
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7684
+ "div",
7685
+ {
7686
+ className: `h-4 w-4 transform rounded-full bg-white shadow transition-transform ${node.boost === void 0 ? "translate-x-0" : "translate-x-4"}`
7687
+ }
7688
+ )
7689
+ }
7690
+ ),
7691
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Boost" })
7692
+ ] }) }),
7693
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onClick: handleToggleNot, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
7694
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7695
+ "div",
7696
+ {
7697
+ className: `h-4 w-8 rounded-full transition-colors ${node.not ? "bg-emerald-500" : "bg-zinc-200"}`,
7698
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7699
+ "div",
7700
+ {
7701
+ className: `h-4 w-4 transform rounded-full bg-white shadow transition-transform ${node.not ? "translate-x-4" : "translate-x-0"}`
7702
+ }
7703
+ )
7704
+ }
7705
+ ),
7706
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Not" })
7707
+ ] }) })
7708
+ ] })
7709
+ ] });
7710
+ };
7711
+
7712
+ // src/components/databrowser/components/ui-query-builder/dnd-context.tsx
7713
+
7714
+
7715
+
7716
+
7717
+
7718
+
7719
+
7720
+ var _core = require('@dnd-kit/core');
7721
+
7722
+ // src/components/databrowser/components/ui-query-builder/drag-overlay.tsx
7723
+
7724
+
7725
+
7726
+ // src/components/databrowser/components/ui-query-builder/query-condition.tsx
7727
+
7728
+
7729
+
7730
+ var formatValueForDisplay = (value) => {
7731
+ if (Array.isArray(value)) {
7732
+ return value.join(", ");
7733
+ }
7734
+ if (typeof value === "boolean") {
7735
+ return value ? "true" : "false";
7736
+ }
7737
+ return String(value);
7738
+ };
7739
+ var QueryCondition = ({
7740
+ node,
7741
+ isDragging = false,
7742
+ dragHandleProps
7743
+ }) => {
7744
+ const { fieldInfos, updateNode, deleteNode } = useQueryBuilderUI();
7745
+ const { condition } = node;
7746
+ const fieldNames = fieldInfos.map((f) => f.name);
7747
+ const [localValue, setLocalValue] = _react.useState.call(void 0, () => formatValueForDisplay(condition.value));
7748
+ const [isValueFocused, setIsValueFocused] = _react.useState.call(void 0, false);
7749
+ const formattedConditionValue = formatValueForDisplay(condition.value);
7750
+ if (!isValueFocused && localValue !== formattedConditionValue) {
7751
+ setLocalValue(formattedConditionValue);
7752
+ }
7753
+ const currentFieldInfo = fieldInfos.find((f) => f.name === condition.field);
7754
+ const currentFieldType = _nullishCoalesce(_optionalChain([currentFieldInfo, 'optionalAccess', _70 => _70.type]), () => ( "unknown"));
7755
+ _react.useEffect.call(void 0, () => {
7756
+ if (currentFieldType === "boolean") {
7757
+ if (condition.value === "true") {
7758
+ updateNode(node.id, {
7759
+ ...node,
7760
+ condition: { ...condition, value: true }
7761
+ });
7762
+ return;
7763
+ }
7764
+ if (condition.value === "false") {
7765
+ updateNode(node.id, {
7766
+ ...node,
7767
+ condition: { ...condition, value: false }
7768
+ });
7769
+ return;
7770
+ }
7771
+ if (condition.value !== true && condition.value !== false) {
7772
+ updateNode(node.id, {
7773
+ ...node,
7774
+ condition: { ...condition, value: true }
7775
+ });
7776
+ }
7777
+ } else {
7778
+ if (typeof condition.value === "boolean") {
7779
+ updateNode(node.id, {
7780
+ ...node,
7781
+ condition: { ...condition, value: condition.value ? "true" : "false" }
7782
+ });
7783
+ }
7784
+ }
7785
+ }, [currentFieldType, condition.value]);
7786
+ const handleFieldChange = (value) => {
7787
+ const newFieldInfo = _optionalChain([fieldInfos, 'optionalAccess', _71 => _71.find, 'call', _72 => _72((f) => f.name === value)]);
7788
+ const newFieldType = _nullishCoalesce(_optionalChain([newFieldInfo, 'optionalAccess', _73 => _73.type]), () => ( "unknown"));
7789
+ const validOperators = getOperatorsForFieldType(newFieldType);
7790
+ const isOperatorValid = validOperators.includes(condition.operator);
7791
+ let newValue = condition.value;
7792
+ if (newFieldType === "boolean") {
7793
+ if (condition.value === "true") {
7794
+ newValue = true;
7795
+ } else if (condition.value === "false") {
7796
+ newValue = false;
7797
+ } else if (typeof condition.value !== "boolean") {
7798
+ newValue = true;
7799
+ }
7800
+ } else if (typeof condition.value === "boolean") {
7801
+ newValue = condition.value ? "true" : "false";
7802
+ }
7803
+ updateNode(node.id, {
7804
+ ...node,
7805
+ condition: {
7806
+ ...condition,
7807
+ field: value,
7808
+ value: newValue,
7809
+ // Reset to 'eq' if current operator is not valid for the new field type
7810
+ ...isOperatorValid ? {} : { operator: "eq" }
7811
+ }
7812
+ });
7813
+ };
7814
+ const handleOperatorChange = (value) => {
7815
+ const updates = { operator: value };
7816
+ if (value === "fuzzy" && !condition.fuzzyDistance) {
7817
+ updates.fuzzyDistance = 1;
7818
+ } else if (value !== "fuzzy") {
7819
+ updates.fuzzyDistance = void 0;
7820
+ }
7821
+ if (value === "in" && !Array.isArray(condition.value)) {
7822
+ updates.value = condition.value ? [String(condition.value)] : [];
7823
+ } else if (value !== "in" && Array.isArray(condition.value)) {
7824
+ updates.value = condition.value[0] || "";
7825
+ }
7826
+ updateNode(node.id, {
7827
+ ...node,
7828
+ condition: { ...condition, ...updates }
7829
+ });
7830
+ };
7831
+ const commitValue = (value) => {
7832
+ let parsedValue = value;
7833
+ if (currentFieldType === "number") {
7834
+ const numValue = Number(value);
7835
+ if (!Number.isNaN(numValue) && value !== "") {
7836
+ parsedValue = numValue;
7837
+ }
7838
+ }
7839
+ if (condition.operator === "in") {
7840
+ parsedValue = value.split(",").map((v) => v.trim()).filter((v) => v !== "");
7841
+ }
7842
+ updateNode(node.id, {
7843
+ ...node,
7844
+ condition: { ...condition, value: parsedValue }
7845
+ });
7846
+ };
7847
+ const handleValueChange = (value) => {
7848
+ setLocalValue(value);
7849
+ commitValue(value);
7850
+ };
7851
+ const handleValueBlur = () => {
7852
+ setIsValueFocused(false);
7853
+ };
7854
+ const handleValueFocus = () => {
7855
+ setIsValueFocused(true);
7856
+ };
7857
+ const handleFuzzyDistanceChange = (value) => {
7858
+ const distance = Number(value);
7859
+ updateNode(node.id, {
7860
+ ...node,
7861
+ condition: { ...condition, fuzzyDistance: distance }
7862
+ });
7863
+ };
7864
+ const handleDelete = () => {
7865
+ deleteNode(node.id);
7866
+ };
7867
+ const allowedOperators = getOperatorsForFieldType(currentFieldType);
7868
+ const filteredOperators = OPERATOR_OPTIONS.filter((op) => allowedOperators.includes(op.value));
7869
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "group/condition flex items-center gap-1 px-1 py-1", children: [
7870
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7871
+ "div",
7872
+ {
7873
+ ref: _optionalChain([dragHandleProps, 'optionalAccess', _74 => _74.ref]),
7874
+ className: "flex cursor-grab items-center px-1 text-zinc-400 hover:text-zinc-600",
7875
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _75 => _75.attributes]),
7876
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _76 => _76.listeners]),
7877
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconGripVertical, { size: 16 })
7878
+ }
7879
+ ),
7880
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex", children: [
7881
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: condition.field, onValueChange: handleFieldChange, children: [
7882
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-32 gap-3 rounded-none rounded-l-md border-r-0 border-zinc-200 bg-white px-2 text-sm font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, { placeholder: "Select field" }) }),
7883
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: fieldNames.length > 0 ? fieldNames.map((field) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: field, children: field }, field)) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-2 py-1.5 text-sm text-zinc-500", children: "No fields available" }) })
7884
+ ] }),
7885
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: condition.operator, onValueChange: handleOperatorChange, children: [
7886
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-24 gap-3 rounded-none border-r-0 border-zinc-200 px-2 text-sm font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
7887
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: filteredOperators.map((op) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: op.value, children: op.label }, op.value)) })
7888
+ ] }),
7889
+ currentFieldType === "boolean" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7890
+ Select,
7891
+ {
7892
+ value: condition.value === true || condition.value === "true" ? "true" : condition.value === false || condition.value === "false" ? "false" : "true",
7893
+ onValueChange: (value) => {
7894
+ const boolValue = value === "true";
7895
+ updateNode(node.id, {
7896
+ ...node,
7897
+ condition: { ...condition, value: boolValue }
7898
+ });
7899
+ },
7900
+ children: [
7901
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-20 gap-3 rounded-none rounded-r-md border border-zinc-200 bg-white px-2 text-sm font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
7902
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
7903
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "true", children: "true" }),
7904
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "false", children: "false" })
7905
+ ] })
7906
+ ]
7907
+ }
7908
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7909
+ "input",
7910
+ {
7911
+ type: "text",
7912
+ value: localValue,
7913
+ onChange: (e) => handleValueChange(e.target.value),
7914
+ onBlur: handleValueBlur,
7915
+ onFocus: handleValueFocus,
7916
+ placeholder: condition.operator === "in" ? "value1, value2, ..." : "value",
7917
+ className: "h-[26px] min-w-0 flex-1 rounded-none rounded-r-md border border-zinc-200 bg-white px-2 text-sm transition-colors focus:border-zinc-400 focus:outline-none"
7918
+ }
7919
+ )
7920
+ ] }),
7921
+ condition.operator === "fuzzy" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7922
+ Select,
7923
+ {
7924
+ value: String(condition.fuzzyDistance || 1),
7925
+ onValueChange: handleFuzzyDistanceChange,
7926
+ children: [
7927
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-16 gap-3 border-zinc-200 bg-white px-2 text-sm", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
7928
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
7929
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "1", children: "1" }),
7930
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "2", children: "2" })
7931
+ ] })
7932
+ ]
7933
+ }
7934
+ ),
7935
+ node.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node }),
7936
+ node.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NotBadge, {}),
7937
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7938
+ "div",
7939
+ {
7940
+ className: `flex items-center gap-1 transition-all duration-100 ${isDragging ? "opacity-0" : "-translate-x-[2px] opacity-0 group-hover/condition:translate-x-0 group-hover/condition:opacity-100 has-[[data-state=open]]:translate-x-0 has-[[data-state=open]]:opacity-100"}`,
7941
+ children: [
7942
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NodeActionsMenu, { node }),
7943
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7944
+ "button",
7945
+ {
7946
+ type: "button",
7947
+ onClick: handleDelete,
7948
+ className: "flex h-[26px] w-[26px] items-center justify-center rounded-md border border-zinc-300 text-zinc-500 transition-colors hover:text-red-500",
7949
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
7950
+ }
7951
+ )
7952
+ ]
7953
+ }
7954
+ )
7955
+ ] });
7956
+ };
7957
+
7958
+ // src/components/databrowser/components/ui-query-builder/drag-overlay.tsx
7959
+
7960
+ var QueryDragOverlay = ({
7961
+ activeNode,
7962
+ onDropAnimationComplete
7963
+ }) => {
7964
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7965
+ _core.DragOverlay,
7966
+ {
7967
+ dropAnimation: {
7968
+ duration: 200,
7969
+ easing: "ease-out",
7970
+ sideEffects: ({ dragOverlay }) => {
7971
+ dragOverlay.node.classList.add("dropping");
7972
+ return () => {
7973
+ onDropAnimationComplete();
7974
+ };
7975
+ }
7976
+ },
7977
+ children: activeNode && activeNode.type === "condition" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative -mt-1", children: [
7978
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "drag-overlay-bg absolute -bottom-1 -top-1 left-0 right-0 rounded-md border border-zinc-300 bg-zinc-100/90 shadow-md" }),
7979
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryCondition, { node: activeNode, isDragging: true }) })
7980
+ ] }) : activeNode && activeNode.type === "group" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative", children: [
7981
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "drag-overlay-bg absolute -bottom-1 -top-1 left-0 right-0 rounded-md border border-zinc-300 bg-zinc-100/90 shadow-md" }),
7982
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative flex items-center gap-1", children: [
7983
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex cursor-grab items-center text-zinc-400", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconGripVertical, { size: 16 }) }),
7984
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-[26px] w-16 items-center justify-between rounded-md border border-zinc-300 bg-blue-50 px-2 text-sm font-medium capitalize text-zinc-700", children: [
7985
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: activeNode.groupOperator === "and" ? "And" : "Or" }),
7986
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7987
+ "svg",
7988
+ {
7989
+ className: "text-zinc-400",
7990
+ width: "16",
7991
+ height: "16",
7992
+ viewBox: "0 0 16 16",
7993
+ fill: "none",
7994
+ xmlns: "http://www.w3.org/2000/svg",
7995
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7996
+ "path",
7997
+ {
7998
+ d: "M4 6L8 10L12 6",
7999
+ stroke: "currentColor",
8000
+ strokeOpacity: "0.4",
8001
+ strokeWidth: "1.2",
8002
+ strokeLinecap: "round",
8003
+ strokeLinejoin: "round"
8004
+ }
8005
+ )
8006
+ }
8007
+ )
8008
+ ] }),
8009
+ activeNode.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node: activeNode, static: true }),
8010
+ activeNode.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NotBadge, {})
8011
+ ] })
8012
+ ] }) : null
8013
+ }
8014
+ );
8015
+ };
8016
+
8017
+ // src/components/databrowser/components/ui-query-builder/dnd-context.tsx
8018
+
8019
+ var QueryDndProvider = ({
8020
+ children,
8021
+ rootNode,
8022
+ setActiveOverId,
8023
+ setDroppingId
8024
+ }) => {
8025
+ const { moveNode } = useQueryBuilderUI();
8026
+ const [activeId, setActiveId] = _react.useState.call(void 0, null);
8027
+ const sensors = _core.useSensors.call(void 0,
8028
+ _core.useSensor.call(void 0, _core.PointerSensor, {
8029
+ activationConstraint: {
8030
+ distance: 8
8031
+ }
8032
+ })
8033
+ );
8034
+ const handleDragStart = (event) => {
8035
+ setDroppingId(null);
8036
+ setActiveId(event.active.id);
8037
+ };
8038
+ const handleDragOver = (event) => {
8039
+ const { over } = event;
8040
+ setActiveOverId(over ? String(over.id) : null);
8041
+ };
8042
+ const handleDragEnd = (event) => {
8043
+ const { active, over } = event;
8044
+ if (over) {
8045
+ setDroppingId(String(active.id));
8046
+ }
8047
+ setActiveId(null);
8048
+ setActiveOverId(null);
8049
+ if (!over) return;
8050
+ const activeIdStr = String(active.id);
8051
+ const overIdStr = String(over.id);
8052
+ const draggedNode = findNodeById(rootNode, activeIdStr);
8053
+ if (!draggedNode) return;
8054
+ const currentParent = findParentGroup(rootNode, activeIdStr);
8055
+ if (!currentParent) return;
8056
+ if (!overIdStr.startsWith("drop-")) return;
8057
+ const parts = overIdStr.split("-");
8058
+ if (parts.length < 3) return;
8059
+ const targetGroupId = parts[1];
8060
+ const targetIndex = Number.parseInt(parts[2], 10);
8061
+ if (Number.isNaN(targetIndex)) return;
8062
+ const currentIndex = currentParent.children.findIndex((c) => c.id === activeIdStr);
8063
+ if (currentParent.id === targetGroupId && // Same group: if dropping at current or current+1 position, it's a no-op
8064
+ (targetIndex === currentIndex || targetIndex === currentIndex + 1)) {
8065
+ return;
8066
+ }
8067
+ let adjustedIndex = targetIndex;
8068
+ if (currentParent.id === targetGroupId && currentIndex < targetIndex) {
8069
+ adjustedIndex = targetIndex - 1;
8070
+ }
8071
+ if (draggedNode.type === "group") {
8072
+ const isDescendant = (parent, childId) => {
8073
+ if (parent.id === childId) return true;
8074
+ if (parent.type === "group") {
8075
+ return parent.children.some((c) => isDescendant(c, childId));
8076
+ }
8077
+ return false;
8078
+ };
8079
+ if (isDescendant(draggedNode, targetGroupId)) {
8080
+ return;
8081
+ }
8082
+ }
8083
+ moveNode(activeIdStr, targetGroupId, adjustedIndex);
8084
+ };
8085
+ const activeNode = activeId ? findNodeById(rootNode, String(activeId)) : null;
8086
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8087
+ _core.DndContext,
8088
+ {
8089
+ sensors,
8090
+ collisionDetection: _core.rectIntersection,
8091
+ onDragStart: handleDragStart,
8092
+ onDragOver: handleDragOver,
8093
+ onDragEnd: handleDragEnd,
8094
+ children: [
8095
+ children,
8096
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8097
+ QueryDragOverlay,
8098
+ {
8099
+ activeNode,
8100
+ onDropAnimationComplete: () => setDroppingId(null)
8101
+ }
8102
+ )
8103
+ ]
8104
+ }
8105
+ );
8106
+ };
8107
+ var findNodeById = (root2, id) => {
8108
+ if (root2.id === id) return root2;
8109
+ if (root2.type === "group") {
8110
+ for (const child of root2.children) {
8111
+ const found = findNodeById(child, id);
8112
+ if (found) return found;
8113
+ }
8114
+ }
8115
+ return null;
8116
+ };
8117
+ var findParentGroup = (root2, targetId) => {
8118
+ if (root2.type !== "group") return null;
8119
+ for (const child of root2.children) {
8120
+ if (child.id === targetId) {
8121
+ return root2;
8122
+ }
8123
+ if (child.type === "group") {
8124
+ const found = findParentGroup(child, targetId);
8125
+ if (found) return found;
8126
+ }
8127
+ }
8128
+ return null;
8129
+ };
8130
+
8131
+ // src/components/databrowser/components/ui-query-builder/draggable-item.tsx
8132
+
8133
+
8134
+ var DraggableItem = ({
8135
+ id,
8136
+ children,
8137
+ droppingId
8138
+ }) => {
8139
+ const { attributes, listeners: listeners2, setNodeRef, isDragging, setActivatorNodeRef } = _core.useDraggable.call(void 0, {
8140
+ id
8141
+ });
8142
+ const isDropAnimating = droppingId === id;
8143
+ const childElement = children;
8144
+ const childWithDragHandle = typeof children === "object" && children !== null && "type" in childElement ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8145
+ childElement.type,
8146
+ {
8147
+ ...childElement.props,
8148
+ dragHandleProps: {
8149
+ ref: setActivatorNodeRef,
8150
+ listeners: listeners2,
8151
+ attributes
8152
+ }
8153
+ }
8154
+ ) : children;
8155
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8156
+ "div",
8157
+ {
8158
+ ref: setNodeRef,
8159
+ className: `${isDropAnimating ? "opacity-0" : isDragging ? "opacity-30" : ""}`,
8160
+ children: childWithDragHandle
8161
+ }
8162
+ );
8163
+ };
8164
+
8165
+ // src/components/databrowser/components/ui-query-builder/drop-zone.tsx
8166
+
8167
+
8168
+ var DropIndicator = ({ id, isOver }) => {
8169
+ const { setNodeRef } = _core.useDroppable.call(void 0, { id });
8170
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: setNodeRef, className: `relative flex h-2 items-center`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8171
+ "div",
8172
+ {
8173
+ className: cn(
8174
+ "h-1 w-full rounded-full bg-blue-500 transition-opacity duration-100",
8175
+ isOver ? "opacity-100" : "opacity-0"
8176
+ )
8177
+ }
8178
+ ) });
8179
+ };
8180
+ var EmptyGroupDropZone = ({ groupId, isOver }) => {
8181
+ const { setNodeRef } = _core.useDroppable.call(void 0, { id: `drop-${groupId}-0` });
8182
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8183
+ "div",
8184
+ {
8185
+ ref: setNodeRef,
8186
+ className: `mt-2 flex h-8 items-center justify-center rounded-md border border-dashed text-sm transition-all ${isOver ? "border-blue-500 bg-blue-50 text-blue-600" : "border-zinc-300 text-zinc-400"}`,
8187
+ children: "Drop items here or add a condition"
8188
+ }
8189
+ );
8190
+ };
8191
+
8192
+ // src/components/databrowser/components/ui-query-builder/query-group.tsx
8193
+
8194
+ var InnerGroup = ({
8195
+ node,
8196
+ isRoot = false,
8197
+ depth,
8198
+ activeOverId,
8199
+ droppingId,
8200
+ dragHandleProps
8201
+ }) => {
8202
+ const { fieldInfos, updateNode, deleteNode, addChildToGroup } = useQueryBuilderUI();
8203
+ const fieldNames = fieldInfos.map((f) => f.name);
8204
+ const handleOperatorChange = (value) => {
8205
+ updateNode(node.id, { groupOperator: value });
8206
+ };
8207
+ const handleAddCondition = () => {
8208
+ addChildToGroup(node.id, createEmptyCondition(fieldNames[0]));
8209
+ };
8210
+ const handleAddGroup = () => {
8211
+ const newGroup = createEmptyGroup("and");
8212
+ newGroup.children = [createEmptyCondition(fieldNames[0])];
8213
+ addChildToGroup(node.id, newGroup);
8214
+ };
8215
+ const handleDeleteGroup = () => {
8216
+ deleteNode(node.id);
8217
+ };
8218
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
8219
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "group/group flex items-center gap-1", children: [
8220
+ !isRoot && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8221
+ "div",
8222
+ {
8223
+ ref: _optionalChain([dragHandleProps, 'optionalAccess', _77 => _77.ref]),
8224
+ className: "flex cursor-grab items-center text-zinc-400",
8225
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _78 => _78.attributes]),
8226
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _79 => _79.listeners]),
8227
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconGripVertical, { size: 16 })
8228
+ }
8229
+ ),
8230
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: node.groupOperator, onValueChange: handleOperatorChange, children: [
8231
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-16 gap-3 rounded-md border-zinc-300 bg-blue-50 px-2 text-sm font-medium capitalize text-zinc-700 [&>svg]:text-zinc-400", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
8232
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
8233
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "and", children: "And" }),
8234
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "or", children: "Or" })
8235
+ ] })
8236
+ ] }),
8237
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { children: [
8238
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8239
+ "button",
8240
+ {
8241
+ type: "button",
8242
+ className: "flex h-[26px] w-[26px] items-center justify-center rounded-md border border-zinc-300 text-zinc-500 transition-colors hover:text-zinc-700",
8243
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { size: 16 })
8244
+ }
8245
+ ) }),
8246
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenuContent, { align: "start", children: [
8247
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onClick: handleAddCondition, children: "Add Condition" }),
8248
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onClick: handleAddGroup, children: "Add Group" })
8249
+ ] })
8250
+ ] }),
8251
+ node.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node }),
8252
+ node.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NotBadge, {}),
8253
+ !isRoot && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8254
+ "div",
8255
+ {
8256
+ className: `flex -translate-x-[2px] items-center gap-1 opacity-0 transition-all duration-100 group-hover/group:translate-x-0 group-hover/group:opacity-100 has-[[data-state=open]]:translate-x-0 has-[[data-state=open]]:opacity-100`,
8257
+ children: [
8258
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NodeActionsMenu, { node }),
8259
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8260
+ "button",
8261
+ {
8262
+ type: "button",
8263
+ onClick: handleDeleteGroup,
8264
+ className: `flex h-[26px] w-[26px] items-center justify-center rounded-md border border-zinc-300 text-zinc-500 transition-colors hover:text-red-500`,
8265
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
8266
+ }
8267
+ )
8268
+ ]
6116
8269
  }
6117
- ) }) }),
8270
+ )
8271
+ ] }),
8272
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `min-h-[20px] ${isRoot ? "" : "ml-2 border-l-2 border-zinc-200 pl-3"}`, children: node.children.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmptyGroupDropZone, { groupId: node.id, isOver: activeOverId === `drop-${node.id}-0` }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
8273
+ node.children.map((child, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
8274
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8275
+ DropIndicator,
8276
+ {
8277
+ id: `drop-${node.id}-${index}`,
8278
+ isOver: activeOverId === `drop-${node.id}-${index}`
8279
+ }
8280
+ ),
8281
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DraggableItem, { id: child.id, droppingId, children: child.type === "condition" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryCondition, { node: child }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8282
+ InnerGroup,
8283
+ {
8284
+ node: child,
8285
+ depth: depth + 1,
8286
+ activeOverId,
8287
+ droppingId
8288
+ }
8289
+ ) })
8290
+ ] }, child.id)),
6118
8291
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6119
- PopoverContent,
8292
+ DropIndicator,
6120
8293
  {
6121
- className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
6122
- autoFocus: false,
6123
- onOpenAutoFocus: (e) => {
6124
- e.preventDefault();
6125
- e.stopPropagation();
6126
- },
6127
- children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6128
- "button",
6129
- {
6130
- ref: (el) => {
6131
- historyItemRefs.current[index] = el;
6132
- },
6133
- onClick: () => handleSubmit(item),
6134
- onMouseEnter: () => setFocusedIndex(index),
6135
- className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
6136
- children: item
6137
- }
6138
- ) }, item))
8294
+ id: `drop-${node.id}-${node.children.length}`,
8295
+ isOver: activeOverId === `drop-${node.id}-${node.children.length}`
6139
8296
  }
6140
8297
  )
6141
- ] }),
6142
- state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6143
- Button,
8298
+ ] }) })
8299
+ ] });
8300
+ };
8301
+ var QueryGroup = ({ node, isRoot = false, depth }) => {
8302
+ const [activeOverId, setActiveOverId] = _react.useState.call(void 0, null);
8303
+ const [droppingId, setDroppingId] = _react.useState.call(void 0, null);
8304
+ if (node.type !== "group") return;
8305
+ if (!isRoot) {
8306
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8307
+ InnerGroup,
6144
8308
  {
6145
- type: "button",
6146
- variant: "link",
6147
- size: "icon",
6148
- className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
6149
- onClick: () => {
6150
- setSearchKey("");
6151
- setState("");
6152
- },
6153
- children: [
6154
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
6155
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
6156
- ]
8309
+ node,
8310
+ isRoot,
8311
+ depth,
8312
+ activeOverId,
8313
+ droppingId
6157
8314
  }
6158
- ),
6159
- " "
6160
- ] });
8315
+ );
8316
+ }
8317
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8318
+ QueryDndProvider,
8319
+ {
8320
+ rootNode: node,
8321
+ setActiveOverId,
8322
+ setDroppingId,
8323
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8324
+ InnerGroup,
8325
+ {
8326
+ node,
8327
+ isRoot,
8328
+ depth,
8329
+ activeOverId,
8330
+ droppingId
8331
+ }
8332
+ )
8333
+ }
8334
+ );
6161
8335
  };
6162
8336
 
6163
- // src/components/databrowser/components/sidebar/skeleton-buttons.tsx
6164
-
6165
- var DEFAULT_SKELETON_COUNT = 6;
6166
- 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: [
6167
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "size-5 shrink-0 rounded" }),
6168
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-4 grow rounded" })
6169
- ] }, idx)) });
6170
-
6171
- // src/components/databrowser/components/sidebar/type-selector.tsx
8337
+ // src/components/databrowser/components/ui-query-builder/use-query-state-sync.ts
6172
8338
 
6173
- var ALL_TYPES_KEY = "all";
6174
- function DataTypeSelector() {
6175
- const { search, setSearchType } = useTab();
6176
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6177
- Select,
6178
- {
6179
- onValueChange: (type) => {
6180
- if (type === ALL_TYPES_KEY) {
6181
- setSearchType(void 0);
6182
- } else {
6183
- setSearchType(type);
6184
- }
6185
- },
6186
- value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
6187
- children: [
6188
- /* @__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, {}) }),
6189
- /* @__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(
6190
- ([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)
6191
- ) }) })
6192
- ]
8339
+ var useQueryStateSync = () => {
8340
+ const { valuesSearch, setValuesSearchQuery } = useTab();
8341
+ const [queryState, setQueryStateInternal] = _react.useState.call(void 0, () => {
8342
+ const parsed = parseQueryString(valuesSearch.query);
8343
+ return parsed || createInitialQueryState();
8344
+ });
8345
+ const lastSyncedQuery = _react.useRef.call(void 0, valuesSearch.query);
8346
+ const isOurUpdate = _react.useRef.call(void 0, false);
8347
+ _react.useEffect.call(void 0, () => {
8348
+ if (isOurUpdate.current) {
8349
+ isOurUpdate.current = false;
8350
+ lastSyncedQuery.current = valuesSearch.query;
8351
+ return;
8352
+ }
8353
+ if (valuesSearch.query !== lastSyncedQuery.current) {
8354
+ const parsed = parseQueryString(valuesSearch.query);
8355
+ if (parsed) {
8356
+ setQueryStateInternal(parsed);
8357
+ }
8358
+ lastSyncedQuery.current = valuesSearch.query;
6193
8359
  }
8360
+ }, [valuesSearch.query]);
8361
+ const setQueryState = _react.useCallback.call(void 0,
8362
+ (modifier) => {
8363
+ setQueryStateInternal((currentState) => {
8364
+ const newState = modifier(structuredClone(currentState));
8365
+ const newQueryString = stringifyQueryState(newState);
8366
+ isOurUpdate.current = true;
8367
+ lastSyncedQuery.current = newQueryString;
8368
+ setValuesSearchQuery(newQueryString);
8369
+ return newState;
8370
+ });
8371
+ },
8372
+ [setValuesSearchQuery]
6194
8373
  );
6195
- }
8374
+ return {
8375
+ queryState,
8376
+ setQueryState
8377
+ };
8378
+ };
6196
8379
 
6197
- // src/components/databrowser/components/sidebar/index.tsx
8380
+ // src/components/databrowser/components/ui-query-builder/ui-query-builder.tsx
6198
8381
 
6199
- function Sidebar() {
6200
- const { keys, query } = useKeys();
6201
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2 p-4", children: [
6202
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100", children: [
6203
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center justify-between pl-1", children: [
6204
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayDbSize, {}),
6205
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-1", children: [
6206
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6207
- ReloadButton,
6208
- {
6209
- onClick: () => {
6210
- queryClient.invalidateQueries({
6211
- queryKey: [FETCH_KEYS_QUERY_KEY]
6212
- });
6213
- queryClient.invalidateQueries({
6214
- queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
6215
- });
6216
- queryClient.invalidateQueries({
6217
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
6218
- });
6219
- queryClient.invalidateQueries({
6220
- queryKey: [FETCH_DB_SIZE_QUERY_KEY]
6221
- });
6222
- queryClient.invalidateQueries({
6223
- queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
6224
- });
6225
- },
6226
- isLoading: query.isFetching
6227
- }
6228
- ),
6229
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
6230
- ] })
6231
- ] }),
6232
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center", children: [
6233
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, {}),
6234
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
6235
- ] })
6236
- ] }),
6237
- query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
6238
- // Infinite scroll already has a loader at the bottom
6239
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, disableRoundedInherit: true, className: "min-h-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {}) })
6240
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Empty, {})
6241
- ] });
6242
- }
8382
+ var UIQueryBuilder = () => {
8383
+ const { valuesSearch } = useTab();
8384
+ const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
8385
+ const { queryState, setQueryState } = useQueryStateSync();
8386
+ const fieldInfos = _optionalChain([indexDetails, 'optionalAccess', _80 => _80.schema]) ? extractFieldInfo(indexDetails.schema) : [];
8387
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderUIProvider, { fieldInfos, setQueryState, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "rounded-lg border border-zinc-200 bg-zinc-50 p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryGroup, { node: queryState.root, isRoot: true, depth: 0 }) }) });
8388
+ };
8389
+ var getFieldType = (schemaType) => {
8390
+ switch (schemaType) {
8391
+ case "TEXT": {
8392
+ return "string";
8393
+ }
8394
+ case "U64":
8395
+ case "I64":
8396
+ case "F64": {
8397
+ return "number";
8398
+ }
8399
+ case "BOOL": {
8400
+ return "boolean";
8401
+ }
8402
+ case "DATE": {
8403
+ return "date";
8404
+ }
8405
+ default: {
8406
+ return "unknown";
8407
+ }
8408
+ }
8409
+ };
8410
+ var extractFieldInfo = (schema) => {
8411
+ return Object.entries(schema).map(([fieldPath, fieldInfo]) => ({
8412
+ name: fieldPath,
8413
+ type: getFieldType(fieldInfo.type)
8414
+ }));
8415
+ };
6243
8416
 
6244
8417
  // src/components/databrowser/components/databrowser-instance.tsx
6245
8418
 
6246
- var DatabrowserInstance = ({ hidden }) => {
6247
- 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: [
6248
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6249
- _reactresizablepanels.PanelGroup,
8419
+ var PREFIX = "const query: Query = ";
8420
+ var SearchContent = () => {
8421
+ const { data: indexes, isLoading } = useFetchSearchIndexes();
8422
+ const [mode, setMode] = _react.useState.call(void 0, "builder");
8423
+ if (isLoading) {
8424
+ return null;
8425
+ }
8426
+ const hasIndexes = indexes && indexes.length > 0;
8427
+ if (!hasIndexes) {
8428
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchEmptyState, {});
8429
+ }
8430
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative", children: [
8431
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute right-4 top-4 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8432
+ Segmented,
6250
8433
  {
6251
- autoSaveId: "persistence",
6252
- direction: "horizontal",
6253
- className: "h-full w-full gap-0.5 text-sm antialiased",
6254
- children: [
6255
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
6256
- /* @__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" }) }),
6257
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
6258
- ]
8434
+ options: [
8435
+ { key: "builder", label: "Query Builder" },
8436
+ { key: "code", label: "Code Editor" }
8437
+ ],
8438
+ value: mode,
8439
+ onChange: (value) => setMode(value),
8440
+ buttonClassName: "h-6"
6259
8441
  }
6260
- ),
6261
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Toaster, {})
6262
- ] }) });
8442
+ ) }),
8443
+ mode === "builder" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UIQueryBuilder, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {})
8444
+ ] });
8445
+ };
8446
+ var DatabrowserInstance = ({ hidden }) => {
8447
+ const { isValuesSearchSelected } = useTab();
8448
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8449
+ "div",
8450
+ {
8451
+ className: cn(
8452
+ "flex min-h-0 grow flex-col rounded-md bg-white px-5 pb-5",
8453
+ hidden && "hidden"
8454
+ ),
8455
+ children: [
8456
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3 py-5", children: [
8457
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Header, {}),
8458
+ isValuesSearchSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchContent, {}),
8459
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderError, {})
8460
+ ] }),
8461
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8462
+ _reactresizablepanels.PanelGroup,
8463
+ {
8464
+ autoSaveId: "persistence",
8465
+ direction: "horizontal",
8466
+ className: "h-full w-full text-sm antialiased",
8467
+ children: [
8468
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
8469
+ /* @__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: [
8470
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
8471
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
8472
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" })
8473
+ ] }),
8474
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
8475
+ ]
8476
+ }
8477
+ ),
8478
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Toaster, {})
8479
+ ]
8480
+ }
8481
+ ) });
6263
8482
  };
6264
8483
 
6265
8484
  // src/components/databrowser/components/databrowser-tabs.tsx
@@ -6271,7 +8490,7 @@ var DatabrowserInstance = ({ hidden }) => {
6271
8490
 
6272
8491
 
6273
8492
 
6274
- var _core = require('@dnd-kit/core');
8493
+
6275
8494
  var _modifiers = require('@dnd-kit/modifiers');
6276
8495
  var _sortable = require('@dnd-kit/sortable');
6277
8496
  var _utilities = require('@dnd-kit/utilities');
@@ -6279,8 +8498,8 @@ var _utilities = require('@dnd-kit/utilities');
6279
8498
 
6280
8499
  // src/components/ui/command.tsx
6281
8500
 
6282
- var _cmdk = require('cmdk');
6283
8501
 
8502
+ var _cmdk = require('cmdk');
6284
8503
 
6285
8504
  var Command = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6286
8505
  _cmdk.Command,
@@ -6368,15 +8587,6 @@ CommandShortcut.displayName = "CommandShortcut";
6368
8587
 
6369
8588
 
6370
8589
 
6371
- // src/components/databrowser/components/tab-type-icon.tsx
6372
-
6373
- function TabTypeIcon({ selectedKey }) {
6374
- const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
6375
- if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-5 rounded" });
6376
- if (!keyType || keyType === "none") return;
6377
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
6378
- }
6379
-
6380
8590
  // src/hooks/use-overflow.ts
6381
8591
 
6382
8592
  var useOverflow = () => {
@@ -6389,7 +8599,7 @@ var useOverflow = () => {
6389
8599
  }
6390
8600
  if (!node) return;
6391
8601
  observerRef.current = new ResizeObserver((entries) => {
6392
- const el = _optionalChain([entries, 'access', _61 => _61.at, 'call', _62 => _62(0), 'optionalAccess', _63 => _63.target]);
8602
+ const el = _optionalChain([entries, 'access', _81 => _81.at, 'call', _82 => _82(0), 'optionalAccess', _83 => _83.target]);
6393
8603
  if (!el) return;
6394
8604
  setIsOverflow(el.scrollWidth > el.clientWidth);
6395
8605
  });
@@ -6397,16 +8607,25 @@ var useOverflow = () => {
6397
8607
  }, []);
6398
8608
  _react.useEffect.call(void 0, () => {
6399
8609
  return () => {
6400
- _optionalChain([observerRef, 'access', _64 => _64.current, 'optionalAccess', _65 => _65.disconnect, 'call', _66 => _66()]);
8610
+ _optionalChain([observerRef, 'access', _84 => _84.current, 'optionalAccess', _85 => _85.disconnect, 'call', _86 => _86()]);
6401
8611
  };
6402
8612
  }, []);
6403
8613
  return { ref, isOverflow };
6404
8614
  };
6405
8615
 
8616
+ // src/components/databrowser/components/tab-type-icon.tsx
8617
+
8618
+ function TabTypeIcon({ selectedKey }) {
8619
+ const { data: keyType, isLoading } = useFetchKeyType(selectedKey);
8620
+ if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "h-5 w-5 rounded" });
8621
+ if (!keyType || keyType === "none") return;
8622
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: keyType, type: "icon" });
8623
+ }
8624
+
6406
8625
  // src/components/databrowser/components/tab.tsx
6407
8626
 
6408
8627
  var Tab = ({ id, isList }) => {
6409
- const { active, search, selectedKey, pinned } = useTab();
8628
+ const { active, search, selectedKey, valuesSearch, pinned, isValuesSearchSelected } = useTab();
6410
8629
  const {
6411
8630
  selectTab,
6412
8631
  removeTab,
@@ -6419,21 +8638,20 @@ var Tab = ({ id, isList }) => {
6419
8638
  } = useDatabrowserStore();
6420
8639
  const hasPinnedTabs = tabs.some(([, data]) => data.pinned);
6421
8640
  const { ref, isOverflow } = useOverflow();
6422
- const label = search.key || selectedKey;
6423
- 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;
8641
+ const label = isValuesSearchSelected ? valuesSearch.index : search.key || selectedKey;
8642
+ 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;
6424
8643
  const tabNode = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6425
8644
  "div",
6426
8645
  {
6427
8646
  id: isList ? `list-tab-${id}` : `tab-${id}`,
6428
8647
  onClick: () => selectTab(id),
6429
8648
  className: cn(
6430
- "flex h-9 w-full cursor-pointer items-center gap-2 px-3 text-[13px] transition-colors",
8649
+ "flex h-[40px] w-full cursor-pointer items-center gap-2 rounded-t-lg px-3 text-[13px] transition-colors",
6431
8650
  isList && "max-w-[370px]",
6432
- !isList && "rounded-t-lg border border-zinc-200",
6433
- !isList && (active ? "border-b-white bg-white text-zinc-900" : "bg-zinc-100 hover:bg-zinc-50")
8651
+ !isList && (active ? "bg-white text-zinc-950" : "bg-zinc-200 text-zinc-600 hover:bg-zinc-100")
6434
8652
  ),
6435
8653
  children: [
6436
- iconNode,
8654
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn(!active && "transition-colors"), children: iconNode }),
6437
8655
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6438
8656
  "span",
6439
8657
  {
@@ -6450,7 +8668,7 @@ var Tab = ({ id, isList }) => {
6450
8668
  e.stopPropagation();
6451
8669
  removeTab(id);
6452
8670
  },
6453
- className: "p-1 text-zinc-300 transition-colors hover:text-zinc-500 dark:text-zinc-400",
8671
+ className: "p-[2px] text-zinc-400 transition-colors hover:text-zinc-500",
6454
8672
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 })
6455
8673
  }
6456
8674
  )
@@ -6507,8 +8725,8 @@ var SortableTab = ({ id }) => {
6507
8725
  const [originalWidth, setOriginalWidth] = _react.useState.call(void 0, null);
6508
8726
  const textRef = _react.useRef.call(void 0, null);
6509
8727
  const { tabs } = useDatabrowserStore();
6510
- const tabData = _optionalChain([tabs, 'access', _67 => _67.find, 'call', _68 => _68(([tabId]) => tabId === id), 'optionalAccess', _69 => _69[1]]);
6511
- const isPinned = _optionalChain([tabData, 'optionalAccess', _70 => _70.pinned]);
8728
+ const tabData = _optionalChain([tabs, 'access', _87 => _87.find, 'call', _88 => _88(([tabId]) => tabId === id), 'optionalAccess', _89 => _89[1]]);
8729
+ const isPinned = _optionalChain([tabData, 'optionalAccess', _90 => _90.pinned]);
6512
8730
  const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = _sortable.useSortable.call(void 0, {
6513
8731
  id,
6514
8732
  disabled: isPinned,
@@ -6653,73 +8871,70 @@ var DatabrowserTabs = ({ onFullScreenClick }) => {
6653
8871
  reorderTabs(oldIndex, newIndex);
6654
8872
  }
6655
8873
  };
6656
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative mb-2 shrink-0", children: [
6657
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-0 left-0 right-0 -z-10 h-[1px] w-full bg-zinc-200" }),
6658
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex translate-y-[1px] items-center gap-1", children: [
6659
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative min-w-0 flex-1", children: [
6660
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6661
- "div",
6662
- {
6663
- 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"}`
6664
- }
6665
- ),
6666
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6667
- "div",
6668
- {
6669
- 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"}`
6670
- }
6671
- ),
6672
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6673
- "div",
6674
- {
6675
- ref: scrollRef,
6676
- onScroll: recomputeShadows,
6677
- className: "scrollbar-hide flex min-w-0 flex-1 items-center gap-1 overflow-x-auto pb-[1px] [&::-webkit-scrollbar]:hidden",
6678
- children: [
6679
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6680
- _core.DndContext,
6681
- {
6682
- sensors,
6683
- collisionDetection: _core.closestCenter,
6684
- onDragEnd: handleDragEnd,
6685
- modifiers: [_modifiers.restrictToHorizontalAxis],
6686
- measuring: {
6687
- droppable: {
6688
- strategy: _core.MeasuringStrategy.Always
6689
- }
6690
- },
6691
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6692
- _sortable.SortableContext,
6693
- {
6694
- items: sortedTabs.map(([id]) => id),
6695
- strategy: _sortable.horizontalListSortingStrategy,
6696
- children: selectedTab && sortedTabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SortableTab, { id }, id))
6697
- }
6698
- )
6699
- }
6700
- ),
6701
- !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, {}) })
6702
- ]
6703
- }
6704
- )
6705
- ] }),
6706
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 pl-1", children: [
6707
- isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}),
6708
- tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsListButton, { tabs, onSelectTab: selectTab }),
6709
- onFullScreenClick && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6710
- Button,
6711
- {
6712
- "aria-label": "Toggle fullscreen",
6713
- variant: "secondary",
6714
- size: "icon-sm",
6715
- onClick: onFullScreenClick,
6716
- className: "flex-shrink-0 bg-blue-100 hover:bg-blue-600 hover:text-white",
6717
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconMaximize, { size: 16 })
6718
- }
6719
- )
6720
- ] })
8874
+ 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: [
8875
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative min-w-0 flex-1", children: [
8876
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8877
+ "div",
8878
+ {
8879
+ 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"}`
8880
+ }
8881
+ ),
8882
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8883
+ "div",
8884
+ {
8885
+ 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"}`
8886
+ }
8887
+ ),
8888
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8889
+ "div",
8890
+ {
8891
+ ref: scrollRef,
8892
+ onScroll: recomputeShadows,
8893
+ className: "scrollbar-hide flex min-w-0 flex-1 items-center gap-1 overflow-x-auto [&::-webkit-scrollbar]:hidden",
8894
+ children: [
8895
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8896
+ _core.DndContext,
8897
+ {
8898
+ sensors,
8899
+ collisionDetection: _core.closestCenter,
8900
+ onDragEnd: handleDragEnd,
8901
+ modifiers: [_modifiers.restrictToHorizontalAxis],
8902
+ measuring: {
8903
+ droppable: {
8904
+ strategy: _core.MeasuringStrategy.Always
8905
+ }
8906
+ },
8907
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8908
+ _sortable.SortableContext,
8909
+ {
8910
+ items: sortedTabs.map(([id]) => id),
8911
+ strategy: _sortable.horizontalListSortingStrategy,
8912
+ children: selectedTab && sortedTabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SortableTab, { id }, id))
8913
+ }
8914
+ )
8915
+ }
8916
+ ),
8917
+ !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, {}) })
8918
+ ]
8919
+ }
8920
+ )
8921
+ ] }),
8922
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 pl-1", children: [
8923
+ isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}),
8924
+ tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsListButton, { tabs, onSelectTab: selectTab }),
8925
+ onFullScreenClick && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8926
+ Button,
8927
+ {
8928
+ "aria-label": "Toggle fullscreen",
8929
+ variant: "secondary",
8930
+ size: "icon-sm",
8931
+ onClick: onFullScreenClick,
8932
+ className: "flex-shrink-0 bg-white text-zinc-500 dark:bg-zinc-100",
8933
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconWindowMaximize, { size: 16 })
8934
+ }
8935
+ )
6721
8936
  ] })
6722
- ] });
8937
+ ] }) });
6723
8938
  };
6724
8939
  function AddTabButton() {
6725
8940
  const { addTab, selectTab } = useDatabrowserStore();
@@ -6728,7 +8943,7 @@ function AddTabButton() {
6728
8943
  const tabsId = addTab();
6729
8944
  selectTab(tabsId);
6730
8945
  setTimeout(() => {
6731
- const tab = _optionalChain([rootRef, 'optionalAccess', _71 => _71.current, 'optionalAccess', _72 => _72.querySelector, 'call', _73 => _73(`#tab-${tabsId}`)]);
8946
+ const tab = _optionalChain([rootRef, 'optionalAccess', _91 => _91.current, 'optionalAccess', _92 => _92.querySelector, 'call', _93 => _93(`#tab-${tabsId}`)]);
6732
8947
  if (!tab) return;
6733
8948
  tab.scrollIntoView({ behavior: "smooth" });
6734
8949
  }, 20);
@@ -6740,8 +8955,8 @@ function AddTabButton() {
6740
8955
  variant: "secondary",
6741
8956
  size: "icon-sm",
6742
8957
  onClick: handleAddTab,
6743
- className: "flex-shrink-0 dark:bg-zinc-200",
6744
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-500 dark:text-zinc-600", size: 16 })
8958
+ className: "flex-shrink-0 bg-zinc-200 ",
8959
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "text-zinc-600", size: 16 })
6745
8960
  }
6746
8961
  );
6747
8962
  }
@@ -6762,7 +8977,7 @@ function TabsListButton({
6762
8977
  onSelectTab(id);
6763
8978
  setOpen(false);
6764
8979
  setTimeout(() => {
6765
- const tab = _optionalChain([rootRef, 'optionalAccess', _74 => _74.current, 'optionalAccess', _75 => _75.querySelector, 'call', _76 => _76(`#tab-${id}`)]);
8980
+ const tab = _optionalChain([rootRef, 'optionalAccess', _94 => _94.current, 'optionalAccess', _95 => _95.querySelector, 'call', _96 => _96(`#tab-${id}`)]);
6766
8981
  if (!tab) return;
6767
8982
  tab.scrollIntoView({ behavior: "smooth" });
6768
8983
  }, 20);
@@ -6773,7 +8988,7 @@ function TabsListButton({
6773
8988
  {
6774
8989
  variant: "secondary",
6775
8990
  size: "sm",
6776
- className: "h-7 gap-1 px-2",
8991
+ className: "gap-1 bg-white px-2",
6777
8992
  "aria-label": "Search in tabs",
6778
8993
  children: [
6779
8994
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs text-zinc-600", children: tabs.length }),
@@ -6844,7 +9059,7 @@ var RedisBrowserRoot = ({
6844
9059
  className: `ups-db ${theme === "dark" ? "dark" : ""}`,
6845
9060
  style: { height: "100%" },
6846
9061
  ref: rootRef,
6847
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col text-zinc-700", children: [
9062
+ 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: [
6848
9063
  !hideTabs && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserTabs, { onFullScreenClick }),
6849
9064
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, {})
6850
9065
  ] })