@apotech-os/ui-sdk 2.5.0 → 2.7.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/index.cjs +273 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +275 -124
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -14,8 +14,8 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
14
14
|
import { useReactTable, getFilteredRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
|
|
15
15
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
16
16
|
import { fr } from 'date-fns/locale/fr';
|
|
17
|
-
import { DayPicker } from 'react-day-picker';
|
|
18
|
-
import { subYears,
|
|
17
|
+
import { DayPicker, labelDayButton } from 'react-day-picker';
|
|
18
|
+
import { subYears, differenceInCalendarDays, subDays, parse, format, startOfYear, subMonths, startOfQuarter, endOfMonth, startOfMonth } from 'date-fns';
|
|
19
19
|
import { BarChart as BarChart$1, Bar, LineChart as LineChart$1, Line, AreaChart as AreaChart$1, Area, FunnelChart as FunnelChart$1, Funnel, Cell, LabelList, ResponsiveContainer, Tooltip, Legend, CartesianGrid, XAxis, YAxis } from 'recharts';
|
|
20
20
|
|
|
21
21
|
// src/cn.ts
|
|
@@ -1079,8 +1079,15 @@ function DataTable({
|
|
|
1079
1079
|
TableRow,
|
|
1080
1080
|
{
|
|
1081
1081
|
"data-state": selected.has(row.id) ? "selected" : void 0,
|
|
1082
|
-
className: onRowClick ? "cursor-pointer" : "hover:bg-transparent",
|
|
1082
|
+
className: onRowClick ? "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset" : "hover:bg-transparent",
|
|
1083
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
1083
1084
|
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
1085
|
+
onKeyDown: onRowClick ? (event) => {
|
|
1086
|
+
if (event.target !== event.currentTarget) return;
|
|
1087
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
1088
|
+
event.preventDefault();
|
|
1089
|
+
onRowClick(row.original);
|
|
1090
|
+
} : void 0,
|
|
1084
1091
|
children: [
|
|
1085
1092
|
selectable && /* @__PURE__ */ jsx(TableCell, { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx(
|
|
1086
1093
|
Checkbox,
|
|
@@ -1354,20 +1361,20 @@ var PERIOD_PRESETS = [
|
|
|
1354
1361
|
{ key: "all", label: "Tout l'historique" }
|
|
1355
1362
|
];
|
|
1356
1363
|
var COMPARE_LABELS = {
|
|
1357
|
-
none: "
|
|
1364
|
+
none: "Ne pas comparer",
|
|
1358
1365
|
previous_period: "P\xE9riode pr\xE9c\xE9dente",
|
|
1359
1366
|
previous_year: "Ann\xE9e pr\xE9c\xE9dente",
|
|
1360
|
-
custom: "
|
|
1367
|
+
custom: "P\xE9riode personnalis\xE9e"
|
|
1368
|
+
};
|
|
1369
|
+
var COMPARE_SHORT_LABELS = {
|
|
1370
|
+
none: "",
|
|
1371
|
+
previous_period: "p\xE9riode pr\xE9c.",
|
|
1372
|
+
previous_year: "N-1",
|
|
1373
|
+
custom: "p\xE9riode choisie"
|
|
1361
1374
|
};
|
|
1362
1375
|
var DAY_FORMAT = "yyyy-MM-dd";
|
|
1363
1376
|
var toDay = (date) => format(date, DAY_FORMAT);
|
|
1364
1377
|
var fromDay = (day) => parse(day, DAY_FORMAT, /* @__PURE__ */ new Date());
|
|
1365
|
-
var CALENDAR_UNIT = {
|
|
1366
|
-
thisMonth: "month",
|
|
1367
|
-
lastMonth: "month",
|
|
1368
|
-
thisQuarter: "quarter",
|
|
1369
|
-
thisYear: "year"
|
|
1370
|
-
};
|
|
1371
1378
|
function presetRange(preset, today) {
|
|
1372
1379
|
const day = toDay(today);
|
|
1373
1380
|
switch (preset) {
|
|
@@ -1384,17 +1391,17 @@ function presetRange(preset, today) {
|
|
|
1384
1391
|
case "last90":
|
|
1385
1392
|
return { from: toDay(subDays(today, 89)), to: day };
|
|
1386
1393
|
case "thisMonth":
|
|
1387
|
-
return { from: toDay(startOfMonth(today)), to:
|
|
1394
|
+
return { from: toDay(startOfMonth(today)), to: day };
|
|
1388
1395
|
case "lastMonth": {
|
|
1389
1396
|
const previous = subMonths(today, 1);
|
|
1390
1397
|
return { from: toDay(startOfMonth(previous)), to: toDay(endOfMonth(previous)) };
|
|
1391
1398
|
}
|
|
1392
1399
|
case "thisQuarter":
|
|
1393
|
-
return { from: toDay(startOfQuarter(today)), to:
|
|
1400
|
+
return { from: toDay(startOfQuarter(today)), to: day };
|
|
1394
1401
|
case "last12Months":
|
|
1395
|
-
return { from: toDay(
|
|
1402
|
+
return { from: toDay(subMonths(today, 12)), to: day };
|
|
1396
1403
|
case "thisYear":
|
|
1397
|
-
return { from: toDay(startOfYear(today)), to:
|
|
1404
|
+
return { from: toDay(startOfYear(today)), to: day };
|
|
1398
1405
|
case "all":
|
|
1399
1406
|
return { to: day };
|
|
1400
1407
|
case "custom":
|
|
@@ -1408,19 +1415,6 @@ function comparisonRange(preset, range, compare2) {
|
|
|
1408
1415
|
if (compare2 === "previous_year") {
|
|
1409
1416
|
return { from: toDay(subYears(from, 1)), to: toDay(subYears(to, 1)) };
|
|
1410
1417
|
}
|
|
1411
|
-
const unit = CALENDAR_UNIT[preset];
|
|
1412
|
-
if (unit === "month") {
|
|
1413
|
-
const previous = subMonths(from, 1);
|
|
1414
|
-
return { from: toDay(startOfMonth(previous)), to: toDay(endOfMonth(previous)) };
|
|
1415
|
-
}
|
|
1416
|
-
if (unit === "quarter") {
|
|
1417
|
-
const previous = addQuarters(from, -1);
|
|
1418
|
-
return { from: toDay(startOfQuarter(previous)), to: toDay(endOfQuarter(previous)) };
|
|
1419
|
-
}
|
|
1420
|
-
if (unit === "year") {
|
|
1421
|
-
const previous = subYears(from, 1);
|
|
1422
|
-
return { from: toDay(startOfYear(previous)), to: toDay(endOfYear(previous)) };
|
|
1423
|
-
}
|
|
1424
1418
|
const length = differenceInCalendarDays(to, from) + 1;
|
|
1425
1419
|
return { from: toDay(subDays(from, length)), to: toDay(subDays(to, length)) };
|
|
1426
1420
|
}
|
|
@@ -1510,12 +1504,20 @@ var DAY_PICKER_CLASS_NAMES = {
|
|
|
1510
1504
|
today: "font-semibold text-primary",
|
|
1511
1505
|
outside: "text-muted-foreground/50",
|
|
1512
1506
|
disabled: "opacity-40",
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1507
|
+
// A cell DayPicker decided not to fill still occupies the grid, and still
|
|
1508
|
+
// matches the range modifiers below — without this it would show a stretch of
|
|
1509
|
+
// painted band with no number in it. `invisible`, not `hidden`: the six-week
|
|
1510
|
+
// grid keeps its height either way.
|
|
1511
|
+
hidden: "invisible"
|
|
1512
|
+
};
|
|
1513
|
+
var DAY_MODIFIER_CLASS_NAMES = {
|
|
1514
|
+
period_middle: "bg-primary/15",
|
|
1515
|
+
period_start: "rounded-l-md [&_button]:bg-primary [&_button]:text-primary-foreground [&_button]:hover:bg-primary",
|
|
1516
|
+
period_end: "rounded-r-md [&_button]:bg-primary [&_button]:text-primary-foreground [&_button]:hover:bg-primary",
|
|
1517
|
+
compare_middle: "bg-chart-2/30",
|
|
1518
|
+
compare_start: "rounded-l-md bg-chart-2/30 [&_button]:ring-2 [&_button]:ring-inset [&_button]:ring-chart-2 [&_button]:font-semibold [&_button]:text-chart-2",
|
|
1519
|
+
compare_end: "rounded-r-md bg-chart-2/30 [&_button]:ring-2 [&_button]:ring-inset [&_button]:ring-chart-2 [&_button]:font-semibold [&_button]:text-chart-2"
|
|
1517
1520
|
};
|
|
1518
|
-
var COMPARE_MODIFIER_CLASS = "bg-chart-2/25 ring-1 ring-inset ring-chart-2/40";
|
|
1519
1521
|
function draftOf(value) {
|
|
1520
1522
|
return {
|
|
1521
1523
|
preset: value.preset,
|
|
@@ -1547,16 +1549,38 @@ function previewCompare(draft) {
|
|
|
1547
1549
|
function activeCompare(draft) {
|
|
1548
1550
|
return draft.preset === "all" ? "none" : draft.compare;
|
|
1549
1551
|
}
|
|
1550
|
-
function
|
|
1551
|
-
if (!
|
|
1552
|
-
|
|
1553
|
-
return isDay(
|
|
1552
|
+
function bandOf(from, to) {
|
|
1553
|
+
if (!isDay(from)) return void 0;
|
|
1554
|
+
const start = fromDay(from);
|
|
1555
|
+
return { from: start, to: isDay(to) ? fromDay(to) : start };
|
|
1556
|
+
}
|
|
1557
|
+
var inBand = (band, date) => band !== void 0 && date >= band.from && date <= band.to;
|
|
1558
|
+
var isBound = (date, bound) => bound !== void 0 && date.getTime() === bound.getTime();
|
|
1559
|
+
function compareBandOf(draft) {
|
|
1560
|
+
const active = activeCompare(draft);
|
|
1561
|
+
if (active === "none") return void 0;
|
|
1562
|
+
if (active === "custom") return bandOf(draft.compareFrom, draft.compareTo);
|
|
1563
|
+
const derived = previewCompare(draft);
|
|
1564
|
+
return derived?.from ? { from: fromDay(derived.from), to: fromDay(derived.to) } : void 0;
|
|
1565
|
+
}
|
|
1566
|
+
function anchorMonth(range, visible, today) {
|
|
1567
|
+
const from = isDay(range.from) ? fromDay(range.from) : void 0;
|
|
1568
|
+
const to = isDay(range.to) ? fromDay(range.to) : void 0;
|
|
1569
|
+
if (visible === 2) return from ?? to;
|
|
1570
|
+
if (!to) return from;
|
|
1571
|
+
if (to <= today) return to;
|
|
1572
|
+
return from && from <= today ? today : from ?? today;
|
|
1573
|
+
}
|
|
1574
|
+
function selectionOf(from, to) {
|
|
1575
|
+
if (!isDay(from)) return void 0;
|
|
1576
|
+
return { from: fromDay(from), to: isDay(to) ? fromDay(to) : void 0 };
|
|
1554
1577
|
}
|
|
1555
1578
|
function DateRangeCompare({
|
|
1556
1579
|
value,
|
|
1557
1580
|
onChange,
|
|
1558
1581
|
comparable = true,
|
|
1559
1582
|
presets = PERIOD_PRESETS,
|
|
1583
|
+
months = 1,
|
|
1560
1584
|
align = "start",
|
|
1561
1585
|
disabled,
|
|
1562
1586
|
className
|
|
@@ -1564,44 +1588,76 @@ function DateRangeCompare({
|
|
|
1564
1588
|
const [open, setOpen] = React2.useState(false);
|
|
1565
1589
|
const [draft, setDraft] = React2.useState(() => draftOf(value));
|
|
1566
1590
|
const [month, setMonth] = React2.useState(void 0);
|
|
1567
|
-
const [
|
|
1568
|
-
const
|
|
1569
|
-
|
|
1570
|
-
|
|
1591
|
+
const [autoMonths, setAutoMonths] = React2.useState(1);
|
|
1592
|
+
const [target, setTarget] = React2.useState("period");
|
|
1593
|
+
const [today, setToday] = React2.useState(() => /* @__PURE__ */ new Date());
|
|
1594
|
+
const visibleMonths = months === "auto" ? autoMonths : months;
|
|
1595
|
+
const showRange = (range2, at = today) => {
|
|
1596
|
+
const next = months === "auto" ? spansTwoMonths(range2) ? 2 : 1 : months;
|
|
1597
|
+
setAutoMonths(next);
|
|
1598
|
+
setMonth(anchorMonth(range2, next, at));
|
|
1571
1599
|
};
|
|
1572
1600
|
const openPanel = () => {
|
|
1601
|
+
const now = /* @__PURE__ */ new Date();
|
|
1602
|
+
setToday(now);
|
|
1573
1603
|
setDraft(draftOf(value));
|
|
1574
|
-
|
|
1604
|
+
setTarget("period");
|
|
1605
|
+
showRange(value.range, now);
|
|
1575
1606
|
setOpen(true);
|
|
1576
1607
|
};
|
|
1577
|
-
const
|
|
1578
|
-
|
|
1579
|
-
|
|
1608
|
+
const range = rangeOf(draft);
|
|
1609
|
+
const compareRange = previewCompare(draft);
|
|
1610
|
+
const compareEditable = comparable && activeCompare(draft) === "custom";
|
|
1611
|
+
const activeTarget = compareEditable ? target : "period";
|
|
1612
|
+
const periodBand = bandOf(draft.from, draft.to);
|
|
1613
|
+
const compareBand = compareBandOf(draft);
|
|
1614
|
+
const emit = (candidate) => {
|
|
1615
|
+
const complete = rangeOf(candidate);
|
|
1616
|
+
if (!complete) return false;
|
|
1617
|
+
onChange(
|
|
1618
|
+
makePeriod(candidate.preset, complete, activeCompare(candidate), customCompareOf(candidate))
|
|
1619
|
+
);
|
|
1620
|
+
setOpen(false);
|
|
1621
|
+
return true;
|
|
1622
|
+
};
|
|
1623
|
+
const apply = () => emit(draft);
|
|
1624
|
+
const pickPreset = (preset, commit) => {
|
|
1625
|
+
const resolved = periodFromPreset(preset, today, activeCompare(draft));
|
|
1626
|
+
const next = {
|
|
1580
1627
|
...draftOf(resolved),
|
|
1581
1628
|
// The rail changes the period, not the comparison: the mode the user chose
|
|
1582
1629
|
// survives, and `activeCompare` decides whether it can apply here.
|
|
1583
1630
|
compare: draft.compare,
|
|
1584
1631
|
compareFrom: draft.compareFrom,
|
|
1585
1632
|
compareTo: draft.compareTo
|
|
1586
|
-
}
|
|
1633
|
+
};
|
|
1634
|
+
setDraft(next);
|
|
1635
|
+
setTarget("period");
|
|
1587
1636
|
showRange(resolved.range);
|
|
1637
|
+
if (!comparable && commit) emit(next);
|
|
1588
1638
|
};
|
|
1589
1639
|
const pickDays = (selected) => {
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
}
|
|
1640
|
+
const from = selected?.from ? toDay(selected.from) : void 0;
|
|
1641
|
+
const to = selected?.to ? toDay(selected.to) : void 0;
|
|
1642
|
+
if (activeTarget === "compare") {
|
|
1643
|
+
setDraft({ ...draft, compare: "custom", compareFrom: from, compareTo: to });
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
setDraft({ ...draft, preset: "custom", from, to });
|
|
1596
1647
|
};
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1648
|
+
const chooseCompare = (mode) => {
|
|
1649
|
+
const next = { ...draft, compare: mode };
|
|
1650
|
+
setDraft(next);
|
|
1651
|
+
setTarget(mode === "custom" ? "compare" : "period");
|
|
1652
|
+
const shown = mode === "custom" ? customCompareOf(next) : range;
|
|
1653
|
+
if (shown) showRange(shown);
|
|
1654
|
+
};
|
|
1655
|
+
const focusTarget = (next) => {
|
|
1656
|
+
setTarget(next);
|
|
1657
|
+
const shown = next === "compare" ? customCompareOf(draft) : range;
|
|
1658
|
+
if (shown) showRange(shown);
|
|
1603
1659
|
};
|
|
1604
|
-
const
|
|
1660
|
+
const footer = activeTarget === "compare" ? compareRange ? formatRange(compareRange) : "P\xE9riode de comparaison \xE0 choisir" : range ? `${formatRange(range)}${compareRange ? ` vs ${formatRange(compareRange)}` : ""}` : "Date de fin \xE0 choisir";
|
|
1605
1661
|
return /* @__PURE__ */ jsx(
|
|
1606
1662
|
Popover,
|
|
1607
1663
|
{
|
|
@@ -1609,42 +1665,81 @@ function DateRangeCompare({
|
|
|
1609
1665
|
onOpenChange: (next) => next ? openPanel() : setOpen(false),
|
|
1610
1666
|
align,
|
|
1611
1667
|
className: cn("w-auto p-0", className),
|
|
1612
|
-
trigger: /* @__PURE__ */
|
|
1613
|
-
|
|
1614
|
-
|
|
1668
|
+
trigger: /* @__PURE__ */ jsxs(Button, { variant: "outline", disabled, children: [
|
|
1669
|
+
/* @__PURE__ */ jsx(IconCalendar, { className: "size-4 text-muted-foreground" }),
|
|
1670
|
+
/* @__PURE__ */ jsx("span", { children: formatPeriod(value) }),
|
|
1671
|
+
value.compare !== "none" && value.compareRange !== void 0 && /* @__PURE__ */ jsxs("span", { className: "rounded-md bg-chart-2/15 px-1.5 py-0.5 text-xs font-medium text-chart-2", children: [
|
|
1672
|
+
"vs ",
|
|
1673
|
+
COMPARE_SHORT_LABELS[value.compare]
|
|
1674
|
+
] }),
|
|
1675
|
+
/* @__PURE__ */ jsx(IconChevronDown, { className: "size-4 text-muted-foreground" })
|
|
1676
|
+
] }),
|
|
1677
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[80vh] items-stretch", children: [
|
|
1678
|
+
(presets.length > 0 || comparable) && /* @__PURE__ */ jsxs("div", { className: "flex w-48 shrink-0 flex-col border-r", children: [
|
|
1679
|
+
presets.length > 0 && /* @__PURE__ */ jsx(
|
|
1680
|
+
PresetRail,
|
|
1681
|
+
{
|
|
1682
|
+
presets,
|
|
1683
|
+
selected: draft.preset,
|
|
1684
|
+
onSelect: pickPreset,
|
|
1685
|
+
className: "min-h-0 flex-1 overflow-y-auto p-2"
|
|
1686
|
+
}
|
|
1687
|
+
),
|
|
1688
|
+
comparable && /* @__PURE__ */ jsx(
|
|
1689
|
+
CompareSection,
|
|
1690
|
+
{
|
|
1691
|
+
draft,
|
|
1692
|
+
compareRange,
|
|
1693
|
+
onModeChange: chooseCompare
|
|
1694
|
+
}
|
|
1695
|
+
)
|
|
1696
|
+
] }),
|
|
1615
1697
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1698
|
+
comparable && /* @__PURE__ */ jsx(
|
|
1699
|
+
TargetPills,
|
|
1700
|
+
{
|
|
1701
|
+
target: activeTarget,
|
|
1702
|
+
onSelect: focusTarget,
|
|
1703
|
+
compareEditable
|
|
1704
|
+
}
|
|
1705
|
+
),
|
|
1616
1706
|
/* @__PURE__ */ jsx("div", { className: "relative p-3", children: /* @__PURE__ */ jsx(
|
|
1617
1707
|
DayPicker,
|
|
1618
1708
|
{
|
|
1619
1709
|
mode: "range",
|
|
1620
1710
|
locale: fr,
|
|
1621
1711
|
weekStartsOn: 1,
|
|
1622
|
-
numberOfMonths:
|
|
1712
|
+
numberOfMonths: visibleMonths,
|
|
1623
1713
|
month,
|
|
1624
1714
|
onMonthChange: setMonth,
|
|
1625
|
-
|
|
1715
|
+
today,
|
|
1716
|
+
disabled: { after: today },
|
|
1717
|
+
fixedWeeks: true,
|
|
1718
|
+
showOutsideDays: visibleMonths === 1,
|
|
1719
|
+
selected: activeTarget === "compare" ? selectionOf(draft.compareFrom, draft.compareTo) : selectionOf(draft.from, draft.to),
|
|
1626
1720
|
onSelect: pickDays,
|
|
1627
1721
|
modifiers: {
|
|
1628
|
-
|
|
1722
|
+
period_middle: periodBand ? [{ from: periodBand.from, to: periodBand.to }] : [],
|
|
1723
|
+
period_start: periodBand ? [periodBand.from] : [],
|
|
1724
|
+
period_end: periodBand ? [periodBand.to] : [],
|
|
1725
|
+
// The period wins any cell both ranges claim.
|
|
1726
|
+
compare_middle: (date) => inBand(compareBand, date) && !inBand(periodBand, date),
|
|
1727
|
+
compare_start: (date) => isBound(date, compareBand?.from) && !inBand(periodBand, date),
|
|
1728
|
+
compare_end: (date) => isBound(date, compareBand?.to) && !inBand(periodBand, date)
|
|
1629
1729
|
},
|
|
1630
|
-
modifiersClassNames:
|
|
1631
|
-
classNames: DAY_PICKER_CLASS_NAMES
|
|
1730
|
+
modifiersClassNames: DAY_MODIFIER_CLASS_NAMES,
|
|
1731
|
+
classNames: DAY_PICKER_CLASS_NAMES,
|
|
1732
|
+
"aria-label": activeTarget === "compare" ? "Calendrier \u2014 s\xE9lection de la comparaison" : "Calendrier \u2014 s\xE9lection de la p\xE9riode",
|
|
1733
|
+
labels: {
|
|
1734
|
+
// Suffixed rather than replaced: which range a click lands in is
|
|
1735
|
+
// the one thing a screen reader cannot get from the grid, and the
|
|
1736
|
+
// default label still carries the date and its state.
|
|
1737
|
+
labelDayButton: (date, modifiers, options, dateLib) => `${labelDayButton(date, modifiers, options, dateLib)} \u2014 ${activeTarget === "compare" ? "comparaison" : "p\xE9riode"}`
|
|
1738
|
+
}
|
|
1632
1739
|
}
|
|
1633
1740
|
) }),
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
{
|
|
1637
|
-
draft,
|
|
1638
|
-
compareRange,
|
|
1639
|
-
onModeChange: (compare2) => setDraft({ ...draft, compare: compare2 }),
|
|
1640
|
-
onCustomChange: (from, to) => setDraft({ ...draft, compareFrom: from, compareTo: to })
|
|
1641
|
-
}
|
|
1642
|
-
),
|
|
1643
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 border-t px-3 py-2", children: [
|
|
1644
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
1645
|
-
range ? formatRange(range) : "Choisissez une date de fin",
|
|
1646
|
-
compareRange && ` vs ${formatRange(compareRange)}`
|
|
1647
|
-
] }),
|
|
1741
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between gap-4 border-t px-3 py-2", children: [
|
|
1742
|
+
/* @__PURE__ */ jsx("p", { role: "status", "aria-live": "polite", className: "text-xs text-muted-foreground", children: footer }),
|
|
1648
1743
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1649
1744
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => setOpen(false), children: "Annuler" }),
|
|
1650
1745
|
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: apply, disabled: !range, children: "Appliquer" })
|
|
@@ -1665,6 +1760,7 @@ function DateRangePicker({ value, onChange, className, disabled }) {
|
|
|
1665
1760
|
},
|
|
1666
1761
|
comparable: false,
|
|
1667
1762
|
presets: [],
|
|
1763
|
+
months: "auto",
|
|
1668
1764
|
disabled,
|
|
1669
1765
|
className
|
|
1670
1766
|
}
|
|
@@ -1673,7 +1769,8 @@ function DateRangePicker({ value, onChange, className, disabled }) {
|
|
|
1673
1769
|
function PresetRail({
|
|
1674
1770
|
presets,
|
|
1675
1771
|
selected,
|
|
1676
|
-
onSelect
|
|
1772
|
+
onSelect,
|
|
1773
|
+
className
|
|
1677
1774
|
}) {
|
|
1678
1775
|
const refs = React2.useRef([]);
|
|
1679
1776
|
const activeIndex = Math.max(
|
|
@@ -1683,7 +1780,7 @@ function PresetRail({
|
|
|
1683
1780
|
const moveTo = (index) => {
|
|
1684
1781
|
const next = (index + presets.length) % presets.length;
|
|
1685
1782
|
refs.current[next]?.focus();
|
|
1686
|
-
onSelect(presets[next].key);
|
|
1783
|
+
onSelect(presets[next].key, false);
|
|
1687
1784
|
};
|
|
1688
1785
|
const onKeyDown = (event, index) => {
|
|
1689
1786
|
const step = { ArrowDown: 1, ArrowRight: 1, ArrowUp: -1, ArrowLeft: -1 }[event.key];
|
|
@@ -1702,7 +1799,7 @@ function PresetRail({
|
|
|
1702
1799
|
{
|
|
1703
1800
|
role: "radiogroup",
|
|
1704
1801
|
"aria-label": "P\xE9riode pr\xE9d\xE9finie",
|
|
1705
|
-
className: "flex
|
|
1802
|
+
className: cn("flex flex-col gap-0.5", className),
|
|
1706
1803
|
children: presets.map((preset, index) => /* @__PURE__ */ jsx(
|
|
1707
1804
|
"button",
|
|
1708
1805
|
{
|
|
@@ -1714,9 +1811,9 @@ function PresetRail({
|
|
|
1714
1811
|
"aria-checked": preset.key === selected,
|
|
1715
1812
|
tabIndex: index === activeIndex ? 0 : -1,
|
|
1716
1813
|
onKeyDown: (event) => onKeyDown(event, index),
|
|
1717
|
-
onClick: () => onSelect(preset.key),
|
|
1814
|
+
onClick: () => onSelect(preset.key, true),
|
|
1718
1815
|
className: cn(
|
|
1719
|
-
"rounded px-3 py-1.5 text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1816
|
+
"shrink-0 rounded px-3 py-1.5 text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1720
1817
|
preset.key === selected ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
1721
1818
|
),
|
|
1722
1819
|
children: preset.label
|
|
@@ -1726,17 +1823,62 @@ function PresetRail({
|
|
|
1726
1823
|
}
|
|
1727
1824
|
);
|
|
1728
1825
|
}
|
|
1826
|
+
var TARGETS = [
|
|
1827
|
+
{ key: "period", label: "P\xE9riode", swatch: "bg-primary" },
|
|
1828
|
+
{ key: "compare", label: "Comparaison", swatch: "ring-2 ring-inset ring-chart-2" }
|
|
1829
|
+
];
|
|
1830
|
+
function TargetPills({
|
|
1831
|
+
target,
|
|
1832
|
+
onSelect,
|
|
1833
|
+
compareEditable
|
|
1834
|
+
}) {
|
|
1835
|
+
return /* @__PURE__ */ jsx(
|
|
1836
|
+
"div",
|
|
1837
|
+
{
|
|
1838
|
+
role: "radiogroup",
|
|
1839
|
+
"aria-label": "Cible de la s\xE9lection",
|
|
1840
|
+
className: "flex items-center gap-1 border-b px-3 py-2",
|
|
1841
|
+
children: TARGETS.map((entry) => {
|
|
1842
|
+
const enabled = entry.key === "period" || compareEditable;
|
|
1843
|
+
return /* @__PURE__ */ jsxs(
|
|
1844
|
+
"button",
|
|
1845
|
+
{
|
|
1846
|
+
type: "button",
|
|
1847
|
+
role: "radio",
|
|
1848
|
+
"aria-checked": target === entry.key,
|
|
1849
|
+
disabled: !enabled,
|
|
1850
|
+
tabIndex: target === entry.key ? 0 : -1,
|
|
1851
|
+
onKeyDown: (event) => {
|
|
1852
|
+
if (!["ArrowDown", "ArrowRight", "ArrowUp", "ArrowLeft"].includes(event.key)) return;
|
|
1853
|
+
event.preventDefault();
|
|
1854
|
+
if (compareEditable) onSelect(target === "period" ? "compare" : "period");
|
|
1855
|
+
},
|
|
1856
|
+
onClick: () => onSelect(entry.key),
|
|
1857
|
+
className: cn(
|
|
1858
|
+
"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-40",
|
|
1859
|
+
target === entry.key ? "border-border bg-muted font-medium text-foreground" : "border-border text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
1860
|
+
),
|
|
1861
|
+
children: [
|
|
1862
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("size-2.5 rounded-sm", entry.swatch) }),
|
|
1863
|
+
entry.label
|
|
1864
|
+
]
|
|
1865
|
+
},
|
|
1866
|
+
entry.key
|
|
1867
|
+
);
|
|
1868
|
+
})
|
|
1869
|
+
}
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
1729
1872
|
function CompareSection({
|
|
1730
1873
|
draft,
|
|
1731
1874
|
compareRange,
|
|
1732
|
-
onModeChange
|
|
1733
|
-
onCustomChange
|
|
1875
|
+
onModeChange
|
|
1734
1876
|
}) {
|
|
1735
1877
|
const derivable = draft.preset !== "all";
|
|
1736
1878
|
const active = activeCompare(draft);
|
|
1737
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
1738
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: "Comparer \xE0" }),
|
|
1739
|
-
|
|
1879
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 border-t p-2", children: [
|
|
1880
|
+
/* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-xs font-medium text-muted-foreground", children: "Comparer \xE0" }),
|
|
1881
|
+
COMPARE_MODES.map((mode) => /* @__PURE__ */ jsx(
|
|
1740
1882
|
"button",
|
|
1741
1883
|
{
|
|
1742
1884
|
type: "button",
|
|
@@ -1744,44 +1886,53 @@ function CompareSection({
|
|
|
1744
1886
|
disabled: mode !== "none" && !derivable,
|
|
1745
1887
|
onClick: () => onModeChange(mode),
|
|
1746
1888
|
className: cn(
|
|
1747
|
-
"
|
|
1748
|
-
active === mode ? "
|
|
1889
|
+
"shrink-0 rounded px-3 py-1.5 text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-40",
|
|
1890
|
+
active === mode ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
1749
1891
|
),
|
|
1750
1892
|
children: COMPARE_LABELS[mode]
|
|
1751
1893
|
},
|
|
1752
1894
|
mode
|
|
1753
|
-
))
|
|
1754
|
-
active
|
|
1755
|
-
// one grid and two ranges to fill, nothing on screen would say which one
|
|
1756
|
-
// a click is about to change.
|
|
1757
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1758
|
-
/* @__PURE__ */ jsx(
|
|
1759
|
-
"input",
|
|
1760
|
-
{
|
|
1761
|
-
type: "date",
|
|
1762
|
-
"aria-label": "D\xE9but de la comparaison",
|
|
1763
|
-
value: draft.compareFrom ?? "",
|
|
1764
|
-
max: draft.compareTo,
|
|
1765
|
-
onChange: (event) => onCustomChange(event.target.value || void 0, draft.compareTo),
|
|
1766
|
-
className: "h-8 rounded-md border border-input bg-transparent px-2 text-sm"
|
|
1767
|
-
}
|
|
1768
|
-
),
|
|
1769
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "\u2192" }),
|
|
1770
|
-
/* @__PURE__ */ jsx(
|
|
1771
|
-
"input",
|
|
1772
|
-
{
|
|
1773
|
-
type: "date",
|
|
1774
|
-
"aria-label": "Fin de la comparaison",
|
|
1775
|
-
value: draft.compareTo ?? "",
|
|
1776
|
-
min: draft.compareFrom,
|
|
1777
|
-
onChange: (event) => onCustomChange(draft.compareFrom, event.target.value || void 0),
|
|
1778
|
-
className: "h-8 rounded-md border border-input bg-transparent px-2 text-sm"
|
|
1779
|
-
}
|
|
1780
|
-
)
|
|
1781
|
-
] }),
|
|
1782
|
-
compareRange && active !== "custom" && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: formatRange(compareRange) })
|
|
1895
|
+
)),
|
|
1896
|
+
compareRange && active !== "custom" && /* @__PURE__ */ jsx("p", { className: "px-3 pt-1 text-xs text-muted-foreground", children: formatRange(compareRange) })
|
|
1783
1897
|
] });
|
|
1784
1898
|
}
|
|
1899
|
+
function IconCalendar({ className }) {
|
|
1900
|
+
return /* @__PURE__ */ jsxs(
|
|
1901
|
+
"svg",
|
|
1902
|
+
{
|
|
1903
|
+
className,
|
|
1904
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1905
|
+
viewBox: "0 0 24 24",
|
|
1906
|
+
fill: "none",
|
|
1907
|
+
stroke: "currentColor",
|
|
1908
|
+
strokeWidth: "2",
|
|
1909
|
+
strokeLinecap: "round",
|
|
1910
|
+
strokeLinejoin: "round",
|
|
1911
|
+
"aria-hidden": "true",
|
|
1912
|
+
children: [
|
|
1913
|
+
/* @__PURE__ */ jsx("path", { d: "M8 2v4M16 2v4M3 10h18" }),
|
|
1914
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "4", rx: "2" })
|
|
1915
|
+
]
|
|
1916
|
+
}
|
|
1917
|
+
);
|
|
1918
|
+
}
|
|
1919
|
+
function IconChevronDown({ className }) {
|
|
1920
|
+
return /* @__PURE__ */ jsx(
|
|
1921
|
+
"svg",
|
|
1922
|
+
{
|
|
1923
|
+
className,
|
|
1924
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1925
|
+
viewBox: "0 0 24 24",
|
|
1926
|
+
fill: "none",
|
|
1927
|
+
stroke: "currentColor",
|
|
1928
|
+
strokeWidth: "2",
|
|
1929
|
+
strokeLinecap: "round",
|
|
1930
|
+
strokeLinejoin: "round",
|
|
1931
|
+
"aria-hidden": "true",
|
|
1932
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
1933
|
+
}
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1785
1936
|
var CHART_COLORS = [
|
|
1786
1937
|
"var(--chart-1)",
|
|
1787
1938
|
"var(--chart-2)",
|
|
@@ -2202,6 +2353,6 @@ function Tooltip2({ label, children, side = "top", className }) {
|
|
|
2202
2353
|
] });
|
|
2203
2354
|
}
|
|
2204
2355
|
|
|
2205
|
-
export { AppApiProvider, AppContextProvider, AppInvokeError, AreaChart, Badge, BarChart, Button, COMPARE_LABELS, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CopyButton, DataTable, DateRangeCompare, DateRangePicker, DropdownMenu, FunnelChart, Input, KpiCard, LineChart, Link, Modal, PERIOD_PRESETS, Popover, Select, SidePanel, Spinner, StackedBarChart, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ToastProvider, Tooltip2 as Tooltip, badgeVariants, buttonVariants, cn, comparisonRange, copyToClipboard, downloadBlob, downloadCsv, formatPeriod, formatRange, makePeriod, periodFromPreset, relativeDelta, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings, useToast };
|
|
2356
|
+
export { AppApiProvider, AppContextProvider, AppInvokeError, AreaChart, Badge, BarChart, Button, COMPARE_LABELS, COMPARE_SHORT_LABELS, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CopyButton, DataTable, DateRangeCompare, DateRangePicker, DropdownMenu, FunnelChart, Input, KpiCard, LineChart, Link, Modal, PERIOD_PRESETS, Popover, Select, SidePanel, Spinner, StackedBarChart, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ToastProvider, Tooltip2 as Tooltip, badgeVariants, buttonVariants, cn, comparisonRange, copyToClipboard, downloadBlob, downloadCsv, formatPeriod, formatRange, makePeriod, periodFromPreset, relativeDelta, toCsv, useAppApi, useAppContext, useAppRun, useAppRuns, useAppSettings, useToast };
|
|
2206
2357
|
//# sourceMappingURL=index.js.map
|
|
2207
2358
|
//# sourceMappingURL=index.js.map
|