@turtleclub/ui 0.7.0-beta.1 → 0.7.0-beta.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"sort-dropdown.d.ts","sourceRoot":"","sources":["../../../../../src/components/features/data-table/sort-dropdown.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAU3D,UAAU,iBAAiB,CAAC,KAAK;IAC/B,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,EAClC,OAAO,EACP,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,EAAE,iBAAiB,CAAC,KAAK,CAAC,2CA8F1B"}
1
+ {"version":3,"file":"sort-dropdown.d.ts","sourceRoot":"","sources":["../../../../../src/components/features/data-table/sort-dropdown.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAU3D,UAAU,iBAAiB,CAAC,KAAK;IAC/B,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,EAClC,OAAO,EACP,WAAW,EACX,YAAY,EACZ,WAAW,GACZ,EAAE,iBAAiB,CAAC,KAAK,CAAC,2CA2F1B"}
@@ -16,6 +16,8 @@ interface SwapInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onC
16
16
  useCustomTokenSelector?: boolean;
17
17
  selectedTokenData?: Token | null;
18
18
  onCustomTokenSelectorClick?: () => void;
19
+ showTokenSelectorBalance?: boolean;
20
+ showInputBalance?: boolean;
19
21
  }
20
22
  declare const SwapInput: React.ForwardRefExoticComponent<SwapInputProps & React.RefAttributes<HTMLDivElement>>;
21
23
  export { SwapInput };
@@ -1 +1 @@
1
- {"version":3,"file":"swap-input.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/swap-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG7D,UAAU,cACR,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACjC,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;CACzC;AAED,QAAA,MAAM,SAAS,uFA0Id,CAAC;AAIF,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"swap-input.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/swap-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG7D,UAAU,cAAe,SAAQ,IAAI,CACnC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EACpC,UAAU,CACX;IACC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACjC,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,QAAA,MAAM,SAAS,uFAiJd,CAAC;AAIF,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"token-selector.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/token-selector.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,UAAU,KAAK;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,QAAA,MAAM,aAAa,GAAI,iGAUpB,kBAAkB,4CA8HpB,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,KAAK,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"token-selector.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/token-selector.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,UAAU,KAAK;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,QAAA,MAAM,aAAa,GAAI,iGAUpB,kBAAkB,4CAoIpB,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,KAAK,KAAK,EAAE,CAAC"}
@@ -13,8 +13,8 @@ declare function Avatar({ className, size, ...props }: React.ComponentProps<type
13
13
  declare function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>): import("react/jsx-runtime").JSX.Element;
14
14
  declare function AvatarFallback({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Fallback>): import("react/jsx-runtime").JSX.Element;
15
15
  declare function TurtleAvatar({ src, alt, fallback, ...rest }: AvatarPrimitive.AvatarProps & {
16
- src: string;
17
- alt: string;
16
+ src?: string;
17
+ alt?: string;
18
18
  fallback?: React.ReactNode;
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
20
  export { TurtleAvatar, Avatar, AvatarImage, AvatarFallback };
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAI1D,QAAA,MAAM,UAAU;;;;;;CAMN,CAAC;AAEX,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,IAAW,EACX,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG;IACrD,IAAI,CAAC,EAAE,MAAM,OAAO,UAAU,CAAC;CAChC,2CAWA;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAQpD;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,QAAQ,CAAC,2CAWvD;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,EACH,GAAG,EACH,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,eAAe,CAAC,WAAW,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,2CAOA;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/avatar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAI1D,QAAA,MAAM,UAAU;;;;;;CAMN,CAAC;AAEX,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,IAAW,EACX,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG;IACrD,IAAI,CAAC,EAAE,MAAM,OAAO,UAAU,CAAC;CAChC,2CAQA;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAQ/F;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,QAAQ,CAAC,2CAQvD;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,EACH,GAAG,EACH,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,eAAe,CAAC,WAAW,GAAG;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,2CASA;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
@@ -77,8 +77,24 @@ interface ComboboxProps<T = string> extends Omit<React.ButtonHTMLAttributes<HTML
77
77
  * Receives an array of the new selected values.
78
78
  */
79
79
  onValueChange: (value: T) => void;
80
+ /**
81
+ * Custom renderer for the selected value displayed in the input.
82
+ * @param option The currently selected option object.
83
+ */
84
+ renderValue?: (option: ComboboxOption<T>) => React.ReactNode;
80
85
  /** The default selected values when the component mounts. */
81
86
  defaultValue?: T;
87
+ /**
88
+ * Callback function triggered when the search input value changes.
89
+ * Useful for server-side filtering or handling large datasets externally.
90
+ */
91
+ onInputValueChange?: (value: string) => void;
92
+ /**
93
+ * If true, disables the built-in filtering logic.
94
+ * Use this when you filter options externally (e.g. server-side search).
95
+ * Optional, defaults to false.
96
+ */
97
+ disableLocalFiltering?: boolean;
82
98
  /**
83
99
  * Placeholder text to be displayed when no values are selected.
84
100
  * Optional, defaults to "Select options".
@@ -111,6 +127,11 @@ interface ComboboxProps<T = string> extends Omit<React.ButtonHTMLAttributes<HTML
111
127
  * Optional, defaults to true.
112
128
  */
113
129
  searchable?: boolean;
130
+ /**
131
+ * If true, searching will also check the 'value' field in addition to 'label'.
132
+ * Optional, defaults to false.
133
+ */
134
+ searchByValue?: boolean;
114
135
  /**
115
136
  * Custom empty state message when no options match search.
116
137
  * Optional, defaults to "No results found."
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/combobox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/combobox.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAK1D,iBAAS,MAAM,CAAC,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,2CAEnD;AAED,iBAAS,aAAa,CAAC,EACrB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,2CAEtD;AAED,iBAAS,YAAY,CAAC,EACpB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,MAAM,CAAC,2CAErD;AAED,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAEpD;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,2CAWtD;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,eAAsB,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,GAAG;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,2CAyBA;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQzE;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAWzE;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAQpD;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,WAAW,CAAC,2CAQ1D;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAK1D,iBAAS,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,2CAE9E;AAED,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,2CAExF;AAED,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,MAAM,CAAC,2CAEtF;AAED,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAEpF;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,2CAWtD;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,eAAsB,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,GAAG;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,2CAyBA;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQzE;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQzE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,2CAQ/F;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,WAAW,CAAC,2CAQ1D;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turtleclub/ui",
3
- "version": "0.7.0-beta.1",
3
+ "version": "0.7.0-beta.10",
4
4
  "description": "shadcn/ui and custom Turtle UI components library",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -84,5 +84,5 @@
84
84
  "vite": "^7.1.6",
85
85
  "vite-plugin-dts": "^4.5.4"
86
86
  },
87
- "gitHead": "d896f0404e2bcb958a52def686e57893b4c68f6b"
87
+ "gitHead": "1c079d74e9530d05b212ee03ee221e668ae3ce96"
88
88
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import React, { Fragment, useMemo } from "react";
3
+ import React, { Fragment, useMemo, useState } from "react";
4
4
 
5
5
  import {
6
6
  ColumnDef,
@@ -29,6 +29,8 @@ import {
29
29
  TableHead,
30
30
  TableHeader,
31
31
  TableRow,
32
+ Input,
33
+ Combobox,
32
34
  } from "../../ui";
33
35
  import SortableHeader from "./sortable-header";
34
36
  import { SearchBar } from "../search-bar";
@@ -77,6 +79,7 @@ type DataTableProps<TData, TValue> = {
77
79
  manualFiltering?: boolean;
78
80
  manualSorting?: boolean;
79
81
  manualPagination?: boolean;
82
+
80
83
  pageCount?: number; // Total page count from server (required when manualPagination is true)
81
84
  rowCount?: number; // Total row count from server (optional, for display purposes)
82
85
 
@@ -132,22 +135,17 @@ export function DataTable<TData, TValue>({
132
135
  pagination: controlledPagination,
133
136
  onPaginationChange: onControlledPaginationChange,
134
137
  }: DataTableProps<TData, TValue>) {
135
- const [columnVisibility, setColumnVisibility] = React.useState(
136
- initialColumnVisibility ?? {},
137
- );
138
+ const [columnVisibility, setColumnVisibility] = React.useState(initialColumnVisibility ?? {});
138
139
  const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});
139
140
  const [expanded, setExpanded] = React.useState<ExpandedState>({});
140
141
 
141
142
  // Internal state (used when not controlled from outside)
142
- const [internalGlobalFilter, setInternalGlobalFilter] =
143
- React.useState<string>("");
144
- const [internalSorting, setInternalSorting] =
145
- React.useState<SortingState>(initialSorting);
146
- const [internalPagination, setInternalPagination] =
147
- React.useState<PaginationState>({
148
- pageIndex: 0,
149
- pageSize: 10,
150
- });
143
+ const [internalGlobalFilter, setInternalGlobalFilter] = React.useState<string>("");
144
+ const [internalSorting, setInternalSorting] = React.useState<SortingState>(initialSorting);
145
+ const [internalPagination, setInternalPagination] = React.useState<PaginationState>({
146
+ pageIndex: 0,
147
+ pageSize: 10,
148
+ });
151
149
 
152
150
  // Use controlled state if provided, otherwise use internal state
153
151
  const globalFilter = controlledGlobalFilter ?? internalGlobalFilter;
@@ -162,13 +160,9 @@ export function DataTable<TData, TValue>({
162
160
  }
163
161
  };
164
162
 
165
- const setSorting = (
166
- updaterOrValue: SortingState | ((old: SortingState) => SortingState),
167
- ) => {
163
+ const setSorting = (updaterOrValue: SortingState | ((old: SortingState) => SortingState)) => {
168
164
  const newSorting =
169
- typeof updaterOrValue === "function"
170
- ? updaterOrValue(sorting)
171
- : updaterOrValue;
165
+ typeof updaterOrValue === "function" ? updaterOrValue(sorting) : updaterOrValue;
172
166
 
173
167
  if (onControlledSortingChange) {
174
168
  onControlledSortingChange(newSorting);
@@ -178,14 +172,10 @@ export function DataTable<TData, TValue>({
178
172
  };
179
173
 
180
174
  const setPagination = (
181
- updaterOrValue:
182
- | PaginationState
183
- | ((old: PaginationState) => PaginationState),
175
+ updaterOrValue: PaginationState | ((old: PaginationState) => PaginationState)
184
176
  ) => {
185
177
  const newPagination =
186
- typeof updaterOrValue === "function"
187
- ? updaterOrValue(pagination)
188
- : updaterOrValue;
178
+ typeof updaterOrValue === "function" ? updaterOrValue(pagination) : updaterOrValue;
189
179
 
190
180
  if (onControlledPaginationChange) {
191
181
  onControlledPaginationChange(newPagination);
@@ -219,7 +209,7 @@ export function DataTable<TData, TValue>({
219
209
  getRowCanExpand: enableExpand ? () => true : undefined,
220
210
 
221
211
  // Server-side control
222
- manualFiltering,
212
+ manualFiltering: manualFiltering,
223
213
  manualSorting,
224
214
  manualPagination,
225
215
  pageCount: manualPagination ? pageCount : undefined,
@@ -231,9 +221,7 @@ export function DataTable<TData, TValue>({
231
221
  getFilteredRowModel: !manualFiltering ? getFilteredRowModel() : undefined,
232
222
  getSortedRowModel: !manualSorting ? getSortedRowModel() : undefined,
233
223
  getPaginationRowModel:
234
- enablePagination && !manualPagination
235
- ? getPaginationRowModel()
236
- : undefined,
224
+ enablePagination && !manualPagination ? getPaginationRowModel() : undefined,
237
225
  getExpandedRowModel: getExpandedRowModel(),
238
226
 
239
227
  // debugTable: true,
@@ -247,7 +235,7 @@ export function DataTable<TData, TValue>({
247
235
  .getHeaderGroups()
248
236
  .map((headerGroup) => headerGroup.headers)
249
237
  .flat(),
250
- [table],
238
+ [table]
251
239
  );
252
240
 
253
241
  return (
@@ -276,10 +264,7 @@ export function DataTable<TData, TValue>({
276
264
  )}
277
265
  </div>
278
266
  ) : undefined}
279
- <ScrollArea
280
- style={{ height: getScrollAreaHeight(size) }}
281
- className={className}
282
- >
267
+ <ScrollArea style={{ height: getScrollAreaHeight(size) }} className={className}>
283
268
  {table.getRowModel().rows?.length || isLoading ? (
284
269
  grid?.displayAsGrid ? (
285
270
  isLoading ? (
@@ -287,15 +272,15 @@ export function DataTable<TData, TValue>({
287
272
  className={cn(
288
273
  "grid gap-1 pr-1.5",
289
274
  "grid-cols-1 md:grid-cols-2 xl:grid-cols-3",
290
- grid.className,
275
+ grid.className
291
276
  )}
292
277
  />
293
278
  ) : (
294
279
  <div
295
280
  className={cn(
296
281
  "grid gap-1 pr-1.5",
297
- // "grid-cols-1 md:grid-cols-2 xl:grid-cols-3",
298
- grid.className,
282
+ "grid-cols-1 md:grid-cols-2 xl:grid-cols-3",
283
+ grid.className
299
284
  )}
300
285
  >
301
286
  {table.getRowModel().rows.map((row) => (
@@ -303,9 +288,7 @@ export function DataTable<TData, TValue>({
303
288
  <Card
304
289
  className={cn(
305
290
  "max-w-none",
306
- onRowClick
307
- ? "hover:bg-neutral-alpha-5 cursor-pointer"
308
- : "",
291
+ onRowClick ? "hover:bg-neutral-alpha-5 cursor-pointer" : ""
309
292
  )}
310
293
  data-state={row.getIsSelected() && "selected"}
311
294
  variant="border"
@@ -315,15 +298,10 @@ export function DataTable<TData, TValue>({
315
298
  <CardTitle className="line-clamp-1 grow text-base">
316
299
  {row
317
300
  .getVisibleCells()
318
- .filter(
319
- (cell) => cell.column.id === grid.headerSlot,
320
- )
301
+ .filter((cell) => cell.column.id === grid.headerSlot)
321
302
  ?.map((cell) => (
322
303
  <Fragment key={cell.id}>
323
- {flexRender(
324
- cell.column.columnDef.cell,
325
- cell.getContext(),
326
- )}
304
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
327
305
  </Fragment>
328
306
  ))}
329
307
  </CardTitle>
@@ -333,10 +311,7 @@ export function DataTable<TData, TValue>({
333
311
  .filter((cell) => cell.column.id === grid?.rightSlot)
334
312
  ?.map((cell) => (
335
313
  <div key={cell.id} className="text-lg">
336
- {flexRender(
337
- cell.column.columnDef.cell,
338
- cell.getContext(),
339
- )}
314
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
340
315
  </div>
341
316
  ))}
342
317
  </CardHeader>
@@ -348,7 +323,7 @@ export function DataTable<TData, TValue>({
348
323
  cell.column.id !== grid.headerSlot &&
349
324
  cell.column.id !== grid.rightSlot &&
350
325
  // @ts-expect-error I know that column id by defintion is keyof TData
351
- !grid.excludeColumns?.includes(cell.column.id),
326
+ !grid.excludeColumns?.includes(cell.column.id)
352
327
  )
353
328
  .map((cell) => {
354
329
  return (
@@ -357,15 +332,10 @@ export function DataTable<TData, TValue>({
357
332
  title={flexRender(
358
333
  cell.column.columnDef.header,
359
334
  headers
360
- .find(
361
- (header) => header.id === cell.column.id,
362
- )
363
- ?.getContext(),
364
- )}
365
- value={flexRender(
366
- cell.column.columnDef.cell,
367
- cell.getContext(),
335
+ .find((header) => header.id === cell.column.id)
336
+ ?.getContext()
368
337
  )}
338
+ value={flexRender(cell.column.columnDef.cell, cell.getContext())}
369
339
  className="justify-between gap-3 *:text-xs"
370
340
  />
371
341
  );
@@ -383,7 +353,15 @@ export function DataTable<TData, TValue>({
383
353
  <TableRow>
384
354
  {headers.map((header) => {
385
355
  return (
386
- <TableHead key={header.id}>
356
+ <TableHead
357
+ key={header.id}
358
+ style={{
359
+ width: header.column.columnDef.size,
360
+ minWidth: header.column.columnDef.minSize,
361
+ maxWidth: header.column.columnDef.maxSize,
362
+ }}
363
+ className={(header.column.columnDef.meta as any)?.className}
364
+ >
387
365
  <SortableHeader header={header} />
388
366
  </TableHead>
389
367
  );
@@ -399,18 +377,11 @@ export function DataTable<TData, TValue>({
399
377
  <TableRow
400
378
  onClick={() => onRowClick?.(row.original)}
401
379
  data-state={row.getIsSelected() && "selected"}
402
- className={
403
- onRowClick
404
- ? "hover:bg-neutral-alpha-5 cursor-pointer"
405
- : ""
406
- }
380
+ className={onRowClick ? "hover:bg-neutral-alpha-5 cursor-pointer" : ""}
407
381
  >
408
382
  {row.getVisibleCells().map((cell) => (
409
383
  <ShadTableCell key={cell.id}>
410
- {flexRender(
411
- cell.column.columnDef.cell,
412
- cell.getContext(),
413
- )}
384
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
414
385
  </ShadTableCell>
415
386
  ))}
416
387
  </TableRow>
@@ -436,10 +407,23 @@ export function DataTable<TData, TValue>({
436
407
  ))
437
408
  )}
438
409
  </ScrollArea>
439
- {enablePagination &&
440
- (manualPagination
441
- ? (pageCount ?? 0) > 1
442
- : table.getPageCount() > 1) && (
410
+ {enablePagination && (manualPagination ? (pageCount ?? 0) > 1 : table.getPageCount() > 1) && (
411
+ <div className="flex items-center justify-between gap-4 px-2">
412
+ <Combobox
413
+ options={[10, 20, 30, 40, 50, 100].map((size) => ({
414
+ label: `Show ${size.toString()} rows per page`,
415
+ value: size,
416
+ }))}
417
+ value={table.getState().pagination.pageSize}
418
+ onValueChange={(value) => {
419
+ table.setPageSize(value);
420
+ }}
421
+ className="w-32!"
422
+ searchable={false}
423
+ closeOnSelect
424
+ placeholder="Rows shown per page"
425
+ />
426
+
443
427
  <Pagination>
444
428
  <PaginationContent>
445
429
  <PaginationItem>
@@ -452,63 +436,85 @@ export function DataTable<TData, TValue>({
452
436
  }
453
437
  />
454
438
  </PaginationItem>
455
- {Array.from({ length: table.getPageCount() }, (_, i) => i).map(
456
- (pageIndex) => {
457
- const currentPage = table.getState().pagination.pageIndex;
458
- const totalPages = table.getPageCount();
459
-
460
- // Show first page, last page, current page, and pages around current
461
- const showPage =
462
- pageIndex === 0 ||
463
- pageIndex === totalPages - 1 ||
464
- (pageIndex >= currentPage - 1 &&
465
- pageIndex <= currentPage + 1);
466
-
467
- // Show ellipsis before current range (but not right after first page)
468
- const showEllipsisBefore =
469
- pageIndex === currentPage - 2 && currentPage > 2;
439
+ {Array.from({ length: table.getPageCount() }, (_, i) => i).map((pageIndex) => {
440
+ const currentPage = table.getState().pagination.pageIndex;
441
+ const totalPages = table.getPageCount();
470
442
 
471
- // Show ellipsis after current range (but not right before last page)
472
- const showEllipsisAfter =
473
- pageIndex === currentPage + 2 &&
474
- currentPage < totalPages - 3;
443
+ // Show first page, last page, current page, and pages around current
444
+ const showPage =
445
+ pageIndex === 0 ||
446
+ pageIndex === totalPages - 1 ||
447
+ (pageIndex >= currentPage - 1 && pageIndex <= currentPage + 1);
475
448
 
476
- if (showEllipsisBefore || showEllipsisAfter) {
477
- return (
478
- <PaginationItem key={pageIndex}>
479
- <PaginationEllipsis />
480
- </PaginationItem>
481
- );
482
- }
449
+ // Show ellipsis before current range (but not right after first page)
450
+ const showEllipsisBefore = pageIndex === currentPage - 2 && currentPage > 2;
483
451
 
484
- if (!showPage) return null;
452
+ // Show ellipsis after current range (but not right before last page)
453
+ const showEllipsisAfter =
454
+ pageIndex === currentPage + 2 && currentPage < totalPages - 3;
485
455
 
456
+ if (showEllipsisBefore || showEllipsisAfter) {
486
457
  return (
487
458
  <PaginationItem key={pageIndex}>
488
- <PaginationLink
489
- onClick={() => table.setPageIndex(pageIndex)}
490
- isActive={currentPage === pageIndex}
491
- className="cursor-pointer"
492
- >
493
- {pageIndex + 1}
494
- </PaginationLink>
459
+ <PaginationEllipsis />
495
460
  </PaginationItem>
496
461
  );
497
- },
498
- )}
462
+ }
463
+
464
+ if (!showPage) return null;
465
+
466
+ return (
467
+ <PaginationItem key={pageIndex}>
468
+ <PaginationLink
469
+ onClick={() => table.setPageIndex(pageIndex)}
470
+ isActive={currentPage === pageIndex}
471
+ className="cursor-pointer"
472
+ >
473
+ {pageIndex + 1}
474
+ </PaginationLink>
475
+ </PaginationItem>
476
+ );
477
+ })}
499
478
  <PaginationItem>
500
479
  <PaginationNext
501
480
  onClick={() => table.nextPage()}
502
481
  className={
503
- !table.getCanNextPage()
504
- ? "pointer-events-none opacity-50"
505
- : "cursor-pointer"
482
+ !table.getCanNextPage() ? "pointer-events-none opacity-50" : "cursor-pointer"
506
483
  }
507
484
  />
508
485
  </PaginationItem>
509
486
  </PaginationContent>
510
487
  </Pagination>
511
- )}
488
+
489
+ <div className="flex items-center gap-2">
490
+ <span className="text-muted-foreground truncate text-xs">Go to page:</span>
491
+ <Input
492
+ min={1}
493
+ max={table.getPageCount()}
494
+ pattern="[0-9]*"
495
+ defaultValue={table.getState().pagination.pageIndex + 1}
496
+ onBlurCapture={(e) => {
497
+ const page = e.target.value ? Number(e.target.value) - 1 : 0;
498
+ if (page >= 0 && page < table.getPageCount()) {
499
+ table.setPageIndex(page);
500
+ }
501
+ }}
502
+ onKeyDown={(e) => {
503
+ if (e.key === "Enter") {
504
+ const page = e.currentTarget.value ? Number(e.currentTarget.value) - 1 : 0;
505
+ if (page >= 0 && page < table.getPageCount()) {
506
+ table.setPageIndex(page);
507
+ }
508
+ }
509
+ }}
510
+ className="w-12"
511
+ />
512
+ <span className="text-muted-foreground truncate text-xs">
513
+ of {table.getPageCount()}
514
+ </span>
515
+ </div>
516
+ </div>
517
+ )}
512
518
  </div>
513
519
  );
514
520
  }
@@ -27,7 +27,7 @@ export function SortDropdown<TData>({
27
27
  }: SortDropdownProps<TData>) {
28
28
  // Filter only sortable columns
29
29
  const sortableHeaders = headers.filter(
30
- (header) => header.column.getCanSort() && !header.isPlaceholder,
30
+ (header) => header.column.getCanSort() && !header.isPlaceholder
31
31
  );
32
32
 
33
33
  const getCurrentSortLabel = () => {
@@ -79,23 +79,20 @@ export function SortDropdown<TData>({
79
79
  <DropdownMenuLabel>Sort by</DropdownMenuLabel>
80
80
  <DropdownMenuSeparator />
81
81
  {sortableHeaders.map((header) => {
82
- const isCurrentAsc =
83
- currentSort?.id === header.column.id && !currentSort.desc;
84
- const isCurrentDesc =
85
- currentSort?.id === header.column.id && currentSort.desc;
82
+ const isCurrentAsc = currentSort?.id === header.column.id && !currentSort.desc;
83
+ const isCurrentDesc = currentSort?.id === header.column.id && currentSort.desc;
86
84
  const isActive = currentSort?.id === header.column.id;
87
85
 
88
86
  return (
89
87
  <DropdownMenuItem
90
88
  key={header.column.id}
91
89
  onClick={() => handleColumnClick(header.column.id)}
92
- className={isActive ? "bg-secondary" : ""}
90
+ className={
91
+ isActive ? "bg-secondary flex items-center gap-2" : "flex items-center gap-2"
92
+ }
93
93
  >
94
- <span className="flex-1">
95
- {flexRender(
96
- header.column.columnDef.header,
97
- header.getContext(),
98
- )}
94
+ <span className="w-fit truncate">
95
+ {flexRender(header.column.columnDef.header, header.getContext())}
99
96
  </span>
100
97
  {isActive &&
101
98
  (isCurrentDesc ? (