@rebasepro/ui 0.17.3 → 0.18.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.
Files changed (127) hide show
  1. package/README.md +4 -0
  2. package/dist/components/MultiSelect.d.ts +10 -0
  3. package/dist/index.es.js +2 -1
  4. package/dist/index.es.js.map +1 -1
  5. package/package.json +32 -23
  6. package/src/components/Alert.tsx +0 -118
  7. package/src/components/Autocomplete.tsx +0 -93
  8. package/src/components/Avatar.tsx +0 -73
  9. package/src/components/Badge.tsx +0 -44
  10. package/src/components/BooleanSwitch.tsx +0 -116
  11. package/src/components/BooleanSwitchWithLabel.tsx +0 -120
  12. package/src/components/Button.tsx +0 -110
  13. package/src/components/Card.tsx +0 -43
  14. package/src/components/CenteredView.tsx +0 -35
  15. package/src/components/Checkbox.tsx +0 -129
  16. package/src/components/Chip.tsx +0 -131
  17. package/src/components/CircularProgress.tsx +0 -53
  18. package/src/components/CircularProgressCenter.tsx +0 -27
  19. package/src/components/Collapse.tsx +0 -66
  20. package/src/components/ColorPicker.tsx +0 -140
  21. package/src/components/Container.tsx +0 -51
  22. package/src/components/DateTimeField.tsx +0 -363
  23. package/src/components/DebouncedTextField.tsx +0 -76
  24. package/src/components/Dialog.tsx +0 -159
  25. package/src/components/DialogActions.tsx +0 -29
  26. package/src/components/DialogContent.tsx +0 -27
  27. package/src/components/DialogTitle.tsx +0 -41
  28. package/src/components/ErrorBoundary.tsx +0 -236
  29. package/src/components/ExpandablePanel.tsx +0 -130
  30. package/src/components/FileUpload.tsx +0 -103
  31. package/src/components/FilterChip.tsx +0 -89
  32. package/src/components/IconButton.tsx +0 -101
  33. package/src/components/InfoLabel.tsx +0 -23
  34. package/src/components/InputLabel.tsx +0 -40
  35. package/src/components/Label.tsx +0 -32
  36. package/src/components/LoadingButton.tsx +0 -32
  37. package/src/components/Markdown.tsx +0 -55
  38. package/src/components/Menu.tsx +0 -114
  39. package/src/components/Menubar.tsx +0 -355
  40. package/src/components/MultiSelect.tsx +0 -433
  41. package/src/components/Paper.tsx +0 -23
  42. package/src/components/Popover.tsx +0 -162
  43. package/src/components/RadioGroup.tsx +0 -74
  44. package/src/components/ResizablePanels.tsx +0 -189
  45. package/src/components/SearchBar.tsx +0 -136
  46. package/src/components/Select.tsx +0 -326
  47. package/src/components/Separator.tsx +0 -28
  48. package/src/components/Sheet.tsx +0 -135
  49. package/src/components/Skeleton.tsx +0 -54
  50. package/src/components/Slider.tsx +0 -110
  51. package/src/components/Table.tsx +0 -178
  52. package/src/components/Tabs.tsx +0 -185
  53. package/src/components/TextField.tsx +0 -270
  54. package/src/components/TextareaAutosize.tsx +0 -368
  55. package/src/components/ToggleButtonGroup.tsx +0 -69
  56. package/src/components/Tooltip.tsx +0 -153
  57. package/src/components/Typography.tsx +0 -132
  58. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +0 -90
  59. package/src/components/VirtualTable/VirtualTable.tsx +0 -700
  60. package/src/components/VirtualTable/VirtualTableCell.tsx +0 -59
  61. package/src/components/VirtualTable/VirtualTableHeader.tsx +0 -327
  62. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +0 -250
  63. package/src/components/VirtualTable/VirtualTableProps.tsx +0 -339
  64. package/src/components/VirtualTable/VirtualTableRow.tsx +0 -51
  65. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +0 -44
  66. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +0 -89
  67. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +0 -71
  68. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +0 -107
  69. package/src/components/VirtualTable/fields/VirtualTableSwitch.tsx +0 -28
  70. package/src/components/VirtualTable/index.tsx +0 -10
  71. package/src/components/VirtualTable/selection/SelectionContext.tsx +0 -36
  72. package/src/components/VirtualTable/selection/SelectionStore.ts +0 -54
  73. package/src/components/VirtualTable/types.tsx +0 -47
  74. package/src/components/common/SelectInputLabel.tsx +0 -23
  75. package/src/components/index.tsx +0 -62
  76. package/src/hooks/PortalContainerContext.tsx +0 -50
  77. package/src/hooks/index.ts +0 -7
  78. package/src/hooks/useDebounceCallback.tsx +0 -21
  79. package/src/hooks/useDebounceValue.tsx +0 -20
  80. package/src/hooks/useDebouncedCallback.ts +0 -39
  81. package/src/hooks/useInjectStyles.tsx +0 -31
  82. package/src/hooks/useOutsideAlerter.tsx +0 -46
  83. package/src/icons/GitHubIcon.tsx +0 -21
  84. package/src/icons/HandleIcon.tsx +0 -23
  85. package/src/icons/Icon.tsx +0 -33
  86. package/src/icons/LucideIconByName.tsx +0 -117
  87. package/src/icons/cool_icon_keys.ts +0 -12
  88. package/src/icons/icon_keys.ts +0 -1936
  89. package/src/icons/index.ts +0 -179
  90. package/src/index.css +0 -169
  91. package/src/index.ts +0 -47
  92. package/src/scripts/fixIconSizes.cjs +0 -92
  93. package/src/scripts/fixIconSizesToConst.cjs +0 -106
  94. package/src/scripts/generateIconKeys.ts +0 -41
  95. package/src/scripts/generateIcons.ts +0 -4
  96. package/src/scripts/saveIconFiles.ts +0 -89
  97. package/src/styles.ts +0 -141
  98. package/src/theme.css +0 -168
  99. package/src/util/chip_colors.ts +0 -242
  100. package/src/util/cls.ts +0 -8
  101. package/src/util/debounce.ts +0 -28
  102. package/src/util/hash.ts +0 -11
  103. package/src/util/index.ts +0 -4
  104. package/src/util/key_to_icon_component.ts +0 -11
  105. package/src/util/lazy_chunk.ts +0 -101
  106. package/src/views/CardView.tsx +0 -281
  107. package/src/views/CollectionView/CollectionCardView.tsx +0 -265
  108. package/src/views/CollectionView/CollectionKanbanView.tsx +0 -246
  109. package/src/views/CollectionView/CollectionListView.tsx +0 -240
  110. package/src/views/CollectionView/CollectionTableView.tsx +0 -229
  111. package/src/views/CollectionView/CollectionView.tsx +0 -450
  112. package/src/views/CollectionView/CollectionViewToolbar.tsx +0 -242
  113. package/src/views/CollectionView/CollectionViewTypes.ts +0 -181
  114. package/src/views/CollectionView/DefaultCellRenderer.tsx +0 -404
  115. package/src/views/CollectionView/index.ts +0 -39
  116. package/src/views/CollectionView/resolveTitleProperty.ts +0 -52
  117. package/src/views/CollectionView/utils.ts +0 -14
  118. package/src/views/Kanban/Board.tsx +0 -384
  119. package/src/views/Kanban/BoardColumn.tsx +0 -138
  120. package/src/views/Kanban/BoardColumnTitle.tsx +0 -47
  121. package/src/views/Kanban/BoardSortableList.tsx +0 -182
  122. package/src/views/Kanban/board_types.ts +0 -80
  123. package/src/views/Kanban/index.tsx +0 -5
  124. package/src/views/Kanban/placement.ts +0 -62
  125. package/src/views/KanbanView.tsx +0 -32
  126. package/src/views/ListView.tsx +0 -296
  127. package/src/views/index.ts +0 -5
@@ -1,59 +0,0 @@
1
- import React from "react";
2
-
3
- import { deepEqual as equal } from "fast-equals"
4
-
5
- import { CellRendererParams, VirtualTableColumn } from "./VirtualTableProps";
6
-
7
- type VirtualTableCellProps<T> = {
8
- dataKey: string;
9
- column: VirtualTableColumn;
10
- columns: VirtualTableColumn[];
11
- rowData: T;
12
- cellData: unknown;
13
- rowIndex: number;
14
- columnIndex: number;
15
- cellRenderer: (props: CellRendererParams<T>) => React.ReactNode;
16
- // Sortable props
17
- sortableNodeRef?: (node: HTMLElement | null) => void;
18
- sortableStyle?: React.CSSProperties;
19
- sortableAttributes?: Record<string, unknown>;
20
- isDragging?: boolean;
21
- isDraggable?: boolean;
22
- frozen?: boolean;
23
- extraData?: unknown;
24
- };
25
-
26
- export const VirtualTableCell = React.memo<VirtualTableCellProps<unknown>>(
27
- function VirtualTableCell<T>(props: VirtualTableCellProps<T>) {
28
- return props.rowData ? props.cellRenderer(
29
- {
30
- cellData: props.cellData,
31
- rowData: props.rowData,
32
- rowIndex: props.rowIndex,
33
- isScrolling: false,
34
- column: props.column,
35
- columns: props.columns,
36
- columnIndex: props.columnIndex,
37
- width: props.column.width,
38
- sortableNodeRef: props.sortableNodeRef,
39
- sortableStyle: props.sortableStyle,
40
- sortableAttributes: props.sortableAttributes,
41
- isDragging: props.isDragging,
42
- isDraggable: props.isDraggable,
43
- frozen: props.frozen,
44
- extraData: props.extraData
45
- } as CellRendererParams<T>
46
- ) : null;
47
- },
48
- (a, b) => {
49
- return equal(a.rowData, b.rowData) &&
50
- equal(a.column, b.column) &&
51
- equal(a.cellData, b.cellData) &&
52
- a.rowIndex === b.rowIndex &&
53
- a.columnIndex === b.columnIndex &&
54
- a.isDragging === b.isDragging &&
55
- a.isDraggable === b.isDraggable &&
56
- a.frozen === b.frozen &&
57
- equal(a.extraData, b.extraData)
58
- }
59
- );
@@ -1,327 +0,0 @@
1
- import { ArrowUpIcon, FilterIcon } from "lucide-react";
2
- import { iconSize } from "../../icons/Icon";
3
-
4
- import React, { RefObject, useCallback, useEffect, useState } from "react";
5
- import { deepEqual as equal } from "fast-equals";
6
-
7
- import { VirtualTableColumn, VirtualTableSort, VirtualTableWhereFilterOp } from "./VirtualTableProps";
8
- import { ErrorBoundary } from "../ErrorBoundary";
9
- import { Badge } from "../Badge";
10
- import { Button } from "../Button";
11
- import { IconButton } from "../IconButton";
12
- import { Popover } from "../Popover";
13
- import { defaultBorderMixin } from "../../styles";
14
- import { cls } from "../../util/cls";
15
- interface FilterFormProps<T> {
16
- column: VirtualTableColumn<T>;
17
- onFilterUpdate: (filter?: [VirtualTableWhereFilterOp, unknown], newOpenFilterState?: boolean) => void;
18
- filter?: [VirtualTableWhereFilterOp, unknown];
19
- onHover: boolean,
20
- createFilterField: (props: FilterFormFieldProps<T>) => React.ReactNode;
21
- hidden: boolean;
22
- setHidden: (hidden: boolean) => void;
23
- }
24
-
25
- export type FilterFormFieldProps<CustomProps> = {
26
- id: React.Key,
27
- filterValue: [VirtualTableWhereFilterOp, unknown] | undefined,
28
- setFilterValue: (filterValue?: [VirtualTableWhereFilterOp, unknown]) => void;
29
- column: VirtualTableColumn<CustomProps>;
30
- hidden: boolean;
31
- setHidden: (hidden: boolean) => void;
32
- };
33
-
34
- type VirtualTableHeaderProps<M extends Record<string, unknown>> = {
35
- resizeHandleRef: React.Ref<HTMLDivElement>;
36
- columnIndex: number;
37
- isResizingIndex: number;
38
- column: VirtualTableColumn<unknown>;
39
- onColumnSort: (key: Extract<keyof M, string>, additive?: boolean) => void;
40
- filter?: [VirtualTableWhereFilterOp, unknown];
41
- sort: VirtualTableSort;
42
- /**
43
- * This column's zero-based rank in a multi-key sort, or `undefined` when
44
- * only one column is sorted and a rank would say nothing.
45
- */
46
- sortPosition?: number;
47
- onFilterUpdate: (column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, unknown]) => void;
48
- onClickResizeColumn?: (columnIndex: number, column: VirtualTableColumn) => void;
49
- createFilterField?: (props: FilterFormFieldProps<unknown>) => React.ReactNode;
50
- AdditionalHeaderWidget?: (props: { onHover: boolean }) => React.ReactNode;
51
- isDragging?: boolean;
52
- isDraggable?: boolean;
53
- };
54
-
55
- /**
56
- * What the next click on this column's sort control will do, spelled out for
57
- * the tooltip and for screen readers. An unlabelled arrow that means three
58
- * different things depending on the state it is in is a control you have to
59
- * click to learn.
60
- */
61
- function sortActionTitle(sort: VirtualTableSort, sortPosition?: number): string {
62
- const rank = sortPosition !== undefined ? ` (sort key ${sortPosition + 1})` : "";
63
- const addKey = " — shift-click to add it under the current sort instead";
64
- if (sort === "asc") return `Sorted ascending${rank}. Click to sort descending.${addKey}`;
65
- if (sort === "desc") return `Sorted descending${rank}. Click to remove this sort.${addKey}`;
66
- return `Click to sort ascending.${addKey}`;
67
- }
68
-
69
- export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<Record<string, unknown>>>(
70
- function VirtualTableHeader<M extends Record<string, unknown>>({
71
- resizeHandleRef,
72
- columnIndex,
73
- isResizingIndex,
74
- sort,
75
- sortPosition,
76
- onColumnSort,
77
- onFilterUpdate,
78
- filter,
79
- column,
80
- onClickResizeColumn,
81
- createFilterField,
82
- AdditionalHeaderWidget,
83
- isDragging,
84
- isDraggable
85
- }: VirtualTableHeaderProps<M>) {
86
-
87
- const [onHover, setOnHover] = useState(false);
88
-
89
- const [openFilter, setOpenFilter] = React.useState(false);
90
- const [hidden, setHidden] = React.useState(false);
91
-
92
- const handleSettingsClick = useCallback((_event: React.MouseEvent) => {
93
- setOpenFilter(true);
94
- }, []);
95
-
96
- const update = useCallback((filterForProperty?: [VirtualTableWhereFilterOp, unknown], newOpenFilterState?: boolean) => {
97
- onFilterUpdate(column, filterForProperty);
98
- if (newOpenFilterState !== undefined)
99
- setOpenFilter(newOpenFilterState);
100
- }, [column, onFilterUpdate]);
101
-
102
- const thisColumnIsResizing = isResizingIndex === columnIndex;
103
- const anotherColumnIsResizing = isResizingIndex !== columnIndex && isResizingIndex > 0;
104
-
105
- const hovered = !anotherColumnIsResizing && (onHover || thisColumnIsResizing);
106
-
107
- return (
108
- <ErrorBoundary>
109
- <div
110
- className={cls("flex py-0 px-3 h-full text-xs uppercase font-semibold relative select-none items-center",
111
- isDragging
112
- ? "bg-primary-bg dark:bg-primary-bg-dark"
113
- : "bg-surface-50 dark:bg-surface-900",
114
- "text-text-secondary hover:text-text-primary dark:text-text-secondary-dark dark:hover:text-text-primary-dark",
115
- !isDragging && "hover:bg-surface-100 dark:hover:bg-surface-900 hover:bg-opacity-50 hover:bg-surface-100/50 dark:hover:bg-opacity-50 dark:hover:bg-surface-900/50",
116
- column.frozen ? "sticky left-0 z-10" : "relative z-0",
117
- isDraggable && "cursor-grab"
118
- )}
119
- style={{
120
- left: column.frozen ? 0 : undefined,
121
- minWidth: column.width,
122
- maxWidth: column.width
123
- }}
124
- onMouseEnter={() => setOnHover(true)}
125
- onMouseMove={() => setOnHover(true)}
126
- onMouseLeave={() => setOnHover(false)}
127
- >
128
-
129
- <div className="overflow-hidden grow">
130
- <div
131
- className={`flex items-center justify-${column.headerAlign} flex-row`}>
132
-
133
- {column.icon && (
134
- <div className="flex-shrink-0 flex items-center justify-center mr-1">
135
- {React.isValidElement(column.icon) ? (
136
- React.cloneElement(column.icon as React.ReactElement<any>, {
137
- size: 14,
138
- className: cls((column.icon as React.ReactElement<any>).props?.className, "flex-shrink-0")
139
- })
140
- ) : (
141
- column.icon
142
- )}
143
- </div>
144
- )}
145
-
146
- <div
147
- className="truncate -webkit-box w-full mr-1 overflow-hidden"
148
- style={{
149
- WebkitBoxOrient: "vertical",
150
- WebkitLineClamp: 2,
151
- justifyContent: column.align
152
- }}>
153
- {column.title}
154
- </div>
155
-
156
- </div>
157
- </div>
158
- <>
159
-
160
- {AdditionalHeaderWidget &&
161
- <AdditionalHeaderWidget onHover={onHover || openFilter}/>}
162
-
163
- {column.sortable && (sort || hovered || openFilter) &&
164
- <div className="flex-shrink-0 flex items-center">
165
- <Badge color="secondary"
166
- invisible={!sort}>
167
- <IconButton
168
- size={"small"}
169
- className={onHover || openFilter ? "bg-white dark:bg-surface-900" : undefined}
170
- // Shift keeps the sort already in place
171
- // and adds this column beneath it, which
172
- // is how a two-key order is built from
173
- // header clicks. Plain click still
174
- // replaces the whole sort, so the common
175
- // case takes no modifier and nothing a
176
- // user knew before stops working.
177
- title={sortActionTitle(sort, sortPosition)}
178
- aria-label={sortActionTitle(sort, sortPosition)}
179
- onClick={(event: React.MouseEvent) => {
180
- onColumnSort(column.key as Extract<keyof M, string>, event.shiftKey);
181
- }}
182
- >
183
- {!sort &&
184
- <ArrowUpIcon size={14} className="flex-shrink-0" />}
185
- {sort === "asc" &&
186
- <ArrowUpIcon size={14} className="flex-shrink-0" />}
187
- {sort === "desc" &&
188
- <ArrowUpIcon size={14} className="flex-shrink-0 rotate-180" />}
189
- </IconButton>
190
- </Badge>
191
- {/* The rank, shown only once there is more than
192
- one key: two arrows with no numbers beside
193
- them say a table is sorted by both columns
194
- and nothing about which one decides. */}
195
- {sort && sortPosition !== undefined && (
196
- <span
197
- className="flex-shrink-0 -ml-0.5 mr-0.5 text-[10px] font-semibold leading-none tabular-nums text-text-secondary dark:text-text-secondary-dark"
198
- aria-hidden={true}
199
- >
200
- {sortPosition + 1}
201
- </span>
202
- )}
203
- </div>
204
- }
205
- </>
206
-
207
- {column.filter && createFilterField && <div className="flex-shrink-0">
208
- <Badge color="secondary"
209
- invisible={!filter}>
210
-
211
- <Popover
212
- open={openFilter}
213
- onOpenChange={setOpenFilter}
214
- className={hidden ? "hidden" : undefined}
215
- modal={true}
216
- trigger={
217
- <IconButton
218
- className={onHover || openFilter ? "bg-white dark:bg-surface-900" : undefined}
219
- size={"small"}
220
- onClick={handleSettingsClick}>
221
- <FilterIcon size={14} className="flex-shrink-0"/>
222
- </IconButton>}
223
- >
224
- <FilterForm column={column}
225
- filter={filter}
226
- onHover={onHover}
227
- onFilterUpdate={update}
228
- createFilterField={createFilterField}
229
- hidden={hidden}
230
- setHidden={setHidden}/>
231
-
232
- </Popover>
233
-
234
- </Badge>
235
-
236
- </div>}
237
-
238
- {column.resizable && <div
239
- ref={resizeHandleRef as React.Ref<HTMLDivElement>}
240
- data-no-dnd="true"
241
- className={cls(
242
- "absolute h-full w-[6px] top-0 right-0 cursor-col-resize",
243
- hovered && "bg-surface-300 dark:bg-surface-700"
244
- )}
245
- onPointerDown={(e) => {
246
- e.stopPropagation();
247
- if (onClickResizeColumn) {
248
- onClickResizeColumn(columnIndex, column);
249
- }
250
- }}
251
- />}
252
- </div>
253
-
254
- </ErrorBoundary>
255
- );
256
- }, equal) as React.FunctionComponent<VirtualTableHeaderProps<Record<string, unknown>>>;
257
-
258
- function FilterForm<M>({
259
- column,
260
- onFilterUpdate,
261
- filter,
262
- onHover,
263
- createFilterField,
264
- hidden,
265
- setHidden
266
- }: FilterFormProps<M>) {
267
-
268
- const id = column.key;
269
-
270
- const [filterInternal, setFilterInternal] = useState<[VirtualTableWhereFilterOp, unknown] | undefined>(filter);
271
-
272
- useEffect(() => {
273
- setFilterInternal(filter);
274
- }, [filter]);
275
-
276
- if (!column.filter) return null;
277
-
278
- const submit = () => {
279
- onFilterUpdate(filterInternal, false);
280
- };
281
-
282
- const reset = (_e: React.MouseEvent) => {
283
- onFilterUpdate(undefined, false);
284
- };
285
-
286
- const filterIsSet = !!filter;
287
-
288
- const filterField = createFilterField({
289
- id,
290
- filterValue: filterInternal,
291
- setFilterValue: setFilterInternal,
292
- column,
293
- hidden,
294
- setHidden
295
- });
296
-
297
- if (!filterField) return null;
298
- return (
299
- <form noValidate={true}
300
- onSubmit={(e) => {
301
- e.stopPropagation();
302
- e.preventDefault();
303
- submit();
304
- }}
305
- className={"text-surface-900 dark:text-white"}>
306
- <div
307
- className={cls(defaultBorderMixin, "py-4 px-6 typography-label border-b")}>
308
- {column.title ?? id}
309
- </div>
310
- {filterField && <div className="m-4 w-[400px]">
311
- {filterField}
312
- </div>}
313
- <div className="flex justify-end m-4">
314
- <Button
315
- className="mr-4"
316
- disabled={!filterIsSet}
317
- variant={"text"}
318
- type="reset"
319
- aria-label="filter clear"
320
- onClick={reset}>Clear</Button>
321
- <Button
322
- type="submit">Filter</Button>
323
- </div>
324
- </form>
325
- );
326
-
327
- }
@@ -1,250 +0,0 @@
1
- import React, { createRef, useCallback, useEffect, useMemo, useState } from "react";
2
-
3
- import { VirtualTableColumn, VirtualTableWhereFilterOp } from "./VirtualTableProps";
4
- import { ErrorBoundary } from "../ErrorBoundary";
5
- import { VirtualTableHeader } from "./VirtualTableHeader";
6
- import { VirtualTableContextProps } from "./types";
7
- import { defaultBorderMixin } from "../../styles";
8
- import { cls } from "../../util/cls";import { useSortable } from "@dnd-kit/sortable";
9
- import { CSS } from "@dnd-kit/utilities";
10
-
11
- // Sortable column header wrapper
12
- const SortableColumnHeader = ({
13
- column,
14
- columnIndex,
15
- columnRefs,
16
- isResizing,
17
- onFilterUpdate,
18
- filter,
19
- sortIndex,
20
- sortCount,
21
- onColumnSort,
22
- onClickResizeColumn,
23
- createFilterField,
24
- isDragging,
25
- isDraggable
26
- }: {
27
- column: VirtualTableColumn;
28
- columnIndex: number;
29
- columnRefs: React.Ref<HTMLDivElement>[];
30
- isResizing: number;
31
- onFilterUpdate: (column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, unknown]) => void;
32
- filter: [VirtualTableWhereFilterOp, unknown] | undefined;
33
- sortIndex: Map<string, { direction: "asc" | "desc"; position: number }>;
34
- sortCount: number;
35
- onColumnSort: (key: string, additive?: boolean) => void;
36
- onClickResizeColumn: (index: number) => void;
37
- createFilterField: ((props: import("./VirtualTableHeader").FilterFormFieldProps<unknown>) => React.ReactNode) | undefined;
38
- isDragging: boolean;
39
- isDraggable: boolean;
40
- }) => {
41
- const [isPressing, setIsPressing] = useState(false);
42
-
43
- const {
44
- attributes,
45
- listeners,
46
- setNodeRef,
47
- transform,
48
- transition
49
- } = useSortable({
50
- id: column.key,
51
- disabled: !isDraggable || column.frozen
52
- });
53
-
54
- const style = {
55
- // Only use translate, ignore any scale transforms
56
- transform: transform ? `translateX(${transform.x}px)` : undefined,
57
- // Don't transition the dragged item - only other items should animate
58
- transition: isDragging ? undefined : transition,
59
- minWidth: column.width,
60
- maxWidth: column.width,
61
- width: column.width
62
- };
63
-
64
- // Combine our press handlers with dnd-kit listeners
65
- const combinedListeners = isDraggable ? {
66
- ...listeners,
67
- onPointerDown: (e: React.PointerEvent) => {
68
- setIsPressing(true);
69
- listeners?.onPointerDown?.(e);
70
- },
71
- onPointerUp: () => setIsPressing(false),
72
- onPointerCancel: () => setIsPressing(false)
73
- } : {};
74
-
75
- // Reset pressing state when drag ends
76
- React.useEffect(() => {
77
- if (!isDragging) {
78
- setIsPressing(false);
79
- }
80
- }, [isDragging]);
81
-
82
- return (
83
- <div
84
- ref={setNodeRef}
85
- style={style}
86
- className={cls(
87
- "flex-shrink-0 h-full",
88
- column.frozen && "sticky left-0 z-10"
89
- )}
90
- {...attributes}
91
- {...combinedListeners}
92
- >
93
- <VirtualTableHeader
94
- resizeHandleRef={columnRefs[columnIndex]}
95
- columnIndex={columnIndex}
96
- isResizingIndex={isResizing}
97
- onFilterUpdate={onFilterUpdate}
98
- filter={filter}
99
- sort={sortIndex.get(column.key)?.direction}
100
- sortPosition={sortCount > 1 ? sortIndex.get(column.key)?.position : undefined}
101
- onColumnSort={onColumnSort}
102
- onClickResizeColumn={onClickResizeColumn}
103
- column={column}
104
- createFilterField={createFilterField}
105
- AdditionalHeaderWidget={column.AdditionalHeaderWidget}
106
- isDragging={isDragging || isPressing}
107
- isDraggable={isDraggable}/>
108
- </div>
109
- );
110
- };
111
-
112
- export const VirtualTableHeaderRow = ({
113
- columns,
114
- sortIndex,
115
- onColumnSort,
116
- onFilterUpdate,
117
- filter,
118
- onColumnResize,
119
- onColumnResizeEnd,
120
- createFilterField,
121
- AddColumnComponent,
122
- onColumnsOrderChange,
123
- data,
124
- cellRenderer: CellRenderer,
125
- rowHeight = 54,
126
- draggingColumnId,
127
- headerHeight = 48
128
- }: VirtualTableContextProps<Record<string, unknown>>) => {
129
-
130
- const columnRefs = useMemo(() => columns.map(() => createRef<HTMLDivElement>()), [columns.length]);
131
- const [isResizing, setIsResizing] = useState(-1);
132
-
133
- const adjustWidthColumn = useCallback((index: number, width: number, end: boolean) => {
134
- const column = columns[index];
135
- const minWidth = 100;
136
- const maxWidth = 800;
137
- const newWidth = width > maxWidth ? maxWidth : (width < minWidth ? minWidth : width);
138
- const params = {
139
- width: newWidth,
140
- key: column.key as string,
141
- column: {
142
- ...column,
143
- width: newWidth
144
- } as VirtualTableColumn
145
- };
146
- if (!end)
147
- onColumnResize(params);
148
- else
149
- onColumnResizeEnd(params);
150
- }, [columns, onColumnResize, onColumnResizeEnd]);
151
-
152
- const getEventNewWidth = useCallback((e: MouseEvent) => {
153
- if (isResizing >= 0) {
154
- const left = columnRefs[isResizing].current?.parentElement?.getBoundingClientRect().left;
155
- if (!left) return;
156
- return e.clientX - left;
157
- }
158
- return undefined;
159
- }, [columnRefs, isResizing]);
160
-
161
- const setCursorDocument = useCallback((isResizing: boolean) => {
162
- document.body.style.cursor = isResizing ? "col-resize" : "auto";
163
- }, []);
164
-
165
- const handleOnMouseMove = useCallback((e: MouseEvent) => {
166
- e.stopPropagation();
167
- e.preventDefault();
168
- const newWidth = getEventNewWidth(e);
169
- if (newWidth)
170
- adjustWidthColumn(isResizing, newWidth, false);
171
- }, [adjustWidthColumn, getEventNewWidth, isResizing]);
172
-
173
- const handleOnMouseUp = useCallback((e: MouseEvent) => {
174
- e.stopPropagation();
175
- e.preventDefault();
176
- const newWidth = getEventNewWidth(e);
177
- if (newWidth)
178
- adjustWidthColumn(isResizing, newWidth, true);
179
- setIsResizing(-1);
180
- setCursorDocument(false);
181
- }, [adjustWidthColumn, getEventNewWidth, isResizing, setCursorDocument]);
182
-
183
- const removeResizingListeners = useCallback(() => {
184
- document.removeEventListener("mousemove", handleOnMouseMove);
185
- document.removeEventListener("mouseup", handleOnMouseUp);
186
- }, [handleOnMouseMove, handleOnMouseUp]);
187
-
188
- const attachResizeListeners = useCallback(() => {
189
- document.addEventListener("mousemove", handleOnMouseMove);
190
- document.addEventListener("mouseup", handleOnMouseUp);
191
- }, [handleOnMouseMove, handleOnMouseUp]);
192
-
193
- useEffect(() => {
194
- if (isResizing >= 0) {
195
- attachResizeListeners();
196
- } else {
197
- removeResizingListeners();
198
- }
199
- return () => {
200
- removeResizingListeners();
201
- };
202
- }, [attachResizeListeners, isResizing, removeResizingListeners]);
203
-
204
- const onClickResizeColumn = useCallback((index: number) => {
205
- setIsResizing(index);
206
- setCursorDocument(true);
207
- }, [setCursorDocument]);
208
-
209
- return (
210
- <>
211
- <div
212
- className={cls(defaultBorderMixin, "z-20 sticky min-w-full flex w-fit flex-row top-0 left-0 border-b bg-surface-50 dark:bg-surface-900")}
213
- style={{ height: headerHeight }}>
214
- {columns.map((column, columnIndex) => {
215
- const columnFilter = column && filter && filter[column.key] ? filter[column.key] : undefined;
216
- const filterForThisProperty: [VirtualTableWhereFilterOp, unknown] | undefined =
217
- columnFilter
218
- ? (Array.isArray(columnFilter[0]) ? (columnFilter as [VirtualTableWhereFilterOp, unknown][])[0] : (columnFilter as [VirtualTableWhereFilterOp, unknown]))
219
- : undefined;
220
-
221
- const isDraggable = !column.frozen && !!onColumnsOrderChange;
222
- const isDragging = draggingColumnId === column.key;
223
-
224
- return (
225
- <ErrorBoundary key={"header_" + column.key}>
226
- <SortableColumnHeader
227
- column={column}
228
- columnIndex={columnIndex}
229
- columnRefs={columnRefs}
230
- isResizing={isResizing}
231
- onFilterUpdate={onFilterUpdate}
232
- filter={filterForThisProperty}
233
- sortIndex={sortIndex}
234
- sortCount={sortIndex.size}
235
- onColumnSort={onColumnSort}
236
- onClickResizeColumn={onClickResizeColumn}
237
- createFilterField={createFilterField}
238
- isDragging={isDragging}
239
- isDraggable={isDraggable}
240
- />
241
- </ErrorBoundary>
242
- );
243
- })}
244
-
245
- {AddColumnComponent && <AddColumnComponent/>}
246
-
247
- </div>
248
- </>
249
- );
250
- };