@react-spectrum/table 3.3.2 → 3.3.3-nightly.3472
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/main.css +1 -1
- package/dist/main.js +45 -18
- package/dist/main.js.map +1 -1
- package/dist/module.js +48 -21
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +27 -27
- package/src/Resizer.tsx +2 -2
- package/src/TableView.tsx +63 -43
package/src/TableView.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import {chain, mergeProps, useLayoutEffect} from '@react-aria/utils';
|
|
|
15
15
|
import {Checkbox} from '@react-spectrum/checkbox';
|
|
16
16
|
import {classNames, useDOMRef, useFocusableRef, useStyleProps, useUnwrapDOMRef} from '@react-spectrum/utils';
|
|
17
17
|
import {DOMRef, FocusableRef} from '@react-types/shared';
|
|
18
|
-
import {FocusRing, useFocusRing} from '@react-aria/focus';
|
|
18
|
+
import {FocusRing, FocusScope, useFocusRing} from '@react-aria/focus';
|
|
19
19
|
import {GridNode} from '@react-types/grid';
|
|
20
20
|
// @ts-ignore
|
|
21
21
|
import intlMessages from '../intl/*.json';
|
|
@@ -81,7 +81,8 @@ interface TableContextValue<T> {
|
|
|
81
81
|
state: TableState<T>,
|
|
82
82
|
layout: TableLayout<T>,
|
|
83
83
|
columnState: TableColumnResizeState<T>,
|
|
84
|
-
headerRowHovered: boolean
|
|
84
|
+
headerRowHovered: boolean,
|
|
85
|
+
isEmpty: boolean
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
const TableContext = React.createContext<TableContextValue<unknown>>(null);
|
|
@@ -252,6 +253,7 @@ function TableView<T extends object>(props: SpectrumTableProps<T>, ref: DOMRef<H
|
|
|
252
253
|
return <TableSelectAllCell column={item} />;
|
|
253
254
|
}
|
|
254
255
|
|
|
256
|
+
// TODO: consider this case, what if we have hidden headers and a empty table
|
|
255
257
|
if (item.props.hideHeader) {
|
|
256
258
|
return (
|
|
257
259
|
<TooltipTrigger placement="top" trigger="focus">
|
|
@@ -304,11 +306,13 @@ function TableView<T extends object>(props: SpectrumTableProps<T>, ref: DOMRef<H
|
|
|
304
306
|
setHorizontalScollbarVisible(bodyRef.current.clientHeight + 2 < bodyRef.current.offsetHeight);
|
|
305
307
|
}
|
|
306
308
|
}, []);
|
|
309
|
+
let {isFocusVisible, focusProps} = useFocusRing();
|
|
310
|
+
let isEmpty = state.collection.size === 0;
|
|
307
311
|
|
|
308
312
|
return (
|
|
309
|
-
<TableContext.Provider value={{state, layout, columnState, headerRowHovered}}>
|
|
313
|
+
<TableContext.Provider value={{state, layout, columnState, headerRowHovered, isEmpty}}>
|
|
310
314
|
<TableVirtualizer
|
|
311
|
-
{...gridProps}
|
|
315
|
+
{...mergeProps(gridProps, focusProps)}
|
|
312
316
|
{...styleProps}
|
|
313
317
|
className={
|
|
314
318
|
classNames(
|
|
@@ -337,13 +341,14 @@ function TableView<T extends object>(props: SpectrumTableProps<T>, ref: DOMRef<H
|
|
|
337
341
|
onVisibleRectChange={onVisibleRectChange}
|
|
338
342
|
domRef={domRef}
|
|
339
343
|
bodyRef={bodyRef}
|
|
344
|
+
isFocusVisible={isFocusVisible}
|
|
340
345
|
getColumnWidth={columnState.getColumnWidth} />
|
|
341
346
|
</TableContext.Provider>
|
|
342
347
|
);
|
|
343
348
|
}
|
|
344
349
|
|
|
345
350
|
// This is a custom Virtualizer that also has a header that syncs its scroll position with the body.
|
|
346
|
-
function TableVirtualizer({layout, collection, focusedKey, renderView, renderWrapper, domRef, bodyRef, setTableWidth, getColumnWidth, onVisibleRectChange: onVisibleRectChangeProp, ...otherProps}) {
|
|
351
|
+
function TableVirtualizer({layout, collection, focusedKey, renderView, renderWrapper, domRef, bodyRef, setTableWidth, getColumnWidth, onVisibleRectChange: onVisibleRectChangeProp, isFocusVisible, ...otherProps}) {
|
|
347
352
|
let {direction} = useLocale();
|
|
348
353
|
let headerRef = useRef<HTMLDivElement>();
|
|
349
354
|
let loadingState = collection.body.props.loadingState;
|
|
@@ -414,37 +419,48 @@ function TableVirtualizer({layout, collection, focusedKey, renderView, renderWra
|
|
|
414
419
|
}, [state.contentSize, state.virtualizer, state.isAnimating, onLoadMore, isLoading]);
|
|
415
420
|
|
|
416
421
|
return (
|
|
417
|
-
<
|
|
418
|
-
{...mergeProps(otherProps, virtualizerProps)}
|
|
419
|
-
ref={domRef}>
|
|
422
|
+
<FocusScope>
|
|
420
423
|
<div
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
424
|
+
// Override virtualizer provided tabindex if TableView is empty so it is tabbable.
|
|
425
|
+
{...mergeProps(otherProps, virtualizerProps, collection.size === 0 && {tabIndex: 0})}
|
|
426
|
+
ref={domRef}>
|
|
427
|
+
<div
|
|
428
|
+
role="presentation"
|
|
429
|
+
className={classNames(styles, 'spectrum-Table-headWrapper')}
|
|
430
|
+
style={{
|
|
431
|
+
width: visibleRect.width,
|
|
432
|
+
height: headerHeight,
|
|
433
|
+
overflow: 'hidden',
|
|
434
|
+
position: 'relative',
|
|
435
|
+
willChange: state.isScrolling ? 'scroll-position' : '',
|
|
436
|
+
transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined
|
|
437
|
+
}}
|
|
438
|
+
ref={headerRef}>
|
|
439
|
+
{state.visibleViews[0]}
|
|
440
|
+
</div>
|
|
441
|
+
<ScrollView
|
|
442
|
+
role="presentation"
|
|
443
|
+
className={
|
|
444
|
+
classNames(
|
|
445
|
+
styles,
|
|
446
|
+
'spectrum-Table-body',
|
|
447
|
+
{
|
|
448
|
+
'focus-ring': isFocusVisible
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
}
|
|
452
|
+
style={{flex: 1}}
|
|
453
|
+
innerStyle={{overflow: 'visible', transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined}}
|
|
454
|
+
ref={bodyRef}
|
|
455
|
+
contentSize={state.contentSize}
|
|
456
|
+
onVisibleRectChange={chain(onVisibleRectChange, onVisibleRectChangeProp)}
|
|
457
|
+
onScrollStart={state.startScrolling}
|
|
458
|
+
onScrollEnd={state.endScrolling}
|
|
459
|
+
onScroll={onScroll}>
|
|
460
|
+
{state.visibleViews[1]}
|
|
461
|
+
</ScrollView>
|
|
433
462
|
</div>
|
|
434
|
-
|
|
435
|
-
role="presentation"
|
|
436
|
-
className={classNames(styles, 'spectrum-Table-body')}
|
|
437
|
-
style={{flex: 1}}
|
|
438
|
-
innerStyle={{overflow: 'visible', transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined}}
|
|
439
|
-
ref={bodyRef}
|
|
440
|
-
contentSize={state.contentSize}
|
|
441
|
-
onVisibleRectChange={chain(onVisibleRectChange, onVisibleRectChangeProp)}
|
|
442
|
-
onScrollStart={state.startScrolling}
|
|
443
|
-
onScrollEnd={state.endScrolling}
|
|
444
|
-
onScroll={onScroll}>
|
|
445
|
-
{state.visibleViews[1]}
|
|
446
|
-
</ScrollView>
|
|
447
|
-
</div>
|
|
463
|
+
</FocusScope>
|
|
448
464
|
);
|
|
449
465
|
}
|
|
450
466
|
|
|
@@ -461,7 +477,8 @@ function TableHeader({children, ...otherProps}) {
|
|
|
461
477
|
function TableColumnHeader(props) {
|
|
462
478
|
let {column} = props;
|
|
463
479
|
let ref = useRef<HTMLDivElement>(null);
|
|
464
|
-
let {state} = useTableContext();
|
|
480
|
+
let {state, isEmpty} = useTableContext();
|
|
481
|
+
let {pressProps, isPressed} = usePress({isDisabled: isEmpty});
|
|
465
482
|
let {columnHeaderProps} = useTableColumnHeader({
|
|
466
483
|
node: column,
|
|
467
484
|
isVirtualized: true
|
|
@@ -469,9 +486,9 @@ function TableColumnHeader(props) {
|
|
|
469
486
|
|
|
470
487
|
let columnProps = column.props as SpectrumColumnProps<unknown>;
|
|
471
488
|
|
|
472
|
-
let {hoverProps, isHovered} = useHover(props);
|
|
489
|
+
let {hoverProps, isHovered} = useHover({...props, isDisabled: isEmpty});
|
|
473
490
|
|
|
474
|
-
const allProps = [columnHeaderProps, hoverProps];
|
|
491
|
+
const allProps = [columnHeaderProps, hoverProps, pressProps];
|
|
475
492
|
|
|
476
493
|
return (
|
|
477
494
|
<FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
|
|
@@ -483,6 +500,7 @@ function TableColumnHeader(props) {
|
|
|
483
500
|
styles,
|
|
484
501
|
'spectrum-Table-headCell',
|
|
485
502
|
{
|
|
503
|
+
'is-active': isPressed,
|
|
486
504
|
'is-resizable': columnProps.allowsResizing,
|
|
487
505
|
'is-sortable': columnProps.allowsSorting,
|
|
488
506
|
'is-sorted-desc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'descending',
|
|
@@ -513,8 +531,9 @@ function TableColumnHeader(props) {
|
|
|
513
531
|
}
|
|
514
532
|
|
|
515
533
|
let _TableColumnHeaderButton = (props, ref: FocusableRef<HTMLDivElement>) => {
|
|
534
|
+
let {isEmpty} = useTableContext();
|
|
516
535
|
let domRef = useFocusableRef(ref);
|
|
517
|
-
let {buttonProps} = useButton({...props, elementType: 'div'}, domRef);
|
|
536
|
+
let {buttonProps} = useButton({...props, elementType: 'div', isDisabled: isEmpty}, domRef);
|
|
518
537
|
return (
|
|
519
538
|
<div className={classNames(styles, 'spectrum-Table-headCellContents')}>
|
|
520
539
|
<FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
|
|
@@ -530,16 +549,17 @@ function ResizableTableColumnHeader(props) {
|
|
|
530
549
|
let ref = useRef(null);
|
|
531
550
|
let triggerRef = useRef(null);
|
|
532
551
|
let resizingRef = useRef(null);
|
|
533
|
-
let {state, columnState, headerRowHovered} = useTableContext();
|
|
552
|
+
let {state, columnState, headerRowHovered, isEmpty} = useTableContext();
|
|
534
553
|
let stringFormatter = useLocalizedStringFormatter(intlMessages);
|
|
554
|
+
let {pressProps, isPressed} = usePress({isDisabled: isEmpty});
|
|
535
555
|
let {columnHeaderProps} = useTableColumnHeader({
|
|
536
556
|
node: column,
|
|
537
557
|
isVirtualized: true,
|
|
538
558
|
hasMenu: true
|
|
539
559
|
}, state, ref);
|
|
540
|
-
let {hoverProps, isHovered} = useHover(props);
|
|
560
|
+
let {hoverProps, isHovered} = useHover({...props, isDisabled: isEmpty});
|
|
541
561
|
|
|
542
|
-
const allProps = [columnHeaderProps, hoverProps];
|
|
562
|
+
const allProps = [columnHeaderProps, hoverProps, pressProps];
|
|
543
563
|
|
|
544
564
|
let columnProps = column.props as SpectrumColumnProps<unknown>;
|
|
545
565
|
|
|
@@ -589,7 +609,7 @@ function ResizableTableColumnHeader(props) {
|
|
|
589
609
|
}
|
|
590
610
|
}, [columnState.currentlyResizingColumn, column.key]);
|
|
591
611
|
|
|
592
|
-
let showResizer = headerRowHovered || columnState.currentlyResizingColumn != null;
|
|
612
|
+
let showResizer = !isEmpty && (headerRowHovered || columnState.currentlyResizingColumn != null);
|
|
593
613
|
|
|
594
614
|
return (
|
|
595
615
|
<FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
|
|
@@ -601,6 +621,7 @@ function ResizableTableColumnHeader(props) {
|
|
|
601
621
|
styles,
|
|
602
622
|
'spectrum-Table-headCell',
|
|
603
623
|
{
|
|
624
|
+
'is-active': isPressed,
|
|
604
625
|
'is-resizable': columnProps.allowsResizing,
|
|
605
626
|
'is-sortable': columnProps.allowsSorting,
|
|
606
627
|
'is-sorted-desc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'descending',
|
|
@@ -685,7 +706,6 @@ function TableSelectAllCell({column}) {
|
|
|
685
706
|
}
|
|
686
707
|
<Checkbox
|
|
687
708
|
{...checkboxProps}
|
|
688
|
-
isDisabled={isSingleSelectionMode}
|
|
689
709
|
isEmphasized
|
|
690
710
|
UNSAFE_style={isSingleSelectionMode ? {visibility: 'hidden'} : undefined}
|
|
691
711
|
UNSAFE_className={classNames(styles, 'spectrum-Table-checkbox')} />
|