@contember/bindx-dataview 0.1.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/dist/DataGrid.d.ts +38 -0
- package/dist/DataGrid.d.ts.map +1 -0
- package/dist/DataViewContext.d.ts +39 -0
- package/dist/DataViewContext.d.ts.map +1 -0
- package/dist/DataViewKeyProvider.d.ts +8 -0
- package/dist/DataViewKeyProvider.d.ts.map +1 -0
- package/dist/HasManyDataGrid.d.ts +51 -0
- package/dist/HasManyDataGrid.d.ts.map +1 -0
- package/dist/columnLeaf.d.ts +72 -0
- package/dist/columnLeaf.d.ts.map +1 -0
- package/dist/columnTypes.d.ts +35 -0
- package/dist/columnTypes.d.ts.map +1 -0
- package/dist/columns.d.ts +115 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/contextHooks.d.ts +45 -0
- package/dist/contextHooks.d.ts.map +1 -0
- package/dist/createColumn.d.ts +37 -0
- package/dist/createColumn.d.ts.map +1 -0
- package/dist/createRelationColumn.d.ts +57 -0
- package/dist/createRelationColumn.d.ts.map +1 -0
- package/dist/dataAttribute.d.ts +6 -0
- package/dist/dataAttribute.d.ts.map +1 -0
- package/dist/export.d.ts +46 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/filterComponents.d.ts +127 -0
- package/dist/filterComponents.d.ts.map +1 -0
- package/dist/filterContext.d.ts +10 -0
- package/dist/filterContext.d.ts.map +1 -0
- package/dist/filterHooks.d.ts +74 -0
- package/dist/filterHooks.d.ts.map +1 -0
- package/dist/filterScope.d.ts +54 -0
- package/dist/filterScope.d.ts.map +1 -0
- package/dist/filterWrappers.d.ts +66 -0
- package/dist/filterWrappers.d.ts.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/infiniteLoad.d.ts +32 -0
- package/dist/infiniteLoad.d.ts.map +1 -0
- package/dist/loaderComponents.d.ts +75 -0
- package/dist/loaderComponents.d.ts.map +1 -0
- package/dist/markers.d.ts +36 -0
- package/dist/markers.d.ts.map +1 -0
- package/dist/pagingComponents.d.ts +50 -0
- package/dist/pagingComponents.d.ts.map +1 -0
- package/dist/renderCellValue.d.ts +9 -0
- package/dist/renderCellValue.d.ts.map +1 -0
- package/dist/select/MultiSelect.d.ts +27 -0
- package/dist/select/MultiSelect.d.ts.map +1 -0
- package/dist/select/Select.d.ts +27 -0
- package/dist/select/Select.d.ts.map +1 -0
- package/dist/select/SelectDataView.d.ts +46 -0
- package/dist/select/SelectDataView.d.ts.map +1 -0
- package/dist/select/SelectEachValue.d.ts +20 -0
- package/dist/select/SelectEachValue.d.ts.map +1 -0
- package/dist/select/SelectItemTrigger.d.ts +25 -0
- package/dist/select/SelectItemTrigger.d.ts.map +1 -0
- package/dist/select/SelectOption.d.ts +23 -0
- package/dist/select/SelectOption.d.ts.map +1 -0
- package/dist/select/SelectPlaceholder.d.ts +16 -0
- package/dist/select/SelectPlaceholder.d.ts.map +1 -0
- package/dist/select/index.d.ts +9 -0
- package/dist/select/index.d.ts.map +1 -0
- package/dist/select/selectContext.d.ts +20 -0
- package/dist/select/selectContext.d.ts.map +1 -0
- package/dist/selectionComponents.d.ts +62 -0
- package/dist/selectionComponents.d.ts.map +1 -0
- package/dist/sortingComponents.d.ts +39 -0
- package/dist/sortingComponents.d.ts.map +1 -0
- package/dist/stateStorage.d.ts +20 -0
- package/dist/stateStorage.d.ts.map +1 -0
- package/dist/useDataGridSetup.d.ts +53 -0
- package/dist/useDataGridSetup.d.ts.map +1 -0
- package/dist/useDataView.d.ts +57 -0
- package/dist/useDataView.d.ts.map +1 -0
- package/dist/useDataViewState.d.ts +89 -0
- package/dist/useDataViewState.d.ts.map +1 -0
- package/package.json +33 -0
- package/src/DataGrid.tsx +173 -0
- package/src/DataViewContext.tsx +56 -0
- package/src/DataViewKeyProvider.tsx +16 -0
- package/src/HasManyDataGrid.tsx +319 -0
- package/src/columnLeaf.ts +148 -0
- package/src/columnTypes.ts +160 -0
- package/src/columns.tsx +306 -0
- package/src/contextHooks.ts +157 -0
- package/src/createColumn.ts +128 -0
- package/src/createRelationColumn.tsx +203 -0
- package/src/dataAttribute.ts +7 -0
- package/src/export.tsx +219 -0
- package/src/filterComponents.tsx +617 -0
- package/src/filterContext.ts +27 -0
- package/src/filterHooks.ts +386 -0
- package/src/filterScope.tsx +89 -0
- package/src/filterWrappers.tsx +187 -0
- package/src/index.ts +356 -0
- package/src/infiniteLoad.tsx +188 -0
- package/src/loaderComponents.tsx +239 -0
- package/src/markers.ts +54 -0
- package/src/pagingComponents.tsx +149 -0
- package/src/select/MultiSelect.tsx +88 -0
- package/src/select/Select.tsx +88 -0
- package/src/select/SelectDataView.tsx +231 -0
- package/src/select/SelectEachValue.tsx +34 -0
- package/src/select/SelectItemTrigger.tsx +51 -0
- package/src/select/SelectOption.tsx +40 -0
- package/src/select/SelectPlaceholder.tsx +22 -0
- package/src/select/index.ts +17 -0
- package/src/select/selectContext.ts +82 -0
- package/src/selectionComponents.tsx +160 -0
- package/src/sortingComponents.tsx +104 -0
- package/src/stateStorage.ts +188 -0
- package/src/useDataGridSetup.ts +230 -0
- package/src/useDataView.ts +148 -0
- package/src/useDataViewState.ts +404 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// Core DataGrid
|
|
2
|
+
export { DataGrid, type DataGridProps, QUERY_FILTER_NAME } from './DataGrid.js'
|
|
3
|
+
export { HasManyDataGrid, type HasManyDataGridProps } from './HasManyDataGrid.js'
|
|
4
|
+
|
|
5
|
+
// Column type definitions (Layer 1: headless behavior)
|
|
6
|
+
export {
|
|
7
|
+
defineColumnType,
|
|
8
|
+
type ColumnTypeDef,
|
|
9
|
+
textColumnDef,
|
|
10
|
+
numberColumnDef,
|
|
11
|
+
dateColumnDef,
|
|
12
|
+
dateTimeColumnDef,
|
|
13
|
+
booleanColumnDef,
|
|
14
|
+
enumColumnDef,
|
|
15
|
+
enumListColumnDef,
|
|
16
|
+
uuidColumnDef,
|
|
17
|
+
isDefinedColumnDef,
|
|
18
|
+
hasOneColumnDef,
|
|
19
|
+
hasManyColumnDef,
|
|
20
|
+
accessField,
|
|
21
|
+
} from './columnTypes.js'
|
|
22
|
+
|
|
23
|
+
// ColumnLeaf, extraction, and children analysis
|
|
24
|
+
export {
|
|
25
|
+
ColumnLeaf,
|
|
26
|
+
type ColumnLeafProps,
|
|
27
|
+
extractColumnLeaves,
|
|
28
|
+
analyzeChildren,
|
|
29
|
+
type ChildrenAnalysisResult,
|
|
30
|
+
} from './columnLeaf.js'
|
|
31
|
+
|
|
32
|
+
// Marker components (toolbar content, layout)
|
|
33
|
+
export {
|
|
34
|
+
DataGridToolbarContent,
|
|
35
|
+
type DataGridToolbarContentProps,
|
|
36
|
+
DataGridLayout,
|
|
37
|
+
type DataGridLayoutProps,
|
|
38
|
+
} from './markers.js'
|
|
39
|
+
|
|
40
|
+
// createColumn factory (Layer 2: UI wrapping)
|
|
41
|
+
export {
|
|
42
|
+
createColumn,
|
|
43
|
+
type ColumnRenderProps,
|
|
44
|
+
type FilterRenderProps,
|
|
45
|
+
type CreateColumnConfig,
|
|
46
|
+
type ColumnComponentProps,
|
|
47
|
+
type ColumnComponent,
|
|
48
|
+
} from './createColumn.js'
|
|
49
|
+
|
|
50
|
+
// createRelationColumn factory (Layer 2: relation columns)
|
|
51
|
+
export {
|
|
52
|
+
createRelationColumn,
|
|
53
|
+
hasOneCellConfig,
|
|
54
|
+
hasManyCellConfig,
|
|
55
|
+
type RelationColumnConfig,
|
|
56
|
+
type RelationFilterContext,
|
|
57
|
+
type RelationCellWrapperContext,
|
|
58
|
+
type RelationColumnProps,
|
|
59
|
+
type RelationColumnComponent,
|
|
60
|
+
} from './createRelationColumn.jsx'
|
|
61
|
+
|
|
62
|
+
// Column components
|
|
63
|
+
export {
|
|
64
|
+
DataGridTextColumn,
|
|
65
|
+
DataGridNumberColumn,
|
|
66
|
+
DataGridDateColumn,
|
|
67
|
+
DataGridDateTimeColumn,
|
|
68
|
+
DataGridBooleanColumn,
|
|
69
|
+
DataGridEnumColumn,
|
|
70
|
+
DataGridEnumListColumn,
|
|
71
|
+
DataGridUuidColumn,
|
|
72
|
+
DataGridIsDefinedColumn,
|
|
73
|
+
DataGridHasOneColumn,
|
|
74
|
+
DataGridHasManyColumn,
|
|
75
|
+
DataGridActionColumn,
|
|
76
|
+
DataGridColumn,
|
|
77
|
+
type DataGridTextColumnProps,
|
|
78
|
+
type DataGridNumberColumnProps,
|
|
79
|
+
type DataGridDateColumnProps,
|
|
80
|
+
type DataGridDateTimeColumnProps,
|
|
81
|
+
type DataGridBooleanColumnProps,
|
|
82
|
+
type DataGridEnumColumnProps,
|
|
83
|
+
type DataGridEnumListColumnProps,
|
|
84
|
+
type DataGridUuidColumnProps,
|
|
85
|
+
type DataGridIsDefinedColumnProps,
|
|
86
|
+
type DataGridHasOneColumnProps,
|
|
87
|
+
type DataGridHasManyColumnProps,
|
|
88
|
+
type DataGridActionColumnProps,
|
|
89
|
+
type DataGridColumnProps,
|
|
90
|
+
type ColumnMeta,
|
|
91
|
+
extractFieldName,
|
|
92
|
+
extractRelatedEntityName,
|
|
93
|
+
hasFieldRefMeta,
|
|
94
|
+
getRelatedAccessor,
|
|
95
|
+
} from './columns.js'
|
|
96
|
+
|
|
97
|
+
// State hooks
|
|
98
|
+
export {
|
|
99
|
+
useFilteringState,
|
|
100
|
+
useSortingState,
|
|
101
|
+
usePagingState,
|
|
102
|
+
useSelectionState,
|
|
103
|
+
type FilteringState,
|
|
104
|
+
type RegisteredFilter,
|
|
105
|
+
type UseFilteringOptions,
|
|
106
|
+
type UseSortingOptions,
|
|
107
|
+
type SortingStateResult,
|
|
108
|
+
type UsePagingOptions,
|
|
109
|
+
type PagingStateResult,
|
|
110
|
+
type UseSelectionOptions,
|
|
111
|
+
type SelectionStateResult,
|
|
112
|
+
} from './useDataViewState.js'
|
|
113
|
+
|
|
114
|
+
// Context
|
|
115
|
+
export {
|
|
116
|
+
useDataViewContext,
|
|
117
|
+
useOptionalDataViewContext,
|
|
118
|
+
DataViewProvider,
|
|
119
|
+
type DataViewContextValue,
|
|
120
|
+
type DataViewItem,
|
|
121
|
+
type DataViewLoaderState as DataViewLoaderStateType,
|
|
122
|
+
type DataViewElementData,
|
|
123
|
+
} from './DataViewContext.js'
|
|
124
|
+
|
|
125
|
+
// Low-level hook
|
|
126
|
+
export { useDataView, type UseDataViewOptions, type DataViewResult } from './useDataView.js'
|
|
127
|
+
|
|
128
|
+
// Data attribute helper
|
|
129
|
+
export { dataAttribute } from './dataAttribute.js'
|
|
130
|
+
|
|
131
|
+
// Filter name context
|
|
132
|
+
export {
|
|
133
|
+
useDataViewFilterName,
|
|
134
|
+
useOptionalDataViewFilterName,
|
|
135
|
+
DataViewFilterNameProvider,
|
|
136
|
+
} from './filterContext.js'
|
|
137
|
+
|
|
138
|
+
// Filter scope and registration components
|
|
139
|
+
export {
|
|
140
|
+
DataViewFilterScope,
|
|
141
|
+
type DataViewFilterScopeProps,
|
|
142
|
+
DataViewFilter,
|
|
143
|
+
type DataViewFilterProps,
|
|
144
|
+
DataViewHasFilterType,
|
|
145
|
+
type DataViewHasFilterTypeProps,
|
|
146
|
+
} from './filterScope.js'
|
|
147
|
+
|
|
148
|
+
// Filter wrapper components (typed name scoping)
|
|
149
|
+
export {
|
|
150
|
+
DataViewTextFilter,
|
|
151
|
+
type DataViewTextFilterProps,
|
|
152
|
+
DataViewBooleanFilter,
|
|
153
|
+
type DataViewBooleanFilterProps,
|
|
154
|
+
DataViewNumberFilter,
|
|
155
|
+
type DataViewNumberFilterProps,
|
|
156
|
+
DataViewDateFilter,
|
|
157
|
+
type DataViewDateFilterProps,
|
|
158
|
+
DataViewEnumFilter,
|
|
159
|
+
type DataViewEnumFilterProps,
|
|
160
|
+
DataViewEnumListFilter,
|
|
161
|
+
type DataViewEnumListFilterProps,
|
|
162
|
+
DataViewHasOneFilter,
|
|
163
|
+
type DataViewHasOneFilterProps,
|
|
164
|
+
DataViewHasManyFilter,
|
|
165
|
+
type DataViewHasManyFilterProps,
|
|
166
|
+
DataViewIsDefinedFilter,
|
|
167
|
+
type DataViewIsDefinedFilterProps,
|
|
168
|
+
DataViewUnionTextFilter,
|
|
169
|
+
type DataViewUnionTextFilterProps,
|
|
170
|
+
} from './filterWrappers.js'
|
|
171
|
+
|
|
172
|
+
// Filter hooks
|
|
173
|
+
export {
|
|
174
|
+
useDataViewFilter,
|
|
175
|
+
type UseDataViewFilterResult,
|
|
176
|
+
useDataViewBooleanFilter,
|
|
177
|
+
useDataViewBooleanFilterFactory,
|
|
178
|
+
type DataViewSetBooleanFilterAction,
|
|
179
|
+
type DataViewBooleanFilterCurrent,
|
|
180
|
+
type UseDataViewBooleanFilterResult,
|
|
181
|
+
useDataViewEnumFilter,
|
|
182
|
+
useDataViewEnumFilterFactory,
|
|
183
|
+
type DataViewSetEnumFilterAction,
|
|
184
|
+
type DataViewEnumFilterCurrent,
|
|
185
|
+
type UseDataViewEnumFilterResult,
|
|
186
|
+
useDataViewRelationFilter,
|
|
187
|
+
useDataViewRelationFilterFactory,
|
|
188
|
+
type DataViewSetRelationFilterAction,
|
|
189
|
+
type DataViewRelationFilterCurrent,
|
|
190
|
+
type UseDataViewRelationFilterResult,
|
|
191
|
+
useDataViewTextFilterInput,
|
|
192
|
+
type UseDataViewTextFilterInputResult,
|
|
193
|
+
useDataViewTextFilterMatchMode,
|
|
194
|
+
type UseDataViewTextFilterMatchModeResult,
|
|
195
|
+
useDataViewNumberFilterInput,
|
|
196
|
+
type UseDataViewNumberFilterInputResult,
|
|
197
|
+
type UseDataViewNumberFilterInputProps,
|
|
198
|
+
useDataViewNullFilter,
|
|
199
|
+
type DataViewSetNullFilterAction,
|
|
200
|
+
type DataViewNullFilterState,
|
|
201
|
+
type UseDataViewNullFilterResult,
|
|
202
|
+
} from './filterHooks.js'
|
|
203
|
+
|
|
204
|
+
// Composable filter components
|
|
205
|
+
export {
|
|
206
|
+
type DataViewFilterState,
|
|
207
|
+
DataViewTextFilterInput,
|
|
208
|
+
type DataViewTextFilterInputProps,
|
|
209
|
+
DataViewTextFilterMatchModeTrigger,
|
|
210
|
+
type DataViewTextFilterMatchModeTriggerProps,
|
|
211
|
+
DataViewTextFilterMatchModeLabel,
|
|
212
|
+
type DataViewTextFilterMatchModeLabelProps,
|
|
213
|
+
DataViewTextFilterResetTrigger,
|
|
214
|
+
type DataViewTextFilterResetTriggerProps,
|
|
215
|
+
DataViewNumberFilterInput,
|
|
216
|
+
type DataViewNumberFilterInputProps,
|
|
217
|
+
DataViewDateFilterInput,
|
|
218
|
+
type DataViewDateFilterInputProps,
|
|
219
|
+
DataViewBooleanFilterTrigger,
|
|
220
|
+
type DataViewBooleanFilterTriggerProps,
|
|
221
|
+
DataViewEnumFilterTrigger,
|
|
222
|
+
type DataViewEnumFilterTriggerProps,
|
|
223
|
+
DataViewEnumFilterState,
|
|
224
|
+
type DataViewEnumFilterStateProps,
|
|
225
|
+
DataViewRelationFilterTrigger,
|
|
226
|
+
type DataViewRelationFilterTriggerProps,
|
|
227
|
+
DataViewRelationFilterState,
|
|
228
|
+
type DataViewRelationFilterStateProps,
|
|
229
|
+
DataViewNullFilterTrigger,
|
|
230
|
+
type DataViewNullFilterTriggerProps,
|
|
231
|
+
DataViewFilterResetTrigger,
|
|
232
|
+
type DataViewFilterResetTriggerProps,
|
|
233
|
+
DataViewDateFilterResetTrigger,
|
|
234
|
+
type DataViewDateFilterResetTriggerProps,
|
|
235
|
+
DataViewNumberFilterResetTrigger,
|
|
236
|
+
type DataViewNumberFilterResetTriggerProps,
|
|
237
|
+
} from './filterComponents.js'
|
|
238
|
+
|
|
239
|
+
// Sorting components
|
|
240
|
+
export {
|
|
241
|
+
DataViewSortingTrigger,
|
|
242
|
+
type DataViewSortingTriggerProps,
|
|
243
|
+
DataViewSortingSwitch,
|
|
244
|
+
type DataViewSortingSwitchProps,
|
|
245
|
+
} from './sortingComponents.js'
|
|
246
|
+
|
|
247
|
+
// Paging components
|
|
248
|
+
export {
|
|
249
|
+
DataViewChangePageTrigger,
|
|
250
|
+
type DataViewChangePageTriggerProps,
|
|
251
|
+
DataViewSetItemsPerPageTrigger,
|
|
252
|
+
type DataViewSetItemsPerPageTriggerProps,
|
|
253
|
+
DataViewPagingStateView,
|
|
254
|
+
type DataViewPagingStateViewProps,
|
|
255
|
+
DataViewPagingInfo,
|
|
256
|
+
type DataViewPagingInfoProps,
|
|
257
|
+
} from './pagingComponents.js'
|
|
258
|
+
|
|
259
|
+
// Selection (visibility + layout) components
|
|
260
|
+
export {
|
|
261
|
+
DataViewVisibilityTrigger,
|
|
262
|
+
type DataViewVisibilityTriggerProps,
|
|
263
|
+
DataViewElement,
|
|
264
|
+
DataViewIsVisible,
|
|
265
|
+
type DataViewElementProps,
|
|
266
|
+
DataViewLayout,
|
|
267
|
+
type DataViewLayoutProps,
|
|
268
|
+
DataViewLayoutTrigger,
|
|
269
|
+
type DataViewLayoutTriggerProps,
|
|
270
|
+
} from './selectionComponents.js'
|
|
271
|
+
|
|
272
|
+
// Export
|
|
273
|
+
export {
|
|
274
|
+
DataViewExportTrigger,
|
|
275
|
+
type DataViewExportTriggerProps,
|
|
276
|
+
CsvExportFactory,
|
|
277
|
+
type ExportFactory,
|
|
278
|
+
type ExportResult,
|
|
279
|
+
type ExportFactoryArgs,
|
|
280
|
+
useDataViewFetchAllData,
|
|
281
|
+
type FetchAllDataResult,
|
|
282
|
+
} from './export.js'
|
|
283
|
+
|
|
284
|
+
// Infinite scroll
|
|
285
|
+
export {
|
|
286
|
+
DataViewInfiniteLoadProvider,
|
|
287
|
+
type DataViewInfiniteLoadProviderProps,
|
|
288
|
+
DataViewInfiniteLoadTrigger,
|
|
289
|
+
type DataViewInfiniteLoadTriggerProps,
|
|
290
|
+
DataViewInfiniteLoadScrollObserver,
|
|
291
|
+
type DataViewInfiniteLoadScrollObserverProps,
|
|
292
|
+
useDataViewInfiniteLoadTrigger,
|
|
293
|
+
} from './infiniteLoad.js'
|
|
294
|
+
|
|
295
|
+
// Loader state, reload, and conditional rendering
|
|
296
|
+
export {
|
|
297
|
+
DataViewReloadTrigger,
|
|
298
|
+
type DataViewReloadTriggerProps,
|
|
299
|
+
DataViewLoaderState,
|
|
300
|
+
type DataViewLoaderStateProps,
|
|
301
|
+
DataViewLoaderStateSwitch,
|
|
302
|
+
type DataViewLoaderStateSwitchProps,
|
|
303
|
+
useDataViewLoaderState,
|
|
304
|
+
useDataViewReload,
|
|
305
|
+
useDataViewHighlightIndex,
|
|
306
|
+
DataViewEmpty,
|
|
307
|
+
type DataViewEmptyProps,
|
|
308
|
+
DataViewNonEmpty,
|
|
309
|
+
type DataViewNonEmptyProps,
|
|
310
|
+
DataViewEachRow,
|
|
311
|
+
type DataViewEachRowProps,
|
|
312
|
+
DataViewHighlightRow,
|
|
313
|
+
type DataViewHighlightRowProps,
|
|
314
|
+
DataViewKeyboardEventHandler,
|
|
315
|
+
type DataViewKeyboardEventHandlerProps,
|
|
316
|
+
} from './loaderComponents.js'
|
|
317
|
+
|
|
318
|
+
// Fine-grained context hooks
|
|
319
|
+
export {
|
|
320
|
+
useDataViewSortingState,
|
|
321
|
+
useDataViewSortingMethods,
|
|
322
|
+
useDataViewSortingDirection,
|
|
323
|
+
type DataViewSortingMethods,
|
|
324
|
+
useDataViewPagingState,
|
|
325
|
+
useDataViewPagingInfo,
|
|
326
|
+
useDataViewPagingMethods,
|
|
327
|
+
type DataViewPagingMethods,
|
|
328
|
+
useDataViewFilteringState,
|
|
329
|
+
useDataViewFilteringMethods,
|
|
330
|
+
useDataViewFilterHandlerRegistry,
|
|
331
|
+
type DataViewFilteringMethods,
|
|
332
|
+
useDataViewSelectionState,
|
|
333
|
+
useDataViewSelectionMethods,
|
|
334
|
+
type DataViewSelectionState,
|
|
335
|
+
type DataViewSelectionMethods,
|
|
336
|
+
useDataViewElements,
|
|
337
|
+
} from './contextHooks.js'
|
|
338
|
+
|
|
339
|
+
// State storage
|
|
340
|
+
export {
|
|
341
|
+
type StateStorage,
|
|
342
|
+
type StateStorageOrName,
|
|
343
|
+
type SetStoredState,
|
|
344
|
+
useStoredState,
|
|
345
|
+
buildDataViewKey,
|
|
346
|
+
} from './stateStorage.js'
|
|
347
|
+
|
|
348
|
+
// DataView key context
|
|
349
|
+
export {
|
|
350
|
+
DataViewKeyProvider,
|
|
351
|
+
type DataViewKeyProviderProps,
|
|
352
|
+
useDataViewKey,
|
|
353
|
+
} from './DataViewKeyProvider.js'
|
|
354
|
+
|
|
355
|
+
// Select
|
|
356
|
+
export * from './select/index.js'
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infinite scroll / load-more components using Radix Slot.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <DataViewInfiniteLoadProvider>
|
|
7
|
+
* <DataViewEachRow>
|
|
8
|
+
* {(item) => <div>{item.title}</div>}
|
|
9
|
+
* </DataViewEachRow>
|
|
10
|
+
* <DataViewInfiniteLoadTrigger>
|
|
11
|
+
* <button>Load More</button>
|
|
12
|
+
* </DataViewInfiniteLoadTrigger>
|
|
13
|
+
* <DataViewInfiniteLoadScrollObserver />
|
|
14
|
+
* </DataViewInfiniteLoadProvider>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import React, { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactElement } from 'react'
|
|
19
|
+
import { Slot } from '@radix-ui/react-slot'
|
|
20
|
+
import { composeEventHandlers } from '@radix-ui/primitive'
|
|
21
|
+
import { useDataViewContext } from './DataViewContext.js'
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Context
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
interface InfiniteLoadContextValue {
|
|
28
|
+
readonly pages: readonly PageData[]
|
|
29
|
+
readonly loadMore: (() => void) | undefined
|
|
30
|
+
readonly isLoadingMore: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface PageData {
|
|
34
|
+
readonly items: readonly { id: string; data: Record<string, unknown> }[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const InfiniteLoadContext = createContext<InfiniteLoadContextValue | null>(null)
|
|
38
|
+
|
|
39
|
+
function useInfiniteLoadContext(): InfiniteLoadContextValue {
|
|
40
|
+
const ctx = useContext(InfiniteLoadContext)
|
|
41
|
+
if (!ctx) {
|
|
42
|
+
throw new Error('useInfiniteLoadContext must be used within DataViewInfiniteLoadProvider')
|
|
43
|
+
}
|
|
44
|
+
return ctx
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Provider
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export interface DataViewInfiniteLoadProviderProps {
|
|
52
|
+
children: React.ReactNode
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function DataViewInfiniteLoadProvider({
|
|
56
|
+
children,
|
|
57
|
+
}: DataViewInfiniteLoadProviderProps): ReactElement {
|
|
58
|
+
const { paging, filtering, sorting } = useDataViewContext()
|
|
59
|
+
const [pages, setPages] = useState<PageData[]>([])
|
|
60
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false)
|
|
61
|
+
|
|
62
|
+
const filterKey = JSON.stringify(filtering.resolvedWhere ?? null)
|
|
63
|
+
const sortKey = JSON.stringify(sorting.resolvedOrderBy ?? null)
|
|
64
|
+
|
|
65
|
+
const previousParams = useRef<{
|
|
66
|
+
filterKey: string
|
|
67
|
+
sortKey: string
|
|
68
|
+
limit: number | undefined
|
|
69
|
+
offset: number | undefined
|
|
70
|
+
} | null>(null)
|
|
71
|
+
|
|
72
|
+
const currentParams = useMemo(() => ({
|
|
73
|
+
filterKey,
|
|
74
|
+
sortKey,
|
|
75
|
+
limit: paging.queryLimit,
|
|
76
|
+
offset: paging.queryOffset,
|
|
77
|
+
}), [filterKey, sortKey, paging.queryLimit, paging.queryOffset])
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const prev = previousParams.current
|
|
81
|
+
if (!prev) {
|
|
82
|
+
setPages([])
|
|
83
|
+
} else if (
|
|
84
|
+
prev.filterKey === currentParams.filterKey
|
|
85
|
+
&& prev.sortKey === currentParams.sortKey
|
|
86
|
+
&& prev.limit === currentParams.limit
|
|
87
|
+
&& prev.limit !== undefined
|
|
88
|
+
&& prev.offset !== undefined
|
|
89
|
+
&& currentParams.offset === prev.offset + prev.limit
|
|
90
|
+
) {
|
|
91
|
+
setIsLoadingMore(true)
|
|
92
|
+
} else {
|
|
93
|
+
setPages([])
|
|
94
|
+
}
|
|
95
|
+
previousParams.current = currentParams
|
|
96
|
+
}, [currentParams])
|
|
97
|
+
|
|
98
|
+
const hasNext = paging.hasNext
|
|
99
|
+
|
|
100
|
+
const loadMore = useMemo((): (() => void) | undefined => {
|
|
101
|
+
if (!hasNext) return undefined
|
|
102
|
+
return () => paging.next()
|
|
103
|
+
}, [hasNext, paging])
|
|
104
|
+
|
|
105
|
+
const contextValue = useMemo((): InfiniteLoadContextValue => ({
|
|
106
|
+
pages,
|
|
107
|
+
loadMore,
|
|
108
|
+
isLoadingMore,
|
|
109
|
+
}), [pages, loadMore, isLoadingMore])
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<InfiniteLoadContext.Provider value={contextValue}>
|
|
113
|
+
{children}
|
|
114
|
+
</InfiniteLoadContext.Provider>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// Load More Trigger — Slot-based
|
|
120
|
+
// ============================================================================
|
|
121
|
+
|
|
122
|
+
export interface DataViewInfiniteLoadTriggerProps {
|
|
123
|
+
children: ReactElement
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const DataViewInfiniteLoadTrigger = forwardRef<HTMLButtonElement, DataViewInfiniteLoadTriggerProps>(
|
|
127
|
+
(props, ref) => {
|
|
128
|
+
const { loadMore, isLoadingMore } = useInfiniteLoadContext()
|
|
129
|
+
|
|
130
|
+
if (!loadMore) return null
|
|
131
|
+
|
|
132
|
+
const { onClick, ...otherProps } = props as React.ButtonHTMLAttributes<HTMLButtonElement> & { children: ReactElement }
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<Slot
|
|
136
|
+
ref={ref}
|
|
137
|
+
onClick={composeEventHandlers(onClick, loadMore)}
|
|
138
|
+
disabled={isLoadingMore}
|
|
139
|
+
data-state={isLoadingMore ? 'loading' : 'idle'}
|
|
140
|
+
{...otherProps}
|
|
141
|
+
/>
|
|
142
|
+
)
|
|
143
|
+
},
|
|
144
|
+
)
|
|
145
|
+
DataViewInfiniteLoadTrigger.displayName = 'DataViewInfiniteLoadTrigger'
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Scroll Observer (auto-trigger)
|
|
149
|
+
// ============================================================================
|
|
150
|
+
|
|
151
|
+
export interface DataViewInfiniteLoadScrollObserverProps {
|
|
152
|
+
/** Root margin for IntersectionObserver. Default: '200px' */
|
|
153
|
+
rootMargin?: string
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function DataViewInfiniteLoadScrollObserver({
|
|
157
|
+
rootMargin = '200px',
|
|
158
|
+
}: DataViewInfiniteLoadScrollObserverProps = {}): ReactElement {
|
|
159
|
+
const { loadMore, isLoadingMore } = useInfiniteLoadContext()
|
|
160
|
+
const sentinelRef = useRef<HTMLSpanElement>(null)
|
|
161
|
+
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const el = sentinelRef.current
|
|
164
|
+
if (!el || !loadMore || isLoadingMore) return
|
|
165
|
+
|
|
166
|
+
const observer = new IntersectionObserver(
|
|
167
|
+
([entry]) => {
|
|
168
|
+
if (entry?.isIntersecting && loadMore) {
|
|
169
|
+
loadMore()
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{ rootMargin },
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
observer.observe(el)
|
|
176
|
+
return () => observer.disconnect()
|
|
177
|
+
}, [loadMore, isLoadingMore, rootMargin])
|
|
178
|
+
|
|
179
|
+
return <span ref={sentinelRef} data-testid="infinite-load-sentinel" />
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Hooks
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
export function useDataViewInfiniteLoadTrigger(): (() => void) | undefined {
|
|
187
|
+
return useInfiniteLoadContext().loadMore
|
|
188
|
+
}
|