@cronocode/react-box 3.1.3 → 3.1.7

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.
@@ -0,0 +1,576 @@
1
+ # @cronocode/react-box - AI Assistant Context
2
+
3
+ Reference document for AI assistants helping developers use this runtime CSS-in-JS library.
4
+
5
+ ---
6
+
7
+ ## Quick Overview
8
+
9
+ **What it is**: A React library that converts component props directly into CSS classes at runtime. No CSS files needed.
10
+
11
+ **Core component**: `Box` - a polymorphic component that accepts ~144 CSS props and renders any HTML element.
12
+
13
+ ```tsx
14
+ import Box from '@cronocode/react-box';
15
+
16
+ // Basic usage
17
+ <Box p={4} bgColor="blue-500" color="white">Content</Box>
18
+
19
+ // Renders as different elements
20
+ <Box tag="button" p={3}>Button</Box>
21
+ <Box tag="a" props={{ href: '/link' }}>Link</Box>
22
+
23
+ // Alias components (recommended)
24
+ import Button from '@cronocode/react-box/components/button';
25
+ <Button p={3}>Button</Button>
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Critical: Numeric Value Formatters
31
+
32
+ **This is the #1 source of confusion.** Different props have different dividers:
33
+
34
+ | Prop Category | Divider | Formula | Example | CSS Output |
35
+ |--------------|---------|---------|---------|------------|
36
+ | Spacing (`p`, `m`, `gap`, `px`, `py`, `mx`, `my`, etc.) | 4 | value/4 rem | `p={4}` | `padding: 1rem` (16px) |
37
+ | Font size (`fontSize`) | **16** | value/16 rem | `fontSize={16}` | `font-size: 1rem` (16px) |
38
+ | Width/Height (numeric) | 4 | value/4 rem | `width={20}` | `width: 5rem` (80px) |
39
+ | Border width (`b`, `bx`, `by`, `bt`, `br`, `bb`, `bl`) | none | direct px | `b={1}` | `border-width: 1px` |
40
+ | Border radius (`borderRadius`) | none | direct px | `borderRadius={8}` | `border-radius: 8px` |
41
+
42
+ ### Common fontSize Values
43
+ ```tsx
44
+ fontSize={12} // → 0.75rem ≈ 12px (small)
45
+ fontSize={14} // → 0.875rem ≈ 14px (body)
46
+ fontSize={16} // → 1rem = 16px (default)
47
+ fontSize={18} // → 1.125rem ≈ 18px (large)
48
+ fontSize={24} // → 1.5rem = 24px (h2)
49
+ fontSize={32} // → 2rem = 32px (h1)
50
+ ```
51
+
52
+ ### Common Spacing Values (divider = 4)
53
+ ```tsx
54
+ p={1} // → 0.25rem = 4px
55
+ p={2} // → 0.5rem = 8px
56
+ p={3} // → 0.75rem = 12px
57
+ p={4} // → 1rem = 16px
58
+ p={6} // → 1.5rem = 24px
59
+ p={8} // → 2rem = 32px
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Prop Reference
65
+
66
+ ### Spacing
67
+ | Prop | CSS Property |
68
+ |------|-------------|
69
+ | `p` | padding |
70
+ | `px` | padding-left + padding-right |
71
+ | `py` | padding-top + padding-bottom |
72
+ | `pt`, `pr`, `pb`, `pl` | padding-top/right/bottom/left |
73
+ | `m` | margin |
74
+ | `mx`, `my` | margin horizontal/vertical |
75
+ | `mt`, `mr`, `mb`, `ml` | margin-top/right/bottom/left |
76
+ | `gap` | gap (flexbox/grid) |
77
+
78
+ ### Layout
79
+ | Prop | CSS Property | Values |
80
+ |------|-------------|--------|
81
+ | `display` | display | `'flex'`, `'block'`, `'inline'`, `'grid'`, `'none'`, `'inline-flex'`, etc. |
82
+ | `d` | flex-direction | `'row'`, `'column'`, `'row-reverse'`, `'column-reverse'` |
83
+ | `wrap` | flex-wrap | `'wrap'`, `'nowrap'`, `'wrap-reverse'` |
84
+ | `items` | align-items | `'center'`, `'start'`, `'end'`, `'stretch'`, `'baseline'` |
85
+ | `justify` | justify-content | `'center'`, `'start'`, `'end'`, `'between'`, `'around'`, `'evenly'` |
86
+ | `flex` | flex | number or string |
87
+ | `grow` | flex-grow | number |
88
+ | `shrink` | flex-shrink | number |
89
+
90
+ ### Sizing
91
+ | Prop | CSS Property | Accepts |
92
+ |------|-------------|---------|
93
+ | `width` | width | number (rem/4), string (`'auto'`, `'1/2'`, `'fit'`, `'fit-screen'`) |
94
+ | `height` | height | number (rem/4), string (`'auto'`, `'fit'`, `'fit-screen'`) |
95
+ | `minWidth`, `maxWidth` | min/max-width | number or string |
96
+ | `minHeight`, `maxHeight` | min/max-height | number or string |
97
+
98
+ ### Colors (Tailwind-like palette)
99
+ | Prop | CSS Property |
100
+ |------|-------------|
101
+ | `bgColor` | background-color |
102
+ | `color` | color |
103
+ | `borderColor` | border-color |
104
+
105
+ **Color values**: `'gray-50'` through `'gray-900'`, same for `red`, `orange`, `yellow`, `green`, `teal`, `blue`, `indigo`, `purple`, `pink`, `violet`.
106
+
107
+ Also: `'white'`, `'black'`, `'transparent'`, `'inherit'`, `'currentColor'`
108
+
109
+ ### Borders
110
+ | Prop | CSS Property |
111
+ |------|-------------|
112
+ | `b` | border-width (all sides) |
113
+ | `bx` | border-left-width + border-right-width |
114
+ | `by` | border-top-width + border-bottom-width |
115
+ | `bt`, `br`, `bb`, `bl` | individual sides |
116
+ | `borderRadius` | border-radius |
117
+ | `borderStyle` | border-style (`'solid'`, `'dashed'`, `'dotted'`, `'none'`) |
118
+
119
+ ### Typography
120
+ | Prop | CSS Property |
121
+ |------|-------------|
122
+ | `fontSize` | font-size (divider: 16) |
123
+ | `fontWeight` | font-weight (`400`, `500`, `600`, `700`, etc.) |
124
+ | `lineHeight` | line-height |
125
+ | `textAlign` | text-align |
126
+ | `textDecoration` | text-decoration |
127
+ | `textTransform` | text-transform |
128
+ | `whiteSpace` | white-space |
129
+ | `overflow` | overflow |
130
+ | `textOverflow` | text-overflow |
131
+
132
+ ### Positioning
133
+ | Prop | CSS Property |
134
+ |------|-------------|
135
+ | `position` | position (`'relative'`, `'absolute'`, `'fixed'`, `'sticky'`) |
136
+ | `top`, `right`, `bottom`, `left` | positioning offsets |
137
+ | `zIndex` | z-index |
138
+
139
+ ### Effects
140
+ | Prop | CSS Property |
141
+ |------|-------------|
142
+ | `shadow` | box-shadow (`'small'`, `'medium'`, `'large'`, `'xl'`, `'none'`) |
143
+ | `opacity` | opacity |
144
+ | `cursor` | cursor |
145
+ | `pointerEvents` | pointer-events |
146
+ | `transition` | transition |
147
+ | `transform` | transform |
148
+
149
+ ---
150
+
151
+ ## Pseudo-Classes
152
+
153
+ Apply styles on interaction states:
154
+
155
+ ```tsx
156
+ <Box
157
+ bgColor="blue-500"
158
+ hover={{ bgColor: 'blue-600' }}
159
+ focus={{ outline: 'none', ring: 2 }}
160
+ active={{ bgColor: 'blue-700' }}
161
+ disabled={{ opacity: 0.5, cursor: 'not-allowed' }}
162
+ />
163
+ ```
164
+
165
+ **Available pseudo-classes**: `hover`, `focus`, `active`, `disabled`, `checked`, `indeterminate`, `required`, `selected`, `focusWithin`, `focusVisible`, `first`, `last`, `even`, `odd`, `empty`
166
+
167
+ ---
168
+
169
+ ## Responsive Breakpoints
170
+
171
+ Mobile-first breakpoints using min-width media queries:
172
+
173
+ ```tsx
174
+ <Box
175
+ p={2} // Base (mobile)
176
+ sm={{ p: 3 }} // ≥640px
177
+ md={{ p: 4 }} // ≥768px
178
+ lg={{ p: 6 }} // ≥1024px
179
+ xl={{ p: 8 }} // ≥1280px
180
+ xxl={{ p: 10 }} // ≥1536px
181
+ />
182
+ ```
183
+
184
+ **Combine with pseudo-classes**:
185
+ ```tsx
186
+ <Box
187
+ bgColor="white"
188
+ hover={{ bgColor: 'gray-100' }}
189
+ md={{
190
+ bgColor: 'gray-50',
191
+ hover: { bgColor: 'gray-200' }
192
+ }}
193
+ />
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Theme System
199
+
200
+ ### Setting Up Themes
201
+
202
+ ```tsx
203
+ import Box from '@cronocode/react-box';
204
+
205
+ function App() {
206
+ return (
207
+ <Box.Theme value="dark">
208
+ <YourApp />
209
+ </Box.Theme>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ### Theme-Aware Styles
215
+
216
+ ```tsx
217
+ <Box
218
+ bgColor="white"
219
+ color="gray-900"
220
+ theme={{
221
+ dark: {
222
+ bgColor: 'gray-900',
223
+ color: 'gray-100',
224
+ },
225
+ }}
226
+ />
227
+ ```
228
+
229
+ ### Theme + Pseudo-Classes
230
+
231
+ ```tsx
232
+ <Box
233
+ bgColor="white"
234
+ hover={{ bgColor: 'gray-100' }}
235
+ theme={{
236
+ dark: {
237
+ bgColor: 'gray-800',
238
+ hover: { bgColor: 'gray-700' },
239
+ },
240
+ }}
241
+ />
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Component System
247
+
248
+ ### Using Built-in Components
249
+
250
+ ```tsx
251
+ <Box component="button" variant="primary">Click me</Box>
252
+ <Box component="button.icon" />
253
+ ```
254
+
255
+ ### Pre-built Components
256
+
257
+ Import ready-to-use components:
258
+
259
+ ```tsx
260
+ // Form components
261
+ import Button from '@cronocode/react-box/components/button';
262
+ import Textbox from '@cronocode/react-box/components/textbox';
263
+ import Checkbox from '@cronocode/react-box/components/checkbox';
264
+ import Dropdown from '@cronocode/react-box/components/dropdown';
265
+ import Tooltip from '@cronocode/react-box/components/tooltip';
266
+
267
+ // Layout
268
+ import Flex from '@cronocode/react-box/components/flex'; // Box with display="flex" (supports inline prop)
269
+ import Grid from '@cronocode/react-box/components/grid'; // Box with display="grid" (supports inline prop)
270
+
271
+ <Button variant="primary">Submit</Button>
272
+ <Textbox placeholder="Enter text..." />
273
+ <Flex gap={4} items="center">...</Flex>
274
+ <Flex inline gap={2}>Inline flex</Flex>
275
+ ```
276
+
277
+ ### Semantic HTML Components
278
+
279
+ Alias components for semantic HTML elements (from `components/semantics`):
280
+
281
+ ```tsx
282
+ import {
283
+ // Typography
284
+ P, H1, H2, H3, H4, H5, H6, Span, Mark,
285
+ // Structure
286
+ Header, Footer, Main, Nav, Section, Article, Aside,
287
+ // Other
288
+ Label, Link, Img, Figure, Figcaption, Details, Summary, Menu, Time,
289
+ } from '@cronocode/react-box/components/semantics';
290
+
291
+ // These are Box aliases with the correct HTML tag
292
+ <H1 fontSize={32} fontWeight={700}>Title</H1>
293
+ <P color="gray-600">Paragraph text</P>
294
+ <Link props={{ href: '/about' }} color="blue-500">About</Link>
295
+ <Flex tag="nav" gap={4}>...</Flex>
296
+ ```
297
+
298
+ ### Custom Components with Box.components()
299
+
300
+ ```tsx
301
+ // Define custom component styles
302
+ Box.components({
303
+ card: {
304
+ styles: {
305
+ display: 'flex',
306
+ d: 'column',
307
+ p: 4,
308
+ bgColor: 'white',
309
+ borderRadius: 8,
310
+ shadow: 'medium',
311
+ },
312
+ variants: {
313
+ bordered: { b: 1, borderColor: 'gray-200', shadow: 'none' },
314
+ elevated: { shadow: 'large' },
315
+ },
316
+ children: {
317
+ header: { styles: { fontSize: 18, fontWeight: 600, mb: 3 } },
318
+ body: { styles: { flex: 1 } },
319
+ },
320
+ },
321
+ });
322
+
323
+ // Use it
324
+ <Box component="card" variant="bordered">
325
+ <Box component="card.header">Title</Box>
326
+ <Box component="card.body">Content</Box>
327
+ </Box>
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Extension System
333
+
334
+ ### Adding Custom Colors/Variables
335
+
336
+ ```tsx
337
+ import Box from '@cronocode/react-box';
338
+
339
+ export const { extendedProps, extendedPropTypes } = Box.extend(
340
+ // Custom CSS variables
341
+ {
342
+ 'brand-primary': '#ff6600',
343
+ 'brand-secondary': '#0066ff',
344
+ },
345
+
346
+ // New props (optional)
347
+ {},
348
+
349
+ // Extend existing props with new values
350
+ {
351
+ bgColor: [
352
+ {
353
+ values: ['brand-primary', 'brand-secondary'] as const,
354
+ styleName: 'background-color',
355
+ valueFormat: (value, getVariable) => getVariable(value),
356
+ },
357
+ ],
358
+ color: [
359
+ {
360
+ values: ['brand-primary', 'brand-secondary'] as const,
361
+ styleName: 'color',
362
+ valueFormat: (value, getVariable) => getVariable(value),
363
+ },
364
+ ],
365
+ }
366
+ );
367
+
368
+ // Now use your custom colors
369
+ <Box bgColor="brand-primary" color="white">Branded</Box>
370
+ ```
371
+
372
+ ### TypeScript Type Augmentation
373
+
374
+ **Manual approach** (simple cases):
375
+
376
+ ```typescript
377
+ // types.d.ts
378
+ import '@cronocode/react-box/types';
379
+
380
+ declare module '@cronocode/react-box/types' {
381
+ namespace Augmented {
382
+ interface BoxPropTypes {
383
+ bgColor: 'brand-primary' | 'brand-secondary';
384
+ }
385
+ interface ComponentsTypes {
386
+ card: 'bordered' | 'elevated';
387
+ }
388
+ }
389
+ }
390
+ ```
391
+
392
+ **Generic approach** (recommended - auto-extracts types from your definitions):
393
+
394
+ ```typescript
395
+ // types.d.ts
396
+ import { ExtractComponentsAndVariants, ExtractBoxStyles } from '@cronocode/react-box/types';
397
+ import { components } from './boxComponents';
398
+ import { extendedPropTypes, extendedProps } from './boxExtends';
399
+
400
+ declare module '@cronocode/react-box/types' {
401
+ namespace Augmented {
402
+ interface BoxProps extends ExtractBoxStyles<typeof extendedProps> {}
403
+ interface BoxPropTypes extends ExtractBoxStyles<typeof extendedPropTypes> {}
404
+ interface ComponentsTypes extends ExtractComponentsAndVariants<typeof components> {}
405
+ }
406
+ }
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Common Patterns
412
+
413
+ ### Flex Container
414
+ ```tsx
415
+ import Flex from '@cronocode/react-box/components/flex';
416
+
417
+ <Flex d="column" gap={4} items="center" justify="between">
418
+ {children}
419
+ </Flex>
420
+ ```
421
+
422
+ ### Card
423
+ ```tsx
424
+ <Box p={4} bgColor="white" borderRadius={8} shadow="medium">
425
+ {content}
426
+ </Box>
427
+ ```
428
+
429
+ ### Button
430
+ ```tsx
431
+ import Button from '@cronocode/react-box/components/button';
432
+
433
+ <Button
434
+ px={4}
435
+ py={2}
436
+ bgColor="blue-500"
437
+ color="white"
438
+ borderRadius={6}
439
+ fontWeight={500}
440
+ hover={{ bgColor: 'blue-600' }}
441
+ disabled={{ opacity: 0.5, cursor: 'not-allowed' }}
442
+ >
443
+ Click me
444
+ </Button>
445
+ ```
446
+
447
+ ### Input Field
448
+ ```tsx
449
+ import Textbox from '@cronocode/react-box/components/textbox';
450
+
451
+ <Textbox
452
+ placeholder="Enter text..."
453
+ width="fit"
454
+ px={3}
455
+ py={2}
456
+ b={1}
457
+ borderColor="gray-300"
458
+ borderRadius={6}
459
+ focus={{ borderColor: 'blue-500', outline: 'none' }}
460
+ />
461
+ ```
462
+
463
+ ### Grid Layout
464
+ ```tsx
465
+ import Grid from '@cronocode/react-box/components/grid';
466
+
467
+ <Grid gridCols={3} gap={4}>
468
+ {items.map(item => <Box key={item.id}>{item.content}</Box>)}
469
+ </Grid>
470
+ ```
471
+
472
+ ### Responsive Stack
473
+ ```tsx
474
+ import Flex from '@cronocode/react-box/components/flex';
475
+
476
+ <Flex d="column" gap={2} md={{ d: 'row', gap: 4 }}>
477
+ {children}
478
+ </Flex>
479
+ ```
480
+
481
+ ### Truncated Text
482
+ ```tsx
483
+ <Box
484
+ overflow="hidden"
485
+ textOverflow="ellipsis"
486
+ whiteSpace="nowrap"
487
+ >
488
+ Long text that will be truncated...
489
+ </Box>
490
+ ```
491
+
492
+ ### Overlay/Modal Backdrop
493
+ ```tsx
494
+ <Box
495
+ position="fixed"
496
+ top={0}
497
+ left={0}
498
+ right={0}
499
+ bottom={0}
500
+ bgColor="black"
501
+ opacity={0.5}
502
+ zIndex={50}
503
+ />
504
+ ```
505
+
506
+ **Note**: For tooltips, dropdowns, and popups that need to escape `overflow: hidden` containers, use the `Tooltip` component instead of manual `zIndex`. It uses React portals to render content outside the DOM hierarchy, avoiding z-index and overflow issues.
507
+
508
+ ```tsx
509
+ import Tooltip from '@cronocode/react-box/components/tooltip';
510
+
511
+ <Tooltip content="Tooltip text">
512
+ <Button>Hover me</Button>
513
+ </Tooltip>
514
+ ```
515
+
516
+ ---
517
+
518
+ ## Group Hover (hoverGroup)
519
+
520
+ Style child elements when parent is hovered:
521
+
522
+ ```tsx
523
+ // Parent with a className
524
+ <Flex className="card-row" gap={2}>
525
+ {/* Child responds to parent hover */}
526
+ <Box
527
+ opacity={0}
528
+ hoverGroup={{ 'card-row': { opacity: 1 } }}
529
+ >
530
+ Actions
531
+ </Box>
532
+ </Flex>
533
+ ```
534
+
535
+ ---
536
+
537
+ ## Server-Side Rendering (SSG/SSR)
538
+
539
+ ```tsx
540
+ import { getStyles, resetStyles } from '@cronocode/react-box/ssg';
541
+
542
+ // After rendering your app, get generated styles
543
+ const cssString = getStyles();
544
+
545
+ // Inject into your HTML
546
+ <style id="crono-box">{cssString}</style>
547
+
548
+ // Reset for next request (in SSR)
549
+ resetStyles();
550
+ ```
551
+
552
+ ---
553
+
554
+ ## Key Reminders for AI Assistants
555
+
556
+ 1. **fontSize uses divider 16**, not 4. `fontSize={14}` → 14px, NOT 3.5px
557
+ 2. **Spacing uses divider 4**. `p={4}` → 16px (1rem)
558
+ 3. **Border width is direct px**. `b={1}` → 1px
559
+ 4. **Colors are Tailwind-like**: `'gray-500'`, `'blue-600'`, etc.
560
+ 5. **Breakpoints are mobile-first**: base → sm → md → lg → xl → xxl
561
+ 6. **Theme styles nest**: `theme={{ dark: { hover: { ... } } }}`
562
+ 7. **Use `tag` prop** to change the HTML element: `<Box tag="button">`
563
+ 8. **HTML attributes go in `props`**: `<Box tag="a" props={{ href: '/link' }}>` - NOT directly as Box props
564
+ 9. **Percentage widths**: Use strings like `width="1/2"` for 50%
565
+ 10. **Full size shortcuts**: `width="fit"` = 100%, `width="fit-screen"` = 100vw
566
+ 11. **Box is memoized** with `React.memo` - props comparison is efficient
567
+
568
+ ---
569
+
570
+ ## Debugging Tips
571
+
572
+ 1. **Inspect styles**: Look for `<style id="crono-box">` in document head
573
+ 2. **Check class names**: Elements get classes like `_b`, `_2a`, etc.
574
+ 3. **Verify variables**: CSS variables are in `:root` rules
575
+ 4. **Theme issues**: Ensure `<Box.Theme>` wraps your app
576
+ 5. **Portal theming**: Tooltips/dropdowns use `#crono-box` container
@@ -0,0 +1,11 @@
1
+ import { default as ColumnModel } from '../models/columnModel';
2
+ import { default as GridModel } from '../models/gridModel';
3
+ interface Props<TRow> {
4
+ column: ColumnModel<TRow>;
5
+ grid: GridModel<TRow>;
6
+ }
7
+ /**
8
+ * Main column filter component that renders the appropriate filter type
9
+ */
10
+ export default function DataGridColumnFilter<TRow>(props: Props<TRow>): import("react/jsx-runtime").JSX.Element | null;
11
+ export {};
@@ -0,0 +1 @@
1
+ export default function DataGridEmptyColumns(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { default as ColumnModel } from '../models/columnModel';
2
+ import { default as GridModel } from '../models/gridModel';
3
+ interface Props<TRow> {
4
+ column: ColumnModel<TRow>;
5
+ grid: GridModel<TRow>;
6
+ }
7
+ export default function DataGridFilterCell<TRow>(props: Props<TRow>): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,6 @@
1
+ import { default as GridModel } from '../models/gridModel';
2
+ interface Props<TRow> {
3
+ grid: GridModel<TRow>;
4
+ }
5
+ export default function DataGridFilterRow<TRow>(props: Props<TRow>): import("react/jsx-runtime").JSX.Element[] | null;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ import { default as GridModel } from '../models/gridModel';
2
+ interface Props<TRow> {
3
+ grid: GridModel<TRow>;
4
+ }
5
+ export default function DataGridGlobalFilter<TRow>(props: Props<TRow>): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -18,6 +18,46 @@ export interface PaginationState {
18
18
  export type Pagination = boolean | {
19
19
  pageSize: number;
20
20
  };
21
+ /** Filter type for column-level filtering */
22
+ export type ColumnFilterType = 'text' | 'number' | 'multiselect';
23
+ /** Text filter configuration (fuzzy search) */
24
+ export interface TextFilterValue {
25
+ type: 'text';
26
+ value: string;
27
+ }
28
+ /** Number filter configuration with comparison operators */
29
+ export interface NumberFilterValue {
30
+ type: 'number';
31
+ operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'between';
32
+ value: number;
33
+ valueTo?: number;
34
+ }
35
+ /** Multi-select filter configuration */
36
+ export interface MultiselectFilterValue {
37
+ type: 'multiselect';
38
+ values: (string | number | boolean | null)[];
39
+ }
40
+ /** Union type for all filter values */
41
+ export type FilterValue = TextFilterValue | NumberFilterValue | MultiselectFilterValue;
42
+ /** Column filters record - maps column key to filter value */
43
+ export type ColumnFilters<TRow> = Partial<Record<keyof TRow | Key, FilterValue>>;
44
+ /** Filter configuration for a column */
45
+ export interface ColumnFilterConfig {
46
+ type: ColumnFilterType;
47
+ /** Placeholder text for input */
48
+ placeholder?: string;
49
+ /** For multiselect: custom options. If not provided, unique values are computed from data */
50
+ options?: {
51
+ label: string;
52
+ value: string | number | boolean | null;
53
+ }[];
54
+ /** For number: step value for input */
55
+ step?: number;
56
+ /** For number: min value */
57
+ min?: number;
58
+ /** For number: max value */
59
+ max?: number;
60
+ }
21
61
  export interface ColumnType<TRow> {
22
62
  key: Key;
23
63
  header?: string;
@@ -28,6 +68,14 @@ export interface ColumnType<TRow> {
28
68
  Cell?: React.ComponentType<{
29
69
  cell: CellModel<TRow>;
30
70
  }>;
71
+ /** Enable filtering for this column. Set to true for default text filter, or provide config */
72
+ filterable?: boolean | ColumnFilterConfig;
73
+ /** Enable sorting for this column. If undefined, inherits from GridDefinition.sortable */
74
+ sortable?: boolean;
75
+ /** Enable resizing for this column. If undefined, inherits from GridDefinition.resizable */
76
+ resizable?: boolean;
77
+ /** If false, column stays fixed at its width and doesn't participate in flex distribution. Default: true */
78
+ flexible?: boolean;
31
79
  }
32
80
  export interface GridDefinition<TRow> {
33
81
  rowKey?: KeysMatching<TRow, Key> | ((rowData: TRow) => Key);
@@ -43,12 +91,32 @@ export interface GridDefinition<TRow> {
43
91
  visibleRowsCount?: number;
44
92
  topBar?: boolean;
45
93
  bottomBar?: boolean;
94
+ /** Title displayed in the top bar */
95
+ title?: React.ReactNode;
96
+ /** Custom filters or actions rendered in the top bar */
97
+ topBarContent?: React.ReactNode;
98
+ /** Enable global filter with fuzzy search */
99
+ globalFilter?: boolean;
100
+ /** Keys of columns to search in global filter. If not provided, all columns are searched */
101
+ globalFilterKeys?: (keyof TRow | Key)[];
102
+ /** Enable sorting for all columns. Default is true. Individual column settings take priority. */
103
+ sortable?: boolean;
104
+ /** Enable resizing for all columns. Default is true. Individual column settings take priority. */
105
+ resizable?: boolean;
46
106
  }
47
107
  export interface DataGridProps<TRow> {
48
108
  data: TRow[];
49
109
  def: GridDefinition<TRow>;
50
110
  loading?: boolean;
51
111
  onSelectionChange?: (event: SelectionChangeEvent<TRow>) => void;
112
+ /** Controlled global filter value */
113
+ globalFilterValue?: string;
114
+ /** Callback when global filter changes */
115
+ onGlobalFilterChange?: (value: string) => void;
116
+ /** Controlled column filters */
117
+ columnFilters?: ColumnFilters<TRow>;
118
+ /** Callback when column filters change */
119
+ onColumnFiltersChange?: (filters: ColumnFilters<TRow>) => void;
52
120
  }
53
121
  interface SelectionChangeEvent<TRow, TKey = TRow[keyof TRow] | number | string> {
54
122
  action: 'select' | 'deselect';