@picked/svelte 0.0.54-next.3 → 0.0.54-next.4
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.
|
@@ -85,10 +85,8 @@
|
|
|
85
85
|
fields.push({ label: 'Step Key', value: step.key })
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (stepName) {
|
|
91
|
-
fields.push({ label: 'Step Name', value: stepName })
|
|
88
|
+
if ('name' in step && step.name) {
|
|
89
|
+
fields.push({ label: 'Step Name', value: step.name })
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
return fields
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/** @file D3-based tree visualization of an experience's node graph in the devtools panel. */
|
|
3
|
+
import { onDestroy } from 'svelte'
|
|
3
4
|
import * as d3 from 'd3'
|
|
4
5
|
import type { ExperienceEdge, ExperienceNode, ExperienceStore } from '@picked/client'
|
|
5
6
|
import { Badge, Button, Spinner, Stack, Text, VisualizationContainer } from '../../ui'
|
|
@@ -16,6 +17,12 @@
|
|
|
16
17
|
const loading = false
|
|
17
18
|
|
|
18
19
|
let treeRenderingDone = false
|
|
20
|
+
let tooltipEl: d3.Selection<HTMLDivElement, unknown, null, undefined> | null = null
|
|
21
|
+
|
|
22
|
+
onDestroy(() => {
|
|
23
|
+
tooltipEl?.remove()
|
|
24
|
+
tooltipEl = null
|
|
25
|
+
})
|
|
19
26
|
|
|
20
27
|
const tree = experience.treeStore
|
|
21
28
|
|
|
@@ -23,11 +30,13 @@
|
|
|
23
30
|
$: edges = $tree.edges
|
|
24
31
|
$: conditions = $tree.conditions
|
|
25
32
|
|
|
33
|
+
|
|
26
34
|
let zoomBehavior: d3.ZoomBehavior<SVGSVGElement, unknown>
|
|
27
35
|
|
|
28
36
|
interface ProcessedNode {
|
|
29
37
|
id: string
|
|
30
38
|
name: string
|
|
39
|
+
tooltip?: string
|
|
31
40
|
type: string
|
|
32
41
|
children: ProcessedNode[]
|
|
33
42
|
_originalNode: ExperienceNode
|
|
@@ -137,25 +146,32 @@
|
|
|
137
146
|
|
|
138
147
|
const getNodeLabel = (node: ExperienceNode): string => {
|
|
139
148
|
if (node.type === 'origin') return 'Start'
|
|
140
|
-
if (node.type === 'step')
|
|
141
|
-
|
|
149
|
+
if (node.type === 'step') return node.name ?? 'Unknown Step'
|
|
150
|
+
|
|
142
151
|
if (node.type === 'condition') {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
if (conditionItem?.name) return conditionItem.name
|
|
146
|
-
if (conditionItem?.logic) return formatLogicRule(conditionItem.logic)
|
|
147
|
-
return 'Condition'
|
|
152
|
+
const conditionItem = node.conditionId ? conditionsMap.get(node.conditionId) : undefined
|
|
153
|
+
return conditionItem?.name ?? 'Condition'
|
|
148
154
|
}
|
|
149
155
|
|
|
156
|
+
if (node.type === 'action') return node.name ?? node.actionKey ?? 'Action'
|
|
157
|
+
|
|
150
158
|
return 'Unknown Node'
|
|
151
159
|
}
|
|
152
160
|
|
|
161
|
+
const getNodeTooltip = (node: ExperienceNode): string | undefined => {
|
|
162
|
+
if (node.type !== 'condition') return undefined
|
|
163
|
+
const conditionItem = node.conditionId ? conditionsMap.get(node.conditionId) : undefined
|
|
164
|
+
if (conditionItem?.logic) return formatLogicRule(conditionItem.logic)
|
|
165
|
+
return undefined
|
|
166
|
+
}
|
|
167
|
+
|
|
153
168
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- D3 visualization runs imperatively outside Svelte reactivity
|
|
154
169
|
const processedNodes = new Map<string, ProcessedNode>()
|
|
155
170
|
nodes.forEach((n) => {
|
|
156
171
|
processedNodes.set(n.id, {
|
|
157
172
|
id: n.id,
|
|
158
173
|
name: getNodeLabel(n),
|
|
174
|
+
tooltip: getNodeTooltip(n),
|
|
159
175
|
type: n.type,
|
|
160
176
|
children: [],
|
|
161
177
|
_originalNode: n,
|
|
@@ -302,20 +318,58 @@
|
|
|
302
318
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
|
303
319
|
.attr('transform', (d: any) => `translate(${d.y},${d.x})`)
|
|
304
320
|
|
|
305
|
-
nodesSelection
|
|
321
|
+
const circles = nodesSelection
|
|
306
322
|
.append('circle')
|
|
307
323
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
|
308
324
|
.attr('r', (d: any) => (d.data.type === 'origin' ? 15 : 10))
|
|
309
325
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
|
310
326
|
.attr('fill', (d: any) => {
|
|
311
327
|
if (d.data._isReference) return '#38bdf8'
|
|
312
|
-
if (d.data.type === 'origin') return '#
|
|
328
|
+
if (d.data.type === 'origin') return '#6b7280'
|
|
313
329
|
if (d.data.type === 'condition') return '#f59e0b'
|
|
314
|
-
return '#
|
|
330
|
+
if (d.data.type === 'action') return '#22c55e'
|
|
331
|
+
return '#3b82f6'
|
|
315
332
|
})
|
|
316
333
|
.attr('stroke', '#fff')
|
|
317
334
|
.attr('stroke-width', 2)
|
|
318
335
|
|
|
336
|
+
tooltipEl?.remove()
|
|
337
|
+
tooltipEl = d3
|
|
338
|
+
.select(svgEl.parentElement)
|
|
339
|
+
.append('div')
|
|
340
|
+
|
|
341
|
+
const tooltip = tooltipEl
|
|
342
|
+
.style('position', 'absolute')
|
|
343
|
+
.style('pointer-events', 'none')
|
|
344
|
+
.style('background', '#1e293b')
|
|
345
|
+
.style('color', '#f8fafc')
|
|
346
|
+
.style('padding', '6px 10px')
|
|
347
|
+
.style('border-radius', '6px')
|
|
348
|
+
.style('font-size', '11px')
|
|
349
|
+
.style('max-width', '260px')
|
|
350
|
+
.style('white-space', 'pre-wrap')
|
|
351
|
+
.style('opacity', '0')
|
|
352
|
+
.style('z-index', '10')
|
|
353
|
+
|
|
354
|
+
circles
|
|
355
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
|
356
|
+
.filter((d: any) => d.data.tooltip)
|
|
357
|
+
.style('cursor', 'default')
|
|
358
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
|
359
|
+
.on('mouseenter', function showTooltip(event: MouseEvent, d: any) {
|
|
360
|
+
const container = svgEl.parentElement
|
|
361
|
+
if (!container || !d.data.tooltip) return
|
|
362
|
+
const rect = container.getBoundingClientRect()
|
|
363
|
+
tooltip
|
|
364
|
+
.text(d.data.tooltip)
|
|
365
|
+
.style('left', `${event.clientX - rect.left + 12}px`)
|
|
366
|
+
.style('top', `${event.clientY - rect.top - 8}px`)
|
|
367
|
+
.style('opacity', '1')
|
|
368
|
+
})
|
|
369
|
+
.on('mouseleave', function hideTooltip() {
|
|
370
|
+
tooltip.style('opacity', '0')
|
|
371
|
+
})
|
|
372
|
+
|
|
319
373
|
nodesSelection
|
|
320
374
|
.append('text')
|
|
321
375
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- D3 callback types are untyped
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@picked/svelte",
|
|
3
|
-
"version": "0.0.54-next.
|
|
3
|
+
"version": "0.0.54-next.4",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"d3": "^7.9.0"
|
|
6
6
|
},
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
},
|
|
89
89
|
"module": "./dist/index.js",
|
|
90
90
|
"peerDependencies": {
|
|
91
|
-
"@picked/client": "0.0.54-next.
|
|
91
|
+
"@picked/client": "0.0.54-next.4",
|
|
92
92
|
"effector": "^23.3.0",
|
|
93
93
|
"svelte": "^5.46.4"
|
|
94
94
|
},
|