Skip to content

Commit 83b0e5d

Browse files
committed
Merge branch 'feat/tree-view' into tree-view/more-a11y
2 parents 1de27ac + b0a69f9 commit 83b0e5d

File tree

6 files changed

+37
-43
lines changed

6 files changed

+37
-43
lines changed

packages/ui/src/elements/TreeView/NestedSectionsTable/Row/index.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const Row: React.FC<DivTableRowProps> = ({
107107
actions: {
108108
selectRow: (event) => {
109109
onSelectionChange({
110-
itemKey: rowItem.rowID,
110+
itemKey: rowItem.itemKey,
111111
options: {
112112
ctrlKey: event.ctrlKey || event.metaKey,
113113
metaKey: event.ctrlKey || event.metaKey,
@@ -116,7 +116,7 @@ export const Row: React.FC<DivTableRowProps> = ({
116116
})
117117
},
118118
toggleExpand: () => {
119-
toggleRow(rowItem.rowID)
119+
toggleRow(rowItem.itemKey)
120120
},
121121
},
122122
dataAttributeName: 'data-row-action',
@@ -131,7 +131,7 @@ export const Row: React.FC<DivTableRowProps> = ({
131131
isDragging && `${baseClass}__section--dragging`,
132132
isDragging && isInvalidTarget && `${baseClass}__section--invalid-target`,
133133
isOdd && `${baseClass}__section--odd`,
134-
targetParentID === rowItem.rowID && `${baseClass}__section--target`,
134+
targetParentID === rowItem.itemKey && `${baseClass}__section--target`,
135135
isRowSelected && `${baseClass}__section--selected`,
136136
hasSelectedAncestor && `${baseClass}__section--selected-descendant`,
137137
isFocused && `${baseClass}__section--focused`,
@@ -167,7 +167,7 @@ export const Row: React.FC<DivTableRowProps> = ({
167167
className={`${baseClass}__drag-handler`}
168168
disabled={
169169
hasSelectedAncestor ||
170-
(selectedItemKeys.size > 1 && !selectedItemKeys.has(rowItem.rowID))
170+
(selectedItemKeys.size > 1 && !selectedItemKeys.has(rowItem.itemKey))
171171
}
172172
onDrag={(event) => {
173173
onRowDrag({
@@ -218,15 +218,15 @@ export const Row: React.FC<DivTableRowProps> = ({
218218
margin={false}
219219
size="small"
220220
>
221-
{loadingRowIDs?.has(rowItem.rowID) ? (
221+
{loadingRowIDs?.has(rowItem.itemKey) ? (
222222
<div className={`${baseClass}__tree-toggle-spinner`}>
223223
<div className={`${baseClass}__spinner-bar`} />
224224
<div className={`${baseClass}__spinner-bar`} />
225225
<div className={`${baseClass}__spinner-bar`} />
226226
</div>
227227
) : (
228228
<ChevronIcon
229-
direction={openItemKeys?.has(rowItem.rowID) ? 'down' : 'right'}
229+
direction={openItemKeys?.has(rowItem.itemKey) ? 'down' : 'right'}
230230
/>
231231
)}
232232
</Button>
@@ -251,7 +251,7 @@ export const Row: React.FC<DivTableRowProps> = ({
251251
dropContextName={dropContextName}
252252
isDragging={isDragging}
253253
onHover={(data) => {
254-
onDroppableHover({ ...data, hoveredRowID: rowItem.rowID })
254+
onDroppableHover({ ...data, hoveredRowID: rowItem.itemKey })
255255
}}
256256
placement="split-top"
257257
segmentWidth={segmentWidth}
@@ -271,7 +271,7 @@ export const Row: React.FC<DivTableRowProps> = ({
271271
dropContextName={dropContextName}
272272
isDragging={isDragging}
273273
onHover={(data) => {
274-
onDroppableHover({ ...data, hoveredRowID: rowItem.rowID })
274+
onDroppableHover({ ...data, hoveredRowID: rowItem.itemKey })
275275
}}
276276
placement="middle"
277277
segmentWidth={segmentWidth}
@@ -284,7 +284,7 @@ export const Row: React.FC<DivTableRowProps> = ({
284284
dropContextName={dropContextName}
285285
isDragging={isDragging}
286286
onHover={(data) => {
287-
onDroppableHover({ ...data, hoveredRowID: rowItem.rowID })
287+
onDroppableHover({ ...data, hoveredRowID: rowItem.itemKey })
288288
}}
289289
placement="split-bottom"
290290
segmentWidth={segmentWidth}
@@ -301,7 +301,7 @@ export const Row: React.FC<DivTableRowProps> = ({
301301
</div>
302302

303303
{/* Render placeholder row below the hovered row */}
304-
{isDragging && hoveredRowItemKey === rowItem.rowID && (
304+
{isDragging && hoveredRowItemKey === rowItem.itemKey && (
305305
<div className={`${baseClass}__placeholder-section`}>
306306
<div className={`${baseClass}__placeholder-row`}>
307307
{columns.map((col) => (

packages/ui/src/elements/TreeView/NestedSectionsTable/TableSection/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ export const TableSection: React.FC<RenderTableSectionProps> = ({
7474
toggleRowExpand: toggleRow,
7575
}) => {
7676
// Helper to count all rows recursively, only counting visible (open) rows
77-
const countRows = (items: SectionRow[]): number => {
78-
return items.reduce((count, item) => {
79-
const isOpen = openItemKeys?.has(item.rowID)
80-
return count + 1 + (item.rows && isOpen ? countRows(item.rows) : 0)
77+
const countRows = (rows: SectionRow[]): number => {
78+
return rows.reduce((count, row) => {
79+
const isOpen = openItemKeys?.has(row.itemKey)
80+
return count + 1 + (row.rows && isOpen ? countRows(row.rows) : 0)
8181
}, 0)
8282
}
8383

@@ -86,7 +86,7 @@ export const TableSection: React.FC<RenderTableSectionProps> = ({
8686
let offset = rowIndexOffset
8787
for (let i = 0; i < index; i++) {
8888
offset += 1
89-
const isOpen = openItemKeys?.has(rows[i].rowID)
89+
const isOpen = openItemKeys?.has(rows[i].itemKey)
9090
if (rows[i].rows && isOpen) {
9191
offset += countRows(rows[i].rows || [])
9292
}
@@ -99,7 +99,7 @@ export const TableSection: React.FC<RenderTableSectionProps> = ({
9999
{rows.map((rowItem, sectionRowIndex: number) => {
100100
const absoluteRowIndex = getAbsoluteRowIndex(sectionRowIndex)
101101
const isLastRow = rows.length - 1 === sectionRowIndex
102-
const hasNestedRows = Boolean(rowItem?.rows?.length) && openItemKeys?.has(rowItem.rowID)
102+
const hasNestedRows = Boolean(rowItem?.rows?.length) && openItemKeys?.has(rowItem.itemKey)
103103
const isRowAtRootLevel = level === 0 || (isLastRow && isLastRowOfRoot)
104104

105105
// Calculate drop target items based on position in hierarchy
@@ -129,12 +129,12 @@ export const TableSection: React.FC<RenderTableSectionProps> = ({
129129
? firstCellWidth + segmentWidth * (level - targetItems.length + 1) + 28
130130
: firstCellWidth + segmentWidth * (hasNestedRows ? level + 1 : level) + 28
131131

132-
const isRowSelected = selectedItemKeys.has(rowItem.rowID)
132+
const isRowSelected = selectedItemKeys.has(rowItem.itemKey)
133133
const isInvalidTarget = hasSelectedAncestor || isRowSelected
134134
const isFirstRowAtRootLevel = level === 0 && sectionRowIndex === 0
135135

136136
const renderResult = (
137-
<React.Fragment key={rowItem.rowID}>
137+
<React.Fragment key={rowItem.itemKey}>
138138
<Row
139139
absoluteRowIndex={absoluteRowIndex}
140140
columns={columns}

packages/ui/src/elements/TreeView/NestedSectionsTable/index.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
4545
let count = 0
4646
for (const row of rows) {
4747
count++
48-
if (row.rows && openItemKeys?.has(row.rowID)) {
48+
if (row.rows && openItemKeys?.has(row.itemKey)) {
4949
count += countVisibleRows(row.rows)
5050
}
5151
}
@@ -69,7 +69,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
6969
return row
7070
}
7171
currentIndex++
72-
if (row.rows && openItemKeys?.has(row.rowID)) {
72+
if (row.rows && openItemKeys?.has(row.itemKey)) {
7373
const found = findRow(row.rows)
7474
if (found) {
7575
return found
@@ -86,19 +86,19 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
8686

8787
// Get visual index from row ID
8888
const getIndexFromRowID = React.useCallback(
89-
(rowID: null | number | string): number => {
90-
if (rowID === null) {
89+
(rowItemKey: ItemKey | null): number => {
90+
if (rowItemKey === null) {
9191
return -1
9292
}
9393

9494
let currentIndex = 0
9595
const findIndex = (rows: SectionRow[]): number => {
9696
for (const row of rows) {
97-
if (row.rowID === rowID) {
97+
if (row.itemKey === rowItemKey) {
9898
return currentIndex
9999
}
100100
currentIndex++
101-
if (row.rows && openItemKeys?.has(row.rowID)) {
101+
if (row.rows && openItemKeys?.has(row.itemKey)) {
102102
const found = findIndex(row.rows)
103103
if (found !== -1) {
104104
return found
@@ -161,7 +161,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
161161
for (let i = startIndex; i <= endIndex; i++) {
162162
const row = getRowAtVisibleIndex(i)
163163
if (row && isRowFocusable(row)) {
164-
rangeItemKeys.push(row.rowID)
164+
rangeItemKeys.push(row.itemKey)
165165
}
166166
}
167167

@@ -203,21 +203,21 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
203203
event.preventDefault()
204204

205205
const direction: -1 | 1 = code === 'ArrowUp' ? -1 : 1
206-
const currentIndex = getIndexFromRowID(row.rowID)
206+
const currentIndex = getIndexFromRowID(row.itemKey)
207207
let nextIndex = currentIndex + direction
208208

209209
// Find next focusable row
210210
while (nextIndex >= 0 && nextIndex < totalVisibleRows) {
211211
const nextRow = getRowAtVisibleIndex(nextIndex)
212212
if (nextRow && isRowFocusable(nextRow)) {
213-
setFocusedRowID(nextRow.rowID)
213+
setFocusedRowID(nextRow.itemKey)
214214

215215
// Handle shift+arrow for range selection
216216
if (shiftKey) {
217217
// Pass the selection event with shiftKey to the next row
218218
// The parent's selection logic should handle range selection
219219
onSelectionChange({
220-
itemKey: nextRow.rowID,
220+
itemKey: nextRow.itemKey,
221221
options: { ctrlKey, metaKey, shiftKey },
222222
})
223223
}
@@ -235,7 +235,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
235235
// Handle expand/collapse for rows with children
236236
if (row.rows?.length || row.hasChildren) {
237237
event.preventDefault()
238-
toggleRowExpand(row.rowID)
238+
toggleRowExpand(row.itemKey)
239239
}
240240
break
241241
}
@@ -264,7 +264,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
264264
case 'Space': {
265265
event.preventDefault()
266266
onSelectionChange({
267-
itemKey: row.rowID,
267+
itemKey: row.itemKey,
268268
options: { ctrlKey, metaKey, shiftKey },
269269
})
270270
break
@@ -319,7 +319,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
319319
targetItem: null | SectionRow
320320
}) => {
321321
setHoveredRowItemKey(newHoveredRowItemKey || null)
322-
setTargetParentID(targetItem?.rowID || null)
322+
setTargetParentID(targetItem?.itemKey || null)
323323
},
324324
[],
325325
)
@@ -344,7 +344,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
344344
event.over.data.current.type === 'tree-view-table' &&
345345
'targetItem' in event.over.data.current
346346
) {
347-
void onDrop({ targetItemKey: event.over.data.current.targetItem?.rowID })
347+
void onDrop({ targetItemKey: event.over.data.current.targetItem?.itemKey })
348348
}
349349
},
350350
onDragStart() {
@@ -379,7 +379,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
379379
if (selectedItemKeys && selectedItemKeys.size > 0) {
380380
setFocusedRowID(Array.from(selectedItemKeys)[0])
381381
} else if (focusedRowID === null && sections && sections.length > 0) {
382-
setFocusedRowID(sections[0].rowID)
382+
setFocusedRowID(sections[0].itemKey)
383383
}
384384
}
385385
}}
@@ -404,7 +404,7 @@ export const NestedSectionsTable: React.FC<NestedSectionsTableProps> = ({
404404
// Convert index back to row ID
405405
const row = getRowAtVisibleIndex(index)
406406
if (row) {
407-
setFocusedRowID(row.rowID)
407+
setFocusedRowID(row.itemKey)
408408
}
409409
}}
410410
onRowDrag={onRowDrag}

packages/ui/src/elements/TreeView/NestedSectionsTable/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export type ItemKey = `${string}-${number | string}`
22
export type SectionRow = {
3+
itemKey: ItemKey
34
name: string
4-
rowID: ItemKey
55
rows?: SectionRow[]
66
} & Record<string, any>
77

packages/ui/src/elements/TreeView/utils/itemsToSectionRows.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ type Args = {
1010
export type ItemKey = `${string}-${number | string}`
1111

1212
export function itemsToSectionRows({ i18nLanguage, items }: Args): SectionRow[] {
13-
// Create a map for quick lookups
14-
const itemMap = new Map<ItemKey, TreeViewItem>()
15-
items.forEach((item) => {
16-
itemMap.set(item.itemKey, item)
17-
})
18-
1913
// Create a map to store section rows
2014
const sectionRowMap = new Map<ItemKey, SectionRow>()
2115

@@ -24,7 +18,7 @@ export function itemsToSectionRows({ i18nLanguage, items }: Args): SectionRow[]
2418
sectionRowMap.set(item.itemKey, {
2519
name: item.value.title,
2620
hasChildren: item.hasChildren,
27-
rowID: item.itemKey,
21+
itemKey: item.itemKey,
2822
rows: [],
2923
updatedAt: item.value.updatedAt
3024
? new Date(item.value.updatedAt).toLocaleDateString(i18nLanguage, {

packages/ui/src/providers/TreeView/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ export function TreeViewProvider({
382382
const isRowFocusable = React.useCallback(
383383
(row: SectionRow) => {
384384
const unfocusableIDs = getAllDescendantIDs({ itemKeys: selectedItemKeys, items })
385-
return !unfocusableIDs.has(row.rowID)
385+
return !unfocusableIDs.has(row.itemKey)
386386
},
387387
[selectedItemKeys, items],
388388
)

0 commit comments

Comments
 (0)