@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.
- package/BOX_AI_CONTEXT.md +576 -0
- package/components/dataGrid/components/dataGridColumnFilter.d.ts +11 -0
- package/components/dataGrid/components/dataGridEmptyColumns.d.ts +1 -0
- package/components/dataGrid/components/dataGridFilterCell.d.ts +8 -0
- package/components/dataGrid/components/dataGridFilterRow.d.ts +6 -0
- package/components/dataGrid/components/dataGridGlobalFilter.d.ts +6 -0
- package/components/dataGrid/contracts/dataGridContract.d.ts +68 -0
- package/components/dataGrid/models/columnModel.d.ts +11 -0
- package/components/dataGrid/models/gridModel.d.ts +59 -2
- package/components/dataGrid.cjs +1 -1
- package/components/dataGrid.mjs +891 -314
- package/components/dropdown.cjs +1 -1
- package/components/dropdown.d.ts +4 -1
- package/components/dropdown.mjs +156 -147
- package/components/form.mjs +1 -1
- package/components/semantics.d.ts +25 -25
- package/components/semantics.mjs +5 -5
- package/components/textbox.cjs +1 -1
- package/components/textbox.d.ts +2 -2
- package/components/textbox.mjs +5 -4
- package/components/tooltip.cjs +1 -1
- package/components/tooltip.d.ts +4 -0
- package/components/tooltip.mjs +45 -41
- package/core/boxStyles.d.ts +65 -31
- package/core/extends/boxComponents.d.ts +660 -159
- package/core/variables.d.ts +25 -1
- package/core.cjs +3 -7
- package/core.mjs +1399 -693
- package/hooks/useVirtualization.d.ts +43 -0
- package/package.json +8 -5
- package/ssg.cjs +1 -1
- package/ssg.mjs +28 -20
- package/types.d.ts +5 -4
- package/utils/string/fuzzySearch.d.ts +27 -0
|
@@ -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 {};
|
|
@@ -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';
|