@adatechnology/conversations-ui 0.1.0-rc.40 → 0.1.0-rc.41
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/flows/index.js
CHANGED
|
@@ -1869,6 +1869,9 @@ var CHAIN_FRAME_PADDING = 36;
|
|
|
1869
1869
|
var QUICK_ADD_COLUMN_GAP = 320;
|
|
1870
1870
|
var FLOW_KEY_PATTERN = /^[a-z0-9_]{2,40}$/;
|
|
1871
1871
|
var EDGE_COLOR_LINEAR = "#94a3b8";
|
|
1872
|
+
var FOCUS_MAX_ZOOM = 1;
|
|
1873
|
+
var FOCUS_PADDING = 0.2;
|
|
1874
|
+
var FOCUS_DURATION_MS = 400;
|
|
1872
1875
|
var EDGE_COLOR_BRANCH = "#8b5cf6";
|
|
1873
1876
|
var EDGE_COLOR_FALLBACK = "#cbd5e1";
|
|
1874
1877
|
var EDGE_COLOR_LIVE = "#3b82f6";
|
|
@@ -1937,6 +1940,7 @@ function FlowsWorkspace({
|
|
|
1937
1940
|
const [rfNodes, setRfNodes] = useState6([]);
|
|
1938
1941
|
const [flowInstance, setFlowInstance] = useState6(null);
|
|
1939
1942
|
const [pendingFocusNodeId, setPendingFocusNodeId] = useState6(null);
|
|
1943
|
+
const [pendingFocusFlowKey, setPendingFocusFlowKey] = useState6(null);
|
|
1940
1944
|
const reloadGraphs = useCallback(async () => {
|
|
1941
1945
|
try {
|
|
1942
1946
|
const loaded = await api.getGraphs();
|
|
@@ -2030,6 +2034,7 @@ function FlowsWorkspace({
|
|
|
2030
2034
|
if (others.some(isFlowDirty) && !window.confirm(labels.workspace.unsavedChangesConfirm)) return;
|
|
2031
2035
|
setOpenFlowKeys(graphs ? mergedFlowKeysFrom(key, graphs) : [key]);
|
|
2032
2036
|
if (editingRef && editingRef.flowKey !== key) setEditingRef(null);
|
|
2037
|
+
setPendingFocusFlowKey(key);
|
|
2033
2038
|
},
|
|
2034
2039
|
[openFlowKeys, isFlowDirty, editingRef, graphs, labels]
|
|
2035
2040
|
);
|
|
@@ -2222,6 +2227,18 @@ function FlowsWorkspace({
|
|
|
2222
2227
|
flowInstance.setCenter(target.position.x + NODE_CARD_WIDTH / 2, target.position.y, { zoom: 1, duration: 400 });
|
|
2223
2228
|
setPendingFocusNodeId(null);
|
|
2224
2229
|
}, [pendingFocusNodeId, flowInstance, rfNodes]);
|
|
2230
|
+
useEffect3(() => {
|
|
2231
|
+
if (!pendingFocusFlowKey || !flowInstance) return;
|
|
2232
|
+
const flowNodes = rfNodes.filter((node) => parseNamespacedId(node.id).flowKey === pendingFocusFlowKey);
|
|
2233
|
+
if (flowNodes.length === 0) return;
|
|
2234
|
+
void flowInstance.fitView({
|
|
2235
|
+
nodes: flowNodes.map((node) => ({ id: node.id })),
|
|
2236
|
+
maxZoom: FOCUS_MAX_ZOOM,
|
|
2237
|
+
padding: FOCUS_PADDING,
|
|
2238
|
+
duration: FOCUS_DURATION_MS
|
|
2239
|
+
});
|
|
2240
|
+
setPendingFocusFlowKey(null);
|
|
2241
|
+
}, [pendingFocusFlowKey, flowInstance, rfNodes]);
|
|
2225
2242
|
const onNodesChange = useCallback((changes) => {
|
|
2226
2243
|
setRfNodes((current) => applyNodeChanges(changes, current));
|
|
2227
2244
|
}, []);
|
package/package.json
CHANGED
|
@@ -98,6 +98,11 @@ const QUICK_ADD_COLUMN_GAP = 320
|
|
|
98
98
|
const FLOW_KEY_PATTERN = /^[a-z0-9_]{2,40}$/
|
|
99
99
|
|
|
100
100
|
const EDGE_COLOR_LINEAR = '#94a3b8'
|
|
101
|
+
|
|
102
|
+
/** Enquadramento ao focar um fluxo pela aba. */
|
|
103
|
+
const FOCUS_MAX_ZOOM = 1
|
|
104
|
+
const FOCUS_PADDING = 0.2
|
|
105
|
+
const FOCUS_DURATION_MS = 400
|
|
101
106
|
const EDGE_COLOR_BRANCH = '#8b5cf6'
|
|
102
107
|
const EDGE_COLOR_FALLBACK = '#cbd5e1'
|
|
103
108
|
const EDGE_COLOR_LIVE = '#3b82f6'
|
|
@@ -262,6 +267,7 @@ export function FlowsWorkspace({
|
|
|
262
267
|
const [rfNodes, setRfNodes] = useState<Node[]>([])
|
|
263
268
|
const [flowInstance, setFlowInstance] = useState<ReactFlowInstance | null>(null)
|
|
264
269
|
const [pendingFocusNodeId, setPendingFocusNodeId] = useState<string | null>(null)
|
|
270
|
+
const [pendingFocusFlowKey, setPendingFocusFlowKey] = useState<string | null>(null)
|
|
265
271
|
|
|
266
272
|
const reloadGraphs = useCallback(async () => {
|
|
267
273
|
try {
|
|
@@ -379,6 +385,10 @@ export function FlowsWorkspace({
|
|
|
379
385
|
if (others.some(isFlowDirty) && !window.confirm(labels.workspace.unsavedChangesConfirm)) return
|
|
380
386
|
setOpenFlowKeys(graphs ? mergedFlowKeysFrom(key, graphs) : [key])
|
|
381
387
|
if (editingRef && editingRef.flowKey !== key) setEditingRef(null)
|
|
388
|
+
// Trocar o fluxo primário não movia a câmera: a aba acendia, o canvas continuava onde
|
|
389
|
+
// estava e o fluxo escolhido ficava fora da tela — clicar em "Consórcio" parecia não fazer
|
|
390
|
+
// nada. O enquadramento espera os cards existirem (ver o efeito abaixo).
|
|
391
|
+
setPendingFocusFlowKey(key)
|
|
382
392
|
},
|
|
383
393
|
[openFlowKeys, isFlowDirty, editingRef, graphs, labels],
|
|
384
394
|
)
|
|
@@ -637,6 +647,22 @@ export function FlowsWorkspace({
|
|
|
637
647
|
setPendingFocusNodeId(null)
|
|
638
648
|
}, [pendingFocusNodeId, flowInstance, rfNodes])
|
|
639
649
|
|
|
650
|
+
// Enquadra o fluxo recém-focado. `fitView` restrito aos cards DELE, e não o `fitView` geral:
|
|
651
|
+
// o canvas mostra o fecho transitivo inteiro, e enquadrar tudo devolveria a mesma visão de
|
|
652
|
+
// sempre. `maxZoom` evita que um fluxo de dois nós encha a tela.
|
|
653
|
+
useEffect(() => {
|
|
654
|
+
if (!pendingFocusFlowKey || !flowInstance) return
|
|
655
|
+
const flowNodes = rfNodes.filter((node) => parseNamespacedId(node.id).flowKey === pendingFocusFlowKey)
|
|
656
|
+
if (flowNodes.length === 0) return
|
|
657
|
+
void flowInstance.fitView({
|
|
658
|
+
nodes: flowNodes.map((node) => ({ id: node.id })),
|
|
659
|
+
maxZoom: FOCUS_MAX_ZOOM,
|
|
660
|
+
padding: FOCUS_PADDING,
|
|
661
|
+
duration: FOCUS_DURATION_MS,
|
|
662
|
+
})
|
|
663
|
+
setPendingFocusFlowKey(null)
|
|
664
|
+
}, [pendingFocusFlowKey, flowInstance, rfNodes])
|
|
665
|
+
|
|
640
666
|
const onNodesChange = useCallback((changes: NodeChange[]) => {
|
|
641
667
|
setRfNodes((current) => applyNodeChanges(changes, current))
|
|
642
668
|
}, [])
|
|
@@ -93,3 +93,34 @@ describe('contrato de customização', () => {
|
|
|
93
93
|
}
|
|
94
94
|
})
|
|
95
95
|
})
|
|
96
|
+
|
|
97
|
+
describe('focar um fluxo leva a câmera até ele', () => {
|
|
98
|
+
/**
|
|
99
|
+
* `focusFlow` trocava o fluxo primário e remesclava o canvas, mas nunca movia a viewport: a aba
|
|
100
|
+
* acendia, a tela continuava onde estava e o fluxo escolhido ficava fora do campo de visão — em
|
|
101
|
+
* "Consórcio", parado no início com o fluxo lá embaixo, clicar parecia não fazer nada.
|
|
102
|
+
*
|
|
103
|
+
* Teste de fonte, como os demais deste arquivo: não prova o enquadramento na tela, prova que o
|
|
104
|
+
* clique pede o enquadramento e que ele é restrito ao fluxo clicado.
|
|
105
|
+
*/
|
|
106
|
+
it('focar um fluxo agenda o enquadramento dele', async () => {
|
|
107
|
+
const content = await Bun.file(WORKSPACE_SOURCE).text()
|
|
108
|
+
|
|
109
|
+
expect(content).toContain('setPendingFocusFlowKey(key)')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('enquadra apenas os cards do fluxo focado, não o canvas inteiro', async () => {
|
|
113
|
+
// O canvas mostra o fecho transitivo inteiro. Um `fitView()` sem `nodes` devolveria a mesma
|
|
114
|
+
// visão de sempre — que é exatamente o defeito relatado.
|
|
115
|
+
const content = await Bun.file(WORKSPACE_SOURCE).text()
|
|
116
|
+
|
|
117
|
+
expect(content).toMatch(/fitView\(\{[\s\S]*?nodes: flowNodes\.map/)
|
|
118
|
+
expect(content).toMatch(/flowKey === pendingFocusFlowKey/)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('limita o zoom, para um fluxo de dois nós não encher a tela', async () => {
|
|
122
|
+
const content = await Bun.file(WORKSPACE_SOURCE).text()
|
|
123
|
+
|
|
124
|
+
expect(content).toContain('maxZoom: FOCUS_MAX_ZOOM')
|
|
125
|
+
})
|
|
126
|
+
})
|