@stfrigerio/sito-template 0.1.7 → 0.1.8

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/index.js CHANGED
@@ -1199,7 +1199,8 @@ const EditFAB = ({ canEdit, isEditMode, hasUnsavedChanges = false, isSaving = fa
1199
1199
 
1200
1200
  var styles$a = {"searchContainer":"SearchBar-module_searchContainer__TdM1w","searchInputWrapper":"SearchBar-module_searchInputWrapper__kCZLU","searchIcon":"SearchBar-module_searchIcon__IIxEu","searchInput":"SearchBar-module_searchInput__V4gkE","clearButton":"SearchBar-module_clearButton__7fNIY","filterSelect":"SearchBar-module_filterSelect__xIVE4","resultsDropdown":"SearchBar-module_resultsDropdown__yh6NF","loadingState":"SearchBar-module_loadingState__4gidK","emptyState":"SearchBar-module_emptyState__RbI4s","spinner":"SearchBar-module_spinner__PMc6-","resultsGroups":"SearchBar-module_resultsGroups__U24DC","resultGroup":"SearchBar-module_resultGroup__SoTQH","groupHeader":"SearchBar-module_groupHeader__bFRHA","groupIcon":"SearchBar-module_groupIcon__9ENM-","groupTitle":"SearchBar-module_groupTitle__ZekZs","groupCount":"SearchBar-module_groupCount__PQIqw","groupResults":"SearchBar-module_groupResults__xTF52","resultItem":"SearchBar-module_resultItem__VaKKy","highlighted":"SearchBar-module_highlighted__Q-3sH","resultTitle":"SearchBar-module_resultTitle__i1uqL","resultSubtitle":"SearchBar-module_resultSubtitle__LQOJ1","resultMeta":"SearchBar-module_resultMeta__Kmkrn","resultContent":"SearchBar-module_resultContent__TzVzL","highlight":"SearchBar-module_highlight__Q3PSP"};
1201
1201
 
1202
- const filterOptions = [
1202
+ // Default filter options for backwards compatibility
1203
+ const defaultFilterOptions = [
1203
1204
  { value: 'all', label: 'All', icon: FiSearch },
1204
1205
  { value: 'projects', label: 'Projects', icon: FiFolder },
1205
1206
  { value: 'clients', label: 'Clients', icon: FiUsers },
@@ -1207,16 +1208,18 @@ const filterOptions = [
1207
1208
  { value: 'interactions', label: 'Interactions', icon: FiMessageSquare },
1208
1209
  { value: 'team', label: 'Team', icon: FiUserPlus },
1209
1210
  ];
1210
- const entityIcons = {
1211
+ const defaultEntityIcons = {
1211
1212
  projects: FiFolder,
1212
1213
  clients: FiUsers,
1213
1214
  contacts: FiBook,
1214
1215
  interactions: FiMessageSquare,
1215
1216
  team: FiUserPlus,
1216
1217
  };
1217
- const SearchBar = ({ className, placeholder = "Search (Ctrl+Space)...", onSearch, onResultClick, onClear, debounceDelay = 300, minSearchLength = 2, showFilter = true, enableKeyboardShortcut = true }) => {
1218
+ const SearchBar = ({ className, placeholder = "Search (Ctrl+Space)...", onSearch, onResultClick, onClear, debounceDelay = 300, minSearchLength = 2, showFilter = true, enableKeyboardShortcut = true, filterOptions: customFilterOptions, entityIcons: customEntityIcons }) => {
1219
+ const filterOptions = customFilterOptions ?? defaultFilterOptions;
1220
+ const entityIcons = customEntityIcons ?? defaultEntityIcons;
1218
1221
  const [query, setQuery] = React.useState('');
1219
- const [filter, setFilter] = React.useState('all');
1222
+ const [filter, setFilter] = React.useState(filterOptions[0]?.value ?? 'all');
1220
1223
  const [results, setResults] = React.useState([]);
1221
1224
  const [isLoading, setIsLoading] = React.useState(false);
1222
1225
  const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
@@ -1545,15 +1548,16 @@ function SiJira (props) {
1545
1548
 
1546
1549
  var styles$6 = {"tabs":"Tabs-module_tabs__Vlvn7","tab":"Tabs-module_tab__uQKim","tabIcon":"Tabs-module_tabIcon__AgN-O"};
1547
1550
 
1548
- const tabs = [
1551
+ // Default tabs for backwards compatibility
1552
+ const defaultTabs = [
1549
1553
  { id: 'details', icon: FiInfo, label: 'Dettagli' },
1550
1554
  { id: 'github', icon: FiGithub, label: 'GitHub' },
1551
1555
  { id: 'jira', icon: SiJira, label: 'Jira' },
1552
1556
  { id: 'functional', icon: FiInfo, label: 'Analisi funzionale' }
1553
1557
  ];
1554
- const Tabs = ({ activeTab, onTabChange }) => {
1555
- return (jsxRuntime.jsx("div", { className: styles$6.tabs, children: tabs.map((tab) => {
1556
- const Icon = tab.icon;
1558
+ const Tabs = ({ activeTab, onTabChange, tabs: customTabs, className = '' }) => {
1559
+ const tabs = customTabs ?? defaultTabs;
1560
+ return (jsxRuntime.jsx("div", { className: `${styles$6.tabs} ${className}`, children: tabs.map((tab) => {
1557
1561
  const isActive = activeTab === tab.id;
1558
1562
  return (jsxRuntime.jsxs(framerMotion.motion.button, { className: styles$6.tab, "data-active": isActive, onClick: () => onTabChange(tab.id), style: { position: 'relative' }, children: [jsxRuntime.jsx(framerMotion.motion.div, { animate: {
1559
1563
  rotate: isActive ? [0, -10, 10, -5, 5, 0] : 0,
@@ -1562,7 +1566,7 @@ const Tabs = ({ activeTab, onTabChange }) => {
1562
1566
  duration: 0.5,
1563
1567
  ease: 'easeInOut'
1564
1568
  }
1565
- }, children: jsxRuntime.jsx(Icon, { className: styles$6.tabIcon }) }), jsxRuntime.jsx("span", { children: tab.label })] }, tab.id));
1569
+ }, children: tab.icon && (typeof tab.icon === 'function' ? (jsxRuntime.jsx("span", { className: styles$6.tabIcon, children: React.createElement(tab.icon) })) : (jsxRuntime.jsx("span", { className: styles$6.tabIcon, children: tab.icon }))) }), jsxRuntime.jsx("span", { children: tab.label })] }, tab.id));
1566
1570
  }) }));
1567
1571
  };
1568
1572
 
@@ -2246,11 +2250,22 @@ const BooleansHeatmap = ({ data, habitName, width = 800, height = 200, habitColo
2246
2250
  var styles$1 = {"container":"SunburstChart-module_container__w1ZYc","title":"SunburstChart-module_title__T6Ak7","chart":"SunburstChart-module_chart__BFM6E","tooltip":"SunburstChart-module_tooltip__TuTAN"};
2247
2251
 
2248
2252
  const COLOR_PALETTE = [
2249
- '#d4af37', '#FFD700', '#FFA500', '#FF8C00',
2250
- '#FF6347', '#DC143C', '#8B4513', '#A0522D',
2251
- '#DEB887', '#F4A460', '#D2691E', '#CD853F'
2253
+ '#6366f1', '#8b5cf6', '#06b6d4', '#10b981',
2254
+ '#f59e0b', '#ef4444', '#ec4899', '#84cc16',
2255
+ '#f97316', '#3b82f6', '#14b8a6', '#f59e0b'
2252
2256
  ];
2253
- const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Chart', tagColors = {} }) => {
2257
+ // Calculate text color based on background luminance for optimal contrast
2258
+ const getTextColor$1 = (backgroundColor) => {
2259
+ const color = d3__namespace.color(backgroundColor);
2260
+ if (!color)
2261
+ return '#ffffff';
2262
+ const rgb = color.rgb();
2263
+ // Calculate relative luminance using WCAG formula
2264
+ const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
2265
+ // Return white text for dark backgrounds, black for light backgrounds
2266
+ return luminance > 0.5 ? '#000000' : '#ffffff';
2267
+ };
2268
+ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Chart', tagColors = {}, unit = 'items', centerLabel }) => {
2254
2269
  const svgRef = React.useRef(null);
2255
2270
  const colorMap = React.useRef(new Map()).current;
2256
2271
  const colorIndex = React.useRef(0);
@@ -2293,7 +2308,8 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2293
2308
  .startAngle(d => d.x0)
2294
2309
  .endAngle(d => d.x1)
2295
2310
  .innerRadius(d => Math.sqrt(d.y0))
2296
- .outerRadius(d => Math.sqrt(d.y1));
2311
+ .outerRadius(d => Math.sqrt(d.y1))
2312
+ .cornerRadius(3);
2297
2313
  const tooltip = d3__namespace.select('body').append('div')
2298
2314
  .attr('class', styles$1.tooltip)
2299
2315
  .style('opacity', 0)
@@ -2312,11 +2328,20 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2312
2328
  .attr('stroke', 'var(--bg-primary)')
2313
2329
  .attr('stroke-width', 2)
2314
2330
  .style('cursor', 'pointer')
2331
+ .style('filter', 'drop-shadow(0 1px 3px rgba(0,0,0,0.12))')
2315
2332
  .on('mouseover', function (event, d) {
2333
+ const hoverArc = d3__namespace.arc()
2334
+ .startAngle(d => d.x0)
2335
+ .endAngle(d => d.x1)
2336
+ .innerRadius(d => Math.sqrt(d.y0) - 2)
2337
+ .outerRadius(d => Math.sqrt(d.y1) + 4)
2338
+ .cornerRadius(3);
2316
2339
  d3__namespace.select(this)
2317
2340
  .transition()
2318
- .duration(200)
2319
- .style('opacity', 0.8);
2341
+ .duration(150)
2342
+ .attr('d', d => hoverArc(d))
2343
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.2))')
2344
+ .style('opacity', 0.9);
2320
2345
  tooltip.transition()
2321
2346
  .duration(200)
2322
2347
  .style('opacity', 1);
@@ -2330,10 +2355,12 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2330
2355
  .style('left', (event.pageX + 10) + 'px')
2331
2356
  .style('top', (event.pageY - 28) + 'px');
2332
2357
  })
2333
- .on('mouseout', function () {
2358
+ .on('mouseout', function (event, d) {
2334
2359
  d3__namespace.select(this)
2335
2360
  .transition()
2336
- .duration(200)
2361
+ .duration(150)
2362
+ .attr('d', d => arc(d))
2363
+ .style('filter', 'drop-shadow(0 1px 3px rgba(0,0,0,0.12))')
2337
2364
  .style('opacity', 1);
2338
2365
  tooltip.transition()
2339
2366
  .duration(500)
@@ -2343,9 +2370,32 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2343
2370
  const angle = d.x1 - d.x0;
2344
2371
  return angle > 0.15 && d.depth <= 2;
2345
2372
  };
2346
- g.selectAll('text')
2373
+ // Calculate average background color for center text contrast
2374
+ const allSegments = nodes.filter(d => d.depth === 1);
2375
+ const avgColor = allSegments.length > 0 ? d3__namespace.interpolateRgb.gamma(2.2)(...allSegments.map(d => getColor(d.data.name, 1)))(0.5) : '#ffffff';
2376
+ const centerTextColor = getTextColor$1(avgColor);
2377
+ // Add center text
2378
+ g.append('text')
2379
+ .attr('text-anchor', 'middle')
2380
+ .attr('alignment-baseline', 'middle')
2381
+ .attr('font-size', '18px')
2382
+ .attr('font-weight', 'bold')
2383
+ .attr('fill', centerTextColor)
2384
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 3px rgba(0,0,0,0.5)' : '0 1px 3px rgba(255,255,255,0.5)')
2385
+ .text(centerLabel || data.name || 'Total');
2386
+ g.append('text')
2387
+ .attr('text-anchor', 'middle')
2388
+ .attr('alignment-baseline', 'middle')
2389
+ .attr('y', 20)
2390
+ .attr('font-size', '14px')
2391
+ .attr('font-weight', '500')
2392
+ .attr('fill', centerTextColor)
2393
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 2px rgba(0,0,0,0.4)' : '0 1px 2px rgba(255,255,255,0.4)')
2394
+ .text(`${(root.value || 0).toLocaleString()} ${unit}`);
2395
+ g.selectAll('text.segment-label')
2347
2396
  .data(nodes.filter(d => d.depth > 0 && d.value && d.value > 0 && shouldDisplayLabel(d)))
2348
2397
  .enter().append('text')
2398
+ .attr('class', 'segment-label')
2349
2399
  .attr('transform', d => {
2350
2400
  const angle = (d.x0 + d.x1) / 2;
2351
2401
  const radius = (Math.sqrt(d.y0) + Math.sqrt(d.y1)) / 2;
@@ -2355,11 +2405,32 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2355
2405
  })
2356
2406
  .attr('text-anchor', 'middle')
2357
2407
  .attr('alignment-baseline', 'middle')
2358
- .attr('font-size', '12px')
2359
- .attr('fill', 'var(--text-inverse)')
2360
- .attr('font-weight', 'var(--font-medium)')
2408
+ .attr('font-size', d => d.depth === 1 ? '13px' : '11px')
2409
+ .attr('fill', d => {
2410
+ let ancestor = d;
2411
+ while (ancestor.depth > 1 && ancestor.parent) {
2412
+ ancestor = ancestor.parent;
2413
+ }
2414
+ const segmentColor = getColor(ancestor.data.name, d.depth);
2415
+ return getTextColor$1(segmentColor);
2416
+ })
2417
+ .attr('font-weight', '600')
2361
2418
  .style('pointer-events', 'none')
2362
- .text(d => d.data.name.substring(0, 10));
2419
+ .style('text-shadow', d => {
2420
+ let ancestor = d;
2421
+ while (ancestor.depth > 1 && ancestor.parent) {
2422
+ ancestor = ancestor.parent;
2423
+ }
2424
+ const segmentColor = getColor(ancestor.data.name, d.depth);
2425
+ const textColor = getTextColor$1(segmentColor);
2426
+ // Use contrasting shadow color
2427
+ const shadowColor = textColor === '#ffffff' ? 'rgba(0,0,0,0.5)' : 'rgba(255,255,255,0.5)';
2428
+ return `0 1px 2px ${shadowColor}`;
2429
+ })
2430
+ .text(d => {
2431
+ const maxLength = d.depth === 1 ? 12 : 8;
2432
+ return d.data.name.substring(0, maxLength);
2433
+ });
2363
2434
  return () => {
2364
2435
  tooltip.remove();
2365
2436
  };
@@ -2370,12 +2441,23 @@ const SunburstChart = ({ data, width = 500, height = 500, title = 'Sunburst Char
2370
2441
  var styles = {"container":"PieChart-module_container__tXjbe","title":"PieChart-module_title__61o0R","chartContainer":"PieChart-module_chartContainer__uLmOz","chart":"PieChart-module_chart__3nqON","legend":"PieChart-module_legend__rAWgh","legendItem":"PieChart-module_legendItem__Nb031","legendColor":"PieChart-module_legendColor__fLuv9","legendLabel":"PieChart-module_legendLabel__xbjBr","legendValue":"PieChart-module_legendValue__h2WS2","tooltip":"PieChart-module_tooltip__140RU"};
2371
2442
 
2372
2443
  const DEFAULT_COLORS = [
2373
- '#d4af37', '#FFD700', '#FFA500', '#FF8C00',
2374
- '#FF6347', '#DC143C', '#8B4513', '#A0522D',
2375
- '#DEB887', '#F4A460', '#D2691E', '#CD853F',
2376
- '#B8860B', '#DAA520', '#F0E68C', '#BDB76B'
2444
+ '#6366f1', '#8b5cf6', '#06b6d4', '#10b981',
2445
+ '#f59e0b', '#ef4444', '#ec4899', '#84cc16',
2446
+ '#f97316', '#3b82f6', '#8b5cf6', '#14b8a6',
2447
+ '#f59e0b', '#ef4444', '#06b6d4', '#10b981'
2377
2448
  ];
2378
- const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', showLegend = true }) => {
2449
+ // Calculate text color based on background luminance for optimal contrast
2450
+ const getTextColor = (backgroundColor) => {
2451
+ const color = d3__namespace.color(backgroundColor);
2452
+ if (!color)
2453
+ return '#ffffff';
2454
+ const rgb = color.rgb();
2455
+ // Calculate relative luminance using WCAG formula
2456
+ const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
2457
+ // Return white text for dark backgrounds, black for light backgrounds
2458
+ return luminance > 0.5 ? '#000000' : '#ffffff';
2459
+ };
2460
+ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', showLegend = true, unit = 'items', centerLabel }) => {
2379
2461
  const svgRef = React.useRef(null);
2380
2462
  const radius = Math.min(width, height) / 2 - 20;
2381
2463
  React.useEffect(() => {
@@ -2389,8 +2471,9 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2389
2471
  .value(d => d.value)
2390
2472
  .sort(null);
2391
2473
  const arc = d3__namespace.arc()
2392
- .innerRadius(0)
2393
- .outerRadius(radius);
2474
+ .innerRadius(radius * 0.4)
2475
+ .outerRadius(radius)
2476
+ .cornerRadius(4);
2394
2477
  const labelArc = d3__namespace.arc()
2395
2478
  .innerRadius(radius * 0.7)
2396
2479
  .outerRadius(radius * 0.7);
@@ -2408,13 +2491,19 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2408
2491
  .attr('d', d => arc(d))
2409
2492
  .attr('fill', (d, i) => d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length])
2410
2493
  .attr('stroke', 'var(--bg-primary)')
2411
- .attr('stroke-width', 2)
2494
+ .attr('stroke-width', 3)
2412
2495
  .style('cursor', 'pointer')
2496
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.15))')
2413
2497
  .on('mouseover', function (event, d) {
2498
+ const hoverArc = d3__namespace.arc()
2499
+ .innerRadius(radius * 0.4)
2500
+ .outerRadius(radius * 1.05)
2501
+ .cornerRadius(4);
2414
2502
  d3__namespace.select(this)
2415
2503
  .transition()
2416
2504
  .duration(200)
2417
- .style('opacity', 0.8);
2505
+ .attr('d', d => hoverArc(d))
2506
+ .style('filter', 'drop-shadow(0 4px 12px rgba(0,0,0,0.25))');
2418
2507
  tooltip.transition()
2419
2508
  .duration(200)
2420
2509
  .style('opacity', 1);
@@ -2427,27 +2516,59 @@ const PieChart = ({ data, width = 400, height = 400, title = 'Distribution', sho
2427
2516
  .style('left', (event.pageX + 10) + 'px')
2428
2517
  .style('top', (event.pageY - 28) + 'px');
2429
2518
  })
2430
- .on('mouseout', function () {
2519
+ .on('mouseout', function (event, d) {
2431
2520
  d3__namespace.select(this)
2432
2521
  .transition()
2433
2522
  .duration(200)
2434
- .style('opacity', 1);
2523
+ .attr('d', d => arc(d))
2524
+ .style('filter', 'drop-shadow(0 2px 8px rgba(0,0,0,0.15))');
2435
2525
  tooltip.transition()
2436
2526
  .duration(500)
2437
2527
  .style('opacity', 0);
2438
2528
  });
2439
- arcs.filter(d => (d.endAngle - d.startAngle) > 0.3)
2529
+ // Calculate average background color for center text contrast
2530
+ const avgColor = data.length > 0 ? d3__namespace.interpolateRgb.gamma(2.2)(...data.map((d, i) => d.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length]))(0.5) : '#ffffff';
2531
+ const centerTextColor = getTextColor(avgColor);
2532
+ // Add center text for donut
2533
+ g.append('text')
2534
+ .attr('text-anchor', 'middle')
2535
+ .attr('alignment-baseline', 'middle')
2536
+ .attr('font-size', '20px')
2537
+ .attr('font-weight', 'bold')
2538
+ .attr('fill', centerTextColor)
2539
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 3px rgba(0,0,0,0.5)' : '0 1px 3px rgba(255,255,255,0.5)')
2540
+ .text(centerLabel || 'Total');
2541
+ g.append('text')
2542
+ .attr('text-anchor', 'middle')
2543
+ .attr('alignment-baseline', 'middle')
2544
+ .attr('y', 22)
2545
+ .attr('font-size', '16px')
2546
+ .attr('font-weight', '600')
2547
+ .attr('fill', centerTextColor)
2548
+ .style('text-shadow', centerTextColor === '#ffffff' ? '0 1px 2px rgba(0,0,0,0.4)' : '0 1px 2px rgba(255,255,255,0.4)')
2549
+ .text(`${total.toLocaleString()} ${unit}`);
2550
+ arcs.filter(d => (d.endAngle - d.startAngle) > 0.2)
2440
2551
  .append('text')
2441
2552
  .attr('transform', d => `translate(${labelArc.centroid(d)})`)
2442
2553
  .attr('text-anchor', 'middle')
2443
2554
  .attr('alignment-baseline', 'middle')
2444
- .attr('font-size', '12px')
2445
- .attr('fill', 'var(--text-inverse)')
2446
- .attr('font-weight', 'var(--font-semibold)')
2555
+ .attr('font-size', '13px')
2556
+ .attr('fill', (d, i) => {
2557
+ const segmentColor = d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2558
+ return getTextColor(segmentColor);
2559
+ })
2560
+ .attr('font-weight', '600')
2447
2561
  .style('pointer-events', 'none')
2562
+ .style('text-shadow', (d, i) => {
2563
+ const segmentColor = d.data.color || DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2564
+ const textColor = getTextColor(segmentColor);
2565
+ // Use contrasting shadow color
2566
+ const shadowColor = textColor === '#ffffff' ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.4)';
2567
+ return `0 1px 2px ${shadowColor}`;
2568
+ })
2448
2569
  .text(d => {
2449
2570
  const percentage = ((d.data.value / total) * 100);
2450
- return percentage > 5 ? `${percentage.toFixed(1)}%` : '';
2571
+ return percentage > 8 ? `${percentage.toFixed(0)}%` : '';
2451
2572
  });
2452
2573
  return () => {
2453
2574
  tooltip.remove();