@optilogic/core 1.0.0-beta.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/dist/index.cjs +6003 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2310 -0
  6. package/dist/index.d.ts +2310 -0
  7. package/dist/index.js +5828 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/styles.css +96 -0
  10. package/dist/tailwind-preset.cjs +106 -0
  11. package/dist/tailwind-preset.cjs.map +1 -0
  12. package/dist/tailwind-preset.d.cts +23 -0
  13. package/dist/tailwind-preset.d.ts +23 -0
  14. package/dist/tailwind-preset.js +101 -0
  15. package/dist/tailwind-preset.js.map +1 -0
  16. package/package.json +154 -0
  17. package/src/components/accordion.tsx +187 -0
  18. package/src/components/alert-dialog.tsx +143 -0
  19. package/src/components/autocomplete.tsx +271 -0
  20. package/src/components/badge.tsx +62 -0
  21. package/src/components/button.tsx +85 -0
  22. package/src/components/calendar.tsx +235 -0
  23. package/src/components/card.tsx +94 -0
  24. package/src/components/checkbox.tsx +77 -0
  25. package/src/components/chip.tsx +77 -0
  26. package/src/components/confirmation-modal.tsx +195 -0
  27. package/src/components/context-menu.tsx +406 -0
  28. package/src/components/copy-button.tsx +84 -0
  29. package/src/components/data-grid/DataGrid.tsx +1027 -0
  30. package/src/components/data-grid/components/CellEditor.tsx +346 -0
  31. package/src/components/data-grid/components/FilterPopover.tsx +459 -0
  32. package/src/components/data-grid/components/HeaderCell.tsx +207 -0
  33. package/src/components/data-grid/components/index.ts +14 -0
  34. package/src/components/data-grid/hooks/index.ts +28 -0
  35. package/src/components/data-grid/hooks/useColumnResize.ts +378 -0
  36. package/src/components/data-grid/hooks/useDataGridState.ts +346 -0
  37. package/src/components/data-grid/hooks/useKeyboardNavigation.ts +361 -0
  38. package/src/components/data-grid/index.ts +71 -0
  39. package/src/components/data-grid/types.ts +478 -0
  40. package/src/components/data-grid/utils/dataProcessing.ts +277 -0
  41. package/src/components/data-grid/utils/index.ts +12 -0
  42. package/src/components/date-picker.tsx +366 -0
  43. package/src/components/dropdown-menu.tsx +230 -0
  44. package/src/components/icon-button.tsx +157 -0
  45. package/src/components/input.tsx +40 -0
  46. package/src/components/label.tsx +37 -0
  47. package/src/components/loading-spinner.tsx +113 -0
  48. package/src/components/modal.tsx +207 -0
  49. package/src/components/popover.tsx +62 -0
  50. package/src/components/progress.tsx +41 -0
  51. package/src/components/resizable-panel.tsx +434 -0
  52. package/src/components/resize-handle.tsx +187 -0
  53. package/src/components/select.tsx +160 -0
  54. package/src/components/separator.tsx +50 -0
  55. package/src/components/skeleton.tsx +37 -0
  56. package/src/components/switch.tsx +59 -0
  57. package/src/components/table.tsx +136 -0
  58. package/src/components/tabs.tsx +102 -0
  59. package/src/components/textarea.tsx +36 -0
  60. package/src/components/theme-picker.tsx +245 -0
  61. package/src/components/toaster.tsx +84 -0
  62. package/src/components/tooltip.tsx +199 -0
  63. package/src/index.ts +318 -0
  64. package/src/styles.css +96 -0
  65. package/src/tailwind-preset.ts +129 -0
  66. package/src/theme/index.ts +41 -0
  67. package/src/theme/presets.ts +502 -0
  68. package/src/theme/types.ts +164 -0
  69. package/src/theme/utils.ts +309 -0
  70. package/src/utils/cn.ts +14 -0
@@ -0,0 +1,478 @@
1
+ /**
2
+ * DataGrid Types
3
+ *
4
+ * Enhanced type definitions for the DataGrid component with support for
5
+ * resizable columns, filtering, sorting, cell editing, and keyboard navigation.
6
+ */
7
+
8
+ import * as React from "react";
9
+
10
+ /**
11
+ * Filter operators for different filter types
12
+ */
13
+ export type TextFilterOperator =
14
+ | "contains"
15
+ | "notContains"
16
+ | "equals"
17
+ | "notEquals"
18
+ | "startsWith"
19
+ | "endsWith"
20
+ | "isEmpty"
21
+ | "isNotEmpty";
22
+
23
+ export type NumberFilterOperator =
24
+ | "equals"
25
+ | "notEquals"
26
+ | "gt"
27
+ | "gte"
28
+ | "lt"
29
+ | "lte"
30
+ | "between"
31
+ | "isEmpty"
32
+ | "isNotEmpty";
33
+
34
+ export type DateFilterOperator =
35
+ | "equals"
36
+ | "notEquals"
37
+ | "before"
38
+ | "after"
39
+ | "between"
40
+ | "isEmpty"
41
+ | "isNotEmpty";
42
+
43
+ export type FilterOperator =
44
+ | TextFilterOperator
45
+ | NumberFilterOperator
46
+ | DateFilterOperator;
47
+
48
+ /**
49
+ * Filter type options
50
+ */
51
+ export type FilterType = "text" | "number" | "date" | "select" | "boolean";
52
+
53
+ /**
54
+ * Editor type options
55
+ */
56
+ export type EditorType = "text" | "number" | "date" | "select" | "boolean";
57
+
58
+ /**
59
+ * Option for select-type filters and editors
60
+ */
61
+ export interface SelectOption {
62
+ value: string;
63
+ label: string;
64
+ }
65
+
66
+ /**
67
+ * Represents possible cell values in the DataGrid.
68
+ * Used for filter values, editing values, and cell accessors.
69
+ */
70
+ export type CellValue = string | number | boolean | Date | null | undefined;
71
+
72
+ /**
73
+ * Filter value type - includes array for multi-select filters
74
+ */
75
+ export type FilterValue = CellValue | CellValue[];
76
+
77
+ /**
78
+ * Filter configuration for a single column
79
+ */
80
+ export interface FilterConfig {
81
+ /** Column key this filter applies to */
82
+ columnKey: string;
83
+ /** Filter operator */
84
+ operator: FilterOperator;
85
+ /** Filter value */
86
+ value: FilterValue;
87
+ /** Secondary value for 'between' operator */
88
+ valueTo?: FilterValue;
89
+ }
90
+
91
+ /**
92
+ * Sort configuration for a single column
93
+ */
94
+ export interface SortConfig {
95
+ /** Column key to sort by */
96
+ field: string;
97
+ /** Sort direction */
98
+ direction: "asc" | "desc";
99
+ }
100
+
101
+ /**
102
+ * Focused cell position
103
+ */
104
+ export interface CellPosition {
105
+ /** Row index */
106
+ rowIndex: number;
107
+ /** Column key */
108
+ columnKey: string;
109
+ }
110
+
111
+ /**
112
+ * Cell editing state
113
+ */
114
+ export interface EditingCell extends CellPosition {
115
+ /** Current editing value */
116
+ value: CellValue;
117
+ /** Original value before editing */
118
+ originalValue: CellValue;
119
+ }
120
+
121
+ /**
122
+ * Column definition for the grid
123
+ */
124
+ export interface ColumnDef<T = Record<string, CellValue>> {
125
+ /** Unique key for the column */
126
+ key: string;
127
+ /** Column header (can be string or React node) */
128
+ header: string | React.ReactNode;
129
+ /** Column width (number for px) */
130
+ width?: number;
131
+ /** Minimum column width when resizing */
132
+ minWidth?: number;
133
+ /** Maximum column width when resizing */
134
+ maxWidth?: number;
135
+ /** Custom cell renderer */
136
+ cell?: (row: T, rowIndex: number) => React.ReactNode;
137
+ /** Accessor function to get cell value (defaults to row[key]) */
138
+ accessor?: (row: T) => CellValue;
139
+
140
+ // Sorting
141
+ /** Whether this column is sortable */
142
+ sortable?: boolean;
143
+ /** Custom sort comparator function */
144
+ sortComparator?: (a: T, b: T) => number;
145
+
146
+ // Resizing
147
+ /** Whether this column is resizable (overrides global setting) */
148
+ resizable?: boolean;
149
+
150
+ // Filtering
151
+ /** Whether this column is filterable */
152
+ filterable?: boolean;
153
+ /** Filter type for this column */
154
+ filterType?: FilterType;
155
+ /** Options for select-type filters */
156
+ filterOptions?: SelectOption[];
157
+ /** Custom filter function for uncontrolled filtering */
158
+ filterFn?: (row: T, filterValue: FilterValue, operator: FilterOperator) => boolean;
159
+
160
+ // Editing
161
+ /** Whether this column is editable */
162
+ editable?: boolean;
163
+ /** Editor type for this column */
164
+ editorType?: EditorType;
165
+ /** Options for select-type editors */
166
+ editorOptions?: SelectOption[];
167
+ /** Validator function - returns true if valid, or error message string */
168
+ validator?: (value: CellValue, row: T) => boolean | string;
169
+
170
+ // Visibility
171
+ /** Whether column is hidden */
172
+ hidden?: boolean;
173
+
174
+ // Pinning (future enhancement)
175
+ /** Pin column to left or right */
176
+ pinned?: "left" | "right";
177
+
178
+ // Alignment
179
+ /** Text alignment */
180
+ align?: "left" | "center" | "right";
181
+ }
182
+
183
+ /**
184
+ * Pagination configuration
185
+ */
186
+ export interface PaginationConfig {
187
+ /** Current page (0-indexed) */
188
+ currentPage: number;
189
+ /** Number of rows per page */
190
+ pageSize: number;
191
+ /** Total number of pages */
192
+ totalPages: number;
193
+ /** Total number of items */
194
+ totalItems?: number;
195
+ /** Callback when page changes */
196
+ onPageChange: (page: number) => void;
197
+ /** Callback when page size changes */
198
+ onPageSizeChange: (size: number) => void;
199
+ /** Available page size options */
200
+ pageSizeOptions?: number[];
201
+ /** Show "go to page" input */
202
+ showGoToPage?: boolean;
203
+ }
204
+
205
+ /**
206
+ * Search configuration (global search)
207
+ */
208
+ export interface SearchConfig {
209
+ /** Current search query */
210
+ searchQuery: string;
211
+ /** Callback when search query changes */
212
+ onSearchChange: (query: string) => void;
213
+ /** Search input placeholder */
214
+ placeholder?: string;
215
+ }
216
+
217
+ /**
218
+ * Complete grid state for controlled/uncontrolled modes
219
+ */
220
+ export interface DataGridState {
221
+ /** Current sorting configuration */
222
+ sorting?: SortConfig[];
223
+ /** Current filter configuration */
224
+ filters?: FilterConfig[];
225
+ /** Current column widths */
226
+ columnWidths?: Record<string, number>;
227
+ /** Hidden column keys */
228
+ hiddenColumns?: string[];
229
+ /** Current pagination state (for uncontrolled mode) */
230
+ pagination?: {
231
+ page: number;
232
+ pageSize: number;
233
+ };
234
+ /** Currently focused cell */
235
+ focusedCell?: CellPosition | null;
236
+ /** Currently editing cell */
237
+ editingCell?: EditingCell | null;
238
+ }
239
+
240
+ /**
241
+ * Callback for cell edit events
242
+ */
243
+ export interface CellEditEvent<T = Record<string, CellValue>> {
244
+ /** Row index */
245
+ rowIndex: number;
246
+ /** Column key */
247
+ columnKey: string;
248
+ /** New value */
249
+ newValue: CellValue;
250
+ /** Original value */
251
+ oldValue: CellValue;
252
+ /** The row data */
253
+ row: T;
254
+ }
255
+
256
+ /**
257
+ * DataGrid props
258
+ */
259
+ export interface DataGridProps<T = Record<string, CellValue>> {
260
+ // ============ DATA ============
261
+ /** Data to display in the grid */
262
+ data: T[];
263
+ /** Column definitions */
264
+ columns: ColumnDef<T>[];
265
+ /** Key accessor for row identification */
266
+ getRowKey?: (row: T, index: number) => string;
267
+
268
+ // ============ FEATURE TOGGLES ============
269
+ /** Enable column resizing globally (default: false) */
270
+ resizableColumns?: boolean;
271
+ /** Enable virtualization for large datasets (default: true if data.length > 100) */
272
+ virtualized?: boolean;
273
+ /** Make header sticky (default: true) */
274
+ stickyHeader?: boolean;
275
+ /** Enable hover tooltips for long content (default: true) */
276
+ showTooltips?: boolean;
277
+ /** Minimum cell content length to show tooltip (default: 30) */
278
+ tooltipMinLength?: number;
279
+ /** Show column dividing borders between cells (default: true) */
280
+ showColumnBorders?: boolean;
281
+ /** Enable internal sorting when in uncontrolled mode (default: true) */
282
+ enableInternalSorting?: boolean;
283
+ /** Enable internal filtering when in uncontrolled mode (default: true) */
284
+ enableInternalFiltering?: boolean;
285
+
286
+ // ============ SORTING (Controlled) ============
287
+ /** Current sorting configuration */
288
+ sorting?: SortConfig[];
289
+ /** Callback when sorting changes */
290
+ onSortChange?: (sorting: SortConfig[]) => void;
291
+
292
+ // ============ FILTERING (Controlled) ============
293
+ /** Current filter configuration */
294
+ filters?: FilterConfig[];
295
+ /** Callback when filters change */
296
+ onFilterChange?: (filters: FilterConfig[]) => void;
297
+
298
+ // ============ COLUMN WIDTHS (Controlled) ============
299
+ /** Current column widths */
300
+ columnWidths?: Record<string, number>;
301
+ /** Callback when a column is resized */
302
+ onColumnResize?: (columnKey: string, width: number) => void;
303
+ /** Callback when column resize starts */
304
+ onColumnResizeStart?: (columnKey: string) => void;
305
+ /** Callback when column resize ends */
306
+ onColumnResizeEnd?: (columnKey: string, width: number) => void;
307
+
308
+ // ============ UNCONTROLLED DEFAULTS ============
309
+ /** Default sorting for uncontrolled mode */
310
+ defaultSorting?: SortConfig[];
311
+ /** Default filters for uncontrolled mode */
312
+ defaultFilters?: FilterConfig[];
313
+ /** Default column widths for uncontrolled mode */
314
+ defaultColumnWidths?: Record<string, number>;
315
+
316
+ // ============ STATE CHANGE CALLBACK ============
317
+ /** Callback when any internal state changes (for uncontrolled mode) */
318
+ onStateChange?: (state: DataGridState) => void;
319
+
320
+ // ============ ROW INTERACTIONS ============
321
+ /** Row click handler */
322
+ onRowClick?: (row: T, rowIndex: number) => void;
323
+ /** Row double-click handler */
324
+ onRowDoubleClick?: (row: T, rowIndex: number) => void;
325
+ /** Selected row keys/ids */
326
+ selectedRows?: string[];
327
+ /** Callback when row selection changes */
328
+ onSelectedRowsChange?: (selectedKeys: string[]) => void;
329
+ /** Row class name function */
330
+ rowClassName?: (row: T, rowIndex: number) => string;
331
+
332
+ // ============ CELL EDITING ============
333
+ /** Cell edit handler - called when cell value changes */
334
+ onCellEdit?: (
335
+ rowIndex: number,
336
+ columnKey: string,
337
+ newValue: CellValue,
338
+ oldValue: CellValue
339
+ ) => void;
340
+ /** Callback before cell edit starts - return false to prevent */
341
+ onCellEditStart?: (rowIndex: number, columnKey: string) => boolean | void;
342
+ /** Callback when cell edit is cancelled */
343
+ onCellEditCancel?: (rowIndex: number, columnKey: string) => void;
344
+
345
+ // ============ KEYBOARD NAVIGATION ============
346
+ /** Currently focused cell (controlled) */
347
+ focusedCell?: CellPosition | null;
348
+ /** Callback when focused cell changes */
349
+ onFocusedCellChange?: (cell: CellPosition | null) => void;
350
+ /** Enable keyboard navigation (default: true) */
351
+ enableKeyboardNavigation?: boolean;
352
+
353
+ // ============ PAGINATION ============
354
+ /** Pagination configuration */
355
+ pagination?: PaginationConfig;
356
+
357
+ // ============ SEARCH ============
358
+ /** Search configuration */
359
+ search?: SearchConfig;
360
+
361
+ // ============ LOADING & EMPTY STATES ============
362
+ /** Loading state */
363
+ loading?: boolean;
364
+ /** Custom loading component */
365
+ loadingComponent?: React.ReactNode;
366
+ /** Empty state message */
367
+ emptyMessage?: string;
368
+ /** Custom empty state component */
369
+ emptyComponent?: React.ReactNode;
370
+
371
+ // ============ STYLING ============
372
+ /** Additional class name for container */
373
+ className?: string;
374
+ /** Additional class name for table */
375
+ tableClassName?: string;
376
+
377
+ // ============ INFINITE SCROLL ============
378
+ /** Enable infinite scroll mode */
379
+ infiniteScroll?: boolean;
380
+ /** Callback when more data should be loaded */
381
+ onLoadMore?: () => void;
382
+ /** Whether more data is available */
383
+ hasMore?: boolean;
384
+ /** Whether currently loading more data */
385
+ loadingMore?: boolean;
386
+ }
387
+
388
+ /**
389
+ * Internal state for the DataGrid
390
+ */
391
+ export interface DataGridInternalState {
392
+ sorting: SortConfig[];
393
+ filters: FilterConfig[];
394
+ columnWidths: Record<string, number>;
395
+ focusedCell: CellPosition | null;
396
+ editingCell: EditingCell | null;
397
+ }
398
+
399
+ /**
400
+ * Context for DataGrid sub-components
401
+ */
402
+ export interface DataGridContextValue<T = Record<string, CellValue>> {
403
+ // Data
404
+ data: T[];
405
+ columns: ColumnDef<T>[];
406
+ getRowKey: (row: T, index: number) => string;
407
+
408
+ // State
409
+ state: DataGridInternalState;
410
+
411
+ // Actions
412
+ setFocusedCell: (cell: CellPosition | null) => void;
413
+ startEditing: (rowIndex: number, columnKey: string) => void;
414
+ commitEdit: (value: CellValue) => void;
415
+ cancelEdit: () => void;
416
+ updateColumnWidth: (columnKey: string, width: number) => void;
417
+ updateSorting: (sorting: SortConfig[]) => void;
418
+ updateFilters: (filters: FilterConfig[]) => void;
419
+
420
+ // Feature flags
421
+ resizableColumns: boolean;
422
+ enableKeyboardNavigation: boolean;
423
+ }
424
+
425
+ /**
426
+ * Props for HeaderCell component
427
+ */
428
+ export interface HeaderCellProps<T = Record<string, CellValue>> {
429
+ column: ColumnDef<T>;
430
+ columnIndex: number;
431
+ width: number;
432
+ sorting?: SortConfig;
433
+ filter?: FilterConfig;
434
+ isResizable: boolean;
435
+ onSort?: () => void;
436
+ onFilterChange?: (filter: FilterConfig | null) => void;
437
+ onResize?: (width: number) => void;
438
+ onResizeStart?: () => void;
439
+ onResizeEnd?: (width: number) => void;
440
+ }
441
+
442
+ /**
443
+ * Props for FilterPopover component
444
+ */
445
+ export interface FilterPopoverProps {
446
+ column: ColumnDef;
447
+ filter?: FilterConfig;
448
+ onFilterChange: (filter: FilterConfig | null) => void;
449
+ }
450
+
451
+ /**
452
+ * Props for CellEditor component
453
+ */
454
+ export interface CellEditorProps<T = Record<string, CellValue>> {
455
+ column: ColumnDef<T>;
456
+ value: CellValue;
457
+ row: T;
458
+ rowIndex: number;
459
+ onCommit: (value: CellValue) => void;
460
+ onCancel: () => void;
461
+ }
462
+
463
+ /**
464
+ * Props for GridCell component
465
+ */
466
+ export interface GridCellProps<T = Record<string, CellValue>> {
467
+ column: ColumnDef<T>;
468
+ row: T;
469
+ rowIndex: number;
470
+ columnIndex: number;
471
+ width: number;
472
+ isEditing: boolean;
473
+ isFocused: boolean;
474
+ onStartEdit: () => void;
475
+ onCommitEdit: (value: CellValue) => void;
476
+ onCancelEdit: () => void;
477
+ onFocus: () => void;
478
+ }