@flowselections/floriday-voorraad 1.0.150 → 1.0.154

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.
Files changed (141) hide show
  1. package/dist-lib/components/fs-ui/DataTable.d.ts +42 -0
  2. package/dist-lib/components/fs-ui/DataTable.d.ts.map +1 -0
  3. package/dist-lib/components/fs-ui/DataTable.js +68 -0
  4. package/dist-lib/components/fs-ui/EmptyState.d.ts +9 -0
  5. package/dist-lib/components/fs-ui/EmptyState.d.ts.map +1 -0
  6. package/dist-lib/components/fs-ui/EmptyState.js +5 -0
  7. package/dist-lib/components/fs-ui/FilterChips.d.ts +13 -0
  8. package/dist-lib/components/fs-ui/FilterChips.d.ts.map +1 -0
  9. package/dist-lib/components/fs-ui/FilterChips.js +8 -0
  10. package/dist-lib/components/fs-ui/FilterPanel.d.ts +19 -0
  11. package/dist-lib/components/fs-ui/FilterPanel.d.ts.map +1 -0
  12. package/dist-lib/components/fs-ui/FilterPanel.js +10 -0
  13. package/dist-lib/components/fs-ui/FiltersButton.d.ts +6 -0
  14. package/dist-lib/components/fs-ui/FiltersButton.d.ts.map +1 -0
  15. package/dist-lib/components/fs-ui/FiltersButton.js +7 -0
  16. package/dist-lib/components/fs-ui/HeaderButton.d.ts +16 -0
  17. package/dist-lib/components/fs-ui/HeaderButton.d.ts.map +1 -0
  18. package/dist-lib/components/fs-ui/HeaderButton.js +10 -0
  19. package/dist-lib/components/fs-ui/HoverTip.d.ts +15 -0
  20. package/dist-lib/components/fs-ui/HoverTip.d.ts.map +1 -0
  21. package/dist-lib/components/fs-ui/HoverTip.js +24 -0
  22. package/dist-lib/components/fs-ui/InlineAlert.d.ts +12 -0
  23. package/dist-lib/components/fs-ui/InlineAlert.d.ts.map +1 -0
  24. package/dist-lib/components/fs-ui/InlineAlert.js +15 -0
  25. package/dist-lib/components/fs-ui/KpiRow.d.ts +10 -0
  26. package/dist-lib/components/fs-ui/KpiRow.d.ts.map +1 -0
  27. package/dist-lib/components/fs-ui/KpiRow.js +8 -0
  28. package/dist-lib/components/fs-ui/KpiTile.d.ts +21 -0
  29. package/dist-lib/components/fs-ui/KpiTile.d.ts.map +1 -0
  30. package/dist-lib/components/fs-ui/KpiTile.js +40 -0
  31. package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts +13 -0
  32. package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts.map +1 -0
  33. package/dist-lib/components/fs-ui/MobilePrimaryAction.js +10 -0
  34. package/dist-lib/components/fs-ui/NoticeBar.d.ts +10 -0
  35. package/dist-lib/components/fs-ui/NoticeBar.d.ts.map +1 -0
  36. package/dist-lib/components/fs-ui/NoticeBar.js +16 -0
  37. package/dist-lib/components/fs-ui/PageHeader.d.ts +19 -0
  38. package/dist-lib/components/fs-ui/PageHeader.d.ts.map +1 -0
  39. package/dist-lib/components/fs-ui/PageHeader.js +9 -0
  40. package/dist-lib/components/fs-ui/Pagination.d.ts +10 -0
  41. package/dist-lib/components/fs-ui/Pagination.d.ts.map +1 -0
  42. package/dist-lib/components/fs-ui/Pagination.js +10 -0
  43. package/dist-lib/components/fs-ui/PillTabs.d.ts +17 -0
  44. package/dist-lib/components/fs-ui/PillTabs.d.ts.map +1 -0
  45. package/dist-lib/components/fs-ui/PillTabs.js +28 -0
  46. package/dist-lib/components/fs-ui/RowMenu.d.ts +13 -0
  47. package/dist-lib/components/fs-ui/RowMenu.d.ts.map +1 -0
  48. package/dist-lib/components/fs-ui/RowMenu.js +7 -0
  49. package/dist-lib/components/fs-ui/SearchInput.d.ts +11 -0
  50. package/dist-lib/components/fs-ui/SearchInput.d.ts.map +1 -0
  51. package/dist-lib/components/fs-ui/SearchInput.js +55 -0
  52. package/dist-lib/components/fs-ui/ShortcutHelp.d.ts +8 -0
  53. package/dist-lib/components/fs-ui/ShortcutHelp.d.ts.map +1 -0
  54. package/dist-lib/components/fs-ui/ShortcutHelp.js +6 -0
  55. package/dist-lib/components/fs-ui/StatusIcon.d.ts +13 -0
  56. package/dist-lib/components/fs-ui/StatusIcon.d.ts.map +1 -0
  57. package/dist-lib/components/fs-ui/StatusIcon.js +15 -0
  58. package/dist-lib/components/fs-ui/TableSkeleton.d.ts +7 -0
  59. package/dist-lib/components/fs-ui/TableSkeleton.d.ts.map +1 -0
  60. package/dist-lib/components/fs-ui/TableSkeleton.js +6 -0
  61. package/dist-lib/components/fs-ui/Toolbar.d.ts +12 -0
  62. package/dist-lib/components/fs-ui/Toolbar.d.ts.map +1 -0
  63. package/dist-lib/components/fs-ui/Toolbar.js +8 -0
  64. package/dist-lib/components/fs-ui/UpdatedAt.d.ts +10 -0
  65. package/dist-lib/components/fs-ui/UpdatedAt.d.ts.map +1 -0
  66. package/dist-lib/components/fs-ui/UpdatedAt.js +18 -0
  67. package/dist-lib/components/voorraad/ArtikelCompositionCard.d.ts.map +1 -1
  68. package/dist-lib/components/voorraad/ArtikelCompositionCard.js +46 -15
  69. package/dist-lib/components/voorraad/ArtikelWizard.js +4 -4
  70. package/dist-lib/components/voorraad/FloridayConnectionNotice.d.ts +7 -6
  71. package/dist-lib/components/voorraad/FloridayConnectionNotice.d.ts.map +1 -1
  72. package/dist-lib/components/voorraad/FloridayConnectionNotice.js +15 -12
  73. package/dist-lib/components/voorraad/FustenPage.d.ts.map +1 -1
  74. package/dist-lib/components/voorraad/FustenPage.js +92 -26
  75. package/dist-lib/components/voorraad/NieuwArtikelPage.d.ts.map +1 -1
  76. package/dist-lib/components/voorraad/NieuwArtikelPage.js +2 -1
  77. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts +3 -1
  78. package/dist-lib/components/voorraad/OrderHistoryCard.d.ts.map +1 -1
  79. package/dist-lib/components/voorraad/OrderHistoryCard.js +26 -50
  80. package/dist-lib/components/voorraad/PublicatiesPage.d.ts.map +1 -1
  81. package/dist-lib/components/voorraad/PublicatiesPage.js +42 -36
  82. package/dist-lib/components/voorraad/Sneltoetsen.d.ts +14 -0
  83. package/dist-lib/components/voorraad/Sneltoetsen.d.ts.map +1 -0
  84. package/dist-lib/components/voorraad/Sneltoetsen.js +44 -0
  85. package/dist-lib/components/voorraad/StockIntegrityAlert.d.ts +42 -1
  86. package/dist-lib/components/voorraad/StockIntegrityAlert.d.ts.map +1 -1
  87. package/dist-lib/components/voorraad/StockIntegrityAlert.js +38 -7
  88. package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
  89. package/dist-lib/components/voorraad/StockMutationHistoryCard.js +10 -46
  90. package/dist-lib/components/voorraad/StockPushMonitor.js +2 -2
  91. package/dist-lib/components/voorraad/TelmomentButton.d.ts +5 -1
  92. package/dist-lib/components/voorraad/TelmomentButton.d.ts.map +1 -1
  93. package/dist-lib/components/voorraad/TelmomentButton.js +13 -6
  94. package/dist-lib/components/voorraad/ValidationOverviewTable.d.ts.map +1 -1
  95. package/dist-lib/components/voorraad/ValidationOverviewTable.js +11 -40
  96. package/dist-lib/components/voorraad/ValidationPage.d.ts +1 -0
  97. package/dist-lib/components/voorraad/ValidationPage.d.ts.map +1 -1
  98. package/dist-lib/components/voorraad/ValidationPage.js +33 -5
  99. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts +4 -1
  100. package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts.map +1 -1
  101. package/dist-lib/components/voorraad/VoorraadBeheerCard.js +26 -5
  102. package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
  103. package/dist-lib/components/voorraad/VoorraadPage.js +67 -38
  104. package/dist-lib/components/voorraad/VoorraadSturingCard.js +1 -1
  105. package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts.map +1 -1
  106. package/dist-lib/components/voorraad/artikel/ArtikelPagina.js +42 -19
  107. package/dist-lib/components/voorraad/lijst/ImporteerKnop.d.ts.map +1 -1
  108. package/dist-lib/components/voorraad/lijst/ImporteerKnop.js +1 -1
  109. package/dist-lib/components/voorraad/lijst/LijstExportKnop.d.ts.map +1 -1
  110. package/dist-lib/components/voorraad/lijst/LijstExportKnop.js +1 -1
  111. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts +8 -2
  112. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts.map +1 -1
  113. package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.js +62 -27
  114. package/dist-lib/hooks/useLocalTradeItems.d.ts +14 -0
  115. package/dist-lib/hooks/useLocalTradeItems.d.ts.map +1 -1
  116. package/dist-lib/hooks/useLocalTradeItems.js +5 -3
  117. package/dist-lib/hooks/useTradeItemStock.d.ts.map +1 -1
  118. package/dist-lib/hooks/useTradeItemStock.js +6 -3
  119. package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
  120. package/dist-lib/hooks/useVoorraadData.js +16 -8
  121. package/dist-lib/hooks/useVoorraadLijst.d.ts +10 -0
  122. package/dist-lib/hooks/useVoorraadLijst.d.ts.map +1 -1
  123. package/dist-lib/hooks/useVoorraadLijst.js +22 -4
  124. package/dist-lib/integrations/supabase/types.d.ts +85 -0
  125. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  126. package/dist-lib/lib/alle-rijen.d.ts +15 -0
  127. package/dist-lib/lib/alle-rijen.d.ts.map +1 -0
  128. package/dist-lib/lib/alle-rijen.js +17 -0
  129. package/dist-lib/lib/db-error-message.d.ts.map +1 -1
  130. package/dist-lib/lib/db-error-message.js +3 -1
  131. package/dist-lib/lib/labels.d.ts +42 -0
  132. package/dist-lib/lib/labels.d.ts.map +1 -0
  133. package/dist-lib/lib/labels.js +152 -0
  134. package/dist-lib/lib/notatie.d.ts +4 -0
  135. package/dist-lib/lib/notatie.d.ts.map +1 -0
  136. package/dist-lib/lib/notatie.js +18 -0
  137. package/dist-lib/lib/voorraad-lijst.d.ts +2 -0
  138. package/dist-lib/lib/voorraad-lijst.d.ts.map +1 -1
  139. package/dist-lib/lib/voorraad-lijst.js +14 -3
  140. package/package.json +2 -1
  141. package/sql/floriday-voorraad-schema.sql +315 -39
@@ -0,0 +1,42 @@
1
+ import { type ReactNode } from "react";
2
+ export interface DataColumn<R> {
3
+ key: string;
4
+ header: ReactNode;
5
+ /** Vaste breedte (bijv. "12%" of "96px"); kolommen schalen evenredig mee. */
6
+ width?: string;
7
+ /** Sorteersleutel; zonder sleutel is de kolom niet sorteerbaar. */
8
+ sortKey?: string;
9
+ render: (row: R) => ReactNode;
10
+ className?: string;
11
+ }
12
+ /**
13
+ * Tabel naar de stijlgids: één afgerond vlak, kolomkoppen blijven zichtbaar,
14
+ * vaste kolombreedtes, alles links, rij 60 px, hover lichtgrijs, actieve rij met
15
+ * groene streep links, open-knop bij hover. J/K = volgende/vorige rij, Enter = openen
16
+ * (nooit tijdens typen). Op mobiel (onder 768 px) een kaartenlijst als `mobileCard` is gegeven.
17
+ */
18
+ export declare function DataTable<R>({ columns, rows, getId, loading, sort, onSort, onOpen, openLabel, selection, empty, mobileCard, rowActions, skeletonRows, keyboard, }: {
19
+ columns: DataColumn<R>[];
20
+ rows: R[];
21
+ getId: (r: R) => string;
22
+ loading?: boolean;
23
+ sort?: {
24
+ key: string;
25
+ asc: boolean;
26
+ };
27
+ onSort?: (key: string) => void;
28
+ onOpen?: (r: R) => void;
29
+ openLabel?: string;
30
+ selection?: {
31
+ selected: Set<string>;
32
+ onToggle: (id: string) => void;
33
+ onToggleAll: (ids: string[]) => void;
34
+ label: (r: R) => string;
35
+ };
36
+ empty?: ReactNode;
37
+ mobileCard?: (r: R) => ReactNode;
38
+ rowActions?: (r: R) => ReactNode;
39
+ skeletonRows?: number;
40
+ keyboard?: boolean;
41
+ }): import("react").JSX.Element;
42
+ //# sourceMappingURL=DataTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/DataTable.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKpE,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,CAAC;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAC3B,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,IAAI,EACJ,MAAM,EACN,MAAM,EACN,SAAoB,EACpB,SAAS,EACT,KAAK,EACL,UAAU,EACV,UAAU,EACV,YAAgB,EAChB,QAAe,GAChB,EAAE;IACD,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;KAAE,CAAC;IACrI,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,+BAoJA"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { ArrowDown, ArrowUp, ChevronRight } from "lucide-react";
4
+ import { TableSkeleton } from "./TableSkeleton.js";
5
+ import { isTypen } from "./SearchInput.js";
6
+ /**
7
+ * Tabel naar de stijlgids: één afgerond vlak, kolomkoppen blijven zichtbaar,
8
+ * vaste kolombreedtes, alles links, rij 60 px, hover lichtgrijs, actieve rij met
9
+ * groene streep links, open-knop bij hover. J/K = volgende/vorige rij, Enter = openen
10
+ * (nooit tijdens typen). Op mobiel (onder 768 px) een kaartenlijst als `mobileCard` is gegeven.
11
+ */
12
+ export function DataTable({ columns, rows, getId, loading, sort, onSort, onOpen, openLabel = "Openen", selection, empty, mobileCard, rowActions, skeletonRows = 8, keyboard = true, }) {
13
+ const [actief, setActief] = useState(-1);
14
+ const rowsRef = useRef(rows);
15
+ rowsRef.current = rows;
16
+ const ids = rows.map(getId);
17
+ useEffect(() => setActief(-1), [ids.join("|")]); // eslint-disable-line react-hooks/exhaustive-deps
18
+ useEffect(() => {
19
+ if (!keyboard)
20
+ return;
21
+ const h = (e) => {
22
+ if (e.metaKey || e.ctrlKey || e.altKey || isTypen(e.target))
23
+ return;
24
+ if (document.querySelector("[role=dialog]"))
25
+ return;
26
+ const n = rowsRef.current.length;
27
+ if (!n)
28
+ return;
29
+ if (e.key === "j" || e.key === "J") {
30
+ e.preventDefault();
31
+ setActief((i) => Math.min(n - 1, i + 1));
32
+ }
33
+ else if (e.key === "k" || e.key === "K") {
34
+ e.preventDefault();
35
+ setActief((i) => Math.max(0, i - 1));
36
+ }
37
+ else if (e.key === "Enter" && onOpen) {
38
+ setActief((i) => { if (i >= 0 && i < n)
39
+ onOpen(rowsRef.current[i]); return i; });
40
+ }
41
+ else if (e.key === "Escape")
42
+ setActief(-1);
43
+ };
44
+ window.addEventListener("keydown", h);
45
+ return () => window.removeEventListener("keydown", h);
46
+ }, [keyboard, onOpen]);
47
+ useEffect(() => {
48
+ if (actief < 0)
49
+ return;
50
+ document.querySelector(`[data-rij="${actief}"]`)?.scrollIntoView({ block: "nearest" });
51
+ }, [actief]);
52
+ const allesGekozen = selection ? ids.length > 0 && ids.every((id) => selection.selected.has(id)) : false;
53
+ const kolomBreedtes = [selection ? "36px" : undefined, ...columns.map((c) => c.width), onOpen || rowActions ? "96px" : undefined].filter((_, i, a) => i > 0 || a[0] !== undefined);
54
+ const leeg = !loading && rows.length === 0;
55
+ const eersteLaad = loading && rows.length === 0;
56
+ return (_jsxs("div", { className: "overflow-hidden rounded-xl border border-border bg-card shadow-sm", children: [(_jsxs("ul", { className: "divide-y divide-border md:hidden", children: [eersteLaad && Array.from({ length: 5 }).map((_, i) => (_jsxs("li", { className: "space-y-2 p-4", "aria-hidden": true, children: [_jsx("div", { className: "h-4 w-2/3 animate-pulse rounded bg-muted" }), _jsx("div", { className: "h-3 w-1/2 animate-pulse rounded bg-muted" })] }, i))), rows.map((r) => (_jsx("li", { className: "transition-opacity duration-150 " + (loading ? "opacity-60" : ""), children: _jsx("div", { role: onOpen ? "button" : undefined, tabIndex: onOpen ? 0 : undefined, onClick: () => onOpen?.(r), onKeyDown: (e) => { if (e.key === "Enter" && onOpen)
57
+ onOpen(r); }, className: "block min-h-11 p-4 active:bg-muted/60", children: mobileCard ? mobileCard(r) : (_jsx("div", { className: "space-y-1", children: columns.map((c, ci) => (_jsxs("div", { className: ci === 0 ? "min-w-0 text-sm font-medium" : "flex min-w-0 items-baseline justify-between gap-3 text-xs", children: [ci > 0 && _jsx("span", { className: "shrink-0 text-muted-foreground", children: c.header }), _jsx("div", { className: "min-w-0 truncate", children: c.render(r) })] }, c.key))) })) }) }, getId(r)))), leeg && _jsx("li", { children: empty })] })), _jsx("div", { className: "hidden max-h-[calc(100dvh-7rem)] overflow-auto md:block xl:max-h-none xl:overflow-visible", children: _jsxs("table", { className: "w-full [&_thead_th]:h-10 [&_thead_th]:text-[11px] [&_thead_th]:font-semibold [&_thead_th]:uppercase [&_thead_th]:tracking-wide [&_thead_th]:text-muted-foreground min-w-[900px] table-fixed caption-bottom text-sm [&_thead_th]:sticky [&_thead_th]:top-0 [&_thead_th]:z-10 [&_thead_th]:bg-card [&_tbody_tr]:transition-colors", children: [_jsxs("colgroup", { children: [selection && _jsx("col", { style: { width: "36px" } }), columns.map((c) => _jsx("col", { style: c.width ? { width: c.width } : undefined }, c.key)), (onOpen || rowActions) && _jsx("col", { style: { width: "96px" } })] }), _jsx("thead", { children: _jsxs("tr", { className: "border-b border-border", children: [selection && (_jsx("th", { className: "px-2 text-left align-middle", children: _jsx("input", { type: "checkbox", className: "h-4 w-4 rounded accent-primary", checked: allesGekozen, onChange: () => selection.onToggleAll(ids), "aria-label": "Alles op deze pagina kiezen" }) })), columns.map((c) => {
58
+ const act = sort && c.sortKey && sort.key === c.sortKey;
59
+ return (_jsx("th", { scope: "col", className: "px-2 text-left align-middle", "aria-sort": act ? (sort.asc ? "ascending" : "descending") : c.sortKey ? "none" : undefined, children: c.sortKey && onSort ? (_jsxs("button", { type: "button", onClick: () => onSort(c.sortKey), className: "inline-flex items-center gap-1 uppercase tracking-wide hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm " + (act ? "text-foreground" : ""), children: [c.header, act && (sort.asc ? _jsx(ArrowUp, { className: "h-3 w-3" }) : _jsx(ArrowDown, { className: "h-3 w-3" }))] })) : c.header }, c.key));
60
+ }), (onOpen || rowActions) && _jsx("th", { className: "px-2", children: _jsx("span", { className: "sr-only", children: "Acties" }) })] }) }), _jsxs("tbody", { children: [eersteLaad && _jsx(TableSkeleton, { columns: kolomBreedtes, rows: skeletonRows }), rows.map((r, i) => {
61
+ const id = getId(r);
62
+ const isActief = i === actief;
63
+ const gekozen = selection?.selected.has(id);
64
+ return (_jsxs("tr", { "data-rij": i, onClick: () => setActief(i), onDoubleClick: () => onOpen?.(r), className: "group h-[60px] border-b border-border transition-colors duration-150 last:border-0 hover:bg-muted/40 motion-reduce:transition-none " +
65
+ (isActief ? "bg-muted/60 " : "") +
66
+ (loading ? "opacity-60" : ""), children: [selection && (_jsxs("td", { className: "relative px-2 py-0 align-middle", onClick: (e) => e.stopPropagation(), children: [(gekozen || isActief) && _jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 w-[3px] " + (gekozen ? "bg-primary" : "bg-primary/40") }), _jsx("input", { type: "checkbox", className: "h-4 w-4 rounded accent-primary", checked: !!gekozen, onChange: () => selection.onToggle(id), "aria-label": `Kies ${selection.label(r)}` })] })), columns.map((c) => _jsx("td", { className: "truncate px-2 py-0 align-middle " + (c.className ?? ""), children: c.render(r) }, c.key)), (onOpen || rowActions) && (_jsx("td", { className: "px-2 py-0 align-middle", onClick: (e) => e.stopPropagation(), children: _jsxs("div", { className: "flex items-center justify-end gap-1", children: [rowActions?.(r), onOpen && (_jsx("button", { type: "button", onClick: () => onOpen(r), "aria-label": openLabel, title: openLabel, className: "inline-flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition-opacity duration-150 hover:bg-muted hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring " + (isActief ? "opacity-100" : "opacity-0 group-hover:opacity-100"), children: _jsx(ChevronRight, { className: "h-4 w-4" }) }))] }) }))] }, id));
67
+ }), leeg && (_jsx("tr", { className: "hover:bg-transparent", children: _jsx("td", { colSpan: columns.length + (selection ? 1 : 0) + (onOpen || rowActions ? 1 : 0), children: empty }) }))] })] }) })] }));
68
+ }
@@ -0,0 +1,9 @@
1
+ import type { ReactNode } from "react";
2
+ /** Lege toestand: groot zacht icoon, korte zin, één actie. */
3
+ export declare function EmptyState({ icon, title, text, action, }: {
4
+ icon: ReactNode;
5
+ title: string;
6
+ text?: string;
7
+ action?: ReactNode;
8
+ }): import("react").JSX.Element;
9
+ //# sourceMappingURL=EmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/EmptyState.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,+BAaA"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** Lege toestand: groot zacht icoon, korte zin, één actie. */
3
+ export function EmptyState({ icon, title, text, action, }) {
4
+ return (_jsxs("div", { className: "flex flex-col items-center gap-3 px-4 py-14 text-center", children: [_jsx("span", { className: "inline-flex h-14 w-14 items-center justify-center rounded-full bg-muted text-muted-foreground", "aria-hidden": true, children: icon }), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: title }), text && _jsx("div", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: text })] }), action] }));
5
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ export interface FilterChip {
3
+ key: string;
4
+ label: string;
5
+ icon?: ReactNode;
6
+ onRemove: () => void;
7
+ }
8
+ /** FilterChip exact naar Verkooporders; "Alles wissen" bij meer dan één. Inline in de werkbalk. */
9
+ export declare function FilterChips({ chips, onClearAll }: {
10
+ chips: FilterChip[];
11
+ onClearAll?: () => void;
12
+ }): import("react").JSX.Element | null;
13
+ //# sourceMappingURL=FilterChips.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChips.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/FilterChips.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,sCAwBlG"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { X } from "lucide-react";
3
+ /** FilterChip exact naar Verkooporders; "Alles wissen" bij meer dan één. Inline in de werkbalk. */
4
+ export function FilterChips({ chips, onClearAll }) {
5
+ if (chips.length === 0)
6
+ return null;
7
+ return (_jsxs(_Fragment, { children: [chips.map((c) => (_jsxs("button", { type: "button", onClick: c.onRemove, "aria-label": `Filter ${c.label} wissen`, className: "inline-flex h-8 items-center gap-1.5 rounded-full border border-border bg-muted px-3 text-xs font-medium text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [&_svg]:h-3.5 [&_svg]:w-3.5", children: [c.icon, c.label, _jsx(X, { className: "h-3.5 w-3.5", "aria-hidden": true })] }, c.key))), onClearAll && chips.length > 1 && (_jsx("button", { type: "button", onClick: onClearAll, className: "h-8 rounded-full px-2 text-xs font-medium text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: "Alles wissen" }))] }));
8
+ }
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+ /** Zijpaneel met alle extra filters (rechts op desktop, volledig scherm op mobiel). */
3
+ export declare function FilterPanel({ open, onOpenChange, children, onClear }: {
4
+ open: boolean;
5
+ onOpenChange: (o: boolean) => void;
6
+ children: ReactNode;
7
+ onClear?: () => void;
8
+ }): import("react").JSX.Element;
9
+ /** Eén filtergroep met keuzeknoppen. */
10
+ export declare function FilterGroup<T extends string>({ title, value, options, onChange }: {
11
+ title: string;
12
+ value: T;
13
+ options: {
14
+ value: T;
15
+ label: string;
16
+ }[];
17
+ onChange: (v: T) => void;
18
+ }): import("react").JSX.Element;
19
+ //# sourceMappingURL=FilterPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterPanel.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/FilterPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,+BAatK;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,OAAO,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAA;CAAE,+BAc/K"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Dialog, DialogContent, DialogHeader, DialogTitle } from "@flowselections/core";
3
+ /** Zijpaneel met alle extra filters (rechts op desktop, volledig scherm op mobiel). */
4
+ export function FilterPanel({ open, onOpenChange, children, onClear }) {
5
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "left-auto right-0 top-0 h-[100dvh] max-w-sm translate-x-0 translate-y-0 rounded-none sm:rounded-none flex flex-col gap-4 data-[state=open]:slide-in-from-right", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Filters" }) }), _jsx("div", { className: "min-h-0 flex-1 space-y-5 overflow-auto", children: children }), _jsxs("div", { className: "flex justify-between gap-2 border-t border-border pt-3", children: [onClear ? _jsx(Button, { variant: "ghost", size: "sm", onClick: onClear, children: "Alles wissen" }) : _jsx("span", {}), _jsx(Button, { size: "sm", onClick: () => onOpenChange(false), children: "Klaar" })] })] }) }));
6
+ }
7
+ /** Eén filtergroep met keuzeknoppen. */
8
+ export function FilterGroup({ title, value, options, onChange }) {
9
+ return (_jsxs("fieldset", { className: "space-y-2", children: [_jsx("legend", { className: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: title }), _jsx("div", { className: "flex flex-wrap gap-2", children: options.map((o) => (_jsx("button", { type: "button", "aria-pressed": o.value === value, onClick: () => onChange(o.value), className: "h-8 rounded-full border px-3 text-xs font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring " + (o.value === value ? "border-primary/30 bg-primary/10 text-foreground" : "border-border bg-card text-foreground/80 hover:bg-muted"), children: o.label }, o.value))) })] }));
10
+ }
@@ -0,0 +1,6 @@
1
+ /** Knop "Filters" exact naar Verkooporders, met teller als er filters actief zijn. */
2
+ export declare function FiltersButton({ count, onClick }: {
3
+ count: number;
4
+ onClick: () => void;
5
+ }): import("react").JSX.Element;
6
+ //# sourceMappingURL=FiltersButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FiltersButton.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/FiltersButton.tsx"],"names":[],"mappings":"AAGA,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,+BAYvF"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@flowselections/core";
3
+ import { SlidersHorizontal } from "lucide-react";
4
+ /** Knop "Filters" exact naar Verkooporders, met teller als er filters actief zijn. */
5
+ export function FiltersButton({ count, onClick }) {
6
+ return (_jsxs(Button, { variant: "outline", size: "sm", onClick: onClick, "aria-label": "Filters", className: "relative h-10 px-3 sm:h-9", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4 sm:mr-2" }), _jsx("span", { className: "hidden sm:inline", children: "Filters" }), count > 0 && (_jsx("span", { className: "ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground", children: count }))] }));
7
+ }
@@ -0,0 +1,16 @@
1
+ import type { ReactNode } from "react";
2
+ /** Secundaire kopknop exact naar Verkooporders: outline sm; op mobiel alleen icoon van 40 px. */
3
+ export declare function HeaderButton({ icon, label, onClick, disabled }: {
4
+ icon: ReactNode;
5
+ label: string;
6
+ onClick?: () => void;
7
+ disabled?: boolean;
8
+ }): import("react").JSX.Element;
9
+ /** Primaire kopknop: size sm met kbd-hint; op mobiel verborgen (vaste knop onderin). */
10
+ export declare function HeaderPrimary({ icon, label, kbd, onClick }: {
11
+ icon: ReactNode;
12
+ label: string;
13
+ kbd?: string;
14
+ onClick: () => void;
15
+ }): import("react").JSX.Element;
16
+ //# sourceMappingURL=HeaderButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderButton.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/HeaderButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,+BAM5I;AAED,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,+BASjI"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@flowselections/core";
3
+ /** Secundaire kopknop exact naar Verkooporders: outline sm; op mobiel alleen icoon van 40 px. */
4
+ export function HeaderButton({ icon, label, onClick, disabled }) {
5
+ return (_jsxs(Button, { variant: "outline", size: "sm", onClick: onClick, disabled: disabled, "aria-label": label, className: "h-10 w-10 p-0 sm:h-9 sm:w-auto sm:px-3 [&_svg]:h-4 [&_svg]:w-4 [&_svg]:sm:mr-2", children: [icon, " ", _jsx("span", { className: "hidden sm:inline", children: label })] }));
6
+ }
7
+ /** Primaire kopknop: size sm met kbd-hint; op mobiel verborgen (vaste knop onderin). */
8
+ export function HeaderPrimary({ icon, label, kbd, onClick }) {
9
+ return (_jsxs(Button, { size: "sm", className: "hidden sm:inline-flex [&_svg]:mr-2 [&_svg]:h-4 [&_svg]:w-4", onClick: onClick, children: [icon, " ", label, kbd && (_jsx("kbd", { "aria-hidden": true, className: "ml-2 hidden rounded border border-primary-foreground/30 bg-primary-foreground/15 px-1.5 font-mono text-[10px] leading-4 text-primary-foreground sm:inline-block", children: kbd }))] }));
10
+ }
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Tooltip op basis van Popover (core heeft geen Tooltip-export): opent bij
4
+ * aanwijzen én bij toetsenbordfocus, sluit met Esc of bij verlaten. De
5
+ * trigger is een knop met een toegankelijke naam.
6
+ */
7
+ export declare function HoverTip({ content, label, children, side, align, className, }: {
8
+ align?: "start" | "center" | "end";
9
+ content: ReactNode;
10
+ label: string;
11
+ children: ReactNode;
12
+ side?: "top" | "bottom" | "left" | "right";
13
+ className?: string;
14
+ }): import("react").JSX.Element;
15
+ //# sourceMappingURL=HoverTip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoverTip.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/HoverTip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGzD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,KAAK,EACL,QAAQ,EACR,IAAY,EACZ,KAAgB,EAChB,SAAc,GACf,EAAE;IACD,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,OAAO,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA4CA"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState } from "react";
3
+ import { Popover, PopoverContent, PopoverTrigger } from "@flowselections/core";
4
+ /**
5
+ * Tooltip op basis van Popover (core heeft geen Tooltip-export): opent bij
6
+ * aanwijzen én bij toetsenbordfocus, sluit met Esc of bij verlaten. De
7
+ * trigger is een knop met een toegankelijke naam.
8
+ */
9
+ export function HoverTip({ content, label, children, side = "top", align = "center", className = "", }) {
10
+ const [open, setOpen] = useState(false);
11
+ const timer = useRef(null);
12
+ const show = () => {
13
+ if (timer.current)
14
+ clearTimeout(timer.current);
15
+ setOpen(true);
16
+ };
17
+ const hide = () => {
18
+ if (timer.current)
19
+ clearTimeout(timer.current);
20
+ timer.current = setTimeout(() => setOpen(false), 80);
21
+ };
22
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { type: "button", "aria-label": label, onPointerEnter: show, onPointerLeave: hide, onFocus: show, onBlur: hide, onClick: (e) => e.stopPropagation(), className: "inline-flex shrink-0 items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring " +
23
+ className, children: children }), _jsx(PopoverContent, { side: side, align: align, avoidCollisions: true, collisionPadding: 8, onOpenAutoFocus: (e) => e.preventDefault(), onCloseAutoFocus: (e) => e.preventDefault(), onPointerEnter: show, onPointerLeave: hide, onClick: (e) => e.stopPropagation(), className: "w-auto min-w-[14rem] max-w-[20rem] rounded-lg p-3 text-xs leading-snug shadow-lg motion-reduce:animate-none", children: content })] }));
24
+ }
@@ -0,0 +1,12 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Melding: afgerond vlak met zachte rode of oker achtergrond, icoon links, actie rechts.
4
+ * Geen technische fouttekst. Op mobiel ingeklapt tot één regel; tik om uit te klappen.
5
+ */
6
+ export declare function InlineAlert({ tone, children, action, icon, }: {
7
+ tone?: "fout" | "let_op" | "info";
8
+ children: ReactNode;
9
+ action?: ReactNode;
10
+ icon?: ReactNode;
11
+ }): import("react").JSX.Element;
12
+ //# sourceMappingURL=InlineAlert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InlineAlert.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/InlineAlert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAe,EACf,QAAQ,EACR,MAAM,EACN,IAAI,GACL,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,+BAyBA"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { AlertTriangle, ChevronDown, Info, XCircle } from "lucide-react";
4
+ /**
5
+ * Melding: afgerond vlak met zachte rode of oker achtergrond, icoon links, actie rechts.
6
+ * Geen technische fouttekst. Op mobiel ingeklapt tot één regel; tik om uit te klappen.
7
+ */
8
+ export function InlineAlert({ tone = "let_op", children, action, icon, }) {
9
+ const [open, setOpen] = useState(false);
10
+ const kleur = tone === "fout" ? "border-destructive/30 bg-destructive/10 text-foreground"
11
+ : tone === "let_op" ? "border-transparent bg-warning-soft text-warning-soft-foreground"
12
+ : "border-border bg-muted/50 text-foreground";
13
+ const Ico = tone === "fout" ? XCircle : tone === "let_op" ? AlertTriangle : Info;
14
+ return (_jsxs("div", { role: tone === "fout" ? "alert" : "status", className: "flex items-start gap-3 rounded-lg border px-3 py-2.5 text-sm " + kleur, children: [_jsx("span", { className: "mt-0.5 shrink-0 [&_svg]:h-4 [&_svg]:w-4 " + (tone === "fout" ? "text-destructive" : ""), "aria-hidden": true, children: icon ?? _jsx(Ico, {}) }), _jsx("div", { className: "min-w-0 flex-1 " + (open ? "" : "line-clamp-1 sm:line-clamp-none"), children: children }), _jsx("button", { type: "button", onClick: () => setOpen((o) => !o), "aria-expanded": open, "aria-label": open ? "Melding inklappen" : "Melding uitklappen", className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-lg sm:hidden", children: _jsx(ChevronDown, { className: "h-4 w-4 transition-transform motion-reduce:transition-none " + (open ? "rotate-180" : "") }) }), action && _jsx("div", { className: "shrink-0", children: action })] }));
15
+ }
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Rij KPI-tegels: 4 naast elkaar vanaf desktop, 2 op tablet; op mobiel veegbaar.
4
+ * De eerste tegel staat binnen de paginamarge van 16 px (scroll-padding), nooit tegen de rand.
5
+ */
6
+ export declare function KpiRow({ children, label }: {
7
+ children: ReactNode;
8
+ label?: string;
9
+ }): import("react").JSX.Element;
10
+ //# sourceMappingURL=KpiRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KpiRow.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/KpiRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAqB,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BASlG"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Rij KPI-tegels: 4 naast elkaar vanaf desktop, 2 op tablet; op mobiel veegbaar.
4
+ * De eerste tegel staat binnen de paginamarge van 16 px (scroll-padding), nooit tegen de rand.
5
+ */
6
+ export function KpiRow({ children, label = "Kerncijfers" }) {
7
+ return (_jsx("section", { "aria-label": label, className: "-mx-4 flex snap-x snap-mandatory scroll-px-4 gap-3 overflow-x-auto px-4 pb-1 [scrollbar-width:none] sm:mx-0 sm:grid sm:grid-cols-2 sm:overflow-visible sm:px-0 sm:pb-0 lg:grid-cols-4 [&::-webkit-scrollbar]:hidden [&>*]:w-[78%] [&>*]:shrink-0 [&>*]:snap-start sm:[&>*]:w-auto", children: children }));
8
+ }
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from "react";
2
+ export interface KpiTrend {
3
+ /** Procentuele wijziging t.o.v. de vorige periode (null = geen vergelijking). */
4
+ pct: number | null;
5
+ label: string;
6
+ /** Hoger is beter (omzet) of slechter (actie nodig). */
7
+ goodWhenUp?: boolean;
8
+ }
9
+ /** KPI-tegel: icoon, label, groot getal, subregel en optionele trend. Alleen weergave. */
10
+ export declare function KpiTile({ title, value, sub, icon, tone, loading, onClick, active, trend, }: {
11
+ title: string;
12
+ value: ReactNode;
13
+ sub?: ReactNode;
14
+ icon?: ReactNode;
15
+ tone?: "default" | "warning";
16
+ loading?: boolean;
17
+ onClick?: () => void;
18
+ active?: boolean;
19
+ trend?: KpiTrend | null;
20
+ }): import("react").JSX.Element;
21
+ //# sourceMappingURL=KpiTile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KpiTile.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/KpiTile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,QAAQ;IACvB,iFAAiF;IACjF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAoCD,0FAA0F;AAC1F,wBAAgB,OAAO,CAAC,EACtB,KAAK,EACL,KAAK,EACL,GAAG,EACH,IAAI,EACJ,IAAgB,EAChB,OAAO,EACP,OAAO,EACP,MAAM,EACN,KAAK,GACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CACzB,+BA4DA"}
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Card, Skeleton } from "@flowselections/core";
3
+ import { ChevronRight, Minus, TrendingDown, TrendingUp } from "lucide-react";
4
+ function Trend({ trend }) {
5
+ if (trend.pct == null)
6
+ return null;
7
+ const flat = Math.abs(trend.pct) < 0.5;
8
+ const up = trend.pct > 0;
9
+ const good = flat ? null : up === (trend.goodWhenUp ?? true);
10
+ const Icon = flat ? Minus : up ? TrendingUp : TrendingDown;
11
+ const tone = good == null ? "text-muted-foreground" : good ? "text-primary" : "text-destructive";
12
+ return (_jsxs("span", { className: "inline-flex min-w-0 items-center gap-1 whitespace-nowrap text-xs font-medium tabular-nums " + tone, title: trend.label, children: [_jsx(Icon, { className: "h-3.5 w-3.5", "aria-hidden": true }), flat ? "0%" : `${up ? "+" : ""}${Math.round(trend.pct)}%`, _jsx("span", { className: "truncate font-normal text-muted-foreground", children: trend.label })] }));
13
+ }
14
+ /** Klein trendlijntje van vorige naar huidige periode (alleen weergave). */
15
+ function Spark({ trend }) {
16
+ if (trend.pct == null)
17
+ return null;
18
+ const up = trend.pct > 0.5;
19
+ const down = trend.pct < -0.5;
20
+ const good = up || down ? up === (trend.goodWhenUp ?? true) : null;
21
+ const tone = good == null ? "text-muted-foreground" : good ? "text-primary" : "text-destructive";
22
+ const y0 = up ? 26 : down ? 6 : 16;
23
+ const y1 = up ? 6 : down ? 26 : 16;
24
+ const mid = (y0 + y1) / 2;
25
+ const d = `M2 ${y0} C 14 ${y0}, 18 ${mid + (up ? 4 : down ? -4 : 0)}, 28 ${mid} S 44 ${mid - (up ? 6 : down ? -6 : 0)}, 50 ${(mid + y1) / 2} S 58 ${y1}, 62 ${y1}`;
26
+ return (_jsx("svg", { viewBox: "0 0 64 32", className: "hidden h-8 w-16 shrink-0 self-end sm:block " + tone, "aria-hidden": true, children: _jsx("path", { d: d, fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }));
27
+ }
28
+ /** KPI-tegel: icoon, label, groot getal, subregel en optionele trend. Alleen weergave. */
29
+ export function KpiTile({ title, value, sub, icon, tone = "default", loading, onClick, active, trend, }) {
30
+ const body = (_jsxs("div", { className: "flex items-center gap-3 sm:gap-4", children: [icon && (_jsx("span", { className: "inline-flex h-10 w-10 sm:h-12 sm:w-12 shrink-0 items-center justify-center rounded-xl [&_svg]:h-5 [&_svg]:w-5 sm:[&_svg]:h-6 sm:[&_svg]:w-6 " +
31
+ (tone === "warning" ? "bg-warning-soft text-warning-soft-foreground" : "bg-primary/10 text-primary"), "aria-hidden": true, children: icon })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: title }), _jsx("div", { className: "mt-0.5 text-2xl font-semibold leading-tight tabular-nums text-foreground", children: loading ? _jsx(Skeleton, { className: "h-7 w-24" }) : value }), _jsx("div", { className: "mt-1 flex min-h-4 flex-col gap-0.5 text-xs text-muted-foreground", children: loading ? _jsx(Skeleton, { className: "h-3 w-32" }) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "truncate", children: sub }), trend && _jsx(Trend, { trend: trend })] })) })] }), !loading && trend && _jsx(Spark, { trend: trend }), onClick && tone === "warning" && _jsx(ChevronRight, { className: "h-5 w-5 shrink-0 text-muted-foreground", "aria-hidden": true })] }));
32
+ return (_jsx(Card, { className: "h-full p-4 sm:p-5 transition-shadow " +
33
+ (onClick ? "hover:border-ring/50 hover:shadow-md " : "") +
34
+ (active ? "ring-2 ring-ring" : ""), children: onClick ? (_jsx("div", { role: "button", tabIndex: 0, onClick: onClick, onKeyDown: (e) => {
35
+ if (e.key === "Enter" || e.key === " ") {
36
+ e.preventDefault();
37
+ onClick();
38
+ }
39
+ }, className: "block w-full cursor-pointer rounded-sm text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: body })) : (body) }));
40
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Primaire actie op mobiel: vaste, schermbrede knop (48 px) onderin met veilige rand.
4
+ * Verbergt zich vanaf tablet en wanneer `hidden` (bijv. bij een selectiebalk).
5
+ */
6
+ export declare function MobilePrimaryAction({ children, onClick, hidden, disabled, icon, }: {
7
+ children: ReactNode;
8
+ onClick: () => void;
9
+ hidden?: boolean;
10
+ disabled?: boolean;
11
+ icon?: ReactNode;
12
+ }): import("react").JSX.Element | null;
13
+ //# sourceMappingURL=MobilePrimaryAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MobilePrimaryAction.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/MobilePrimaryAction.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,IAAI,GACL,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,sCAeA"}
@@ -0,0 +1,10 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Primaire actie op mobiel: vaste, schermbrede knop (48 px) onderin met veilige rand.
4
+ * Verbergt zich vanaf tablet en wanneer `hidden` (bijv. bij een selectiebalk).
5
+ */
6
+ export function MobilePrimaryAction({ children, onClick, hidden, disabled, icon, }) {
7
+ if (hidden)
8
+ return null;
9
+ return (_jsx("div", { className: "fixed inset-x-0 bottom-0 z-30 border-t border-border bg-background/95 p-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur md:hidden", children: _jsxs("button", { type: "button", onClick: onClick, disabled: disabled, className: "inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg bg-primary text-base font-medium text-primary-foreground shadow-lg transition-opacity active:opacity-90 disabled:opacity-50 [&_svg]:h-4 [&_svg]:w-4", children: [icon, children] }) }));
10
+ }
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * NoticeBar naar Verkooporders: één inklapbare balk voor alle meldingen. Ingeklapt
4
+ * hooguit 2 regels (één per melding), de rest als "+ n meldingen"; uitklappen toont alles.
5
+ * `items` zijn korte zinnen, nooit lijsten van artikelen.
6
+ */
7
+ export declare function NoticeBar({ items }: {
8
+ items: ReactNode[];
9
+ }): import("react").JSX.Element | null;
10
+ //# sourceMappingURL=NoticeBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoticeBar.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/NoticeBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,sCA0B1D"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { ChevronDown, Info } from "lucide-react";
4
+ /**
5
+ * NoticeBar naar Verkooporders: één inklapbare balk voor alle meldingen. Ingeklapt
6
+ * hooguit 2 regels (één per melding), de rest als "+ n meldingen"; uitklappen toont alles.
7
+ * `items` zijn korte zinnen, nooit lijsten van artikelen.
8
+ */
9
+ export function NoticeBar({ items }) {
10
+ const [open, setOpen] = useState(false);
11
+ if (items.length === 0)
12
+ return null;
13
+ const zichtbaar = open ? items : items.slice(0, 2);
14
+ const rest = items.length - zichtbaar.length;
15
+ return (_jsx("div", { role: "status", className: "shrink-0 rounded-lg border border-border bg-warning-soft text-sm text-warning-soft-foreground", children: _jsxs("button", { type: "button", "aria-expanded": open, onClick: () => setOpen((o) => !o), className: "flex w-full items-start gap-2 px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-lg", children: [_jsx(Info, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": true }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [zichtbaar.map((it, i) => (_jsx("span", { className: "min-w-0 " + (open ? "" : "truncate"), children: it }, i))), rest > 0 && _jsxs("span", { className: "font-medium", children: ["+ ", rest, " ", rest === 1 ? "melding" : "meldingen"] })] }), (items.length > 2 || open) && (_jsx(ChevronDown, { className: "ml-auto mt-0.5 h-4 w-4 shrink-0 transition-transform " + (open ? "rotate-180" : ""), "aria-hidden": true }))] }) }));
16
+ }
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Paginakop exact naar Verkooporders: h1 (20/24 px, 700) met daaronder alleen
4
+ * "Bijgewerkt hh:mm". Rechts periode, secundaire knoppen en één primaire knop.
5
+ * Op mobiel staat de kop in een raster: titel links, knoppen (icoon) rechts.
6
+ */
7
+ export declare function PageHeader({ title, updated, crumb, media, meta, actions, }: {
8
+ title: ReactNode;
9
+ /** Meestal <UpdatedAt />. */
10
+ updated?: ReactNode;
11
+ /** Kleine terug-link boven de titel (alleen detailpagina's). */
12
+ crumb?: ReactNode;
13
+ /** Optioneel beeld links van de titel (alleen detailpagina's). */
14
+ media?: ReactNode;
15
+ /** Alleen detailpagina's: vaste kerngegevens onder de titel. */
16
+ meta?: ReactNode;
17
+ actions?: ReactNode;
18
+ }): import("react").JSX.Element;
19
+ //# sourceMappingURL=PageHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/PageHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,KAAK,EACL,KAAK,EACL,IAAI,EACJ,OAAO,GACR,EAAE;IACD,KAAK,EAAE,SAAS,CAAC;IACjB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gEAAgE;IAChE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,kEAAkE;IAClE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,+BAqBA"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Paginakop exact naar Verkooporders: h1 (20/24 px, 700) met daaronder alleen
4
+ * "Bijgewerkt hh:mm". Rechts periode, secundaire knoppen en één primaire knop.
5
+ * Op mobiel staat de kop in een raster: titel links, knoppen (icoon) rechts.
6
+ */
7
+ export function PageHeader({ title, updated, crumb, media, meta, actions, }) {
8
+ return (_jsxs("header", { className: "shrink-0 flex flex-col gap-1", children: [crumb && _jsx("div", { className: "text-sm text-muted-foreground", children: crumb }), _jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 sm:flex sm:flex-wrap sm:justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [media, _jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "truncate text-xl font-bold leading-tight sm:text-2xl tracking-tight text-foreground", children: title }), updated && (_jsx("p", { className: "flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground", "aria-live": "polite", children: updated })), meta && _jsx("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-sm", children: meta })] })] }), actions && _jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: actions })] })] }));
9
+ }
@@ -0,0 +1,10 @@
1
+ /** Paginering exact naar Verkooporders: "1–25 van 120" links, "Per pagina" en pijlen met "1 / 5" rechts. */
2
+ export declare function Pagination({ page, pageSize, totalCount, onPage, onPageSize, sizes, }: {
3
+ page: number;
4
+ pageSize: number;
5
+ totalCount: number;
6
+ onPage: (p: number) => void;
7
+ onPageSize?: (n: number) => void;
8
+ sizes?: number[];
9
+ }): import("react").JSX.Element;
10
+ //# sourceMappingURL=Pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/Pagination.tsx"],"names":[],"mappings":"AAGA,4GAA4G;AAC5G,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,MAAM,EACN,UAAU,EACV,KAAyB,GAC1B,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,+BAuCA"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@flowselections/core";
3
+ import { ChevronLeft, ChevronRight } from "lucide-react";
4
+ /** Paginering exact naar Verkooporders: "1–25 van 120" links, "Per pagina" en pijlen met "1 / 5" rechts. */
5
+ export function Pagination({ page, pageSize, totalCount, onPage, onPageSize, sizes = [10, 25, 50, 100], }) {
6
+ const totalPages = Math.max(1, Math.ceil(totalCount / pageSize));
7
+ return (_jsxs("nav", { "aria-label": "Paginering", className: "shrink-0 flex flex-wrap items-center justify-between gap-3 text-sm text-muted-foreground", children: [_jsx("div", { className: "tabular-nums", children: totalCount === 0
8
+ ? "Geen resultaten"
9
+ : `${((page - 1) * pageSize + 1).toLocaleString("nl-NL")}–${Math.min(page * pageSize, totalCount).toLocaleString("nl-NL")} van ${totalCount.toLocaleString("nl-NL")}` }), _jsxs("div", { className: "flex items-center gap-3", children: [onPageSize && (_jsxs("div", { className: "hidden items-center gap-2 sm:flex", children: [_jsx("span", { children: "Per pagina" }), _jsxs(Select, { value: String(pageSize), onValueChange: (v) => onPageSize(Number(v)), children: [_jsx(SelectTrigger, { className: "h-8 w-20", "aria-label": "Resultaten per pagina", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: sizes.map((n) => (_jsx(SelectItem, { value: String(n), children: n }, n))) })] })] })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "outline", size: "icon", className: "h-10 w-10 sm:h-8 sm:w-8", onClick: () => onPage(Math.max(1, page - 1)), disabled: page <= 1, "aria-label": "Vorige pagina", children: _jsx(ChevronLeft, { className: "h-4 w-4" }) }), _jsxs("div", { className: "px-2 text-foreground tabular-nums", "aria-current": "page", children: [page, " / ", totalPages] }), _jsx(Button, { variant: "outline", size: "icon", className: "h-10 w-10 sm:h-8 sm:w-8", onClick: () => onPage(Math.min(totalPages, page + 1)), disabled: page >= totalPages, "aria-label": "Volgende pagina", children: _jsx(ChevronRight, { className: "h-4 w-4" }) })] })] })] }));
10
+ }
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from "react";
2
+ export interface PillTab<T extends string = string> {
3
+ value: T;
4
+ label: string;
5
+ icon?: ReactNode;
6
+ /** Teller; undefined = geen teller, null = nog laden. */
7
+ count?: number | null;
8
+ hint?: string;
9
+ }
10
+ /** StatusTabs exact naar Verkooporders: altijd één regel, scrollt horizontaal met vervaging. */
11
+ export declare function PillTabs<T extends string>({ tabs, value, onChange, label, }: {
12
+ tabs: PillTab<T>[];
13
+ value: T;
14
+ onChange: (v: T) => void;
15
+ label?: string;
16
+ }): import("react").JSX.Element;
17
+ //# sourceMappingURL=PillTabs.d.ts.map