@lovett/ui 0.0.1
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/README.md +28 -0
- package/package.json +53 -0
- package/src/accordion.tsx +153 -0
- package/src/atoms.tsx +197 -0
- package/src/badge.tsx +91 -0
- package/src/brand-logo-tile.tsx +200 -0
- package/src/bulk-action-bar.tsx +104 -0
- package/src/button-group.tsx +46 -0
- package/src/button.tsx +93 -0
- package/src/calculator-shell-v2.tsx +380 -0
- package/src/calculator-shell.tsx +310 -0
- package/src/card.tsx +369 -0
- package/src/checkbox.tsx +114 -0
- package/src/chip-nav.tsx +347 -0
- package/src/choropleth.tsx +62 -0
- package/src/code-block.tsx +235 -0
- package/src/completion-ring.tsx +119 -0
- package/src/copy-field.tsx +169 -0
- package/src/data-grid/column-options-menu.tsx +127 -0
- package/src/data-grid/data-grid.tsx +391 -0
- package/src/data-grid/drawer-panel.tsx +146 -0
- package/src/data-grid/index.ts +29 -0
- package/src/data-grid/sortable-parts.tsx +215 -0
- package/src/data-grid/table-body.tsx +238 -0
- package/src/data-grid/table-elements.tsx +135 -0
- package/src/data-grid/table-header.tsx +95 -0
- package/src/data-grid/table-overlays.tsx +78 -0
- package/src/data-grid/table-parts.tsx +15 -0
- package/src/data-grid/table-summary-footer.tsx +101 -0
- package/src/data-grid/table-view.tsx +176 -0
- package/src/data-grid/types.ts +141 -0
- package/src/data-grid/use-grid-columns.ts +311 -0
- package/src/data-grid/use-grid-editing.ts +154 -0
- package/src/device-frame.tsx +274 -0
- package/src/dropdown-button.tsx +221 -0
- package/src/dropdown-menu.tsx +450 -0
- package/src/empty-state.tsx +85 -0
- package/src/file-upload/file-drop-zone.tsx +156 -0
- package/src/file-upload/file-preview-grid.tsx +39 -0
- package/src/file-upload/file-preview-item.tsx +175 -0
- package/src/file-upload/file-thumbnail.tsx +98 -0
- package/src/file-upload/file-upload-button.tsx +95 -0
- package/src/file-upload/index.ts +13 -0
- package/src/file-upload/use-file-upload.ts +371 -0
- package/src/filter-bar.tsx +125 -0
- package/src/filter-dropdown.tsx +289 -0
- package/src/floating-drawer.tsx +420 -0
- package/src/folder-card.tsx +188 -0
- package/src/folder-tree-picker.tsx +511 -0
- package/src/format.ts +117 -0
- package/src/frame-stack.tsx +73 -0
- package/src/hero-form-card.tsx +471 -0
- package/src/index.ts +372 -0
- package/src/input.tsx +130 -0
- package/src/kbd.tsx +41 -0
- package/src/lib/layout.ts +22 -0
- package/src/lib/utils.ts +6 -0
- package/src/markdown.tsx +214 -0
- package/src/menu-button.tsx +142 -0
- package/src/meta-previews/CreativeMedia.tsx +119 -0
- package/src/meta-previews/InstagramExplorePreview.tsx +340 -0
- package/src/meta-previews/InstagramFeedCarousel.tsx +245 -0
- package/src/meta-previews/InstagramFeedPreview.tsx +259 -0
- package/src/meta-previews/MetaFeedCarousel.tsx +228 -0
- package/src/meta-previews/MetaFeedPreview.tsx +294 -0
- package/src/meta-previews/MetaInstreamPreview.tsx +135 -0
- package/src/meta-previews/MetaMessengerPreview.tsx +795 -0
- package/src/meta-previews/MetaReelPreview.tsx +750 -0
- package/src/meta-previews/MetaRightColumnPreview.tsx +245 -0
- package/src/meta-previews/MetaSearchPreview.tsx +113 -0
- package/src/meta-previews/MetaStoryPreview.tsx +1132 -0
- package/src/meta-previews/ProfileAvatar.tsx +79 -0
- package/src/meta-previews/defaults.ts +27 -0
- package/src/meta-previews/index.ts +37 -0
- package/src/meta-previews/types.ts +219 -0
- package/src/metric-card.tsx +117 -0
- package/src/modal.tsx +131 -0
- package/src/option-tile.tsx +252 -0
- package/src/page-hero.tsx +78 -0
- package/src/page-shell.tsx +440 -0
- package/src/pagination.tsx +86 -0
- package/src/pill-button.tsx +103 -0
- package/src/profile-section.tsx +389 -0
- package/src/progress-bar.tsx +84 -0
- package/src/radio.tsx +172 -0
- package/src/range-slider.tsx +161 -0
- package/src/resizable.tsx +282 -0
- package/src/search-bar.tsx +81 -0
- package/src/segmented-pill.tsx +143 -0
- package/src/shell.tsx +464 -0
- package/src/slider.tsx +107 -0
- package/src/sortable-table.tsx +198 -0
- package/src/sortable.tsx +137 -0
- package/src/stat-row.tsx +132 -0
- package/src/stats-grid.tsx +38 -0
- package/src/step-loader.tsx +141 -0
- package/src/styles.css +562 -0
- package/src/tabs.tsx +143 -0
- package/src/tag-chip-input.tsx +394 -0
- package/src/textarea.tsx +39 -0
- package/src/toast.tsx +59 -0
- package/src/tokens.css +579 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataGridDragOverlay + DataGridDropIndicator — visual chrome that
|
|
3
|
+
* renders during column drag-reorder.
|
|
4
|
+
*
|
|
5
|
+
* Ported 2026-05-18 from gray-ui-csm
|
|
6
|
+
* https://github.com/Jason-uxui/gray-ui-csm/blob/baf8346ac0c1160282e0b173de1bffc594d9c9c3/components/data-grid/table-overlays.tsx
|
|
7
|
+
* License: MIT (see packages/ui/licenses/gray-ui-csm-LICENSE.txt)
|
|
8
|
+
* Workspace ADR: ADR-025
|
|
9
|
+
*
|
|
10
|
+
* BRING_WITH_REFACTOR: token reskin to workspace vocabulary per
|
|
11
|
+
* ADR-025 D7.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { DataGridColumn } from './types'
|
|
15
|
+
|
|
16
|
+
type DataGridDragOverlayProps<ColumnId extends string> = {
|
|
17
|
+
dragOverlayColumn: DataGridColumn<ColumnId> | null
|
|
18
|
+
columnWidths: Record<ColumnId, number>
|
|
19
|
+
dragOverlayHeight: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function DataGridDragOverlay<ColumnId extends string>({
|
|
23
|
+
dragOverlayColumn,
|
|
24
|
+
columnWidths,
|
|
25
|
+
dragOverlayHeight,
|
|
26
|
+
}: DataGridDragOverlayProps<ColumnId>) {
|
|
27
|
+
if (!dragOverlayColumn) return null
|
|
28
|
+
|
|
29
|
+
const Icon = dragOverlayColumn.icon
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
className="pointer-events-none rounded-[var(--radius-md)]"
|
|
34
|
+
style={{
|
|
35
|
+
width: columnWidths[dragOverlayColumn.id],
|
|
36
|
+
height: dragOverlayHeight,
|
|
37
|
+
border: '1px solid rgb(var(--border))',
|
|
38
|
+
background: 'rgb(var(--bg-card))',
|
|
39
|
+
boxShadow: 'var(--shadow-lg, 0 10px 32px rgba(0,0,0,0.18))',
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
42
|
+
<div
|
|
43
|
+
className="flex h-8 items-center gap-1.5 px-2 text-xs font-medium"
|
|
44
|
+
style={{
|
|
45
|
+
borderBottom: '1px solid rgb(var(--border))',
|
|
46
|
+
color: 'rgb(var(--foreground))',
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<Icon className="h-3.5 w-3.5 shrink-0" />
|
|
50
|
+
<span className="truncate">{dragOverlayColumn.label}</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type DataGridDropIndicatorProps = {
|
|
57
|
+
dropIndicatorLeft: number | null
|
|
58
|
+
dragTableRect: { top: number; height: number } | null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function DataGridDropIndicator({
|
|
62
|
+
dropIndicatorLeft,
|
|
63
|
+
dragTableRect,
|
|
64
|
+
}: DataGridDropIndicatorProps) {
|
|
65
|
+
if (dropIndicatorLeft === null || !dragTableRect) return null
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
className="pointer-events-none fixed z-50 w-0.5"
|
|
70
|
+
style={{
|
|
71
|
+
left: dropIndicatorLeft - 1,
|
|
72
|
+
top: dragTableRect.top,
|
|
73
|
+
height: dragTableRect.height,
|
|
74
|
+
background: 'rgb(var(--accent))',
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export aggregator for the DataGrid's table sub-components.
|
|
3
|
+
*
|
|
4
|
+
* Ported 2026-05-18 from gray-ui-csm
|
|
5
|
+
* https://github.com/Jason-uxui/gray-ui-csm/blob/baf8346ac0c1160282e0b173de1bffc594d9c9c3/components/data-grid/table-parts.tsx
|
|
6
|
+
* License: MIT (see packages/ui/licenses/gray-ui-csm-LICENSE.txt)
|
|
7
|
+
* Workspace ADR: ADR-025
|
|
8
|
+
*
|
|
9
|
+
* BRING_AS_IS: re-exports only — relative-path adjustments only.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export { DataGridTableHeader } from './table-header'
|
|
13
|
+
export { DataGridTableBody } from './table-body'
|
|
14
|
+
export { DataGridSummaryFooter } from './table-summary-footer'
|
|
15
|
+
export { DataGridDragOverlay, DataGridDropIndicator } from './table-overlays'
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataGridSummaryFooter — optional sum-style row beneath the body.
|
|
3
|
+
*
|
|
4
|
+
* Ported 2026-05-18 from gray-ui-csm
|
|
5
|
+
* https://github.com/Jason-uxui/gray-ui-csm/blob/baf8346ac0c1160282e0b173de1bffc594d9c9c3/components/data-grid/table-summary-footer.tsx
|
|
6
|
+
* License: MIT (see packages/ui/licenses/gray-ui-csm-LICENSE.txt)
|
|
7
|
+
* Workspace ADR: ADR-025
|
|
8
|
+
*
|
|
9
|
+
* BRING_WITH_REFACTOR: token reskin per ADR-025 D7.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { CSSProperties, ReactNode } from 'react'
|
|
13
|
+
|
|
14
|
+
import { cn } from '../lib/utils'
|
|
15
|
+
import { TableCell, TableFooter, TableRow } from './table-elements'
|
|
16
|
+
|
|
17
|
+
import type { DataGridColumn, DataGridRowBase } from './types'
|
|
18
|
+
|
|
19
|
+
type DataGridSummaryFooterProps<
|
|
20
|
+
Row extends DataGridRowBase,
|
|
21
|
+
ColumnId extends string,
|
|
22
|
+
> = {
|
|
23
|
+
showSummaries: boolean
|
|
24
|
+
stickySummaryFooter: boolean
|
|
25
|
+
renderSummary:
|
|
26
|
+
| ((
|
|
27
|
+
column: DataGridColumn<ColumnId>,
|
|
28
|
+
visibleRows: Row[],
|
|
29
|
+
) => ReactNode)
|
|
30
|
+
| undefined
|
|
31
|
+
visibleColumns: DataGridColumn<ColumnId>[]
|
|
32
|
+
visibleRows: Row[]
|
|
33
|
+
columnWidths: Record<ColumnId, number>
|
|
34
|
+
draggingColumnId: ColumnId | null
|
|
35
|
+
isEmptyValue: (value: ReactNode) => boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function DataGridSummaryFooter<
|
|
39
|
+
Row extends DataGridRowBase,
|
|
40
|
+
ColumnId extends string,
|
|
41
|
+
>({
|
|
42
|
+
showSummaries,
|
|
43
|
+
stickySummaryFooter,
|
|
44
|
+
renderSummary,
|
|
45
|
+
visibleColumns,
|
|
46
|
+
visibleRows,
|
|
47
|
+
columnWidths,
|
|
48
|
+
draggingColumnId,
|
|
49
|
+
isEmptyValue,
|
|
50
|
+
}: DataGridSummaryFooterProps<Row, ColumnId>) {
|
|
51
|
+
if (!showSummaries || !renderSummary) return null
|
|
52
|
+
|
|
53
|
+
const stickyCellStyle: CSSProperties | undefined = stickySummaryFooter
|
|
54
|
+
? {
|
|
55
|
+
position: 'sticky',
|
|
56
|
+
bottom: 0,
|
|
57
|
+
zIndex: 10,
|
|
58
|
+
background: 'rgb(var(--bg-card))',
|
|
59
|
+
borderTop: '1px solid rgb(var(--border))',
|
|
60
|
+
}
|
|
61
|
+
: undefined
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<TableFooter>
|
|
65
|
+
<TableRow className="hover:bg-transparent">
|
|
66
|
+
<TableCell
|
|
67
|
+
className={cn('h-10 px-2 py-1')}
|
|
68
|
+
style={{
|
|
69
|
+
borderRight: '1px solid rgb(var(--border))',
|
|
70
|
+
...stickyCellStyle,
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
73
|
+
{visibleColumns.map((column) => {
|
|
74
|
+
const summaryContent = renderSummary(column, visibleRows)
|
|
75
|
+
const isDraggingThisColumn = draggingColumnId === column.id
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<TableCell
|
|
79
|
+
key={`summary-${column.id}`}
|
|
80
|
+
className={cn('h-10 px-2 py-1 text-left text-xs whitespace-nowrap')}
|
|
81
|
+
style={{
|
|
82
|
+
width: columnWidths[column.id],
|
|
83
|
+
minWidth: columnWidths[column.id],
|
|
84
|
+
color: 'rgb(var(--text-muted))',
|
|
85
|
+
borderRight: '1px solid rgb(var(--border))',
|
|
86
|
+
background: isDraggingThisColumn
|
|
87
|
+
? 'rgb(var(--surface-overlay-soft))'
|
|
88
|
+
: stickyCellStyle?.background,
|
|
89
|
+
...stickyCellStyle,
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{!isEmptyValue(summaryContent) ? (
|
|
93
|
+
<span className="inline-block">{summaryContent}</span>
|
|
94
|
+
) : null}
|
|
95
|
+
</TableCell>
|
|
96
|
+
)
|
|
97
|
+
})}
|
|
98
|
+
</TableRow>
|
|
99
|
+
</TableFooter>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataGridTableView — composes Header + Body + SummaryFooter inside
|
|
3
|
+
* a single <Table>.
|
|
4
|
+
*
|
|
5
|
+
* Ported 2026-05-18 from gray-ui-csm
|
|
6
|
+
* https://github.com/Jason-uxui/gray-ui-csm/blob/baf8346ac0c1160282e0b173de1bffc594d9c9c3/components/data-grid/table-view.tsx
|
|
7
|
+
* License: MIT (see packages/ui/licenses/gray-ui-csm-LICENSE.txt)
|
|
8
|
+
* Workspace ADR: ADR-025
|
|
9
|
+
*
|
|
10
|
+
* BRING_WITH_REFACTOR:
|
|
11
|
+
* • Table sub-component imported from local table-elements (DEV-1)
|
|
12
|
+
* • No additional styling beyond what the sub-components carry
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
KeyboardEvent as ReactKeyboardEvent,
|
|
17
|
+
PointerEvent as ReactPointerEvent,
|
|
18
|
+
ReactNode,
|
|
19
|
+
RefObject,
|
|
20
|
+
} from 'react'
|
|
21
|
+
|
|
22
|
+
import { Table } from './table-elements'
|
|
23
|
+
import {
|
|
24
|
+
DataGridSummaryFooter,
|
|
25
|
+
DataGridTableBody,
|
|
26
|
+
DataGridTableHeader,
|
|
27
|
+
} from './table-parts'
|
|
28
|
+
import type {
|
|
29
|
+
DataGridColumn,
|
|
30
|
+
DataGridRowBase,
|
|
31
|
+
DataGridSortState,
|
|
32
|
+
EditingCell,
|
|
33
|
+
} from './types'
|
|
34
|
+
|
|
35
|
+
type DataGridTableViewProps<
|
|
36
|
+
Row extends DataGridRowBase,
|
|
37
|
+
ColumnId extends string,
|
|
38
|
+
> = {
|
|
39
|
+
tableRef: RefObject<HTMLTableElement | null>
|
|
40
|
+
gridMinWidth: number
|
|
41
|
+
visibleColumns: DataGridColumn<ColumnId>[]
|
|
42
|
+
columnWidths: Record<ColumnId, number>
|
|
43
|
+
visibleRows: Row[]
|
|
44
|
+
getRowLabel: (row: Row) => string
|
|
45
|
+
editingCell: EditingCell<ColumnId> | null
|
|
46
|
+
isEditableColumn: (columnId: ColumnId) => boolean
|
|
47
|
+
startEditing: (row: Row, columnId: ColumnId) => void
|
|
48
|
+
onCellKeyDown: (
|
|
49
|
+
event: ReactKeyboardEvent<HTMLTableCellElement>,
|
|
50
|
+
row: Row,
|
|
51
|
+
rowIndex: number,
|
|
52
|
+
column: DataGridColumn<ColumnId>,
|
|
53
|
+
colIndex: number,
|
|
54
|
+
) => void
|
|
55
|
+
inputRef: RefObject<HTMLInputElement | null>
|
|
56
|
+
draftValue: string
|
|
57
|
+
setDraftValue: (value: string) => void
|
|
58
|
+
commitEdit: () => void
|
|
59
|
+
cancelEdit: () => void
|
|
60
|
+
canOpenDrawer: (columnId: ColumnId) => boolean
|
|
61
|
+
renderCell: (row: Row, column: DataGridColumn<ColumnId>) => ReactNode
|
|
62
|
+
onOpenDrawer: (cell: EditingCell<ColumnId>) => void
|
|
63
|
+
selectedRowIds: string[]
|
|
64
|
+
allVisibleRowsSelected: boolean
|
|
65
|
+
someVisibleRowsSelected: boolean
|
|
66
|
+
onToggleRowSelection: (rowId: string, checked: boolean) => void
|
|
67
|
+
onToggleAllRows: (checked: boolean) => void
|
|
68
|
+
showSummaries: boolean
|
|
69
|
+
renderSummary:
|
|
70
|
+
| ((
|
|
71
|
+
column: DataGridColumn<ColumnId>,
|
|
72
|
+
visibleRows: Row[],
|
|
73
|
+
) => ReactNode)
|
|
74
|
+
| undefined
|
|
75
|
+
stickySummaryFooter: boolean
|
|
76
|
+
tableContainerClassName: string | undefined
|
|
77
|
+
isEmptyValue: (value: ReactNode) => boolean
|
|
78
|
+
onResizeStart: (
|
|
79
|
+
event: ReactPointerEvent<HTMLButtonElement>,
|
|
80
|
+
columnId: ColumnId,
|
|
81
|
+
) => void
|
|
82
|
+
draggingColumnId: ColumnId | null
|
|
83
|
+
sort: DataGridSortState<ColumnId> | null
|
|
84
|
+
onSortChange: ((columnId: ColumnId) => void) | undefined
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function DataGridTableView<
|
|
88
|
+
Row extends DataGridRowBase,
|
|
89
|
+
ColumnId extends string,
|
|
90
|
+
>({
|
|
91
|
+
tableRef,
|
|
92
|
+
gridMinWidth,
|
|
93
|
+
visibleColumns,
|
|
94
|
+
columnWidths,
|
|
95
|
+
visibleRows,
|
|
96
|
+
getRowLabel,
|
|
97
|
+
editingCell,
|
|
98
|
+
isEditableColumn,
|
|
99
|
+
startEditing,
|
|
100
|
+
onCellKeyDown,
|
|
101
|
+
inputRef,
|
|
102
|
+
draftValue,
|
|
103
|
+
setDraftValue,
|
|
104
|
+
commitEdit,
|
|
105
|
+
cancelEdit,
|
|
106
|
+
canOpenDrawer,
|
|
107
|
+
renderCell,
|
|
108
|
+
onOpenDrawer,
|
|
109
|
+
selectedRowIds,
|
|
110
|
+
allVisibleRowsSelected,
|
|
111
|
+
someVisibleRowsSelected,
|
|
112
|
+
onToggleRowSelection,
|
|
113
|
+
onToggleAllRows,
|
|
114
|
+
showSummaries,
|
|
115
|
+
renderSummary,
|
|
116
|
+
stickySummaryFooter,
|
|
117
|
+
tableContainerClassName,
|
|
118
|
+
isEmptyValue,
|
|
119
|
+
onResizeStart,
|
|
120
|
+
draggingColumnId,
|
|
121
|
+
sort,
|
|
122
|
+
onSortChange,
|
|
123
|
+
}: DataGridTableViewProps<Row, ColumnId>) {
|
|
124
|
+
return (
|
|
125
|
+
<Table
|
|
126
|
+
ref={tableRef}
|
|
127
|
+
className="table-fixed"
|
|
128
|
+
containerClassName={tableContainerClassName}
|
|
129
|
+
style={{ width: `max(100%, ${gridMinWidth}px)` }}
|
|
130
|
+
>
|
|
131
|
+
<DataGridTableHeader
|
|
132
|
+
visibleColumns={visibleColumns}
|
|
133
|
+
columnWidths={columnWidths}
|
|
134
|
+
allVisibleRowsSelected={allVisibleRowsSelected}
|
|
135
|
+
someVisibleRowsSelected={someVisibleRowsSelected}
|
|
136
|
+
onToggleAllRows={onToggleAllRows}
|
|
137
|
+
onResizeStart={onResizeStart}
|
|
138
|
+
sort={sort}
|
|
139
|
+
onSortChange={onSortChange}
|
|
140
|
+
/>
|
|
141
|
+
|
|
142
|
+
<DataGridTableBody
|
|
143
|
+
visibleRows={visibleRows}
|
|
144
|
+
getRowLabel={getRowLabel}
|
|
145
|
+
visibleColumns={visibleColumns}
|
|
146
|
+
editingCell={editingCell}
|
|
147
|
+
isEditableColumn={isEditableColumn}
|
|
148
|
+
startEditing={startEditing}
|
|
149
|
+
onCellKeyDown={onCellKeyDown}
|
|
150
|
+
inputRef={inputRef}
|
|
151
|
+
draftValue={draftValue}
|
|
152
|
+
setDraftValue={setDraftValue}
|
|
153
|
+
commitEdit={commitEdit}
|
|
154
|
+
cancelEdit={cancelEdit}
|
|
155
|
+
canOpenDrawer={canOpenDrawer}
|
|
156
|
+
renderCell={renderCell}
|
|
157
|
+
onOpenDrawer={onOpenDrawer}
|
|
158
|
+
selectedRowIds={selectedRowIds}
|
|
159
|
+
onToggleRowSelection={onToggleRowSelection}
|
|
160
|
+
columnWidths={columnWidths}
|
|
161
|
+
draggingColumnId={draggingColumnId}
|
|
162
|
+
/>
|
|
163
|
+
|
|
164
|
+
<DataGridSummaryFooter
|
|
165
|
+
showSummaries={showSummaries}
|
|
166
|
+
renderSummary={renderSummary}
|
|
167
|
+
stickySummaryFooter={stickySummaryFooter}
|
|
168
|
+
visibleColumns={visibleColumns}
|
|
169
|
+
visibleRows={visibleRows}
|
|
170
|
+
columnWidths={columnWidths}
|
|
171
|
+
draggingColumnId={draggingColumnId}
|
|
172
|
+
isEmptyValue={isEmptyValue}
|
|
173
|
+
/>
|
|
174
|
+
</Table>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataGrid public types.
|
|
3
|
+
*
|
|
4
|
+
* Ported 2026-05-18 from gray-ui-csm
|
|
5
|
+
* https://github.com/Jason-uxui/gray-ui-csm/blob/baf8346ac0c1160282e0b173de1bffc594d9c9c3/components/data-grid/types.ts
|
|
6
|
+
* License: MIT (see packages/ui/licenses/gray-ui-csm-LICENSE.txt)
|
|
7
|
+
* Workspace ADR: ADR-025
|
|
8
|
+
*
|
|
9
|
+
* BRING_AS_IS per ADR-025 bucket table — surface API unchanged from
|
|
10
|
+
* source so the source repo's docs still apply.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { ComponentProps, ComponentType, ReactNode } from 'react'
|
|
14
|
+
import type { DndContext, DragEndEvent } from '@dnd-kit/core'
|
|
15
|
+
|
|
16
|
+
export type DataGridIcon = ComponentType<{
|
|
17
|
+
className?: string
|
|
18
|
+
}>
|
|
19
|
+
|
|
20
|
+
export type DataGridRowBase = {
|
|
21
|
+
id: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DataGridColumn<ColumnId extends string> = {
|
|
25
|
+
id: ColumnId
|
|
26
|
+
label: string
|
|
27
|
+
icon: DataGridIcon
|
|
28
|
+
defaultWidth: number
|
|
29
|
+
minWidth?: number
|
|
30
|
+
/** Per-column sort opt-out (ADR-027). Defaults to true when DataGrid's
|
|
31
|
+
* `onSortChange` is provided; false when not. Set explicitly to disable
|
|
32
|
+
* sorting for columns that don't have a meaningful comparator. */
|
|
33
|
+
sortable?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Row-sort state (ADR-027). DataGrid renders the chevron + ARIA per
|
|
37
|
+
* this state but does NOT sort rows itself — parent passes pre-sorted
|
|
38
|
+
* `rows`. */
|
|
39
|
+
export type DataGridSortState<ColumnId extends string> = {
|
|
40
|
+
columnId: ColumnId
|
|
41
|
+
dir: 'asc' | 'desc'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type DataGridDrawerPanelProps<Row, ColumnId extends string> = {
|
|
45
|
+
drawerRow: Row | null
|
|
46
|
+
drawerRowIndex: number
|
|
47
|
+
drawerRowCount: number
|
|
48
|
+
drawerColumn: DataGridColumn<ColumnId> | null
|
|
49
|
+
drawerCellValue: ReactNode
|
|
50
|
+
getRowLabel: (row: Row) => string
|
|
51
|
+
isEditableColumn: (columnId: ColumnId) => boolean
|
|
52
|
+
isEmptyValue: (value: ReactNode) => boolean
|
|
53
|
+
updateRow: (rowId: string, updater: (row: Row) => Row) => void
|
|
54
|
+
openPreviousRow: () => void
|
|
55
|
+
openNextRow: () => void
|
|
56
|
+
closeDrawer: () => void
|
|
57
|
+
/** Whether the drawer should be visible. The default <DrawerPanel>
|
|
58
|
+
* reads this to drive its <FloatingDrawer isOpen> binding; consumer
|
|
59
|
+
* render-overrides may use it the same way. Added in the workspace
|
|
60
|
+
* port (DEVIATION-5) to remove the `@base-ui/react` context coupling
|
|
61
|
+
* the source relied on. */
|
|
62
|
+
isOpen: boolean
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type DataGridToolbarRenderProps<ColumnId extends string> = {
|
|
66
|
+
visibleRowCount: number
|
|
67
|
+
selectedRowIds: string[]
|
|
68
|
+
selectedRowCount: number
|
|
69
|
+
allVisibleRowsSelected: boolean
|
|
70
|
+
someVisibleRowsSelected: boolean
|
|
71
|
+
onToggleAllRows: (checked: boolean) => void
|
|
72
|
+
clearSelection: () => void
|
|
73
|
+
showSummaries: boolean
|
|
74
|
+
onShowSummariesChange: (next: boolean) => void
|
|
75
|
+
visibleColumns: DataGridColumn<ColumnId>[]
|
|
76
|
+
visibleColumnIds: ColumnId[]
|
|
77
|
+
hiddenColumns: DataGridColumn<ColumnId>[]
|
|
78
|
+
toggleColumnVisibility: (columnId: ColumnId, visible: boolean) => void
|
|
79
|
+
optionsSensors: NonNullable<
|
|
80
|
+
ComponentProps<typeof DndContext>['sensors']
|
|
81
|
+
>
|
|
82
|
+
onOptionColumnDragEnd: (event: DragEndEvent) => void
|
|
83
|
+
optionsDndContextId: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type DataGridProps<
|
|
87
|
+
Row extends DataGridRowBase,
|
|
88
|
+
ColumnId extends string,
|
|
89
|
+
> = {
|
|
90
|
+
rows: Row[]
|
|
91
|
+
columns: DataGridColumn<ColumnId>[]
|
|
92
|
+
getRowLabel: (row: Row) => string
|
|
93
|
+
renderCell: (row: Row, column: DataGridColumn<ColumnId>) => ReactNode
|
|
94
|
+
isEditableColumn: (columnId: ColumnId) => boolean
|
|
95
|
+
getCellEditValue: (row: Row, columnId: ColumnId) => string
|
|
96
|
+
applyCellEdit: (row: Row, columnId: ColumnId, nextValue: string) => Row
|
|
97
|
+
getDrawerCellValue: (row: Row, columnId: ColumnId) => ReactNode
|
|
98
|
+
canOpenDrawer?: (columnId: ColumnId) => boolean
|
|
99
|
+
renderSummary?: (
|
|
100
|
+
column: DataGridColumn<ColumnId>,
|
|
101
|
+
visibleRows: Row[],
|
|
102
|
+
) => ReactNode
|
|
103
|
+
renderDrawerPanel?: (
|
|
104
|
+
props: DataGridDrawerPanelProps<Row, ColumnId>,
|
|
105
|
+
) => ReactNode
|
|
106
|
+
renderToolbar?: (
|
|
107
|
+
props: DataGridToolbarRenderProps<ColumnId>,
|
|
108
|
+
) => ReactNode
|
|
109
|
+
onToolbarPropsChange?: (props: DataGridToolbarRenderProps<ColumnId>) => void
|
|
110
|
+
onOpenDrawerCell?: (cell: EditingCell<ColumnId>) => void
|
|
111
|
+
/** Drawer renders in modal mode (backdrop + Esc + scroll lock).
|
|
112
|
+
* Defaults to `false` per the source's contextless API. */
|
|
113
|
+
drawerModal?: boolean
|
|
114
|
+
/** Pixel width of the drawer panel; passed through to FloatingDrawer.
|
|
115
|
+
* Defaults to 520 (the FloatingDrawer side="right" default). */
|
|
116
|
+
drawerSize?: number
|
|
117
|
+
stickySummaryFooter?: boolean
|
|
118
|
+
fillAvailableHeight?: boolean
|
|
119
|
+
tableContainerClassName?: string
|
|
120
|
+
onRowsChange?: (rows: Row[]) => void
|
|
121
|
+
/** Currently-sorted column + direction (ADR-027). Parent owns the
|
|
122
|
+
* state and passes pre-sorted `rows`. When `null` or omitted, no
|
|
123
|
+
* chevron renders (all columns show the unsorted indicator). */
|
|
124
|
+
sort?: DataGridSortState<ColumnId> | null
|
|
125
|
+
/** Header click handler (ADR-027). Receives the clicked column id;
|
|
126
|
+
* parent decides next direction (typical: toggle if same column,
|
|
127
|
+
* else default to 'asc'). When omitted, headers are non-interactive
|
|
128
|
+
* for sort purposes. Drag-to-reorder still works. */
|
|
129
|
+
onSortChange?: (columnId: ColumnId) => void
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type EditingCell<ColumnId extends string> = {
|
|
133
|
+
rowId: string
|
|
134
|
+
columnId: ColumnId
|
|
135
|
+
originRect?: {
|
|
136
|
+
x: number
|
|
137
|
+
y: number
|
|
138
|
+
width: number
|
|
139
|
+
height: number
|
|
140
|
+
}
|
|
141
|
+
}
|