@juspay/svelte-ui-components 2.75.0 → 2.76.1

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.
@@ -28,7 +28,10 @@
28
28
  testId,
29
29
  classes,
30
30
  columnLabels,
31
- nodeColorResolver
31
+ nodeColorResolver,
32
+ minLinkWidth = 1,
33
+ dataLabelOffsetX = 0,
34
+ disableDimOnHover = false
32
35
  }: SankeyChartProperties = $props();
33
36
 
34
37
  // ── State ──────────────────────────────────────────────────────
@@ -54,7 +57,8 @@
54
57
  Math.max(0, chartHeight - MARGIN * 2),
55
58
  nodeWidth,
56
59
  nodePadding,
57
- iterations
60
+ iterations,
61
+ minLinkWidth
58
62
  )
59
63
  );
60
64
 
@@ -98,6 +102,9 @@
98
102
  };
99
103
 
100
104
  let connectedNodes = $derived.by(() => {
105
+ if (disableDimOnHover) {
106
+ return null;
107
+ }
101
108
  if (hoveredNode !== null) {
102
109
  const connected = new SvelteSet<string>([hoveredNode]);
103
110
  for (const l of links) {
@@ -285,7 +292,8 @@
285
292
 
286
293
  {#each layout.links as link, i (i)}
287
294
  {@const highlighted = isLinkHighlighted(link.source, link.target)}
288
- {@const dimmed = (hoveredNode !== null || hoveredLink !== null) && !highlighted}
295
+ {@const dimmed =
296
+ !disableDimOnHover && (hoveredNode !== null || hoveredLink !== null) && !highlighted}
289
297
  <!-- svelte-ignore a11y_no_static_element_interactions -->
290
298
  <!-- svelte-ignore a11y_click_events_have_key_events -->
291
299
  <path
@@ -293,7 +301,7 @@
293
301
  d={link.path}
294
302
  fill="none"
295
303
  stroke={link.color ?? nodeColorMap.get(link.source) ?? getColor(0)}
296
- stroke-width={Math.max(1, link.width)}
304
+ stroke-width={Math.max(minLinkWidth, link.width)}
297
305
  stroke-opacity={highlighted ? 0.7 : dimmed ? 0.08 : 0.4}
298
306
  onmouseenter={(e) => handleLinkEnter(e, link.source, link.target)}
299
307
  onmousemove={trackMouse}
@@ -326,7 +334,9 @@
326
334
  <text
327
335
  class="sankey-label"
328
336
  class:node-dimmed={dimmed}
329
- x={node.column === 0 ? node.x - 6 : node.x + node.width + 6}
337
+ x={node.column === 0
338
+ ? node.x - 6 - dataLabelOffsetX
339
+ : node.x + node.width + 6 + dataLabelOffsetX}
330
340
  y={node.y + node.height / 2}
331
341
  text-anchor={node.column === 0 ? 'end' : 'start'}
332
342
  dominant-baseline="middle"
@@ -57,6 +57,25 @@ export type OptionalSankeyChartProperties = {
57
57
  * through to the default palette colour.
58
58
  */
59
59
  nodeColorResolver?: (id: string, label: string | null) => string | null;
60
+ /**
61
+ * Minimum rendered thickness (px) for any link or node bar. Tiny flows that would otherwise
62
+ * collapse to sub-pixel widths remain at this thickness so they stay visually discoverable.
63
+ * Defaults to `1`. Lighthouse uses `2` for dense payment-flow diagrams.
64
+ */
65
+ minLinkWidth?: number;
66
+ /**
67
+ * Horizontal offset in pixels applied to every node data-label, relative to the default
68
+ * position (left of first-column nodes, right of all other nodes). Positive values push
69
+ * the label further away from the node; negative values pull it closer. Lighthouse uses
70
+ * `30` to create breathing room between the node bar and its label.
71
+ */
72
+ dataLabelOffsetX?: number;
73
+ /**
74
+ * When `true`, hovering a node does **not** dim unrelated nodes — all nodes and links
75
+ * remain at full opacity. Useful for dense diagrams where the dimming effect makes it hard
76
+ * to read the overall structure. Defaults to `false` (standard dim-on-hover behaviour).
77
+ */
78
+ disableDimOnHover?: boolean;
60
79
  };
61
80
  export type SankeyChartEventProperties = {
62
81
  onnodeclick?: (event: {
@@ -14,7 +14,7 @@ export declare function computeSankeyLayout(nodes: Array<{
14
14
  target: string;
15
15
  value: number;
16
16
  color?: string;
17
- }>, width: number, height: number, nodeWidth?: number, nodePadding?: number, iterations?: number): {
17
+ }>, width: number, height: number, nodeWidth?: number, nodePadding?: number, iterations?: number, minLinkWidth?: number): {
18
18
  nodes: ComputedSankeyNode[];
19
19
  links: ComputedSankeyLink[];
20
20
  };
@@ -42,7 +42,7 @@ export function computePieLayout(data, startAngle = -Math.PI / 2, padAngle = 0)
42
42
  return slices;
43
43
  }
44
44
  // ── Sankey layout ───────────────────────────────────────────────
45
- export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16, nodePadding = 8, iterations = 6) {
45
+ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16, nodePadding = 8, iterations = 6, minLinkWidth = 1) {
46
46
  if (nodes.length === 0) {
47
47
  return { nodes: [], links: [] };
48
48
  }
@@ -104,9 +104,10 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
104
104
  for (const id of ids) {
105
105
  const val = nodeValues.get(id) ?? 0;
106
106
  const h = totalValue > 0 ? (val / totalValue) * availableHeight : availableHeight / ids.length;
107
+ const renderedH = Math.max(minLinkWidth, h);
107
108
  nodeY.set(id, y);
108
- nodeH.set(id, Math.max(1, h));
109
- y += h + nodePadding;
109
+ nodeH.set(id, renderedH);
110
+ y += renderedH + nodePadding;
110
111
  }
111
112
  }
112
113
  // Iterative relaxation (upstream pass)
@@ -160,7 +161,7 @@ export function computeSankeyLayout(nodes, links, width, height, nodeWidth = 16,
160
161
  const targetNode = nodeById.get(l.target);
161
162
  const sVal = nodeValues.get(l.source) ?? 1;
162
163
  const sourceH = nodeH.get(l.source) ?? 0;
163
- const linkWidth = Math.max(1, (l.value / Math.max(sVal, 1)) * sourceH);
164
+ const linkWidth = Math.max(minLinkWidth, (l.value / Math.max(sVal, 1)) * sourceH);
164
165
  const sx = (sourceNode?.x ?? 0) + nodeWidth;
165
166
  const sy = (sourceOffsets.get(l.source) ?? 0) + linkWidth / 2;
166
167
  const tx = targetNode?.x ?? 0;
@@ -0,0 +1,15 @@
1
+ export type ChartHighlightType = 'bar-chart' | 'line-chart' | 'donut-chart';
2
+ /**
3
+ * The imperative interface a chart hands back through `onChartReady`, so an
4
+ * external orchestrator (e.g. voice narration sync) can drive point highlighting
5
+ * without knowing the chart's internal rendering. Replaces the legacy pattern of
6
+ * reaching into a charting-library instance stored on the DOM node.
7
+ */
8
+ export type ChartHighlightAPI = {
9
+ /** Highlight the data point at this zero-based index; pass `null` to clear. */
10
+ highlight: (index: number | null) => void;
11
+ /** The ordered category labels for this chart, for name-based lookup. */
12
+ getCategories: () => string[];
13
+ /** The chart kind, for consumers maintaining a registry of charts. */
14
+ type: ChartHighlightType;
15
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -68,6 +68,9 @@ export { default as PieChart } from './PieChart/PieChart.svelte';
68
68
  export { default as SankeyChart } from './SankeyChart/SankeyChart.svelte';
69
69
  export { default as LottiePlayer } from './LottiePlayer/LottiePlayer.svelte';
70
70
  export { default as StatCard } from './StatCard/StatCard.svelte';
71
+ export { default as DeltaIndicator } from './DeltaIndicator/DeltaIndicator.svelte';
72
+ export { default as DualAxisBarChart } from './DualAxisBarChart/DualAxisBarChart.svelte';
73
+ export { default as FunnelChart } from './FunnelChart/FunnelChart.svelte';
71
74
  export type * from './Button/properties';
72
75
  export type * from './Modal/properties';
73
76
  export type * from './Input/properties';
@@ -132,5 +135,9 @@ export type * from './PieChart/properties';
132
135
  export type * from './SankeyChart/properties';
133
136
  export type * from './LottiePlayer/properties';
134
137
  export type * from './StatCard/properties';
138
+ export type * from './DeltaIndicator/properties';
139
+ export type * from './DualAxisBarChart/properties';
140
+ export type * from './FunnelChart/properties';
141
+ export type * from './_chart/highlight';
135
142
  export { validateInput } from './utils';
136
143
  export { formatNumberIndian } from './_chart/format';
package/dist/index.js CHANGED
@@ -68,5 +68,8 @@ export { default as PieChart } from './PieChart/PieChart.svelte';
68
68
  export { default as SankeyChart } from './SankeyChart/SankeyChart.svelte';
69
69
  export { default as LottiePlayer } from './LottiePlayer/LottiePlayer.svelte';
70
70
  export { default as StatCard } from './StatCard/StatCard.svelte';
71
+ export { default as DeltaIndicator } from './DeltaIndicator/DeltaIndicator.svelte';
72
+ export { default as DualAxisBarChart } from './DualAxisBarChart/DualAxisBarChart.svelte';
73
+ export { default as FunnelChart } from './FunnelChart/FunnelChart.svelte';
71
74
  export { validateInput } from './utils';
72
75
  export { formatNumberIndian } from './_chart/format';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "2.75.0",
3
+ "version": "2.76.1",
4
4
  "description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
5
5
  "keywords": [
6
6
  "svelte",