@astryxdesign/lab 0.7.0-canary.4ec1f4e → 0.7.0-canary.61639ee
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/MobileTokenizer/MobileTokenizer.js +1 -1
- package/dist/Tour/Tour.d.ts.map +1 -1
- package/dist/Tour/Tour.js +8 -5
- package/dist/TransferList/TransferList.js +1 -1
- package/dist/TransferList/TransferListSelector.d.ts +1 -1
- package/dist/TransferList/TransferListSelector.d.ts.map +1 -1
- package/dist/TransferList/TransferListSelector.js +14 -15
- package/package.json +4 -4
- package/src/MobileTokenizer/MobileTokenizer.tsx +1 -1
- package/src/Tour/Tour.test.tsx +53 -1
- package/src/Tour/Tour.tsx +8 -5
- package/src/TransferList/TransferList.doc.mjs +9 -7
- package/src/TransferList/TransferList.tsx +1 -1
- package/src/TransferList/TransferListSelector.test.tsx +44 -5
- package/src/TransferList/TransferListSelector.tsx +16 -19
package/dist/Tour/Tour.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/Tour/Tour.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"Tour.d.ts","sourceRoot":"","sources":["../../src/Tour/Tour.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAiC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACrE,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC/C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAmB,EACnB,gBAAwB,GACzB,EAAE,SAAS,+BA0EX;yBAhFe,IAAI"}
|
package/dist/Tour/Tour.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* - /packages/lab/src/Tour/Tour.test.tsx (tests for new/changed behavior)
|
|
29
29
|
* - /packages/lab/src/Tour/index.ts (exports if types change)
|
|
30
30
|
*/
|
|
31
|
-
import { useCallback,
|
|
31
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
32
32
|
import { TourContext } from "./TourContext.js";
|
|
33
33
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
34
34
|
/**
|
|
@@ -68,13 +68,16 @@ export function Tour({
|
|
|
68
68
|
};
|
|
69
69
|
}, []);
|
|
70
70
|
|
|
71
|
-
// Reset to the first step
|
|
72
|
-
//
|
|
73
|
-
|
|
71
|
+
// Reset to the first step when the tour is deactivated, so a dismissed tour
|
|
72
|
+
// begins from the top next time isActive flips back on. Adjusted during
|
|
73
|
+
// render, so no commit carries the old step past deactivation.
|
|
74
|
+
const [wasActive, setWasActive] = useState(isActive);
|
|
75
|
+
if (!Object.is(wasActive, isActive)) {
|
|
76
|
+
setWasActive(isActive);
|
|
74
77
|
if (!isActive) {
|
|
75
78
|
setActiveStepIndex(0);
|
|
76
79
|
}
|
|
77
|
-
}
|
|
80
|
+
}
|
|
78
81
|
const stepCount = stepIds.length;
|
|
79
82
|
const onNext = useCallback(() => {
|
|
80
83
|
// Runs from a click/imperative call (never during render), so branch on the
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { type ReactNode } from 'react';
|
|
13
13
|
import { type ComplexSelectorProps } from '@astryxdesign/core/ComplexSelector';
|
|
14
14
|
import { type TransferListProps } from './TransferList';
|
|
15
|
-
type TransferListSelectorShellProp = 'label' | 'triggerLabel' | 'isLabelHidden' | 'description' | 'isOptional' | 'isRequired' | 'isDisabled' | 'isLoading' | 'status' | 'statusVariant' | 'labelTooltip' | 'size' | 'width' | 'placement' | '
|
|
15
|
+
type TransferListSelectorShellProp = 'label' | 'triggerLabel' | 'isLabelHidden' | 'description' | 'isOptional' | 'isRequired' | 'isDisabled' | 'isLoading' | 'status' | 'statusVariant' | 'labelTooltip' | 'size' | 'width' | 'placement' | 'controlXstyle' | 'controlClassName' | 'controlStyle' | 'data-testid';
|
|
16
16
|
type TransferListContentProp = 'options' | 'selectedLabel' | 'availableLabel' | 'hasSearch' | 'searchLabel' | 'searchPlaceholder' | 'isReorderable' | 'hasSelectAll' | 'hasClear' | 'renderOption' | 'selectedEmptyText' | 'availableEmptyText' | 'noResultsText';
|
|
17
17
|
export type TransferListSelectorCommitBehavior = 'immediate' | 'staged';
|
|
18
18
|
export type TransferListSelectorProps<T extends string = string> = Pick<ComplexSelectorProps<readonly T[]>, TransferListSelectorShellProp> & Pick<TransferListProps<T>, TransferListContentProp> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransferListSelector.d.ts","sourceRoot":"","sources":["../../src/TransferList/TransferListSelector.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAA2C,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG/E,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,oCAAoC,CAAC;AAI5C,OAAO,EAAe,KAAK,iBAAiB,EAAC,MAAM,gBAAgB,CAAC;AAsDpE,KAAK,6BAA6B,GAC9B,OAAO,GACP,cAAc,GACd,eAAe,GACf,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,eAAe,GACf,cAAc,GACd,MAAM,GACN,OAAO,GACP,WAAW,GACX,
|
|
1
|
+
{"version":3,"file":"TransferListSelector.d.ts","sourceRoot":"","sources":["../../src/TransferList/TransferListSelector.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAA2C,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAG/E,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,oCAAoC,CAAC;AAI5C,OAAO,EAAe,KAAK,iBAAiB,EAAC,MAAM,gBAAgB,CAAC;AAsDpE,KAAK,6BAA6B,GAC9B,OAAO,GACP,cAAc,GACd,eAAe,GACf,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,eAAe,GACf,cAAc,GACd,MAAM,GACN,OAAO,GACP,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,cAAc,GACd,aAAa,CAAC;AAElB,KAAK,uBAAuB,GACxB,SAAS,GACT,eAAe,GACf,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,mBAAmB,GACnB,eAAe,GACf,cAAc,GACd,UAAU,GACV,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,eAAe,CAAC;AAEpB,MAAM,MAAM,kCAAkC,GAAG,WAAW,GAAG,QAAQ,CAAC;AAExE,MAAM,MAAM,yBAAyB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACrE,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC,EAClC,6BAA6B,CAC9B,GACC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,uBAAuB,CAAC,GAAG;IACpD,mDAAmD;IACnD,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC;IACxC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D;;;OAGG;IACH,cAAc,CAAC,EAAE,kCAAkC,CAAC;IACpD,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AA+BJ;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAC9D,KAAK,EACL,WAAW,EACX,OAAO,EACP,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,cAA4B,EAC5B,YAAY,EACZ,UAAU,EACV,SAAS,EACT,KAAK,EACL,UAAU,EAAE,mBAAmB,EAC/B,WAAW,EAAE,oBAAoB,EACjC,aAAa,EACb,cAAc,EACd,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,GAAG,aAAa,EACjB,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,SAAS,CAkI1C;yBA7Je,oBAAoB"}
|
|
@@ -115,24 +115,23 @@ export function TransferListSelector({
|
|
|
115
115
|
const applyLabel = applyLabelFromProps ?? t('@astryx.transferListSelector.apply');
|
|
116
116
|
const cancelLabel = cancelLabelFromProps ?? t('@astryx.transferListSelector.cancel');
|
|
117
117
|
const [draftValue, setDraftValue] = useState(value);
|
|
118
|
-
const previousAppliedValueRef = useRef([...value]);
|
|
119
|
-
const previousCommitBehaviorRef = useRef(commitBehavior);
|
|
120
118
|
const resetDraft = useCallback(() => {
|
|
121
119
|
setDraftValue([...value]);
|
|
122
120
|
}, [value]);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
|
|
122
|
+
// A changed applied value or commit behavior discards the staged draft.
|
|
123
|
+
// Adjusted during render, so no commit paints the discarded draft.
|
|
124
|
+
const [draftSource, setDraftSource] = useState(() => ({
|
|
125
|
+
value: [...value],
|
|
126
|
+
commitBehavior
|
|
127
|
+
}));
|
|
128
|
+
if (!areOrderedValuesEqual(draftSource.value, value) || !Object.is(draftSource.commitBehavior, commitBehavior)) {
|
|
129
|
+
setDraftSource({
|
|
130
|
+
value: [...value],
|
|
131
|
+
commitBehavior
|
|
132
|
+
});
|
|
133
|
+
setDraftValue([...value]);
|
|
134
|
+
}
|
|
136
135
|
const resolvedWidth = typeof width === 'number' ? `${width}px` : width ?? DEFAULT_SELECTOR_WIDTH;
|
|
137
136
|
return /*#__PURE__*/_jsx(ComplexSelector, {
|
|
138
137
|
...selectorProps,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/lab",
|
|
3
|
-
"version": "0.7.0-canary.
|
|
3
|
+
"version": "0.7.0-canary.61639ee",
|
|
4
4
|
"description": "Experimental Astryx components — published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.",
|
|
5
5
|
"author": "Meta Open Source",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@stylexjs/stylex": ">=0.10.0",
|
|
50
|
-
"@astryxdesign/core": "0.7.0-canary.
|
|
50
|
+
"@astryxdesign/core": "0.7.0-canary.61639ee",
|
|
51
51
|
"react": ">=19.0.0",
|
|
52
52
|
"react-dom": ">=19.0.0"
|
|
53
53
|
},
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"d3-shape": "^3.2.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@astryxdesign/a11y-spec": "0.7.0-canary.
|
|
61
|
-
"@astryxdesign/cli": "0.7.0-canary.
|
|
60
|
+
"@astryxdesign/a11y-spec": "0.7.0-canary.61639ee",
|
|
61
|
+
"@astryxdesign/cli": "0.7.0-canary.61639ee",
|
|
62
62
|
"@babel/cli": "^7.29.7",
|
|
63
63
|
"@babel/core": "^7.29.7",
|
|
64
64
|
"@babel/preset-react": "^7.29.7",
|
package/src/Tour/Tour.test.tsx
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import {describe, it, expect, vi, beforeAll} from 'vitest';
|
|
14
14
|
import {render, screen, fireEvent} from '@testing-library/react';
|
|
15
|
-
import {useRef, useState} from 'react';
|
|
15
|
+
import {Profiler, useRef, useState} from 'react';
|
|
16
16
|
import {Tour} from './Tour';
|
|
17
17
|
import {TourStep} from './TourStep';
|
|
18
18
|
import {useTour} from './useTour';
|
|
@@ -259,3 +259,55 @@ describe('useTour', () => {
|
|
|
259
259
|
expect(last.last).toBe(false);
|
|
260
260
|
});
|
|
261
261
|
});
|
|
262
|
+
|
|
263
|
+
describe('Tour reset timing', () => {
|
|
264
|
+
function StepProbe() {
|
|
265
|
+
const tour = useTour();
|
|
266
|
+
return <output data-testid="step-index">{tour?.activeStepIndex}</output>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function Harness({isActive}: {isActive: boolean}) {
|
|
270
|
+
const aRef = useRef<HTMLButtonElement>(null);
|
|
271
|
+
const bRef = useRef<HTMLButtonElement>(null);
|
|
272
|
+
return (
|
|
273
|
+
<>
|
|
274
|
+
<button type="button" ref={aRef}>
|
|
275
|
+
Target A
|
|
276
|
+
</button>
|
|
277
|
+
<button type="button" ref={bRef}>
|
|
278
|
+
Target B
|
|
279
|
+
</button>
|
|
280
|
+
<Tour isActive={isActive} onDismiss={() => {}}>
|
|
281
|
+
<StepProbe />
|
|
282
|
+
<TourStep targetRef={aRef} heading="First">
|
|
283
|
+
First body
|
|
284
|
+
</TourStep>
|
|
285
|
+
<TourStep targetRef={bRef} heading="Second">
|
|
286
|
+
Second body
|
|
287
|
+
</TourStep>
|
|
288
|
+
</Tour>
|
|
289
|
+
</>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
it('resets to the first step in the same commit that deactivates the tour', () => {
|
|
294
|
+
const frames: string[] = [];
|
|
295
|
+
const onRender = () =>
|
|
296
|
+
frames.push(screen.getByTestId('step-index').textContent ?? '');
|
|
297
|
+
const ui = (isActive: boolean) => (
|
|
298
|
+
<Profiler id="tour" onRender={onRender}>
|
|
299
|
+
<Harness isActive={isActive} />
|
|
300
|
+
</Profiler>
|
|
301
|
+
);
|
|
302
|
+
const {rerender} = render(ui(true));
|
|
303
|
+
fireEvent.click(screen.getByText('Next'));
|
|
304
|
+
expect(screen.getByTestId('step-index')).toHaveTextContent('1');
|
|
305
|
+
|
|
306
|
+
frames.length = 0;
|
|
307
|
+
rerender(ui(false));
|
|
308
|
+
|
|
309
|
+
expect(frames.length).toBeGreaterThan(0);
|
|
310
|
+
expect(frames).not.toContain('1');
|
|
311
|
+
expect(screen.getByTestId('step-index')).toHaveTextContent('0');
|
|
312
|
+
});
|
|
313
|
+
});
|
package/src/Tour/Tour.tsx
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* - /packages/lab/src/Tour/index.ts (exports if types change)
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
-
import {useCallback,
|
|
32
|
+
import {useCallback, useMemo, useState, type ReactNode} from 'react';
|
|
33
33
|
import {
|
|
34
34
|
TourContext,
|
|
35
35
|
type TourDismissSource,
|
|
@@ -108,13 +108,16 @@ export function Tour({
|
|
|
108
108
|
};
|
|
109
109
|
}, []);
|
|
110
110
|
|
|
111
|
-
// Reset to the first step
|
|
112
|
-
//
|
|
113
|
-
|
|
111
|
+
// Reset to the first step when the tour is deactivated, so a dismissed tour
|
|
112
|
+
// begins from the top next time isActive flips back on. Adjusted during
|
|
113
|
+
// render, so no commit carries the old step past deactivation.
|
|
114
|
+
const [wasActive, setWasActive] = useState(isActive);
|
|
115
|
+
if (!Object.is(wasActive, isActive)) {
|
|
116
|
+
setWasActive(isActive);
|
|
114
117
|
if (!isActive) {
|
|
115
118
|
setActiveStepIndex(0);
|
|
116
119
|
}
|
|
117
|
-
}
|
|
120
|
+
}
|
|
118
121
|
|
|
119
122
|
const stepCount = stepIds.length;
|
|
120
123
|
|
|
@@ -239,24 +239,26 @@ export const docs = {
|
|
|
239
239
|
'Optional async action run after each immediate commit or a changed staged Apply; drives optimistic and busy state.',
|
|
240
240
|
},
|
|
241
241
|
{
|
|
242
|
-
name: '
|
|
242
|
+
name: 'controlXstyle',
|
|
243
243
|
type: 'StyleXStyles',
|
|
244
|
-
description:
|
|
244
|
+
description:
|
|
245
|
+
"StyleX styles for the external selector's bordered control box.",
|
|
245
246
|
},
|
|
246
247
|
{
|
|
247
|
-
name: '
|
|
248
|
+
name: 'controlClassName',
|
|
248
249
|
type: 'string',
|
|
249
|
-
description:
|
|
250
|
+
description: "Class name applied to the external selector's control box.",
|
|
250
251
|
},
|
|
251
252
|
{
|
|
252
|
-
name: '
|
|
253
|
+
name: 'controlStyle',
|
|
253
254
|
type: 'CSSProperties',
|
|
254
|
-
description:
|
|
255
|
+
description:
|
|
256
|
+
"Inline styles applied to the external selector's control box.",
|
|
255
257
|
},
|
|
256
258
|
{
|
|
257
259
|
name: 'data-testid',
|
|
258
260
|
type: 'string',
|
|
259
|
-
description: 'Test ID for the selector trigger
|
|
261
|
+
description: 'Test ID for the selector trigger button.',
|
|
260
262
|
},
|
|
261
263
|
],
|
|
262
264
|
components: [
|
|
@@ -1216,7 +1216,7 @@ export function TransferList<T extends string = string>({
|
|
|
1216
1216
|
startIcon={<Icon icon="search" size="sm" color="secondary" />}
|
|
1217
1217
|
hasClear
|
|
1218
1218
|
width="100%"
|
|
1219
|
-
|
|
1219
|
+
controlXstyle={styles.search}
|
|
1220
1220
|
onChange={handleSearch}
|
|
1221
1221
|
/>
|
|
1222
1222
|
</div>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* SYNC: When TransferListSelector.tsx behavior changes, update this test.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {useState} from 'react';
|
|
12
|
+
import {Profiler, useState} from 'react';
|
|
13
13
|
import {afterAll, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
14
14
|
import {
|
|
15
15
|
fireEvent,
|
|
@@ -557,10 +557,10 @@ describe('TransferListSelector', () => {
|
|
|
557
557
|
expect(
|
|
558
558
|
screen.getByText('Choose the columns shown in the table.'),
|
|
559
559
|
).toBeVisible();
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
'
|
|
563
|
-
);
|
|
560
|
+
// data-testid lands on the trigger button inside the control box.
|
|
561
|
+
expect(
|
|
562
|
+
screen.getByTestId('column-selector').closest('.astryx-complex-selector'),
|
|
563
|
+
).toHaveAttribute('data-size', 'sm');
|
|
564
564
|
expect(
|
|
565
565
|
screen.getByRole('button', {name: 'Table columns'}),
|
|
566
566
|
).toHaveTextContent('Customize columns');
|
|
@@ -603,3 +603,42 @@ describe('TransferListSelector', () => {
|
|
|
603
603
|
);
|
|
604
604
|
});
|
|
605
605
|
});
|
|
606
|
+
|
|
607
|
+
describe('TransferListSelector draft reset timing', () => {
|
|
608
|
+
it('replaces a staged draft in the same commit as an external value change', async () => {
|
|
609
|
+
const user = userEvent.setup();
|
|
610
|
+
const frames: boolean[] = [];
|
|
611
|
+
const onRender = () =>
|
|
612
|
+
frames.push(
|
|
613
|
+
screen.queryByRole('button', {name: 'Remove Owner', ...hidden}) != null,
|
|
614
|
+
);
|
|
615
|
+
const ui = (value: string[]) => (
|
|
616
|
+
<Profiler id="selector" onRender={onRender}>
|
|
617
|
+
<TransferListSelector
|
|
618
|
+
label="Visible fields"
|
|
619
|
+
options={OPTIONS}
|
|
620
|
+
value={value}
|
|
621
|
+
onChange={() => {}}
|
|
622
|
+
commitBehavior="staged"
|
|
623
|
+
/>
|
|
624
|
+
</Profiler>
|
|
625
|
+
);
|
|
626
|
+
const view = render(ui(['name', 'status']));
|
|
627
|
+
await openSelector();
|
|
628
|
+
await user.click(
|
|
629
|
+
screen.getByRole('button', {name: 'Add Owner', ...hidden}),
|
|
630
|
+
);
|
|
631
|
+
expect(
|
|
632
|
+
screen.getByRole('button', {name: 'Remove Owner', ...hidden}),
|
|
633
|
+
).toBeInTheDocument();
|
|
634
|
+
|
|
635
|
+
frames.length = 0;
|
|
636
|
+
view.rerender(ui(['name']));
|
|
637
|
+
|
|
638
|
+
expect(frames.length).toBeGreaterThan(0);
|
|
639
|
+
expect(frames).not.toContain(true);
|
|
640
|
+
expect(
|
|
641
|
+
screen.getByRole('button', {name: 'Add Owner', ...hidden}),
|
|
642
|
+
).toBeInTheDocument();
|
|
643
|
+
});
|
|
644
|
+
});
|
|
@@ -93,9 +93,9 @@ type TransferListSelectorShellProp =
|
|
|
93
93
|
| 'size'
|
|
94
94
|
| 'width'
|
|
95
95
|
| 'placement'
|
|
96
|
-
| '
|
|
97
|
-
| '
|
|
98
|
-
| '
|
|
96
|
+
| 'controlXstyle'
|
|
97
|
+
| 'controlClassName'
|
|
98
|
+
| 'controlStyle'
|
|
99
99
|
| 'data-testid';
|
|
100
100
|
|
|
101
101
|
type TransferListContentProp =
|
|
@@ -217,27 +217,24 @@ export function TransferListSelector<T extends string = string>({
|
|
|
217
217
|
const cancelLabel =
|
|
218
218
|
cancelLabelFromProps ?? t('@astryx.transferListSelector.cancel');
|
|
219
219
|
const [draftValue, setDraftValue] = useState<readonly T[]>(value);
|
|
220
|
-
const previousAppliedValueRef = useRef<readonly T[]>([...value]);
|
|
221
|
-
const previousCommitBehaviorRef = useRef(commitBehavior);
|
|
222
220
|
|
|
223
221
|
const resetDraft = useCallback(() => {
|
|
224
222
|
setDraftValue([...value]);
|
|
225
223
|
}, [value]);
|
|
226
224
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}, [commitBehavior, resetDraft]);
|
|
225
|
+
// A changed applied value or commit behavior discards the staged draft.
|
|
226
|
+
// Adjusted during render, so no commit paints the discarded draft.
|
|
227
|
+
const [draftSource, setDraftSource] = useState(() => ({
|
|
228
|
+
value: [...value],
|
|
229
|
+
commitBehavior,
|
|
230
|
+
}));
|
|
231
|
+
if (
|
|
232
|
+
!areOrderedValuesEqual(draftSource.value, value) ||
|
|
233
|
+
!Object.is(draftSource.commitBehavior, commitBehavior)
|
|
234
|
+
) {
|
|
235
|
+
setDraftSource({value: [...value], commitBehavior});
|
|
236
|
+
setDraftValue([...value]);
|
|
237
|
+
}
|
|
241
238
|
|
|
242
239
|
const resolvedWidth =
|
|
243
240
|
typeof width === 'number'
|