@box-kite/react 0.0.1 → 1.0.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.
- package/.claude/rules/box-kite-rules.md +43 -0
- package/.claude/skills/box-kite/SKILL.md +431 -0
- package/BOX_AI_CONTEXT.md +1833 -0
- package/BOX_KITE_AI_CONTEXT.md +1833 -0
- package/LICENSE +21 -0
- package/README.md +710 -7
- package/a11y.cjs +1 -0
- package/a11y.d.ts +15 -0
- package/a11y.mjs +3 -0
- package/behavior.cjs +1 -0
- package/behavior.mjs +295 -0
- package/box.cjs +1 -0
- package/box.d.ts +46 -0
- package/box.mjs +23 -0
- package/client.cjs +1 -0
- package/client.mjs +163 -0
- package/components/baseSvg.cjs +1 -0
- package/components/baseSvg.d.ts +5 -0
- package/components/baseSvg.mjs +21 -0
- package/components/button.cjs +1 -0
- package/components/button.d.ts +16 -0
- package/components/button.mjs +19 -0
- package/components/chart.cjs +1 -0
- package/components/chart.d.ts +82 -0
- package/components/chart.mjs +261 -0
- package/components/checkbox.cjs +1 -0
- package/components/checkbox.d.ts +28 -0
- package/components/checkbox.mjs +38 -0
- package/components/dataGrid/components/dataGridBody.d.ts +7 -0
- package/components/dataGrid/components/dataGridBottomBar.d.ts +6 -0
- package/components/dataGrid/components/dataGridCell.d.ts +15 -0
- package/components/dataGrid/components/dataGridCellRowDetail.d.ts +6 -0
- package/components/dataGrid/components/dataGridCellRowSelection.d.ts +6 -0
- package/components/dataGrid/components/dataGridCellText.d.ts +6 -0
- package/components/dataGrid/components/dataGridColumnFilter.d.ts +9 -0
- package/components/dataGrid/components/dataGridColumnGroups.d.ts +7 -0
- package/components/dataGrid/components/dataGridContent.d.ts +6 -0
- package/components/dataGrid/components/dataGridDetailRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridEmptyColumns.d.ts +6 -0
- package/components/dataGrid/components/dataGridFilterCell.d.ts +11 -0
- package/components/dataGrid/components/dataGridFilterRow.d.ts +6 -0
- package/components/dataGrid/components/dataGridGlobalFilter.d.ts +6 -0
- package/components/dataGrid/components/dataGridGroupRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridHeader.d.ts +6 -0
- package/components/dataGrid/components/dataGridHeaderCell.d.ts +9 -0
- package/components/dataGrid/components/dataGridHeaderCellContextMenu.d.ts +11 -0
- package/components/dataGrid/components/dataGridHeaderCellResizer.d.ts +14 -0
- package/components/dataGrid/components/dataGridLoader.d.ts +11 -0
- package/components/dataGrid/components/dataGridPagination.d.ts +6 -0
- package/components/dataGrid/components/dataGridRow.d.ts +8 -0
- package/components/dataGrid/components/dataGridTopBar.d.ts +6 -0
- package/components/dataGrid/components/dataGridTopBarContextMenu.d.ts +6 -0
- package/components/dataGrid/contracts/dataGridContract.d.ts +213 -0
- package/components/dataGrid/gridNavigationContext.d.ts +24 -0
- package/components/dataGrid/models/cellModel.d.ts +18 -0
- package/components/dataGrid/models/columnModel.d.ts +150 -0
- package/components/dataGrid/models/columnVisibilityModel.d.ts +24 -0
- package/components/dataGrid/models/detailRowModel.d.ts +22 -0
- package/components/dataGrid/models/filterModel.d.ts +22 -0
- package/components/dataGrid/models/gridModel.d.ts +206 -0
- package/components/dataGrid/models/groupRowCellModel.d.ts +26 -0
- package/components/dataGrid/models/groupRowModel.d.ts +48 -0
- package/components/dataGrid/models/headerCellModel.d.ts +83 -0
- package/components/dataGrid/models/paginationModel.d.ts +32 -0
- package/components/dataGrid/models/rowModel.d.ts +34 -0
- package/components/dataGrid/models/viewportModel.d.ts +44 -0
- package/components/dataGrid/useGrid.d.ts +8 -0
- package/components/dataGrid/useGridNavigation.d.ts +21 -0
- package/components/dataGrid.cjs +1 -0
- package/components/dataGrid.d.ts +2 -0
- package/components/dataGrid.mjs +3178 -0
- package/components/dropdown/dropdownContext.d.ts +44 -0
- package/components/dropdown/dropdownItems.d.ts +22 -0
- package/components/dropdown/dropdownRowRenderer.d.ts +8 -0
- package/components/dropdown/dropdownSearch.d.ts +21 -0
- package/components/dropdown/utils.d.ts +1 -0
- package/components/dropdown.cjs +1 -0
- package/components/dropdown.d.ts +47 -0
- package/components/dropdown.mjs +479 -0
- package/components/flex.cjs +1 -0
- package/components/flex.d.ts +6 -0
- package/components/flex.mjs +16 -0
- package/components/form.cjs +1 -0
- package/components/form.d.ts +10 -0
- package/components/form.mjs +58 -0
- package/components/grid.cjs +1 -0
- package/components/grid.d.ts +6 -0
- package/components/grid.mjs +16 -0
- package/components/icon.cjs +1 -0
- package/components/icon.d.ts +36 -0
- package/components/icon.mjs +41 -0
- package/components/overlay.cjs +1 -0
- package/components/overlay.d.ts +43 -0
- package/components/overlay.mjs +82 -0
- package/components/presence.cjs +1 -0
- package/components/presence.d.ts +30 -0
- package/components/presence.mjs +11 -0
- package/components/radioButton.cjs +1 -0
- package/components/radioButton.d.ts +24 -0
- package/components/radioButton.mjs +32 -0
- package/components/radioGroup.cjs +1 -0
- package/components/radioGroup.d.ts +38 -0
- package/components/radioGroup.mjs +79 -0
- package/components/select.cjs +1 -0
- package/components/select.d.ts +42 -0
- package/components/select.mjs +36 -0
- package/components/semantics.cjs +1 -0
- package/components/semantics.d.ts +34 -0
- package/components/semantics.mjs +17 -0
- package/components/svg.cjs +1 -0
- package/components/svg.d.ts +63 -0
- package/components/svg.mjs +141 -0
- package/components/switch.cjs +1 -0
- package/components/switch.d.ts +20 -0
- package/components/switch.mjs +25 -0
- package/components/textarea.cjs +1 -0
- package/components/textarea.d.ts +27 -0
- package/components/textarea.mjs +33 -0
- package/components/textbox.cjs +1 -0
- package/components/textbox.d.ts +26 -0
- package/components/textbox.mjs +33 -0
- package/components/tooltip.cjs +1 -0
- package/components/tooltip.d.ts +63 -0
- package/components/tooltip.mjs +108 -0
- package/components/visuallyHidden.cjs +1 -0
- package/components/visuallyHidden.d.ts +6 -0
- package/components/visuallyHidden.mjs +23 -0
- package/effects.cjs +1 -0
- package/effects.mjs +6 -0
- package/forms.cjs +1 -0
- package/forms.mjs +21 -0
- package/icons/dotsIcon.d.ts +2 -0
- package/icons/expandIcon.d.ts +2 -0
- package/icons/groupingIcon.d.ts +2 -0
- package/icons/pinIcon.d.ts +2 -0
- package/icons/searchIcon.d.ts +2 -0
- package/icons/sortIcon.d.ts +2 -0
- package/motion.cjs +1 -0
- package/motion.mjs +66 -0
- package/package.json +203 -7
- package/platform.cjs +1 -0
- package/platform.mjs +32 -0
- package/react/a11y/callbacks.d.ts +12 -0
- package/react/a11y/useControllableState.d.ts +25 -0
- package/react/a11y/useDismiss.d.ts +25 -0
- package/react/a11y/useFocusReturn.d.ts +18 -0
- package/react/a11y/useIdentifier.d.ts +17 -0
- package/react/a11y/useRovingFocus.d.ts +84 -0
- package/react/animation/usePresence.d.ts +32 -0
- package/react/boxClassNames.d.ts +25 -0
- package/react/boxProps.d.ts +49 -0
- package/react/boxTagProps.d.ts +7 -0
- package/react/clientRuntime.d.ts +11 -0
- package/react/effects.d.ts +10 -0
- package/react/forms/labelledControl.d.ts +17 -0
- package/react/forms/placeholderProp.d.ts +13 -0
- package/react/hooks/usePortalContainer.d.ts +1 -0
- package/react/hooks/useVirtualization.d.ts +43 -0
- package/react/hooks/useVisibility.d.ts +9 -0
- package/react/reactTypes.d.ts +10 -0
- package/react/resolveStyles.d.ts +18 -0
- package/react/styleElements.d.ts +3 -0
- package/react/svg/attributesInProps.d.ts +4 -0
- package/react/svg/svgNaming.d.ts +15 -0
- package/react/theme/theme.d.ts +26 -0
- package/react/theme/themeContext.d.ts +7 -0
- package/react/useStyles.d.ts +22 -0
- package/react-shared.cjs +1 -0
- package/react-shared.mjs +105 -0
- package/rolldown-runtime.cjs +1 -0
- package/rsc.cjs +1 -0
- package/rsc.d.ts +27 -0
- package/rsc.mjs +18 -0
- package/ssg.cjs +1 -0
- package/ssg.d.ts +24 -0
- package/ssg.mjs +25 -0
- package/utils/animation/animationUtils.d.ts +29 -0
- package/utils/array/arrayUtils.d.ts +15 -0
- package/utils/box/boxUtils.d.ts +5 -0
- package/utils/chart/chartUtils.d.ts +98 -0
- package/utils/dom/domUtils.d.ts +26 -0
- package/utils/environment/environmentUtils.d.ts +18 -0
- package/utils/fn/fnUtils.d.ts +4 -0
- package/utils/form/formUtils.d.ts +8 -0
- package/utils/memo.d.ts +10 -0
- package/utils/object/objectUtils.d.ts +13 -0
- package/utils/string/fuzzySearch.d.ts +27 -0
- package/utils/string/stringUtils.d.ts +4 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { ComponentsAndVariants } from '../../../types';
|
|
2
|
+
import { ColumnFilters, DataGridProps, FilterValue, Key, PaginationState, PinPositionInput, SortDirection } from '../contracts/dataGridContract';
|
|
3
|
+
import { default as ColumnModel } from './columnModel';
|
|
4
|
+
import { default as ColumnVisibilityModel } from './columnVisibilityModel';
|
|
5
|
+
import { default as DetailRowModel } from './detailRowModel';
|
|
6
|
+
import { default as FilterModel } from './filterModel';
|
|
7
|
+
import { default as GroupRowModel } from './groupRowModel';
|
|
8
|
+
import { default as PaginationModel } from './paginationModel';
|
|
9
|
+
import { default as RowModel } from './rowModel';
|
|
10
|
+
import { default as ViewportModel } from './viewportModel';
|
|
11
|
+
export declare const ROW_NUMBER_CELL_KEY: Key;
|
|
12
|
+
export declare const DEFAULT_ROW_NUMBER_COLUMN_WIDTH = 70;
|
|
13
|
+
export declare const ROW_SELECTION_CELL_KEY: Key;
|
|
14
|
+
export declare const GROUPING_CELL_KEY: Key;
|
|
15
|
+
export declare const ROW_DETAIL_CELL_KEY: Key;
|
|
16
|
+
export default class GridModel<TRow> {
|
|
17
|
+
props: DataGridProps<TRow>;
|
|
18
|
+
constructor(props: DataGridProps<TRow>, onChange?: () => void);
|
|
19
|
+
private _version;
|
|
20
|
+
private readonly listeners;
|
|
21
|
+
/** Subscribe to changes; returns an unsubscribe function. */
|
|
22
|
+
subscribe: (listener: () => void) => (() => void);
|
|
23
|
+
/** Monotonic snapshot version — stable between changes, increments on notify(). */
|
|
24
|
+
getSnapshot: () => number;
|
|
25
|
+
/** Signal subscribers that state changed and a re-render is needed. */
|
|
26
|
+
notify: () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Sync incoming props. Called during render by the framework adapter — clears
|
|
29
|
+
* the affected memos but does NOT notify (no extra render cycle; memos recompute
|
|
30
|
+
* lazily on next access).
|
|
31
|
+
*/
|
|
32
|
+
setProps(props: DataGridProps<TRow>): void;
|
|
33
|
+
get componentName(): keyof ComponentsAndVariants;
|
|
34
|
+
private _identifier;
|
|
35
|
+
/**
|
|
36
|
+
* A unique prefix for the ids this grid wires ARIA with. Supplied by the adapter, because only
|
|
37
|
+
* the adapter can produce one that survives hydration — `useIdentifier` in React's case.
|
|
38
|
+
*/
|
|
39
|
+
get identifier(): string;
|
|
40
|
+
setIdentifier(identifier: string): void;
|
|
41
|
+
/** The title's id: a grid is not named by the rows in it, so it is named by this. */
|
|
42
|
+
get titleId(): string;
|
|
43
|
+
get resizerStyle(): 'visible' | 'hover' | 'hidden';
|
|
44
|
+
get resizeMode(): 'smooth' | 'instant';
|
|
45
|
+
readonly sourceColumns: import('../../../utils/memo').Memo<ColumnModel<TRow>[]>;
|
|
46
|
+
readonly columns: import('../../../utils/memo').Memo<{
|
|
47
|
+
start: ColumnModel<TRow>[];
|
|
48
|
+
middle: ColumnModel<TRow>[];
|
|
49
|
+
end: ColumnModel<TRow>[];
|
|
50
|
+
flat: ColumnModel<TRow>[];
|
|
51
|
+
leafs: ColumnModel<TRow>[];
|
|
52
|
+
visibleLeafs: ColumnModel<TRow>[];
|
|
53
|
+
userVisibleLeafs: ColumnModel<TRow>[];
|
|
54
|
+
maxDeath: number;
|
|
55
|
+
}>;
|
|
56
|
+
readonly headerRows: import('../../../utils/memo').Memo<ColumnModel<TRow>[][]>;
|
|
57
|
+
readonly gridTemplateColumns: import('../../../utils/memo').Memo<string>;
|
|
58
|
+
private _globalFilterValue;
|
|
59
|
+
get globalFilterValue(): string;
|
|
60
|
+
private _columnFilters;
|
|
61
|
+
get columnFilters(): ColumnFilters<TRow>;
|
|
62
|
+
/**
|
|
63
|
+
* Apply global filter (fuzzy search across all or specified columns)
|
|
64
|
+
*/
|
|
65
|
+
private applyGlobalFilter;
|
|
66
|
+
/**
|
|
67
|
+
* Apply column-level filters
|
|
68
|
+
*/
|
|
69
|
+
private applyColumnFilters;
|
|
70
|
+
/**
|
|
71
|
+
* Check if a cell value matches a filter
|
|
72
|
+
*/
|
|
73
|
+
private matchesFilter;
|
|
74
|
+
/**
|
|
75
|
+
* Apply external predicate filters from the filters prop
|
|
76
|
+
*/
|
|
77
|
+
private applyExternalFilters;
|
|
78
|
+
/**
|
|
79
|
+
* Get filtered data (applies external, global, then column filters)
|
|
80
|
+
*/
|
|
81
|
+
get filteredData(): TRow[];
|
|
82
|
+
private fireServerStateChange;
|
|
83
|
+
/**
|
|
84
|
+
* Set global filter value
|
|
85
|
+
*/
|
|
86
|
+
setGlobalFilter: (value: string) => void;
|
|
87
|
+
/**
|
|
88
|
+
* Set a single column filter
|
|
89
|
+
*/
|
|
90
|
+
setColumnFilter: (columnKey: Key, filter: FilterValue | undefined) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Clear all column filters
|
|
93
|
+
*/
|
|
94
|
+
clearColumnFilters: () => void;
|
|
95
|
+
/**
|
|
96
|
+
* Clear all filters (global + column)
|
|
97
|
+
*/
|
|
98
|
+
clearAllFilters: () => void;
|
|
99
|
+
/**
|
|
100
|
+
* Get unique values for a column (used for multiselect filter options)
|
|
101
|
+
*/
|
|
102
|
+
getColumnUniqueValues: (columnKey: Key) => (string | number | boolean | null)[];
|
|
103
|
+
/**
|
|
104
|
+
* Check if any filter is active
|
|
105
|
+
*/
|
|
106
|
+
get hasActiveFilters(): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Get count of filtered rows vs total rows
|
|
109
|
+
*/
|
|
110
|
+
get filterStats(): {
|
|
111
|
+
filtered: number;
|
|
112
|
+
total: number;
|
|
113
|
+
};
|
|
114
|
+
readonly rows: import('../../../utils/memo').Memo<GroupRowModel<TRow>[] | RowModel<TRow>[]>;
|
|
115
|
+
readonly flatRows: import('../../../utils/memo').Memo<(GroupRowModel<TRow> | RowModel<TRow> | DetailRowModel<TRow>)[]>;
|
|
116
|
+
get rowHeight(): number;
|
|
117
|
+
readonly sizes: import('../../../utils/memo').Memo<Record<string, string>>;
|
|
118
|
+
private _containerWidth;
|
|
119
|
+
get containerWidth(): number;
|
|
120
|
+
/**
|
|
121
|
+
* The DOM element that carries the column-sizing CSS variables (the grid container).
|
|
122
|
+
* Set by the React adapter. During a resize drag the adapter writes the width vars
|
|
123
|
+
* here directly — bypassing React re-renders — and only commits to state on release.
|
|
124
|
+
*/
|
|
125
|
+
private _sizingElement;
|
|
126
|
+
get sizingElement(): HTMLElement | null;
|
|
127
|
+
setSizingElement: (el: HTMLElement | null) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Which way the grid reads, resolved off the element the widths are written to. A model with no
|
|
130
|
+
* element yet — a server render, a headless host — reads as left to right, the initial value.
|
|
131
|
+
*/
|
|
132
|
+
get isRtl(): boolean;
|
|
133
|
+
setContainerWidth: (width: number) => void;
|
|
134
|
+
readonly flexWidths: import('../../../utils/memo').Memo<Record<Key, number>>;
|
|
135
|
+
getFlexWidth(key: Key): number | undefined;
|
|
136
|
+
readonly DEFAULT_ROW_HEIGHT_PX = 48;
|
|
137
|
+
readonly MIN_COLUMN_WIDTH_PX = 48;
|
|
138
|
+
readonly DEFAULT_COLUMN_WIDTH_PX = 200;
|
|
139
|
+
expandedGroupRow: Set<Key>;
|
|
140
|
+
private _expandedDetailRows;
|
|
141
|
+
get expandedDetailRows(): Set<Key>;
|
|
142
|
+
toggleDetailRow: (rowKey: Key) => void;
|
|
143
|
+
private _page;
|
|
144
|
+
private _pageSize?;
|
|
145
|
+
get page(): number;
|
|
146
|
+
get pageSize(): number;
|
|
147
|
+
get pageSizeOptions(): number[] | undefined;
|
|
148
|
+
get isPaginated(): boolean;
|
|
149
|
+
get paginationState(): PaginationState | undefined;
|
|
150
|
+
changePage: (page: number) => void;
|
|
151
|
+
changePageSize: (size: number) => void;
|
|
152
|
+
readonly rowOffsets: import('../../../utils/memo').Memo<{
|
|
153
|
+
offsets: number[];
|
|
154
|
+
totalHeight: number;
|
|
155
|
+
}>;
|
|
156
|
+
/** Headless virtualization (windowing math; scrollTop is owned by the adapter). */
|
|
157
|
+
readonly viewport: ViewportModel<TRow>;
|
|
158
|
+
/** Backs the top-bar column-visibility menu. */
|
|
159
|
+
readonly columnVisibility: ColumnVisibilityModel<TRow>;
|
|
160
|
+
/** Filtering concern (grid-level state + derived flags). */
|
|
161
|
+
readonly filter: FilterModel<TRow>;
|
|
162
|
+
/** Pagination concern (navigation + row-range derivations). */
|
|
163
|
+
readonly pagination: PaginationModel<TRow>;
|
|
164
|
+
/** Whether any user-facing column is currently visible (else the empty-columns state shows). */
|
|
165
|
+
get hasVisibleColumns(): boolean;
|
|
166
|
+
get isEmpty(): boolean;
|
|
167
|
+
/** Header select-all checkbox state. */
|
|
168
|
+
get allRowsSelected(): boolean;
|
|
169
|
+
get someRowsSelected(): boolean;
|
|
170
|
+
private _selectionAnnounced;
|
|
171
|
+
/**
|
|
172
|
+
* What the grid's live region says. Ticking a checkbox halfway down a virtualized grid changes nothing a
|
|
173
|
+
* screen reader would read, so the count is announced instead — and it stays empty until a selection has
|
|
174
|
+
* happened, since some readers announce a region that already holds text on mount.
|
|
175
|
+
*/
|
|
176
|
+
get selectionAnnouncement(): string;
|
|
177
|
+
/** The columns currently grouped, resolved from groupColumns keys (backs the top-bar group chips). */
|
|
178
|
+
get groupedColumns(): ColumnModel<TRow>[];
|
|
179
|
+
selectedRows: Set<Key>;
|
|
180
|
+
get inlineStartEdge(): number;
|
|
181
|
+
get inlineEndEdge(): number;
|
|
182
|
+
readonly inlineStartEdgeVarName = "--inline-start-edge";
|
|
183
|
+
readonly rowHeightVarName = "--row-height";
|
|
184
|
+
readonly viewportWidthVarName = "--viewport-width";
|
|
185
|
+
private readonly _idMap;
|
|
186
|
+
private _autoId;
|
|
187
|
+
private readonly _idFactory;
|
|
188
|
+
getRowKey(row: TRow): Key;
|
|
189
|
+
setSortColumn: (columnKey: Key, sortDirection?: SortDirection) => void;
|
|
190
|
+
pinColumn: (uniqueKey: string, pin?: PinPositionInput) => void;
|
|
191
|
+
toggleGrouping: (columnKey: Key) => void;
|
|
192
|
+
unGroupAll: () => void;
|
|
193
|
+
toggleGroupRow: (groupRowKey: Key) => void;
|
|
194
|
+
toggleRowSelection: (rowKey: Key) => void;
|
|
195
|
+
toggleRowsSelection: (rowKeys: Key[]) => void;
|
|
196
|
+
toggleSelectAllRows: () => void;
|
|
197
|
+
toggleColumnVisibility: (columnKey: Key) => void;
|
|
198
|
+
setWidth: (columnKey: Key, width: number) => void;
|
|
199
|
+
groupColumns: Set<Key>;
|
|
200
|
+
hiddenColumns: Set<Key>;
|
|
201
|
+
columnWidths: Map<Key, number>;
|
|
202
|
+
private _sortColumn?;
|
|
203
|
+
get sortColumn(): Key | undefined;
|
|
204
|
+
private _sortDirection?;
|
|
205
|
+
get sortDirection(): SortDirection | undefined;
|
|
206
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { default as ColumnModel } from './columnModel';
|
|
2
|
+
import { default as GridModel } from './gridModel';
|
|
3
|
+
import { default as GroupRowModel } from './groupRowModel';
|
|
4
|
+
/**
|
|
5
|
+
* How a cell participates in a group row's layout: `grouping` is the expand/label cell spanning the
|
|
6
|
+
* grouped columns, `selection` the select-all cell, `spacer` a pinned or leading cell with its own value,
|
|
7
|
+
* and `hidden` a data column absorbed into the grouping cell's span.
|
|
8
|
+
*/
|
|
9
|
+
export type GroupRowCellKind = 'grouping' | 'selection' | 'spacer' | 'hidden';
|
|
10
|
+
export default class GroupRowCellModel<TRow> {
|
|
11
|
+
readonly grid: GridModel<TRow>;
|
|
12
|
+
readonly row: GroupRowModel<TRow>;
|
|
13
|
+
readonly column: ColumnModel<TRow>;
|
|
14
|
+
constructor(grid: GridModel<TRow>, row: GroupRowModel<TRow>, column: ColumnModel<TRow>);
|
|
15
|
+
get value(): string | number | null;
|
|
16
|
+
get isExpanded(): boolean;
|
|
17
|
+
get isFirst(): boolean;
|
|
18
|
+
get isLast(): boolean;
|
|
19
|
+
get cellKind(): GroupRowCellKind;
|
|
20
|
+
get depthPadding(): number;
|
|
21
|
+
get gridColumnSpan(): number;
|
|
22
|
+
get widthVar(): string;
|
|
23
|
+
get isEndPinned(): boolean;
|
|
24
|
+
/** Grouping cell shows a right border only when the grouping column is left-pinned. */
|
|
25
|
+
get hasGroupingBorder(): boolean;
|
|
26
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Key } from '../contracts/dataGridContract';
|
|
2
|
+
import { default as ColumnModel } from './columnModel';
|
|
3
|
+
import { default as DetailRowModel } from './detailRowModel';
|
|
4
|
+
import { default as GridModel } from './gridModel';
|
|
5
|
+
import { default as GroupRowCellModel } from './groupRowCellModel';
|
|
6
|
+
import { default as RowModel } from './rowModel';
|
|
7
|
+
export default class GroupRowModel<TRow> {
|
|
8
|
+
readonly grid: GridModel<TRow>;
|
|
9
|
+
readonly groupColumn: ColumnModel<TRow>;
|
|
10
|
+
readonly rows: RowModel<TRow>[] | GroupRowModel<TRow>[];
|
|
11
|
+
readonly rowIndex: number;
|
|
12
|
+
readonly groupValue: Key;
|
|
13
|
+
constructor(grid: GridModel<TRow>, groupColumn: ColumnModel<TRow>, rows: RowModel<TRow>[] | GroupRowModel<TRow>[], rowIndex: number, groupValue: Key);
|
|
14
|
+
get key(): Key;
|
|
15
|
+
parentRow?: GroupRowModel<TRow>;
|
|
16
|
+
private readonly _cells;
|
|
17
|
+
get cells(): GroupRowCellModel<TRow>[];
|
|
18
|
+
/**
|
|
19
|
+
* The cells this row actually renders, each with the column it starts at. A `hidden` cell is a
|
|
20
|
+
* data column the grouping cell has absorbed into its span: no element, and nothing to navigate
|
|
21
|
+
* to — which is why a group row's cell positions and its `aria-colindex` values differ.
|
|
22
|
+
*/
|
|
23
|
+
private readonly _renderedCells;
|
|
24
|
+
get renderedCells(): {
|
|
25
|
+
cell: GroupRowCellModel<TRow>;
|
|
26
|
+
columnIndex: number;
|
|
27
|
+
}[];
|
|
28
|
+
/** Fewer than the column count — the width the grid navigation sees for this row. */
|
|
29
|
+
get cellCount(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Where a cell starts in column-index space. The cells the grouping cell spans are not rendered
|
|
32
|
+
* at all, so an ordinal here is short of its column by however many of them came before it.
|
|
33
|
+
*/
|
|
34
|
+
columnOf(cell: number): number;
|
|
35
|
+
get selected(): boolean;
|
|
36
|
+
get indeterminate(): boolean;
|
|
37
|
+
get expanded(): boolean;
|
|
38
|
+
get depth(): number;
|
|
39
|
+
get count(): number;
|
|
40
|
+
get flatRows(): (RowModel<TRow> | GroupRowModel<TRow> | DetailRowModel<TRow>)[];
|
|
41
|
+
get allRows(): RowModel<TRow>[];
|
|
42
|
+
get groupingColumn(): ColumnModel<TRow>;
|
|
43
|
+
get groupingColumnGridColumn(): number;
|
|
44
|
+
readonly kind: "group";
|
|
45
|
+
toggleRow(): void;
|
|
46
|
+
/** Select/deselect every leaf row under this group. */
|
|
47
|
+
toggleSelectAll: () => void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { SortDirection } from '../contracts/dataGridContract';
|
|
2
|
+
import { default as ColumnModel } from './columnModel';
|
|
3
|
+
/** All derived state for rendering a column's header cell and its context menu. */
|
|
4
|
+
export default class HeaderCellModel<TRow> {
|
|
5
|
+
readonly column: ColumnModel<TRow>;
|
|
6
|
+
constructor(column: ColumnModel<TRow>);
|
|
7
|
+
private get grid();
|
|
8
|
+
/** Header label. `null` for the row-number and selection cells (rendered specially). */
|
|
9
|
+
get label(): string | number | null;
|
|
10
|
+
/**
|
|
11
|
+
* A name for a header that draws nothing. The row-number and row-detail columns are blank on
|
|
12
|
+
* screen by design, and a blank column header leaves every cell under it unlabelled — which is
|
|
13
|
+
* the one thing a screen reader relies on when it reads a cell out.
|
|
14
|
+
*/
|
|
15
|
+
get hiddenLabel(): string | undefined;
|
|
16
|
+
get isSortable(): boolean;
|
|
17
|
+
get isSorted(): boolean;
|
|
18
|
+
get sortDirection(): SortDirection | undefined;
|
|
19
|
+
get showResizer(): boolean;
|
|
20
|
+
get showContextMenu(): boolean;
|
|
21
|
+
/** Grid column span: a leaf occupies one column, a group header spans its leaf count. */
|
|
22
|
+
get gridColumn(): number;
|
|
23
|
+
/** 1-based `aria-colindex`: the first column this header covers. */
|
|
24
|
+
get columnIndex(): number;
|
|
25
|
+
/** `aria-colspan`, left off when the header covers a single column. */
|
|
26
|
+
get columnSpan(): number | undefined;
|
|
27
|
+
/** `aria-rowspan`: a leaf declared above the deepest level reaches down to the bottom row. */
|
|
28
|
+
get rowSpan(): number | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* `aria-sort`. A sortable column that is not the sorted one still carries `none`: that is what
|
|
31
|
+
* tells a screen reader the column *can* be sorted, and leaving it off says the opposite.
|
|
32
|
+
*/
|
|
33
|
+
get ariaSort(): 'ascending' | 'descending' | 'none' | undefined;
|
|
34
|
+
/** What the resizer names itself. A separator carries no text, so it has nothing else to go on. */
|
|
35
|
+
get resizerLabel(): string;
|
|
36
|
+
/** `aria-valuenow`: how wide the column is right now, in px. */
|
|
37
|
+
get width(): number;
|
|
38
|
+
/** `aria-valuemin`: every leaf the header covers at the narrowest the grid allows. */
|
|
39
|
+
get minWidth(): number;
|
|
40
|
+
/**
|
|
41
|
+
* `aria-valuemax`. There is no width the grid refuses — a drag can take a column past the
|
|
42
|
+
* viewport and scroll to it — so the ceiling the keyboard offers is the grid's own width, raised
|
|
43
|
+
* to whatever a drag has already made it so that `aria-valuenow` stays inside the range.
|
|
44
|
+
*/
|
|
45
|
+
get maxWidth(): number;
|
|
46
|
+
/** Room for the sort icon, which sits where the reading ends — so an end-aligned header needs it in front. */
|
|
47
|
+
get paddingStart(): number | undefined;
|
|
48
|
+
get paddingEnd(): number | undefined;
|
|
49
|
+
/** Variant flags for the header cell. */
|
|
50
|
+
get variant(): {
|
|
51
|
+
isPinned: boolean;
|
|
52
|
+
isFirstStartPinned: boolean;
|
|
53
|
+
isLastStartPinned: boolean;
|
|
54
|
+
isFirstEndPinned: boolean;
|
|
55
|
+
isLastEndPinned: boolean;
|
|
56
|
+
isSortable: boolean;
|
|
57
|
+
isRowNumber: boolean;
|
|
58
|
+
isFirstLeaf: boolean;
|
|
59
|
+
isLastLeaf: boolean;
|
|
60
|
+
};
|
|
61
|
+
/** Variant flags for the context-menu trigger button. */
|
|
62
|
+
get contextMenuButtonVariant(): {
|
|
63
|
+
isPinned: boolean;
|
|
64
|
+
isFirstStartPinned: boolean;
|
|
65
|
+
isLastStartPinned: boolean;
|
|
66
|
+
isFirstEndPinned: boolean;
|
|
67
|
+
isLastEndPinned: boolean;
|
|
68
|
+
isSortable: boolean;
|
|
69
|
+
isRowNumber: boolean;
|
|
70
|
+
};
|
|
71
|
+
private get sections();
|
|
72
|
+
get canSortAsc(): boolean;
|
|
73
|
+
get canSortDesc(): boolean;
|
|
74
|
+
get canClearSort(): boolean;
|
|
75
|
+
get canPinStart(): boolean;
|
|
76
|
+
get canPinEnd(): boolean;
|
|
77
|
+
get canUnpin(): boolean;
|
|
78
|
+
get canGroupBy(): boolean;
|
|
79
|
+
get canUnGroupAll(): boolean;
|
|
80
|
+
get hasSortSection(): boolean;
|
|
81
|
+
get hasPinSection(): boolean;
|
|
82
|
+
get hasGroupSection(): boolean;
|
|
83
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PaginationState } from '../contracts/dataGridContract';
|
|
2
|
+
import { default as GridModel } from './gridModel';
|
|
3
|
+
/**
|
|
4
|
+
* Pagination concern: navigation state + derived row range for the bottom bar / pager.
|
|
5
|
+
* The coupled mutations (page-reset on filter/sort, server-state events) live on GridModel;
|
|
6
|
+
* this model owns the navigation behavior and derivations the UI needs.
|
|
7
|
+
*/
|
|
8
|
+
export default class PaginationModel<TRow> {
|
|
9
|
+
readonly grid: GridModel<TRow>;
|
|
10
|
+
constructor(grid: GridModel<TRow>);
|
|
11
|
+
get isPaginated(): boolean;
|
|
12
|
+
get state(): PaginationState | undefined;
|
|
13
|
+
get pageSizeOptions(): number[] | undefined;
|
|
14
|
+
get page(): number;
|
|
15
|
+
get pageSize(): number;
|
|
16
|
+
get totalPages(): number;
|
|
17
|
+
get totalItems(): number;
|
|
18
|
+
get canGoPrev(): boolean;
|
|
19
|
+
get canGoNext(): boolean;
|
|
20
|
+
/** 1-based index of the first row on the current page. */
|
|
21
|
+
get startItem(): number;
|
|
22
|
+
/** 1-based index of the last row on the current page (clamped to totalItems). */
|
|
23
|
+
get endItem(): number;
|
|
24
|
+
changePage: (page: number) => void;
|
|
25
|
+
changePageSize: (size: number) => void;
|
|
26
|
+
firstPage: () => void;
|
|
27
|
+
prevPage: () => void;
|
|
28
|
+
nextPage: () => void;
|
|
29
|
+
lastPage: () => void;
|
|
30
|
+
/** Parse a raw page-jump input and navigate (clamped to [1, totalPages]); ignores non-numeric input. */
|
|
31
|
+
jumpToPage: (raw: string) => void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Key } from '../contracts/dataGridContract';
|
|
2
|
+
import { default as CellModel } from './cellModel';
|
|
3
|
+
import { default as DetailRowModel } from './detailRowModel';
|
|
4
|
+
import { default as GridModel } from './gridModel';
|
|
5
|
+
import { default as GroupRowModel } from './groupRowModel';
|
|
6
|
+
export default class RowModel<TRow> {
|
|
7
|
+
readonly grid: GridModel<TRow>;
|
|
8
|
+
readonly data: TRow;
|
|
9
|
+
readonly rowIndex: number;
|
|
10
|
+
constructor(grid: GridModel<TRow>, data: TRow, rowIndex: number);
|
|
11
|
+
private _key?;
|
|
12
|
+
/**
|
|
13
|
+
* Resolved lazily: getRowKey() can call crypto.randomUUID(), so building a model for every
|
|
14
|
+
* row would generate a key for thousands of off-screen rows. Only rows that actually render
|
|
15
|
+
* (or are otherwise inspected) pay the cost. getRowKey itself is idempotent per row.
|
|
16
|
+
*/
|
|
17
|
+
get key(): Key;
|
|
18
|
+
parentRow?: GroupRowModel<TRow>;
|
|
19
|
+
readonly count = 1;
|
|
20
|
+
readonly kind: "row";
|
|
21
|
+
/** Whether clicking the row toggles its detail panel. */
|
|
22
|
+
get expandOnRowClick(): boolean;
|
|
23
|
+
toggleDetail: () => void;
|
|
24
|
+
private readonly _cells;
|
|
25
|
+
get cells(): CellModel<TRow>[];
|
|
26
|
+
/** One cell per visible column — the width the grid navigation sees for this row. */
|
|
27
|
+
get cellCount(): number;
|
|
28
|
+
/** Where a cell starts in column-index space: one cell per column, so its own ordinal. */
|
|
29
|
+
columnOf(cell: number): number;
|
|
30
|
+
get selected(): boolean;
|
|
31
|
+
get expanded(): boolean;
|
|
32
|
+
get flatRows(): (RowModel<TRow> | DetailRowModel<TRow>)[];
|
|
33
|
+
get allRows(): this;
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { default as GridModel } from './gridModel';
|
|
2
|
+
/** Windowing parameters for the virtualized body. Rows are sliced by the adapter from these. */
|
|
3
|
+
export interface ViewportWindow {
|
|
4
|
+
/** Index of the first row to render. */
|
|
5
|
+
startIndex: number;
|
|
6
|
+
/** Number of rows to render starting at `startIndex`. */
|
|
7
|
+
take: number;
|
|
8
|
+
/** Pixel offset to translate the rendered slice down to its scroll position. */
|
|
9
|
+
translateY: number;
|
|
10
|
+
/** Total scrollable height of all rows. */
|
|
11
|
+
totalHeight: number;
|
|
12
|
+
/** Fixed viewport height, or undefined when rendering all rows. */
|
|
13
|
+
viewHeight: number | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Headless virtualization: given a scrollTop, computes which rows are visible and how
|
|
17
|
+
* to position them. Pure math — `scrollTop` is owned by the adapter (so scrolling does
|
|
18
|
+
* not notify the store / re-render the whole grid).
|
|
19
|
+
*/
|
|
20
|
+
export default class ViewportModel<TRow> {
|
|
21
|
+
readonly grid: GridModel<TRow>;
|
|
22
|
+
static readonly DEFAULT_VISIBLE_ROWS_COUNT = 10;
|
|
23
|
+
static readonly ROWS_TO_PRELOAD = 20;
|
|
24
|
+
constructor(grid: GridModel<TRow>);
|
|
25
|
+
get showAll(): boolean;
|
|
26
|
+
get hasDetailRows(): boolean;
|
|
27
|
+
get isEmpty(): boolean;
|
|
28
|
+
/** Number of rows the viewport shows at once (all rows when `visibleRowsCount === 'all'`). */
|
|
29
|
+
get visibleRowsCount(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Rows a PageUp/PageDown moves. Deliberately not `visibleRowsCount`, which is every row when
|
|
32
|
+
* `visibleRowsCount === 'all'` — a Page key that jumps to the end of the grid is the End key.
|
|
33
|
+
*/
|
|
34
|
+
get pageRows(): number;
|
|
35
|
+
get viewHeight(): number | undefined;
|
|
36
|
+
get totalHeight(): number;
|
|
37
|
+
/** Height to reserve for the empty/no-data state. */
|
|
38
|
+
get emptyHeight(): number;
|
|
39
|
+
/** Where a row sits inside the scrolled body — what a keyboard jump scrolls to. */
|
|
40
|
+
rowTop(index: number): number;
|
|
41
|
+
/** Binary search for the first row whose offset is <= scrollTop (variable-height rows). */
|
|
42
|
+
private findStartIndex;
|
|
43
|
+
window(scrollTop: number): ViewportWindow;
|
|
44
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DataGridProps } from './contracts/dataGridContract';
|
|
2
|
+
import { default as GridModel } from './models/gridModel';
|
|
3
|
+
/**
|
|
4
|
+
* React binding for the headless GridModel store: the model owns all state and behaviour, React only
|
|
5
|
+
* subscribes. `setProps` syncs incoming props during render, and `useSyncExternalStore` re-renders
|
|
6
|
+
* whenever the model notifies.
|
|
7
|
+
*/
|
|
8
|
+
export default function useGrid<TRow>(props: DataGridProps<TRow>): GridModel<TRow>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GridNavigation } from './gridNavigationContext';
|
|
2
|
+
import { default as GridModel } from './models/gridModel';
|
|
3
|
+
export interface GridNavigationOptions<TRow> {
|
|
4
|
+
grid: GridModel<TRow>;
|
|
5
|
+
/** The scrolling element — a jump to a row outside the rendered window has to scroll first. */
|
|
6
|
+
scrollerRef: React.RefObject<HTMLElement | null>;
|
|
7
|
+
scrollTop: number;
|
|
8
|
+
onScrollTo: (top: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface GridNavigator extends GridNavigation {
|
|
11
|
+
/** Put this on the `role="grid"` element: cell keystrokes bubble to it. */
|
|
12
|
+
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* APG's grid pattern over a virtualized body. Focus lives on the cells, one in the tab order at a time,
|
|
16
|
+
* and `useRovingFocus` owns which; what belongs here is what virtualization adds — a jump to a row nobody
|
|
17
|
+
* has scrolled to has no element to focus, so the move scrolls, waits for the render it caused, and
|
|
18
|
+
* focuses from a layout effect. Inside a cell the grid steps back: the widget keeps every key, and Enter
|
|
19
|
+
* or F2 got focus there while Escape takes it out.
|
|
20
|
+
*/
|
|
21
|
+
export default function useGridNavigation<TRow>(options: GridNavigationOptions<TRow>): GridNavigator;
|