@workbench-kit/shell-react 0.0.2-prototype.0.2.31 → 0.0.2-prototype.0.2.33
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/package.json +9 -9
- package/src/field-remap/chrome-labels.ts +29 -0
- package/src/field-remap/convert-palette.tsx +14 -13
- package/src/field-remap/demo.tsx +17 -1
- package/src/field-remap/detail-panel.tsx +6 -5
- package/src/field-remap/flow.tsx +297 -155
- package/src/field-remap/panel.tsx +17 -0
- package/src/field-remap/view.css +82 -2
- package/src/index.ts +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workbench-kit/shell-react",
|
|
3
|
-
"version": "0.0.2-prototype.0.2.
|
|
3
|
+
"version": "0.0.2-prototype.0.2.33",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
"@radix-ui/react-slot": "^1.3.0",
|
|
32
32
|
"@xyflow/react": "^12.11.2",
|
|
33
33
|
"jsonata": "^2.2.0",
|
|
34
|
-
"@workbench-kit/react": "0.0.2-prototype.0.2.
|
|
35
|
-
"@workbench-kit/
|
|
36
|
-
"@workbench-kit/
|
|
37
|
-
"@workbench-kit/
|
|
38
|
-
"@workbench-kit/
|
|
39
|
-
"@workbench-kit/
|
|
40
|
-
"@workbench-kit/
|
|
41
|
-
"@workbench-kit/
|
|
34
|
+
"@workbench-kit/react": "0.0.2-prototype.0.2.33",
|
|
35
|
+
"@workbench-kit/field-remap": "0.0.2-prototype.0.2.33",
|
|
36
|
+
"@workbench-kit/workbench-config": "0.0.2-prototype.0.2.33",
|
|
37
|
+
"@workbench-kit/workbench-core": "0.0.2-prototype.0.2.33",
|
|
38
|
+
"@workbench-kit/tokens": "0.0.2-prototype.0.2.33",
|
|
39
|
+
"@workbench-kit/platform": "0.0.2-prototype.0.2.33",
|
|
40
|
+
"@workbench-kit/workbench-extension-sdk": "0.0.2-prototype.0.2.33",
|
|
41
|
+
"@workbench-kit/workspace": "0.0.2-prototype.0.2.33"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"react": "^19.0.0",
|
|
@@ -19,12 +19,19 @@ export interface FieldRemapChromeLabels {
|
|
|
19
19
|
readonly convertPaletteAriaLabel: string;
|
|
20
20
|
readonly convertsListAriaLabel: string;
|
|
21
21
|
readonly placeConvert: string;
|
|
22
|
+
readonly addCombine: string;
|
|
23
|
+
readonly addSplit: string;
|
|
22
24
|
readonly operatorsTitle: string;
|
|
23
25
|
readonly operatorsDescription: string;
|
|
26
|
+
readonly addTransform: string;
|
|
27
|
+
readonly editItems: string;
|
|
28
|
+
readonly removeBinding: string;
|
|
24
29
|
readonly showMinimap: string;
|
|
25
30
|
readonly hideMinimap: string;
|
|
26
31
|
readonly showHiddenFields: string;
|
|
27
32
|
readonly hideHiddenFields: string;
|
|
33
|
+
readonly emptyDetailTitle: string;
|
|
34
|
+
readonly emptyDetailDescription: string;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
export const defaultFieldRemapChromeLabels: FieldRemapChromeLabels = {
|
|
@@ -35,13 +42,21 @@ export const defaultFieldRemapChromeLabels: FieldRemapChromeLabels = {
|
|
|
35
42
|
convertPaletteAriaLabel: 'Convert palette',
|
|
36
43
|
convertsListAriaLabel: 'Converts',
|
|
37
44
|
placeConvert: 'Place convert',
|
|
45
|
+
addCombine: 'Add combine',
|
|
46
|
+
addSplit: 'Add split',
|
|
38
47
|
operatorsTitle: 'n→m operators',
|
|
39
48
|
operatorsDescription:
|
|
40
49
|
'Create combine (n→1) or split (1→n), then wire ports or edit in the side rail.',
|
|
50
|
+
addTransform: 'Add convert',
|
|
51
|
+
editItems: 'Edit items',
|
|
52
|
+
removeBinding: 'Remove binding',
|
|
41
53
|
showMinimap: 'Show minimap',
|
|
42
54
|
hideMinimap: 'Hide minimap',
|
|
43
55
|
showHiddenFields: 'Show hidden fields',
|
|
44
56
|
hideHiddenFields: 'Hide hidden fields',
|
|
57
|
+
emptyDetailTitle: 'Start with a convert',
|
|
58
|
+
emptyDetailDescription:
|
|
59
|
+
'Use the Convert palette to place a convert, then wire source → draft → target. Or select an existing binding / convert note on the canvas.',
|
|
45
60
|
};
|
|
46
61
|
|
|
47
62
|
/** Stable capability ids for optional `t()` injection (not free prose). */
|
|
@@ -52,12 +67,19 @@ export const fieldRemapChromeLabelKeys = {
|
|
|
52
67
|
convertPaletteAriaLabel: 'fieldRemap.convertPaletteAriaLabel',
|
|
53
68
|
convertsListAriaLabel: 'fieldRemap.convertsListAriaLabel',
|
|
54
69
|
placeConvert: 'fieldRemap.placeConvert',
|
|
70
|
+
addCombine: 'fieldRemap.addCombine',
|
|
71
|
+
addSplit: 'fieldRemap.addSplit',
|
|
55
72
|
operatorsTitle: 'fieldRemap.operatorsTitle',
|
|
56
73
|
operatorsDescription: 'fieldRemap.operatorsDescription',
|
|
74
|
+
addTransform: 'fieldRemap.addTransform',
|
|
75
|
+
editItems: 'fieldRemap.editItems',
|
|
76
|
+
removeBinding: 'fieldRemap.removeBinding',
|
|
57
77
|
showMinimap: 'fieldRemap.showMinimap',
|
|
58
78
|
hideMinimap: 'fieldRemap.hideMinimap',
|
|
59
79
|
showHiddenFields: 'fieldRemap.showHiddenFields',
|
|
60
80
|
hideHiddenFields: 'fieldRemap.hideHiddenFields',
|
|
81
|
+
emptyDetailTitle: 'fieldRemap.emptyDetailTitle',
|
|
82
|
+
emptyDetailDescription: 'fieldRemap.emptyDetailDescription',
|
|
61
83
|
} as const satisfies Record<keyof FieldRemapChromeLabels, string>;
|
|
62
84
|
|
|
63
85
|
export function resolveFieldRemapChromeLabels(
|
|
@@ -80,11 +102,18 @@ export function resolveFieldRemapChromeLabels(
|
|
|
80
102
|
convertPaletteAriaLabel: resolve('convertPaletteAriaLabel'),
|
|
81
103
|
convertsListAriaLabel: resolve('convertsListAriaLabel'),
|
|
82
104
|
placeConvert: resolve('placeConvert'),
|
|
105
|
+
addCombine: resolve('addCombine'),
|
|
106
|
+
addSplit: resolve('addSplit'),
|
|
83
107
|
operatorsTitle: resolve('operatorsTitle'),
|
|
84
108
|
operatorsDescription: resolve('operatorsDescription'),
|
|
109
|
+
addTransform: resolve('addTransform'),
|
|
110
|
+
editItems: resolve('editItems'),
|
|
111
|
+
removeBinding: resolve('removeBinding'),
|
|
85
112
|
showMinimap: resolve('showMinimap'),
|
|
86
113
|
hideMinimap: resolve('hideMinimap'),
|
|
87
114
|
showHiddenFields: resolve('showHiddenFields'),
|
|
88
115
|
hideHiddenFields: resolve('hideHiddenFields'),
|
|
116
|
+
emptyDetailTitle: resolve('emptyDetailTitle'),
|
|
117
|
+
emptyDetailDescription: resolve('emptyDetailDescription'),
|
|
89
118
|
};
|
|
90
119
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JSX } from 'react';
|
|
2
2
|
import { SideBarList, SideBarListItem } from '@workbench-kit/react/layout';
|
|
3
|
-
import {
|
|
3
|
+
import { IconButton } from '@workbench-kit/react/primitives';
|
|
4
4
|
import type { ValueTransformRegistry } from '@workbench-kit/field-remap';
|
|
5
5
|
|
|
6
6
|
import { defaultFieldRemapChromeLabels, type FieldRemapChromeLabels } from './chrome-labels.js';
|
|
@@ -45,19 +45,20 @@ export function FieldRemapConvertPalette({
|
|
|
45
45
|
</header>
|
|
46
46
|
|
|
47
47
|
<div className="workbench-field-remap-convert-palette__place">
|
|
48
|
-
<
|
|
48
|
+
<IconButton
|
|
49
|
+
compact
|
|
49
50
|
type="button"
|
|
50
51
|
data-testid="field-remap-place-draft"
|
|
51
52
|
disabled={!selectedTransformId}
|
|
53
|
+
icon="codicon-add"
|
|
54
|
+
label={chromeLabels.placeConvert}
|
|
52
55
|
onClick={() => {
|
|
53
56
|
if (!selectedTransformId) {
|
|
54
57
|
return;
|
|
55
58
|
}
|
|
56
59
|
onPlaceDraft(selectedTransformId);
|
|
57
60
|
}}
|
|
58
|
-
|
|
59
|
-
{chromeLabels.placeConvert}
|
|
60
|
-
</Button>
|
|
61
|
+
/>
|
|
61
62
|
</div>
|
|
62
63
|
|
|
63
64
|
<SideBarList
|
|
@@ -95,24 +96,24 @@ export function FieldRemapConvertPalette({
|
|
|
95
96
|
<p>{chromeLabels.operatorsDescription}</p>
|
|
96
97
|
<div className="workbench-field-remap-convert-palette__operator-actions">
|
|
97
98
|
{onAddCombine ? (
|
|
98
|
-
<
|
|
99
|
+
<IconButton
|
|
99
100
|
compact
|
|
100
101
|
type="button"
|
|
101
102
|
data-testid="field-remap-add-combine"
|
|
103
|
+
icon="codicon-git-merge"
|
|
104
|
+
label={chromeLabels.addCombine}
|
|
102
105
|
onClick={onAddCombine}
|
|
103
|
-
|
|
104
|
-
Add combine
|
|
105
|
-
</Button>
|
|
106
|
+
/>
|
|
106
107
|
) : null}
|
|
107
108
|
{onAddSplit ? (
|
|
108
|
-
<
|
|
109
|
+
<IconButton
|
|
109
110
|
compact
|
|
110
111
|
type="button"
|
|
111
112
|
data-testid="field-remap-add-split"
|
|
113
|
+
icon="codicon-split-horizontal"
|
|
114
|
+
label={chromeLabels.addSplit}
|
|
112
115
|
onClick={onAddSplit}
|
|
113
|
-
|
|
114
|
-
Add split
|
|
115
|
-
</Button>
|
|
116
|
+
/>
|
|
116
117
|
) : null}
|
|
117
118
|
</div>
|
|
118
119
|
</div>
|
package/src/field-remap/demo.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState, type JSX } from 'react';
|
|
|
2
2
|
import { Button } from '@workbench-kit/react/primitives';
|
|
3
3
|
|
|
4
4
|
import type { FieldRemapChromeLabels, FieldRemapTranslate } from './chrome-labels.js';
|
|
5
|
-
import type { FieldRemapFlowActions } from './flow.js';
|
|
5
|
+
import type { FieldRemapFlowActions, FieldRemapFlowMapperProps } from './flow.js';
|
|
6
6
|
import type { FieldRemapIoChrome } from './io-class-browse.js';
|
|
7
7
|
import { FieldRemapPanel } from './panel.js';
|
|
8
8
|
import {
|
|
@@ -15,6 +15,12 @@ export interface SampleFieldRemapDemoProps {
|
|
|
15
15
|
readonly sampleId?: FieldRemapSampleId | string | undefined;
|
|
16
16
|
/** Forwarded to Flow mapper (default true). */
|
|
17
17
|
readonly showMinimap?: boolean | undefined;
|
|
18
|
+
/** Forwarded Flow chrome preset. */
|
|
19
|
+
readonly chrome?: FieldRemapFlowMapperProps['chrome'];
|
|
20
|
+
readonly showFlowHint?: FieldRemapFlowMapperProps['showFlowHint'];
|
|
21
|
+
readonly showBindingsList?: FieldRemapFlowMapperProps['showBindingsList'];
|
|
22
|
+
readonly showConvertPalette?: FieldRemapFlowMapperProps['showConvertPalette'];
|
|
23
|
+
readonly emptyDetail?: FieldRemapFlowMapperProps['emptyDetail'];
|
|
18
24
|
/** When true, show host-chrome demo controls (minimap toggle + fit view). */
|
|
19
25
|
readonly showHostChromeDemo?: boolean | undefined;
|
|
20
26
|
/** Prefer `browse` for I/O class/field inspection demos. */
|
|
@@ -31,6 +37,11 @@ export interface SampleFieldRemapDemoProps {
|
|
|
31
37
|
export function SampleFieldRemapDemo({
|
|
32
38
|
sampleId = 'nested-ab',
|
|
33
39
|
showMinimap: showMinimapProp,
|
|
40
|
+
chrome,
|
|
41
|
+
showFlowHint,
|
|
42
|
+
showBindingsList,
|
|
43
|
+
showConvertPalette,
|
|
44
|
+
emptyDetail,
|
|
34
45
|
showHostChromeDemo = false,
|
|
35
46
|
ioChrome,
|
|
36
47
|
browseSeedShapes = false,
|
|
@@ -76,6 +87,11 @@ export function SampleFieldRemapDemo({
|
|
|
76
87
|
key={`${sample.id}:${ioChrome ?? 'default'}:${browseSeedShapes ? 'seed' : 'plain'}`}
|
|
77
88
|
sample={sample}
|
|
78
89
|
showMinimap={showMinimap}
|
|
90
|
+
chrome={chrome}
|
|
91
|
+
showFlowHint={showFlowHint}
|
|
92
|
+
showBindingsList={showBindingsList}
|
|
93
|
+
showConvertPalette={showConvertPalette}
|
|
94
|
+
emptyDetail={emptyDetail}
|
|
79
95
|
onShowMinimapChange={setShowMinimap}
|
|
80
96
|
ioChrome={ioChrome}
|
|
81
97
|
editableShapes={ioChrome === 'browse' ? false : undefined}
|
|
@@ -45,6 +45,8 @@ export interface FieldRemapDetailPanelProps {
|
|
|
45
45
|
readonly onDiscardDraft?: ((localId: string) => void) | undefined;
|
|
46
46
|
readonly operators?: readonly MappingOperator[] | undefined;
|
|
47
47
|
readonly onOperatorsChange?: ((operators: readonly MappingOperator[]) => void) | undefined;
|
|
48
|
+
readonly emptyDetailTitle?: string | undefined;
|
|
49
|
+
readonly emptyDetailDescription?: string | undefined;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
function fieldLabel(
|
|
@@ -77,6 +79,8 @@ export function FieldRemapDetailPanel({
|
|
|
77
79
|
onDiscardDraft,
|
|
78
80
|
operators = [],
|
|
79
81
|
onOperatorsChange,
|
|
82
|
+
emptyDetailTitle = 'Start with a convert',
|
|
83
|
+
emptyDetailDescription = 'Use the Convert palette to place a convert, then wire source → draft → target. Or select an existing binding / convert note on the canvas.',
|
|
80
84
|
}: FieldRemapDetailPanelProps): JSX.Element | null {
|
|
81
85
|
const edge = useMemo(() => {
|
|
82
86
|
if (!selection || (selection.kind !== 'edge' && selection.kind !== 'transformStep')) {
|
|
@@ -113,11 +117,8 @@ export function FieldRemapDetailPanel({
|
|
|
113
117
|
data-testid="field-remap-detail"
|
|
114
118
|
aria-label="Binding details"
|
|
115
119
|
>
|
|
116
|
-
<h4>
|
|
117
|
-
<p data-testid="field-remap-detail-empty-hint">
|
|
118
|
-
Use the Convert palette to place a convert, then wire source → draft → target. Or select
|
|
119
|
-
an existing binding / convert note on the canvas.
|
|
120
|
-
</p>
|
|
120
|
+
<h4>{emptyDetailTitle}</h4>
|
|
121
|
+
<p data-testid="field-remap-detail-empty-hint">{emptyDetailDescription}</p>
|
|
121
122
|
</aside>
|
|
122
123
|
);
|
|
123
124
|
}
|
package/src/field-remap/flow.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Children,
|
|
2
3
|
useCallback,
|
|
3
4
|
useEffect,
|
|
4
5
|
useImperativeHandle,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
type KeyboardEvent,
|
|
10
11
|
type MouseEvent,
|
|
11
12
|
type Ref,
|
|
13
|
+
type ReactNode,
|
|
12
14
|
} from 'react';
|
|
13
15
|
import {
|
|
14
16
|
Background,
|
|
@@ -28,7 +30,8 @@ import {
|
|
|
28
30
|
type NodeProps,
|
|
29
31
|
} from '@xyflow/react';
|
|
30
32
|
import '@xyflow/react/dist/style.css';
|
|
31
|
-
import { Badge,
|
|
33
|
+
import { Badge, IconButton } from '@workbench-kit/react/primitives';
|
|
34
|
+
import { SplitView } from '@workbench-kit/react/workbench/split-view';
|
|
32
35
|
import {
|
|
33
36
|
MAX_TRANSFORM_CHAIN,
|
|
34
37
|
type MappingEdge,
|
|
@@ -323,6 +326,22 @@ export interface FieldRemapFlowMapperProps {
|
|
|
323
326
|
readonly edges: readonly MappingEdge[];
|
|
324
327
|
readonly transforms: ValueTransformRegistry;
|
|
325
328
|
readonly onEdgesChange: (edges: readonly MappingEdge[]) => void;
|
|
329
|
+
/**
|
|
330
|
+
* `card` preserves the demo chrome. `embed` omits the flow hint and binding list;
|
|
331
|
+
* explicit `show*` props below take precedence.
|
|
332
|
+
*/
|
|
333
|
+
readonly chrome?: 'card' | 'embed' | undefined;
|
|
334
|
+
/** Show the empty-selection detail hint, or collapse that rail until a selection exists. */
|
|
335
|
+
readonly emptyDetail?: 'hint' | 'collapse' | undefined;
|
|
336
|
+
/** Show the convert-first hint. Defaults to true for `card`, false for `embed`. */
|
|
337
|
+
readonly showFlowHint?: boolean | undefined;
|
|
338
|
+
/** Show the bottom binding list. Defaults to true for `card`, false for `embed`. */
|
|
339
|
+
readonly showBindingsList?: boolean | undefined;
|
|
340
|
+
/**
|
|
341
|
+
* Mount the primary Convert palette. Defaults to true for both chrome modes; when false,
|
|
342
|
+
* the workspace expands without leaving an empty grid track.
|
|
343
|
+
*/
|
|
344
|
+
readonly showConvertPalette?: boolean | undefined;
|
|
326
345
|
/** Document v2 n→m operators (display + authoring when onOperatorsChange is set). */
|
|
327
346
|
readonly operators?: readonly MappingOperator[] | undefined;
|
|
328
347
|
readonly onOperatorsChange?: ((operators: readonly MappingOperator[]) => void) | undefined;
|
|
@@ -380,12 +399,87 @@ export interface FieldRemapFlowMapperProps {
|
|
|
380
399
|
readonly t?: FieldRemapTranslate | undefined;
|
|
381
400
|
}
|
|
382
401
|
|
|
402
|
+
interface FieldRemapSplitWorkspaceProps {
|
|
403
|
+
readonly children: ReactNode;
|
|
404
|
+
readonly layout: 'wide' | 'medium' | 'narrow';
|
|
405
|
+
readonly showConvertPalette: boolean;
|
|
406
|
+
readonly showDetail: boolean;
|
|
407
|
+
readonly surface: 'binding' | 'convert-note' | 'draft-convert' | 'operator';
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* The Flow rails are deliberately composed from the shared SplitView primitive so keyboard and
|
|
412
|
+
* pointer resizing stay consistent with the rest of the workbench. At narrower host widths the
|
|
413
|
+
* palette and/or detail move above or below the canvas rather than squeezing its usable width.
|
|
414
|
+
*/
|
|
415
|
+
function FieldRemapSplitWorkspace({
|
|
416
|
+
children,
|
|
417
|
+
layout,
|
|
418
|
+
showConvertPalette,
|
|
419
|
+
showDetail,
|
|
420
|
+
surface,
|
|
421
|
+
}: FieldRemapSplitWorkspaceProps): JSX.Element {
|
|
422
|
+
const [palette, canvas, detail] = Children.toArray(children);
|
|
423
|
+
const isNarrow = layout === 'narrow';
|
|
424
|
+
const canvasWithDetail = showDetail ? (
|
|
425
|
+
<SplitView
|
|
426
|
+
className="workbench-field-remap-flow__canvas-detail-split"
|
|
427
|
+
defaultSecondarySizePx={isNarrow ? 220 : 320}
|
|
428
|
+
layoutMode="secondary-fixed"
|
|
429
|
+
maxSecondarySizePx={isNarrow ? 320 : 480}
|
|
430
|
+
minPrimarySizePx={isNarrow ? 200 : 280}
|
|
431
|
+
minSecondarySizePx={isNarrow ? 160 : 256}
|
|
432
|
+
orientation={isNarrow ? 'vertical' : 'horizontal'}
|
|
433
|
+
primary={canvas}
|
|
434
|
+
secondary={detail}
|
|
435
|
+
/>
|
|
436
|
+
) : (
|
|
437
|
+
canvas
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
const content = showConvertPalette ? (
|
|
441
|
+
<SplitView
|
|
442
|
+
className="workbench-field-remap-flow__palette-split"
|
|
443
|
+
defaultPrimarySizePx={isNarrow ? 192 : 240}
|
|
444
|
+
maxPrimarySizePx={isNarrow ? 288 : 320}
|
|
445
|
+
minPrimarySizePx={isNarrow ? 160 : 192}
|
|
446
|
+
minSecondarySizePx={isNarrow ? 200 : 280}
|
|
447
|
+
orientation={layout === 'wide' ? 'horizontal' : 'vertical'}
|
|
448
|
+
primary={palette}
|
|
449
|
+
primarySizeUnit="pixels"
|
|
450
|
+
secondary={canvasWithDetail}
|
|
451
|
+
/>
|
|
452
|
+
) : (
|
|
453
|
+
canvasWithDetail
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
return (
|
|
457
|
+
<div
|
|
458
|
+
className={
|
|
459
|
+
showConvertPalette
|
|
460
|
+
? 'workbench-field-remap-flow__workspace workbench-field-remap-flow__workspace--split'
|
|
461
|
+
: 'workbench-field-remap-flow__workspace workbench-field-remap-flow__workspace--split workbench-field-remap-flow__workspace--without-palette'
|
|
462
|
+
}
|
|
463
|
+
data-layout={layout}
|
|
464
|
+
data-surface={surface}
|
|
465
|
+
data-testid="field-remap-workspace"
|
|
466
|
+
>
|
|
467
|
+
{content}
|
|
468
|
+
</div>
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
|
|
383
472
|
function FieldRemapFlowCanvas({
|
|
384
473
|
sources,
|
|
385
474
|
targets,
|
|
386
475
|
edges,
|
|
387
476
|
transforms,
|
|
388
477
|
onEdgesChange,
|
|
478
|
+
chrome = 'card',
|
|
479
|
+
emptyDetail: emptyDetailProp,
|
|
480
|
+
showFlowHint: showFlowHintProp,
|
|
481
|
+
showBindingsList: showBindingsListProp,
|
|
482
|
+
showConvertPalette = true,
|
|
389
483
|
operators = [],
|
|
390
484
|
onOperatorsChange,
|
|
391
485
|
sourceTitle,
|
|
@@ -407,6 +501,11 @@ function FieldRemapFlowCanvas({
|
|
|
407
501
|
() => resolveFieldRemapChromeLabels(labelOverrides, t),
|
|
408
502
|
[labelOverrides, t],
|
|
409
503
|
);
|
|
504
|
+
const showFlowHint = showFlowHintProp ?? chrome !== 'embed';
|
|
505
|
+
const showBindingsList = showBindingsListProp ?? chrome !== 'embed';
|
|
506
|
+
const emptyDetail = emptyDetailProp ?? (chrome === 'embed' ? 'collapse' : 'hint');
|
|
507
|
+
const mapperRef = useRef<HTMLDivElement>(null);
|
|
508
|
+
const [workspaceLayout, setWorkspaceLayout] = useState<'wide' | 'medium' | 'narrow'>('wide');
|
|
410
509
|
const [internalSelection, setInternalSelection] = useState<FieldRemapSelection>(null);
|
|
411
510
|
const selection = selectionProp !== undefined ? selectionProp : internalSelection;
|
|
412
511
|
const setSelection = onSelectionChangeProp ?? setInternalSelection;
|
|
@@ -417,6 +516,29 @@ function FieldRemapFlowCanvas({
|
|
|
417
516
|
});
|
|
418
517
|
const transformRegistrySignature = createTransformRegistrySignature(transforms);
|
|
419
518
|
|
|
519
|
+
useEffect(() => {
|
|
520
|
+
const element = mapperRef.current;
|
|
521
|
+
if (!element || typeof ResizeObserver === 'undefined') {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const updateLayout = () => {
|
|
526
|
+
const remSize = Number.parseFloat(getComputedStyle(element).fontSize) || 16;
|
|
527
|
+
const width = element.getBoundingClientRect().width;
|
|
528
|
+
if (width <= 0) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const nextLayout =
|
|
532
|
+
width <= 60 * remSize ? 'narrow' : width <= 68.75 * remSize ? 'medium' : 'wide';
|
|
533
|
+
setWorkspaceLayout((current) => (current === nextLayout ? current : nextLayout));
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
updateLayout();
|
|
537
|
+
const observer = new ResizeObserver(updateLayout);
|
|
538
|
+
observer.observe(element);
|
|
539
|
+
return () => observer.disconnect();
|
|
540
|
+
}, []);
|
|
541
|
+
|
|
420
542
|
const graph = useMemo(
|
|
421
543
|
() =>
|
|
422
544
|
mappingToFlowGraph({
|
|
@@ -746,26 +868,32 @@ function FieldRemapFlowCanvas({
|
|
|
746
868
|
|
|
747
869
|
return (
|
|
748
870
|
<div
|
|
871
|
+
ref={mapperRef}
|
|
749
872
|
className="workbench-field-remap-flow"
|
|
750
873
|
data-testid="field-remap-mapper"
|
|
874
|
+
data-chrome={chrome}
|
|
875
|
+
data-flow-hint={showFlowHint ? 'on' : 'off'}
|
|
876
|
+
data-bindings-list={showBindingsList ? 'on' : 'off'}
|
|
877
|
+
data-convert-palette={showConvertPalette ? 'on' : 'off'}
|
|
878
|
+
data-empty-detail={emptyDetail}
|
|
751
879
|
data-minimap={showMinimap ? 'on' : 'off'}
|
|
752
880
|
data-hidden-fields={includeHidden ? 'on' : 'off'}
|
|
753
881
|
onKeyDown={onKeyDown}
|
|
754
882
|
>
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
883
|
+
{showFlowHint ? (
|
|
884
|
+
<p className="workbench-field-remap-mapper__hint" data-testid="field-remap-hint">
|
|
885
|
+
Convert-first: pick a convert in the palette, place it, then wire source → draft → target.
|
|
886
|
+
Select a convert note for the Convert editor; select a binding for lighter mapping detail.
|
|
887
|
+
Use n→m actions to author combine/split. Alt-click removes a convert step or operator.
|
|
888
|
+
Escape clears selection and unfinished drafts.
|
|
889
|
+
</p>
|
|
890
|
+
) : null}
|
|
761
891
|
|
|
762
|
-
<
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
data-surface={
|
|
892
|
+
<FieldRemapSplitWorkspace
|
|
893
|
+
layout={workspaceLayout}
|
|
894
|
+
showConvertPalette={showConvertPalette}
|
|
895
|
+
showDetail={emptyDetail === 'hint' || selection !== null}
|
|
896
|
+
surface={
|
|
769
897
|
selection?.kind === 'transformStep'
|
|
770
898
|
? 'convert-note'
|
|
771
899
|
: selection?.kind === 'draft'
|
|
@@ -775,31 +903,35 @@ function FieldRemapFlowCanvas({
|
|
|
775
903
|
: 'binding'
|
|
776
904
|
}
|
|
777
905
|
>
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
906
|
+
<>
|
|
907
|
+
{showConvertPalette ? (
|
|
908
|
+
<FieldRemapConvertPalette
|
|
909
|
+
transforms={transforms}
|
|
910
|
+
selectedTransformId={placeTransformId}
|
|
911
|
+
onSelectedTransformIdChange={setPlaceTransformId}
|
|
912
|
+
onPlaceDraft={placeDraft}
|
|
913
|
+
chromeLabels={chromeLabels}
|
|
914
|
+
onAddCombine={
|
|
915
|
+
onOperatorsChange
|
|
916
|
+
? () => {
|
|
917
|
+
const next = createCombineOperator();
|
|
918
|
+
onOperatorsChange([...operators, next]);
|
|
919
|
+
setSelection({ kind: 'operator', operatorId: next.id });
|
|
920
|
+
}
|
|
921
|
+
: undefined
|
|
922
|
+
}
|
|
923
|
+
onAddSplit={
|
|
924
|
+
onOperatorsChange
|
|
925
|
+
? () => {
|
|
926
|
+
const next = createSplitOperator();
|
|
927
|
+
onOperatorsChange([...operators, next]);
|
|
928
|
+
setSelection({ kind: 'operator', operatorId: next.id });
|
|
929
|
+
}
|
|
930
|
+
: undefined
|
|
931
|
+
}
|
|
932
|
+
/>
|
|
933
|
+
) : null}
|
|
934
|
+
</>
|
|
803
935
|
|
|
804
936
|
<div className="workbench-field-remap-flow__canvas" data-testid="field-remap-flow">
|
|
805
937
|
<ReactFlow
|
|
@@ -930,130 +1062,140 @@ function FieldRemapFlowCanvas({
|
|
|
930
1062
|
</ReactFlow>
|
|
931
1063
|
</div>
|
|
932
1064
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1065
|
+
<>
|
|
1066
|
+
{emptyDetail === 'hint' || selection !== null ? (
|
|
1067
|
+
<FieldRemapDetailPanel
|
|
1068
|
+
selection={selection}
|
|
1069
|
+
edges={edges}
|
|
1070
|
+
sources={sources}
|
|
1071
|
+
targets={targets}
|
|
1072
|
+
transforms={transforms}
|
|
1073
|
+
onEdgesChange={onEdgesChange}
|
|
1074
|
+
onSelectionChange={setSelection}
|
|
1075
|
+
drafts={drafts}
|
|
1076
|
+
onDiscardDraft={(localId) => {
|
|
1077
|
+
setDrafts((current) => current.filter((item) => item.localId !== localId));
|
|
1078
|
+
}}
|
|
1079
|
+
operators={operators}
|
|
1080
|
+
onOperatorsChange={onOperatorsChange}
|
|
1081
|
+
emptyDetailTitle={chromeLabels.emptyDetailTitle}
|
|
1082
|
+
emptyDetailDescription={chromeLabels.emptyDetailDescription}
|
|
1083
|
+
/>
|
|
1084
|
+
) : null}
|
|
1085
|
+
</>
|
|
1086
|
+
</FieldRemapSplitWorkspace>
|
|
949
1087
|
|
|
950
|
-
|
|
951
|
-
<
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1088
|
+
{showBindingsList ? (
|
|
1089
|
+
<div className="workbench-field-remap-flow__bindings" data-testid="field-remap-edges">
|
|
1090
|
+
<h4>{chromeLabels.bindingsTitle}</h4>
|
|
1091
|
+
<ul>
|
|
1092
|
+
{edges.map((edge) => {
|
|
1093
|
+
const portTypes = edgePortTypes(edge, sources, targets);
|
|
1094
|
+
const appendCatalog = listCompatibleTransforms({
|
|
1095
|
+
registry: transforms,
|
|
1096
|
+
edge,
|
|
1097
|
+
stepIndex: edge.transformIds?.length ?? 0,
|
|
1098
|
+
sourceType: portTypes.sourceType,
|
|
1099
|
+
targetType: portTypes.targetType,
|
|
1100
|
+
mode: 'append',
|
|
1101
|
+
});
|
|
1102
|
+
const defaultAddId = appendCatalog[0]?.id;
|
|
1103
|
+
const listContext = canEditListContext(edge, sources, targets);
|
|
1104
|
+
const selected =
|
|
1105
|
+
(selection?.kind === 'edge' || selection?.kind === 'transformStep') &&
|
|
1106
|
+
selection.edgeId === edge.id;
|
|
968
1107
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
>
|
|
975
|
-
<button
|
|
976
|
-
type="button"
|
|
977
|
-
className="workbench-field-remap-flow__binding-select"
|
|
978
|
-
data-testid={`field-remap-select-edge-${edge.id}`}
|
|
979
|
-
onClick={() => setSelection({ kind: 'edge', edgeId: edge.id })}
|
|
1108
|
+
return (
|
|
1109
|
+
<li
|
|
1110
|
+
key={edge.id}
|
|
1111
|
+
className={selected ? 'is-selected' : undefined}
|
|
1112
|
+
data-testid={`field-remap-lane-${edge.id}`}
|
|
980
1113
|
>
|
|
981
|
-
<
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1114
|
+
<button
|
|
1115
|
+
type="button"
|
|
1116
|
+
className="workbench-field-remap-flow__binding-select"
|
|
1117
|
+
data-testid={`field-remap-select-edge-${edge.id}`}
|
|
1118
|
+
onClick={() => setSelection({ kind: 'edge', edgeId: edge.id })}
|
|
1119
|
+
>
|
|
1120
|
+
<code>
|
|
1121
|
+
{edge.sourceFieldId} →{' '}
|
|
1122
|
+
{(edge.transformIds ?? []).length > 0
|
|
1123
|
+
? `${(edge.transformIds ?? []).join(' → ')} → `
|
|
1124
|
+
: ''}
|
|
1125
|
+
{edge.targetSlotId}
|
|
1126
|
+
{edge.itemEdges ? ` · ${edge.itemEdges.length} item fields` : ''}
|
|
1127
|
+
</code>
|
|
1128
|
+
</button>
|
|
1129
|
+
<span className="workbench-field-remap-mapper__edge-actions">
|
|
1130
|
+
{(edge.transformIds?.length ?? 0) < MAX_TRANSFORM_CHAIN && defaultAddId ? (
|
|
1131
|
+
<IconButton
|
|
1132
|
+
compact
|
|
1133
|
+
type="button"
|
|
1134
|
+
data-testid={`field-remap-add-node-${edge.id}`}
|
|
1135
|
+
icon="codicon-add"
|
|
1136
|
+
label={chromeLabels.addTransform}
|
|
1137
|
+
onClick={() => {
|
|
1138
|
+
const next = addTransformStepToEdge(edge, defaultAddId, {
|
|
1139
|
+
registry: transforms,
|
|
1140
|
+
sourceType: portTypes.sourceType,
|
|
1141
|
+
targetType: portTypes.targetType,
|
|
1142
|
+
});
|
|
1143
|
+
if (!next) {
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
onEdgesChange(edges.map((item) => (item.id === edge.id ? next : item)));
|
|
1147
|
+
setSelection({
|
|
1148
|
+
kind: 'transformStep',
|
|
1149
|
+
edgeId: edge.id,
|
|
1150
|
+
stepIndex: (next.transformIds?.length ?? 1) - 1,
|
|
1151
|
+
});
|
|
1152
|
+
}}
|
|
1153
|
+
/>
|
|
1154
|
+
) : null}
|
|
1155
|
+
{listContext ? (
|
|
1156
|
+
<IconButton
|
|
1157
|
+
compact
|
|
1158
|
+
type="button"
|
|
1159
|
+
data-testid={`field-remap-edit-items-${edge.id}`}
|
|
1160
|
+
icon="codicon-edit"
|
|
1161
|
+
label={chromeLabels.editItems}
|
|
1162
|
+
onClick={() => {
|
|
1163
|
+
if (!edge.itemEdges) {
|
|
1164
|
+
onEdgesChange(
|
|
1165
|
+
edges.map((item) =>
|
|
1166
|
+
item.id === edge.id ? enableListContextOnEdge(item) : item,
|
|
1167
|
+
),
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
setSelection({ kind: 'edge', edgeId: edge.id });
|
|
1171
|
+
}}
|
|
1172
|
+
/>
|
|
1173
|
+
) : null}
|
|
1174
|
+
<IconButton
|
|
1018
1175
|
compact
|
|
1019
1176
|
type="button"
|
|
1020
|
-
data-testid={`field-remap-
|
|
1177
|
+
data-testid={`field-remap-remove-edge-${edge.id}`}
|
|
1178
|
+
icon="codicon-trash"
|
|
1179
|
+
label={chromeLabels.removeBinding}
|
|
1180
|
+
variant="danger"
|
|
1021
1181
|
onClick={() => {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1182
|
+
onEdgesChange(edges.filter((item) => item.id !== edge.id));
|
|
1183
|
+
if (
|
|
1184
|
+
selection &&
|
|
1185
|
+
(selection.kind === 'edge' || selection.kind === 'transformStep') &&
|
|
1186
|
+
selection.edgeId === edge.id
|
|
1187
|
+
) {
|
|
1188
|
+
setSelection(null);
|
|
1028
1189
|
}
|
|
1029
|
-
setSelection({ kind: 'edge', edgeId: edge.id });
|
|
1030
1190
|
}}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
onEdgesChange(edges.filter((item) => item.id !== edge.id));
|
|
1040
|
-
if (
|
|
1041
|
-
selection &&
|
|
1042
|
-
(selection.kind === 'edge' || selection.kind === 'transformStep') &&
|
|
1043
|
-
selection.edgeId === edge.id
|
|
1044
|
-
) {
|
|
1045
|
-
setSelection(null);
|
|
1046
|
-
}
|
|
1047
|
-
}}
|
|
1048
|
-
>
|
|
1049
|
-
Remove
|
|
1050
|
-
</Button>
|
|
1051
|
-
</span>
|
|
1052
|
-
</li>
|
|
1053
|
-
);
|
|
1054
|
-
})}
|
|
1055
|
-
</ul>
|
|
1056
|
-
</div>
|
|
1191
|
+
/>
|
|
1192
|
+
</span>
|
|
1193
|
+
</li>
|
|
1194
|
+
);
|
|
1195
|
+
})}
|
|
1196
|
+
</ul>
|
|
1197
|
+
</div>
|
|
1198
|
+
) : null}
|
|
1057
1199
|
</div>
|
|
1058
1200
|
);
|
|
1059
1201
|
}
|
|
@@ -83,6 +83,13 @@ export interface FieldRemapPanelProps {
|
|
|
83
83
|
readonly targetShape?: unknown;
|
|
84
84
|
/** Forwarded to {@link FieldRemapFlowMapper} (default true). */
|
|
85
85
|
readonly showMinimap?: boolean | undefined;
|
|
86
|
+
/** Forwarded Flow chrome preset. `embed` hides the hint and binding list by default. */
|
|
87
|
+
readonly chrome?: FieldRemapFlowMapperProps['chrome'];
|
|
88
|
+
/** Explicit Flow chrome overrides take precedence over {@link FieldRemapPanelProps.chrome}. */
|
|
89
|
+
readonly showFlowHint?: FieldRemapFlowMapperProps['showFlowHint'];
|
|
90
|
+
readonly showBindingsList?: FieldRemapFlowMapperProps['showBindingsList'];
|
|
91
|
+
readonly showConvertPalette?: FieldRemapFlowMapperProps['showConvertPalette'];
|
|
92
|
+
readonly emptyDetail?: FieldRemapFlowMapperProps['emptyDetail'];
|
|
86
93
|
/** Forwarded to {@link FieldRemapFlowMapper} Controls MiniMap toggle. */
|
|
87
94
|
readonly onShowMinimapChange?: FieldRemapFlowMapperProps['onShowMinimapChange'];
|
|
88
95
|
readonly onPaneContextMenu?: FieldRemapFlowMapperProps['onPaneContextMenu'];
|
|
@@ -138,6 +145,11 @@ export function FieldRemapPanel({
|
|
|
138
145
|
sourceSample: sourceSampleProp,
|
|
139
146
|
targetShape: targetShapeProp,
|
|
140
147
|
showMinimap,
|
|
148
|
+
chrome,
|
|
149
|
+
showFlowHint,
|
|
150
|
+
showBindingsList,
|
|
151
|
+
showConvertPalette,
|
|
152
|
+
emptyDetail,
|
|
141
153
|
onShowMinimapChange,
|
|
142
154
|
onPaneContextMenu,
|
|
143
155
|
onNodeContextMenu,
|
|
@@ -420,6 +432,11 @@ export function FieldRemapPanel({
|
|
|
420
432
|
sourceTitle={sample.sourceLabel}
|
|
421
433
|
targetTitle={sample.targetLabel}
|
|
422
434
|
showMinimap={showMinimap}
|
|
435
|
+
chrome={chrome}
|
|
436
|
+
showFlowHint={showFlowHint}
|
|
437
|
+
showBindingsList={showBindingsList}
|
|
438
|
+
showConvertPalette={showConvertPalette}
|
|
439
|
+
emptyDetail={emptyDetail}
|
|
423
440
|
onShowMinimapChange={onShowMinimapChange}
|
|
424
441
|
includeHidden={includeHidden}
|
|
425
442
|
onIncludeHiddenChange={setIncludeHidden}
|
package/src/field-remap/view.css
CHANGED
|
@@ -301,6 +301,8 @@
|
|
|
301
301
|
display: flex;
|
|
302
302
|
flex-direction: column;
|
|
303
303
|
gap: 0.75rem;
|
|
304
|
+
container-name: field-remap-flow;
|
|
305
|
+
container-type: inline-size;
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
.workbench-field-remap-flow__workspace {
|
|
@@ -311,7 +313,74 @@
|
|
|
311
313
|
align-items: stretch;
|
|
312
314
|
}
|
|
313
315
|
|
|
314
|
-
|
|
316
|
+
.workbench-field-remap-flow__workspace--without-palette {
|
|
317
|
+
grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.workbench-field-remap-flow__workspace--split {
|
|
321
|
+
display: flex;
|
|
322
|
+
height: min(40rem, 70vh);
|
|
323
|
+
min-height: 26rem;
|
|
324
|
+
gap: 0;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.workbench-field-remap-flow__workspace--split > .ui-workbench-split-view,
|
|
328
|
+
.workbench-field-remap-flow__workspace--split
|
|
329
|
+
.ui-workbench-split-view__secondary
|
|
330
|
+
> .ui-workbench-split-view {
|
|
331
|
+
width: 100%;
|
|
332
|
+
height: 100%;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.workbench-field-remap-flow__workspace--split .workbench-field-remap-flow__canvas {
|
|
336
|
+
height: auto;
|
|
337
|
+
min-height: 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Embed hosts own the outer pane. Keep Flow rails flat and separate them with dividers only. */
|
|
341
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-flow__workspace {
|
|
342
|
+
gap: 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-palette,
|
|
346
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-flow__canvas,
|
|
347
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-detail,
|
|
348
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-note {
|
|
349
|
+
border-radius: 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-palette {
|
|
353
|
+
border: 0;
|
|
354
|
+
border-inline-end: 1px solid var(--vscode-panel-border, var(--color-border));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-flow__canvas {
|
|
358
|
+
border: 0;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-detail,
|
|
362
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-note {
|
|
363
|
+
border: 0;
|
|
364
|
+
border-inline-start: 1px solid var(--vscode-panel-border, var(--color-border));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* SplitView supplies the shared rail divider in embed mode, avoiding a doubled border. */
|
|
368
|
+
.workbench-field-remap-flow[data-chrome='embed']
|
|
369
|
+
.workbench-field-remap-flow__workspace--split
|
|
370
|
+
.workbench-field-remap-convert-palette,
|
|
371
|
+
.workbench-field-remap-flow[data-chrome='embed']
|
|
372
|
+
.workbench-field-remap-flow__workspace--split
|
|
373
|
+
.workbench-field-remap-flow__canvas,
|
|
374
|
+
.workbench-field-remap-flow[data-chrome='embed']
|
|
375
|
+
.workbench-field-remap-flow__workspace--split
|
|
376
|
+
.workbench-field-remap-detail,
|
|
377
|
+
.workbench-field-remap-flow[data-chrome='embed']
|
|
378
|
+
.workbench-field-remap-flow__workspace--split
|
|
379
|
+
.workbench-field-remap-convert-note {
|
|
380
|
+
border: 0;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@container field-remap-flow (max-width: 68.75rem) {
|
|
315
384
|
.workbench-field-remap-flow__workspace {
|
|
316
385
|
grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
|
|
317
386
|
}
|
|
@@ -319,12 +388,23 @@
|
|
|
319
388
|
.workbench-field-remap-convert-palette {
|
|
320
389
|
grid-column: 1 / -1;
|
|
321
390
|
}
|
|
391
|
+
|
|
392
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-palette {
|
|
393
|
+
border-inline-end: 0;
|
|
394
|
+
border-block-end: 1px solid var(--vscode-panel-border, var(--color-border));
|
|
395
|
+
}
|
|
322
396
|
}
|
|
323
397
|
|
|
324
|
-
@
|
|
398
|
+
@container field-remap-flow (max-width: 60rem) {
|
|
325
399
|
.workbench-field-remap-flow__workspace {
|
|
326
400
|
grid-template-columns: 1fr;
|
|
327
401
|
}
|
|
402
|
+
|
|
403
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-detail,
|
|
404
|
+
.workbench-field-remap-flow[data-chrome='embed'] .workbench-field-remap-convert-note {
|
|
405
|
+
border-inline-start: 0;
|
|
406
|
+
border-block-start: 1px solid var(--vscode-panel-border, var(--color-border));
|
|
407
|
+
}
|
|
328
408
|
}
|
|
329
409
|
|
|
330
410
|
.workbench-field-remap-convert-palette {
|