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

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
@@ -744,7 +744,6 @@ var import_jsx_runtime12 = require("react/jsx-runtime");
744
744
  function OpportunitiesSelector({
745
745
  value,
746
746
  onValueChange,
747
- productId,
748
747
  placeholder = "Select opportunities",
749
748
  disabled = false,
750
749
  className,
@@ -752,13 +751,7 @@ function OpportunitiesSelector({
752
751
  closeOnSelect = true,
753
752
  searchable = true
754
753
  }) {
755
- const isProductSelected = !!productId && productId.trim() !== "";
756
- const { data: opportunitiesData, isLoading } = (0, import_hooks4.useOpportunities)({
757
- filters: {
758
- productId
759
- },
760
- enabled: isProductSelected
761
- });
754
+ const { data: opportunitiesData, isLoading } = (0, import_hooks4.useOpportunities)();
762
755
  const opportunities = (0, import_react8.useMemo)(
763
756
  () => opportunitiesData?.opportunities ?? [],
764
757
  [opportunitiesData?.opportunities]
@@ -782,11 +775,6 @@ function OpportunitiesSelector({
782
775
  ) : void 0
783
776
  }));
784
777
  }, [opportunities]);
785
- (0, import_react8.useEffect)(() => {
786
- if (!isProductSelected && value.length > 0) {
787
- onValueChange([]);
788
- }
789
- }, [isProductSelected, value, onValueChange]);
790
778
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
791
779
  import_ui10.MultiSelect,
792
780
  {
@@ -794,8 +782,8 @@ function OpportunitiesSelector({
794
782
  options: opportunityOptions,
795
783
  value,
796
784
  onValueChange,
797
- disabled: disabled || isLoading || !isProductSelected,
798
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
785
+ disabled: disabled || isLoading,
786
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
799
787
  closeOnSelect,
800
788
  maxCount,
801
789
  className
@@ -965,20 +953,13 @@ var import_jsx_runtime16 = require("react/jsx-runtime");
965
953
  function OpportunitySelector({
966
954
  value,
967
955
  onValueChange,
968
- productId,
969
956
  placeholder = "Select opportunity",
970
957
  disabled = false,
971
958
  className,
972
959
  closeOnSelect = true,
973
960
  searchable = true
974
961
  }) {
975
- const isProductSelected = !!productId && productId.trim() !== "";
976
- const { data: opportunitiesData, isLoading } = (0, import_hooks8.useOpportunities)({
977
- filters: {
978
- productId
979
- },
980
- enabled: isProductSelected
981
- });
962
+ const { data: opportunitiesData, isLoading } = (0, import_hooks8.useOpportunities)();
982
963
  const opportunities = (0, import_react12.useMemo)(
983
964
  () => opportunitiesData?.opportunities ?? [],
984
965
  [opportunitiesData?.opportunities]
@@ -1002,11 +983,6 @@ function OpportunitySelector({
1002
983
  ) : void 0
1003
984
  }));
1004
985
  }, [opportunities]);
1005
- (0, import_react12.useEffect)(() => {
1006
- if (!isProductSelected && value) {
1007
- onValueChange("");
1008
- }
1009
- }, [isProductSelected, value, onValueChange]);
1010
986
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1011
987
  import_ui14.Combobox,
1012
988
  {
@@ -1014,8 +990,8 @@ function OpportunitySelector({
1014
990
  options: opportunityOptions,
1015
991
  value,
1016
992
  onValueChange,
1017
- disabled: disabled || isLoading || !isProductSelected,
1018
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
993
+ disabled: disabled || isLoading,
994
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
1019
995
  closeOnSelect,
1020
996
  className
1021
997
  }
@@ -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 { 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 } 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
@@ -469,8 +469,6 @@ interface OpportunitySelectorProps$1 {
469
469
  value: string[];
470
470
  /** Callback when selection changes */
471
471
  onValueChange: (values: string[]) => void;
472
- /** Selected product ID to filter opportunities */
473
- productId?: string;
474
472
  /** Placeholder text */
475
473
  placeholder?: string;
476
474
  /** Whether the selector is disabled */
@@ -484,7 +482,7 @@ interface OpportunitySelectorProps$1 {
484
482
  /** Whether to show search */
485
483
  searchable?: boolean;
486
484
  }
487
- declare function OpportunitiesSelector({ value, onValueChange, productId, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
485
+ declare function OpportunitiesSelector({ value, onValueChange, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
488
486
 
489
487
  interface ChainSelectorProps {
490
488
  /** Selected chain ID */
@@ -547,8 +545,6 @@ interface OpportunitySelectorProps {
547
545
  value: string;
548
546
  /** Callback when selection changes */
549
547
  onValueChange: (value: string) => void;
550
- /** Selected product ID to filter opportunities */
551
- productId?: string;
552
548
  /** Placeholder text */
553
549
  placeholder?: string;
554
550
  /** Whether the selector is disabled */
@@ -560,6 +556,6 @@ interface OpportunitySelectorProps {
560
556
  /** Whether to show search */
561
557
  searchable?: boolean;
562
558
  }
563
- declare function OpportunitySelector({ value, onValueChange, productId, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
559
+ declare function OpportunitySelector({ value, onValueChange, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
564
560
 
565
561
  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
@@ -469,8 +469,6 @@ interface OpportunitySelectorProps$1 {
469
469
  value: string[];
470
470
  /** Callback when selection changes */
471
471
  onValueChange: (values: string[]) => void;
472
- /** Selected product ID to filter opportunities */
473
- productId?: string;
474
472
  /** Placeholder text */
475
473
  placeholder?: string;
476
474
  /** Whether the selector is disabled */
@@ -484,7 +482,7 @@ interface OpportunitySelectorProps$1 {
484
482
  /** Whether to show search */
485
483
  searchable?: boolean;
486
484
  }
487
- declare function OpportunitiesSelector({ value, onValueChange, productId, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
485
+ declare function OpportunitiesSelector({ value, onValueChange, placeholder, disabled, className, maxCount, closeOnSelect, searchable, }: OpportunitySelectorProps$1): react_jsx_runtime.JSX.Element;
488
486
 
489
487
  interface ChainSelectorProps {
490
488
  /** Selected chain ID */
@@ -547,8 +545,6 @@ interface OpportunitySelectorProps {
547
545
  value: string;
548
546
  /** Callback when selection changes */
549
547
  onValueChange: (value: string) => void;
550
- /** Selected product ID to filter opportunities */
551
- productId?: string;
552
548
  /** Placeholder text */
553
549
  placeholder?: string;
554
550
  /** Whether the selector is disabled */
@@ -560,6 +556,6 @@ interface OpportunitySelectorProps {
560
556
  /** Whether to show search */
561
557
  searchable?: boolean;
562
558
  }
563
- declare function OpportunitySelector({ value, onValueChange, productId, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
559
+ declare function OpportunitySelector({ value, onValueChange, placeholder, disabled, className, closeOnSelect, searchable, }: OpportunitySelectorProps): react_jsx_runtime.JSX.Element;
564
560
 
565
561
  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.js CHANGED
@@ -694,14 +694,13 @@ function ProductsSelector({
694
694
  }
695
695
 
696
696
  // src/selectors/OpportunitiesSelector.tsx
697
- import { useMemo as useMemo7, useEffect as useEffect3 } from "react";
697
+ import { useMemo as useMemo7 } from "react";
698
698
  import { MultiSelect as MultiSelect4 } from "@turtleclub/ui";
699
699
  import { useOpportunities } from "@turtleclub/hooks";
700
700
  import { jsx as jsx12 } from "react/jsx-runtime";
701
701
  function OpportunitiesSelector({
702
702
  value,
703
703
  onValueChange,
704
- productId,
705
704
  placeholder = "Select opportunities",
706
705
  disabled = false,
707
706
  className,
@@ -709,13 +708,7 @@ function OpportunitiesSelector({
709
708
  closeOnSelect = true,
710
709
  searchable = true
711
710
  }) {
712
- const isProductSelected = !!productId && productId.trim() !== "";
713
- const { data: opportunitiesData, isLoading } = useOpportunities({
714
- filters: {
715
- productId
716
- },
717
- enabled: isProductSelected
718
- });
711
+ const { data: opportunitiesData, isLoading } = useOpportunities();
719
712
  const opportunities = useMemo7(
720
713
  () => opportunitiesData?.opportunities ?? [],
721
714
  [opportunitiesData?.opportunities]
@@ -739,11 +732,6 @@ function OpportunitiesSelector({
739
732
  ) : void 0
740
733
  }));
741
734
  }, [opportunities]);
742
- useEffect3(() => {
743
- if (!isProductSelected && value.length > 0) {
744
- onValueChange([]);
745
- }
746
- }, [isProductSelected, value, onValueChange]);
747
735
  return /* @__PURE__ */ jsx12(
748
736
  MultiSelect4,
749
737
  {
@@ -751,8 +739,8 @@ function OpportunitiesSelector({
751
739
  options: opportunityOptions,
752
740
  value,
753
741
  onValueChange,
754
- disabled: disabled || isLoading || !isProductSelected,
755
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
742
+ disabled: disabled || isLoading,
743
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
756
744
  closeOnSelect,
757
745
  maxCount,
758
746
  className
@@ -809,7 +797,7 @@ function ChainSelector({
809
797
  }
810
798
 
811
799
  // src/selectors/TokenSelector.tsx
812
- import { useEffect as useEffect4, useMemo as useMemo9 } from "react";
800
+ import { useEffect as useEffect3, useMemo as useMemo9 } from "react";
813
801
  import { Combobox as Combobox2 } from "@turtleclub/ui";
814
802
  import { useSupportedTokens as useSupportedTokens2 } from "@turtleclub/hooks";
815
803
  import { jsx as jsx14 } from "react/jsx-runtime";
@@ -846,7 +834,7 @@ function TokenSelector({
846
834
  ) : void 0
847
835
  }));
848
836
  }, [tokens]);
849
- useEffect4(() => {
837
+ useEffect3(() => {
850
838
  if (!isChainSelected && value) {
851
839
  onValueChange("");
852
840
  }
@@ -915,27 +903,20 @@ function ProductSelector({
915
903
  }
916
904
 
917
905
  // src/selectors/OpportunitySelector.tsx
918
- import { useMemo as useMemo11, useEffect as useEffect5 } from "react";
906
+ import { useMemo as useMemo11 } from "react";
919
907
  import { Combobox as Combobox4 } from "@turtleclub/ui";
920
908
  import { useOpportunities as useOpportunities2 } from "@turtleclub/hooks";
921
909
  import { jsx as jsx16 } from "react/jsx-runtime";
922
910
  function OpportunitySelector({
923
911
  value,
924
912
  onValueChange,
925
- productId,
926
913
  placeholder = "Select opportunity",
927
914
  disabled = false,
928
915
  className,
929
916
  closeOnSelect = true,
930
917
  searchable = true
931
918
  }) {
932
- const isProductSelected = !!productId && productId.trim() !== "";
933
- const { data: opportunitiesData, isLoading } = useOpportunities2({
934
- filters: {
935
- productId
936
- },
937
- enabled: isProductSelected
938
- });
919
+ const { data: opportunitiesData, isLoading } = useOpportunities2();
939
920
  const opportunities = useMemo11(
940
921
  () => opportunitiesData?.opportunities ?? [],
941
922
  [opportunitiesData?.opportunities]
@@ -959,11 +940,6 @@ function OpportunitySelector({
959
940
  ) : void 0
960
941
  }));
961
942
  }, [opportunities]);
962
- useEffect5(() => {
963
- if (!isProductSelected && value) {
964
- onValueChange("");
965
- }
966
- }, [isProductSelected, value, onValueChange]);
967
943
  return /* @__PURE__ */ jsx16(
968
944
  Combobox4,
969
945
  {
@@ -971,8 +947,8 @@ function OpportunitySelector({
971
947
  options: opportunityOptions,
972
948
  value,
973
949
  onValueChange,
974
- disabled: disabled || isLoading || !isProductSelected,
975
- placeholder: !isProductSelected ? "Select a product first" : isLoading ? "Loading opportunities..." : placeholder,
950
+ disabled: disabled || isLoading,
951
+ placeholder: isLoading ? "Loading opportunities..." : placeholder,
976
952
  closeOnSelect,
977
953
  className
978
954
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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":["\"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":["Label","useQueryState","jsx","jsxs","useQueryState","jsx","useQueryState","parseAsString","Fragment","jsx","jsx","jsxs","cn","jsx","jsxs","Badge","Button","cn","Fragment","jsx","jsxs","cn","jsx","jsxs","cn","useQueryState","parseAsInteger","useMemo","useQueryState","parseAsString","useMemo","useCallback","useMemo","jsx","useEffect","useMemo","MultiSelect","jsx","useMemo","MultiSelect","jsx","useMemo","useEffect","MultiSelect","jsx","useMemo","useSupportedChains","jsx","useEffect","useMemo","Combobox","useSupportedTokens","jsx","useMemo","Combobox","useProducts","jsx","useMemo","useEffect","Combobox","useOpportunities","jsx"]}
1
+ {"version":3,"sources":["../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":["\"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 } 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":["Label","useQueryState","jsx","jsxs","useQueryState","jsx","useQueryState","parseAsString","Fragment","jsx","jsx","jsxs","cn","jsx","jsxs","Badge","Button","cn","Fragment","jsx","jsxs","cn","jsx","jsxs","cn","useQueryState","parseAsInteger","useMemo","useQueryState","parseAsString","useMemo","useCallback","useMemo","jsx","useEffect","useMemo","MultiSelect","jsx","useMemo","MultiSelect","jsx","useMemo","MultiSelect","jsx","useMemo","useSupportedChains","jsx","useEffect","useMemo","Combobox","useSupportedTokens","jsx","useMemo","Combobox","useProducts","jsx","useMemo","Combobox","useOpportunities","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turtleclub/core",
3
- "version": "0.1.0-beta.15",
3
+ "version": "0.1.0-beta.16",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "870ea6275c89bf0ab96c325b89b9d8c0a9e82100"
45
+ "gitHead": "163e7723f570e1e9efa1c48806e14e6d4a5a7d8d"
46
46
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useMemo, useEffect } from "react";
3
+ import { useMemo } from "react";
4
4
  import { MultiSelect } from "@turtleclub/ui";
5
5
  import { useOpportunities } from "@turtleclub/hooks";
6
6
 
@@ -9,8 +9,6 @@ interface OpportunitySelectorProps {
9
9
  value: string[];
10
10
  /** Callback when selection changes */
11
11
  onValueChange: (values: string[]) => void;
12
- /** Selected product ID to filter opportunities */
13
- productId?: string;
14
12
  /** Placeholder text */
15
13
  placeholder?: string;
16
14
  /** Whether the selector is disabled */
@@ -28,7 +26,6 @@ interface OpportunitySelectorProps {
28
26
  export function OpportunitiesSelector({
29
27
  value,
30
28
  onValueChange,
31
- productId,
32
29
  placeholder = "Select opportunities",
33
30
  disabled = false,
34
31
  className,
@@ -36,14 +33,7 @@ export function OpportunitiesSelector({
36
33
  closeOnSelect = true,
37
34
  searchable = true,
38
35
  }: OpportunitySelectorProps) {
39
- const isProductSelected = !!productId && productId.trim() !== "";
40
-
41
- const { data: opportunitiesData, isLoading } = useOpportunities({
42
- filters: {
43
- productId,
44
- },
45
- enabled: isProductSelected,
46
- });
36
+ const { data: opportunitiesData, isLoading } = useOpportunities();
47
37
 
48
38
  const opportunities = useMemo(
49
39
  () => opportunitiesData?.opportunities ?? [],
@@ -73,27 +63,14 @@ export function OpportunitiesSelector({
73
63
  }));
74
64
  }, [opportunities]);
75
65
 
76
- // Clear selection when product changes
77
- useEffect(() => {
78
- if (!isProductSelected && value.length > 0) {
79
- onValueChange([]);
80
- }
81
- }, [isProductSelected, value, onValueChange]);
82
-
83
66
  return (
84
67
  <MultiSelect
85
68
  searchable={searchable}
86
69
  options={opportunityOptions}
87
70
  value={value}
88
71
  onValueChange={onValueChange}
89
- disabled={disabled || isLoading || !isProductSelected}
90
- placeholder={
91
- !isProductSelected
92
- ? "Select a product first"
93
- : isLoading
94
- ? "Loading opportunities..."
95
- : placeholder
96
- }
72
+ disabled={disabled || isLoading}
73
+ placeholder={isLoading ? "Loading opportunities..." : placeholder}
97
74
  closeOnSelect={closeOnSelect}
98
75
  maxCount={maxCount}
99
76
  className={className}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useMemo, useEffect } from "react";
3
+ import { useMemo } from "react";
4
4
  import { Combobox } from "@turtleclub/ui";
5
5
  import { useOpportunities } from "@turtleclub/hooks";
6
6
 
@@ -9,8 +9,6 @@ interface OpportunitySelectorProps {
9
9
  value: string;
10
10
  /** Callback when selection changes */
11
11
  onValueChange: (value: string) => void;
12
- /** Selected product ID to filter opportunities */
13
- productId?: string;
14
12
  /** Placeholder text */
15
13
  placeholder?: string;
16
14
  /** Whether the selector is disabled */
@@ -26,21 +24,13 @@ interface OpportunitySelectorProps {
26
24
  export function OpportunitySelector({
27
25
  value,
28
26
  onValueChange,
29
- productId,
30
27
  placeholder = "Select opportunity",
31
28
  disabled = false,
32
29
  className,
33
30
  closeOnSelect = true,
34
31
  searchable = true,
35
32
  }: OpportunitySelectorProps) {
36
- const isProductSelected = !!productId && productId.trim() !== "";
37
-
38
- const { data: opportunitiesData, isLoading } = useOpportunities({
39
- filters: {
40
- productId,
41
- },
42
- enabled: isProductSelected,
43
- });
33
+ const { data: opportunitiesData, isLoading } = useOpportunities();
44
34
 
45
35
  const opportunities = useMemo(
46
36
  () => opportunitiesData?.opportunities ?? [],
@@ -70,27 +60,14 @@ export function OpportunitySelector({
70
60
  }));
71
61
  }, [opportunities]);
72
62
 
73
- // Clear selection when product changes
74
- useEffect(() => {
75
- if (!isProductSelected && value) {
76
- onValueChange("");
77
- }
78
- }, [isProductSelected, value, onValueChange]);
79
-
80
63
  return (
81
64
  <Combobox
82
65
  searchable={searchable}
83
66
  options={opportunityOptions}
84
67
  value={value}
85
68
  onValueChange={onValueChange}
86
- disabled={disabled || isLoading || !isProductSelected}
87
- placeholder={
88
- !isProductSelected
89
- ? "Select a product first"
90
- : isLoading
91
- ? "Loading opportunities..."
92
- : placeholder
93
- }
69
+ disabled={disabled || isLoading}
70
+ placeholder={isLoading ? "Loading opportunities..." : placeholder}
94
71
  closeOnSelect={closeOnSelect}
95
72
  className={className}
96
73
  />