@jetbrains/ring-ui 8.0.0-beta.4 → 8.0.0-beta.6
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/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/banner/banner.css +3 -3
- package/components/button-group/button-group.css +5 -5
- package/components/collapse/collapse-content.d.ts +7 -0
- package/components/collapse/collapse-content.js +41 -6
- package/components/collapse/collapse-context.d.ts +1 -0
- package/components/collapse/collapse-context.js +1 -0
- package/components/collapse/collapse.d.ts +9 -0
- package/components/collapse/collapse.js +2 -1
- package/components/collapsible-group/collapsible-group.css +6 -0
- package/components/collapsible-group/collapsible-group.d.ts +14 -1
- package/components/collapsible-group/collapsible-group.js +4 -3
- package/components/date-picker/consts.d.ts +1 -0
- package/components/date-picker/date-input.js +6 -2
- package/components/expand/collapsible-group.css +4 -0
- package/components/global/variables.css +18 -18
- package/components/global/variables_dark.css +18 -18
- 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.d.ts +1 -0
- package/components/i18n/messages.json +1 -0
- package/components/table/default-item-renderer.d.ts +7 -1
- package/components/table/default-item-renderer.js +18 -5
- 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 -4
- package/components/table/internal/table-header.js +32 -246
- package/components/table/internal/{virtual-items.d.ts → virtualization.d.ts} +10 -3
- package/components/table/internal/{virtual-items.js → virtualization.js} +8 -6
- package/components/table/item-virtualization.d.ts +5 -3
- package/components/table/item-virtualization.js +4 -6
- 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 +0 -32
- package/components/table/table-const.js +0 -7
- package/components/table/table-primitives.d.ts +43 -0
- package/components/table/table-primitives.js +9 -0
- package/components/table/table-props.d.ts +29 -5
- package/components/table/table.css +17 -10
- package/components/table/table.d.ts +31 -5
- package/components/table/table.js +64 -35
- package/components/tag/tag.css +3 -3
- package/components/user-card/smart-user-card-tooltip.d.ts +1 -1
- package/components/util-stories.d.ts +2 -2
- package/package.json +14 -14
- package/components/table/internal/column-animation.d.ts +0 -16
- package/components/table/internal/column-animation.js +0 -45
|
@@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef, use } from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import dataTests from '../global/data-tests';
|
|
4
4
|
import { getRect } from '../global/dom';
|
|
5
|
+
import { parseCssDuration } from '../global/parse-css-duration';
|
|
5
6
|
import { toPx } from './utils';
|
|
6
7
|
import CollapseContext from './collapse-context';
|
|
7
8
|
import { COLLAPSE_CONTENT_TEST_ID, COLLAPSE_CONTENT_CONTAINER_TEST_ID } from './consts';
|
|
@@ -10,11 +11,14 @@ const DURATION_FACTOR = 0.5;
|
|
|
10
11
|
const DEFAULT_HEIGHT = 0;
|
|
11
12
|
const VISIBLE = 1;
|
|
12
13
|
const HIDDEN = 0;
|
|
14
|
+
// margin for the hide fallback timer, so it fires only if transitionend never did
|
|
15
|
+
const HIDE_FALLBACK_EXTRA_DELAY = 100;
|
|
16
|
+
const isFullyCollapsed = (collapsed, initialContentHeight) => collapsed && initialContentHeight <= DEFAULT_HEIGHT;
|
|
13
17
|
/**
|
|
14
18
|
* @name CollapseContent
|
|
15
19
|
*/
|
|
16
20
|
export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-test': dataTest, }) => {
|
|
17
|
-
const { collapsed, duration, id, disableAnimation } = use(CollapseContext);
|
|
21
|
+
const { collapsed, duration, id, disableAnimation, keepMounted } = use(CollapseContext);
|
|
18
22
|
const containerRef = useRef(null);
|
|
19
23
|
const contentRef = useRef(null);
|
|
20
24
|
const [initialContentHeight] = useState(minHeight);
|
|
@@ -23,20 +27,41 @@ export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-te
|
|
|
23
27
|
const height = toPx(nextHeight);
|
|
24
28
|
const [shouldHideContent, setShouldHideContent] = useState(collapsed && minHeight <= DEFAULT_HEIGHT);
|
|
25
29
|
useEffect(() => {
|
|
26
|
-
|
|
30
|
+
const container = containerRef.current;
|
|
31
|
+
function finalizeCollapse() {
|
|
27
32
|
if (initialContentHeight <= DEFAULT_HEIGHT) {
|
|
28
33
|
setShouldHideContent(collapsed);
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
|
-
|
|
36
|
+
function onTransitionEnd(event) {
|
|
37
|
+
// transitionend bubbles: only the container's own height transition finalizes the collapse
|
|
38
|
+
if (event.target === container && event.propertyName === 'height') {
|
|
39
|
+
finalizeCollapse();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
32
42
|
container?.addEventListener('transitionend', onTransitionEnd);
|
|
43
|
+
// fallback for suppressed or cancelled transitions (e.g. `transition: none` overrides),
|
|
44
|
+
// which emit no transitionend and would otherwise leave the content interactive forever.
|
|
45
|
+
// Armed once per collapse toggle from the --duration committed to the DOM — the value
|
|
46
|
+
// the running transition actually uses — so it can neither undercut a transition started
|
|
47
|
+
// from a stale height nor be restarted by content resizes or duration changes mid-collapse
|
|
48
|
+
const cssDuration = parseCssDuration(container?.style.getPropertyValue('--duration') || '');
|
|
49
|
+
const fallbackTimeout = window.setTimeout(finalizeCollapse, cssDuration + HIDE_FALLBACK_EXTRA_DELAY);
|
|
33
50
|
return () => {
|
|
34
51
|
container?.removeEventListener('transitionend', onTransitionEnd);
|
|
52
|
+
window.clearTimeout(fallbackTimeout);
|
|
35
53
|
};
|
|
36
54
|
}, [collapsed, initialContentHeight]);
|
|
55
|
+
// render-phase state adjustments (not effects): the React Compiler lint forbids
|
|
56
|
+
// setState-in-effect, and https://react.dev/learn/you-might-not-need-an-effect
|
|
57
|
+
// documents this pattern for resetting state when props change
|
|
37
58
|
if (!collapsed && shouldHideContent) {
|
|
38
59
|
setShouldHideContent(false);
|
|
39
60
|
}
|
|
61
|
+
// without a transition there is no transitionend to wait for, so hide immediately
|
|
62
|
+
if (disableAnimation && !shouldHideContent && isFullyCollapsed(collapsed, initialContentHeight)) {
|
|
63
|
+
setShouldHideContent(true);
|
|
64
|
+
}
|
|
40
65
|
useEffect(() => {
|
|
41
66
|
if (contentRef.current) {
|
|
42
67
|
const observer = new ResizeObserver(() => {
|
|
@@ -52,10 +77,20 @@ export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-te
|
|
|
52
77
|
opacity: collapsed && !minHeight ? HIDDEN : VISIBLE,
|
|
53
78
|
};
|
|
54
79
|
const fadeShouldBeVisible = Boolean(minHeight && collapsed);
|
|
55
|
-
const
|
|
80
|
+
const contentVisible = !shouldHideContent;
|
|
81
|
+
const contentHidden = Boolean(keepMounted) && !contentVisible;
|
|
82
|
+
// interaction is blocked as soon as the panel collapses (matching aria-expanded), while
|
|
83
|
+
// visibility waits for the animation to finish so the content stays painted meanwhile.
|
|
84
|
+
// This includes a minHeight preview: content clipped below it must not take focus,
|
|
85
|
+
// and inert cannot be applied any more granularly than to the whole subtree
|
|
86
|
+
const contentInert = collapsed;
|
|
56
87
|
return (<div ref={containerRef} id={`collapse-content-${id}`} data-test={dataTests(COLLAPSE_CONTENT_CONTAINER_TEST_ID)} className={classNames(styles.container, { [styles.transition]: !disableAnimation })} style={style}>
|
|
57
|
-
<div ref={contentRef} data-test={dataTests(COLLAPSE_CONTENT_TEST_ID, dataTest)}
|
|
58
|
-
|
|
88
|
+
<div ref={contentRef} data-test={dataTests(COLLAPSE_CONTENT_TEST_ID, dataTest)}
|
|
89
|
+
// visibility: hidden removes the fully collapsed content from the tab order and accessibility
|
|
90
|
+
// tree, but descendants can override it with visibility: visible — inert cannot be escaped.
|
|
91
|
+
// Both are rendered in JSX so server-rendered collapsed markup is protected before hydration.
|
|
92
|
+
style={contentHidden ? { visibility: 'hidden' } : undefined} inert={contentInert}>
|
|
93
|
+
{keepMounted || contentVisible ? children : null}
|
|
59
94
|
</div>
|
|
60
95
|
{fadeShouldBeVisible && <div className={styles.fade}/>}
|
|
61
96
|
</div>);
|
|
@@ -4,6 +4,15 @@ interface Props {
|
|
|
4
4
|
onChange?: (collapsed: boolean) => void;
|
|
5
5
|
duration?: number;
|
|
6
6
|
disableAnimation?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Keep children mounted while collapsed (hidden via `visibility: hidden`
|
|
9
|
+
* and the `inert` attribute) instead of unmounting them, preserving their state.
|
|
10
|
+
* Note: hidden form controls still participate in form validation
|
|
11
|
+
* and submission — disable them while collapsed if needed.
|
|
12
|
+
* Content rendered through portals (e.g. Popup) escapes the hidden
|
|
13
|
+
* wrapper and is not hidden — close overlays on collapse.
|
|
14
|
+
*/
|
|
15
|
+
keepMounted?: boolean;
|
|
7
16
|
className?: string;
|
|
8
17
|
defaultCollapsed?: boolean;
|
|
9
18
|
collapsed?: boolean | null;
|
|
@@ -5,7 +5,7 @@ import { BASE_ANIMATION_DURATION } from './consts';
|
|
|
5
5
|
/**
|
|
6
6
|
* @name Collapse
|
|
7
7
|
*/
|
|
8
|
-
export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disableAnimation = false, className = '', onChange = () => { }, defaultCollapsed = true, collapsed = null, }) => {
|
|
8
|
+
export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disableAnimation = false, keepMounted = false, className = '', onChange = () => { }, defaultCollapsed = true, collapsed = null, }) => {
|
|
9
9
|
const [innerCollapsed, setInnerCollapsed] = useState(defaultCollapsed);
|
|
10
10
|
const id = useId();
|
|
11
11
|
const finalCollapsedValue = collapsed ?? innerCollapsed;
|
|
@@ -19,6 +19,7 @@ export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disable
|
|
|
19
19
|
setCollapsed,
|
|
20
20
|
duration,
|
|
21
21
|
disableAnimation,
|
|
22
|
+
keepMounted,
|
|
22
23
|
id,
|
|
23
24
|
}}>
|
|
24
25
|
{children}
|
|
@@ -11,10 +11,23 @@ export interface CollapsibleGroupProps {
|
|
|
11
11
|
onChange?: (expanded: boolean) => void;
|
|
12
12
|
disableAnimation?: boolean;
|
|
13
13
|
interactive?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Keep children mounted while collapsed (hidden via `visibility: hidden`
|
|
16
|
+
* and the `inert` attribute) instead of unmounting them, preserving their state.
|
|
17
|
+
* Note: hidden form controls still participate in form validation
|
|
18
|
+
* and submission — disable them while collapsed if needed.
|
|
19
|
+
* Content rendered through portals (e.g. Popup) escapes the hidden
|
|
20
|
+
* wrapper and is not hidden — close overlays on collapse.
|
|
21
|
+
*/
|
|
22
|
+
keepMounted?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Wraps the header in an <h2>–<h6> to keep the document outline.
|
|
25
|
+
*/
|
|
26
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6;
|
|
14
27
|
'data-test'?: string | null | undefined;
|
|
15
28
|
}
|
|
16
29
|
declare const CollapsibleGroup: {
|
|
17
|
-
({ ref, avatar, title, subtitle, children, className, defaultExpanded, expanded, onChange, disableAnimation, interactive, "data-test": dataTest, }: CollapsibleGroupProps): React.JSX.Element;
|
|
30
|
+
({ ref, avatar, title, subtitle, children, className, defaultExpanded, expanded, onChange, disableAnimation, interactive, keepMounted, headingLevel, "data-test": dataTest, }: CollapsibleGroupProps): React.JSX.Element;
|
|
18
31
|
displayName: string;
|
|
19
32
|
};
|
|
20
33
|
export default CollapsibleGroup;
|
|
@@ -36,7 +36,7 @@ function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
|
|
|
36
36
|
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
37
37
|
</span>);
|
|
38
38
|
}
|
|
39
|
-
const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, 'data-test': dataTest, }) => {
|
|
39
|
+
const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, keepMounted = false, headingLevel, 'data-test': dataTest, }) => {
|
|
40
40
|
const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
|
|
41
41
|
const [hovered, setHovered] = useState(false);
|
|
42
42
|
const [focused, setFocused] = useState(false);
|
|
@@ -60,9 +60,10 @@ const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, d
|
|
|
60
60
|
[styles.expanded]: isExpanded,
|
|
61
61
|
[styles.focused]: focused,
|
|
62
62
|
});
|
|
63
|
+
const header = interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} onFocus={() => setFocused(true)} onBlur={onBlur}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>);
|
|
63
64
|
return (<div ref={ref} className={classes} data-test={dataTest}>
|
|
64
|
-
<Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} className={styles.collapseRoot}>
|
|
65
|
-
{
|
|
65
|
+
<Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} keepMounted={keepMounted} className={styles.collapseRoot}>
|
|
66
|
+
{headingLevel != null ? React.createElement(`h${headingLevel}`, { className: styles.heading }, header) : header}
|
|
66
67
|
<CollapseContent>
|
|
67
68
|
<div className={styles.body}>{children}</div>
|
|
68
69
|
</CollapseContent>
|
|
@@ -47,7 +47,7 @@ export default class DateInput extends React.PureComponent {
|
|
|
47
47
|
};
|
|
48
48
|
render() {
|
|
49
49
|
const { active, divider, text, time, name, hoverDate, date, displayFormat, translations, onActivate, onClear, fromPlaceholder, toPlaceholder, timePlaceholder, locale, } = this.props;
|
|
50
|
-
const { translate } = this.context;
|
|
50
|
+
const { messages, translate } = this.context;
|
|
51
51
|
let displayText = '';
|
|
52
52
|
if (active && hoverDate) {
|
|
53
53
|
displayText = displayFormat(hoverDate, locale);
|
|
@@ -70,7 +70,11 @@ export default class DateInput extends React.PureComponent {
|
|
|
70
70
|
case 'time':
|
|
71
71
|
return timePlaceholder || (translations?.addTime ?? translate('addTime'));
|
|
72
72
|
default:
|
|
73
|
-
return (translations?.
|
|
73
|
+
return (translations?.selectDate ??
|
|
74
|
+
translations?.selectName ??
|
|
75
|
+
messages.selectDate ??
|
|
76
|
+
messages.selectName ??
|
|
77
|
+
translate('selectDate'))
|
|
74
78
|
.replace('%name%', name)
|
|
75
79
|
.replace('{{name}}', name);
|
|
76
80
|
}
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
composes: header from '../collapsible-group/collapsible-group.css';
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
.heading {
|
|
31
|
+
composes: heading from '../collapsible-group/collapsible-group.css';
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
.headerButton {
|
|
31
35
|
composes: headerButton from '../collapsible-group/collapsible-group.css';
|
|
32
36
|
}
|
|
@@ -48,18 +48,18 @@
|
|
|
48
48
|
--ring-main-error-color: rgb(var(--ring-main-error-components)); /* #CC3645 */
|
|
49
49
|
--ring-main-error-hover-components: 188, 48, 62;
|
|
50
50
|
--ring-main-error-hover-color: rgb(var(--ring-main-error-hover-components)); /* #BC303E */
|
|
51
|
-
--ring-main-warning-components:
|
|
52
|
-
--ring-main-warning-color: rgb(var(--ring-main-warning-components)); /* #
|
|
53
|
-
--ring-main-warning-hover-components:
|
|
54
|
-
--ring-main-warning-hover-color: rgb(var(--ring-main-warning-hover-components)); /* #
|
|
51
|
+
--ring-main-warning-components: 255, 175, 15;
|
|
52
|
+
--ring-main-warning-color: rgb(var(--ring-main-warning-components)); /* #FFAF0F */
|
|
53
|
+
--ring-main-warning-hover-components: 223, 147, 3;
|
|
54
|
+
--ring-main-warning-hover-color: rgb(var(--ring-main-warning-hover-components)); /* #DF9303 */
|
|
55
55
|
--ring-main-purple-components: 131, 77, 240;
|
|
56
56
|
--ring-main-purple-color: rgb(var(--ring-main-purple-components)); /* #834DF0 */
|
|
57
57
|
--ring-main-purple-hover-components: 116, 68, 212;
|
|
58
58
|
--ring-main-purple-hover-color: rgb(var(--ring-main-purple-hover-components)); /* #7444D4 */
|
|
59
59
|
--ring-icon-error-components: 204, 54, 69;
|
|
60
60
|
--ring-icon-error-color: rgb(var(--ring-icon-error-components)); /* #CC3645 */
|
|
61
|
-
--ring-icon-warning-components:
|
|
62
|
-
--ring-icon-warning-color: rgb(var(--ring-icon-warning-components)); /* #
|
|
61
|
+
--ring-icon-warning-components: 223, 147, 3;
|
|
62
|
+
--ring-icon-warning-color: rgb(var(--ring-icon-warning-components)); /* #DF9303 */
|
|
63
63
|
--ring-icon-success-components: 32, 138, 60;
|
|
64
64
|
--ring-icon-success-color: rgb(var(--ring-icon-success-components)); /* #208A3C */
|
|
65
65
|
--ring-icon-highlight-components: 255, 175, 15;
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
--ring-error-border-color: rgb(var(--ring-error-border-components)); /* #F2B6BB */
|
|
75
75
|
--ring-error-border-hover-components: 228, 106, 118;
|
|
76
76
|
--ring-error-border-hover-color: rgb(var(--ring-error-border-hover-components)); /* #E46A76 */
|
|
77
|
-
--ring-warning-border-components:
|
|
78
|
-
--ring-warning-border-color: rgb(var(--ring-warning-border-components)); /* #
|
|
79
|
-
--ring-warning-border-hover-components:
|
|
80
|
-
--ring-warning-border-hover-color: rgb(var(--ring-warning-border-hover-components)); /* #
|
|
77
|
+
--ring-warning-border-components: 254, 210, 119;
|
|
78
|
+
--ring-warning-border-color: rgb(var(--ring-warning-border-components)); /* #FED277 */
|
|
79
|
+
--ring-warning-border-hover-components: 253, 189, 61;
|
|
80
|
+
--ring-warning-border-hover-color: rgb(var(--ring-warning-border-hover-components)); /* #FDBD3D */
|
|
81
81
|
--ring-highlight-border-components: 254, 210, 119;
|
|
82
82
|
--ring-highlight-border-color: rgb(var(--ring-highlight-border-components)); /* #FED277 */
|
|
83
83
|
--ring-highlight-border-hover-components: 253, 189, 61;
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
--ring-link-hover-color: rgb(var(--ring-link-hover-components)); /* #2E55A3 */
|
|
117
117
|
--ring-error-components: 204, 54, 69;
|
|
118
118
|
--ring-error-color: rgb(var(--ring-error-components)); /* #CC3645 */
|
|
119
|
-
--ring-warning-components:
|
|
120
|
-
--ring-warning-color: rgb(var(--ring-warning-components)); /* #
|
|
119
|
+
--ring-warning-components: 156, 97, 0;
|
|
120
|
+
--ring-warning-color: rgb(var(--ring-warning-components)); /* #9C6100 */ /* Prefer using warning icon + regular text color */
|
|
121
121
|
--ring-success-components: 31, 117, 54;
|
|
122
122
|
--ring-success-color: rgb(var(--ring-success-components)); /* #1F7536 */ /* Prefer using success icon + regular text color */
|
|
123
123
|
--ring-purple-text-components: 131, 77, 240;
|
|
@@ -154,8 +154,8 @@
|
|
|
154
154
|
--ring-tag-hover-background-color: rgb(var(--ring-tag-hover-background-components)); /* #DFE1E5 */
|
|
155
155
|
--ring-removed-background-components: 250, 212, 216;
|
|
156
156
|
--ring-removed-background-color: rgb(var(--ring-removed-background-components)); /* #FAD4D8 */
|
|
157
|
-
--ring-warning-background-components:
|
|
158
|
-
--ring-warning-background-color: rgb(var(--ring-warning-background-components)); /* #
|
|
157
|
+
--ring-warning-background-components: 255, 241, 209;
|
|
158
|
+
--ring-warning-background-color: rgb(var(--ring-warning-background-components)); /* #FFF1D1 */
|
|
159
159
|
--ring-highlight-background-components: 255, 241, 209;
|
|
160
160
|
--ring-highlight-background-color: rgb(var(--ring-highlight-background-components)); /* #FFF1D1 */
|
|
161
161
|
--ring-added-background-components: 197, 229, 204;
|
|
@@ -172,8 +172,8 @@
|
|
|
172
172
|
--ring-table-loader-background-color: rgba(var(--ring-content-background-components), 0.5); /* #FFFFFF50 */
|
|
173
173
|
--ring-removed-subtle-background-components: 255, 235, 236;
|
|
174
174
|
--ring-removed-subtle-background-color: rgb(var(--ring-removed-subtle-background-components)); /* #FFEBEC */
|
|
175
|
-
--ring-warning-subtle-background-components: 255,
|
|
176
|
-
--ring-warning-subtle-background-color: rgb(var(--ring-warning-subtle-background-components)); /* #
|
|
175
|
+
--ring-warning-subtle-background-components: 255, 246, 222;
|
|
176
|
+
--ring-warning-subtle-background-color: rgb(var(--ring-warning-subtle-background-components)); /* #FFF6DE */
|
|
177
177
|
--ring-highlight-subtle-background-components: 255, 246, 222;
|
|
178
178
|
--ring-highlight-subtle-background-color: rgb(var(--ring-highlight-subtle-background-components)); /* #FFF6DE */
|
|
179
179
|
--ring-added-subtle-background-components: 230, 247, 233;
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
--ring-success-container-light-color: rgb(var(--ring-success-container-light-components)); /* #F2FCF3 */
|
|
187
187
|
--ring-error-container-light-components: 255, 242, 243;
|
|
188
188
|
--ring-error-container-light-color: rgb(var(--ring-error-container-light-components)); /* #FFF2F3 */
|
|
189
|
-
--ring-warning-container-light-components: 255,
|
|
190
|
-
--ring-warning-container-light-color: rgb(var(--ring-warning-container-light-components)); /* #
|
|
189
|
+
--ring-warning-container-light-components: 255, 250, 235;
|
|
190
|
+
--ring-warning-container-light-color: rgb(var(--ring-warning-container-light-components)); /* #FFFAEB */
|
|
191
191
|
--ring-highlight-container-light-components: 255, 250, 235;
|
|
192
192
|
--ring-highlight-container-light-color: rgb(var(--ring-highlight-container-light-components)); /* #FFFAEB */
|
|
193
193
|
--ring-grey-container-light-components: 247, 248, 250;
|
|
@@ -39,18 +39,18 @@
|
|
|
39
39
|
--ring-main-error-color: rgb(var(--ring-main-error-components)); /* #BD5757 */
|
|
40
40
|
--ring-main-error-hover-components: 156, 78, 78;
|
|
41
41
|
--ring-main-error-hover-color: rgb(var(--ring-main-error-hover-components)); /* #9C4E4E */
|
|
42
|
-
--ring-main-warning-components:
|
|
43
|
-
--ring-main-warning-color: rgb(var(--ring-main-warning-components)); /* #
|
|
44
|
-
--ring-main-warning-hover-components:
|
|
45
|
-
--ring-main-warning-hover-color: rgb(var(--ring-main-warning-hover-components)); /* #
|
|
42
|
+
--ring-main-warning-components: 214, 174, 88;
|
|
43
|
+
--ring-main-warning-color: rgb(var(--ring-main-warning-components)); /* #D6AE58 */
|
|
44
|
+
--ring-main-warning-hover-components: 186, 151, 82;
|
|
45
|
+
--ring-main-warning-hover-color: rgb(var(--ring-main-warning-hover-components)); /* #BA9752 */
|
|
46
46
|
--ring-main-purple-components: 149, 90, 224;
|
|
47
47
|
--ring-main-purple-color: rgb(var(--ring-main-purple-components)); /* #955AE0 */
|
|
48
48
|
--ring-main-purple-hover-components: 129, 80, 190;
|
|
49
49
|
--ring-main-purple-hover-color: rgb(var(--ring-main-purple-hover-components)); /* #8150BE */
|
|
50
50
|
--ring-icon-error-components: 227, 119, 116;
|
|
51
51
|
--ring-icon-error-color: rgb(var(--ring-icon-error-components)); /* #E37774 */
|
|
52
|
-
--ring-icon-warning-components:
|
|
53
|
-
--ring-icon-warning-color: rgb(var(--ring-icon-warning-components)); /* #
|
|
52
|
+
--ring-icon-warning-components: 214, 174, 88;
|
|
53
|
+
--ring-icon-warning-color: rgb(var(--ring-icon-warning-components)); /* #D6AE58 */
|
|
54
54
|
--ring-icon-success-components: 95, 173, 101;
|
|
55
55
|
--ring-icon-success-color: rgb(var(--ring-icon-success-components)); /* #5FAD65 */
|
|
56
56
|
--ring-icon-highlight-components: 214, 174, 88;
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
--ring-error-border-color: rgb(var(--ring-error-border-components)); /* #7A4343 */
|
|
66
66
|
--ring-error-border-hover-components: 156, 78, 78;
|
|
67
67
|
--ring-error-border-hover-color: rgb(var(--ring-error-border-hover-components)); /* #9C4E4E */
|
|
68
|
-
--ring-warning-border-components: 130,
|
|
69
|
-
--ring-warning-border-color: rgb(var(--ring-warning-border-components)); /* #
|
|
70
|
-
--ring-warning-border-hover-components:
|
|
71
|
-
--ring-warning-border-hover-color: rgb(var(--ring-warning-border-hover-components)); /* #
|
|
68
|
+
--ring-warning-border-components: 130, 106, 65;
|
|
69
|
+
--ring-warning-border-color: rgb(var(--ring-warning-border-components)); /* #826A41 */
|
|
70
|
+
--ring-warning-border-hover-components: 158, 129, 74;
|
|
71
|
+
--ring-warning-border-hover-color: rgb(var(--ring-warning-border-hover-components)); /* #9E814A */
|
|
72
72
|
--ring-highlight-border-components: 130, 106, 65;
|
|
73
73
|
--ring-highlight-border-color: rgb(var(--ring-highlight-border-components)); /* #826A41 */
|
|
74
74
|
--ring-highlight-border-hover-components: 158, 129, 74;
|
|
@@ -101,8 +101,8 @@
|
|
|
101
101
|
--ring-link-hover-color: rgb(var(--ring-link-hover-components)); /* #6B9BFA */
|
|
102
102
|
--ring-error-components: 227, 119, 116;
|
|
103
103
|
--ring-error-color: rgb(var(--ring-error-components)); /* #E37774 */
|
|
104
|
-
--ring-warning-components:
|
|
105
|
-
--ring-warning-color: rgb(var(--ring-warning-components)); /* #
|
|
104
|
+
--ring-warning-components: 242, 197, 92;
|
|
105
|
+
--ring-warning-color: rgb(var(--ring-warning-components)); /* #F2C55C */ /* Prefer using warning icon + regular text color */
|
|
106
106
|
--ring-success-components: 95, 173, 101;
|
|
107
107
|
--ring-success-color: rgb(var(--ring-success-components)); /* #5FAD65 */ /* Prefer using success icon + regular text color */
|
|
108
108
|
--ring-purple-text-components: 181, 137, 236;
|
|
@@ -140,8 +140,8 @@
|
|
|
140
140
|
--ring-tag-hover-background-color: rgb(var(--ring-tag-hover-background-components)); /* #4E5157 */
|
|
141
141
|
--ring-removed-background-components: 94, 56, 56;
|
|
142
142
|
--ring-removed-background-color: rgb(var(--ring-removed-background-components)); /* #5E3838 */
|
|
143
|
-
--ring-warning-background-components:
|
|
144
|
-
--ring-warning-background-color: rgb(var(--ring-warning-background-components)); /* #
|
|
143
|
+
--ring-warning-background-components: 94, 77, 51;
|
|
144
|
+
--ring-warning-background-color: rgb(var(--ring-warning-background-components)); /* #5E4D33 */
|
|
145
145
|
--ring-highlight-background-components: 94, 77, 51;
|
|
146
146
|
--ring-highlight-background-color: rgb(var(--ring-highlight-background-components)); /* #5E4D33 */
|
|
147
147
|
--ring-added-background-components: 55, 82, 57;
|
|
@@ -157,8 +157,8 @@
|
|
|
157
157
|
--ring-table-loader-background-color: rgba(var(--ring-content-background-components), 0.5); /* #2B2D3050 */
|
|
158
158
|
--ring-removed-subtle-background-components: 64, 41, 41;
|
|
159
159
|
--ring-removed-subtle-background-color: rgb(var(--ring-removed-subtle-background-components)); /* #402929 */
|
|
160
|
-
--ring-warning-subtle-background-components:
|
|
161
|
-
--ring-warning-subtle-background-color: rgb(var(--ring-warning-subtle-background-components)); /* #
|
|
160
|
+
--ring-warning-subtle-background-components: 61, 50, 35;
|
|
161
|
+
--ring-warning-subtle-background-color: rgb(var(--ring-warning-subtle-background-components)); /* #3D3223 */
|
|
162
162
|
--ring-highlight-subtle-background-components: 61, 50, 35;
|
|
163
163
|
--ring-highlight-subtle-background-color: rgb(var(--ring-highlight-subtle-background-components)); /* #3D3223 */
|
|
164
164
|
--ring-added-subtle-background-components: 37, 54, 39;
|
|
@@ -171,8 +171,8 @@
|
|
|
171
171
|
--ring-success-container-light-color: rgb(var(--ring-success-container-light-components)); /* #222D25 */
|
|
172
172
|
--ring-error-container-light-components: 54, 38, 39;
|
|
173
173
|
--ring-error-container-light-color: rgb(var(--ring-error-container-light-components)); /* #362627 */
|
|
174
|
-
--ring-warning-container-light-components:
|
|
175
|
-
--ring-warning-container-light-color: rgb(var(--ring-warning-container-light-components)); /* #
|
|
174
|
+
--ring-warning-container-light-components: 49, 42, 35;
|
|
175
|
+
--ring-warning-container-light-color: rgb(var(--ring-warning-container-light-components)); /* #312A23 */
|
|
176
176
|
--ring-highlight-container-light-components: 49, 42, 35;
|
|
177
177
|
--ring-highlight-container-light-color: rgb(var(--ring-highlight-container-light-components)); /* #312A23 */
|
|
178
178
|
--ring-grey-container-light-components: 43, 45, 48;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@import '../global/variables.css';
|
|
2
2
|
|
|
3
|
-
@value link, active from '../link/link.css';
|
|
3
|
+
@value link, active as linkActive from '../link/link.css';
|
|
4
4
|
|
|
5
5
|
:root,
|
|
6
6
|
:host {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
color: var(--ring-header-link-color);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
& .
|
|
44
|
+
& .linkActive {
|
|
45
45
|
color: var(--ring-active-text-color);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
color: var(--ring-header-link-color);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
& .
|
|
75
|
+
& .linkActive {
|
|
76
76
|
color: var(--ring-active-text-color);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -20,7 +20,7 @@ export interface RequestParams<RawBody extends boolean = true | false> extends F
|
|
|
20
20
|
export type RequestParamsWithoutMethod<RawBody extends boolean = boolean> = Omit<RequestParams<RawBody>, 'method'>;
|
|
21
21
|
export interface HTTPAuth {
|
|
22
22
|
requestToken(): Promise<string | null> | string | null;
|
|
23
|
-
forceTokenUpdate(): Promise<string | null>;
|
|
23
|
+
forceTokenUpdate(failedToken?: string | null): Promise<string | null>;
|
|
24
24
|
}
|
|
25
25
|
export default class HTTP implements Partial<HTTPAuth> {
|
|
26
26
|
baseUrl: string | null | undefined;
|
|
@@ -28,7 +28,7 @@ export default class HTTP implements Partial<HTTPAuth> {
|
|
|
28
28
|
fetchConfig: RequestInit;
|
|
29
29
|
requestToken?: () => Promise<string | null> | string | null;
|
|
30
30
|
shouldRefreshToken?: (error: string) => boolean;
|
|
31
|
-
forceTokenUpdate?: () => Promise<string | null>;
|
|
31
|
+
forceTokenUpdate?: (failedToken?: string | null) => Promise<string | null>;
|
|
32
32
|
constructor(auth?: HTTPAuth, baseUrl?: string | null | undefined, fetchConfig?: RequestInit);
|
|
33
33
|
setAuth: (auth: HTTPAuth) => void;
|
|
34
34
|
setBaseUrl: (baseUrl: string | null | undefined) => void;
|
package/components/http/http.js
CHANGED
|
@@ -50,7 +50,7 @@ export default class HTTP {
|
|
|
50
50
|
setAuth = (auth) => {
|
|
51
51
|
this.requestToken = () => auth.requestToken();
|
|
52
52
|
this.shouldRefreshToken = auth.constructor.shouldRefreshToken;
|
|
53
|
-
this.forceTokenUpdate =
|
|
53
|
+
this.forceTokenUpdate = failedToken => auth.forceTokenUpdate(failedToken);
|
|
54
54
|
};
|
|
55
55
|
setBaseUrl = (baseUrl) => {
|
|
56
56
|
this.baseUrl = baseUrl;
|
|
@@ -141,7 +141,7 @@ export default class HTTP {
|
|
|
141
141
|
}
|
|
142
142
|
const shouldRefreshToken = typeof error.data.error === 'string' ? this.shouldRefreshToken?.(error.data.error) : false;
|
|
143
143
|
if (shouldRefreshToken) {
|
|
144
|
-
token = await this.forceTokenUpdate?.();
|
|
144
|
+
token = await this.forceTokenUpdate?.(token);
|
|
145
145
|
response = await this._performRequest(url, token, params);
|
|
146
146
|
return this._processResponse(response);
|
|
147
147
|
}
|
|
@@ -32,6 +32,12 @@ export interface DefaultItemRendererProps {
|
|
|
32
32
|
* and track the visibility yourself.
|
|
33
33
|
*/
|
|
34
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;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* Standard component for rendering a table row.
|
|
@@ -46,4 +52,4 @@ export interface DefaultItemRendererProps {
|
|
|
46
52
|
* accessible controls, such as checkboxes or buttons with accessible
|
|
47
53
|
* labels.
|
|
48
54
|
*/
|
|
49
|
-
export declare function DefaultItemRenderer<T>({ index, keyboardFocusable, clickable, selected, level, noItemVirtualization, ref: userRef, className, ...restProps }: DefaultItemRendererProps & ComponentPropsWithRef<'tr'>): import("react").JSX.Element | null;
|
|
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,9 +1,11 @@
|
|
|
1
1
|
import { use, useCallback, useRef } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import {
|
|
3
|
+
import { TablePropsContext } from './table-const';
|
|
4
4
|
import { useComposedRef } from '../global/compose-refs';
|
|
5
5
|
import { useItemVirtualization } from './item-virtualization';
|
|
6
6
|
import { TableCell, TableRow } from './table-primitives';
|
|
7
|
+
import { ReorderAnimationContext } from './internal/reorder-animation-context';
|
|
8
|
+
import { useReorderItemLayout } from './reorder-item-layout';
|
|
7
9
|
import styles from './table.css';
|
|
8
10
|
/**
|
|
9
11
|
* Standard component for rendering a table row.
|
|
@@ -18,7 +20,7 @@ import styles from './table.css';
|
|
|
18
20
|
* accessible controls, such as checkboxes or buttons with accessible
|
|
19
21
|
* labels.
|
|
20
22
|
*/
|
|
21
|
-
export function DefaultItemRenderer({ index, keyboardFocusable, clickable, selected, level, noItemVirtualization, ref: userRef, className, ...restProps }) {
|
|
23
|
+
export function DefaultItemRenderer({ index, keyboardFocusable, clickable, selected, level, noItemVirtualization, noReorderLayout, ref: userRef, className, ...restProps }) {
|
|
22
24
|
const localRef = useRef(null);
|
|
23
25
|
const composedRef = useComposedRef(userRef, localRef);
|
|
24
26
|
useItemVirtualization({
|
|
@@ -33,18 +35,29 @@ export function DefaultItemRenderer({ index, keyboardFocusable, clickable, selec
|
|
|
33
35
|
? element.getBoundingClientRect().height
|
|
34
36
|
: undefined, [noItemVirtualization]),
|
|
35
37
|
});
|
|
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
|
+
});
|
|
36
46
|
const tableProps = use(TablePropsContext);
|
|
37
47
|
if (!tableProps) {
|
|
38
48
|
return null;
|
|
39
49
|
}
|
|
40
|
-
const
|
|
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;
|
|
41
54
|
const { data, columns } = tableProps;
|
|
42
55
|
const item = data[index];
|
|
43
56
|
const indentSize = 24;
|
|
44
|
-
return (<TableRow ref={composedRef} keyboardFocusable={keyboardFocusable} className={classNames(className, clickable && styles.clickableRow, selected && styles.selectedRow)} {...restProps}>
|
|
57
|
+
return (<TableRow ref={composedRef} keyboardFocusable={keyboardFocusable} className={classNames(className, clickable && styles.clickableRow, selected && styles.selectedRow, isAnimatedItem && animateClassName)} {...restProps}>
|
|
45
58
|
{columns.map((column, columnIndex) => {
|
|
46
59
|
const { key, tdClassName, indent } = column;
|
|
47
|
-
return (<TableCell key={key} className={classNames(columnIndex ===
|
|
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}>
|
|
48
61
|
{column.renderCell?.(item, index, data) ?? getDefaultCellValue(item, columnIndex, key)}
|
|
49
62
|
</TableCell>);
|
|
50
63
|
})}
|
|
@@ -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 {};
|