@maestro-js/components 1.0.0-alpha.18 → 1.0.0-alpha.2

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.
Files changed (56) hide show
  1. package/commands/add.ts +1 -16
  2. package/dist/components.json +1 -1
  3. package/dist/index.js +1 -14
  4. package/package.json +5 -5
  5. package/registry.json +790 -598
  6. package/scripts/build.ts +4 -11
  7. package/src/components/alert-dialog.tsx +3 -3
  8. package/src/components/avatar.tsx +1 -1
  9. package/src/components/button-link.tsx +0 -3
  10. package/src/components/button.tsx +0 -4
  11. package/src/components/checkbox.tsx +7 -7
  12. package/src/components/chip.tsx +7 -7
  13. package/src/components/container.tsx +3 -3
  14. package/src/components/dialog.tsx +7 -21
  15. package/src/components/disclosure.tsx +1 -1
  16. package/src/components/drawer.tsx +5 -19
  17. package/src/components/form.tsx +5 -27
  18. package/src/components/helpers/form-field.tsx +8 -7
  19. package/src/components/helpers/get-button-classes.ts +23 -23
  20. package/src/components/helpers/headless-button.tsx +1 -1
  21. package/src/components/inline-alert.tsx +3 -3
  22. package/src/components/labeled-value.tsx +2 -2
  23. package/src/components/menu.tsx +26 -60
  24. package/src/components/month-day-input.tsx +1 -2
  25. package/src/components/multiselect.tsx +70 -74
  26. package/src/components/radio.tsx +8 -8
  27. package/src/components/select.tsx +8 -9
  28. package/src/components/stepper.tsx +6 -6
  29. package/src/components/switch.tsx +7 -7
  30. package/src/components/tabs.tsx +1 -1
  31. package/src/components/tag-field.tsx +3 -3
  32. package/src/components/text-area.tsx +1 -1
  33. package/src/components/text-field.tsx +1 -4
  34. package/src/components/toast.tsx +6 -6
  35. package/src/components/toggle-button-group.tsx +2 -2
  36. package/src/utils/icons.d.ts +1 -2
  37. package/src/utils/use-tab-indicator.ts +9 -9
  38. package/src/components/date-range.tsx +0 -138
  39. package/src/components/optional-link.tsx +0 -15
  40. package/src/components/table/headless-templated-row-table.ts +0 -550
  41. package/src/components/table/index.tsx +0 -41
  42. package/src/components/table/server-table.ts +0 -143
  43. package/src/components/table/table-actions.tsx +0 -76
  44. package/src/components/table/table-container.tsx +0 -173
  45. package/src/components/table/table-container.type-test.ts +0 -155
  46. package/src/components/table/table-filters/date-range-filter.tsx +0 -227
  47. package/src/components/table/table-filters/select-filter.tsx +0 -211
  48. package/src/components/table/table-filters/sort.tsx +0 -85
  49. package/src/components/table/table-primitives.tsx +0 -226
  50. package/src/components/table/table-toolbar.tsx +0 -300
  51. package/src/components/table/table-types.ts +0 -61
  52. package/src/components/table/use-client-table.ts +0 -157
  53. package/src/components/table/use-client-table.type-test.ts +0 -217
  54. package/src/components/table/use-server-table.ts +0 -192
  55. package/src/components/table/use-server-table.type-test.ts +0 -174
  56. package/src/utils/use-query-state.ts +0 -626
@@ -1,226 +0,0 @@
1
- import { NavLink, type NavLinkProps } from 'react-router'
2
- import { twMerge } from 'tailwind-merge'
3
- import { Icon } from '../icon'
4
- import React from 'react'
5
- import { PlainCheckbox } from '../checkbox'
6
- import type { StandardTable } from './table-types'
7
-
8
- // --- Layout ---
9
-
10
- export function TableMain({
11
- className,
12
- ...props
13
- }: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>) {
14
- return <div className={twMerge('max-w-full h-auto', className)} {...props} />
15
- }
16
-
17
- export function TableBody({
18
- className,
19
- ...props
20
- }: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>) {
21
- return (
22
- <div className="w-full">
23
- <div
24
- className={twMerge(
25
- 'flex flex-col flex-nowrap w-full',
26
- '[&>*+*>*]:border-t [&>*+*>*]:border-gray-950/5' /** select table cells for all but the first row */,
27
- className
28
- )}
29
- {...props}
30
- />
31
- </div>
32
- )
33
- }
34
-
35
- export function TableCell({
36
- className,
37
- ...props
38
- }: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>) {
39
- return <div className={twMerge('basis-0 grow min-w-0 py-3.5 px-2', className)} {...props} />
40
- }
41
-
42
- // --- Row ---
43
-
44
- const TableRowContext = React.createContext<{ table: StandardTable; multiSelect?: boolean }>(null as any)
45
- export const TableRowContextProvider = TableRowContext.Provider
46
-
47
- interface TableRowProps {
48
- row: Record<string, any>
49
- children?: React.ReactNode
50
- className?: string
51
- hideMobileSpacer?: boolean
52
- ['aria-label']?: string
53
- }
54
-
55
- export function TableRow({ row, children, className, hideMobileSpacer, 'aria-label': ariaLabel }: TableRowProps) {
56
- const { table, multiSelect } = React.useContext(TableRowContext)
57
- const selected = table.isRowSelected?.(row) ?? false
58
-
59
- return (
60
- <div
61
- className={twMerge('flex flex-row w-full h-auto', selected && 'bg-gray-50', className)}
62
- onClick={(e) => {
63
- const isTouchableDevice = navigator.maxTouchPoints > 0
64
- const isSmallScreen = !window.matchMedia('(min-width: 640px)').matches
65
-
66
- const target = e.target as HTMLElement
67
- const isInteractiveElement = target.closest('input, label, button, a')
68
-
69
- if ((isTouchableDevice || isSmallScreen) && !isInteractiveElement) {
70
- const title = e.currentTarget.querySelector('[data-row-title*="true"]')
71
- const titleLink = title instanceof HTMLAnchorElement ? title : title?.querySelector('a')
72
- titleLink?.click()
73
- }
74
- }}
75
- role="row"
76
- aria-label={ariaLabel}
77
- >
78
- {multiSelect ? (
79
- <div className="relative shrink-0 hidden md:flex items-start pt-3.5 pl-4 pr-2 *:scale-90">
80
- {selected ? <div className="absolute inset-y-0 left-0 w-0.5 bg-primary-600" /> : null}
81
- <PlainCheckbox checked={selected} onChange={() => table.toggleRowSelection?.(row)} />
82
- </div>
83
- ) : null}
84
- {!hideMobileSpacer ? <TableCell className={twMerge('relative grow-0 w-3', multiSelect && 'md:hidden')} /> : null}
85
-
86
- {children}
87
- </div>
88
- )
89
- }
90
-
91
- // --- Title / Description ---
92
-
93
- export interface TableTitleProps extends React.DetailedHTMLProps<
94
- React.HTMLAttributes<HTMLParagraphElement>,
95
- HTMLParagraphElement
96
- > {}
97
-
98
- export function TableTitle({ className, ...props }: TableTitleProps) {
99
- return <p {...props} data-row-title="true" className={twMerge('truncate text-sm font-medium text-blue-600', className)} />
100
- }
101
-
102
- export function TableTitleLink({ className, ...props }: NavLinkProps) {
103
- return (
104
- <NavLink
105
- {...props}
106
- data-row-title="true"
107
- className={(b) =>
108
- twMerge('truncate text-sm font-medium text-blue-600', typeof className === 'function' ? className(b) : className)
109
- }
110
- />
111
- )
112
- }
113
-
114
- export interface TableDescriptionProps extends React.DetailedHTMLProps<
115
- React.HTMLAttributes<HTMLDivElement>,
116
- HTMLDivElement
117
- > {}
118
-
119
- export function TableDescription({ className, ...props }: TableDescriptionProps) {
120
- return <div {...props} className={twMerge('truncate text-sm text-gray-500', className)} />
121
- }
122
-
123
- // --- Footer ---
124
-
125
- export interface TableFooterProps {
126
- table: StandardTable
127
- hideResultCount?: boolean
128
- }
129
-
130
- export function TableFooter({ table, hideResultCount }: TableFooterProps) {
131
- const { limit, skip } = table.state.pagination
132
- const rowCount = table.getRowCount()
133
-
134
- const pageCount = Math.ceil(limit ? rowCount / limit : 1)
135
- const pageNumber = limit > 0 ? Math.floor(skip / limit) : 0
136
-
137
- const goToPage = (page: number) => {
138
- table.setPagination({ limit, skip: page * (limit || 25) })
139
- }
140
-
141
- const canGoPrevious = pageNumber > 0
142
- const canGoNext = pageNumber < pageCount - 1
143
-
144
- const showingFrom = skip + 1
145
- const showingTo = limit ? Math.min(skip + limit, rowCount) : rowCount
146
- const pages = getPaginationRange(pageCount, pageNumber)
147
-
148
- return (
149
- <nav className="flex items-center justify-between border-t border-gray-950/5 px-4 py-2">
150
- {!hideResultCount ? (
151
- <p className="text-xs text-gray-400 tabular-nums">
152
- {showingFrom}–{showingTo} of {rowCount}
153
- </p>
154
- ) : (
155
- <div />
156
- )}
157
- {pageCount > 1 && (
158
- <div className="flex items-center gap-0.5">
159
- <button
160
- type="button"
161
- onClick={() => canGoPrevious && goToPage(pageNumber - 1)}
162
- disabled={!canGoPrevious}
163
- className="inline-flex items-center justify-center rounded-md p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 disabled:opacity-30 disabled:hover:bg-transparent"
164
- aria-label="Previous page"
165
- >
166
- <Icon name="chevron-left" className="size-3.5" />
167
- </button>
168
- <div className="flex items-center gap-0.5 max-sm:hidden">
169
- {pages.map((page, i) => {
170
- if (page === '...') {
171
- return (
172
- <span key={`ellipsis-${i}`} className="px-1 text-xs text-gray-400">
173
- ...
174
- </span>
175
- )
176
- }
177
- const isSelected = page === pageNumber
178
- return (
179
- <button
180
- type="button"
181
- key={page}
182
- onClick={() => goToPage(page)}
183
- className={twMerge(
184
- 'inline-flex items-center justify-center size-7 rounded-full text-xs tabular-nums',
185
- isSelected
186
- ? 'bg-gray-100 text-gray-900 font-medium'
187
- : 'text-gray-400 hover:bg-gray-50 hover:text-gray-600'
188
- )}
189
- >
190
- {page + 1}
191
- </button>
192
- )
193
- })}
194
- </div>
195
- <span className="text-xs tabular-nums text-gray-400 sm:hidden px-1">
196
- {pageNumber + 1}/{pageCount}
197
- </span>
198
- <button
199
- type="button"
200
- onClick={() => canGoNext && goToPage(pageNumber + 1)}
201
- disabled={!canGoNext}
202
- className="inline-flex items-center justify-center rounded-md p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 disabled:opacity-30 disabled:hover:bg-transparent"
203
- aria-label="Next page"
204
- >
205
- <Icon name="chevron-right" className="size-3.5" />
206
- </button>
207
- </div>
208
- )}
209
- </nav>
210
- )
211
- }
212
-
213
- function getPaginationRange(pageCount: number, currentPage: number): (number | '...')[] {
214
- const delta = 1
215
- const range: (number | '...')[] = []
216
-
217
- for (let i = 0; i < pageCount; i++) {
218
- if (i === 0 || i === pageCount - 1 || (i >= currentPage - delta && i <= currentPage + delta)) {
219
- range.push(i)
220
- } else if (range[range.length - 1] !== '...') {
221
- range.push('...')
222
- }
223
- }
224
-
225
- return range
226
- }
@@ -1,300 +0,0 @@
1
- import { twMerge } from 'tailwind-merge'
2
- import { type To, Link, useNavigate } from 'react-router'
3
- import { Icon } from '../icon'
4
- import { OptionalLink, type OptionalLinkProps } from '../optional-link'
5
- import { usePress } from '@react-aria/interactions'
6
- import React from 'react'
7
- import { mergeProps } from '@react-aria/utils'
8
- import { HeadlessButton } from '../helpers/headless-button'
9
- import { PlainCheckbox } from '../checkbox'
10
- import { Button, Menu, MenuItem, MenuTrigger, Popover } from 'react-aria-components'
11
- import type { StandardTable } from './table-types'
12
-
13
- // --- Header ---
14
-
15
- export interface TableHeaderProps {
16
- table: StandardTable
17
- multiSelect?: boolean
18
- multiSelectActions?: React.ReactNode
19
- children: React.ReactNode
20
- sticky?: boolean
21
- hide?: boolean
22
- action?: React.ReactNode
23
- }
24
-
25
- export function TableHeader({ table, multiSelect, multiSelectActions, children, sticky, hide, action }: TableHeaderProps) {
26
- const rowCount = table.getRows().length
27
- const selectionSize = table.state.rowSelection?.size ?? 0
28
- const hasSelection = multiSelect && selectionSize > 0
29
-
30
- if (hide) return null
31
-
32
- return (
33
- <div
34
- className={twMerge(
35
- 'bg-gray-100 border-b border-gray-950/10 py-0.5',
36
- sticky && 'sticky z-20 md:z-[2] top-0',
37
- hasSelection && 'bg-primary-50 border-primary-200'
38
- )}
39
- >
40
- <div className="flex items-center gap-2 pl-4 pr-1.5 min-h-9">
41
- {action}
42
- {multiSelect ? (
43
- <div className="flex items-center *:scale-90">
44
- <PlainCheckbox
45
- checked={rowCount > 0 ? selectionSize === rowCount : false}
46
- onChange={() => table.toggleAllRowSelection?.()}
47
- isDisabled={rowCount === 0}
48
- />
49
- </div>
50
- ) : null}
51
- {hasSelection ? (
52
- <>
53
- <span className="text-sm text-primary-700 font-medium">{selectionSize} selected</span>
54
- <button
55
- type="button"
56
- onClick={() => table.clearRowSelection?.()}
57
- className="text-sm text-gray-500 hover:text-gray-700 flex items-center gap-1"
58
- >
59
- <Icon name="x-mark" className="size-4" />
60
- <span className="max-sm:hidden">Clear</span>
61
- </button>
62
- <div className="grow" />
63
- {multiSelectActions}
64
- </>
65
- ) : (
66
- <>
67
- <div className="grow" />
68
- <div className="flex overflow-x-scroll scrollbar-hide md:overflow-x-visible h-full gap-2">{children}</div>
69
- </>
70
- )}
71
- </div>
72
- </div>
73
- )
74
- }
75
-
76
- // --- Search ---
77
-
78
- interface TableSearchProps {
79
- table: StandardTable
80
- actions?: React.ReactNode
81
- placeholder?: string | null
82
- hideActionsOnMobile?: boolean
83
- hasFilters?: boolean
84
- hideSearch?: boolean
85
- }
86
-
87
- export function TableSearch({ table, actions, placeholder, hideActionsOnMobile, hasFilters, hideSearch }: TableSearchProps) {
88
- const [inputValue, setInputValue] = React.useState(table.state.search ?? '')
89
-
90
- React.useEffect(() => {
91
- setInputValue(table.state.search ?? '')
92
- }, [table.state.search])
93
-
94
- const commitSearch = React.useCallback(
95
- (value: string) => {
96
- table.setSearch(value)
97
- },
98
- [table]
99
- )
100
-
101
- const clearAll = () => {
102
- table.setSearch('')
103
- }
104
-
105
- return (
106
- <div className="w-full mb-3">
107
- <div
108
- className={twMerge(
109
- 'flex',
110
- hideActionsOnMobile ? 'md:flex-row-reverse md:gap-x-2 flex-wrap' : 'flex-row-reverse gap-x-2'
111
- )}
112
- >
113
- <div className={twMerge(hideActionsOnMobile && 'basis-full md:basis-auto')}>{actions}</div>
114
- {hideSearch ? null : (
115
- <form
116
- className="flex grow"
117
- onSubmit={(e) => {
118
- e.preventDefault()
119
- commitSearch(inputValue)
120
- }}
121
- >
122
- <div className="grow relative max-w-2xl" role="search">
123
- <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
124
- <Icon name="magnifying-glass" className="size-4 text-gray-400" aria-hidden="true" />
125
- </div>
126
- <input
127
- className={twMerge(
128
- 'w-full max-w-2xl pl-9 rounded-md border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-black/10 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 text-sm/6 max-sm:text-base/6',
129
- hasFilters ? 'pr-8' : 'pr-3'
130
- )}
131
- enterKeyHint="search"
132
- placeholder={placeholder || undefined}
133
- value={inputValue}
134
- onChange={(e) => setInputValue(e.target.value)}
135
- />
136
- {table.state.search ? (
137
- <button
138
- type="button"
139
- onClick={clearAll}
140
- className="absolute inset-y-0 right-0 flex items-center pr-2.5"
141
- aria-label="Clear search"
142
- >
143
- <Icon name="x-mark" className="size-4 text-gray-400 hover:text-gray-600" />
144
- </button>
145
- ) : null}
146
- </div>
147
- </form>
148
- )}
149
- </div>
150
- </div>
151
- )
152
- }
153
-
154
- // --- Actions ---
155
-
156
- export type NavigationAction = { label: string; to: To; replace?: boolean; preventScrollReset?: boolean; disabled?: boolean }
157
- export type ButtonAction = { label: string; onClick: () => void; disabled?: boolean }
158
- export type ActionParams = NavigationAction | ButtonAction
159
-
160
- export type TableActionProps = {
161
- actions: (ActionParams | null | undefined)[] | null | undefined
162
- maxVisibleActions?: number
163
- compact?: boolean
164
- }
165
-
166
- function isNavigationAction(action: ActionParams): action is NavigationAction {
167
- return 'to' in action
168
- }
169
-
170
- export function TableActions({ actions: rawActions, maxVisibleActions = 4, compact }: TableActionProps) {
171
- const navigate = useNavigate()
172
- const actions = (rawActions?.filter(Boolean) || []) as ActionParams[]
173
-
174
- // If we have more actions than the max, always use dropdown on desktop too
175
- const useDropdownOnDesktop = actions.length > maxVisibleActions
176
-
177
- const dropdownTriggerClassName = compact
178
- ? 'inline-flex items-center rounded px-2 py-0.5 text-sm font-medium text-primary-700 hover:text-primary-900 hover:bg-primary-100 truncate'
179
- : twMerge(
180
- 'inline-flex items-center rounded bg-white px-2 py-1 text-sm font-semibold text-gray-900',
181
- 'shadow-sm ring-1 ring-black/10',
182
- 'disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-white',
183
- 'hover:bg-gray-50 truncate'
184
- )
185
-
186
- return (
187
- <>
188
- <div className={useDropdownOnDesktop ? '' : 'xl:hidden'}>
189
- {actions.length ? (
190
- <MenuTrigger>
191
- <Button className={dropdownTriggerClassName}>
192
- Actions
193
- <Icon name="chevron-down" className="h-5 w-5" />
194
- </Button>
195
- <Popover offset={4} className="w-48 rounded-md shadow-lg ring-1 ring-black/10 bg-white z-20">
196
- <Menu className="outline-none py-1">
197
- {actions.map((a) => (
198
- <MenuItem
199
- key={a.label}
200
- isDisabled={a.disabled}
201
- onAction={() => {
202
- if (isNavigationAction(a)) {
203
- navigate(a.to, { replace: a.replace, preventScrollReset: a.preventScrollReset })
204
- } else {
205
- a.onClick()
206
- }
207
- }}
208
- className={({ isFocused }) =>
209
- twMerge(
210
- 'text-sm px-4 py-2 cursor-pointer outline-none',
211
- isFocused ? 'text-white bg-primary-500' : 'text-gray-900',
212
- a.disabled && 'opacity-50 cursor-not-allowed'
213
- )
214
- }
215
- >
216
- {a.label}
217
- </MenuItem>
218
- ))}
219
- </Menu>
220
- </Popover>
221
- </MenuTrigger>
222
- ) : null}
223
- </div>
224
- {!useDropdownOnDesktop ? (
225
- <div className="gap-x-2 hidden xl:flex">
226
- {actions.map((a) =>
227
- isNavigationAction(a) ? (
228
- <ActionLink
229
- to={a.to}
230
- replace={a.replace}
231
- key={a.label}
232
- preventScrollReset={a.preventScrollReset}
233
- disabled={a.disabled}
234
- compact={compact}
235
- >
236
- {a.label}
237
- </ActionLink>
238
- ) : (
239
- <ActionButton key={a.label} onClick={a.onClick} disabled={a.disabled} compact={compact}>
240
- {a.label}
241
- </ActionButton>
242
- )
243
- )}
244
- </div>
245
- ) : null}
246
- </>
247
- )
248
- }
249
-
250
- function ActionLink(props: OptionalLinkProps & { compact?: boolean }) {
251
- const ref = React.useRef<HTMLAnchorElement>(null)
252
- const { isPressed, pressProps } = usePress({
253
- ref
254
- })
255
- const { compact, ...linkProps } = props
256
- return (
257
- <OptionalLink
258
- {...mergeProps(pressProps, linkProps)}
259
- ref={ref}
260
- className={twMerge(
261
- props.className,
262
- props.disabled && 'cursor-not-allowed opacity-30',
263
- compact
264
- ? 'inline-flex items-center rounded px-2 py-0.5 text-sm font-medium text-primary-700 hover:text-primary-900 hover:bg-primary-100 truncate'
265
- : twMerge(
266
- 'inline-flex items-center rounded bg-white px-2 py-1 text-sm font-semibold text-gray-900',
267
- 'shadow-sm ring-1 ring-black/10',
268
- 'hover:bg-gray-50 truncate'
269
- ),
270
- isPressed && 'scale-[.98]'
271
- )}
272
- >
273
- {props.children}
274
- </OptionalLink>
275
- )
276
- }
277
-
278
- type ActionButtonProps = React.ComponentProps<typeof HeadlessButton> & { compact?: boolean }
279
-
280
- function ActionButton(props: ActionButtonProps) {
281
- const { className, compact, ...restProps } = props
282
- return (
283
- <HeadlessButton
284
- {...restProps}
285
- className={twMerge(
286
- typeof className === 'function' ? className({ isPressed: false }) : className,
287
- props.disabled && 'cursor-not-allowed opacity-30',
288
- compact
289
- ? 'inline-flex items-center rounded px-2 py-0.5 text-sm font-medium text-primary-700 hover:text-primary-900 hover:bg-primary-100 truncate'
290
- : twMerge(
291
- 'inline-flex items-center rounded bg-white px-2 py-1 text-sm font-semibold text-gray-900',
292
- 'shadow-sm ring-1 ring-black/10',
293
- 'hover:bg-gray-50 truncate data-[pressed=true]:scale-[.98]'
294
- )
295
- )}
296
- >
297
- {props.children}
298
- </HeadlessButton>
299
- )
300
- }
@@ -1,61 +0,0 @@
1
- import type { ReactNode } from 'react'
2
- import type { Iso } from 'iso-fns'
3
- import type { DateRangeRootAdditionalProps } from '../date-range'
4
-
5
- type PaginationState = { limit: number; skip: number }
6
- type SetterOrUpdater<T> = T | ((prev: T) => T)
7
-
8
- export type StandardTable<
9
- FC extends Record<string, any> = Record<string, any>,
10
- SC extends Record<string, any> = Record<string, any>
11
- > = {
12
- getRows(): Record<string, any>[]
13
- getRowCount(): number
14
- getFilterConfig(): FC
15
- getSortConfig(): { [K in keyof SC]: null }
16
- state: {
17
- filters: { [K in keyof FC]: FC[K] | null | undefined }
18
- sort: (keyof SC & string) | null
19
- search: string
20
- pagination: PaginationState
21
- rowSelection?: Set<string>
22
- }
23
- setFilters(val: SetterOrUpdater<{ [K in keyof FC]: FC[K] | null | undefined }>): void
24
- setSort(val: any): void
25
- setSearch(val: SetterOrUpdater<string>): void
26
- setPagination(val: SetterOrUpdater<PaginationState>): void
27
- toggleAllRowSelection?(): void
28
- toggleRowSelection?(row: Record<string, any>): void
29
- isRowSelected?(row: Record<string, any>): boolean
30
- clearRowSelection?(): void
31
- }
32
-
33
- type DefaultTableFilter<V = any> = {
34
- label: string
35
- type?: never
36
- options: { label: string; value: V; className?: string; icon?: ReactNode }[]
37
- autoComplete?: boolean
38
- }
39
-
40
- type DateRangeTableFilter = {
41
- label: string
42
- type: 'date-range'
43
- options?: Pick<DateRangeRootAdditionalProps, 'shouldDisableDate' | 'shouldDisableEndDate' | 'shouldDisableStartDate'> & {
44
- quickPresets?: { label: string; value: { startDate: Iso.Date; endDate: Iso.Date } }[]
45
- }
46
- }
47
-
48
- export type TableFilterLocalization<V = any> = 0 extends 1 & V
49
- ? DefaultTableFilter | DateRangeTableFilter
50
- : [V] extends [{ startDate: Iso.Date; endDate: Iso.Date }]
51
- ? DateRangeTableFilter
52
- : DefaultTableFilter<V>
53
-
54
- export type TableLocalization<
55
- FC extends Record<string, any> = Record<string, any>,
56
- SC extends Record<string, any> = Record<string, any>
57
- > = {
58
- filters: { [K in keyof FC]: TableFilterLocalization<FC[K]> }
59
- sorts: { [key in keyof SC]: { label: string } }
60
- searchPlaceholder?: string
61
- }