@orianatech/pire 0.10.0 → 0.12.0
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/components/data/BarChart.d.cts +32 -0
- package/dist/components/data/BarChart.d.ts +33 -0
- package/dist/components/data/BarChart.d.ts.map +1 -0
- package/dist/components/data/ChartFrame.d.cts +62 -0
- package/dist/components/data/ChartFrame.d.ts +63 -0
- package/dist/components/data/ChartFrame.d.ts.map +1 -0
- package/dist/components/data/DonutChart.d.cts +26 -0
- package/dist/components/data/DonutChart.d.ts +27 -0
- package/dist/components/data/DonutChart.d.ts.map +1 -0
- package/dist/components/data/LineChart.d.cts +29 -0
- package/dist/components/data/LineChart.d.ts +30 -0
- package/dist/components/data/LineChart.d.ts.map +1 -0
- package/dist/components/data/LinkList.d.ts.map +1 -1
- package/dist/components/data/chartGeometry.d.cts +67 -0
- package/dist/components/data/chartGeometry.d.ts +68 -0
- package/dist/components/data/chartGeometry.d.ts.map +1 -0
- package/dist/components.css +100 -3
- package/dist/i18n/messages.d.cts +6 -0
- package/dist/i18n/messages.d.ts +6 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/index.cjs +575 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +571 -72
- package/dist/index.js.map +1 -1
- package/dist/tokens/colors.css +60 -5
- package/dist/tokens/themes.css +30 -5
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -835,7 +835,10 @@ var enMessages = {
|
|
|
835
835
|
fileUploadChoose: "Choose files",
|
|
836
836
|
fileUploadRemoveNamed: "Remove {name}",
|
|
837
837
|
fileUploadUploading: "Uploading",
|
|
838
|
-
fileDropZonePrompt: "Drag files here, or choose them"
|
|
838
|
+
fileDropZonePrompt: "Drag files here, or choose them",
|
|
839
|
+
chartCategoryHeader: "Category",
|
|
840
|
+
chartNoValue: "No data",
|
|
841
|
+
chartEmpty: "No data for this period"
|
|
839
842
|
};
|
|
840
843
|
var esMessages = {
|
|
841
844
|
filterBarLabel: "Filtros",
|
|
@@ -872,7 +875,10 @@ var esMessages = {
|
|
|
872
875
|
fileUploadChoose: "Elegir archivos",
|
|
873
876
|
fileUploadRemoveNamed: "Quitar {name}",
|
|
874
877
|
fileUploadUploading: "Subiendo",
|
|
875
|
-
fileDropZonePrompt: "Arrastr\xE1 archivos ac\xE1, o elegilos"
|
|
878
|
+
fileDropZonePrompt: "Arrastr\xE1 archivos ac\xE1, o elegilos",
|
|
879
|
+
chartCategoryHeader: "Categor\xEDa",
|
|
880
|
+
chartNoValue: "Sin datos",
|
|
881
|
+
chartEmpty: "Sin datos para este per\xEDodo"
|
|
876
882
|
};
|
|
877
883
|
|
|
878
884
|
// src/i18n/PireIntlProvider.tsx
|
|
@@ -2459,20 +2465,509 @@ function Timeline({ entries, reverse = false, className, ...rest }) {
|
|
|
2459
2465
|
] }, entry.id ?? i)) });
|
|
2460
2466
|
}
|
|
2461
2467
|
|
|
2468
|
+
// src/components/data/chartGeometry.ts
|
|
2469
|
+
var VIZ_SLOT_COUNT = 6;
|
|
2470
|
+
var NICE_STEPS = [1, 2, 2.5, 5, 10];
|
|
2471
|
+
function niceStep(rough) {
|
|
2472
|
+
if (!(rough > 0)) return 1;
|
|
2473
|
+
const magnitude = 10 ** Math.floor(Math.log10(rough));
|
|
2474
|
+
const normalized = rough / magnitude;
|
|
2475
|
+
return (NICE_STEPS.find((candidate) => candidate >= normalized) ?? 10) * magnitude;
|
|
2476
|
+
}
|
|
2477
|
+
function linearScale(values, tickCount = 4, startAtZero = true) {
|
|
2478
|
+
const present = values.filter((value) => value != null && Number.isFinite(value));
|
|
2479
|
+
if (present.length === 0) return { min: 0, max: 1, ticks: [0, 1] };
|
|
2480
|
+
let low = Math.min(...present);
|
|
2481
|
+
let high = Math.max(...present);
|
|
2482
|
+
if (startAtZero) {
|
|
2483
|
+
low = Math.min(0, low);
|
|
2484
|
+
high = Math.max(0, high);
|
|
2485
|
+
}
|
|
2486
|
+
if (low === high) {
|
|
2487
|
+
high = low === 0 ? 1 : low + Math.abs(low);
|
|
2488
|
+
}
|
|
2489
|
+
const step = niceStep((high - low) / Math.max(1, tickCount));
|
|
2490
|
+
const EDGE_TOLERANCE = 1e-9;
|
|
2491
|
+
const decimals = Math.max(0, 1 - Math.floor(Math.log10(step)));
|
|
2492
|
+
const toStepPrecision = (value) => Number(value.toFixed(decimals));
|
|
2493
|
+
const min = toStepPrecision(Math.floor(low / step + EDGE_TOLERANCE) * step);
|
|
2494
|
+
const max = toStepPrecision(Math.ceil(high / step - EDGE_TOLERANCE) * step);
|
|
2495
|
+
const stepCount = Math.round((max - min) / step);
|
|
2496
|
+
const ticks = Array.from(
|
|
2497
|
+
{ length: stepCount + 1 },
|
|
2498
|
+
(_, index) => toStepPrecision(min + index * step)
|
|
2499
|
+
);
|
|
2500
|
+
return { min, max, ticks };
|
|
2501
|
+
}
|
|
2502
|
+
function scalePosition(value, scale) {
|
|
2503
|
+
const span = scale.max - scale.min;
|
|
2504
|
+
return span === 0 ? 0 : (value - scale.min) / span;
|
|
2505
|
+
}
|
|
2506
|
+
function seriesColor(series, index) {
|
|
2507
|
+
const slot = series.colorIndex ?? index + 1;
|
|
2508
|
+
return slot >= 1 && slot <= VIZ_SLOT_COUNT ? `var(--viz-${slot})` : "var(--viz-other)";
|
|
2509
|
+
}
|
|
2510
|
+
var IS_DEV2 = process.env.NODE_ENV !== "production";
|
|
2511
|
+
var warnedCharts = /* @__PURE__ */ new Set();
|
|
2512
|
+
function warnOnSlotOverflow(series, chartLabel) {
|
|
2513
|
+
if (!IS_DEV2 || warnedCharts.has(chartLabel)) return;
|
|
2514
|
+
if (series.length <= VIZ_SLOT_COUNT) return;
|
|
2515
|
+
warnedCharts.add(chartLabel);
|
|
2516
|
+
console.warn(
|
|
2517
|
+
`[pire] "${chartLabel}" has ${series.length} series but the palette defines ${VIZ_SLOT_COUNT} distinguishable colours. The extras render in one shared neutral. Group the tail into an "Other" series, or split the chart into small multiples.`
|
|
2518
|
+
);
|
|
2519
|
+
}
|
|
2520
|
+
function warnOnDonutShape(series, categoryCount, chartLabel) {
|
|
2521
|
+
if (!IS_DEV2 || warnedCharts.has(`donut:${chartLabel}`)) return;
|
|
2522
|
+
const complaints = [];
|
|
2523
|
+
if (series.length > 1) {
|
|
2524
|
+
complaints.push(`it has ${series.length} series but a donut draws one \u2014 the rest are ignored`);
|
|
2525
|
+
}
|
|
2526
|
+
if (categoryCount > VIZ_SLOT_COUNT) {
|
|
2527
|
+
complaints.push(`it has ${categoryCount} segments and the palette defines ${VIZ_SLOT_COUNT}; past about four, slices stop being readable at all \u2014 group the tail into "Other"`);
|
|
2528
|
+
}
|
|
2529
|
+
if (series[0]?.values.some((value) => value != null && value < 0)) {
|
|
2530
|
+
complaints.push("it contains negative values, which have no part-to-whole meaning \u2014 a signed measure belongs in a bar chart");
|
|
2531
|
+
}
|
|
2532
|
+
if (complaints.length === 0) return;
|
|
2533
|
+
warnedCharts.add(`donut:${chartLabel}`);
|
|
2534
|
+
console.warn(`[pire] DonutChart "${chartLabel}": ${complaints.join("; ")}.`);
|
|
2535
|
+
}
|
|
2536
|
+
function stackTotal(series, categoryIndex) {
|
|
2537
|
+
return series.reduce((total, one) => total + (one.values[categoryIndex] ?? 0), 0);
|
|
2538
|
+
}
|
|
2539
|
+
function flatValues(series) {
|
|
2540
|
+
return series.flatMap((one) => one.values);
|
|
2541
|
+
}
|
|
2542
|
+
function alignToCategories(series, categoryCount) {
|
|
2543
|
+
return series.map((one) => one.values.length <= categoryCount ? one : { ...one, values: one.values.slice(0, categoryCount) });
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
// src/components/data/ChartFrame.tsx
|
|
2547
|
+
import { jsx as jsx47, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
2548
|
+
function seriesLegend(series) {
|
|
2549
|
+
return series.map((one, index) => ({
|
|
2550
|
+
key: one.id,
|
|
2551
|
+
label: one.label,
|
|
2552
|
+
color: seriesColor(one, index)
|
|
2553
|
+
}));
|
|
2554
|
+
}
|
|
2555
|
+
var defaultFormatValue = (value) => value.toLocaleString();
|
|
2556
|
+
function ChartFrame({
|
|
2557
|
+
label,
|
|
2558
|
+
title,
|
|
2559
|
+
description,
|
|
2560
|
+
categories,
|
|
2561
|
+
series,
|
|
2562
|
+
formatValue,
|
|
2563
|
+
legend,
|
|
2564
|
+
showDataTable,
|
|
2565
|
+
className,
|
|
2566
|
+
style,
|
|
2567
|
+
children
|
|
2568
|
+
}) {
|
|
2569
|
+
const msg = usePireMessages();
|
|
2570
|
+
return /* @__PURE__ */ jsxs40("figure", { className: cx("pire-chart", className), style, children: [
|
|
2571
|
+
title || description ? /* @__PURE__ */ jsxs40("figcaption", { className: "pire-chart-head", children: [
|
|
2572
|
+
title ? /* @__PURE__ */ jsx47("span", { className: "pire-chart-title", children: title }) : null,
|
|
2573
|
+
description ? /* @__PURE__ */ jsx47("span", { className: "pire-chart-desc", children: description }) : null
|
|
2574
|
+
] }) : null,
|
|
2575
|
+
legend && legend.length > 1 ? /* @__PURE__ */ jsx47("ul", { className: "pire-chart-legend", children: legend.map((item) => /* @__PURE__ */ jsxs40("li", { className: "pire-chart-legend-item", children: [
|
|
2576
|
+
/* @__PURE__ */ jsx47("span", { className: "pire-chart-swatch", style: { background: item.color } }),
|
|
2577
|
+
item.label
|
|
2578
|
+
] }, item.key)) }) : null,
|
|
2579
|
+
/* @__PURE__ */ jsx47("div", { className: "pire-chart-plot", "aria-hidden": "true", children }),
|
|
2580
|
+
/* @__PURE__ */ jsx47("div", { className: showDataTable ? "pire-chart-table" : "pire-sr-only", children: /* @__PURE__ */ jsxs40("table", { children: [
|
|
2581
|
+
/* @__PURE__ */ jsx47("caption", { children: label }),
|
|
2582
|
+
/* @__PURE__ */ jsx47("thead", { children: /* @__PURE__ */ jsxs40("tr", { children: [
|
|
2583
|
+
/* @__PURE__ */ jsx47("th", { scope: "col", children: msg.chartCategoryHeader }),
|
|
2584
|
+
series.map((one) => /* @__PURE__ */ jsx47("th", { scope: "col", children: one.label }, one.id))
|
|
2585
|
+
] }) }),
|
|
2586
|
+
/* @__PURE__ */ jsx47("tbody", { children: categories.map((category, categoryIndex) => (
|
|
2587
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
|
|
2588
|
+
/* @__PURE__ */ jsxs40("tr", { children: [
|
|
2589
|
+
/* @__PURE__ */ jsx47("th", { scope: "row", children: category }),
|
|
2590
|
+
series.map((one) => {
|
|
2591
|
+
const value = one.values[categoryIndex];
|
|
2592
|
+
return /* @__PURE__ */ jsx47("td", { children: value == null ? msg.chartNoValue : formatValue(value) }, one.id);
|
|
2593
|
+
})
|
|
2594
|
+
] }, categoryIndex)
|
|
2595
|
+
)) })
|
|
2596
|
+
] }) })
|
|
2597
|
+
] });
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
// src/components/data/BarChart.tsx
|
|
2601
|
+
import { jsx as jsx48, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
2602
|
+
function BarChart({
|
|
2603
|
+
categories,
|
|
2604
|
+
series: rawSeries,
|
|
2605
|
+
title,
|
|
2606
|
+
description,
|
|
2607
|
+
formatValue = defaultFormatValue,
|
|
2608
|
+
height = 260,
|
|
2609
|
+
emptyState,
|
|
2610
|
+
showDataTable,
|
|
2611
|
+
orientation = "horizontal",
|
|
2612
|
+
stacked = false,
|
|
2613
|
+
showValues,
|
|
2614
|
+
className,
|
|
2615
|
+
style,
|
|
2616
|
+
...rest
|
|
2617
|
+
}) {
|
|
2618
|
+
const label = rest["aria-label"];
|
|
2619
|
+
const msg = usePireMessages();
|
|
2620
|
+
warnOnSlotOverflow(rawSeries, label);
|
|
2621
|
+
const series = alignToCategories(rawSeries, categories.length);
|
|
2622
|
+
const hasData = categories.length > 0 && series.length > 0;
|
|
2623
|
+
const withValues = showValues ?? series.length === 1;
|
|
2624
|
+
const scale = linearScale(
|
|
2625
|
+
stacked ? categories.map((_, index) => stackTotal(series, index)) : flatValues(series)
|
|
2626
|
+
);
|
|
2627
|
+
const sizeOf = (value) => `${scalePosition(value, scale) * 100}%`;
|
|
2628
|
+
const horizontalLabelFor = (categoryIndex) => {
|
|
2629
|
+
if (stacked) return formatValue(stackTotal(series, categoryIndex));
|
|
2630
|
+
const value = series[0].values[categoryIndex];
|
|
2631
|
+
return value == null ? msg.chartNoValue : formatValue(value);
|
|
2632
|
+
};
|
|
2633
|
+
return /* @__PURE__ */ jsx48(
|
|
2634
|
+
ChartFrame,
|
|
2635
|
+
{
|
|
2636
|
+
label,
|
|
2637
|
+
title,
|
|
2638
|
+
description,
|
|
2639
|
+
categories,
|
|
2640
|
+
series,
|
|
2641
|
+
formatValue,
|
|
2642
|
+
legend: seriesLegend(series),
|
|
2643
|
+
showDataTable,
|
|
2644
|
+
className,
|
|
2645
|
+
style,
|
|
2646
|
+
children: !hasData ? /* @__PURE__ */ jsx48("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsx48(
|
|
2647
|
+
"div",
|
|
2648
|
+
{
|
|
2649
|
+
className: "pire-chart-bars",
|
|
2650
|
+
"data-orientation": orientation,
|
|
2651
|
+
"data-stacked": String(stacked),
|
|
2652
|
+
style: { "--pire-chart-height": `${height}px` },
|
|
2653
|
+
children: categories.map((category, categoryIndex) => (
|
|
2654
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
|
|
2655
|
+
/* @__PURE__ */ jsxs41("div", { className: "pire-chart-group", children: [
|
|
2656
|
+
/* @__PURE__ */ jsx48("span", { className: "pire-chart-cat", children: category }),
|
|
2657
|
+
/* @__PURE__ */ jsx48("div", { className: "pire-chart-track", children: series.map((one, seriesIndex) => {
|
|
2658
|
+
const value = one.values[categoryIndex];
|
|
2659
|
+
if (value == null) return null;
|
|
2660
|
+
return /* @__PURE__ */ jsxs41(
|
|
2661
|
+
"div",
|
|
2662
|
+
{
|
|
2663
|
+
className: "pire-chart-bar",
|
|
2664
|
+
style: {
|
|
2665
|
+
"--pire-bar-size": sizeOf(value),
|
|
2666
|
+
"--pire-bar-color": seriesColor(one, seriesIndex)
|
|
2667
|
+
},
|
|
2668
|
+
children: [
|
|
2669
|
+
withValues && orientation === "vertical" ? /* @__PURE__ */ jsx48("span", { className: "pire-chart-barval", children: formatValue(value) }) : null,
|
|
2670
|
+
/* @__PURE__ */ jsxs41("span", { className: "pire-chart-tip", role: "presentation", children: [
|
|
2671
|
+
series.length > 1 ? `${one.label}: ` : "",
|
|
2672
|
+
formatValue(value)
|
|
2673
|
+
] })
|
|
2674
|
+
]
|
|
2675
|
+
},
|
|
2676
|
+
one.id
|
|
2677
|
+
);
|
|
2678
|
+
}) }),
|
|
2679
|
+
withValues && orientation === "horizontal" ? /* @__PURE__ */ jsx48("span", { className: "pire-chart-val", children: horizontalLabelFor(categoryIndex) }) : null
|
|
2680
|
+
] }, categoryIndex)
|
|
2681
|
+
))
|
|
2682
|
+
}
|
|
2683
|
+
)
|
|
2684
|
+
}
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
// src/components/data/LineChart.tsx
|
|
2689
|
+
import * as React13 from "react";
|
|
2690
|
+
import { jsx as jsx49, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
2691
|
+
var PLOT_INSET = { top: 10, right: 14, bottom: 24, left: 58 };
|
|
2692
|
+
var MARKER_LIMIT = 20;
|
|
2693
|
+
var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React13.useEffect : React13.useLayoutEffect;
|
|
2694
|
+
function useMeasuredWidth() {
|
|
2695
|
+
const ref = React13.useRef(null);
|
|
2696
|
+
const [width, setWidth] = React13.useState(0);
|
|
2697
|
+
useIsomorphicLayoutEffect2(() => {
|
|
2698
|
+
const element = ref.current;
|
|
2699
|
+
if (!element) return;
|
|
2700
|
+
setWidth(element.getBoundingClientRect().width);
|
|
2701
|
+
const observer = new ResizeObserver(([entry]) => setWidth(entry.contentRect.width));
|
|
2702
|
+
observer.observe(element);
|
|
2703
|
+
return () => observer.disconnect();
|
|
2704
|
+
}, []);
|
|
2705
|
+
return [ref, width];
|
|
2706
|
+
}
|
|
2707
|
+
function LineChart({
|
|
2708
|
+
categories,
|
|
2709
|
+
series: rawSeries,
|
|
2710
|
+
title,
|
|
2711
|
+
description,
|
|
2712
|
+
formatValue = defaultFormatValue,
|
|
2713
|
+
height = 260,
|
|
2714
|
+
emptyState,
|
|
2715
|
+
showDataTable,
|
|
2716
|
+
showArea = false,
|
|
2717
|
+
showMarkers,
|
|
2718
|
+
zoomToData = false,
|
|
2719
|
+
className,
|
|
2720
|
+
style,
|
|
2721
|
+
...rest
|
|
2722
|
+
}) {
|
|
2723
|
+
const label = rest["aria-label"];
|
|
2724
|
+
const msg = usePireMessages();
|
|
2725
|
+
warnOnSlotOverflow(rawSeries, label);
|
|
2726
|
+
const [plotRef, width] = useMeasuredWidth();
|
|
2727
|
+
const series = alignToCategories(rawSeries, categories.length);
|
|
2728
|
+
const hasData = categories.length > 0 && series.length > 0;
|
|
2729
|
+
const withMarkers = showMarkers ?? categories.length <= MARKER_LIMIT;
|
|
2730
|
+
const scale = linearScale(flatValues(series), 4, !zoomToData);
|
|
2731
|
+
const innerWidth = Math.max(0, width - PLOT_INSET.left - PLOT_INSET.right);
|
|
2732
|
+
const innerHeight = Math.max(0, height - PLOT_INSET.top - PLOT_INSET.bottom);
|
|
2733
|
+
const xAt = (index) => PLOT_INSET.left + (categories.length <= 1 ? innerWidth / 2 : index / (categories.length - 1) * innerWidth);
|
|
2734
|
+
const yAt = (value) => PLOT_INSET.top + innerHeight - scalePosition(value, scale) * innerHeight;
|
|
2735
|
+
const pathFor = (values) => {
|
|
2736
|
+
let path = "";
|
|
2737
|
+
let penIsDown = false;
|
|
2738
|
+
values.forEach((value, index) => {
|
|
2739
|
+
if (value == null) {
|
|
2740
|
+
penIsDown = false;
|
|
2741
|
+
return;
|
|
2742
|
+
}
|
|
2743
|
+
path += `${penIsDown ? "L" : "M"}${xAt(index)} ${yAt(value)} `;
|
|
2744
|
+
penIsDown = true;
|
|
2745
|
+
});
|
|
2746
|
+
return path.trim();
|
|
2747
|
+
};
|
|
2748
|
+
const areaFor = (values) => {
|
|
2749
|
+
const present = values.map((value, index) => ({ value, index })).filter((point) => point.value != null);
|
|
2750
|
+
if (present.length < 2) return "";
|
|
2751
|
+
const baseline = PLOT_INSET.top + innerHeight;
|
|
2752
|
+
const line = present.map((point) => `${xAt(point.index)} ${yAt(point.value)}`).join(" L");
|
|
2753
|
+
const last = present[present.length - 1];
|
|
2754
|
+
return `M${xAt(present[0].index)} ${baseline} L${line} L${xAt(last.index)} ${baseline} Z`;
|
|
2755
|
+
};
|
|
2756
|
+
const labelEvery = Math.max(1, Math.ceil(categories.length / Math.max(2, Math.floor(innerWidth / 64))));
|
|
2757
|
+
return /* @__PURE__ */ jsx49(
|
|
2758
|
+
ChartFrame,
|
|
2759
|
+
{
|
|
2760
|
+
label,
|
|
2761
|
+
title,
|
|
2762
|
+
description,
|
|
2763
|
+
categories,
|
|
2764
|
+
series,
|
|
2765
|
+
formatValue,
|
|
2766
|
+
legend: seriesLegend(series),
|
|
2767
|
+
showDataTable,
|
|
2768
|
+
className,
|
|
2769
|
+
style,
|
|
2770
|
+
children: !hasData ? /* @__PURE__ */ jsx49("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs42("div", { className: "pire-chart-lines", ref: plotRef, style: { height }, children: [
|
|
2771
|
+
width > 0 ? /* @__PURE__ */ jsxs42(
|
|
2772
|
+
"svg",
|
|
2773
|
+
{
|
|
2774
|
+
width,
|
|
2775
|
+
height,
|
|
2776
|
+
className: "pire-chart-svg",
|
|
2777
|
+
"aria-hidden": "true",
|
|
2778
|
+
focusable: "false",
|
|
2779
|
+
children: [
|
|
2780
|
+
/* @__PURE__ */ jsx49("g", { className: "pire-chart-grid", children: scale.ticks.map((tick) => /* @__PURE__ */ jsx49(
|
|
2781
|
+
"line",
|
|
2782
|
+
{
|
|
2783
|
+
x1: PLOT_INSET.left,
|
|
2784
|
+
x2: width - PLOT_INSET.right,
|
|
2785
|
+
y1: yAt(tick),
|
|
2786
|
+
y2: yAt(tick)
|
|
2787
|
+
},
|
|
2788
|
+
tick
|
|
2789
|
+
)) }),
|
|
2790
|
+
/* @__PURE__ */ jsxs42("g", { className: "pire-chart-tick", children: [
|
|
2791
|
+
scale.ticks.map((tick) => /* @__PURE__ */ jsx49(
|
|
2792
|
+
"text",
|
|
2793
|
+
{
|
|
2794
|
+
x: PLOT_INSET.left - 8,
|
|
2795
|
+
y: yAt(tick),
|
|
2796
|
+
textAnchor: "end",
|
|
2797
|
+
dominantBaseline: "middle",
|
|
2798
|
+
children: formatValue(tick)
|
|
2799
|
+
},
|
|
2800
|
+
tick
|
|
2801
|
+
)),
|
|
2802
|
+
categories.map((category, index) => index % labelEvery === 0 ? (
|
|
2803
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
|
|
2804
|
+
/* @__PURE__ */ jsx49("text", { x: xAt(index), y: height - 6, textAnchor: "middle", children: category }, index)
|
|
2805
|
+
) : null)
|
|
2806
|
+
] }),
|
|
2807
|
+
showArea && series[0] ? /* @__PURE__ */ jsx49(
|
|
2808
|
+
"path",
|
|
2809
|
+
{
|
|
2810
|
+
d: areaFor(series[0].values),
|
|
2811
|
+
className: "pire-chart-area",
|
|
2812
|
+
style: { fill: seriesColor(series[0], 0) }
|
|
2813
|
+
}
|
|
2814
|
+
) : null,
|
|
2815
|
+
/* @__PURE__ */ jsx49("g", { className: "pire-chart-line", fill: "none", children: series.map((one, index) => /* @__PURE__ */ jsx49("path", { d: pathFor(one.values), stroke: seriesColor(one, index) }, one.id)) }),
|
|
2816
|
+
withMarkers ? /* @__PURE__ */ jsx49("g", { className: "pire-chart-marker", children: series.map((one, seriesIndex) => one.values.map((value, index) => value == null ? null : (
|
|
2817
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: a series is positional — the index is the point's identity, and category labels repeat.
|
|
2818
|
+
/* @__PURE__ */ jsx49(
|
|
2819
|
+
"circle",
|
|
2820
|
+
{
|
|
2821
|
+
cx: xAt(index),
|
|
2822
|
+
cy: yAt(value),
|
|
2823
|
+
r: 4,
|
|
2824
|
+
fill: seriesColor(one, seriesIndex)
|
|
2825
|
+
},
|
|
2826
|
+
`${one.id}-${index}`
|
|
2827
|
+
)
|
|
2828
|
+
))) }) : null
|
|
2829
|
+
]
|
|
2830
|
+
}
|
|
2831
|
+
) : null,
|
|
2832
|
+
/* @__PURE__ */ jsx49(
|
|
2833
|
+
"div",
|
|
2834
|
+
{
|
|
2835
|
+
className: "pire-chart-hover",
|
|
2836
|
+
style: { inset: `${PLOT_INSET.top}px ${PLOT_INSET.right}px ${PLOT_INSET.bottom}px ${PLOT_INSET.left}px` },
|
|
2837
|
+
children: categories.map((category, categoryIndex) => (
|
|
2838
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: categories are positional and repeat legitimately (two quarters both labelled "Q1").
|
|
2839
|
+
/* @__PURE__ */ jsx49("div", { className: "pire-chart-band", children: /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip", role: "presentation", children: [
|
|
2840
|
+
/* @__PURE__ */ jsx49("strong", { children: category }),
|
|
2841
|
+
series.map((one) => {
|
|
2842
|
+
const value = one.values[categoryIndex];
|
|
2843
|
+
return /* @__PURE__ */ jsxs42("span", { className: "pire-chart-tip-row", children: [
|
|
2844
|
+
one.label,
|
|
2845
|
+
": ",
|
|
2846
|
+
value == null ? "No data" : formatValue(value)
|
|
2847
|
+
] }, one.id);
|
|
2848
|
+
})
|
|
2849
|
+
] }) }, categoryIndex)
|
|
2850
|
+
))
|
|
2851
|
+
}
|
|
2852
|
+
)
|
|
2853
|
+
] })
|
|
2854
|
+
}
|
|
2855
|
+
);
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2858
|
+
// src/components/data/DonutChart.tsx
|
|
2859
|
+
import * as React14 from "react";
|
|
2860
|
+
import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
2861
|
+
var SEGMENT_GAP_DEGREES = 1.5;
|
|
2862
|
+
function DonutChart({
|
|
2863
|
+
categories,
|
|
2864
|
+
series,
|
|
2865
|
+
title,
|
|
2866
|
+
description,
|
|
2867
|
+
formatValue = defaultFormatValue,
|
|
2868
|
+
height = 220,
|
|
2869
|
+
emptyState,
|
|
2870
|
+
showDataTable,
|
|
2871
|
+
centerLabel,
|
|
2872
|
+
centerCaption,
|
|
2873
|
+
thickness = 28,
|
|
2874
|
+
className,
|
|
2875
|
+
style,
|
|
2876
|
+
...rest
|
|
2877
|
+
}) {
|
|
2878
|
+
const label = rest["aria-label"];
|
|
2879
|
+
const msg = usePireMessages();
|
|
2880
|
+
const [hoveredIndex, setHoveredIndex] = React14.useState(null);
|
|
2881
|
+
warnOnDonutShape(series, categories.length, label);
|
|
2882
|
+
const values = (series[0]?.values ?? []).slice(0, categories.length);
|
|
2883
|
+
const segments = categories.map((category, index) => ({ category, index, value: values[index] ?? 0 })).filter((segment) => segment.value > 0);
|
|
2884
|
+
const total = segments.reduce((sum, segment) => sum + segment.value, 0);
|
|
2885
|
+
const hasData = segments.length > 0 && total > 0;
|
|
2886
|
+
const size = height;
|
|
2887
|
+
const radius = (size - thickness) / 2;
|
|
2888
|
+
const circumference = 2 * Math.PI * radius;
|
|
2889
|
+
const gapLength = SEGMENT_GAP_DEGREES / 360 * circumference;
|
|
2890
|
+
const legend = segments.map((segment) => ({
|
|
2891
|
+
key: segment.category,
|
|
2892
|
+
label: segment.category,
|
|
2893
|
+
color: colorForSegment(segment.index)
|
|
2894
|
+
}));
|
|
2895
|
+
const hovered = hoveredIndex == null ? null : segments.find((segment) => segment.index === hoveredIndex) ?? null;
|
|
2896
|
+
let arcStart = 0;
|
|
2897
|
+
return /* @__PURE__ */ jsx50(
|
|
2898
|
+
ChartFrame,
|
|
2899
|
+
{
|
|
2900
|
+
label,
|
|
2901
|
+
title,
|
|
2902
|
+
description,
|
|
2903
|
+
categories,
|
|
2904
|
+
series,
|
|
2905
|
+
formatValue,
|
|
2906
|
+
legend,
|
|
2907
|
+
showDataTable,
|
|
2908
|
+
className,
|
|
2909
|
+
style,
|
|
2910
|
+
children: !hasData ? /* @__PURE__ */ jsx50("div", { className: "pire-chart-empty", children: emptyState ?? msg.chartEmpty }) : /* @__PURE__ */ jsxs43("div", { className: "pire-chart-donut", style: { height: size }, children: [
|
|
2911
|
+
/* @__PURE__ */ jsx50(
|
|
2912
|
+
"svg",
|
|
2913
|
+
{
|
|
2914
|
+
width: size,
|
|
2915
|
+
height: size,
|
|
2916
|
+
"aria-hidden": "true",
|
|
2917
|
+
focusable: "false",
|
|
2918
|
+
onMouseLeave: () => setHoveredIndex(null),
|
|
2919
|
+
children: /* @__PURE__ */ jsx50("g", { transform: `rotate(-90 ${size / 2} ${size / 2})`, children: segments.map((segment) => {
|
|
2920
|
+
const arcLength = segment.value / total * circumference;
|
|
2921
|
+
const offset = arcStart;
|
|
2922
|
+
arcStart += arcLength;
|
|
2923
|
+
return (
|
|
2924
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: pointer-only enhancement inside an aria-hidden plot — the arcs carry nothing the data table does not, so there is nothing here for a keyboard to reach.
|
|
2925
|
+
/* @__PURE__ */ jsx50(
|
|
2926
|
+
"circle",
|
|
2927
|
+
{
|
|
2928
|
+
className: "pire-chart-arc",
|
|
2929
|
+
cx: size / 2,
|
|
2930
|
+
cy: size / 2,
|
|
2931
|
+
r: radius,
|
|
2932
|
+
stroke: colorForSegment(segment.index),
|
|
2933
|
+
strokeWidth: thickness,
|
|
2934
|
+
strokeDasharray: `${Math.max(0, arcLength - gapLength)} ${circumference}`,
|
|
2935
|
+
strokeDashoffset: -offset,
|
|
2936
|
+
"data-hovered": hoveredIndex === segment.index ? "true" : void 0,
|
|
2937
|
+
onMouseEnter: () => setHoveredIndex(segment.index)
|
|
2938
|
+
},
|
|
2939
|
+
segment.category
|
|
2940
|
+
)
|
|
2941
|
+
);
|
|
2942
|
+
}) })
|
|
2943
|
+
}
|
|
2944
|
+
),
|
|
2945
|
+
/* @__PURE__ */ jsxs43("div", { className: "pire-chart-donut-center", style: { width: size - thickness * 2 - 8 }, children: [
|
|
2946
|
+
/* @__PURE__ */ jsx50("span", { className: "pire-chart-donut-value", children: hovered ? formatValue(hovered.value) : centerLabel ?? formatValue(total) }),
|
|
2947
|
+
/* @__PURE__ */ jsx50("span", { className: "pire-chart-donut-caption", children: hovered ? hovered.category : centerCaption })
|
|
2948
|
+
] })
|
|
2949
|
+
] })
|
|
2950
|
+
}
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2953
|
+
function colorForSegment(index) {
|
|
2954
|
+
return index < VIZ_SLOT_COUNT ? `var(--viz-${index + 1})` : "var(--viz-other)";
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2462
2957
|
// src/components/data/LinkList.tsx
|
|
2463
2958
|
import { Button as AriaButton12 } from "react-aria-components";
|
|
2464
|
-
import { jsx as
|
|
2959
|
+
import { jsx as jsx51, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
2465
2960
|
function LinkList({ items, onSelect, className, ...rest }) {
|
|
2466
|
-
return /* @__PURE__ */
|
|
2467
|
-
item.icon ? /* @__PURE__ */
|
|
2468
|
-
item.key ? /* @__PURE__ */
|
|
2469
|
-
item.text ? /* @__PURE__ */
|
|
2961
|
+
return /* @__PURE__ */ jsx51("div", { className: cx("pire-linklist", className), role: "list", ...rest, children: items.map((item) => /* @__PURE__ */ jsx51("div", { role: "listitem", className: "pire-linklist-row", children: /* @__PURE__ */ jsxs44(AriaButton12, { className: "pire-linklist-item", onPress: () => onSelect?.(item.id), children: [
|
|
2962
|
+
item.icon ? /* @__PURE__ */ jsx51(Icon, { name: item.icon, size: 16, style: { color: "var(--text-secondary)" } }) : null,
|
|
2963
|
+
item.key ? /* @__PURE__ */ jsx51("span", { className: "pire-linklist-key", children: item.key }) : null,
|
|
2964
|
+
item.text ? /* @__PURE__ */ jsx51("span", { className: "pire-linklist-text", children: item.text }) : null,
|
|
2470
2965
|
item.trailing
|
|
2471
|
-
] }, item.id)) });
|
|
2966
|
+
] }) }, item.id)) });
|
|
2472
2967
|
}
|
|
2473
2968
|
|
|
2474
2969
|
// src/components/layout/PageBand.tsx
|
|
2475
|
-
import { jsx as
|
|
2970
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
2476
2971
|
function PageBand({
|
|
2477
2972
|
surface = "card",
|
|
2478
2973
|
hasBorder = true,
|
|
@@ -2480,7 +2975,7 @@ function PageBand({
|
|
|
2480
2975
|
className,
|
|
2481
2976
|
...rest
|
|
2482
2977
|
}) {
|
|
2483
|
-
return /* @__PURE__ */
|
|
2978
|
+
return /* @__PURE__ */ jsx52(
|
|
2484
2979
|
"div",
|
|
2485
2980
|
{
|
|
2486
2981
|
className: cx("pire-pageband", className),
|
|
@@ -2493,56 +2988,56 @@ function PageBand({
|
|
|
2493
2988
|
}
|
|
2494
2989
|
|
|
2495
2990
|
// src/components/layout/PageHeader.tsx
|
|
2496
|
-
import { jsx as
|
|
2991
|
+
import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
2497
2992
|
function PageHeader({ title, subtitle, actions, className, ...rest }) {
|
|
2498
|
-
return /* @__PURE__ */
|
|
2499
|
-
/* @__PURE__ */
|
|
2500
|
-
/* @__PURE__ */
|
|
2501
|
-
subtitle ? /* @__PURE__ */
|
|
2993
|
+
return /* @__PURE__ */ jsxs45("header", { className: cx("pire-pageheader", className), ...rest, children: [
|
|
2994
|
+
/* @__PURE__ */ jsxs45("div", { style: { minWidth: 0 }, children: [
|
|
2995
|
+
/* @__PURE__ */ jsx53("h1", { className: "pire-pageheader-title", children: title }),
|
|
2996
|
+
subtitle ? /* @__PURE__ */ jsx53("p", { className: "pire-pageheader-sub", children: subtitle }) : null
|
|
2502
2997
|
] }),
|
|
2503
|
-
actions ? /* @__PURE__ */
|
|
2998
|
+
actions ? /* @__PURE__ */ jsx53("div", { className: "pire-pageheader-actions", children: actions }) : null
|
|
2504
2999
|
] });
|
|
2505
3000
|
}
|
|
2506
3001
|
|
|
2507
3002
|
// src/components/layout/SectionHeader.tsx
|
|
2508
|
-
import { jsx as
|
|
3003
|
+
import { jsx as jsx54, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
2509
3004
|
function SectionHeader({ title, meta, actions, className, ...rest }) {
|
|
2510
|
-
return /* @__PURE__ */
|
|
2511
|
-
/* @__PURE__ */
|
|
2512
|
-
meta ? /* @__PURE__ */
|
|
2513
|
-
actions ? /* @__PURE__ */
|
|
3005
|
+
return /* @__PURE__ */ jsxs46("div", { className: cx("pire-sectionhead", className), ...rest, children: [
|
|
3006
|
+
/* @__PURE__ */ jsx54("span", { className: "pire-eyebrow", children: title }),
|
|
3007
|
+
meta ? /* @__PURE__ */ jsx54("span", { style: { font: "var(--type-caption)", color: "var(--text-tertiary)" }, children: meta }) : null,
|
|
3008
|
+
actions ? /* @__PURE__ */ jsx54("div", { className: "pire-sectionhead-actions", children: actions }) : null
|
|
2514
3009
|
] });
|
|
2515
3010
|
}
|
|
2516
3011
|
|
|
2517
3012
|
// src/components/layout/SelectionBar.tsx
|
|
2518
|
-
import { jsx as
|
|
3013
|
+
import { jsx as jsx55, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
2519
3014
|
function SelectionBar({ count, noun = "record", children, actions, className, ...rest }) {
|
|
2520
3015
|
if (!count) return null;
|
|
2521
|
-
return /* @__PURE__ */
|
|
2522
|
-
/* @__PURE__ */
|
|
3016
|
+
return /* @__PURE__ */ jsxs47("div", { className: cx("pire-selectionbar", className), role: "status", "aria-live": "polite", ...rest, children: [
|
|
3017
|
+
/* @__PURE__ */ jsxs47("span", { className: "pire-selectionbar-count", children: [
|
|
2523
3018
|
count.toLocaleString(),
|
|
2524
3019
|
" ",
|
|
2525
3020
|
noun,
|
|
2526
3021
|
count === 1 ? "" : "s",
|
|
2527
3022
|
" selected"
|
|
2528
3023
|
] }),
|
|
2529
|
-
children ? /* @__PURE__ */
|
|
2530
|
-
actions ? /* @__PURE__ */
|
|
3024
|
+
children ? /* @__PURE__ */ jsx55("span", { style: { color: "var(--text-secondary)", font: "var(--type-caption)" }, children }) : null,
|
|
3025
|
+
actions ? /* @__PURE__ */ jsx55("div", { className: "pire-selectionbar-actions", children: actions }) : null
|
|
2531
3026
|
] });
|
|
2532
3027
|
}
|
|
2533
3028
|
|
|
2534
3029
|
// src/components/layout/FooterBar.tsx
|
|
2535
|
-
import { jsx as
|
|
3030
|
+
import { jsx as jsx56, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
2536
3031
|
function FooterBar({ note, actions, children, className, ...rest }) {
|
|
2537
|
-
return /* @__PURE__ */
|
|
2538
|
-
note ? /* @__PURE__ */
|
|
3032
|
+
return /* @__PURE__ */ jsxs48("footer", { className: cx("pire-footerbar", className), ...rest, children: [
|
|
3033
|
+
note ? /* @__PURE__ */ jsx56("span", { className: "pire-footerbar-note", children: note }) : null,
|
|
2539
3034
|
children,
|
|
2540
|
-
actions ? /* @__PURE__ */
|
|
3035
|
+
actions ? /* @__PURE__ */ jsx56("div", { className: "pire-footerbar-actions", children: actions }) : null
|
|
2541
3036
|
] });
|
|
2542
3037
|
}
|
|
2543
3038
|
|
|
2544
3039
|
// src/components/patterns/ConfirmDialog.tsx
|
|
2545
|
-
import { Fragment as Fragment4, jsx as
|
|
3040
|
+
import { Fragment as Fragment4, jsx as jsx57, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
2546
3041
|
function ConfirmDialog({
|
|
2547
3042
|
isOpen,
|
|
2548
3043
|
title,
|
|
@@ -2556,7 +3051,7 @@ function ConfirmDialog({
|
|
|
2556
3051
|
onConfirm,
|
|
2557
3052
|
onCancel
|
|
2558
3053
|
}) {
|
|
2559
|
-
return /* @__PURE__ */
|
|
3054
|
+
return /* @__PURE__ */ jsxs49(
|
|
2560
3055
|
Dialog,
|
|
2561
3056
|
{
|
|
2562
3057
|
isOpen,
|
|
@@ -2566,12 +3061,12 @@ function ConfirmDialog({
|
|
|
2566
3061
|
onClose: onCancel,
|
|
2567
3062
|
isDismissable: !isBusy,
|
|
2568
3063
|
showClose: false,
|
|
2569
|
-
footer: /* @__PURE__ */
|
|
2570
|
-
/* @__PURE__ */
|
|
2571
|
-
/* @__PURE__ */
|
|
3064
|
+
footer: /* @__PURE__ */ jsxs49(Fragment4, { children: [
|
|
3065
|
+
/* @__PURE__ */ jsx57(Button, { variant: "tertiary", isDisabled: isBusy, onPress: onCancel, children: cancelLabel }),
|
|
3066
|
+
/* @__PURE__ */ jsx57(Button, { variant: tone === "danger" ? "danger" : "primary", isDisabled: isBusy, onPress: onConfirm, children: isBusy ? "Working\u2026" : confirmLabel })
|
|
2572
3067
|
] }),
|
|
2573
3068
|
children: [
|
|
2574
|
-
consequence ? /* @__PURE__ */
|
|
3069
|
+
consequence ? /* @__PURE__ */ jsx57(InlineMessage, { kind: tone === "danger" ? "error" : "warning", style: { marginBottom: children ? "var(--sp-3)" : 0 }, children: consequence }) : null,
|
|
2575
3070
|
children
|
|
2576
3071
|
]
|
|
2577
3072
|
}
|
|
@@ -2580,10 +3075,10 @@ function ConfirmDialog({
|
|
|
2580
3075
|
|
|
2581
3076
|
// src/components/patterns/SidePanel.tsx
|
|
2582
3077
|
import { ModalOverlay as ModalOverlay2, Modal as Modal2, Dialog as AriaDialog4, Heading as Heading5 } from "react-aria-components";
|
|
2583
|
-
import { jsx as
|
|
3078
|
+
import { jsx as jsx58, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
2584
3079
|
function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onClose, className }) {
|
|
2585
3080
|
const msg = usePireMessages();
|
|
2586
|
-
return /* @__PURE__ */
|
|
3081
|
+
return /* @__PURE__ */ jsx58(
|
|
2587
3082
|
ModalOverlay2,
|
|
2588
3083
|
{
|
|
2589
3084
|
className: "pire-sidepanel-overlay",
|
|
@@ -2592,36 +3087,36 @@ function SidePanel({ isOpen, title, subtitle, width = 400, children, footer, onC
|
|
|
2592
3087
|
onOpenChange: (o) => {
|
|
2593
3088
|
if (!o) onClose?.();
|
|
2594
3089
|
},
|
|
2595
|
-
children: /* @__PURE__ */
|
|
2596
|
-
/* @__PURE__ */
|
|
2597
|
-
/* @__PURE__ */
|
|
2598
|
-
/* @__PURE__ */
|
|
2599
|
-
subtitle ? /* @__PURE__ */
|
|
3090
|
+
children: /* @__PURE__ */ jsx58(Modal2, { className: cx("pire-sidepanel", className), style: { width }, children: /* @__PURE__ */ jsxs50(AriaDialog4, { className: "pire-dialog", style: { height: "100%" }, children: [
|
|
3091
|
+
/* @__PURE__ */ jsxs50("header", { className: "pire-dialog-head", children: [
|
|
3092
|
+
/* @__PURE__ */ jsxs50("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3093
|
+
/* @__PURE__ */ jsx58(Heading5, { slot: "title", className: "pire-dialog-title", children: title }),
|
|
3094
|
+
subtitle ? /* @__PURE__ */ jsx58("p", { className: "pire-dialog-sub", style: { margin: 0 }, children: subtitle }) : null
|
|
2600
3095
|
] }),
|
|
2601
|
-
/* @__PURE__ */
|
|
3096
|
+
/* @__PURE__ */ jsx58(IconButton, { icon: "x", label: msg.sidePanelClose, size: "sm", onPress: onClose })
|
|
2602
3097
|
] }),
|
|
2603
|
-
/* @__PURE__ */
|
|
2604
|
-
footer ? /* @__PURE__ */
|
|
3098
|
+
/* @__PURE__ */ jsx58("div", { className: "pire-dialog-body", style: { flex: 1 }, children }),
|
|
3099
|
+
footer ? /* @__PURE__ */ jsx58("footer", { className: "pire-dialog-foot", children: footer }) : null
|
|
2605
3100
|
] }) })
|
|
2606
3101
|
}
|
|
2607
3102
|
);
|
|
2608
3103
|
}
|
|
2609
3104
|
|
|
2610
3105
|
// src/components/patterns/EmptyState.tsx
|
|
2611
|
-
import { jsx as
|
|
3106
|
+
import { jsx as jsx59, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
2612
3107
|
function EmptyState({ icon = "file-text", title, action, compact, children, className, ...rest }) {
|
|
2613
|
-
return /* @__PURE__ */
|
|
2614
|
-
/* @__PURE__ */
|
|
2615
|
-
title ? /* @__PURE__ */
|
|
2616
|
-
children ? /* @__PURE__ */
|
|
3108
|
+
return /* @__PURE__ */ jsxs51("div", { className: cx("pire-empty", className), "data-compact": compact ? "true" : void 0, ...rest, children: [
|
|
3109
|
+
/* @__PURE__ */ jsx59(Icon, { name: icon, size: 24, className: "pire-empty-icon" }),
|
|
3110
|
+
title ? /* @__PURE__ */ jsx59("p", { className: "pire-empty-title", style: { margin: 0 }, children: title }) : null,
|
|
3111
|
+
children ? /* @__PURE__ */ jsx59("p", { className: "pire-empty-body", style: { margin: 0 }, children }) : null,
|
|
2617
3112
|
action
|
|
2618
3113
|
] });
|
|
2619
3114
|
}
|
|
2620
3115
|
|
|
2621
3116
|
// src/components/patterns/FileDropZone.tsx
|
|
2622
|
-
import * as
|
|
3117
|
+
import * as React15 from "react";
|
|
2623
3118
|
import { DropZone, FileTrigger as FileTrigger2, isFileDropItem } from "react-aria-components";
|
|
2624
|
-
import { jsx as
|
|
3119
|
+
import { jsx as jsx60, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
2625
3120
|
var isImage2 = (file) => file.type.startsWith("image/");
|
|
2626
3121
|
function FileDropZone({
|
|
2627
3122
|
label,
|
|
@@ -2647,10 +3142,10 @@ function FileDropZone({
|
|
|
2647
3142
|
style
|
|
2648
3143
|
}) {
|
|
2649
3144
|
const msg = usePireMessages();
|
|
2650
|
-
const [uncontrolled, setUncontrolled] =
|
|
3145
|
+
const [uncontrolled, setUncontrolled] = React15.useState(defaultValue ?? []);
|
|
2651
3146
|
const files = value ?? uncontrolled;
|
|
2652
|
-
const created =
|
|
2653
|
-
|
|
3147
|
+
const created = React15.useRef([]);
|
|
3148
|
+
React15.useEffect(() => () => {
|
|
2654
3149
|
for (const url of created.current) URL.revokeObjectURL(url);
|
|
2655
3150
|
}, []);
|
|
2656
3151
|
const commit = (next) => {
|
|
@@ -2670,12 +3165,12 @@ function FileDropZone({
|
|
|
2670
3165
|
commit(allowsMultiple ? [...files, ...wrapped] : wrapped.slice(0, 1));
|
|
2671
3166
|
};
|
|
2672
3167
|
const remove = (target) => commit(files.filter((f) => f.file !== target));
|
|
2673
|
-
return /* @__PURE__ */
|
|
2674
|
-
label ? /* @__PURE__ */
|
|
3168
|
+
return /* @__PURE__ */ jsxs52("div", { className: cx("pire-field", className), style, "data-full-width": String(fullWidth), children: [
|
|
3169
|
+
label ? /* @__PURE__ */ jsxs52("span", { className: "pire-field-label", children: [
|
|
2675
3170
|
label,
|
|
2676
|
-
isRequired ? /* @__PURE__ */
|
|
3171
|
+
isRequired ? /* @__PURE__ */ jsx60("span", { className: "pire-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2677
3172
|
] }) : null,
|
|
2678
|
-
/* @__PURE__ */
|
|
3173
|
+
/* @__PURE__ */ jsxs52(
|
|
2679
3174
|
DropZone,
|
|
2680
3175
|
{
|
|
2681
3176
|
className: "pire-dropzone",
|
|
@@ -2688,25 +3183,25 @@ function FileDropZone({
|
|
|
2688
3183
|
accept(dropped);
|
|
2689
3184
|
},
|
|
2690
3185
|
children: [
|
|
2691
|
-
/* @__PURE__ */
|
|
2692
|
-
/* @__PURE__ */
|
|
2693
|
-
/* @__PURE__ */
|
|
3186
|
+
/* @__PURE__ */ jsx60(Icon, { name: "download", size: 24, className: "pire-dropzone-icon" }),
|
|
3187
|
+
/* @__PURE__ */ jsx60("span", { className: "pire-dropzone-prompt", children: promptLabel ?? msg.fileDropZonePrompt }),
|
|
3188
|
+
/* @__PURE__ */ jsx60(
|
|
2694
3189
|
FileTrigger2,
|
|
2695
3190
|
{
|
|
2696
3191
|
acceptedFileTypes,
|
|
2697
3192
|
allowsMultiple,
|
|
2698
3193
|
onSelect: (list) => accept(list ? [...list] : []),
|
|
2699
|
-
children: /* @__PURE__ */
|
|
3194
|
+
children: /* @__PURE__ */ jsx60(Button, { variant: "secondary", isDisabled: isDisabled || isReadOnly, children: msg.fileUploadChoose })
|
|
2700
3195
|
}
|
|
2701
3196
|
)
|
|
2702
3197
|
]
|
|
2703
3198
|
}
|
|
2704
3199
|
),
|
|
2705
|
-
files.length ? /* @__PURE__ */
|
|
2706
|
-
previewUrl ? /* @__PURE__ */
|
|
2707
|
-
/* @__PURE__ */
|
|
2708
|
-
/* @__PURE__ */
|
|
2709
|
-
isDisabled || isReadOnly ? null : /* @__PURE__ */
|
|
3200
|
+
files.length ? /* @__PURE__ */ jsx60("ul", { className: "pire-fileupload-list", children: files.map(({ file, previewUrl }) => /* @__PURE__ */ jsxs52("li", { className: "pire-fileupload-item", children: [
|
|
3201
|
+
previewUrl ? /* @__PURE__ */ jsx60("img", { className: "pire-fileupload-thumb", src: previewUrl, alt: "" }) : /* @__PURE__ */ jsx60(Icon, { name: "file-text", size: 16, className: "pire-fileupload-icon" }),
|
|
3202
|
+
/* @__PURE__ */ jsx60("span", { className: "pire-fileupload-name", children: file.name }),
|
|
3203
|
+
/* @__PURE__ */ jsx60("span", { className: "pire-fileupload-size", children: formatFileSize(file.size) }),
|
|
3204
|
+
isDisabled || isReadOnly ? null : /* @__PURE__ */ jsx60(
|
|
2710
3205
|
IconButton,
|
|
2711
3206
|
{
|
|
2712
3207
|
icon: "x",
|
|
@@ -2716,9 +3211,9 @@ function FileDropZone({
|
|
|
2716
3211
|
}
|
|
2717
3212
|
)
|
|
2718
3213
|
] }, `${file.name}-${file.size}-${file.lastModified}`)) }) : null,
|
|
2719
|
-
uploadProgress != null ? /* @__PURE__ */
|
|
2720
|
-
description ? /* @__PURE__ */
|
|
2721
|
-
isInvalid && errorMessage ? /* @__PURE__ */
|
|
3214
|
+
uploadProgress != null ? /* @__PURE__ */ jsx60(ProgressBar, { value: uploadProgress, label: msg.fileUploadUploading }) : null,
|
|
3215
|
+
description ? /* @__PURE__ */ jsx60("span", { className: "pire-field-hint", children: description }) : null,
|
|
3216
|
+
isInvalid && errorMessage ? /* @__PURE__ */ jsx60("span", { className: "pire-field-error", children: errorMessage }) : null
|
|
2722
3217
|
] });
|
|
2723
3218
|
}
|
|
2724
3219
|
|
|
@@ -2727,6 +3222,7 @@ import { DialogTrigger, MenuTrigger as MenuTrigger2, SubmenuTrigger, Popover as
|
|
|
2727
3222
|
export {
|
|
2728
3223
|
Avatar,
|
|
2729
3224
|
Badge,
|
|
3225
|
+
BarChart,
|
|
2730
3226
|
Breadcrumb,
|
|
2731
3227
|
Button,
|
|
2732
3228
|
Card,
|
|
@@ -2739,6 +3235,7 @@ export {
|
|
|
2739
3235
|
DescriptionList,
|
|
2740
3236
|
Dialog,
|
|
2741
3237
|
DialogTrigger,
|
|
3238
|
+
DonutChart,
|
|
2742
3239
|
EmptyState,
|
|
2743
3240
|
FileDropZone,
|
|
2744
3241
|
FileUpload,
|
|
@@ -2752,6 +3249,7 @@ export {
|
|
|
2752
3249
|
InlineMessage,
|
|
2753
3250
|
Input,
|
|
2754
3251
|
KpiTile,
|
|
3252
|
+
LineChart,
|
|
2755
3253
|
Link,
|
|
2756
3254
|
LinkList,
|
|
2757
3255
|
Menu,
|
|
@@ -2792,6 +3290,7 @@ export {
|
|
|
2792
3290
|
Toast,
|
|
2793
3291
|
ToastProvider,
|
|
2794
3292
|
Tooltip,
|
|
3293
|
+
VIZ_SLOT_COUNT,
|
|
2795
3294
|
ValueHelpDialog,
|
|
2796
3295
|
ValueHelpField,
|
|
2797
3296
|
configureIcons,
|