@turtleclub/core 0.1.0-beta.15 → 0.1.0-beta.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -239,10 +239,24 @@ function FiltersPopover({
239
239
  );
240
240
  const sectionNames = Object.keys(sections);
241
241
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui4.Popover, { children: [
242
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui4.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui4.Button, { variant: "outline", className: (0, import_ui4.cn)(className), children: [
243
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.SlidersHorizontal, { className: "mr-2 h-4 w-4" }),
244
- triggerLabel
245
- ] }) }),
242
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
243
+ import_ui4.PopoverTrigger,
244
+ {
245
+ className: (0, import_ui4.cn)(
246
+ (0, import_ui4.buttonVariants)({
247
+ variant: "default",
248
+ size: "default",
249
+ border: "bordered"
250
+ }),
251
+ "!bg-neutral-alpha-2",
252
+ className
253
+ ),
254
+ children: [
255
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.SlidersHorizontal, { className: "mr-2 h-4 w-4" }),
256
+ triggerLabel
257
+ ]
258
+ }
259
+ ),
246
260
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
247
261
  import_ui4.PopoverContent,
248
262
  {
@@ -342,6 +356,9 @@ function FiltersWrapper({
342
356
  layout,
343
357
  className,
344
358
  badgesClassName,
359
+ slotClassName,
360
+ leftSlot,
361
+ rightSlot,
345
362
  columns = 3,
346
363
  triggerLabel = "Filters",
347
364
  popoverColumns = 2,
@@ -356,16 +373,20 @@ function FiltersWrapper({
356
373
  }) {
357
374
  const hasActiveFilters = activeFilters.some((filter) => filter.isActive && filter.value);
358
375
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: (0, import_ui6.cn)("space-y-3", className), children: [
359
- layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FiltersGrid, { filters, columns, className: popoverClassName }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
360
- FiltersPopover,
361
- {
362
- filters,
363
- triggerLabel,
364
- columns: popoverColumns,
365
- className: popoverClassName,
366
- popoverClassName: popoverContentClassName
367
- }
368
- ),
376
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: (0, import_ui6.cn)("flex items-center gap-2", slotClassName), children: [
377
+ leftSlot,
378
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex-1", children: layout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FiltersGrid, { filters, columns, className: popoverClassName }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
379
+ FiltersPopover,
380
+ {
381
+ filters,
382
+ triggerLabel,
383
+ columns: popoverColumns,
384
+ className: popoverClassName,
385
+ popoverClassName: popoverContentClassName
386
+ }
387
+ ) }),
388
+ rightSlot
389
+ ] }),
369
390
  showActiveBadges && hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
370
391
  ActiveFilterBadges,
371
392
  {
@@ -744,7 +765,6 @@ var import_jsx_runtime12 = require("react/jsx-runtime");
744
765
  function OpportunitiesSelector({
745
766
  value,
746
767
  onValueChange,
747
- productId,
748
768
  placeholder = "Select opportunities",
749
769
  disabled = false,
750
770
  className,
@@ -752,13 +772,7 @@ function OpportunitiesSelector({
752
772
  closeOnSelect = true,
753
773
  searchable = true
754
774
  }) {
755
- const isProductSelected = !!productId && productId.trim() !== "";
756
- const { data: opportunitiesData, isLoading } = (0, import_hooks4.useOpportunities)({
757
- filters: {
758
- productId
759
- },
760
- enabled: isProductSelected
761
- });
775
+ const { data: opportunitiesData, isLoading } = (0, import_hooks4.useOpportunities)();
762
776
  const opportunities = (0, import_react8.useMemo)(
763
777
  () => opportunitiesData?.opportunities ?? [],
764
778
  [opportunitiesData?.opportunities]
@@ -782,11 +796,6 @@ function OpportunitiesSelector({
782
796
  ) : void 0
783
797
  }));
784
798
  }, [opportunities]);
785
- (0, import_react8.useEffect)(() => {
786
- if (!isProductSelected && value.length > 0) {
787
- onValueChange([]);
788
- }
789
- }, [isProductSelected, value, onValueChange]);
790
799
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
791
800
  import_ui10.MultiSelect,
792
801
  {
@@ -794,8 +803,8 @@ function OpportunitiesSelector({
794
803
  options: opportunityOptions,
795
804
  value,
796
805
  onValueChange,
797
- disabled: disabled || isLoading || !isProductSelected,
798
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
806
+ disabled: disabled || isLoading,
807
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
799
808
  closeOnSelect,
800
809
  maxCount,
801
810
  className
@@ -965,20 +974,13 @@ var import_jsx_runtime16 = require("react/jsx-runtime");
965
974
  function OpportunitySelector({
966
975
  value,
967
976
  onValueChange,
968
- productId,
969
977
  placeholder = "Select opportunity",
970
978
  disabled = false,
971
979
  className,
972
980
  closeOnSelect = true,
973
981
  searchable = true
974
982
  }) {
975
- const isProductSelected = !!productId && productId.trim() !== "";
976
- const { data: opportunitiesData, isLoading } = (0, import_hooks8.useOpportunities)({
977
- filters: {
978
- productId
979
- },
980
- enabled: isProductSelected
981
- });
983
+ const { data: opportunitiesData, isLoading } = (0, import_hooks8.useOpportunities)();
982
984
  const opportunities = (0, import_react12.useMemo)(
983
985
  () => opportunitiesData?.opportunities ?? [],
984
986
  [opportunitiesData?.opportunities]
@@ -1002,11 +1004,6 @@ function OpportunitySelector({
1002
1004
  ) : void 0
1003
1005
  }));
1004
1006
  }, [opportunities]);
1005
- (0, import_react12.useEffect)(() => {
1006
- if (!isProductSelected && value) {
1007
- onValueChange("");
1008
- }
1009
- }, [isProductSelected, value, onValueChange]);
1010
1007
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1011
1008
  import_ui14.Combobox,
1012
1009
  {
@@ -1014,8 +1011,8 @@ function OpportunitySelector({
1014
1011
  options: opportunityOptions,
1015
1012
  value,
1016
1013
  onValueChange,
1017
- disabled: disabled || isLoading || !isProductSelected,
1018
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
1014
+ disabled: disabled || isLoading,
1015
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
1019
1016
  closeOnSelect,
1020
1017
  className
1021
1018
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/filters/RangeSliderFilter.tsx","../src/filters/BooleanFilter.tsx","../src/filters/Filter.tsx","../src/filters/MultiSelectFilter.tsx","../src/wrappers/FiltersGrid.tsx","../src/wrappers/FiltersPopover.tsx","../src/wrappers/ActiveFilterBadges.tsx","../src/wrappers/FiltersWrapper.tsx","../src/helpers/usePagination.ts","../src/helpers/useSorting.ts","../src/selectors/ChainsSelector.tsx","../src/selectors/TokensSelector.tsx","../src/selectors/ProductsSelector.tsx","../src/selectors/OpportunitiesSelector.tsx","../src/selectors/ChainSelector.tsx","../src/selectors/TokenSelector.tsx","../src/selectors/ProductSelector.tsx","../src/selectors/OpportunitySelector.tsx"],"sourcesContent":["export * from \"./filters\";\nexport * from \"./wrappers\";\nexport * from \"./helpers\";\nexport * from \"./selectors\";\n","\"use client\";\n\nimport React, { useEffect, useState } from \"react\";\nimport { Slider, Label } from \"@turtleclub/ui\";\nimport { useQueryState, parseAsInteger } from \"nuqs\";\n\ninterface RangeSliderFilterProps {\n /** Query key for minimum value (default: 'min') */\n minQueryKey?: string;\n /** Query key for maximum value (default: 'max') */\n maxQueryKey?: string;\n /** Minimum value (default: 0) */\n min?: number;\n /** Maximum value (default: 100) */\n max?: number;\n /** Step value for slider (default: 1) */\n step?: number;\n /** Whether the filter is disabled */\n disabled?: boolean;\n /** Custom label for the filter */\n label: string;\n /** Whether to show values (default: true) */\n showValues?: boolean;\n /** Value formatter function */\n formatValue?: (value: number) => string;\n /** Custom className for the container */\n className?: string;\n}\n\nconst defaultFormatter = (value: number): string => {\n return value.toLocaleString();\n};\n\nexport function RangeSliderFilter({\n minQueryKey = \"min\",\n maxQueryKey = \"max\",\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n label = \"Range\",\n showValues = true,\n formatValue = defaultFormatter,\n className = \"\",\n}: RangeSliderFilterProps) {\n const [minValue, setMinValue] = useQueryState(minQueryKey, parseAsInteger.withDefault(min));\n\n const [maxValue, setMaxValue] = useQueryState(maxQueryKey, parseAsInteger.withDefault(max));\n\n // Local state for slider values (to avoid excessive URL updates)\n const [localRange, setLocalRange] = useState([minValue, maxValue]);\n\n // Update local state when query params change\n useEffect(() => {\n setLocalRange([minValue, maxValue]);\n }, [minValue, maxValue]);\n\n const handleRangeChange = (values: number[]) => {\n setLocalRange(values);\n };\n\n const handleRangeCommit = (values: number[]) => {\n const [newMin, newMax] = values;\n if (newMin !== minValue) {\n setMinValue(newMin === min ? null : newMin);\n }\n if (newMax !== maxValue) {\n setMaxValue(newMax === max ? null : newMax);\n }\n };\n\n const isDefaultRange = localRange[0] === min && localRange[1] === max;\n\n return (\n <div className={`space-y-3 ${className}`}>\n <div className=\"flex items-center justify-between\">\n <Label className=\"text-sm font-medium\">{label}</Label>\n {showValues && (\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <span>{formatValue(localRange[0])}</span>\n <span>-</span>\n <span>{formatValue(localRange[1])}</span>\n </div>\n )}\n </div>\n\n <div className=\"px-2\">\n <Slider\n value={localRange}\n onValueChange={handleRangeChange}\n onValueCommit={handleRangeCommit}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n className=\"w-full\"\n />\n </div>\n\n {showValues && (\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>{formatValue(min)}</span>\n <span>{formatValue(max)}</span>\n </div>\n )}\n\n {!isDefaultRange && (\n <div className=\"flex justify-end\">\n <button\n onClick={() => {\n setLocalRange([min, max]);\n handleRangeCommit([min, max]);\n }}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n disabled={disabled}\n >\n Reset\n </button>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Switch, Label } from \"@turtleclub/ui\";\nimport { useQueryState, parseAsBoolean } from \"nuqs\";\n\ninterface BooleanSwitchFilterProps {\n /** Query key for the boolean value (default: 'enabled') */\n queryKey?: string;\n /** Default value when not set (default: false) */\n defaultValue?: boolean;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Label for the switch */\n label: string;\n /** Description text (optional) */\n description?: string;\n /** Custom className for the container */\n className?: string;\n}\n\nexport function BooleanFilter({\n queryKey = \"enabled\",\n defaultValue = false,\n disabled = false,\n label,\n description,\n className = \"\",\n}: BooleanSwitchFilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsBoolean.withDefault(defaultValue));\n\n const handleToggle = (checked: boolean) => {\n // If the value is the same as default, remove from URL\n setValue(checked === defaultValue ? null : checked);\n };\n\n return (\n <div className={`flex items-center justify-between space-x-2 ${className}`}>\n <div className=\"space-y-0.5\">\n <Label className=\"text-sm font-medium\">{label}</Label>\n {description && <p className=\"text-xs text-muted-foreground\">{description}</p>}\n </div>\n <Switch checked={value} onCheckedChange={handleToggle} disabled={disabled} />\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { useQueryState, parseAsString } from \"nuqs\";\n\ninterface FilterProps {\n /** Query parameter key */\n queryKey: string;\n /** Child component to render (selector) */\n children: (props: { value: string; onValueChange: (value: string) => void }) => React.ReactNode;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n}\n\n/**\n * Generic Filter component that handles nuqs URL state management for single values.\n *\n * Provides value and onValueChange props to child components,\n * decoupling selector logic from URL state management.\n *\n * @example Basic Single Selection\n * ```tsx\n * // Single chain selection - persists to URL as ?chainId=ethereum\n * <Filter queryKey=\"chainId\">\n * {({ value, onValueChange }) => (\n * <ChainSelector\n * value={value}\n * onValueChange={onValueChange}\n * placeholder=\"Select chain\"\n * />\n * )}\n * </Filter>\n * ```\n */\nexport function Filter({ queryKey, children, onValueChange }: FilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsString.withDefault(\"\"));\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue || null);\n onValueChange?.(newValue);\n };\n\n return <>{children({ value, onValueChange: handleValueChange })}</>;\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { useQueryState, parseAsArrayOf, parseAsString } from \"nuqs\";\n\ninterface MultiSelectFilterProps {\n /** Query parameter key */\n queryKey: string;\n /** Child component to render (selector) */\n children: (props: {\n value: string[];\n onValueChange: (values: string[]) => void;\n }) => React.ReactNode;\n /** Callback when values change */\n onValueChange?: (values: string[]) => void;\n}\n\n/**\n * Generic MultiSelectFilter component that handles nuqs URL state management for array values.\n *\n * Provides value and onValueChange props to child components,\n * decoupling selector logic from URL state management.\n *\n * @example\n * ```tsx\n * <MultiSelectFilter queryKey=\"chainId\">\n * {({ value, onValueChange }) => (\n * <ChainsSelector\n * value={value}\n * onValueChange={onValueChange}\n * placeholder=\"Select chains\"\n * />\n * )}\n * </MultiSelectFilter>\n * ```\n */\nexport function MultiSelectFilter({ queryKey, children, onValueChange }: MultiSelectFilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsArrayOf(parseAsString).withDefault([]));\n\n const handleValueChange = (newValue: string[]) => {\n setValue(newValue.length > 0 ? newValue : null);\n onValueChange?.(newValue);\n };\n\n return <>{children({ value, onValueChange: handleValueChange })}</>;\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn, Label } from \"@turtleclub/ui\";\n\nexport interface FilterConfig {\n key: string;\n label: string;\n component: React.ReactNode;\n enabled: boolean;\n section?: string;\n}\n\nexport interface FiltersGridProps {\n filters: FilterConfig[];\n columns?: number;\n className?: string;\n sectionClassName?: string;\n}\n\nexport function FiltersGrid({\n filters,\n columns = 3,\n className,\n sectionClassName,\n}: FiltersGridProps) {\n const enabledFilters = filters.filter((filter) => filter.enabled);\n\n if (enabledFilters.length === 0) {\n return null;\n }\n\n // Group filters by section\n const sections = enabledFilters.reduce(\n (acc, filter) => {\n const sectionName = filter.section || \"default\";\n if (!acc[sectionName]) {\n acc[sectionName] = [];\n }\n acc[sectionName].push(filter);\n return acc;\n },\n {} as Record<string, typeof enabledFilters>\n );\n\n const sectionNames = Object.keys(sections);\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {sectionNames.map((sectionName, sectionIndex) => (\n <div key={sectionName}>\n {sectionIndex > 0 && <div className=\"border-t border-border mb-4\" />}\n <div\n className={cn(\"grid gap-2\", sectionClassName)}\n style={{\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {sections[sectionName].map((filter) => (\n <div key={filter.key} className=\"flex flex-col gap-2\">\n {filter.component}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Popover, PopoverContent, PopoverTrigger, Button, cn, Label, Badge } from \"@turtleclub/ui\";\nimport { SlidersHorizontal } from \"lucide-react\";\nimport { FilterConfig } from \"./FiltersGrid\";\n\nexport interface FiltersPopoverProps {\n filters: FilterConfig[];\n triggerLabel?: string;\n columns?: number;\n className?: string;\n popoverClassName?: string;\n sectionClassName?: string;\n}\n\nexport function FiltersPopover({\n filters,\n triggerLabel = \"Filters\",\n columns = 2,\n className,\n popoverClassName,\n sectionClassName,\n}: FiltersPopoverProps) {\n const enabledFilters = filters.filter((filter) => filter.enabled);\n\n if (enabledFilters.length === 0) {\n return null;\n }\n\n // Group filters by section\n const sections = enabledFilters.reduce(\n (acc, filter) => {\n const sectionName = filter.section || \"default\";\n if (!acc[sectionName]) {\n acc[sectionName] = [];\n }\n acc[sectionName].push(filter);\n return acc;\n },\n {} as Record<string, typeof enabledFilters>\n );\n\n const sectionNames = Object.keys(sections);\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <Button variant=\"outline\" className={cn(className)}>\n <SlidersHorizontal className=\"mr-2 h-4 w-4\" />\n {triggerLabel}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className={cn(\"w-auto min-w-[400px] max-w-[600px]\", popoverClassName)}\n align=\"start\"\n >\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h4 className=\"font-medium text-sm\">Filters</h4>\n </div>\n <div className=\"space-y-4\">\n {sectionNames.map((sectionName, sectionIndex) => (\n <div key={sectionName}>\n {sectionIndex > 0 && <div className=\"border-t border-border mb-4\" />}\n <div\n className={cn(\"grid gap-2\", sectionClassName)}\n style={{\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {sections[sectionName].map((filter) => (\n <div key={filter.key} className=\"flex flex-col gap-2\">\n {filter.component}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","\"use client\";\n\nimport React, { useMemo } from \"react\";\nimport { Badge, Button, cn } from \"@turtleclub/ui\";\nimport { X } from \"lucide-react\";\n\nexport interface ActiveFilterConfig {\n /** Unique key for the filter */\n key: string;\n /** Display label for the filter */\n label: string;\n /** Current filter value to display */\n value: string;\n /** Query parameter key(s) this filter uses */\n queryKeys: string | string[];\n /** Whether this filter is currently active */\n isActive: boolean;\n}\n\nexport interface ActiveFilterBadgesProps {\n /** Array of filter configurations */\n filters: ActiveFilterConfig[];\n /** Custom className for the container */\n className?: string;\n /** Label for clear all button (default: \"Clear All\") */\n clearAllLabel?: string;\n /** Whether to show clear all button (default: true) */\n showClearAll?: boolean;\n /** Custom render function for individual badges */\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n /** Callback function to clear individual filter */\n onClearFilter: (queryKeys: string | string[]) => void;\n /** Callback function to clear all filters */\n onClearAll: (allQueryKeys: (string | string[])[]) => void;\n}\n\n/**\n * Component that displays active filter badges with individual clear buttons\n * and an optional \"clear all\" button.\n *\n * @example\n * ```tsx\n * const activeFilters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * value: 'Ethereum',\n * queryKeys: 'chainId',\n * isActive: true,\n * },\n * {\n * key: 'sorting',\n * label: 'Sort',\n * value: 'Name (A-Z)',\n * queryKeys: ['sortBy', 'sortOrder'],\n * isActive: true,\n * },\n * ];\n *\n * <ActiveFilterBadges filters={activeFilters} />\n * ```\n */\nexport function ActiveFilterBadges({\n filters,\n className,\n clearAllLabel = \"Clear All\",\n showClearAll = true,\n renderBadge,\n onClearFilter,\n onClearAll,\n}: ActiveFilterBadgesProps) {\n // Get only active filters\n const activeFilters = useMemo(() => {\n return filters.filter((filter) => filter.isActive && filter.value);\n }, [filters]);\n\n // Clear all function\n const clearAll = () => {\n const allQueryKeys = activeFilters.map((filter) => filter.queryKeys);\n onClearAll(allQueryKeys);\n };\n\n // Don't render if no active filters\n if (activeFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)}>\n {activeFilters.map((filter) => {\n return (\n <FilterBadge\n key={filter.key}\n filter={filter}\n renderBadge={renderBadge}\n onClearFilter={onClearFilter}\n />\n );\n })}\n\n {showClearAll && activeFilters.length > 1 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={clearAll} className=\"h-7 px-2 text-xs\">\n {clearAllLabel}\n </Button>\n )}\n </div>\n );\n}\n\ninterface FilterBadgeProps {\n filter: ActiveFilterConfig;\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n onClearFilter: (queryKeys: string | string[]) => void;\n}\n\nfunction FilterBadge({ filter, renderBadge, onClearFilter }: FilterBadgeProps) {\n const clearFilter = () => {\n onClearFilter(filter.queryKeys);\n };\n\n if (renderBadge) {\n return <>{renderBadge(filter, clearFilter)}</>;\n }\n\n return (\n <Badge className=\"flex items-center gap-1 pr-1 border-border border\">\n <span className=\"text-xs\">\n {filter.label}: {filter.value}\n </span>\n <button\n onClick={clearFilter}\n className=\"ml-1 rounded-full p-0.5 hover:bg-black/10 focus:bg-black/10 focus:outline-none\"\n aria-label={`Clear ${filter.label} filter`}\n >\n <X className=\"h-3 w-3\" />\n </button>\n </Badge>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@turtleclub/ui\";\nimport { FiltersGrid } from \"./FiltersGrid\";\nimport { FiltersPopover } from \"./FiltersPopover\";\nimport { ActiveFilterBadges, ActiveFilterConfig } from \"./ActiveFilterBadges\";\nimport { FilterConfig } from \"./FiltersGrid\";\n\nexport interface FiltersWrapperProps {\n /** Array of filter configurations */\n filters: FilterConfig[];\n /** Array of active filter configurations for badges */\n activeFilters: ActiveFilterConfig[];\n /** Layout type: 'grid' or 'popover' */\n layout: \"grid\" | \"popover\";\n /** Custom className for the wrapper */\n className?: string;\n /** Custom className for the active badges section */\n badgesClassName?: string;\n\n // Grid-specific props\n /** Number of columns for grid layout (default: 3) */\n columns?: number;\n\n // Popover-specific props\n /** Button label for popover trigger (default: \"Filters\") */\n triggerLabel?: string;\n /** Number of columns in popover (default: 2) */\n popoverColumns?: number;\n /** Custom className for popover trigger button */\n popoverClassName?: string;\n /** Custom className for popover content */\n popoverContentClassName?: string;\n\n // Active badges props\n /** Label for clear all button (default: \"Clear All\") */\n clearAllLabel?: string;\n /** Whether to show clear all button (default: true) */\n showClearAll?: boolean;\n /** Custom render function for individual badges */\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n /** Whether to show active filter badges (default: true) */\n showActiveBadges?: boolean;\n /** Callback function to clear individual filter */\n onClearFilter: (queryKeys: string | string[]) => void;\n /** Callback function to clear all filters */\n onClearAll: (allQueryKeys: (string | string[])[]) => void;\n}\n\n/**\n * Unified wrapper component that combines filter controls with active filter badges.\n *\n * Supports both grid and popover layouts, automatically displays active filter badges\n * below the filter controls with individual and bulk clear functionality.\n *\n * @example\n * ```tsx\n * const filters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * component: <ChainFilter />,\n * enabled: true,\n * },\n * ];\n *\n * const activeFilters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * value: 'Ethereum',\n * queryKeys: 'chainId',\n * isActive: true,\n * },\n * ];\n *\n * <FiltersWrapper\n * layout=\"grid\"\n * filters={filters}\n * activeFilters={activeFilters}\n * />\n * ```\n */\nexport function FiltersWrapper({\n filters,\n activeFilters,\n layout,\n className,\n badgesClassName,\n columns = 3,\n triggerLabel = \"Filters\",\n popoverColumns = 2,\n popoverClassName,\n popoverContentClassName,\n clearAllLabel = \"Clear All\",\n showClearAll = true,\n renderBadge,\n showActiveBadges = true,\n onClearFilter,\n onClearAll,\n}: FiltersWrapperProps) {\n const hasActiveFilters = activeFilters.some((filter) => filter.isActive && filter.value);\n\n return (\n <div className={cn(\"space-y-3\", className)}>\n {/* Filter Controls */}\n {layout === \"grid\" ? (\n <FiltersGrid filters={filters} columns={columns} className={popoverClassName} />\n ) : (\n <FiltersPopover\n filters={filters}\n triggerLabel={triggerLabel}\n columns={popoverColumns}\n className={popoverClassName}\n popoverClassName={popoverContentClassName}\n />\n )}\n\n {/* Active Filter Badges */}\n {showActiveBadges && hasActiveFilters && (\n <ActiveFilterBadges\n filters={activeFilters}\n className={badgesClassName}\n clearAllLabel={clearAllLabel}\n showClearAll={showClearAll}\n renderBadge={renderBadge}\n onClearFilter={onClearFilter}\n onClearAll={onClearAll}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useQueryState, parseAsInteger } from \"nuqs\";\nimport { useMemo, useCallback } from \"react\";\nimport type { PaginationState } from \"@tanstack/react-table\";\n\nexport interface UsePaginationOptions {\n /** Default page size (default: 10) */\n defaultPageSize?: number;\n /** Default page index (default: 0) */\n defaultPageIndex?: number;\n /** Query param key for page index (default: 'page') */\n pageIndexKey?: string;\n /** Query param key for page size (default: 'pageSize') */\n pageSizeKey?: string;\n}\n\nexport interface UsePaginationReturn {\n /** Current pagination state for TanStack Table */\n pagination: PaginationState;\n /** Function to update pagination state */\n setPagination: (updater: PaginationState | ((prev: PaginationState) => PaginationState)) => void;\n /** Current page index (0-based) */\n pageIndex: number;\n /** Current page size */\n pageSize: number;\n /** Set page index directly */\n setPageIndex: (pageIndex: number) => void;\n /** Set page size directly */\n setPageSize: (pageSize: number) => void;\n /** Go to next page */\n nextPage: (totalPages?: number) => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to first page */\n firstPage: () => void;\n /** Go to last page */\n lastPage: (totalPages: number) => void;\n /** Reset pagination to defaults */\n reset: () => void;\n /** Check if can go to next page */\n canNextPage: (totalPages?: number) => boolean;\n /** Check if can go to previous page */\n canPreviousPage: boolean;\n}\n\n/**\n * Hook for managing server-side pagination state using nuqs.\n *\n * This hook synchronizes pagination state with URL query parameters,\n * making it perfect for server-side pagination where the URL should\n * reflect the current page and page size.\n *\n * @example\n * ```tsx\n * function MyTable() {\n * const {\n * pagination,\n * setPagination,\n * pageIndex,\n * pageSize,\n * setPageIndex,\n * setPageSize\n * } = usePagination({\n * defaultPageSize: 20,\n * pageIndexKey: 'page',\n * pageSizeKey: 'limit'\n * });\n *\n * // Use with TanStack Table\n * const table = useReactTable({\n * data,\n * columns,\n * manualPagination: true,\n * pagination,\n * onPaginationChange: setPagination,\n * pageCount: Math.ceil(totalCount / pageSize),\n * });\n *\n * return <DataTable table={table} />;\n * }\n * ```\n */\nexport function usePagination(options: UsePaginationOptions = {}): UsePaginationReturn {\n const {\n defaultPageSize = 10,\n defaultPageIndex = 0,\n pageIndexKey = \"page\",\n pageSizeKey = \"pageSize\",\n } = options;\n\n // Use nuqs to manage query state\n const [rawPageIndex, setRawPageIndex] = useQueryState(\n pageIndexKey,\n parseAsInteger.withDefault(defaultPageIndex)\n );\n\n const [rawPageSize, setRawPageSize] = useQueryState(\n pageSizeKey,\n parseAsInteger.withDefault(defaultPageSize)\n );\n\n // Ensure page index is never negative\n const pageIndex = useMemo(() => Math.max(0, rawPageIndex), [rawPageIndex]);\n\n // Use page size directly from query state\n const pageSize = rawPageSize;\n\n // Create pagination state for TanStack Table\n const pagination = useMemo<PaginationState>(\n () => ({\n pageIndex,\n pageSize,\n }),\n [pageIndex, pageSize]\n );\n\n // Set pagination function that handles both object and function updates\n const setPagination = useCallback(\n (updater: PaginationState | ((prev: PaginationState) => PaginationState)) => {\n const newPagination = typeof updater === \"function\" ? updater(pagination) : updater;\n\n if (newPagination.pageIndex !== pageIndex) {\n setRawPageIndex(Math.max(0, newPagination.pageIndex));\n }\n\n if (newPagination.pageSize !== pageSize) {\n setRawPageSize(newPagination.pageSize);\n }\n },\n [pagination, pageIndex, pageSize, setRawPageIndex, setRawPageSize]\n );\n\n // Individual setters\n const setPageIndex = useCallback(\n (newPageIndex: number) => {\n setRawPageIndex(Math.max(0, newPageIndex));\n },\n [setRawPageIndex]\n );\n\n const setPageSize = useCallback(\n (newPageSize: number) => {\n setRawPageSize(newPageSize);\n // Reset to first page when page size changes\n setRawPageIndex(0);\n },\n [setRawPageSize, setRawPageIndex]\n );\n\n // Navigation functions\n const nextPage = useCallback(\n (totalPages?: number) => {\n const nextPageIndex = pageIndex + 1;\n if (!totalPages || nextPageIndex < totalPages) {\n setPageIndex(nextPageIndex);\n }\n },\n [pageIndex, setPageIndex]\n );\n\n const previousPage = useCallback(() => {\n if (pageIndex > 0) {\n setPageIndex(pageIndex - 1);\n }\n }, [pageIndex, setPageIndex]);\n\n const firstPage = useCallback(() => {\n setPageIndex(0);\n }, [setPageIndex]);\n\n const lastPage = useCallback(\n (totalPages: number) => {\n setPageIndex(Math.max(0, totalPages - 1));\n },\n [setPageIndex]\n );\n\n // Reset function\n const reset = useCallback(() => {\n setRawPageIndex(defaultPageIndex);\n setRawPageSize(defaultPageSize);\n }, [setRawPageIndex, setRawPageSize, defaultPageIndex, defaultPageSize]);\n\n // Navigation state\n const canPreviousPage = pageIndex > 0;\n const canNextPage = useCallback(\n (totalPages?: number) => {\n if (!totalPages) return true; // Assume we can go next if total pages unknown\n return pageIndex < totalPages - 1;\n },\n [pageIndex]\n );\n\n return {\n pagination,\n setPagination,\n pageIndex,\n pageSize,\n setPageIndex,\n setPageSize,\n nextPage,\n previousPage,\n firstPage,\n lastPage,\n reset,\n canNextPage,\n canPreviousPage,\n };\n}\n","\"use client\";\n\nimport { useQueryState, parseAsString } from \"nuqs\";\nimport { useMemo, useCallback } from \"react\";\nimport type { SortingState } from \"@tanstack/react-table\";\n\nexport interface UseSortingOptions {\n /** Default sort column (default: undefined - no sorting) */\n defaultSortBy?: string;\n /** Default sort order (default: 'asc') */\n defaultSortOrder?: \"asc\" | \"desc\";\n /** Query param key for sort column (default: 'sortBy') */\n sortByKey?: string;\n /** Query param key for sort order (default: 'sortOrder') */\n sortOrderKey?: string;\n}\n\nexport interface UseSortingReturn {\n /** Current sorting state for TanStack Table */\n sorting: SortingState;\n /** Function to update sorting state */\n setSorting: (updater: SortingState | ((prev: SortingState) => SortingState)) => void;\n /** Current sort column (undefined if no sorting) */\n sortBy: string | undefined;\n /** Current sort order */\n sortOrder: \"asc\" | \"desc\";\n /** Set sort column and order directly */\n setSort: (column: string, order?: \"asc\" | \"desc\") => void;\n /** Clear all sorting */\n clearSort: () => void;\n /** Toggle sort order for a column */\n toggleSort: (column: string) => void;\n /** Check if a column is currently sorted */\n isSorted: (column: string) => boolean;\n /** Get sort order for a column */\n getSortOrder: (column: string) => \"asc\" | \"desc\" | undefined;\n}\n\n/**\n * Hook for managing server-side sorting state using nuqs.\n *\n * This hook synchronizes sorting state with URL query parameters,\n * making it perfect for server-side sorting where the URL should\n * reflect the current sort state.\n *\n * @example\n * ```tsx\n * function MyTable() {\n * const {\n * sorting,\n * setSorting,\n * sortBy,\n * sortOrder,\n * setSort,\n * toggleSort\n * } = useSorting({\n * defaultSortBy: 'name',\n * defaultSortOrder: 'asc'\n * });\n *\n * // Use with TanStack Table\n * const table = useReactTable({\n * data,\n * columns,\n * manualSorting: true,\n * sorting,\n * onSortingChange: setSorting,\n * });\n *\n * return <DataTable table={table} />;\n * }\n * ```\n */\nexport function useSorting(options: UseSortingOptions = {}): UseSortingReturn {\n const {\n defaultSortBy,\n defaultSortOrder = \"asc\",\n sortByKey = \"sortBy\",\n sortOrderKey = \"sortOrder\",\n } = options;\n\n // Use nuqs to manage query state\n const [sortBy, setSortBy] = useQueryState(\n sortByKey,\n parseAsString.withDefault(defaultSortBy || \"\")\n );\n\n const [sortOrder, setSortOrder] = useQueryState(\n sortOrderKey,\n parseAsString.withDefault(defaultSortOrder)\n );\n\n // Ensure sort order is valid\n const validSortOrder = useMemo(() => {\n return sortOrder === \"desc\" ? \"desc\" : \"asc\";\n }, [sortOrder]);\n\n // Create sorting state for TanStack Table\n const sorting = useMemo<SortingState>(() => {\n if (!sortBy || sortBy.trim() === \"\") {\n return [];\n }\n return [\n {\n id: sortBy,\n desc: validSortOrder === \"desc\",\n },\n ];\n }, [sortBy, validSortOrder]);\n\n // Set sorting function that handles both object and function updates\n const setSorting = useCallback(\n (updater: SortingState | ((prev: SortingState) => SortingState)) => {\n const newSorting = typeof updater === \"function\" ? updater(sorting) : updater;\n\n if (newSorting.length === 0) {\n // Clear sorting\n setSortBy(\"\");\n } else {\n // Set first sort (TanStack Table typically only has one sort at a time)\n const firstSort = newSorting[0];\n setSortBy(firstSort.id);\n setSortOrder(firstSort.desc ? \"desc\" : \"asc\");\n }\n },\n [sorting, setSortBy, setSortOrder]\n );\n\n // Set sort column and order directly\n const setSort = useCallback(\n (column: string, order: \"asc\" | \"desc\" = \"asc\") => {\n setSortBy(column);\n setSortOrder(order);\n },\n [setSortBy, setSortOrder]\n );\n\n // Clear all sorting\n const clearSort = useCallback(() => {\n setSortBy(null);\n }, [setSortBy]);\n\n // Toggle sort order for a column\n const toggleSort = useCallback(\n (column: string) => {\n if (sortBy === column) {\n // Same column, toggle order\n setSortOrder(validSortOrder === \"asc\" ? \"desc\" : \"asc\");\n } else {\n // Different column, set new column with asc\n setSortBy(column);\n setSortOrder(\"asc\");\n }\n },\n [sortBy, validSortOrder, setSortBy, setSortOrder]\n );\n\n // Check if a column is currently sorted\n const isSorted = useCallback(\n (column: string) => {\n return sortBy === column;\n },\n [sortBy]\n );\n\n // Get sort order for a column\n const getSortOrder = useCallback(\n (column: string) => {\n return sortBy === column ? validSortOrder : undefined;\n },\n [sortBy, validSortOrder]\n );\n\n return {\n sorting,\n setSorting,\n sortBy: sortBy || undefined,\n sortOrder: validSortOrder,\n setSort,\n clearSort,\n toggleSort,\n isSorted,\n getSortOrder,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useSupportedChains } from \"@turtleclub/hooks\";\n\ninterface ChainSelectorProps {\n /** Selected chain IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ChainsSelector({\n value,\n onValueChange,\n placeholder = \"Select chains\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: ChainSelectorProps) {\n const { chains, isLoading } = useSupportedChains();\n\n const chainOptions = useMemo(() => {\n if (!chains || chains.length === 0) return [];\n\n const filteredChains = chains.filter((chain) => chain.status === \"active\");\n\n return filteredChains.map((chain) => ({\n label: chain.name,\n value: chain?.id ?? \"\",\n icon: chain.logoUrl\n ? () => (\n <img\n src={chain.logoUrl}\n alt={chain.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [chains]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={chainOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading chains...\" : placeholder}\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useSupportedTokens } from \"@turtleclub/hooks\";\n\ninterface TokenSelectorProps {\n /** Selected token IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Selected chain ID to filter tokens */\n chainId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function TokensSelector({\n value,\n onValueChange,\n chainId,\n placeholder = \"Select tokens\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: TokenSelectorProps) {\n const isChainSelected = !!chainId && chainId.trim() !== \"\";\n\n const { tokens, isLoading } = useSupportedTokens({\n // chainId: isChainSelected ? chainId : undefined,\n limit: 100,\n enabled: isChainSelected,\n });\n\n const tokenOptions = useMemo(() => {\n if (!tokens) return [];\n\n return tokens.map((token) => ({\n label: `${token.symbol} - ${token.name}`,\n value: token?.id || \"\",\n icon: token.logoUrl\n ? () => (\n <img\n src={token.logoUrl}\n alt={token.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [tokens]);\n\n // Clear selection when chain changes\n useEffect(() => {\n if (!isChainSelected && value.length > 0) {\n onValueChange([]);\n }\n }, [isChainSelected, value, onValueChange]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={tokenOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isChainSelected}\n placeholder={\n !isChainSelected ? \"Select a chain first\" : isLoading ? \"Loading tokens...\" : placeholder\n }\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useProducts } from \"@turtleclub/hooks\";\n\ninterface ProductSelectorProps {\n /** Selected product IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ProductsSelector({\n value,\n onValueChange,\n placeholder = \"Select products\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: ProductSelectorProps) {\n const { data: productsData, isLoading } = useProducts({});\n\n const products = useMemo(() => productsData?.products ?? [], [productsData?.products]);\n\n const productOptions = useMemo(() => {\n if (!products || products.length === 0) return [];\n\n return products.map((product) => ({\n label: product.name,\n value: product.id,\n icon: product.logoUrl\n ? () => (\n <img\n src={product.logoUrl}\n alt={product.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [products]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={productOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading products...\" : placeholder}\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo, useEffect } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useOpportunities } from \"@turtleclub/hooks\";\n\ninterface OpportunitySelectorProps {\n /** Selected opportunity IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Selected product ID to filter opportunities */\n productId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function OpportunitiesSelector({\n value,\n onValueChange,\n productId,\n placeholder = \"Select opportunities\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: OpportunitySelectorProps) {\n const isProductSelected = !!productId && productId.trim() !== \"\";\n\n const { data: opportunitiesData, isLoading } = useOpportunities({\n filters: {\n productId,\n },\n enabled: isProductSelected,\n });\n\n const opportunities = useMemo(\n () => opportunitiesData?.opportunities ?? [],\n [opportunitiesData?.opportunities]\n );\n\n const opportunityOptions = useMemo(() => {\n if (!opportunities || opportunities.length === 0) return [];\n\n const filteredOpportunities = opportunities.filter((opp) => opp.status === \"active\");\n\n return filteredOpportunities.map((opportunity) => ({\n label: opportunity.name || opportunity.shortName,\n value: opportunity.id!,\n description: opportunity.shortName !== opportunity.name ? opportunity.shortName : undefined,\n icon: opportunity.depositTokens?.[0]?.logoUrl\n ? () => (\n <img\n src={opportunity.depositTokens[0].logoUrl}\n alt={opportunity.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [opportunities]);\n\n // Clear selection when product changes\n useEffect(() => {\n if (!isProductSelected && value.length > 0) {\n onValueChange([]);\n }\n }, [isProductSelected, value, onValueChange]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={opportunityOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isProductSelected}\n placeholder={\n !isProductSelected\n ? \"Select a product first\"\n : isLoading\n ? \"Loading opportunities...\"\n : placeholder\n }\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useSupportedChains } from \"@turtleclub/hooks\";\n\ninterface ChainSelectorProps {\n /** Selected chain ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ChainSelector({\n value,\n onValueChange,\n placeholder = \"Select chain\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: ChainSelectorProps) {\n const { chains, isLoading } = useSupportedChains();\n\n const chainOptions = useMemo(() => {\n if (!chains || chains.length === 0) return [];\n\n const filteredChains = chains.filter((chain) => chain.status === \"active\");\n\n return filteredChains.map((chain) => ({\n label: chain.name,\n value: chain?.id ?? \"\",\n icon: chain.logoUrl\n ? () => (\n <img\n src={chain.logoUrl}\n alt={chain.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [chains]);\n\n return (\n <Combobox\n searchable={searchable}\n options={chainOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading chains...\" : placeholder}\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useSupportedTokens } from \"@turtleclub/hooks\";\n\ninterface TokenSelectorProps {\n /** Selected token ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Selected chain ID to filter tokens */\n chainId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function TokenSelector({\n value,\n onValueChange,\n chainId,\n placeholder = \"Select token\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: TokenSelectorProps) {\n const isChainSelected = !!chainId && chainId.trim() !== \"\";\n\n const { tokens, isLoading } = useSupportedTokens({\n // chainId: isChainSelected ? chainId : undefined,\n limit: 100,\n enabled: isChainSelected,\n });\n\n const tokenOptions = useMemo(() => {\n if (!tokens) return [];\n\n return tokens.map((token) => ({\n label: `${token.symbol} - ${token.name}`,\n value: token?.id || \"\",\n icon: token.logoUrl\n ? () => (\n <img\n src={token.logoUrl}\n alt={token.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [tokens]);\n\n // Clear selection when chain changes\n useEffect(() => {\n if (!isChainSelected && value) {\n onValueChange(\"\");\n }\n }, [isChainSelected, value, onValueChange]);\n\n return (\n <Combobox\n searchable={searchable}\n options={tokenOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isChainSelected}\n placeholder={\n !isChainSelected ? \"Select a chain first\" : isLoading ? \"Loading tokens...\" : placeholder\n }\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useProducts } from \"@turtleclub/hooks\";\n\ninterface ProductSelectorProps {\n /** Selected product ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ProductSelector({\n value,\n onValueChange,\n placeholder = \"Select product\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: ProductSelectorProps) {\n const { data: productsData, isLoading } = useProducts({});\n\n const products = useMemo(() => productsData?.products ?? [], [productsData?.products]);\n\n const productOptions = useMemo(() => {\n if (!products || products.length === 0) return [];\n\n return products.map((product) => ({\n label: product.name,\n value: product.id,\n icon: product.logoUrl\n ? () => (\n <img\n src={product.logoUrl}\n alt={product.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [products]);\n\n return (\n <Combobox\n searchable={searchable}\n options={productOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading products...\" : placeholder}\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo, useEffect } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useOpportunities } from \"@turtleclub/hooks\";\n\ninterface OpportunitySelectorProps {\n /** Selected opportunity ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Selected product ID to filter opportunities */\n productId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function OpportunitySelector({\n value,\n onValueChange,\n productId,\n placeholder = \"Select opportunity\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: OpportunitySelectorProps) {\n const isProductSelected = !!productId && productId.trim() !== \"\";\n\n const { data: opportunitiesData, isLoading } = useOpportunities({\n filters: {\n productId,\n },\n enabled: isProductSelected,\n });\n\n const opportunities = useMemo(\n () => opportunitiesData?.opportunities ?? [],\n [opportunitiesData?.opportunities]\n );\n\n const opportunityOptions = useMemo(() => {\n if (!opportunities || opportunities.length === 0) return [];\n\n const filteredOpportunities = opportunities.filter((opp) => opp.status === \"active\");\n\n return filteredOpportunities.map((opportunity) => ({\n label: opportunity.name || opportunity.shortName,\n value: opportunity.id!,\n description: opportunity.shortName !== opportunity.name ? opportunity.shortName : undefined,\n icon: opportunity.depositTokens?.[0]?.logoUrl\n ? () => (\n <img\n src={opportunity.depositTokens[0].logoUrl}\n alt={opportunity.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [opportunities]);\n\n // Clear selection when product changes\n useEffect(() => {\n if (!isProductSelected && value) {\n onValueChange(\"\");\n }\n }, [isProductSelected, value, onValueChange]);\n\n return (\n <Combobox\n searchable={searchable}\n options={opportunityOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isProductSelected}\n placeholder={\n !isProductSelected\n ? \"Select a product first\"\n : isLoading\n ? \"Loading opportunities...\"\n : placeholder\n }\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n"],"mappings":"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","names":["import_ui","import_nuqs","import_jsx_runtime","import_nuqs","import_jsx_runtime","import_nuqs","import_jsx_runtime","import_ui","import_jsx_runtime","import_ui","import_jsx_runtime","import_react","import_ui","import_lucide_react","import_jsx_runtime","import_ui","import_jsx_runtime","import_nuqs","import_react","import_nuqs","import_react","import_react","import_ui","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/filters/RangeSliderFilter.tsx","../src/filters/BooleanFilter.tsx","../src/filters/Filter.tsx","../src/filters/MultiSelectFilter.tsx","../src/wrappers/FiltersGrid.tsx","../src/wrappers/FiltersPopover.tsx","../src/wrappers/ActiveFilterBadges.tsx","../src/wrappers/FiltersWrapper.tsx","../src/helpers/usePagination.ts","../src/helpers/useSorting.ts","../src/selectors/ChainsSelector.tsx","../src/selectors/TokensSelector.tsx","../src/selectors/ProductsSelector.tsx","../src/selectors/OpportunitiesSelector.tsx","../src/selectors/ChainSelector.tsx","../src/selectors/TokenSelector.tsx","../src/selectors/ProductSelector.tsx","../src/selectors/OpportunitySelector.tsx"],"sourcesContent":["export * from \"./filters\";\nexport * from \"./wrappers\";\nexport * from \"./helpers\";\nexport * from \"./selectors\";\n","\"use client\";\n\nimport React, { useEffect, useState } from \"react\";\nimport { Slider, Label } from \"@turtleclub/ui\";\nimport { useQueryState, parseAsInteger } from \"nuqs\";\n\ninterface RangeSliderFilterProps {\n /** Query key for minimum value (default: 'min') */\n minQueryKey?: string;\n /** Query key for maximum value (default: 'max') */\n maxQueryKey?: string;\n /** Minimum value (default: 0) */\n min?: number;\n /** Maximum value (default: 100) */\n max?: number;\n /** Step value for slider (default: 1) */\n step?: number;\n /** Whether the filter is disabled */\n disabled?: boolean;\n /** Custom label for the filter */\n label: string;\n /** Whether to show values (default: true) */\n showValues?: boolean;\n /** Value formatter function */\n formatValue?: (value: number) => string;\n /** Custom className for the container */\n className?: string;\n}\n\nconst defaultFormatter = (value: number): string => {\n return value.toLocaleString();\n};\n\nexport function RangeSliderFilter({\n minQueryKey = \"min\",\n maxQueryKey = \"max\",\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n label = \"Range\",\n showValues = true,\n formatValue = defaultFormatter,\n className = \"\",\n}: RangeSliderFilterProps) {\n const [minValue, setMinValue] = useQueryState(minQueryKey, parseAsInteger.withDefault(min));\n\n const [maxValue, setMaxValue] = useQueryState(maxQueryKey, parseAsInteger.withDefault(max));\n\n // Local state for slider values (to avoid excessive URL updates)\n const [localRange, setLocalRange] = useState([minValue, maxValue]);\n\n // Update local state when query params change\n useEffect(() => {\n setLocalRange([minValue, maxValue]);\n }, [minValue, maxValue]);\n\n const handleRangeChange = (values: number[]) => {\n setLocalRange(values);\n };\n\n const handleRangeCommit = (values: number[]) => {\n const [newMin, newMax] = values;\n if (newMin !== minValue) {\n setMinValue(newMin === min ? null : newMin);\n }\n if (newMax !== maxValue) {\n setMaxValue(newMax === max ? null : newMax);\n }\n };\n\n const isDefaultRange = localRange[0] === min && localRange[1] === max;\n\n return (\n <div className={`space-y-3 ${className}`}>\n <div className=\"flex items-center justify-between\">\n <Label className=\"text-sm font-medium\">{label}</Label>\n {showValues && (\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <span>{formatValue(localRange[0])}</span>\n <span>-</span>\n <span>{formatValue(localRange[1])}</span>\n </div>\n )}\n </div>\n\n <div className=\"px-2\">\n <Slider\n value={localRange}\n onValueChange={handleRangeChange}\n onValueCommit={handleRangeCommit}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n className=\"w-full\"\n />\n </div>\n\n {showValues && (\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>{formatValue(min)}</span>\n <span>{formatValue(max)}</span>\n </div>\n )}\n\n {!isDefaultRange && (\n <div className=\"flex justify-end\">\n <button\n onClick={() => {\n setLocalRange([min, max]);\n handleRangeCommit([min, max]);\n }}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors\"\n disabled={disabled}\n >\n Reset\n </button>\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Switch, Label } from \"@turtleclub/ui\";\nimport { useQueryState, parseAsBoolean } from \"nuqs\";\n\ninterface BooleanSwitchFilterProps {\n /** Query key for the boolean value (default: 'enabled') */\n queryKey?: string;\n /** Default value when not set (default: false) */\n defaultValue?: boolean;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Label for the switch */\n label: string;\n /** Description text (optional) */\n description?: string;\n /** Custom className for the container */\n className?: string;\n}\n\nexport function BooleanFilter({\n queryKey = \"enabled\",\n defaultValue = false,\n disabled = false,\n label,\n description,\n className = \"\",\n}: BooleanSwitchFilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsBoolean.withDefault(defaultValue));\n\n const handleToggle = (checked: boolean) => {\n // If the value is the same as default, remove from URL\n setValue(checked === defaultValue ? null : checked);\n };\n\n return (\n <div className={`flex items-center justify-between space-x-2 ${className}`}>\n <div className=\"space-y-0.5\">\n <Label className=\"text-sm font-medium\">{label}</Label>\n {description && <p className=\"text-xs text-muted-foreground\">{description}</p>}\n </div>\n <Switch checked={value} onCheckedChange={handleToggle} disabled={disabled} />\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { useQueryState, parseAsString } from \"nuqs\";\n\ninterface FilterProps {\n /** Query parameter key */\n queryKey: string;\n /** Child component to render (selector) */\n children: (props: { value: string; onValueChange: (value: string) => void }) => React.ReactNode;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n}\n\n/**\n * Generic Filter component that handles nuqs URL state management for single values.\n *\n * Provides value and onValueChange props to child components,\n * decoupling selector logic from URL state management.\n *\n * @example Basic Single Selection\n * ```tsx\n * // Single chain selection - persists to URL as ?chainId=ethereum\n * <Filter queryKey=\"chainId\">\n * {({ value, onValueChange }) => (\n * <ChainSelector\n * value={value}\n * onValueChange={onValueChange}\n * placeholder=\"Select chain\"\n * />\n * )}\n * </Filter>\n * ```\n */\nexport function Filter({ queryKey, children, onValueChange }: FilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsString.withDefault(\"\"));\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue || null);\n onValueChange?.(newValue);\n };\n\n return <>{children({ value, onValueChange: handleValueChange })}</>;\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { useQueryState, parseAsArrayOf, parseAsString } from \"nuqs\";\n\ninterface MultiSelectFilterProps {\n /** Query parameter key */\n queryKey: string;\n /** Child component to render (selector) */\n children: (props: {\n value: string[];\n onValueChange: (values: string[]) => void;\n }) => React.ReactNode;\n /** Callback when values change */\n onValueChange?: (values: string[]) => void;\n}\n\n/**\n * Generic MultiSelectFilter component that handles nuqs URL state management for array values.\n *\n * Provides value and onValueChange props to child components,\n * decoupling selector logic from URL state management.\n *\n * @example\n * ```tsx\n * <MultiSelectFilter queryKey=\"chainId\">\n * {({ value, onValueChange }) => (\n * <ChainsSelector\n * value={value}\n * onValueChange={onValueChange}\n * placeholder=\"Select chains\"\n * />\n * )}\n * </MultiSelectFilter>\n * ```\n */\nexport function MultiSelectFilter({ queryKey, children, onValueChange }: MultiSelectFilterProps) {\n const [value, setValue] = useQueryState(queryKey, parseAsArrayOf(parseAsString).withDefault([]));\n\n const handleValueChange = (newValue: string[]) => {\n setValue(newValue.length > 0 ? newValue : null);\n onValueChange?.(newValue);\n };\n\n return <>{children({ value, onValueChange: handleValueChange })}</>;\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn, Label } from \"@turtleclub/ui\";\n\nexport interface FilterConfig {\n key: string;\n label: string;\n component: React.ReactNode;\n enabled: boolean;\n section?: string;\n}\n\nexport interface FiltersGridProps {\n filters: FilterConfig[];\n columns?: number;\n className?: string;\n sectionClassName?: string;\n}\n\nexport function FiltersGrid({\n filters,\n columns = 3,\n className,\n sectionClassName,\n}: FiltersGridProps) {\n const enabledFilters = filters.filter((filter) => filter.enabled);\n\n if (enabledFilters.length === 0) {\n return null;\n }\n\n // Group filters by section\n const sections = enabledFilters.reduce(\n (acc, filter) => {\n const sectionName = filter.section || \"default\";\n if (!acc[sectionName]) {\n acc[sectionName] = [];\n }\n acc[sectionName].push(filter);\n return acc;\n },\n {} as Record<string, typeof enabledFilters>\n );\n\n const sectionNames = Object.keys(sections);\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {sectionNames.map((sectionName, sectionIndex) => (\n <div key={sectionName}>\n {sectionIndex > 0 && <div className=\"border-t border-border mb-4\" />}\n <div\n className={cn(\"grid gap-2\", sectionClassName)}\n style={{\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {sections[sectionName].map((filter) => (\n <div key={filter.key} className=\"flex flex-col gap-2\">\n {filter.component}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n buttonVariants,\n cn,\n Label,\n Badge,\n} from \"@turtleclub/ui\";\nimport { SlidersHorizontal } from \"lucide-react\";\nimport { FilterConfig } from \"./FiltersGrid\";\n\nexport interface FiltersPopoverProps {\n filters: FilterConfig[];\n triggerLabel?: string;\n columns?: number;\n className?: string;\n popoverClassName?: string;\n sectionClassName?: string;\n}\n\nexport function FiltersPopover({\n filters,\n triggerLabel = \"Filters\",\n columns = 2,\n className,\n popoverClassName,\n sectionClassName,\n}: FiltersPopoverProps) {\n const enabledFilters = filters.filter((filter) => filter.enabled);\n\n if (enabledFilters.length === 0) {\n return null;\n }\n\n // Group filters by section\n const sections = enabledFilters.reduce(\n (acc, filter) => {\n const sectionName = filter.section || \"default\";\n if (!acc[sectionName]) {\n acc[sectionName] = [];\n }\n acc[sectionName].push(filter);\n return acc;\n },\n {} as Record<string, typeof enabledFilters>\n );\n\n const sectionNames = Object.keys(sections);\n\n return (\n <Popover>\n <PopoverTrigger\n className={cn(\n buttonVariants({\n variant: \"default\",\n size: \"default\",\n border: \"bordered\",\n }),\n \"!bg-neutral-alpha-2\",\n className\n )}\n >\n <SlidersHorizontal className=\"mr-2 h-4 w-4\" />\n {triggerLabel}\n </PopoverTrigger>\n <PopoverContent\n className={cn(\"w-auto min-w-[400px] max-w-[600px]\", popoverClassName)}\n align=\"start\"\n >\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h4 className=\"font-medium text-sm\">Filters</h4>\n </div>\n <div className=\"space-y-4\">\n {sectionNames.map((sectionName, sectionIndex) => (\n <div key={sectionName}>\n {sectionIndex > 0 && <div className=\"border-t border-border mb-4\" />}\n <div\n className={cn(\"grid gap-2\", sectionClassName)}\n style={{\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,\n }}\n >\n {sections[sectionName].map((filter) => (\n <div key={filter.key} className=\"flex flex-col gap-2\">\n {filter.component}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","\"use client\";\n\nimport React, { useMemo } from \"react\";\nimport { Badge, Button, cn } from \"@turtleclub/ui\";\nimport { X } from \"lucide-react\";\n\nexport interface ActiveFilterConfig {\n /** Unique key for the filter */\n key: string;\n /** Display label for the filter */\n label: string;\n /** Current filter value to display */\n value: string;\n /** Query parameter key(s) this filter uses */\n queryKeys: string | string[];\n /** Whether this filter is currently active */\n isActive: boolean;\n}\n\nexport interface ActiveFilterBadgesProps {\n /** Array of filter configurations */\n filters: ActiveFilterConfig[];\n /** Custom className for the container */\n className?: string;\n /** Label for clear all button (default: \"Clear All\") */\n clearAllLabel?: string;\n /** Whether to show clear all button (default: true) */\n showClearAll?: boolean;\n /** Custom render function for individual badges */\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n /** Callback function to clear individual filter */\n onClearFilter: (queryKeys: string | string[]) => void;\n /** Callback function to clear all filters */\n onClearAll: (allQueryKeys: (string | string[])[]) => void;\n}\n\n/**\n * Component that displays active filter badges with individual clear buttons\n * and an optional \"clear all\" button.\n *\n * @example\n * ```tsx\n * const activeFilters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * value: 'Ethereum',\n * queryKeys: 'chainId',\n * isActive: true,\n * },\n * {\n * key: 'sorting',\n * label: 'Sort',\n * value: 'Name (A-Z)',\n * queryKeys: ['sortBy', 'sortOrder'],\n * isActive: true,\n * },\n * ];\n *\n * <ActiveFilterBadges filters={activeFilters} />\n * ```\n */\nexport function ActiveFilterBadges({\n filters,\n className,\n clearAllLabel = \"Clear All\",\n showClearAll = true,\n renderBadge,\n onClearFilter,\n onClearAll,\n}: ActiveFilterBadgesProps) {\n // Get only active filters\n const activeFilters = useMemo(() => {\n return filters.filter((filter) => filter.isActive && filter.value);\n }, [filters]);\n\n // Clear all function\n const clearAll = () => {\n const allQueryKeys = activeFilters.map((filter) => filter.queryKeys);\n onClearAll(allQueryKeys);\n };\n\n // Don't render if no active filters\n if (activeFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)}>\n {activeFilters.map((filter) => {\n return (\n <FilterBadge\n key={filter.key}\n filter={filter}\n renderBadge={renderBadge}\n onClearFilter={onClearFilter}\n />\n );\n })}\n\n {showClearAll && activeFilters.length > 1 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={clearAll} className=\"h-7 px-2 text-xs\">\n {clearAllLabel}\n </Button>\n )}\n </div>\n );\n}\n\ninterface FilterBadgeProps {\n filter: ActiveFilterConfig;\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n onClearFilter: (queryKeys: string | string[]) => void;\n}\n\nfunction FilterBadge({ filter, renderBadge, onClearFilter }: FilterBadgeProps) {\n const clearFilter = () => {\n onClearFilter(filter.queryKeys);\n };\n\n if (renderBadge) {\n return <>{renderBadge(filter, clearFilter)}</>;\n }\n\n return (\n <Badge className=\"flex items-center gap-1 pr-1 border-border border\">\n <span className=\"text-xs\">\n {filter.label}: {filter.value}\n </span>\n <button\n onClick={clearFilter}\n className=\"ml-1 rounded-full p-0.5 hover:bg-black/10 focus:bg-black/10 focus:outline-none\"\n aria-label={`Clear ${filter.label} filter`}\n >\n <X className=\"h-3 w-3\" />\n </button>\n </Badge>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@turtleclub/ui\";\nimport { FiltersGrid } from \"./FiltersGrid\";\nimport { FiltersPopover } from \"./FiltersPopover\";\nimport { ActiveFilterBadges, ActiveFilterConfig } from \"./ActiveFilterBadges\";\nimport { FilterConfig } from \"./FiltersGrid\";\n\nexport interface FiltersWrapperProps {\n /** Array of filter configurations */\n filters: FilterConfig[];\n /** Array of active filter configurations for badges */\n activeFilters: ActiveFilterConfig[];\n /** Layout type: 'grid' or 'popover' */\n layout: \"grid\" | \"popover\";\n /** Custom className for the wrapper */\n className?: string;\n /** Custom className for the active badges section */\n badgesClassName?: string;\n /** Custom className for the slot container */\n slotClassName?: string;\n /** Optional content to render on the left side of filters */\n leftSlot?: React.ReactNode;\n /** Optional content to render on the right side of filters */\n rightSlot?: React.ReactNode;\n\n // Grid-specific props\n /** Number of columns for grid layout (default: 3) */\n columns?: number;\n\n // Popover-specific props\n /** Button label for popover trigger (default: \"Filters\") */\n triggerLabel?: string;\n /** Number of columns in popover (default: 2) */\n popoverColumns?: number;\n /** Custom className for popover trigger button */\n popoverClassName?: string;\n /** Custom className for popover content */\n popoverContentClassName?: string;\n\n // Active badges props\n /** Label for clear all button (default: \"Clear All\") */\n clearAllLabel?: string;\n /** Whether to show clear all button (default: true) */\n showClearAll?: boolean;\n /** Custom render function for individual badges */\n renderBadge?: (filter: ActiveFilterConfig, clearFilter: () => void) => React.ReactNode;\n /** Whether to show active filter badges (default: true) */\n showActiveBadges?: boolean;\n /** Callback function to clear individual filter */\n onClearFilter: (queryKeys: string | string[]) => void;\n /** Callback function to clear all filters */\n onClearAll: (allQueryKeys: (string | string[])[]) => void;\n}\n\n/**\n * Unified wrapper component that combines filter controls with active filter badges.\n *\n * Supports both grid and popover layouts, automatically displays active filter badges\n * below the filter controls with individual and bulk clear functionality.\n *\n * @example\n * ```tsx\n * const filters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * component: <ChainFilter />,\n * enabled: true,\n * },\n * ];\n *\n * const activeFilters = [\n * {\n * key: 'chain',\n * label: 'Chain',\n * value: 'Ethereum',\n * queryKeys: 'chainId',\n * isActive: true,\n * },\n * ];\n *\n * <FiltersWrapper\n * layout=\"grid\"\n * filters={filters}\n * activeFilters={activeFilters}\n * />\n * ```\n */\nexport function FiltersWrapper({\n filters,\n activeFilters,\n layout,\n className,\n badgesClassName,\n slotClassName,\n leftSlot,\n rightSlot,\n columns = 3,\n triggerLabel = \"Filters\",\n popoverColumns = 2,\n popoverClassName,\n popoverContentClassName,\n clearAllLabel = \"Clear All\",\n showClearAll = true,\n renderBadge,\n showActiveBadges = true,\n onClearFilter,\n onClearAll,\n}: FiltersWrapperProps) {\n const hasActiveFilters = activeFilters.some((filter) => filter.isActive && filter.value);\n\n return (\n <div className={cn(\"space-y-3\", className)}>\n {/* Filter Controls */}\n <div className={cn(\"flex items-center gap-2\", slotClassName)}>\n {leftSlot}\n <div className=\"flex-1\">\n {layout === \"grid\" ? (\n <FiltersGrid filters={filters} columns={columns} className={popoverClassName} />\n ) : (\n <FiltersPopover\n filters={filters}\n triggerLabel={triggerLabel}\n columns={popoverColumns}\n className={popoverClassName}\n popoverClassName={popoverContentClassName}\n />\n )}\n </div>\n {rightSlot}\n </div>\n\n {/* Active Filter Badges */}\n {showActiveBadges && hasActiveFilters && (\n <ActiveFilterBadges\n filters={activeFilters}\n className={badgesClassName}\n clearAllLabel={clearAllLabel}\n showClearAll={showClearAll}\n renderBadge={renderBadge}\n onClearFilter={onClearFilter}\n onClearAll={onClearAll}\n />\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useQueryState, parseAsInteger } from \"nuqs\";\nimport { useMemo, useCallback } from \"react\";\nimport type { PaginationState } from \"@tanstack/react-table\";\n\nexport interface UsePaginationOptions {\n /** Default page size (default: 10) */\n defaultPageSize?: number;\n /** Default page index (default: 0) */\n defaultPageIndex?: number;\n /** Query param key for page index (default: 'page') */\n pageIndexKey?: string;\n /** Query param key for page size (default: 'pageSize') */\n pageSizeKey?: string;\n}\n\nexport interface UsePaginationReturn {\n /** Current pagination state for TanStack Table */\n pagination: PaginationState;\n /** Function to update pagination state */\n setPagination: (updater: PaginationState | ((prev: PaginationState) => PaginationState)) => void;\n /** Current page index (0-based) */\n pageIndex: number;\n /** Current page size */\n pageSize: number;\n /** Set page index directly */\n setPageIndex: (pageIndex: number) => void;\n /** Set page size directly */\n setPageSize: (pageSize: number) => void;\n /** Go to next page */\n nextPage: (totalPages?: number) => void;\n /** Go to previous page */\n previousPage: () => void;\n /** Go to first page */\n firstPage: () => void;\n /** Go to last page */\n lastPage: (totalPages: number) => void;\n /** Reset pagination to defaults */\n reset: () => void;\n /** Check if can go to next page */\n canNextPage: (totalPages?: number) => boolean;\n /** Check if can go to previous page */\n canPreviousPage: boolean;\n}\n\n/**\n * Hook for managing server-side pagination state using nuqs.\n *\n * This hook synchronizes pagination state with URL query parameters,\n * making it perfect for server-side pagination where the URL should\n * reflect the current page and page size.\n *\n * @example\n * ```tsx\n * function MyTable() {\n * const {\n * pagination,\n * setPagination,\n * pageIndex,\n * pageSize,\n * setPageIndex,\n * setPageSize\n * } = usePagination({\n * defaultPageSize: 20,\n * pageIndexKey: 'page',\n * pageSizeKey: 'limit'\n * });\n *\n * // Use with TanStack Table\n * const table = useReactTable({\n * data,\n * columns,\n * manualPagination: true,\n * pagination,\n * onPaginationChange: setPagination,\n * pageCount: Math.ceil(totalCount / pageSize),\n * });\n *\n * return <DataTable table={table} />;\n * }\n * ```\n */\nexport function usePagination(options: UsePaginationOptions = {}): UsePaginationReturn {\n const {\n defaultPageSize = 10,\n defaultPageIndex = 0,\n pageIndexKey = \"page\",\n pageSizeKey = \"pageSize\",\n } = options;\n\n // Use nuqs to manage query state\n const [rawPageIndex, setRawPageIndex] = useQueryState(\n pageIndexKey,\n parseAsInteger.withDefault(defaultPageIndex)\n );\n\n const [rawPageSize, setRawPageSize] = useQueryState(\n pageSizeKey,\n parseAsInteger.withDefault(defaultPageSize)\n );\n\n // Ensure page index is never negative\n const pageIndex = useMemo(() => Math.max(0, rawPageIndex), [rawPageIndex]);\n\n // Use page size directly from query state\n const pageSize = rawPageSize;\n\n // Create pagination state for TanStack Table\n const pagination = useMemo<PaginationState>(\n () => ({\n pageIndex,\n pageSize,\n }),\n [pageIndex, pageSize]\n );\n\n // Set pagination function that handles both object and function updates\n const setPagination = useCallback(\n (updater: PaginationState | ((prev: PaginationState) => PaginationState)) => {\n const newPagination = typeof updater === \"function\" ? updater(pagination) : updater;\n\n if (newPagination.pageIndex !== pageIndex) {\n setRawPageIndex(Math.max(0, newPagination.pageIndex));\n }\n\n if (newPagination.pageSize !== pageSize) {\n setRawPageSize(newPagination.pageSize);\n }\n },\n [pagination, pageIndex, pageSize, setRawPageIndex, setRawPageSize]\n );\n\n // Individual setters\n const setPageIndex = useCallback(\n (newPageIndex: number) => {\n setRawPageIndex(Math.max(0, newPageIndex));\n },\n [setRawPageIndex]\n );\n\n const setPageSize = useCallback(\n (newPageSize: number) => {\n setRawPageSize(newPageSize);\n // Reset to first page when page size changes\n setRawPageIndex(0);\n },\n [setRawPageSize, setRawPageIndex]\n );\n\n // Navigation functions\n const nextPage = useCallback(\n (totalPages?: number) => {\n const nextPageIndex = pageIndex + 1;\n if (!totalPages || nextPageIndex < totalPages) {\n setPageIndex(nextPageIndex);\n }\n },\n [pageIndex, setPageIndex]\n );\n\n const previousPage = useCallback(() => {\n if (pageIndex > 0) {\n setPageIndex(pageIndex - 1);\n }\n }, [pageIndex, setPageIndex]);\n\n const firstPage = useCallback(() => {\n setPageIndex(0);\n }, [setPageIndex]);\n\n const lastPage = useCallback(\n (totalPages: number) => {\n setPageIndex(Math.max(0, totalPages - 1));\n },\n [setPageIndex]\n );\n\n // Reset function\n const reset = useCallback(() => {\n setRawPageIndex(defaultPageIndex);\n setRawPageSize(defaultPageSize);\n }, [setRawPageIndex, setRawPageSize, defaultPageIndex, defaultPageSize]);\n\n // Navigation state\n const canPreviousPage = pageIndex > 0;\n const canNextPage = useCallback(\n (totalPages?: number) => {\n if (!totalPages) return true; // Assume we can go next if total pages unknown\n return pageIndex < totalPages - 1;\n },\n [pageIndex]\n );\n\n return {\n pagination,\n setPagination,\n pageIndex,\n pageSize,\n setPageIndex,\n setPageSize,\n nextPage,\n previousPage,\n firstPage,\n lastPage,\n reset,\n canNextPage,\n canPreviousPage,\n };\n}\n","\"use client\";\n\nimport { useQueryState, parseAsString } from \"nuqs\";\nimport { useMemo, useCallback } from \"react\";\nimport type { SortingState } from \"@tanstack/react-table\";\n\nexport interface UseSortingOptions {\n /** Default sort column (default: undefined - no sorting) */\n defaultSortBy?: string;\n /** Default sort order (default: 'asc') */\n defaultSortOrder?: \"asc\" | \"desc\";\n /** Query param key for sort column (default: 'sortBy') */\n sortByKey?: string;\n /** Query param key for sort order (default: 'sortOrder') */\n sortOrderKey?: string;\n}\n\nexport interface UseSortingReturn {\n /** Current sorting state for TanStack Table */\n sorting: SortingState;\n /** Function to update sorting state */\n setSorting: (updater: SortingState | ((prev: SortingState) => SortingState)) => void;\n /** Current sort column (undefined if no sorting) */\n sortBy: string | undefined;\n /** Current sort order */\n sortOrder: \"asc\" | \"desc\";\n /** Set sort column and order directly */\n setSort: (column: string, order?: \"asc\" | \"desc\") => void;\n /** Clear all sorting */\n clearSort: () => void;\n /** Toggle sort order for a column */\n toggleSort: (column: string) => void;\n /** Check if a column is currently sorted */\n isSorted: (column: string) => boolean;\n /** Get sort order for a column */\n getSortOrder: (column: string) => \"asc\" | \"desc\" | undefined;\n}\n\n/**\n * Hook for managing server-side sorting state using nuqs.\n *\n * This hook synchronizes sorting state with URL query parameters,\n * making it perfect for server-side sorting where the URL should\n * reflect the current sort state.\n *\n * @example\n * ```tsx\n * function MyTable() {\n * const {\n * sorting,\n * setSorting,\n * sortBy,\n * sortOrder,\n * setSort,\n * toggleSort\n * } = useSorting({\n * defaultSortBy: 'name',\n * defaultSortOrder: 'asc'\n * });\n *\n * // Use with TanStack Table\n * const table = useReactTable({\n * data,\n * columns,\n * manualSorting: true,\n * sorting,\n * onSortingChange: setSorting,\n * });\n *\n * return <DataTable table={table} />;\n * }\n * ```\n */\nexport function useSorting(options: UseSortingOptions = {}): UseSortingReturn {\n const {\n defaultSortBy,\n defaultSortOrder = \"asc\",\n sortByKey = \"sortBy\",\n sortOrderKey = \"sortOrder\",\n } = options;\n\n // Use nuqs to manage query state\n const [sortBy, setSortBy] = useQueryState(\n sortByKey,\n parseAsString.withDefault(defaultSortBy || \"\")\n );\n\n const [sortOrder, setSortOrder] = useQueryState(\n sortOrderKey,\n parseAsString.withDefault(defaultSortOrder)\n );\n\n // Ensure sort order is valid\n const validSortOrder = useMemo(() => {\n return sortOrder === \"desc\" ? \"desc\" : \"asc\";\n }, [sortOrder]);\n\n // Create sorting state for TanStack Table\n const sorting = useMemo<SortingState>(() => {\n if (!sortBy || sortBy.trim() === \"\") {\n return [];\n }\n return [\n {\n id: sortBy,\n desc: validSortOrder === \"desc\",\n },\n ];\n }, [sortBy, validSortOrder]);\n\n // Set sorting function that handles both object and function updates\n const setSorting = useCallback(\n (updater: SortingState | ((prev: SortingState) => SortingState)) => {\n const newSorting = typeof updater === \"function\" ? updater(sorting) : updater;\n\n if (newSorting.length === 0) {\n // Clear sorting\n setSortBy(\"\");\n } else {\n // Set first sort (TanStack Table typically only has one sort at a time)\n const firstSort = newSorting[0];\n setSortBy(firstSort.id);\n setSortOrder(firstSort.desc ? \"desc\" : \"asc\");\n }\n },\n [sorting, setSortBy, setSortOrder]\n );\n\n // Set sort column and order directly\n const setSort = useCallback(\n (column: string, order: \"asc\" | \"desc\" = \"asc\") => {\n setSortBy(column);\n setSortOrder(order);\n },\n [setSortBy, setSortOrder]\n );\n\n // Clear all sorting\n const clearSort = useCallback(() => {\n setSortBy(null);\n }, [setSortBy]);\n\n // Toggle sort order for a column\n const toggleSort = useCallback(\n (column: string) => {\n if (sortBy === column) {\n // Same column, toggle order\n setSortOrder(validSortOrder === \"asc\" ? \"desc\" : \"asc\");\n } else {\n // Different column, set new column with asc\n setSortBy(column);\n setSortOrder(\"asc\");\n }\n },\n [sortBy, validSortOrder, setSortBy, setSortOrder]\n );\n\n // Check if a column is currently sorted\n const isSorted = useCallback(\n (column: string) => {\n return sortBy === column;\n },\n [sortBy]\n );\n\n // Get sort order for a column\n const getSortOrder = useCallback(\n (column: string) => {\n return sortBy === column ? validSortOrder : undefined;\n },\n [sortBy, validSortOrder]\n );\n\n return {\n sorting,\n setSorting,\n sortBy: sortBy || undefined,\n sortOrder: validSortOrder,\n setSort,\n clearSort,\n toggleSort,\n isSorted,\n getSortOrder,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useSupportedChains } from \"@turtleclub/hooks\";\n\ninterface ChainSelectorProps {\n /** Selected chain IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ChainsSelector({\n value,\n onValueChange,\n placeholder = \"Select chains\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: ChainSelectorProps) {\n const { chains, isLoading } = useSupportedChains();\n\n const chainOptions = useMemo(() => {\n if (!chains || chains.length === 0) return [];\n\n const filteredChains = chains.filter((chain) => chain.status === \"active\");\n\n return filteredChains.map((chain) => ({\n label: chain.name,\n value: chain?.id ?? \"\",\n icon: chain.logoUrl\n ? () => (\n <img\n src={chain.logoUrl}\n alt={chain.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [chains]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={chainOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading chains...\" : placeholder}\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useSupportedTokens } from \"@turtleclub/hooks\";\n\ninterface TokenSelectorProps {\n /** Selected token IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Selected chain ID to filter tokens */\n chainId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function TokensSelector({\n value,\n onValueChange,\n chainId,\n placeholder = \"Select tokens\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: TokenSelectorProps) {\n const isChainSelected = !!chainId && chainId.trim() !== \"\";\n\n const { tokens, isLoading } = useSupportedTokens({\n // chainId: isChainSelected ? chainId : undefined,\n limit: 100,\n enabled: isChainSelected,\n });\n\n const tokenOptions = useMemo(() => {\n if (!tokens) return [];\n\n return tokens.map((token) => ({\n label: `${token.symbol} - ${token.name}`,\n value: token?.id || \"\",\n icon: token.logoUrl\n ? () => (\n <img\n src={token.logoUrl}\n alt={token.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [tokens]);\n\n // Clear selection when chain changes\n useEffect(() => {\n if (!isChainSelected && value.length > 0) {\n onValueChange([]);\n }\n }, [isChainSelected, value, onValueChange]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={tokenOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isChainSelected}\n placeholder={\n !isChainSelected ? \"Select a chain first\" : isLoading ? \"Loading tokens...\" : placeholder\n }\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useProducts } from \"@turtleclub/hooks\";\n\ninterface ProductSelectorProps {\n /** Selected product IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ProductsSelector({\n value,\n onValueChange,\n placeholder = \"Select products\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: ProductSelectorProps) {\n const { data: productsData, isLoading } = useProducts({});\n\n const products = useMemo(() => productsData?.products ?? [], [productsData?.products]);\n\n const productOptions = useMemo(() => {\n if (!products || products.length === 0) return [];\n\n return products.map((product) => ({\n label: product.name,\n value: product.id,\n icon: product.logoUrl\n ? () => (\n <img\n src={product.logoUrl}\n alt={product.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [products]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={productOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading products...\" : placeholder}\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { MultiSelect } from \"@turtleclub/ui\";\nimport { useOpportunities } from \"@turtleclub/hooks\";\n\ninterface OpportunitySelectorProps {\n /** Selected opportunity IDs */\n value: string[];\n /** Callback when selection changes */\n onValueChange: (values: string[]) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Maximum count to show in trigger */\n maxCount?: number;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function OpportunitiesSelector({\n value,\n onValueChange,\n placeholder = \"Select opportunities\",\n disabled = false,\n className,\n maxCount = 1,\n closeOnSelect = true,\n searchable = true,\n}: OpportunitySelectorProps) {\n const { data: opportunitiesData, isLoading } = useOpportunities();\n\n const opportunities = useMemo(\n () => opportunitiesData?.opportunities ?? [],\n [opportunitiesData?.opportunities]\n );\n\n const opportunityOptions = useMemo(() => {\n if (!opportunities || opportunities.length === 0) return [];\n\n const filteredOpportunities = opportunities.filter((opp) => opp.status === \"active\");\n\n return filteredOpportunities.map((opportunity) => ({\n label: opportunity.name || opportunity.shortName,\n value: opportunity.id!,\n description: opportunity.shortName !== opportunity.name ? opportunity.shortName : undefined,\n icon: opportunity.depositTokens?.[0]?.logoUrl\n ? () => (\n <img\n src={opportunity.depositTokens[0].logoUrl}\n alt={opportunity.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [opportunities]);\n\n return (\n <MultiSelect\n searchable={searchable}\n options={opportunityOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading opportunities...\" : placeholder}\n closeOnSelect={closeOnSelect}\n maxCount={maxCount}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useSupportedChains } from \"@turtleclub/hooks\";\n\ninterface ChainSelectorProps {\n /** Selected chain ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ChainSelector({\n value,\n onValueChange,\n placeholder = \"Select chain\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: ChainSelectorProps) {\n const { chains, isLoading } = useSupportedChains();\n\n const chainOptions = useMemo(() => {\n if (!chains || chains.length === 0) return [];\n\n const filteredChains = chains.filter((chain) => chain.status === \"active\");\n\n return filteredChains.map((chain) => ({\n label: chain.name,\n value: chain?.id ?? \"\",\n icon: chain.logoUrl\n ? () => (\n <img\n src={chain.logoUrl}\n alt={chain.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [chains]);\n\n return (\n <Combobox\n searchable={searchable}\n options={chainOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading chains...\" : placeholder}\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useSupportedTokens } from \"@turtleclub/hooks\";\n\ninterface TokenSelectorProps {\n /** Selected token ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Selected chain ID to filter tokens */\n chainId?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function TokenSelector({\n value,\n onValueChange,\n chainId,\n placeholder = \"Select token\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: TokenSelectorProps) {\n const isChainSelected = !!chainId && chainId.trim() !== \"\";\n\n const { tokens, isLoading } = useSupportedTokens({\n // chainId: isChainSelected ? chainId : undefined,\n limit: 100,\n enabled: isChainSelected,\n });\n\n const tokenOptions = useMemo(() => {\n if (!tokens) return [];\n\n return tokens.map((token) => ({\n label: `${token.symbol} - ${token.name}`,\n value: token?.id || \"\",\n icon: token.logoUrl\n ? () => (\n <img\n src={token.logoUrl}\n alt={token.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [tokens]);\n\n // Clear selection when chain changes\n useEffect(() => {\n if (!isChainSelected && value) {\n onValueChange(\"\");\n }\n }, [isChainSelected, value, onValueChange]);\n\n return (\n <Combobox\n searchable={searchable}\n options={tokenOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading || !isChainSelected}\n placeholder={\n !isChainSelected ? \"Select a chain first\" : isLoading ? \"Loading tokens...\" : placeholder\n }\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useProducts } from \"@turtleclub/hooks\";\n\ninterface ProductSelectorProps {\n /** Selected product ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function ProductSelector({\n value,\n onValueChange,\n placeholder = \"Select product\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: ProductSelectorProps) {\n const { data: productsData, isLoading } = useProducts({});\n\n const products = useMemo(() => productsData?.products ?? [], [productsData?.products]);\n\n const productOptions = useMemo(() => {\n if (!products || products.length === 0) return [];\n\n return products.map((product) => ({\n label: product.name,\n value: product.id,\n icon: product.logoUrl\n ? () => (\n <img\n src={product.logoUrl}\n alt={product.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [products]);\n\n return (\n <Combobox\n searchable={searchable}\n options={productOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading products...\" : placeholder}\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { Combobox } from \"@turtleclub/ui\";\nimport { useOpportunities } from \"@turtleclub/hooks\";\n\ninterface OpportunitySelectorProps {\n /** Selected opportunity ID */\n value: string;\n /** Callback when selection changes */\n onValueChange: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the selector is disabled */\n disabled?: boolean;\n /** Custom className */\n className?: string;\n /** Whether to close on select */\n closeOnSelect?: boolean;\n /** Whether to show search */\n searchable?: boolean;\n}\n\nexport function OpportunitySelector({\n value,\n onValueChange,\n placeholder = \"Select opportunity\",\n disabled = false,\n className,\n closeOnSelect = true,\n searchable = true,\n}: OpportunitySelectorProps) {\n const { data: opportunitiesData, isLoading } = useOpportunities();\n\n const opportunities = useMemo(\n () => opportunitiesData?.opportunities ?? [],\n [opportunitiesData?.opportunities]\n );\n\n const opportunityOptions = useMemo(() => {\n if (!opportunities || opportunities.length === 0) return [];\n\n const filteredOpportunities = opportunities.filter((opp) => opp.status === \"active\");\n\n return filteredOpportunities.map((opportunity) => ({\n label: opportunity.name || opportunity.shortName,\n value: opportunity.id!,\n description: opportunity.shortName !== opportunity.name ? opportunity.shortName : undefined,\n icon: opportunity.depositTokens?.[0]?.logoUrl\n ? () => (\n <img\n src={opportunity.depositTokens[0].logoUrl}\n alt={opportunity.name}\n width={16}\n height={16}\n className=\"size-4 rounded-full\"\n />\n )\n : undefined,\n }));\n }, [opportunities]);\n\n return (\n <Combobox\n searchable={searchable}\n options={opportunityOptions}\n value={value}\n onValueChange={onValueChange}\n disabled={disabled || isLoading}\n placeholder={isLoading ? \"Loading opportunities...\" : placeholder}\n closeOnSelect={closeOnSelect}\n className={className}\n />\n );\n}\n"],"mappings":"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","names":["import_ui","import_nuqs","import_jsx_runtime","import_nuqs","import_jsx_runtime","import_nuqs","import_jsx_runtime","import_ui","import_jsx_runtime","import_ui","import_jsx_runtime","import_react","import_ui","import_lucide_react","import_jsx_runtime","import_ui","import_jsx_runtime","import_nuqs","import_react","import_nuqs","import_react","import_react","import_ui","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime","import_react","import_ui","import_hooks","import_jsx_runtime"]}
package/dist/index.d.cts CHANGED
@@ -199,6 +199,12 @@ interface FiltersWrapperProps {
199
199
  className?: string;
200
200
  /** Custom className for the active badges section */
201
201
  badgesClassName?: string;
202
+ /** Custom className for the slot container */
203
+ slotClassName?: string;
204
+ /** Optional content to render on the left side of filters */
205
+ leftSlot?: React.ReactNode;
206
+ /** Optional content to render on the right side of filters */
207
+ rightSlot?: React.ReactNode;
202
208
  /** Number of columns for grid layout (default: 3) */
203
209
  columns?: number;
204
210
  /** Button label for popover trigger (default: "Filters") */
@@ -256,7 +262,7 @@ interface FiltersWrapperProps {
256
262
  * />
257
263
  * ```
258
264
  */
259
- declare function FiltersWrapper({ filters, activeFilters, layout, className, badgesClassName, columns, triggerLabel, popoverColumns, popoverClassName, popoverContentClassName, clearAllLabel, showClearAll, renderBadge, showActiveBadges, onClearFilter, onClearAll, }: FiltersWrapperProps): react_jsx_runtime.JSX.Element;
265
+ declare function FiltersWrapper({ filters, activeFilters, layout, className, badgesClassName, slotClassName, leftSlot, rightSlot, columns, triggerLabel, popoverColumns, popoverClassName, popoverContentClassName, clearAllLabel, showClearAll, renderBadge, showActiveBadges, onClearFilter, onClearAll, }: FiltersWrapperProps): react_jsx_runtime.JSX.Element;
260
266
 
261
267
  interface UsePaginationOptions {
262
268
  /** Default page size (default: 10) */
@@ -469,8 +475,6 @@ interface OpportunitySelectorProps$1 {
469
475
  value: string[];
470
476
  /** Callback when selection changes */
471
477
  onValueChange: (values: string[]) => void;
472
- /** Selected product ID to filter opportunities */
473
- productId?: string;
474
478
  /** Placeholder text */
475
479
  placeholder?: string;
476
480
  /** Whether the selector is disabled */
@@ -484,7 +488,7 @@ interface OpportunitySelectorProps$1 {
484
488
  /** Whether to show search */
485
489
  searchable?: boolean;
486
490
  }
487
- declare function OpportunitiesSelector({ value, onValueChange, productId, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
491
+ declare function OpportunitiesSelector({ value, onValueChange, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
488
492
 
489
493
  interface ChainSelectorProps {
490
494
  /** Selected chain ID */
@@ -547,8 +551,6 @@ interface OpportunitySelectorProps {
547
551
  value: string;
548
552
  /** Callback when selection changes */
549
553
  onValueChange: (value: string) => void;
550
- /** Selected product ID to filter opportunities */
551
- productId?: string;
552
554
  /** Placeholder text */
553
555
  placeholder?: string;
554
556
  /** Whether the selector is disabled */
@@ -560,6 +562,6 @@ interface OpportunitySelectorProps {
560
562
  /** Whether to show search */
561
563
  searchable?: boolean;
562
564
  }
563
- declare function OpportunitySelector({ value, onValueChange, productId, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
565
+ declare function OpportunitySelector({ value, onValueChange, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
564
566
 
565
567
  export { ActiveFilterBadges, type ActiveFilterBadgesProps, type ActiveFilterConfig, BooleanFilter, ChainSelector, ChainsSelector, Filter, type FilterConfig, FiltersGrid, type FiltersGridProps, FiltersPopover, type FiltersPopoverProps, FiltersWrapper, type FiltersWrapperProps, MultiSelectFilter, OpportunitiesSelector, OpportunitySelector, ProductSelector, ProductsSelector, RangeSliderFilter, TokenSelector, TokensSelector, type UsePaginationOptions, type UsePaginationReturn, type UseSortingOptions, type UseSortingReturn, usePagination, useSorting };
package/dist/index.d.ts CHANGED
@@ -199,6 +199,12 @@ interface FiltersWrapperProps {
199
199
  className?: string;
200
200
  /** Custom className for the active badges section */
201
201
  badgesClassName?: string;
202
+ /** Custom className for the slot container */
203
+ slotClassName?: string;
204
+ /** Optional content to render on the left side of filters */
205
+ leftSlot?: React.ReactNode;
206
+ /** Optional content to render on the right side of filters */
207
+ rightSlot?: React.ReactNode;
202
208
  /** Number of columns for grid layout (default: 3) */
203
209
  columns?: number;
204
210
  /** Button label for popover trigger (default: "Filters") */
@@ -256,7 +262,7 @@ interface FiltersWrapperProps {
256
262
  * />
257
263
  * ```
258
264
  */
259
- declare function FiltersWrapper({ filters, activeFilters, layout, className, badgesClassName, columns, triggerLabel, popoverColumns, popoverClassName, popoverContentClassName, clearAllLabel, showClearAll, renderBadge, showActiveBadges, onClearFilter, onClearAll, }: FiltersWrapperProps): react_jsx_runtime.JSX.Element;
265
+ declare function FiltersWrapper({ filters, activeFilters, layout, className, badgesClassName, slotClassName, leftSlot, rightSlot, columns, triggerLabel, popoverColumns, popoverClassName, popoverContentClassName, clearAllLabel, showClearAll, renderBadge, showActiveBadges, onClearFilter, onClearAll, }: FiltersWrapperProps): react_jsx_runtime.JSX.Element;
260
266
 
261
267
  interface UsePaginationOptions {
262
268
  /** Default page size (default: 10) */
@@ -469,8 +475,6 @@ interface OpportunitySelectorProps$1 {
469
475
  value: string[];
470
476
  /** Callback when selection changes */
471
477
  onValueChange: (values: string[]) => void;
472
- /** Selected product ID to filter opportunities */
473
- productId?: string;
474
478
  /** Placeholder text */
475
479
  placeholder?: string;
476
480
  /** Whether the selector is disabled */
@@ -484,7 +488,7 @@ interface OpportunitySelectorProps$1 {
484
488
  /** Whether to show search */
485
489
  searchable?: boolean;
486
490
  }
487
- declare function OpportunitiesSelector({ value, onValueChange, productId, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
491
+ declare function OpportunitiesSelector({ value, onValueChange, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
488
492
 
489
493
  interface ChainSelectorProps {
490
494
  /** Selected chain ID */
@@ -547,8 +551,6 @@ interface OpportunitySelectorProps {
547
551
  value: string;
548
552
  /** Callback when selection changes */
549
553
  onValueChange: (value: string) => void;
550
- /** Selected product ID to filter opportunities */
551
- productId?: string;
552
554
  /** Placeholder text */
553
555
  placeholder?: string;
554
556
  /** Whether the selector is disabled */
@@ -560,6 +562,6 @@ interface OpportunitySelectorProps {
560
562
  /** Whether to show search */
561
563
  searchable?: boolean;
562
564
  }
563
- declare function OpportunitySelector({ value, onValueChange, productId, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
565
+ declare function OpportunitySelector({ value, onValueChange, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
564
566
 
565
567
  export { ActiveFilterBadges, type ActiveFilterBadgesProps, type ActiveFilterConfig, BooleanFilter, ChainSelector, ChainsSelector, Filter, type FilterConfig, FiltersGrid, type FiltersGridProps, FiltersPopover, type FiltersPopoverProps, FiltersWrapper, type FiltersWrapperProps, MultiSelectFilter, OpportunitiesSelector, OpportunitySelector, ProductSelector, ProductsSelector, RangeSliderFilter, TokenSelector, TokensSelector, type UsePaginationOptions, type UsePaginationReturn, type UseSortingOptions, type UseSortingReturn, usePagination, useSorting };