@jetbrains/ring-ui 8.0.0-beta.1 → 8.0.0-beta.10
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/babel.config.js +1 -9
- package/components/alert/alert-actions.d.ts +4 -0
- package/components/alert/alert-actions.js +5 -0
- package/components/alert/alert-heading.d.ts +4 -0
- package/components/alert/alert-heading.js +6 -0
- package/components/alert/alert.css +63 -22
- package/components/alert/alert.d.ts +14 -1
- package/components/alert/alert.js +34 -19
- package/components/alert/container.css +1 -2
- package/components/alert-service/alert-service.d.ts +2 -1
- package/components/alert-service/alert-service.js +8 -4
- package/components/auth/auth-core.d.ts +5 -9
- package/components/auth/auth-core.js +56 -15
- package/components/auth-dialog-service/auth-dialog-service.js +2 -2
- package/components/avatar/avatar-info.js +0 -2
- package/components/avatar/avatar-size.d.ts +0 -4
- package/components/avatar/avatar-size.js +0 -4
- package/components/avatar/avatar.js +0 -6
- package/components/avatar/fallback-avatar.js +0 -28
- package/components/avatar-stack/avatar-stack.js +1 -1
- package/components/banner/banner.css +3 -3
- package/components/button/button.css +4 -4
- package/components/button/button.d.ts +0 -4
- package/components/button/button.js +2 -7
- package/components/button-group/button-group.css +5 -5
- package/components/checkbox/checkbox.d.ts +1 -1
- package/components/collapse/collapse-content.d.ts +7 -0
- package/components/collapse/collapse-content.js +44 -11
- package/components/collapse/collapse-context.d.ts +2 -0
- package/components/collapse/collapse-context.js +2 -0
- package/components/collapse/collapse-control.js +2 -2
- package/components/collapse/collapse.css +8 -2
- package/components/collapse/collapse.d.ts +9 -0
- package/components/collapse/collapse.js +12 -3
- package/components/{expand → collapsible-group}/collapsible-group.css +7 -1
- package/components/collapsible-group/collapsible-group.d.ts +33 -0
- package/components/{expand → collapsible-group}/collapsible-group.js +13 -21
- package/components/confirm-service/confirm-service.js +2 -2
- package/components/data-list/data-list.d.ts +1 -1
- package/components/data-list/data-list.mock.d.ts +1 -1
- package/components/data-list/item.d.ts +1 -1
- package/components/data-list/selection.d.ts +1 -1
- package/components/data-list/selection.js +1 -1
- package/components/date-picker/consts.d.ts +1 -0
- package/components/date-picker/date-input.js +6 -2
- package/components/date-picker/months.js +2 -2
- package/components/date-picker/use-scroll-behavior.js +5 -6
- package/components/date-picker/years.js +2 -2
- package/components/dialog/dialog.d.ts +2 -2
- package/components/dialog/dialog.js +2 -2
- package/components/dropdown-menu/dropdown-menu.d.ts +4 -4
- package/components/dropdown-menu/dropdown-menu.js +4 -4
- package/components/editable-heading/editable-heading.d.ts +1 -2
- package/components/editable-heading/editable-heading.js +18 -19
- package/components/global/compose-refs.d.ts +2 -1
- package/components/global/compose-refs.js +24 -8
- package/components/global/create-stateful-context.js +5 -5
- package/components/global/focus-with-temporary-tabindex.d.ts +11 -0
- package/components/global/focus-with-temporary-tabindex.js +21 -0
- package/components/global/intersection-observer-context.d.ts +31 -11
- package/components/global/intersection-observer-context.js +47 -28
- package/components/global/is-within-interactive-element.d.ts +6 -0
- package/components/global/is-within-interactive-element.js +26 -0
- package/components/global/is-within-navigable-element.d.ts +6 -0
- package/components/global/is-within-navigable-element.js +27 -0
- package/components/global/parse-css-duration.d.ts +5 -0
- package/components/global/parse-css-duration.js +13 -0
- package/components/global/rerender-hoc.d.ts +4 -2
- package/components/global/rerender-hoc.js +4 -4
- package/components/global/schedule-with-cleanup.d.ts +12 -0
- package/components/global/schedule-with-cleanup.js +34 -0
- package/components/{legacy-table/selection.d.ts → global/table-selection.d.ts} +14 -14
- package/components/{legacy-table/selection.js → global/table-selection.js} +2 -2
- package/components/global/theme.d.ts +4 -3
- package/components/global/theme.js +8 -8
- package/components/global/variables.css +18 -28
- package/components/global/variables.interface.d.ts +0 -4
- package/components/global/variables_dark.css +18 -25
- package/components/header/header.css +3 -3
- package/components/http/http.d.ts +2 -2
- package/components/http/http.js +2 -2
- package/components/i18n/i18n-context.js +1 -1
- package/components/i18n/i18n.d.ts +1 -0
- package/components/i18n/messages.json +1 -0
- package/components/icon/icon.css +0 -27
- package/components/icon/icon.d.ts +0 -1
- package/components/icon/icon.js +2 -4
- package/components/input/input.d.ts +1 -1
- package/components/island/adaptive-island-hoc.js +4 -4
- package/components/island/content.d.ts +7 -2
- package/components/island/content.js +5 -5
- package/components/legacy-table/cell.js +1 -1
- package/components/legacy-table/header-cell.js +1 -1
- package/components/legacy-table/header.js +1 -1
- package/components/legacy-table/multitable.d.ts +1 -1
- package/components/legacy-table/row.d.ts +1 -1
- package/components/legacy-table/row.js +1 -1
- package/components/legacy-table/selection-adapter.d.ts +3 -3
- package/components/legacy-table/selection-shortcuts-hoc.d.ts +5 -5
- package/components/legacy-table/simple-table.d.ts +2 -2
- package/components/legacy-table/simple-table.js +3 -3
- package/components/legacy-table/smart-table.d.ts +5 -5
- package/components/legacy-table/smart-table.js +3 -3
- package/components/legacy-table/table.js +1 -1
- package/components/list/consts.d.ts +0 -1
- package/components/list/consts.js +0 -1
- package/components/list/list.d.ts +0 -4
- package/components/login-dialog/service.js +2 -2
- package/components/popup/popup.d.ts +2 -0
- package/components/popup/popup.js +2 -2
- package/components/popup/popup.target.d.ts +3 -2
- package/components/popup/popup.target.js +4 -6
- package/components/query-assist/query-assist.d.ts +3 -1
- package/components/query-assist/query-assist.js +2 -2
- package/components/radio/radio-item.d.ts +3 -3
- package/components/radio/radio-item.js +3 -4
- package/components/radio/radio.d.ts +2 -2
- package/components/radio/radio.js +1 -1
- package/components/select/select-popup.d.ts +3 -2
- package/components/select/select-popup.js +3 -3
- package/components/select/select.d.ts +6 -2
- package/components/select/select.js +2 -4
- package/components/selection-toolbar/selection-toolbar.css +86 -0
- package/components/selection-toolbar/selection-toolbar.d.ts +11 -0
- package/components/selection-toolbar/selection-toolbar.js +23 -0
- package/components/slider/slider.js +4 -5
- package/components/tab-trap/tab-trap.d.ts +3 -3
- package/components/tab-trap/tab-trap.js +3 -5
- package/components/table/default-item-renderer.d.ts +41 -11
- package/components/table/default-item-renderer.js +60 -47
- package/components/table/internal/reorder-animation-context.d.ts +21 -0
- package/components/table/internal/reorder-animation-context.js +60 -0
- package/components/table/internal/reorder-handle.d.ts +9 -0
- package/components/table/internal/reorder-handle.js +334 -0
- package/components/table/internal/reorder-layout-context.d.ts +16 -0
- package/components/table/internal/reorder-layout-context.js +69 -0
- package/components/table/internal/table-header.d.ts +1 -0
- package/components/table/internal/table-header.js +143 -0
- package/components/table/internal/virtualization.d.ts +41 -0
- package/components/table/{table-virtualize.js → internal/virtualization.js} +82 -46
- package/components/table/item-virtualization.d.ts +37 -0
- package/components/table/item-virtualization.js +26 -0
- package/components/table/reorder-animation.d.ts +37 -0
- package/components/table/reorder-animation.js +11 -0
- package/components/table/reorder-item-layout.d.ts +32 -0
- package/components/table/reorder-item-layout.js +23 -0
- package/components/table/table-const.d.ts +8 -6
- package/components/table/table-const.js +7 -5
- package/components/table/table-primitives.d.ts +64 -0
- package/components/table/table-primitives.js +34 -0
- package/components/table/table-props.d.ts +304 -0
- package/components/table/table-props.js +1 -0
- package/components/table/table.css +179 -67
- package/components/table/table.d.ts +231 -224
- package/components/table/table.js +327 -2
- package/components/tag/tag.css +3 -3
- package/components/tags-input/tags-input.d.ts +3 -1
- package/components/tooltip/tooltip.d.ts +2 -1
- package/components/tooltip/tooltip.js +6 -5
- package/components/upload/upload.d.ts +4 -3
- package/components/upload/upload.js +3 -7
- package/components/user-agreement/service.js +2 -2
- package/components/user-card/smart-user-card-tooltip.d.ts +1 -1
- package/components/util-stories.d.ts +26 -0
- package/components/util-stories.js +61 -0
- package/package.json +44 -47
- package/components/content-layout/content-layout.css +0 -109
- package/components/content-layout/content-layout.d.ts +0 -20
- package/components/content-layout/content-layout.js +0 -40
- package/components/content-layout/sidebar.d.ts +0 -26
- package/components/content-layout/sidebar.js +0 -71
- package/components/date-picker/use-intersection-observer.d.ts +0 -6
- package/components/date-picker/use-intersection-observer.js +0 -48
- package/components/expand/collapsible-group.d.ts +0 -16
- package/components/global/composeRefs.d.ts +0 -6
- package/components/global/composeRefs.js +0 -7
- package/components/global/use-event-callback.d.ts +0 -1
- package/components/global/use-event-callback.js +0 -15
- package/components/grid/col.d.ts +0 -16
- package/components/grid/col.js +0 -35
- package/components/grid/grid.css +0 -920
- package/components/grid/grid.d.ts +0 -13
- package/components/grid/grid.js +0 -19
- package/components/grid/row.d.ts +0 -21
- package/components/grid/row.js +0 -41
- package/components/old-browsers-message/__mocks__/old-browsers-message.js +0 -1
- package/components/old-browsers-message/old-browsers-message-stop.d.ts +0 -1
- package/components/old-browsers-message/old-browsers-message-stop.js +0 -2
- package/components/old-browsers-message/old-browsers-message.css +0 -26
- package/components/old-browsers-message/old-browsers-message.d.ts +0 -5
- package/components/old-browsers-message/old-browsers-message.js +0 -86
- package/components/old-browsers-message/white-list.d.ts +0 -2
- package/components/old-browsers-message/white-list.js +0 -24
- package/components/table/table-base.d.ts +0 -24
- package/components/table/table-base.js +0 -79
- package/components/table/table-component.d.ts +0 -53
- package/components/table/table-component.js +0 -101
- package/components/table/table-virtualize.d.ts +0 -32
- /package/components/legacy-table/{table.css → legacy-table.css} +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
@import '../global/variables.css';
|
|
2
|
+
|
|
3
|
+
.toolbar {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
max-width: 100%;
|
|
9
|
+
height: calc(var(--ring-unit) * 5);
|
|
10
|
+
padding: 10px calc(var(--ring-unit) * 2);
|
|
11
|
+
|
|
12
|
+
pointer-events: auto;
|
|
13
|
+
|
|
14
|
+
color: var(--ring-white-text-color);
|
|
15
|
+
border-radius: var(--ring-border-radius-large);
|
|
16
|
+
background-color: var(--ring-sidebar-background-color);
|
|
17
|
+
box-shadow:
|
|
18
|
+
0 2px 8px rgb(0 28 54 / 10%),
|
|
19
|
+
0 1px 2px rgb(0 28 54 / 4%);
|
|
20
|
+
|
|
21
|
+
line-height: var(--ring-line-height);
|
|
22
|
+
gap: calc(var(--ring-unit) * 2);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.content {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: calc(var(--ring-unit) * 3);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.selectAll {
|
|
32
|
+
flex: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.actions {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: calc(var(--ring-unit) * 2);
|
|
39
|
+
|
|
40
|
+
min-width: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.closeAction {
|
|
44
|
+
flex: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.separator {
|
|
48
|
+
flex: none;
|
|
49
|
+
|
|
50
|
+
width: 1px;
|
|
51
|
+
height: calc(var(--ring-unit) * 2);
|
|
52
|
+
margin-inline: var(--ring-unit);
|
|
53
|
+
|
|
54
|
+
background-color: var(--ring-line-color);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.compact {
|
|
58
|
+
min-width: 0;
|
|
59
|
+
max-width: 100%;
|
|
60
|
+
padding-inline: 12px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.compact .content {
|
|
64
|
+
min-width: 0;
|
|
65
|
+
gap: var(--ring-unit);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.compact .label {
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
|
|
71
|
+
flex: 1 1 auto;
|
|
72
|
+
|
|
73
|
+
min-width: 0;
|
|
74
|
+
|
|
75
|
+
white-space: nowrap;
|
|
76
|
+
|
|
77
|
+
text-overflow: ellipsis;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.compact .actions {
|
|
81
|
+
flex-shrink: 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.compact .separator {
|
|
85
|
+
margin-inline: 2px;
|
|
86
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
|
+
export interface SelectionToolbarProps extends ComponentPropsWithRef<'div'> {
|
|
3
|
+
label: ReactNode;
|
|
4
|
+
selectAll?: ReactNode;
|
|
5
|
+
closeAction: ReactNode;
|
|
6
|
+
compact?: boolean;
|
|
7
|
+
'data-test'?: string | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function SelectionToolbar({ ref, label, selectAll, closeAction, compact, className, children, 'data-test': dataTest, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...restProps }: SelectionToolbarProps): import("react").JSX.Element;
|
|
10
|
+
export declare function SelectionToolbarSeparator(): import("react").JSX.Element;
|
|
11
|
+
export default SelectionToolbar;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useId } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import dataTests from '../global/data-tests';
|
|
4
|
+
import Theme, { ThemeProvider } from '../global/theme';
|
|
5
|
+
import styles from './selection-toolbar.css';
|
|
6
|
+
export function SelectionToolbar({ ref, label, selectAll, closeAction, compact, className, children, 'data-test': dataTest, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...restProps }) {
|
|
7
|
+
const labelId = useId();
|
|
8
|
+
const hasSelectAll = selectAll != null;
|
|
9
|
+
return (<ThemeProvider {...restProps} ref={ref} theme={Theme.DARK} role='group' aria-label={ariaLabel} aria-labelledby={ariaLabelledBy ?? (ariaLabel == null ? labelId : undefined)} data-test={dataTests('ring-selection-toolbar', dataTest)} className={classNames(styles.toolbar, { [styles.compact]: compact }, className)}>
|
|
10
|
+
<div className={styles.content}>
|
|
11
|
+
<span id={labelId} className={styles.label}>
|
|
12
|
+
{label}
|
|
13
|
+
</span>
|
|
14
|
+
{hasSelectAll && <span className={styles.selectAll}>{selectAll}</span>}
|
|
15
|
+
<div className={styles.actions}>{children}</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div className={styles.closeAction}>{closeAction}</div>
|
|
18
|
+
</ThemeProvider>);
|
|
19
|
+
}
|
|
20
|
+
export function SelectionToolbarSeparator() {
|
|
21
|
+
return <span role='separator' aria-orientation='vertical' className={styles.separator}/>;
|
|
22
|
+
}
|
|
23
|
+
export default SelectionToolbar;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Fragment, useEffect, useRef, useState } from 'react';
|
|
1
|
+
import { Fragment, useEffect, useEffectEvent, useRef, useState } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { isArray } from '../global/typescript-utils';
|
|
5
5
|
import Shortcuts from '../shortcuts/shortcuts';
|
|
6
6
|
import getUID from '../global/get-uid';
|
|
7
7
|
import { adjustValues, calculateMarks, calculateValue, HUNDRED, toPercent, toRange, validateValue } from './slider.utils';
|
|
8
|
-
import useEventCallback from '../global/use-event-callback';
|
|
9
8
|
import styles from './slider.css';
|
|
10
9
|
export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1, disabled, marks, showTicks, showTag, className, renderTag, onChange, }) => {
|
|
11
10
|
const ref = useRef(null);
|
|
@@ -86,7 +85,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
|
|
|
86
85
|
setIsDragging(true);
|
|
87
86
|
previouslyDragged.current = false;
|
|
88
87
|
};
|
|
89
|
-
const handleMouseUp =
|
|
88
|
+
const handleMouseUp = useEffectEvent(({ pageX }) => {
|
|
90
89
|
const nextValues = adjustValues(validValues, ref, draggedIndex, pageX, max, min, validStep);
|
|
91
90
|
if (nextValues[0] > nextValues[1]) {
|
|
92
91
|
nextValues.reverse();
|
|
@@ -96,7 +95,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
|
|
|
96
95
|
setIsDragging(false);
|
|
97
96
|
previouslyDragged.current = true;
|
|
98
97
|
});
|
|
99
|
-
const handleMouseMove =
|
|
98
|
+
const handleMouseMove = useEffectEvent(({ pageX }) => {
|
|
100
99
|
const nextValues = adjustValues(validValues, ref, draggedIndex, pageX, max, min, validStep);
|
|
101
100
|
if (nextValues[0] > nextValues[1]) {
|
|
102
101
|
nextValues.reverse();
|
|
@@ -120,7 +119,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
|
|
|
120
119
|
window.removeEventListener('mousemove', handleMouseMove);
|
|
121
120
|
window.removeEventListener('mouseup', handleMouseUp);
|
|
122
121
|
};
|
|
123
|
-
}, [isDragging, disabled
|
|
122
|
+
}, [isDragging, disabled]);
|
|
124
123
|
return (<div ref={ref} role='presentation' // contains interactive elements
|
|
125
124
|
className={classNames(styles.slider, className, {
|
|
126
125
|
[styles.disabled]: disabled,
|
|
@@ -2,6 +2,7 @@ import { type HTMLAttributes, type ReactNode } from 'react';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
export declare const FOCUSABLE_ELEMENTS = "input, button, select, textarea, a[href], *[tabindex]:not([data-trap-button]):not([data-scrollable-container])";
|
|
4
4
|
export interface TabTrapProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
ref?: React.Ref<TabTrapObject>;
|
|
5
6
|
children: ReactNode;
|
|
6
7
|
trapDisabled?: boolean;
|
|
7
8
|
autoFocusFirst?: boolean;
|
|
@@ -11,8 +12,7 @@ export interface TabTrapProps extends HTMLAttributes<HTMLElement> {
|
|
|
11
12
|
/**
|
|
12
13
|
* @name TabTrap
|
|
13
14
|
*/
|
|
14
|
-
interface
|
|
15
|
+
export interface TabTrapObject {
|
|
15
16
|
node: HTMLElement | null;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
export default TabTrap;
|
|
18
|
+
export default function TabTrap({ ref, children, trapDisabled, autoFocusFirst, focusBackOnClose, focusBackOnExit, ...restProps }: TabTrapProps): React.JSX.Element;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { isNodeInVisiblePartOfPage } from '../global/dom';
|
|
4
4
|
import styles from './tab-trap.css';
|
|
5
5
|
export const FOCUSABLE_ELEMENTS = 'input, button, select, textarea, a[href], *[tabindex]:not([data-trap-button]):not([data-scrollable-container])';
|
|
6
|
-
|
|
7
|
-
const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, autoFocusFirst = true, focusBackOnClose = true, focusBackOnExit = false, ...restProps }, ref) {
|
|
6
|
+
export default function TabTrap({ ref, children, trapDisabled = false, autoFocusFirst = true, focusBackOnClose = true, focusBackOnExit = false, ...restProps }) {
|
|
8
7
|
const nodeRef = useRef(null);
|
|
9
8
|
const trapButtonNodeRef = useRef(null);
|
|
10
9
|
const previousFocusedNodeRef = useRef(null);
|
|
@@ -121,5 +120,4 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
121
120
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
122
121
|
tabIndex={0} onFocus={restoreFocusOrFocusFirst} data-trap-button/>
|
|
123
122
|
</div>);
|
|
124
|
-
}
|
|
125
|
-
export default TabTrap;
|
|
123
|
+
}
|
|
@@ -1,25 +1,55 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ComponentPropsWithRef } from 'react';
|
|
2
2
|
export interface DefaultItemRendererProps {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* The index of the `data` item to render.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
index: number;
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* If `true`, the row will be focusable with up/down arrow keys.
|
|
9
|
+
* Focus is implemented using the
|
|
10
|
+
* ["roving tabindex"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Guides/Keyboard-navigable_JavaScript_widgets#technique_1_roving_tabindex)
|
|
11
|
+
* technique, that is, only the focused row has `tabIndex={0}`.
|
|
9
12
|
*/
|
|
10
|
-
|
|
13
|
+
keyboardFocusable?: boolean;
|
|
11
14
|
/**
|
|
12
|
-
* Changes the
|
|
13
|
-
* Note that `false`
|
|
15
|
+
* Changes the background on hover and applies the pointer cursor.
|
|
16
|
+
* Note that `false` does not mean the row cannot handle `onClick`.
|
|
14
17
|
*/
|
|
15
18
|
clickable?: boolean;
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
20
|
+
* If `true`, the row is highlighted as selected with a different background color.
|
|
21
|
+
*/
|
|
22
|
+
selected?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The nesting level of an item. Applies an indent for columns with
|
|
25
|
+
* `Column.indent` set to `true`. `0`, negative values, and an unset value
|
|
26
|
+
* mean no indent.
|
|
19
27
|
*/
|
|
20
28
|
level?: number;
|
|
29
|
+
/**
|
|
30
|
+
* When set to `true`, does not control item virtualization.
|
|
31
|
+
* Useful when you include `DefaultItemRenderer` as a part of a custom row renderer,
|
|
32
|
+
* and track the visibility yourself.
|
|
33
|
+
*/
|
|
34
|
+
noItemVirtualization?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* When set to `true`, does not report the item's boundaries to the reorder system.
|
|
37
|
+
* Useful when you include `DefaultItemRenderer` as a part of a custom row renderer
|
|
38
|
+
* that registers boundaries itself.
|
|
39
|
+
*/
|
|
40
|
+
noReorderLayout?: boolean;
|
|
21
41
|
}
|
|
22
42
|
/**
|
|
23
|
-
*
|
|
43
|
+
* Standard component for rendering a table row.
|
|
44
|
+
*
|
|
45
|
+
* Renders an item using the table's column definitions and lets you
|
|
46
|
+
* configure item-scoped behavior such as selection, keyboard navigation,
|
|
47
|
+
* event handlers, `className`, and `ref`.
|
|
48
|
+
*
|
|
49
|
+
* Note that row-level click and keyboard handlers are not discoverable
|
|
50
|
+
* by assistive technologies. Make sure that any functionality relying on
|
|
51
|
+
* them (such as selection or expand/collapse) is also available through
|
|
52
|
+
* accessible controls, such as checkboxes or buttons with accessible
|
|
53
|
+
* labels.
|
|
24
54
|
*/
|
|
25
|
-
export declare function DefaultItemRenderer<T>({
|
|
55
|
+
export declare function DefaultItemRenderer<T>({ index, keyboardFocusable, clickable, selected, level, noItemVirtualization, noReorderLayout, ref: userRef, className, ...restProps }: DefaultItemRendererProps & ComponentPropsWithRef<'tr'>): import("react").JSX.Element | null;
|
|
@@ -1,61 +1,74 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { use, useCallback, useRef } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { TablePropsContext } from './table-const';
|
|
4
|
+
import { useComposedRef } from '../global/compose-refs';
|
|
5
|
+
import { useItemVirtualization } from './item-virtualization';
|
|
6
|
+
import { TableCell, TableRow } from './table-primitives';
|
|
7
|
+
import { ReorderAnimationContext } from './internal/reorder-animation-context';
|
|
8
|
+
import { useReorderItemLayout } from './reorder-item-layout';
|
|
6
9
|
import styles from './table.css';
|
|
7
|
-
const INDENT_SIZE = 24;
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
11
|
+
* Standard component for rendering a table row.
|
|
12
|
+
*
|
|
13
|
+
* Renders an item using the table's column definitions and lets you
|
|
14
|
+
* configure item-scoped behavior such as selection, keyboard navigation,
|
|
15
|
+
* event handlers, `className`, and `ref`.
|
|
16
|
+
*
|
|
17
|
+
* Note that row-level click and keyboard handlers are not discoverable
|
|
18
|
+
* by assistive technologies. Make sure that any functionality relying on
|
|
19
|
+
* them (such as selection or expand/collapse) is also available through
|
|
20
|
+
* accessible controls, such as checkboxes or buttons with accessible
|
|
21
|
+
* labels.
|
|
10
22
|
*/
|
|
11
|
-
export function DefaultItemRenderer({
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
export function DefaultItemRenderer({ index, keyboardFocusable, clickable, selected, level, noItemVirtualization, noReorderLayout, ref: userRef, className, ...restProps }) {
|
|
24
|
+
const localRef = useRef(null);
|
|
25
|
+
const composedRef = useComposedRef(userRef, localRef);
|
|
26
|
+
useItemVirtualization({
|
|
27
|
+
index,
|
|
28
|
+
refs: localRef,
|
|
29
|
+
onIntersectionChange: useCallback(([isIntersecting], _i, [element]) => isIntersecting === false &&
|
|
30
|
+
!noItemVirtualization &&
|
|
31
|
+
element?.isConnected &&
|
|
32
|
+
!element.contains(document.activeElement) &&
|
|
33
|
+
!element.previousElementSibling?.contains(document.activeElement) &&
|
|
34
|
+
!element.nextElementSibling?.contains(document.activeElement)
|
|
35
|
+
? element.getBoundingClientRect().height
|
|
36
|
+
: undefined, [noItemVirtualization]),
|
|
19
37
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const focused = selection?.isFocused(item);
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (focused)
|
|
39
|
-
ref.current?.focus();
|
|
40
|
-
}, [focused, ref]);
|
|
41
|
-
function handleBlur(e) {
|
|
42
|
-
onBlur?.(e);
|
|
43
|
-
if (!e.defaultPrevented && focused) {
|
|
44
|
-
onItemFocus?.(null, -1, data);
|
|
45
|
-
}
|
|
38
|
+
useReorderItemLayout({
|
|
39
|
+
disabled: noReorderLayout,
|
|
40
|
+
index,
|
|
41
|
+
getBounds: () => {
|
|
42
|
+
const r = localRef.current?.getBoundingClientRect();
|
|
43
|
+
return { start: r?.top ?? 0, end: r?.bottom ?? 0 };
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const tableProps = use(TablePropsContext);
|
|
47
|
+
if (!tableProps) {
|
|
48
|
+
return null;
|
|
46
49
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
const { reorderAnimation } = use(ReorderAnimationContext);
|
|
51
|
+
const isAnimatedItem = reorderAnimation?.direction === 'items' && reorderAnimation.index === index;
|
|
52
|
+
const animatedColumnIndex = reorderAnimation?.direction === 'columns' ? reorderAnimation.index : undefined;
|
|
53
|
+
const animateClassName = reorderAnimation?.className;
|
|
54
|
+
const { data, columns } = tableProps;
|
|
55
|
+
const item = data[index];
|
|
56
|
+
const indentSize = 24;
|
|
57
|
+
return (<TableRow ref={composedRef} keyboardFocusable={keyboardFocusable} className={classNames(className, clickable && styles.clickableRow, selected && styles.selectedRow, isAnimatedItem && animateClassName)} {...restProps}>
|
|
58
|
+
{columns.map((column, columnIndex) => {
|
|
59
|
+
const { key, tdClassName, indent } = column;
|
|
60
|
+
return (<TableCell key={key} className={classNames(columnIndex === animatedColumnIndex && animateClassName, typeof tdClassName === 'function' ? tdClassName(item, index, data) : tdClassName)} style={indent && level != null && level > 0 ? { paddingInlineStart: `${level * indentSize}px` } : undefined}>
|
|
61
|
+
{column.renderCell?.(item, index, data) ?? getDefaultCellValue(item, columnIndex, key)}
|
|
62
|
+
</TableCell>);
|
|
63
|
+
})}
|
|
51
64
|
</TableRow>);
|
|
52
65
|
}
|
|
53
|
-
function getDefaultCellValue(item, columnIndex) {
|
|
66
|
+
function getDefaultCellValue(item, columnIndex, columnKey) {
|
|
54
67
|
if (Array.isArray(item)) {
|
|
55
|
-
return String(item[columnIndex]
|
|
68
|
+
return String(item[columnIndex]);
|
|
56
69
|
}
|
|
57
70
|
if (item !== null && typeof item === 'object') {
|
|
58
|
-
return String(
|
|
71
|
+
return String(item[String(columnKey)]);
|
|
59
72
|
}
|
|
60
73
|
if (columnIndex === 0) {
|
|
61
74
|
return String(item);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import type { Column } from '../table-props';
|
|
3
|
+
import type { ReorderAnimation } from '../reorder-animation';
|
|
4
|
+
export interface ReorderSpec {
|
|
5
|
+
direction: 'columns' | 'items';
|
|
6
|
+
fromIndex: number;
|
|
7
|
+
insertionIndex: number;
|
|
8
|
+
}
|
|
9
|
+
interface ReorderAnimationContextValue {
|
|
10
|
+
reorderAnimation: ReorderAnimation | null;
|
|
11
|
+
expectReorder: (reorderSpec: ReorderSpec) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const ReorderAnimationContext: import("react").Context<ReorderAnimationContextValue>;
|
|
14
|
+
export declare function useReorderAnimationContextValue<T>({ noColumnReorderAnimation, noItemReorderAnimation, tableRef, data, columns, }: {
|
|
15
|
+
noColumnReorderAnimation: boolean | undefined;
|
|
16
|
+
noItemReorderAnimation: boolean | undefined;
|
|
17
|
+
tableRef: RefObject<HTMLTableElement | null>;
|
|
18
|
+
data: readonly T[];
|
|
19
|
+
columns: readonly Column<T>[];
|
|
20
|
+
}): ReorderAnimationContextValue;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createContext, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { parseCssDuration } from '../../global/parse-css-duration';
|
|
3
|
+
import { requestAnimationFrameWithCleanup, setTimeoutWithCleanup } from '../../global/schedule-with-cleanup';
|
|
4
|
+
import styles from '../table.css';
|
|
5
|
+
/** How long to wait for the data to change after {@link expectReorder} is called. */
|
|
6
|
+
const pendingReorderTimeoutMs = 1000;
|
|
7
|
+
export const ReorderAnimationContext = createContext({
|
|
8
|
+
reorderAnimation: null,
|
|
9
|
+
expectReorder: () => { },
|
|
10
|
+
});
|
|
11
|
+
export function useReorderAnimationContextValue({ noColumnReorderAnimation, noItemReorderAnimation, tableRef, data, columns, }) {
|
|
12
|
+
const [reorderAnimation, setReorderAnimation] = useState(null);
|
|
13
|
+
const pendingReorderRef = useRef(null);
|
|
14
|
+
function expectReorder(reorderSpec) {
|
|
15
|
+
const isColumn = reorderSpec.direction === 'columns';
|
|
16
|
+
if ((isColumn && noColumnReorderAnimation) || (!isColumn && noItemReorderAnimation))
|
|
17
|
+
return;
|
|
18
|
+
if (pendingReorderRef.current) {
|
|
19
|
+
window.clearTimeout(pendingReorderRef.current.timerId);
|
|
20
|
+
}
|
|
21
|
+
const timerId = window.setTimeout(() => {
|
|
22
|
+
pendingReorderRef.current = null;
|
|
23
|
+
}, pendingReorderTimeoutMs);
|
|
24
|
+
pendingReorderRef.current = { ...reorderSpec, timerId, columns, data };
|
|
25
|
+
}
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
return () => {
|
|
28
|
+
if (pendingReorderRef.current) {
|
|
29
|
+
window.clearTimeout(pendingReorderRef.current.timerId);
|
|
30
|
+
pendingReorderRef.current = null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}, []);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const table = tableRef.current;
|
|
36
|
+
const pendingReorder = pendingReorderRef.current;
|
|
37
|
+
if (!table || !pendingReorder)
|
|
38
|
+
return;
|
|
39
|
+
const { direction, data: pendingData, columns: pendingColumns } = pendingReorder;
|
|
40
|
+
const isColumn = direction === 'columns';
|
|
41
|
+
if ((isColumn && columns === pendingColumns) || (!isColumn && data === pendingData))
|
|
42
|
+
return;
|
|
43
|
+
pendingReorderRef.current = null;
|
|
44
|
+
const { fromIndex, insertionIndex } = pendingReorder;
|
|
45
|
+
// Moving forward shifts the array by one, hence -1
|
|
46
|
+
const index = fromIndex < insertionIndex ? insertionIndex - 1 : insertionIndex;
|
|
47
|
+
return requestAnimationFrameWithCleanup(() => setReorderAnimation(prev => prev == null ? { direction, index, phase: 'initial', className: styles.reorderAnimationInitial } : prev));
|
|
48
|
+
}, [data, columns, tableRef]);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (reorderAnimation?.phase === 'initial') {
|
|
51
|
+
return requestAnimationFrameWithCleanup(() => setReorderAnimation(prev => prev === reorderAnimation ? { ...prev, phase: 'fade-out', className: styles.reorderAnimationFadeOut } : prev));
|
|
52
|
+
}
|
|
53
|
+
if (reorderAnimation?.phase === 'fade-out') {
|
|
54
|
+
const fadeOutMs = parseCssDuration(window.getComputedStyle(tableRef.current).getPropertyValue('--reorder-animation-fade-out-duration'));
|
|
55
|
+
return setTimeoutWithCleanup(() => setReorderAnimation(prev => (prev === reorderAnimation ? null : prev)), fadeOutMs);
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}, [reorderAnimation, tableRef]);
|
|
59
|
+
return { reorderAnimation, expectReorder };
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ComponentPropsWithRef } from 'react';
|
|
2
|
+
import type { DragState } from '../table-primitives';
|
|
3
|
+
export declare function ReorderHandle<T>({ direction, index, noDragFrame, noHandleTranslate, onUserDrag, ref: userRef, className, onKeyDown, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onLostPointerCapture, ...restProps }: {
|
|
4
|
+
direction: 'columns' | 'items';
|
|
5
|
+
index: number;
|
|
6
|
+
noDragFrame?: boolean;
|
|
7
|
+
noHandleTranslate?: boolean;
|
|
8
|
+
onUserDrag?: (state: DragState) => void;
|
|
9
|
+
} & ComponentPropsWithRef<'button'>): import("react").JSX.Element;
|