@flowselections/floriday-voorraad 1.0.149 → 1.0.152
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-lib/components/fs-ui/DataTable.d.ts +42 -0
- package/dist-lib/components/fs-ui/DataTable.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/DataTable.js +68 -0
- package/dist-lib/components/fs-ui/EmptyState.d.ts +9 -0
- package/dist-lib/components/fs-ui/EmptyState.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/EmptyState.js +5 -0
- package/dist-lib/components/fs-ui/FilterChips.d.ts +13 -0
- package/dist-lib/components/fs-ui/FilterChips.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/FilterChips.js +8 -0
- package/dist-lib/components/fs-ui/HoverTip.d.ts +15 -0
- package/dist-lib/components/fs-ui/HoverTip.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/HoverTip.js +24 -0
- package/dist-lib/components/fs-ui/InlineAlert.d.ts +12 -0
- package/dist-lib/components/fs-ui/InlineAlert.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/InlineAlert.js +15 -0
- package/dist-lib/components/fs-ui/KpiRow.d.ts +10 -0
- package/dist-lib/components/fs-ui/KpiRow.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/KpiRow.js +8 -0
- package/dist-lib/components/fs-ui/KpiTile.d.ts +21 -0
- package/dist-lib/components/fs-ui/KpiTile.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/KpiTile.js +40 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts +13 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/MobilePrimaryAction.js +10 -0
- package/dist-lib/components/fs-ui/PageHeader.d.ts +18 -0
- package/dist-lib/components/fs-ui/PageHeader.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/PageHeader.js +8 -0
- package/dist-lib/components/fs-ui/PillTabs.d.ts +19 -0
- package/dist-lib/components/fs-ui/PillTabs.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/PillTabs.js +18 -0
- package/dist-lib/components/fs-ui/SearchInput.d.ts +14 -0
- package/dist-lib/components/fs-ui/SearchInput.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/SearchInput.js +51 -0
- package/dist-lib/components/fs-ui/StatusIcon.d.ts +13 -0
- package/dist-lib/components/fs-ui/StatusIcon.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/StatusIcon.js +15 -0
- package/dist-lib/components/fs-ui/TableSkeleton.d.ts +7 -0
- package/dist-lib/components/fs-ui/TableSkeleton.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/TableSkeleton.js +6 -0
- package/dist-lib/components/fs-ui/Toolbar.d.ts +8 -0
- package/dist-lib/components/fs-ui/Toolbar.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/Toolbar.js +5 -0
- package/dist-lib/components/fs-ui/UpdatedAt.d.ts +6 -0
- package/dist-lib/components/fs-ui/UpdatedAt.d.ts.map +1 -0
- package/dist-lib/components/fs-ui/UpdatedAt.js +10 -0
- package/dist-lib/components/voorraad/ArtikelCompositionCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ArtikelCompositionCard.js +46 -15
- package/dist-lib/components/voorraad/ArtikelWizard.js +4 -4
- package/dist-lib/components/voorraad/FloridayConnectionNotice.d.ts +6 -6
- package/dist-lib/components/voorraad/FloridayConnectionNotice.d.ts.map +1 -1
- package/dist-lib/components/voorraad/FloridayConnectionNotice.js +10 -12
- package/dist-lib/components/voorraad/FustenPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/FustenPage.js +4 -2
- package/dist-lib/components/voorraad/NieuwArtikelPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/NieuwArtikelPage.js +2 -1
- package/dist-lib/components/voorraad/PublicatiesPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/PublicatiesPage.js +2 -1
- package/dist-lib/components/voorraad/Sneltoetsen.d.ts +14 -0
- package/dist-lib/components/voorraad/Sneltoetsen.d.ts.map +1 -0
- package/dist-lib/components/voorraad/Sneltoetsen.js +45 -0
- package/dist-lib/components/voorraad/StockIntegrityAlert.d.ts.map +1 -1
- package/dist-lib/components/voorraad/StockIntegrityAlert.js +9 -2
- package/dist-lib/components/voorraad/StockPushMonitor.js +2 -2
- package/dist-lib/components/voorraad/TelmomentButton.d.ts +5 -1
- package/dist-lib/components/voorraad/TelmomentButton.d.ts.map +1 -1
- package/dist-lib/components/voorraad/TelmomentButton.js +13 -6
- package/dist-lib/components/voorraad/ValidationOverviewTable.js +9 -7
- package/dist-lib/components/voorraad/ValidationPage.d.ts +1 -0
- package/dist-lib/components/voorraad/ValidationPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ValidationPage.js +33 -5
- package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts +4 -1
- package/dist-lib/components/voorraad/VoorraadBeheerCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadBeheerCard.js +26 -5
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +48 -34
- package/dist-lib/components/voorraad/VoorraadSturingCard.js +1 -1
- package/dist-lib/components/voorraad/artikel/ArtikelPagina.d.ts.map +1 -1
- package/dist-lib/components/voorraad/artikel/ArtikelPagina.js +28 -18
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts +8 -2
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.d.ts.map +1 -1
- package/dist-lib/components/voorraad/lijst/VoorraadLijstTabel.js +62 -27
- package/dist-lib/hooks/useLocalTradeItems.d.ts +14 -0
- package/dist-lib/hooks/useLocalTradeItems.d.ts.map +1 -1
- package/dist-lib/hooks/useLocalTradeItems.js +5 -3
- package/dist-lib/hooks/useTradeItemStock.d.ts.map +1 -1
- package/dist-lib/hooks/useTradeItemStock.js +6 -3
- package/dist-lib/hooks/useVoorraadData.d.ts.map +1 -1
- package/dist-lib/hooks/useVoorraadData.js +16 -8
- package/dist-lib/hooks/useVoorraadLijst.d.ts +10 -0
- package/dist-lib/hooks/useVoorraadLijst.d.ts.map +1 -1
- package/dist-lib/hooks/useVoorraadLijst.js +22 -4
- package/dist-lib/integrations/supabase/types.d.ts +59 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/alle-rijen.d.ts +15 -0
- package/dist-lib/lib/alle-rijen.d.ts.map +1 -0
- package/dist-lib/lib/alle-rijen.js +17 -0
- package/dist-lib/lib/db-error-message.d.ts.map +1 -1
- package/dist-lib/lib/db-error-message.js +3 -1
- package/package.json +2 -1
- 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,+BA0IA"}
|
|
@@ -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 ? "44px" : 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: [mobileCard && (_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(r) }) }, getId(r)))), leeg && _jsx("li", { children: empty })] })), _jsx("div", { className: (mobileCard ? "hidden md:block " : "") + "max-h-[calc(100vh-12rem)] overflow-auto", children: _jsxs("table", { className: "w-full min-w-[900px] table-fixed text-sm", children: [_jsxs("colgroup", { children: [selection && _jsx("col", { style: { width: "44px" } }), columns.map((c) => _jsx("col", { style: c.width ? { width: c.width } : undefined }, c.key)), (onOpen || rowActions) && _jsx("col", { style: { width: "96px" } })] }), _jsx("thead", { className: "sticky top-0 z-10 bg-card", children: _jsxs("tr", { className: "h-10 border-b border-border", children: [selection && (_jsx("th", { className: "px-3 text-left", 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-3 text-left text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", "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 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-3", 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 || gekozen ? "bg-primary/5 shadow-[inset_3px_0_0_var(--primary)] " : "") +
|
|
66
|
+
(loading ? "opacity-60" : ""), children: [selection && (_jsx("td", { className: "px-3", onClick: (e) => e.stopPropagation(), children: _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-3 " + (c.className ?? ""), children: c.render(r) }, c.key)), (onOpen || rowActions) && (_jsx("td", { className: "px-3", 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", { 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
|
+
/** Actieve filters als ronde chips met icoon en kruisje; "Alles wissen" bij meer dan één. */
|
|
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,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,sCAoBlG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { X } from "lucide-react";
|
|
3
|
+
/** Actieve filters als ronde chips met icoon en kruisje; "Alles wissen" bij meer dan één. */
|
|
4
|
+
export function FilterChips({ chips, onClearAll }) {
|
|
5
|
+
if (chips.length === 0)
|
|
6
|
+
return null;
|
|
7
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2", "aria-label": "Actieve filters", children: [chips.map((c) => (_jsxs("span", { className: "inline-flex h-8 items-center gap-1.5 rounded-full border border-primary/30 bg-primary/10 pl-3 pr-1 text-sm text-primary [&_svg]:h-4 [&_svg]:w-4", children: [c.icon, c.label, _jsx("button", { type: "button", onClick: c.onRemove, "aria-label": `Filter ${c.label} wissen`, className: "inline-flex h-6 w-6 items-center justify-center rounded-full hover:bg-primary/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] }, c.key))), onClearAll && chips.length > 1 && (_jsx("button", { type: "button", onClick: onClearAll, className: "h-8 rounded-full px-3 text-sm text-muted-foreground hover:text-foreground", children: "Alles wissen" }))] }));
|
|
8
|
+
}
|
|
@@ -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 een
|
|
4
|
+
* veegbare rij (snap per tegel, ca. 78% breed) zonder zichtbare scrollbalk.
|
|
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 een
|
|
4
|
+
* veegbare rij (snap per tegel, ca. 78% breed) zonder zichtbare scrollbalk.
|
|
5
|
+
*/
|
|
6
|
+
export function KpiRow({ children, label = "Kerncijfers" }) {
|
|
7
|
+
return (_jsx("section", { "aria-label": label, className: "-mx-4 flex snap-x snap-mandatory 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,18 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Paginakop: links (kruimel), titel en bijgewerkt-tijd; rechts de acties.
|
|
4
|
+
* Titel 24 px (20 px mobiel), zonder icoon. Knoppen wrappen netjes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function PageHeader({ title, updated, crumb, media, meta, actions, }: {
|
|
7
|
+
title: ReactNode;
|
|
8
|
+
/** Meestal <UpdatedAt />. */
|
|
9
|
+
updated?: ReactNode;
|
|
10
|
+
/** Kleine terug-link boven de titel. */
|
|
11
|
+
crumb?: ReactNode;
|
|
12
|
+
/** Optioneel beeld links van de titel (bijv. foto van het item). */
|
|
13
|
+
media?: ReactNode;
|
|
14
|
+
/** Extra regel onder de titel (status, prijs). */
|
|
15
|
+
meta?: ReactNode;
|
|
16
|
+
actions?: ReactNode;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
//# 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;;;GAGG;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,wCAAwC;IACxC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,kDAAkD;IAClD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB,+BAiBA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Paginakop: links (kruimel), titel en bijgewerkt-tijd; rechts de acties.
|
|
4
|
+
* Titel 24 px (20 px mobiel), zonder icoon. Knoppen wrappen netjes.
|
|
5
|
+
*/
|
|
6
|
+
export function PageHeader({ title, updated, crumb, media, meta, actions, }) {
|
|
7
|
+
return (_jsxs("header", { className: "flex flex-col gap-2", children: [crumb && _jsx("div", { className: "text-sm text-muted-foreground", children: crumb }), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 flex-1 basis-64 items-start gap-4", children: [media, _jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "break-words text-xl font-bold leading-tight tracking-tight text-foreground sm:text-2xl", children: title }), updated && _jsx("div", { className: "mt-1 text-xs text-muted-foreground", 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 gap-2", children: actions })] })] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Tabbladen als pillen met icoon + label + teller. Actief: groene tint en rand,
|
|
11
|
+
* teller groen gevuld. Leeg (0): gedempte tekst. Mobiel veegbaar met vervaging rechts.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PillTabs<T extends string>({ tabs, value, onChange, label, }: {
|
|
14
|
+
tabs: PillTab<T>[];
|
|
15
|
+
value: T;
|
|
16
|
+
onChange: (v: T) => void;
|
|
17
|
+
label?: string;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=PillTabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PillTabs.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/PillTabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAChD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,EACzC,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAkB,GACnB,EAAE;IACD,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,+BA0CA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Tabbladen als pillen met icoon + label + teller. Actief: groene tint en rand,
|
|
4
|
+
* teller groen gevuld. Leeg (0): gedempte tekst. Mobiel veegbaar met vervaging rechts.
|
|
5
|
+
*/
|
|
6
|
+
export function PillTabs({ tabs, value, onChange, label = "Weergave", }) {
|
|
7
|
+
return (_jsxs("div", { className: "relative", children: [_jsx("div", { role: "tablist", "aria-label": label, className: "flex gap-2 overflow-x-auto pr-6 [scrollbar-width:none] sm:flex-wrap sm:overflow-visible sm:pr-0 [&::-webkit-scrollbar]:hidden", children: tabs.map((t) => {
|
|
8
|
+
const actief = t.value === value;
|
|
9
|
+
const leeg = t.count === 0 && !actief;
|
|
10
|
+
return (_jsxs("button", { type: "button", role: "tab", "aria-selected": actief, onClick: () => onChange(t.value), className: "inline-flex h-9 shrink-0 items-center gap-2 whitespace-nowrap rounded-lg border px-3 text-sm font-medium transition-colors duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none [&_svg]:h-4 [&_svg]:w-4 " +
|
|
11
|
+
(actief
|
|
12
|
+
? "border-primary/40 bg-primary/10 text-primary"
|
|
13
|
+
: leeg
|
|
14
|
+
? "border-transparent text-muted-foreground/70 hover:bg-muted"
|
|
15
|
+
: "border-transparent text-muted-foreground hover:bg-muted hover:text-foreground"), children: [t.icon, t.label, t.count !== undefined && (_jsx("span", { className: "inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-xs tabular-nums " +
|
|
16
|
+
(actief ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"), children: t.count === null ? "…" : t.count.toLocaleString("nl-NL") }))] }, t.value));
|
|
17
|
+
}) }), _jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-y-0 right-0 w-6 bg-gradient-to-l from-background to-transparent sm:hidden" })] }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** True als de gebruiker in een invoerveld typt (sneltoetsen doen dan niets). */
|
|
2
|
+
export declare function isTypen(t: EventTarget | null): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Zoekveld: filtert tijdens typen (250 ms), één zachte focusring, wis-kruisje,
|
|
5
|
+
* "/" focust (niet tijdens typen elders), Esc wist. Mobiel 40 px hoog met 16 px tekst.
|
|
6
|
+
*/
|
|
7
|
+
export declare function SearchInput({ value, onChange, placeholder, label, delay, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (v: string) => void;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
label?: string;
|
|
12
|
+
delay?: number;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=SearchInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/SearchInput.tsx"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAItD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,WAAuB,EACvB,KAAgB,EAChB,KAAW,GACZ,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,+BAiDA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Search, X } from "lucide-react";
|
|
4
|
+
/** True als de gebruiker in een invoerveld typt (sneltoetsen doen dan niets). */
|
|
5
|
+
export function isTypen(t) {
|
|
6
|
+
const el = t;
|
|
7
|
+
if (!el)
|
|
8
|
+
return false;
|
|
9
|
+
return el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT" || el.isContentEditable;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Zoekveld: filtert tijdens typen (250 ms), één zachte focusring, wis-kruisje,
|
|
13
|
+
* "/" focust (niet tijdens typen elders), Esc wist. Mobiel 40 px hoog met 16 px tekst.
|
|
14
|
+
*/
|
|
15
|
+
export function SearchInput({ value, onChange, placeholder = "Zoeken…", label = "Zoeken", delay = 250, }) {
|
|
16
|
+
const [tekst, setTekst] = useState(value);
|
|
17
|
+
const ref = useRef(null);
|
|
18
|
+
const laatst = useRef(value);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (value !== laatst.current) {
|
|
21
|
+
laatst.current = value;
|
|
22
|
+
setTekst(value);
|
|
23
|
+
}
|
|
24
|
+
}, [value]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (tekst === laatst.current)
|
|
27
|
+
return;
|
|
28
|
+
const t = setTimeout(() => { laatst.current = tekst; onChange(tekst); }, delay);
|
|
29
|
+
return () => clearTimeout(t);
|
|
30
|
+
}, [tekst, delay, onChange]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const h = (e) => {
|
|
33
|
+
if (e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey && !isTypen(e.target)) {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
ref.current?.focus();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
window.addEventListener("keydown", h);
|
|
39
|
+
return () => window.removeEventListener("keydown", h);
|
|
40
|
+
}, []);
|
|
41
|
+
const wis = () => { setTekst(""); laatst.current = ""; onChange(""); };
|
|
42
|
+
return (_jsxs("div", { className: "relative w-full max-w-md", children: [_jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground", "aria-hidden": true }), _jsx("input", { ref: ref, type: "search", value: tekst, "aria-label": label, placeholder: placeholder, onChange: (e) => setTekst(e.target.value), onKeyDown: (e) => {
|
|
43
|
+
if (e.key === "Escape") {
|
|
44
|
+
e.stopPropagation();
|
|
45
|
+
if (tekst)
|
|
46
|
+
wis();
|
|
47
|
+
else
|
|
48
|
+
ref.current?.blur();
|
|
49
|
+
}
|
|
50
|
+
}, className: "h-10 w-full rounded-lg border border-input bg-card pl-9 pr-16 text-base text-foreground shadow-sm outline-none transition-shadow duration-150 placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring/40 sm:h-9 sm:text-sm [&::-webkit-search-cancel-button]:hidden" }), _jsx("div", { className: "absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-1", children: tekst ? (_jsx("button", { type: "button", onClick: wis, "aria-label": "Zoekopdracht wissen", className: "inline-flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx(X, { className: "h-4 w-4" }) })) : (_jsx("kbd", { className: "hidden rounded-sm border bg-muted px-1.5 text-[11px] text-muted-foreground md:inline", children: "/" })) })] }));
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type StatusTone = "klaar" | "open" | "bezig" | "fout";
|
|
3
|
+
/**
|
|
4
|
+
* Klein rond statusicoon met tooltip: groen klaar, grijs open, oker bezig, rood fout.
|
|
5
|
+
* Geen gekleurde vlakjes eromheen. Het label is de toegankelijke naam.
|
|
6
|
+
*/
|
|
7
|
+
export declare function StatusIcon({ tone, icon, label, detail }: {
|
|
8
|
+
tone: StatusTone;
|
|
9
|
+
icon: ReactNode;
|
|
10
|
+
label: string;
|
|
11
|
+
detail?: ReactNode;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=StatusIcon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusIcon.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/StatusIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAS7D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,+BAejI"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { HoverTip } from "./HoverTip.js";
|
|
3
|
+
const TONE = {
|
|
4
|
+
klaar: "text-primary",
|
|
5
|
+
open: "text-muted-foreground",
|
|
6
|
+
bezig: "text-warning-soft-foreground",
|
|
7
|
+
fout: "text-destructive",
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Klein rond statusicoon met tooltip: groen klaar, grijs open, oker bezig, rood fout.
|
|
11
|
+
* Geen gekleurde vlakjes eromheen. Het label is de toegankelijke naam.
|
|
12
|
+
*/
|
|
13
|
+
export function StatusIcon({ tone, icon, label, detail }) {
|
|
14
|
+
return (_jsx(HoverTip, { label: label, className: "h-6 w-6 [&_svg]:h-4 [&_svg]:w-4 " + TONE[tone], content: _jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-[13px] font-semibold text-foreground", children: label }), detail && _jsx("div", { className: "text-muted-foreground", children: detail })] }), children: icon }));
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Skeletrijen in de echte vorm van de tabel (60 px hoog, zelfde kolombreedtes). */
|
|
2
|
+
export declare function TableSkeleton({ columns, rows, media }: {
|
|
3
|
+
columns: Array<string | undefined>;
|
|
4
|
+
rows?: number;
|
|
5
|
+
media?: boolean;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=TableSkeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableSkeleton.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/TableSkeleton.tsx"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,IAAQ,EAAE,KAAY,EAAE,EAAE;IAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,+BAwBxI"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Skeleton } from "@flowselections/core";
|
|
3
|
+
/** Skeletrijen in de echte vorm van de tabel (60 px hoog, zelfde kolombreedtes). */
|
|
4
|
+
export function TableSkeleton({ columns, rows = 8, media = true }) {
|
|
5
|
+
return (_jsx(_Fragment, { children: Array.from({ length: rows }).map((_, r) => (_jsx("tr", { className: "h-[60px] border-b border-border last:border-0", "aria-hidden": true, children: columns.map((w, c) => (_jsx("td", { className: "px-3", style: w ? { width: w } : undefined, children: c === 0 && media ? (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "h-9 w-9 rounded-lg" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Skeleton, { className: "h-3.5 w-40" }), _jsx(Skeleton, { className: "h-3 w-24" })] })] })) : (_jsx(Skeleton, { className: "h-3.5 w-14" })) }, c))) }, r))) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** Werkbalk: zoekbalk links, knoppen (Filters, Kolommen) rechts; chips op de regel eronder. */
|
|
3
|
+
export declare function Toolbar({ children, right, chips }: {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
right?: ReactNode;
|
|
6
|
+
chips?: ReactNode;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=Toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../../src/components/fs-ui/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,+FAA+F;AAC/F,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,+BAUjH"}
|