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