@stfrigerio/sito-template 0.1.21 → 0.1.22

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.
@@ -1 +1 @@
1
- {"version":3,"file":"SleepChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SleepChart/SleepChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAA;AAIzD,UAAU,SAAS;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,UAAU,eAAe;IACrB,SAAS,EAAE,SAAS,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAOD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAoQhD,CAAA"}
1
+ {"version":3,"file":"SleepChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SleepChart/SleepChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAA;AAIzD,UAAU,SAAS;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,UAAU,eAAe;IACrB,SAAS,EAAE,SAAS,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAOD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA6UhD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SunburstChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SunburstChart/SunburstChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAA;AAI7D,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,UAAU,kBAAkB;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAgCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkiBtD,CAAA"}
1
+ {"version":3,"file":"SunburstChart.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/charts/SunburstChart/SunburstChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAA;AAI7D,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,UAAU,kBAAkB;IACxB,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAgCD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4jBtD,CAAA"}
package/dist/index.esm.js CHANGED
@@ -2473,9 +2473,9 @@ const parseTimeToDecimal = (time) => {
2473
2473
  const [hours, minutes] = time.split(':').map(Number);
2474
2474
  return hours + minutes / 60;
2475
2475
  };
2476
- const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2476
+ const SleepChart = ({ sleepData, width = 800, height = 400, onDateClick }) => {
2477
2477
  const svgRef = useRef(null);
2478
- const margin = useMemo(() => ({ top: 20, right: 20, bottom: 40, left: 60 }), []);
2478
+ const margin = useMemo(() => ({ top: 30, right: 30, bottom: 50, left: 80 }), []);
2479
2479
  const chartWidth = width - margin.left - margin.right;
2480
2480
  const chartHeight = height - margin.top - margin.bottom;
2481
2481
  useEffect(() => {
@@ -2489,17 +2489,18 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2489
2489
  const tooltip = d3.select('body').append('div')
2490
2490
  .attr('class', 'sleep-chart-tooltip')
2491
2491
  .style('position', 'absolute')
2492
- .style('background', 'var(--bg-secondary)')
2493
- .style('color', 'var(--text-primary)')
2494
- .style('padding', '12px')
2495
- .style('border-radius', '8px')
2496
- .style('box-shadow', '0 4px 12px rgba(0,0,0,0.25)')
2497
- .style('border', '1px solid var(--border-primary)')
2492
+ .style('background', 'linear-gradient(135deg, rgba(155, 89, 182, 0.95), rgba(52, 152, 219, 0.95))')
2493
+ .style('color', '#ffffff')
2494
+ .style('padding', '16px')
2495
+ .style('border-radius', '12px')
2496
+ .style('box-shadow', '0 8px 24px rgba(0,0,0,0.3)')
2497
+ .style('border', '1px solid rgba(255,255,255,0.2)')
2498
2498
  .style('font-size', '14px')
2499
2499
  .style('pointer-events', 'none')
2500
2500
  .style('opacity', 0)
2501
2501
  .style('z-index', '1000')
2502
- .style('backdrop-filter', 'blur(8px)');
2502
+ .style('backdrop-filter', 'blur(12px)')
2503
+ .style('min-width', '180px');
2503
2504
  const xScale = d3.scaleLinear()
2504
2505
  .domain([18, 42])
2505
2506
  .range([0, chartWidth]);
@@ -2507,16 +2508,39 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2507
2508
  const yScale = d3.scaleBand()
2508
2509
  .domain(yDomain)
2509
2510
  .range([0, chartHeight])
2510
- .paddingInner(0.1)
2511
- .paddingOuter(0.05);
2511
+ .paddingInner(0.2)
2512
+ .paddingOuter(0.1);
2513
+ // Add vertical grid lines with midnight/noon highlights
2512
2514
  g.selectAll('.grid-line-x')
2513
- .data(d3.range(18, 43, 3))
2515
+ .data(d3.range(18, 43, 1))
2514
2516
  .enter().append('line')
2515
2517
  .attr('class', styles$4.gridLine)
2516
2518
  .attr('x1', d => xScale(d))
2517
2519
  .attr('y1', 0)
2518
2520
  .attr('x2', d => xScale(d))
2519
- .attr('y2', chartHeight);
2521
+ .attr('y2', chartHeight)
2522
+ .style('stroke', d => {
2523
+ const hour = d % 24;
2524
+ if (hour === 0)
2525
+ return 'var(--color-border)'; // Midnight
2526
+ if (hour === 12)
2527
+ return 'var(--color-border)'; // Noon
2528
+ return 'var(--color-border)';
2529
+ })
2530
+ .style('stroke-opacity', d => {
2531
+ const hour = d % 24;
2532
+ if (hour === 0 || hour === 12)
2533
+ return 0.3;
2534
+ if (hour % 3 === 0)
2535
+ return 0.15;
2536
+ return 0.05;
2537
+ })
2538
+ .style('stroke-width', d => {
2539
+ const hour = d % 24;
2540
+ if (hour === 0 || hour === 12)
2541
+ return 2;
2542
+ return 1;
2543
+ });
2520
2544
  sleepData.forEach((dayData) => {
2521
2545
  const yValue = yScale(dayData.date);
2522
2546
  if (yValue === undefined)
@@ -2554,37 +2578,60 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2554
2578
  }
2555
2579
  // Draw the bar only if both values exist
2556
2580
  if (sleepHour !== null && wakeHour !== null) {
2557
- sleepGroup.append('rect')
2581
+ const rect = sleepGroup.append('rect')
2558
2582
  .attr('x', xScale(sleepHour))
2559
2583
  .attr('y', yValue)
2560
- .attr('width', Math.max(0, xScale(wakeHour) - xScale(sleepHour)))
2584
+ .attr('width', 0) // Start with 0 width for animation
2561
2585
  .attr('height', barHeight)
2562
- .attr('rx', 4)
2586
+ .attr('rx', barHeight / 2)
2563
2587
  .attr('fill', 'url(#sleepGradient)')
2564
- .attr('opacity', 0.8)
2565
- .attr('stroke', 'none');
2588
+ .attr('opacity', 0) // Start invisible
2589
+ .attr('stroke', 'rgba(255,255,255,0.3)')
2590
+ .attr('stroke-width', 1)
2591
+ .style('filter', 'drop-shadow(0 2px 8px rgba(155, 89, 182, 0.3))');
2592
+ // Animate the bar
2593
+ rect.transition()
2594
+ .duration(800)
2595
+ .delay(Math.random() * 200) // Stagger the animations
2596
+ .ease(d3.easeCubicOut)
2597
+ .attr('width', Math.max(0, xScale(wakeHour) - xScale(sleepHour)))
2598
+ .attr('opacity', 0.85);
2566
2599
  }
2567
2600
  // Draw sleep dot if sleep time exists
2568
2601
  if (sleepHour !== null) {
2569
- sleepGroup.append('circle')
2602
+ const sleepDot = sleepGroup.append('circle')
2570
2603
  .attr('cx', xScale(sleepHour))
2571
2604
  .attr('cy', yValue + barHeight / 2)
2572
- .attr('r', 4)
2605
+ .attr('r', 0) // Start with 0 radius
2573
2606
  .attr('fill', '#9B59B6')
2574
- .attr('stroke', '#fff')
2575
- .attr('stroke-width', 1)
2576
- .style('filter', 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))');
2607
+ .attr('stroke', '#ffffff')
2608
+ .attr('stroke-width', 2)
2609
+ .style('filter', 'drop-shadow(0 3px 6px rgba(155, 89, 182, 0.4))')
2610
+ .style('transition', 'all 0.3s ease');
2611
+ // Animate the dot
2612
+ sleepDot.transition()
2613
+ .duration(400)
2614
+ .delay(300 + Math.random() * 100)
2615
+ .ease(d3.easeBackOut)
2616
+ .attr('r', 6);
2577
2617
  }
2578
2618
  // Draw wake dot if wake hour exists
2579
2619
  if (wakeHour !== null) {
2580
- sleepGroup.append('circle')
2620
+ const wakeDot = sleepGroup.append('circle')
2581
2621
  .attr('cx', xScale(wakeHour))
2582
2622
  .attr('cy', yValue + barHeight / 2)
2583
- .attr('r', 4)
2623
+ .attr('r', 0) // Start with 0 radius
2584
2624
  .attr('fill', '#3498DB')
2585
- .attr('stroke', '#fff')
2586
- .attr('stroke-width', 1)
2587
- .style('filter', 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))');
2625
+ .attr('stroke', '#ffffff')
2626
+ .attr('stroke-width', 2)
2627
+ .style('filter', 'drop-shadow(0 3px 6px rgba(52, 152, 219, 0.4))')
2628
+ .style('transition', 'all 0.3s ease');
2629
+ // Animate the dot
2630
+ wakeDot.transition()
2631
+ .duration(400)
2632
+ .delay(500 + Math.random() * 100)
2633
+ .ease(d3.easeBackOut)
2634
+ .attr('r', 6);
2588
2635
  }
2589
2636
  // Add hover interactions with tooltip
2590
2637
  sleepGroup
@@ -2594,7 +2641,12 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2594
2641
  .transition()
2595
2642
  .duration(200)
2596
2643
  .attr('opacity', 1)
2597
- .style('filter', 'brightness(1.1)');
2644
+ .style('filter', 'drop-shadow(0 4px 12px rgba(155, 89, 182, 0.5)) brightness(1.1)');
2645
+ // Scale up the dots
2646
+ d3.select(this).selectAll('circle')
2647
+ .transition()
2648
+ .duration(200)
2649
+ .attr('r', 8);
2598
2650
  // Show tooltip
2599
2651
  const formatTime = (hour) => {
2600
2652
  const h24 = hour % 24;
@@ -2603,18 +2655,18 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2603
2655
  const minutes = Math.round((hour % 1) * 60);
2604
2656
  return `${h12}:${minutes.toString().padStart(2, '0')} ${ampm}`;
2605
2657
  };
2606
- let tooltipContent = `<div><strong>${new Date(dayData.date).toLocaleDateString()}</strong></div>`;
2658
+ let tooltipContent = `<div style="font-weight: bold; margin-bottom: 8px; font-size: 16px;">${new Date(dayData.date).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' })}</div>`;
2607
2659
  if (sleepHour !== null && wakeHour !== null) {
2608
2660
  const sleepDuration = wakeHour - sleepHour;
2609
- tooltipContent += `<div>Sleep: ${formatTime(sleepHour)}</div>`;
2610
- tooltipContent += `<div>Wake: ${formatTime(wakeHour)}</div>`;
2611
- tooltipContent += `<div>Duration: ${Math.floor(sleepDuration)}h ${Math.round((sleepDuration % 1) * 60)}m</div>`;
2661
+ tooltipContent += `<div style="margin: 4px 0;">🌙 Sleep: ${formatTime(sleepHour)}</div>`;
2662
+ tooltipContent += `<div style="margin: 4px 0;">☀️ Wake: ${formatTime(wakeHour)}</div>`;
2663
+ tooltipContent += `<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.2);">⏱️ Duration: ${Math.floor(sleepDuration)}h ${Math.round((sleepDuration % 1) * 60)}m</div>`;
2612
2664
  }
2613
2665
  else {
2614
2666
  if (sleepHour !== null)
2615
- tooltipContent += `<div>Sleep: ${formatTime(sleepHour)}</div>`;
2667
+ tooltipContent += `<div style="margin: 4px 0;">🌙 Sleep: ${formatTime(sleepHour)}</div>`;
2616
2668
  if (wakeHour !== null)
2617
- tooltipContent += `<div>Wake: ${formatTime(wakeHour)}</div>`;
2669
+ tooltipContent += `<div style="margin: 4px 0;">☀️ Wake: ${formatTime(wakeHour)}</div>`;
2618
2670
  }
2619
2671
  tooltip.html(tooltipContent)
2620
2672
  .style('opacity', 1)
@@ -2626,8 +2678,13 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2626
2678
  d3.select(this).select('rect')
2627
2679
  .transition()
2628
2680
  .duration(200)
2629
- .attr('opacity', 0.8)
2630
- .style('filter', 'none');
2681
+ .attr('opacity', 0.85)
2682
+ .style('filter', 'drop-shadow(0 2px 8px rgba(155, 89, 182, 0.3))');
2683
+ // Reset dots
2684
+ d3.select(this).selectAll('circle')
2685
+ .transition()
2686
+ .duration(200)
2687
+ .attr('r', 6);
2631
2688
  // Hide tooltip
2632
2689
  tooltip.style('opacity', 0);
2633
2690
  })
@@ -2647,16 +2704,23 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2647
2704
  gradient.append('stop')
2648
2705
  .attr('offset', '0%')
2649
2706
  .attr('stop-color', '#9B59B6')
2650
- .attr('stop-opacity', 0.9);
2707
+ .attr('stop-opacity', 1);
2708
+ gradient.append('stop')
2709
+ .attr('offset', '50%')
2710
+ .attr('stop-color', '#7B68A6')
2711
+ .attr('stop-opacity', 1);
2651
2712
  gradient.append('stop')
2652
2713
  .attr('offset', '100%')
2653
2714
  .attr('stop-color', '#3498DB')
2654
- .attr('stop-opacity', 0.9);
2715
+ .attr('stop-opacity', 1);
2655
2716
  const xAxisTicks = d3.range(18, 43, 3).map(hour => ({
2656
2717
  value: hour,
2657
- label: (hour % 24).toString().padStart(2, '0') + ':00'
2718
+ label: hour === 24 ? '12 AM' : hour === 36 ? '12 PM' :
2719
+ (hour % 24) === 0 ? '12 AM' :
2720
+ (hour % 24) < 12 ? `${hour % 24} AM` :
2721
+ (hour % 24) === 12 ? '12 PM' : `${(hour % 24) - 12} PM`
2658
2722
  }));
2659
- g.append('g')
2723
+ const xAxis = g.append('g')
2660
2724
  .attr('class', styles$4.xAxis)
2661
2725
  .attr('transform', `translate(0,${chartHeight})`)
2662
2726
  .call(d3.axisBottom(xScale)
@@ -2664,7 +2728,14 @@ const SleepChart = ({ sleepData, width = 800, height = 300, onDateClick }) => {
2664
2728
  .tickFormat((d) => {
2665
2729
  const tick = xAxisTicks.find(t => t.value === d);
2666
2730
  return tick ? tick.label : '';
2667
- }));
2731
+ })
2732
+ .tickSizeOuter(0));
2733
+ // Style axis ticks
2734
+ xAxis.selectAll('text')
2735
+ .style('font-weight', d => {
2736
+ const hour = d % 24;
2737
+ return hour === 0 || hour === 12 ? '600' : '400';
2738
+ });
2668
2739
  const yAxisTicks = yDomain.filter((_, i) => i % Math.ceil(yDomain.length / 10) === 0);
2669
2740
  g.append('g')
2670
2741
  .attr('class', styles$4.yAxis)
@@ -2908,8 +2979,8 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2908
2979
  const interpolatedArc = d3.arc()
2909
2980
  .startAngle(() => currX0)
2910
2981
  .endAngle(() => currX1)
2911
- .innerRadius(() => Math.sqrt(currY0))
2912
- .outerRadius(() => Math.sqrt(currY1))
2982
+ .innerRadius(() => Math.min(radius, Math.sqrt(Math.max(0, currY0))))
2983
+ .outerRadius(() => Math.min(radius, Math.sqrt(Math.max(0, currY1))))
2913
2984
  .cornerRadius(3);
2914
2985
  return interpolatedArc(node) || '';
2915
2986
  };
@@ -2939,13 +3010,20 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2939
3010
  .ease(d3.easeCubicInOut);
2940
3011
  // Zoom to clicked node - scale to fill the entire circle
2941
3012
  const clickedOriginal = clickedNode;
3013
+ // Ensure we use the original x values for proper scaling
3014
+ // The x-scale maps the clicked node's angular extent to the full circle
2942
3015
  const xScale = d3.scaleLinear()
2943
3016
  .domain([clickedOriginal.x0Original, clickedOriginal.x1Original])
2944
- .range([0, 2 * Math.PI]);
2945
- // For the radial scale, we want to map the clicked node's radial range to the full circle
3017
+ .range([0, 2 * Math.PI])
3018
+ .clamp(true); // Ensure values stay within bounds
3019
+ // For the radial scale, we want to keep the children visible
3020
+ // Map from the clicked node's inner radius to the maximum child radius
3021
+ const maxChildRadius = Math.max(clickedOriginal.y1Original, ...nodes.filter(d => isParentOf(clickedNode, d) && d !== clickedNode)
3022
+ .map(d => d.y1Original));
2946
3023
  const yScale = d3.scaleLinear()
2947
- .domain([clickedOriginal.y0Original, clickedOriginal.y1Original])
2948
- .range([0, radius * radius]);
3024
+ .domain([clickedOriginal.y0Original, maxChildRadius])
3025
+ .range([0, radius * radius])
3026
+ .clamp(true); // Ensure values stay within bounds
2949
3027
  // First, immediately hide elements that shouldn't be visible
2950
3028
  paths.style('opacity', (d) => isParentOf(clickedNode, d) ? 1 : 0);
2951
3029
  paths.transition(transition)
@@ -2957,17 +3035,31 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2957
3035
  return () => '';
2958
3036
  }
2959
3037
  // Calculate new positions based on the original positions
2960
- const newX0 = xScale(node.x0Original);
2961
- const newX1 = xScale(node.x1Original);
2962
- // For radial positions, map them within the clicked node's range
3038
+ // Ensure angular values wrap correctly and don't get stuck
3039
+ let newX0 = xScale(node.x0Original);
3040
+ let newX1 = xScale(node.x1Original);
3041
+ // Handle edge case where the scaled values might be equal or inverted
3042
+ if (Math.abs(newX1 - newX0) < 0.001) {
3043
+ // If the segment would be too small, give it a minimum size
3044
+ newX1 = newX0 + 0.001;
3045
+ }
3046
+ // Ensure the angles span correctly (handle wraparound)
3047
+ if (newX1 < newX0) {
3048
+ newX1 = newX0 + (2 * Math.PI * (node.x1Original - node.x0Original) / (clickedOriginal.x1Original - clickedOriginal.x0Original));
3049
+ }
3050
+ // For radial positions, scale appropriately
2963
3051
  let newY0, newY1;
2964
3052
  if (node === clickedNode) {
2965
- // The clicked node itself should fill from center to edge
3053
+ // The clicked node itself should fill from center to where its children start
2966
3054
  newY0 = 0;
2967
- newY1 = radius * radius;
3055
+ // Find the minimum y0 of its direct children to determine where to end
3056
+ const childrenY0 = node.children ?
3057
+ Math.min(...node.children.map(c => c.y0Original)) :
3058
+ clickedOriginal.y1Original;
3059
+ newY1 = yScale(childrenY0) * 0.95; // Slightly smaller to create visual separation
2968
3060
  }
2969
3061
  else {
2970
- // Child nodes should be scaled within the full radius
3062
+ // Child nodes should be scaled within the remaining space
2971
3063
  newY0 = yScale(node.y0Original);
2972
3064
  newY1 = yScale(node.y1Original);
2973
3065
  }
@@ -2990,8 +3082,8 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2990
3082
  const interpolatedArc = d3.arc()
2991
3083
  .startAngle(() => currX0)
2992
3084
  .endAngle(() => currX1)
2993
- .innerRadius(() => Math.sqrt(currY0))
2994
- .outerRadius(() => Math.sqrt(currY1))
3085
+ .innerRadius(() => Math.min(radius, Math.sqrt(Math.max(0, currY0))))
3086
+ .outerRadius(() => Math.min(radius, Math.sqrt(Math.max(0, currY1))))
2995
3087
  .cornerRadius(3);
2996
3088
  return interpolatedArc(node) || '';
2997
3089
  };
@@ -3027,11 +3119,11 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
3027
3119
  return getColor(ancestor.data.name, d.depth);
3028
3120
  })
3029
3121
  .attr('stroke', () => {
3030
- // Get computed background color
3122
+ // Get computed border color from theme
3031
3123
  const computedStyle = window.getComputedStyle(svgRef.current);
3032
- return computedStyle.getPropertyValue('--bg-primary') || '#ffffff';
3124
+ return computedStyle.getPropertyValue('--color-border') || '#e2e8f0';
3033
3125
  })
3034
- .attr('stroke-width', 1)
3126
+ .attr('stroke-width', 2)
3035
3127
  .style('cursor', d => (!d.children || d.children.length === 0) ? 'default' : 'pointer')
3036
3128
  .on('click', handleClick)
3037
3129
  .on('mouseover', function (event, d) {