1use std::cmp::Ordering;
2use std::sync::Arc;
3
4use serde_json::Value;
5
6use super::{Aggregation, AggregationFnSpec, BuiltInAggregationFn};
7
8pub type ColumnId = Arc<str>;
9
10pub type SortCmpFn<TData> = Arc<dyn Fn(&TData, &TData) -> Ordering>;
11pub type SortIsUndefinedFn<TData> = Arc<dyn Fn(&TData) -> bool>;
12pub type SortValueFn<TData> = Arc<dyn Fn(&TData) -> TanStackValue>;
13pub type UniqueValuesFn<TData> = Arc<dyn Fn(&TData, usize) -> Vec<TanStackValue>>;
14pub type FilterFn<TData> = Arc<dyn Fn(&TData, &Value) -> bool>;
15pub type FilterFnWithMeta<TData> = Arc<dyn Fn(&TData, &Value, &mut dyn FnMut(Value)) -> bool>;
16pub type FacetKeyFn<TData> = Arc<dyn Fn(&TData) -> u64>;
17pub type FacetStrFn<TData> = Arc<dyn for<'r> Fn(&'r TData) -> &'r str>;
18pub type ValueU64Fn<TData> = Arc<dyn Fn(&TData) -> u64>;
19
20#[derive(Debug, Clone, PartialEq)]
26pub enum TanStackValue {
27 Undefined,
28 Null,
29 Bool(bool),
30 Number(f64),
31 String(Arc<str>),
32 Array(Vec<TanStackValue>),
33 DateTime(f64),
35}
36
37impl From<bool> for TanStackValue {
38 fn from(value: bool) -> Self {
39 TanStackValue::Bool(value)
40 }
41}
42
43impl From<f32> for TanStackValue {
44 fn from(value: f32) -> Self {
45 TanStackValue::Number(value as f64)
46 }
47}
48
49impl From<f64> for TanStackValue {
50 fn from(value: f64) -> Self {
51 TanStackValue::Number(value)
52 }
53}
54
55impl From<i32> for TanStackValue {
56 fn from(value: i32) -> Self {
57 TanStackValue::Number(value as f64)
58 }
59}
60
61impl From<i64> for TanStackValue {
62 fn from(value: i64) -> Self {
63 TanStackValue::Number(value as f64)
64 }
65}
66
67impl From<u32> for TanStackValue {
68 fn from(value: u32) -> Self {
69 TanStackValue::Number(value as f64)
70 }
71}
72
73impl From<u64> for TanStackValue {
74 fn from(value: u64) -> Self {
75 TanStackValue::Number(value as f64)
76 }
77}
78
79impl From<usize> for TanStackValue {
80 fn from(value: usize) -> Self {
81 TanStackValue::Number(value as f64)
82 }
83}
84
85impl From<String> for TanStackValue {
86 fn from(value: String) -> Self {
87 TanStackValue::String(Arc::<str>::from(value))
88 }
89}
90
91impl From<Arc<str>> for TanStackValue {
92 fn from(value: Arc<str>) -> Self {
93 TanStackValue::String(value)
94 }
95}
96
97impl From<&str> for TanStackValue {
98 fn from(value: &str) -> Self {
99 TanStackValue::String(Arc::<str>::from(value))
100 }
101}
102
103impl From<Vec<TanStackValue>> for TanStackValue {
104 fn from(value: Vec<TanStackValue>) -> Self {
105 TanStackValue::Array(value)
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
110pub enum BuiltInSortingFn {
111 Alphanumeric,
112 AlphanumericCaseSensitive,
113 Text,
114 TextCaseSensitive,
115 Datetime,
116 Basic,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Hash)]
120pub enum SortingFnSpec {
121 Auto,
123 BuiltIn(BuiltInSortingFn),
125 Named(Arc<str>),
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
130pub enum BuiltInFilterFn {
131 IncludesString,
132 IncludesStringSensitive,
133 EqualsString,
134 ArrIncludes,
135 ArrIncludesAll,
136 ArrIncludesSome,
137 Equals,
138 WeakEquals,
139 InNumberRange,
140}
141
142#[derive(Debug, Clone, PartialEq, Eq, Hash)]
143pub enum FilteringFnSpec {
144 Auto,
146 BuiltIn(BuiltInFilterFn),
148 Named(Arc<str>),
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
153pub enum SortUndefined {
154 Disabled,
156 First,
157 Last,
158 Dir(i8),
160}
161
162pub struct ColumnDef<TData> {
163 pub id: ColumnId,
164 pub columns: Vec<ColumnDef<TData>>,
168 pub sort_cmp: Option<SortCmpFn<TData>>,
169 pub sorting_fn: Option<SortingFnSpec>,
170 pub sort_value: Option<SortValueFn<TData>>,
171 pub sort_undefined: Option<SortUndefined>,
172 pub sort_is_undefined: Option<SortIsUndefinedFn<TData>>,
173 pub filtering_fn: Option<FilteringFnSpec>,
174 pub filter_fn: Option<FilterFn<TData>>,
175 pub filter_fn_with_meta: Option<FilterFnWithMeta<TData>>,
176 pub facet_key_fn: Option<FacetKeyFn<TData>>,
177 pub facet_str_fn: Option<FacetStrFn<TData>>,
178 pub value_u64_fn: Option<ValueU64Fn<TData>>,
179 pub unique_values_fn: Option<UniqueValuesFn<TData>>,
180 pub invert_sorting: bool,
181 pub sort_desc_first: Option<bool>,
182 pub enable_sorting: bool,
183 pub enable_multi_sort: bool,
184 pub enable_column_filter: bool,
185 pub enable_global_filter: bool,
186 pub aggregation: Aggregation,
187 pub aggregation_fn: AggregationFnSpec,
188 pub enable_hiding: bool,
189 pub enable_ordering: bool,
190 pub enable_pinning: bool,
191 pub enable_resizing: bool,
192 pub enable_grouping: bool,
193 pub size: f32,
194 pub min_size: f32,
195 pub max_size: f32,
196}
197
198impl<TData> Clone for ColumnDef<TData> {
199 fn clone(&self) -> Self {
200 Self {
201 id: self.id.clone(),
202 columns: self.columns.clone(),
203 sort_cmp: self.sort_cmp.clone(),
204 sorting_fn: self.sorting_fn.clone(),
205 sort_value: self.sort_value.clone(),
206 sort_undefined: self.sort_undefined,
207 sort_is_undefined: self.sort_is_undefined.clone(),
208 filtering_fn: self.filtering_fn.clone(),
209 filter_fn: self.filter_fn.clone(),
210 filter_fn_with_meta: self.filter_fn_with_meta.clone(),
211 facet_key_fn: self.facet_key_fn.clone(),
212 facet_str_fn: self.facet_str_fn.clone(),
213 value_u64_fn: self.value_u64_fn.clone(),
214 unique_values_fn: self.unique_values_fn.clone(),
215 invert_sorting: self.invert_sorting,
216 sort_desc_first: self.sort_desc_first,
217 enable_sorting: self.enable_sorting,
218 enable_multi_sort: self.enable_multi_sort,
219 enable_column_filter: self.enable_column_filter,
220 enable_global_filter: self.enable_global_filter,
221 aggregation: self.aggregation,
222 aggregation_fn: self.aggregation_fn.clone(),
223 enable_hiding: self.enable_hiding,
224 enable_ordering: self.enable_ordering,
225 enable_pinning: self.enable_pinning,
226 enable_resizing: self.enable_resizing,
227 enable_grouping: self.enable_grouping,
228 size: self.size,
229 min_size: self.min_size,
230 max_size: self.max_size,
231 }
232 }
233}
234
235impl<TData> std::fmt::Debug for ColumnDef<TData> {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 f.debug_struct("ColumnDef")
238 .field("id", &self.id)
239 .finish_non_exhaustive()
240 }
241}
242
243impl<TData> ColumnDef<TData> {
244 pub fn new(id: impl Into<ColumnId>) -> Self {
245 Self {
246 id: id.into(),
247 columns: Vec::new(),
248 sort_cmp: None,
249 sorting_fn: None,
250 sort_value: None,
251 sort_undefined: None,
252 sort_is_undefined: None,
253 filtering_fn: None,
254 filter_fn: None,
255 filter_fn_with_meta: None,
256 facet_key_fn: None,
257 facet_str_fn: None,
258 value_u64_fn: None,
259 unique_values_fn: None,
260 invert_sorting: false,
261 sort_desc_first: None,
262 enable_sorting: true,
263 enable_multi_sort: true,
264 enable_column_filter: true,
265 enable_global_filter: true,
266 aggregation: Aggregation::None,
267 aggregation_fn: AggregationFnSpec::Auto,
268 enable_hiding: true,
269 enable_ordering: true,
270 enable_pinning: true,
271 enable_resizing: true,
272 enable_grouping: true,
273 size: 150.0,
274 min_size: 20.0,
275 max_size: f32::MAX,
276 }
277 }
278
279 pub fn sort_by(mut self, cmp: impl Fn(&TData, &TData) -> Ordering + 'static) -> Self {
280 self.sort_cmp = Some(Arc::new(cmp));
281 self
282 }
283
284 pub fn columns(mut self, columns: Vec<ColumnDef<TData>>) -> Self {
286 self.columns = columns;
287 self
288 }
289
290 pub fn sort_value_by(mut self, get_value: impl Fn(&TData) -> TanStackValue + 'static) -> Self {
292 self.sort_value = Some(Arc::new(get_value));
293 self
294 }
295
296 pub fn unique_values_by(
298 mut self,
299 get_unique_values: impl Fn(&TData, usize) -> Vec<TanStackValue> + 'static,
300 ) -> Self {
301 self.unique_values_fn = Some(Arc::new(get_unique_values));
302 self
303 }
304
305 pub fn aggregation_fn_auto(mut self) -> Self {
307 self.aggregation_fn = AggregationFnSpec::Auto;
308 self
309 }
310
311 pub fn aggregation_fn_builtin(mut self, agg: BuiltInAggregationFn) -> Self {
313 self.aggregation_fn = AggregationFnSpec::BuiltIn(agg);
314 self
315 }
316
317 pub fn aggregation_fn_named(mut self, key: impl Into<Arc<str>>) -> Self {
319 self.aggregation_fn = AggregationFnSpec::Named(key.into());
320 self
321 }
322
323 pub fn aggregation_fn_none(mut self) -> Self {
325 self.aggregation_fn = AggregationFnSpec::None;
326 self
327 }
328
329 pub fn sorting_fn_auto(mut self) -> Self {
331 self.sorting_fn = Some(SortingFnSpec::Auto);
332 self
333 }
334
335 pub fn sorting_fn_builtin(mut self, sorting_fn: BuiltInSortingFn) -> Self {
337 self.sorting_fn = Some(SortingFnSpec::BuiltIn(sorting_fn));
338 self
339 }
340
341 pub fn sorting_fn_named(mut self, key: impl Into<Arc<str>>) -> Self {
343 self.sorting_fn = Some(SortingFnSpec::Named(key.into()));
344 self
345 }
346
347 pub fn filtering_fn_auto(mut self) -> Self {
349 self.filtering_fn = Some(FilteringFnSpec::Auto);
350 self
351 }
352
353 pub fn filtering_fn_builtin(mut self, filter_fn: BuiltInFilterFn) -> Self {
355 self.filtering_fn = Some(FilteringFnSpec::BuiltIn(filter_fn));
356 self
357 }
358
359 pub fn filtering_fn_named(mut self, key: impl Into<Arc<str>>) -> Self {
361 self.filtering_fn = Some(FilteringFnSpec::Named(key.into()));
362 self
363 }
364
365 pub fn sort_undefined_by(
370 mut self,
371 sort_undefined: SortUndefined,
372 is_undefined: impl Fn(&TData) -> bool + 'static,
373 ) -> Self {
374 self.sort_undefined = Some(sort_undefined);
375 self.sort_is_undefined = Some(Arc::new(is_undefined));
376 self
377 }
378
379 pub fn sort_undefined_disabled(mut self) -> Self {
381 self.sort_undefined = Some(SortUndefined::Disabled);
382 self.sort_is_undefined = None;
383 self
384 }
385
386 pub fn invert_sorting(mut self, invert: bool) -> Self {
391 self.invert_sorting = invert;
392 self
393 }
394
395 pub fn sort_desc_first(mut self, enabled: bool) -> Self {
399 self.sort_desc_first = Some(enabled);
400 self
401 }
402
403 pub fn enable_sorting(mut self, enabled: bool) -> Self {
407 self.enable_sorting = enabled;
408 self
409 }
410
411 pub fn enable_multi_sort(mut self, enabled: bool) -> Self {
415 self.enable_multi_sort = enabled;
416 self
417 }
418
419 pub fn enable_column_filter(mut self, enabled: bool) -> Self {
420 self.enable_column_filter = enabled;
421 self
422 }
423
424 pub fn enable_global_filter(mut self, enabled: bool) -> Self {
425 self.enable_global_filter = enabled;
426 self
427 }
428
429 pub fn filter_by(mut self, f: impl Fn(&TData, &str) -> bool + 'static) -> Self {
430 let f = Arc::new(f);
431 self.filter_fn_with_meta = None;
432 self.filter_fn = Some(Arc::new(move |row, value| {
433 let Some(s) = value.as_str() else {
434 return false;
435 };
436 f(row, s)
437 }));
438 self
439 }
440
441 pub fn filter_by_with_meta(
443 mut self,
444 f: impl Fn(&TData, &Value, &mut dyn FnMut(Value)) -> bool + 'static,
445 ) -> Self {
446 self.filter_fn = None;
447 self.filter_fn_with_meta = Some(Arc::new(f));
448 self
449 }
450
451 pub fn facet_key_by(mut self, f: impl Fn(&TData) -> u64 + 'static) -> Self {
453 self.facet_key_fn = Some(Arc::new(f));
454 self
455 }
456
457 pub fn facet_str_by(mut self, f: impl for<'r> Fn(&'r TData) -> &'r str + 'static) -> Self {
459 self.facet_str_fn = Some(Arc::new(f));
460 self
461 }
462
463 pub fn value_u64_by(mut self, f: impl Fn(&TData) -> u64 + 'static) -> Self {
468 self.value_u64_fn = Some(Arc::new(f));
469 self
470 }
471
472 pub fn aggregate(mut self, aggregation: Aggregation) -> Self {
473 self.aggregation = aggregation;
474 self
475 }
476
477 pub fn enable_hiding(mut self, enabled: bool) -> Self {
478 self.enable_hiding = enabled;
479 self
480 }
481
482 pub fn enable_ordering(mut self, enabled: bool) -> Self {
483 self.enable_ordering = enabled;
484 self
485 }
486
487 pub fn enable_pinning(mut self, enabled: bool) -> Self {
488 self.enable_pinning = enabled;
489 self
490 }
491
492 pub fn enable_resizing(mut self, enabled: bool) -> Self {
493 self.enable_resizing = enabled;
494 self
495 }
496
497 pub fn enable_grouping(mut self, enabled: bool) -> Self {
498 self.enable_grouping = enabled;
499 self
500 }
501
502 pub fn size(mut self, size: f32) -> Self {
503 self.size = size;
504 self
505 }
506
507 pub fn min_size(mut self, min_size: f32) -> Self {
508 self.min_size = min_size;
509 self
510 }
511
512 pub fn max_size(mut self, max_size: f32) -> Self {
513 self.max_size = max_size;
514 self
515 }
516}
517
518#[derive(Debug, Clone, Copy)]
519pub struct ColumnHelper<TData> {
520 _marker: std::marker::PhantomData<TData>,
521}
522
523pub fn create_column_helper<TData>() -> ColumnHelper<TData> {
524 ColumnHelper {
525 _marker: std::marker::PhantomData,
526 }
527}
528
529impl<TData> ColumnHelper<TData> {
530 pub fn accessor<V>(
531 self,
532 id: impl Into<ColumnId>,
533 accessor: impl Fn(&TData) -> V + 'static,
534 ) -> ColumnDef<TData>
535 where
536 V: Ord + Into<TanStackValue>,
537 {
538 let accessor = Arc::new(accessor);
539 let sort_accessor = accessor.clone();
540 let value_accessor = accessor.clone();
541 ColumnDef::new(id)
542 .sort_by(move |a, b| sort_accessor(a).cmp(&sort_accessor(b)))
543 .sort_value_by(move |row| value_accessor(row).into())
544 }
545
546 pub fn accessor_str(
547 self,
548 id: impl Into<ColumnId>,
549 accessor: impl for<'r> Fn(&'r TData) -> &'r str + 'static,
550 ) -> ColumnDef<TData>
551 where
552 TData: 'static,
553 {
554 let accessor: Arc<dyn for<'r> Fn(&'r TData) -> &'r str> = Arc::new(accessor);
555 let sort_accessor = accessor.clone();
556 let facet_accessor = accessor.clone();
557 let value_accessor = accessor.clone();
558 ColumnDef::new(id)
559 .sort_by(move |a, b| sort_accessor(a).cmp(sort_accessor(b)))
560 .sort_value_by(move |row| TanStackValue::String(Arc::<str>::from(value_accessor(row))))
561 .facet_str_by(move |row| facet_accessor(row))
562 }
563}