@ramses1er/cbk-toolkit 1.4.9 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +44 -5
- package/dist/index.js +415 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { ReactNode, ComponentType } from 'react';
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import React__default, { ReactNode, ComponentType } from 'react';
|
|
3
3
|
|
|
4
4
|
type IconType = ReactNode | ComponentType<{
|
|
5
5
|
size?: number;
|
|
@@ -31,12 +31,12 @@ interface SideNavProps extends SideNavStaticConfig {
|
|
|
31
31
|
children: ReactNode;
|
|
32
32
|
currentPath: string;
|
|
33
33
|
}
|
|
34
|
-
declare function SideNav({ children, title, mainItems, currentPath, brand, footer, toggleIcon, }: SideNavProps):
|
|
34
|
+
declare function SideNav({ children, title, mainItems, currentPath, brand, footer, toggleIcon, }: SideNavProps): React$1.JSX.Element;
|
|
35
35
|
|
|
36
36
|
declare function createSideNav(config: SideNavStaticConfig): ({ children, currentPath, }: {
|
|
37
37
|
children: React.ReactNode;
|
|
38
38
|
currentPath: string;
|
|
39
|
-
}) =>
|
|
39
|
+
}) => React$1.JSX.Element;
|
|
40
40
|
|
|
41
41
|
declare class ApiError extends Error {
|
|
42
42
|
status: number;
|
|
@@ -54,6 +54,45 @@ type FetcherOptions = RequestInit & {
|
|
|
54
54
|
};
|
|
55
55
|
declare function fetcher<T = unknown>(url: string, options?: FetcherOptions): Promise<T>;
|
|
56
56
|
|
|
57
|
+
type Column<T> = {
|
|
58
|
+
header: string;
|
|
59
|
+
accessor?: keyof T;
|
|
60
|
+
render?: (row: T) => React.ReactNode;
|
|
61
|
+
excludeFromPrint?: boolean;
|
|
62
|
+
};
|
|
63
|
+
type TableProps<T> = {
|
|
64
|
+
data: T[];
|
|
65
|
+
columns: Column<T>[];
|
|
66
|
+
loading?: boolean;
|
|
67
|
+
error?: ApiError | null;
|
|
68
|
+
label?: string;
|
|
69
|
+
printable?: boolean;
|
|
70
|
+
pageSize?: number;
|
|
71
|
+
pageSizeOptions?: number[];
|
|
72
|
+
showPagination?: boolean;
|
|
73
|
+
};
|
|
74
|
+
declare function Table<T>({ data, columns, loading, error, label, printable, pageSize, pageSizeOptions, showPagination, }: TableProps<T>): React$1.JSX.Element;
|
|
75
|
+
|
|
76
|
+
type TableAction<T> = {
|
|
77
|
+
label: string;
|
|
78
|
+
icon: React__default.ReactNode;
|
|
79
|
+
callback: (row: T) => void;
|
|
80
|
+
color?: string;
|
|
81
|
+
};
|
|
82
|
+
type ActionsMenuProps<T> = {
|
|
83
|
+
row: T;
|
|
84
|
+
actions: TableAction<T>[];
|
|
85
|
+
};
|
|
86
|
+
declare function ActionsMenu<T>({ row, actions }: ActionsMenuProps<T>): React__default.JSX.Element;
|
|
87
|
+
|
|
88
|
+
type ModalProps = {
|
|
89
|
+
title: string;
|
|
90
|
+
isOpen: boolean;
|
|
91
|
+
onClose: () => void;
|
|
92
|
+
children: React__default.ReactNode | ((requestClose: () => void) => React__default.ReactNode);
|
|
93
|
+
};
|
|
94
|
+
declare function Modal({ title, isOpen, onClose, children }: ModalProps): React__default.ReactPortal | null;
|
|
95
|
+
|
|
57
96
|
declare class HttpError extends Error {
|
|
58
97
|
status: number;
|
|
59
98
|
code?: string;
|
|
@@ -69,4 +108,4 @@ declare class HttpError extends Error {
|
|
|
69
108
|
*/
|
|
70
109
|
declare function handleServerError(error: unknown, defaultStatus?: number, showDetails?: boolean): Response;
|
|
71
110
|
|
|
72
|
-
export { ApiError, type FetcherOptions, HttpError, type NavItem, SideNav, type SideNavProps, type SideNavStaticConfig, createSideNav, fetcher, handleServerError };
|
|
111
|
+
export { ActionsMenu, ApiError, type Column, type FetcherOptions, HttpError, Modal, type NavItem, SideNav, type SideNavProps, type SideNavStaticConfig, Table, type TableAction, createSideNav, fetcher, handleServerError };
|
package/dist/index.js
CHANGED
|
@@ -262,6 +262,418 @@ function createSideNav(config) {
|
|
|
262
262
|
};
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
// packages/ui/src/table/table.tsx
|
|
266
|
+
import { Printer, ChevronLeft, ChevronRight } from "lucide-react";
|
|
267
|
+
import clsx from "clsx";
|
|
268
|
+
import { useState as useState3, useMemo, useCallback } from "react";
|
|
269
|
+
|
|
270
|
+
// packages/ui/src/feedback/error-display.tsx
|
|
271
|
+
import { X } from "lucide-react";
|
|
272
|
+
import { useState as useState2 } from "react";
|
|
273
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
274
|
+
function ErrorDisplay({ error }) {
|
|
275
|
+
const [dismissed, setDismissed] = useState2(false);
|
|
276
|
+
if (!error || dismissed) return null;
|
|
277
|
+
return /* @__PURE__ */ jsx3("div", { className: "w-full overflow-x-auto", children: /* @__PURE__ */ jsx3("div", { className: "rounded-lg shadow-md border border-red-200 bg-red-50", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between gap-4 px-4 py-4", children: [
|
|
278
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", children: [
|
|
279
|
+
/* @__PURE__ */ jsx3("p", { className: "text-red-700 font-medium", children: "Erreur" }),
|
|
280
|
+
/* @__PURE__ */ jsx3("p", { className: "text-red-600 text-sm", children: error.message })
|
|
281
|
+
] }),
|
|
282
|
+
/* @__PURE__ */ jsx3(
|
|
283
|
+
"button",
|
|
284
|
+
{
|
|
285
|
+
onClick: () => setDismissed(true),
|
|
286
|
+
className: "text-red-400 hover:text-red-600 shrink-0 cursor-pointer",
|
|
287
|
+
children: /* @__PURE__ */ jsx3(X, { className: "w-5 h-5" })
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
] }) }) });
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// packages/ui/src/table/table.tsx
|
|
294
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
295
|
+
var VISIBLE_PAGES = 5;
|
|
296
|
+
function Table({
|
|
297
|
+
data,
|
|
298
|
+
columns,
|
|
299
|
+
loading,
|
|
300
|
+
error,
|
|
301
|
+
label,
|
|
302
|
+
printable,
|
|
303
|
+
pageSize = 5,
|
|
304
|
+
pageSizeOptions = [5, 10, 20],
|
|
305
|
+
showPagination = true
|
|
306
|
+
}) {
|
|
307
|
+
const [tooltip, setTooltip] = useState3(null);
|
|
308
|
+
const [page, setPage] = useState3(1);
|
|
309
|
+
const [perPage, setPerPage] = useState3(pageSize);
|
|
310
|
+
const totalPages = useMemo(
|
|
311
|
+
() => Math.max(1, Math.ceil(data.length / perPage)),
|
|
312
|
+
[data.length, perPage]
|
|
313
|
+
);
|
|
314
|
+
const safePage = Math.min(page, totalPages);
|
|
315
|
+
const displayData = useMemo(
|
|
316
|
+
() => data.slice((safePage - 1) * perPage, safePage * perPage),
|
|
317
|
+
[data, safePage, perPage]
|
|
318
|
+
);
|
|
319
|
+
const paginationRange = useMemo(() => {
|
|
320
|
+
const half = Math.floor(VISIBLE_PAGES / 2);
|
|
321
|
+
let start = Math.max(1, safePage - half);
|
|
322
|
+
let end = Math.min(totalPages, start + VISIBLE_PAGES - 1);
|
|
323
|
+
if (end - start + 1 < VISIBLE_PAGES) {
|
|
324
|
+
start = Math.max(1, end - VISIBLE_PAGES + 1);
|
|
325
|
+
}
|
|
326
|
+
const range = [];
|
|
327
|
+
if (start > 1) {
|
|
328
|
+
range.push(1);
|
|
329
|
+
if (start > 2) range.push("...");
|
|
330
|
+
}
|
|
331
|
+
for (let i = start; i <= end; i++) range.push(i);
|
|
332
|
+
if (end < totalPages) {
|
|
333
|
+
if (end < totalPages - 1) range.push("...");
|
|
334
|
+
range.push(totalPages);
|
|
335
|
+
}
|
|
336
|
+
return range;
|
|
337
|
+
}, [safePage, totalPages]);
|
|
338
|
+
const handlePageSizeChange = useCallback((value) => {
|
|
339
|
+
setPerPage(value);
|
|
340
|
+
setPage(1);
|
|
341
|
+
}, []);
|
|
342
|
+
const colCount = columns.length;
|
|
343
|
+
const colWidth = colCount > 0 ? `${Math.round(100 / colCount)}%` : "auto";
|
|
344
|
+
const handleMouseEnter = (e, content) => {
|
|
345
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
346
|
+
setTooltip({
|
|
347
|
+
content,
|
|
348
|
+
x: rect.left + rect.width / 2,
|
|
349
|
+
y: rect.top
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
const handleMouseLeave = () => {
|
|
353
|
+
setTooltip(null);
|
|
354
|
+
};
|
|
355
|
+
const banner = error ? /* @__PURE__ */ jsx4("div", { className: "mb-4", children: /* @__PURE__ */ jsx4(ErrorDisplay, { error }, error.message) }) : null;
|
|
356
|
+
if (loading) {
|
|
357
|
+
return /* @__PURE__ */ jsxs3("div", { className: "w-full overflow-x-auto", children: [
|
|
358
|
+
banner,
|
|
359
|
+
/* @__PURE__ */ jsx4("div", { className: "rounded-lg shadow-md border border-gray-200", children: /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center py-20 text-gray-500", children: "Chargement..." }) })
|
|
360
|
+
] });
|
|
361
|
+
}
|
|
362
|
+
if (!data || data.length === 0) {
|
|
363
|
+
return /* @__PURE__ */ jsxs3("div", { className: "w-full overflow-x-auto", children: [
|
|
364
|
+
banner,
|
|
365
|
+
/* @__PURE__ */ jsx4("div", { className: "rounded-lg shadow-md border border-gray-200", children: /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center py-20 text-gray-500", children: "Aucun \xE9l\xE9ment" }) })
|
|
366
|
+
] });
|
|
367
|
+
}
|
|
368
|
+
return /* @__PURE__ */ jsxs3("div", { className: "w-full overflow-x-auto", children: [
|
|
369
|
+
banner,
|
|
370
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mb-2", children: [
|
|
371
|
+
label && /* @__PURE__ */ jsxs3("div", { className: "text-sm font-semibold text-gray-700", children: [
|
|
372
|
+
label,
|
|
373
|
+
": ",
|
|
374
|
+
data.length
|
|
375
|
+
] }),
|
|
376
|
+
printable && /* @__PURE__ */ jsxs3(
|
|
377
|
+
"button",
|
|
378
|
+
{
|
|
379
|
+
onClick: () => window.print(),
|
|
380
|
+
className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 transition-colors print:hidden",
|
|
381
|
+
children: [
|
|
382
|
+
/* @__PURE__ */ jsx4(Printer, { className: "w-4 h-4" }),
|
|
383
|
+
"Imprimer"
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
] }),
|
|
388
|
+
/* @__PURE__ */ jsx4("div", { className: "rounded-lg shadow-md border border-gray-200", children: /* @__PURE__ */ jsxs3("table", { className: "w-full table-fixed divide-y divide-gray-200 print:table-fixed", children: [
|
|
389
|
+
/* @__PURE__ */ jsx4("thead", { className: "bg-blue-500 rounded-t-lg", children: /* @__PURE__ */ jsx4("tr", { children: columns.map((col, index) => /* @__PURE__ */ jsx4(
|
|
390
|
+
"th",
|
|
391
|
+
{
|
|
392
|
+
style: { width: colWidth },
|
|
393
|
+
className: clsx(
|
|
394
|
+
"px-6 py-3 text-left text-xs font-bold text-white uppercase tracking-wider truncate",
|
|
395
|
+
col.excludeFromPrint && "print:hidden"
|
|
396
|
+
),
|
|
397
|
+
children: col.header
|
|
398
|
+
},
|
|
399
|
+
index
|
|
400
|
+
)) }) }),
|
|
401
|
+
/* @__PURE__ */ jsx4(
|
|
402
|
+
"tbody",
|
|
403
|
+
{
|
|
404
|
+
className: clsx(
|
|
405
|
+
"bg-white divide-y divide-gray-200",
|
|
406
|
+
printable && "print:hidden"
|
|
407
|
+
),
|
|
408
|
+
children: displayData.map((row, rowIndex) => /* @__PURE__ */ jsx4(
|
|
409
|
+
"tr",
|
|
410
|
+
{
|
|
411
|
+
className: "hover:bg-gray-100 transition-colors duration-200",
|
|
412
|
+
children: columns.map((col, colIndex) => {
|
|
413
|
+
const cellContent = col.render ? col.render(row) : String(row[col.accessor]);
|
|
414
|
+
const textContent = typeof cellContent === "string" ? cellContent : "";
|
|
415
|
+
return /* @__PURE__ */ jsx4(
|
|
416
|
+
"td",
|
|
417
|
+
{
|
|
418
|
+
style: { width: colWidth },
|
|
419
|
+
className: clsx(
|
|
420
|
+
"px-6 py-4 text-sm text-gray-700",
|
|
421
|
+
col.excludeFromPrint && "print:hidden"
|
|
422
|
+
),
|
|
423
|
+
children: typeof cellContent === "string" ? /* @__PURE__ */ jsx4(
|
|
424
|
+
"div",
|
|
425
|
+
{
|
|
426
|
+
className: "truncate",
|
|
427
|
+
onMouseEnter: (e) => handleMouseEnter(e, textContent),
|
|
428
|
+
onMouseLeave: handleMouseLeave,
|
|
429
|
+
children: cellContent
|
|
430
|
+
}
|
|
431
|
+
) : cellContent
|
|
432
|
+
},
|
|
433
|
+
colIndex
|
|
434
|
+
);
|
|
435
|
+
})
|
|
436
|
+
},
|
|
437
|
+
rowIndex
|
|
438
|
+
))
|
|
439
|
+
}
|
|
440
|
+
),
|
|
441
|
+
printable && /* @__PURE__ */ jsx4("tbody", { className: "hidden print:table-row-group", children: data.map((row, rowIndex) => /* @__PURE__ */ jsx4("tr", { children: columns.map((col, colIndex) => {
|
|
442
|
+
const cellContent = col.render ? col.render(row) : String(row[col.accessor]);
|
|
443
|
+
return /* @__PURE__ */ jsx4(
|
|
444
|
+
"td",
|
|
445
|
+
{
|
|
446
|
+
style: { width: colWidth },
|
|
447
|
+
className: clsx(
|
|
448
|
+
"px-6 py-4 text-sm text-gray-700",
|
|
449
|
+
col.excludeFromPrint && "print:hidden"
|
|
450
|
+
),
|
|
451
|
+
children: cellContent
|
|
452
|
+
},
|
|
453
|
+
colIndex
|
|
454
|
+
);
|
|
455
|
+
}) }, rowIndex)) })
|
|
456
|
+
] }) }),
|
|
457
|
+
showPagination && totalPages > 1 && /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mt-4 text-sm print:hidden", children: [
|
|
458
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-gray-600", children: [
|
|
459
|
+
/* @__PURE__ */ jsx4("span", { children: "Lignes par page :" }),
|
|
460
|
+
/* @__PURE__ */ jsx4(
|
|
461
|
+
"select",
|
|
462
|
+
{
|
|
463
|
+
value: perPage,
|
|
464
|
+
onChange: (e) => handlePageSizeChange(Number(e.target.value)),
|
|
465
|
+
className: "border border-gray-300 rounded px-2 py-1 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-blue-400",
|
|
466
|
+
children: pageSizeOptions.map((opt) => /* @__PURE__ */ jsx4("option", { value: opt, children: opt }, opt))
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
] }),
|
|
470
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
471
|
+
/* @__PURE__ */ jsx4(
|
|
472
|
+
"button",
|
|
473
|
+
{
|
|
474
|
+
onClick: () => setPage((p) => Math.max(1, p - 1)),
|
|
475
|
+
disabled: safePage <= 1,
|
|
476
|
+
className: clsx(
|
|
477
|
+
"p-1.5 rounded transition-colors",
|
|
478
|
+
safePage <= 1 ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"
|
|
479
|
+
),
|
|
480
|
+
children: /* @__PURE__ */ jsx4(ChevronLeft, { className: "w-4 h-4" })
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
paginationRange.map(
|
|
484
|
+
(item, i) => item === "..." ? /* @__PURE__ */ jsx4("span", { className: "px-2 text-gray-400", children: "..." }, `ellipsis-${i}`) : /* @__PURE__ */ jsx4(
|
|
485
|
+
"button",
|
|
486
|
+
{
|
|
487
|
+
onClick: () => setPage(item),
|
|
488
|
+
className: clsx(
|
|
489
|
+
"min-w-8 px-2 py-1 rounded text-sm font-medium transition-colors",
|
|
490
|
+
item === safePage ? "bg-blue-500 text-white" : "text-gray-600 hover:bg-gray-100"
|
|
491
|
+
),
|
|
492
|
+
children: item
|
|
493
|
+
},
|
|
494
|
+
item
|
|
495
|
+
)
|
|
496
|
+
),
|
|
497
|
+
/* @__PURE__ */ jsx4(
|
|
498
|
+
"button",
|
|
499
|
+
{
|
|
500
|
+
onClick: () => setPage((p) => Math.min(totalPages, p + 1)),
|
|
501
|
+
disabled: safePage >= totalPages,
|
|
502
|
+
className: clsx(
|
|
503
|
+
"p-1.5 rounded transition-colors",
|
|
504
|
+
safePage >= totalPages ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"
|
|
505
|
+
),
|
|
506
|
+
children: /* @__PURE__ */ jsx4(ChevronRight, { className: "w-4 h-4" })
|
|
507
|
+
}
|
|
508
|
+
)
|
|
509
|
+
] }),
|
|
510
|
+
/* @__PURE__ */ jsxs3("div", { className: "text-gray-500", children: [
|
|
511
|
+
"Page ",
|
|
512
|
+
safePage,
|
|
513
|
+
" sur ",
|
|
514
|
+
totalPages
|
|
515
|
+
] })
|
|
516
|
+
] }),
|
|
517
|
+
tooltip && /* @__PURE__ */ jsx4(
|
|
518
|
+
"div",
|
|
519
|
+
{
|
|
520
|
+
className: "fixed z-20 px-3 py-2 text-sm text-white bg-gray-800 rounded-lg shadow-lg pointer-events-none whitespace-nowrap",
|
|
521
|
+
style: {
|
|
522
|
+
left: tooltip.x,
|
|
523
|
+
top: tooltip.y - 8,
|
|
524
|
+
transform: "translate(-50%, -100%)"
|
|
525
|
+
},
|
|
526
|
+
children: tooltip.content
|
|
527
|
+
}
|
|
528
|
+
),
|
|
529
|
+
/* @__PURE__ */ jsx4("style", { children: `
|
|
530
|
+
@media print {
|
|
531
|
+
body * { visibility: hidden; }
|
|
532
|
+
.w-full.overflow-x-auto { visibility: visible; }
|
|
533
|
+
.w-full.overflow-x-auto * { visibility: visible; }
|
|
534
|
+
.w-full.overflow-x-auto { position: absolute; left: 0; top: 0; width: 100%; }
|
|
535
|
+
}
|
|
536
|
+
` })
|
|
537
|
+
] });
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// packages/ui/src/table/actions-menu.tsx
|
|
541
|
+
import { useState as useState4, useRef, useEffect as useEffect2 } from "react";
|
|
542
|
+
import { Ellipsis } from "lucide-react";
|
|
543
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
544
|
+
function ActionsMenu({ row, actions }) {
|
|
545
|
+
const [isOpen, setIsOpen] = useState4(false);
|
|
546
|
+
const [coords, setCoords] = useState4({ top: 0, left: 0 });
|
|
547
|
+
const buttonRef = useRef(null);
|
|
548
|
+
const menuRef = useRef(null);
|
|
549
|
+
useEffect2(() => {
|
|
550
|
+
function handleClickOutside(event) {
|
|
551
|
+
if (menuRef.current && buttonRef.current && !menuRef.current.contains(event.target) && !buttonRef.current.contains(event.target)) {
|
|
552
|
+
setIsOpen(false);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
556
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
557
|
+
}, []);
|
|
558
|
+
const toggleMenu = () => {
|
|
559
|
+
if (buttonRef.current) {
|
|
560
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
561
|
+
const menuWidth = 180;
|
|
562
|
+
const menuHeight = actions.length * 40;
|
|
563
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
564
|
+
const spaceRight = window.innerWidth - rect.left;
|
|
565
|
+
let top = rect.bottom;
|
|
566
|
+
let left = rect.left;
|
|
567
|
+
if (spaceBelow < menuHeight + 20) {
|
|
568
|
+
top = rect.top - menuHeight;
|
|
569
|
+
}
|
|
570
|
+
if (spaceRight < menuWidth + 20) {
|
|
571
|
+
left = rect.left - menuWidth + 30;
|
|
572
|
+
}
|
|
573
|
+
setCoords({ top, left });
|
|
574
|
+
}
|
|
575
|
+
setIsOpen(!isOpen);
|
|
576
|
+
};
|
|
577
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
578
|
+
/* @__PURE__ */ jsx5(
|
|
579
|
+
"button",
|
|
580
|
+
{
|
|
581
|
+
ref: buttonRef,
|
|
582
|
+
onClick: toggleMenu,
|
|
583
|
+
className: "p-1 hover:bg-gray-100 rounded-full",
|
|
584
|
+
children: /* @__PURE__ */ jsx5(Ellipsis, { className: "w-5 h-5" })
|
|
585
|
+
}
|
|
586
|
+
),
|
|
587
|
+
isOpen && /* @__PURE__ */ jsx5(
|
|
588
|
+
"div",
|
|
589
|
+
{
|
|
590
|
+
ref: menuRef,
|
|
591
|
+
className: "fixed bg-white border border-gray-200 rounded shadow-lg z-20",
|
|
592
|
+
style: {
|
|
593
|
+
top: coords.top,
|
|
594
|
+
left: coords.left,
|
|
595
|
+
minWidth: 180
|
|
596
|
+
},
|
|
597
|
+
children: actions.map((action, idx) => /* @__PURE__ */ jsxs4(
|
|
598
|
+
"button",
|
|
599
|
+
{
|
|
600
|
+
className: `flex items-center gap-2 px-4 py-2 w-full text-sm hover:bg-gray-100 ${action.color || "text-gray-700"}`,
|
|
601
|
+
onClick: () => {
|
|
602
|
+
action.callback(row);
|
|
603
|
+
setIsOpen(false);
|
|
604
|
+
},
|
|
605
|
+
children: [
|
|
606
|
+
action.icon,
|
|
607
|
+
action.label
|
|
608
|
+
]
|
|
609
|
+
},
|
|
610
|
+
idx
|
|
611
|
+
))
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
] });
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// packages/ui/src/modals/modal.tsx
|
|
618
|
+
import { X as X2 } from "lucide-react";
|
|
619
|
+
import { useEffect as useEffect3 } from "react";
|
|
620
|
+
import { createPortal } from "react-dom";
|
|
621
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
622
|
+
function Modal({ title, isOpen, onClose, children }) {
|
|
623
|
+
const requestClose = () => {
|
|
624
|
+
onClose();
|
|
625
|
+
};
|
|
626
|
+
useEffect3(() => {
|
|
627
|
+
if (isOpen) {
|
|
628
|
+
document.body.style.overflow = "hidden";
|
|
629
|
+
}
|
|
630
|
+
return () => {
|
|
631
|
+
document.body.style.overflow = "";
|
|
632
|
+
};
|
|
633
|
+
}, [isOpen]);
|
|
634
|
+
useEffect3(() => {
|
|
635
|
+
function handleEsc(e) {
|
|
636
|
+
if (e.key === "Escape") {
|
|
637
|
+
onClose();
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (isOpen) {
|
|
641
|
+
document.addEventListener("keydown", handleEsc);
|
|
642
|
+
}
|
|
643
|
+
return () => {
|
|
644
|
+
document.removeEventListener("keydown", handleEsc);
|
|
645
|
+
};
|
|
646
|
+
}, [isOpen, onClose]);
|
|
647
|
+
if (!isOpen) return null;
|
|
648
|
+
const content = typeof children === "function" ? children(requestClose) : children;
|
|
649
|
+
return createPortal(
|
|
650
|
+
/* @__PURE__ */ jsxs5("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
651
|
+
/* @__PURE__ */ jsx6(
|
|
652
|
+
"div",
|
|
653
|
+
{
|
|
654
|
+
className: "absolute inset-0 bg-black/20 backdrop-blur-sm",
|
|
655
|
+
onClick: onClose
|
|
656
|
+
}
|
|
657
|
+
),
|
|
658
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative bg-white rounded-lg shadow-lg w-full max-w-2xl mx-4 p-6 flex flex-col max-h-[85vh]", children: [
|
|
659
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between mb-4 border-b-2 border-gray-400 pb-3 sticky top-0 bg-white z-10", children: [
|
|
660
|
+
/* @__PURE__ */ jsx6("h2", { className: "text-lg font-semibold text-gray-900", children: title }),
|
|
661
|
+
/* @__PURE__ */ jsx6(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
onClick: onClose,
|
|
665
|
+
className: "text-gray-500 hover:text-gray-700 text-xl cursor-pointer",
|
|
666
|
+
children: /* @__PURE__ */ jsx6(X2, {})
|
|
667
|
+
}
|
|
668
|
+
)
|
|
669
|
+
] }),
|
|
670
|
+
/* @__PURE__ */ jsx6("div", { className: "overflow-y-auto flex-1 min-h-0", children: content })
|
|
671
|
+
] })
|
|
672
|
+
] }),
|
|
673
|
+
document.body
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
|
|
265
677
|
// packages/utils/src/fetcher.ts
|
|
266
678
|
var ApiError = class extends Error {
|
|
267
679
|
status;
|
|
@@ -367,9 +779,12 @@ function handleServerError(error, defaultStatus = 500, showDetails) {
|
|
|
367
779
|
);
|
|
368
780
|
}
|
|
369
781
|
export {
|
|
782
|
+
ActionsMenu,
|
|
370
783
|
ApiError,
|
|
371
784
|
HttpError,
|
|
785
|
+
Modal,
|
|
372
786
|
SideNav,
|
|
787
|
+
Table,
|
|
373
788
|
createSideNav,
|
|
374
789
|
fetcher,
|
|
375
790
|
handleServerError
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../packages/ui/src/layouts/side-nav.tsx","../packages/ui/src/config/create-side-nav.tsx","../packages/utils/src/fetcher.ts","../packages/lib/src/http-error.ts","../packages/lib/src/handle-server-error.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n ReactNode,\r\n useState,\r\n useEffect,\r\n createElement,\r\n isValidElement,\r\n type ComponentType,\r\n} from \"react\";\r\n\r\ntype IconType = ReactNode | ComponentType<{ size?: number }>;\r\n\r\nexport interface NavItem {\r\n id: string;\r\n label: string;\r\n title?: string;\r\n icon?: IconType;\r\n href: string;\r\n subItems?: NavItem[];\r\n}\r\n\r\nexport interface SideNavStaticConfig {\r\n brand?: {\r\n logo?: ReactNode;\r\n name?: string;\r\n tagline?: string;\r\n };\r\n mainItems: NavItem[];\r\n title?: string;\r\n footer?: { icon?: IconType; label: string; href: string }[];\r\n toggleIcon?: ReactNode;\r\n}\r\n\r\nexport interface SideNavProps extends SideNavStaticConfig {\r\n children: ReactNode;\r\n currentPath: string;\r\n}\r\n\r\nfunction isActive(href: string, currentPath: string) {\r\n return currentPath === href || currentPath.startsWith(href + \"/\");\r\n}\r\n\r\nfunction isExactActive(href: string, currentPath: string) {\r\n return currentPath === href;\r\n}\r\n\r\nexport function SideNav({\r\n children,\r\n title,\r\n mainItems,\r\n currentPath,\r\n brand,\r\n footer,\r\n toggleIcon,\r\n}: SideNavProps) {\r\n const activeMain = mainItems.find((item) => isActive(item.href, currentPath));\r\n const headerTitle = title ?? activeMain?.title ?? activeMain?.label;\r\n const [expandedSection, setExpandedSection] = useState<string | null>(\r\n activeMain?.id ?? null,\r\n );\r\n\r\n const toggleSection = (id: string) => {\r\n setExpandedSection((prev) => (prev === id ? null : id));\r\n };\r\n\r\n const [isMobileOpen, setIsMobileOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") setIsMobileOpen(false);\r\n };\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isMobileOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"\";\r\n }\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isMobileOpen]);\r\n\r\n const closeMobileNav = () => setIsMobileOpen(false);\r\n\r\n return (\r\n <div className=\"flex min-h-screen\">\r\n <aside\r\n className={`w-64 bg-white border-r border-gray-200 flex flex-col fixed h-full z-50 transition-transform duration-300 ease-in-out md:translate-x-0 ${\r\n isMobileOpen ? \"translate-x-0\" : \"-translate-x-full\"\r\n }`}\r\n >\r\n {brand && (\r\n <div className=\"p-[6.5px] border-b border-gray-100\">\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n {brand.logo &&\r\n (typeof brand.logo === \"string\" ? (\r\n <img\r\n src={brand.logo}\r\n alt={brand.name ?? \"\"}\r\n className=\"w-12.5 h-12.5\"\r\n />\r\n ) : (\r\n brand.logo\r\n ))}\r\n {brand.name && (\r\n <p className=\"text-gray-500 text-base font-semibold\">\r\n {brand.name}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <nav className=\"flex-1 p-4 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {mainItems.map((item) => {\r\n const active = isActive(item.href, currentPath);\r\n const isExpanded = expandedSection === item.id;\r\n const hasSubItems = item.subItems && item.subItems.length > 0;\r\n\r\n return (\r\n <li key={item.id}>\r\n <div className=\"flex items-center gap-1\">\r\n <a\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors flex-1 ${\r\n active\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {item.icon &&\r\n (typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(\r\n item.icon as ComponentType<{ size?: number }>,\r\n { size: 20 },\r\n )\r\n ))}\r\n {item.label}\r\n </a>\r\n {active && hasSubItems && (\r\n <button\r\n onClick={() => toggleSection(item.id)}\r\n className={`p-1.5 rounded-lg transition-colors ${\r\n active\r\n ? \"text-black hover:bg-gray-100\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n title={isExpanded ? \"Réduire\" : \"Développer\"}\r\n >\r\n {toggleIcon ? (\r\n <span\r\n className={`inline-block transition-transform duration-200 ${\r\n isExpanded ? \"rotate-0\" : \"-rotate-90\"\r\n }`}\r\n >\r\n {toggleIcon}\r\n </span>\r\n ) : (\r\n <span className=\"text-xs\">\r\n {isExpanded ? \"▼\" : \"▶\"}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {active && hasSubItems && (\r\n <div\r\n className={`grid transition-all duration-300 ease-in-out ${\r\n isExpanded ? \"grid-rows-[1fr]\" : \"grid-rows-[0fr]\"\r\n }`}\r\n >\r\n <div className=\"overflow-hidden\">\r\n <ul className=\"ml-4 mt-1 space-y-1 pl-2\">\r\n {item.subItems!.map((sub) => (\r\n <li key={sub.id}>\r\n <a\r\n href={sub.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${\r\n isExactActive(sub.href, currentPath)\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {sub.label}\r\n </a>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {footer && footer.length > 0 && (\r\n <div className=\"p-4 border-t border-gray-100 space-y-1\">\r\n {footer.map((item) => (\r\n <a\r\n key={item.label}\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className=\"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors\"\r\n >\r\n {typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(item.icon as ComponentType<{ size?: number }>, {\r\n size: 20,\r\n })\r\n )}\r\n {item.label}\r\n </a>\r\n ))}\r\n </div>\r\n )}\r\n </aside>\r\n\r\n {isMobileOpen && (\r\n <div\r\n className=\"fixed inset-0 z-40 bg-black/50 md:hidden\"\r\n onClick={closeMobileNav}\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n\r\n <div className=\"flex-1 ml-64 max-md:ml-0 min-w-0\">\r\n {headerTitle && (\r\n <header className=\"h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6 fixed top-0 right-0 left-64 max-md:left-0 z-20\">\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n className=\"md:hidden p-2 -ml-2 rounded-lg hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <h1 className=\"text-base font-semibold text-gray-500\">\r\n {headerTitle}\r\n </h1>\r\n </div>\r\n {brand?.tagline && (\r\n <span className=\"text-sm text-gray-500 max-md:hidden\">\r\n {brand.tagline}\r\n </span>\r\n )}\r\n </header>\r\n )}\r\n {!headerTitle && (\r\n <button\r\n className=\"md:hidden fixed top-4 left-4 z-10 p-2 rounded-lg bg-white border border-gray-200 shadow-sm hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n <main\r\n className={(headerTitle ? \"p-6 pt-20\" : \"p-6\") + \" overflow-x-auto\"}\r\n >\r\n {children}\r\n </main>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { SideNav, type SideNavStaticConfig } from \"../layouts/side-nav\";\n\nexport function createSideNav(config: SideNavStaticConfig) {\n return function ConfiguredSideNav({\n children,\n currentPath,\n }: {\n children: React.ReactNode;\n currentPath: string;\n }) {\n return (\n <SideNav {...config} currentPath={currentPath}>\n {children}\n </SideNav>\n );\n };\n}\n","export class ApiError extends Error {\r\n public status: number;\r\n public code?: string;\r\n public data?: unknown;\r\n\r\n constructor(params: {\r\n message: string;\r\n status: number;\r\n code?: string;\r\n data?: unknown;\r\n }) {\r\n super(params.message);\r\n this.status = params.status;\r\n this.code = params.code;\r\n this.data = params.data;\r\n }\r\n}\r\n\r\ntype BackendErrorShape = {\r\n code?: string;\r\n status?: number;\r\n message?: string;\r\n};\r\n\r\nexport type FetcherOptions = RequestInit & {\r\n skipJsonParsing?: boolean;\r\n};\r\n\r\nexport async function fetcher<T = unknown>(\r\n url: string,\r\n options: FetcherOptions = {},\r\n): Promise<T> {\r\n const { headers, skipJsonParsing = false, ...rest } = options;\r\n\r\n const response = await fetch(url, {\r\n credentials: \"include\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...headers,\r\n },\r\n ...rest,\r\n });\r\n\r\n let responseData: unknown = null;\r\n const contentType = response.headers.get(\"content-type\");\r\n\r\n if (!skipJsonParsing && contentType?.includes(\"application/json\")) {\r\n responseData = await response.json();\r\n }\r\n\r\n if (!response.ok) {\r\n const backendError = responseData as BackendErrorShape;\r\n\r\n throw new ApiError({\r\n message: backendError?.message || \"Une erreur est survenue\",\r\n status: backendError?.status || response.status,\r\n code: backendError?.code,\r\n data: responseData,\r\n });\r\n }\r\n\r\n return responseData as T;\r\n}\r\n","export class HttpError extends Error {\r\n status: number;\r\n code?: string;\r\n\r\n constructor(message: string, status = 400, code?: string) {\r\n super(message);\r\n\r\n this.name = \"HttpError\";\r\n this.status = status;\r\n this.code = code;\r\n\r\n Object.setPrototypeOf(this, HttpError.prototype);\r\n }\r\n}\r\n","import { HttpError } from \"./http-error\";\r\n\r\nconst GENERIC_MESSAGE = \"Erreur serveur\";\r\n\r\nfunction shouldShowDetails(showDetails?: boolean): boolean {\r\n return showDetails ?? process.env.NODE_ENV !== \"production\";\r\n}\r\n\r\nfunction sanitizedResponse(\r\n message: string,\r\n code: string,\r\n status: number,\r\n showDetails?: boolean,\r\n) {\r\n return Response.json(\r\n {\r\n message: showDetails ? message : GENERIC_MESSAGE,\r\n code: showDetails ? code : \"INTERNAL_ERROR\",\r\n status,\r\n },\r\n { status },\r\n );\r\n}\r\n\r\n/**\r\n * Transforme n'importe quelle erreur en réponse JSON standardisée\r\n * @param error L'erreur levée\r\n * @param defaultStatus Statut HTTP par défaut si non défini\r\n * @param showDetails Force l'affichage des détails (true) ou le mode sécurisé (false). Par défaut : automatique selon NODE_ENV\r\n * @returns Response JSON\r\n */\r\nexport function handleServerError(\r\n error: unknown,\r\n defaultStatus = 500,\r\n showDetails?: boolean,\r\n) {\r\n const details = shouldShowDetails(showDetails);\r\n\r\n console.error(\"Erreur capturée :\", error);\r\n\r\n // Cas HttpError personnalisé — toujours visible (erreur intentionnelle)\r\n if (error instanceof HttpError) {\r\n const status = error.status ?? defaultStatus;\r\n return Response.json(\r\n {\r\n message: error.message,\r\n code: error.code ?? \"INTERNAL_ERROR\",\r\n status,\r\n },\r\n { status },\r\n );\r\n }\r\n\r\n // Cas classique : objet Error\r\n if (error instanceof Error) {\r\n return sanitizedResponse(\r\n error.message,\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n }\r\n\r\n // Cas objet brut ou autre type\r\n if (typeof error === \"object\" && error !== null) {\r\n return sanitizedResponse(\r\n JSON.stringify(error),\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n }\r\n\r\n // Cas fallback : string ou autre\r\n return sanitizedResponse(\r\n String(error),\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx"]}
|
|
1
|
+
{"version":3,"sources":["../packages/ui/src/layouts/side-nav.tsx","../packages/ui/src/config/create-side-nav.tsx","../packages/ui/src/table/table.tsx","../packages/ui/src/feedback/error-display.tsx","../packages/ui/src/table/actions-menu.tsx","../packages/ui/src/modals/modal.tsx","../packages/utils/src/fetcher.ts","../packages/lib/src/http-error.ts","../packages/lib/src/handle-server-error.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n ReactNode,\r\n useState,\r\n useEffect,\r\n createElement,\r\n isValidElement,\r\n type ComponentType,\r\n} from \"react\";\r\n\r\ntype IconType = ReactNode | ComponentType<{ size?: number }>;\r\n\r\nexport interface NavItem {\r\n id: string;\r\n label: string;\r\n title?: string;\r\n icon?: IconType;\r\n href: string;\r\n subItems?: NavItem[];\r\n}\r\n\r\nexport interface SideNavStaticConfig {\r\n brand?: {\r\n logo?: ReactNode;\r\n name?: string;\r\n tagline?: string;\r\n };\r\n mainItems: NavItem[];\r\n title?: string;\r\n footer?: { icon?: IconType; label: string; href: string }[];\r\n toggleIcon?: ReactNode;\r\n}\r\n\r\nexport interface SideNavProps extends SideNavStaticConfig {\r\n children: ReactNode;\r\n currentPath: string;\r\n}\r\n\r\nfunction isActive(href: string, currentPath: string) {\r\n return currentPath === href || currentPath.startsWith(href + \"/\");\r\n}\r\n\r\nfunction isExactActive(href: string, currentPath: string) {\r\n return currentPath === href;\r\n}\r\n\r\nexport function SideNav({\r\n children,\r\n title,\r\n mainItems,\r\n currentPath,\r\n brand,\r\n footer,\r\n toggleIcon,\r\n}: SideNavProps) {\r\n const activeMain = mainItems.find((item) => isActive(item.href, currentPath));\r\n const headerTitle = title ?? activeMain?.title ?? activeMain?.label;\r\n const [expandedSection, setExpandedSection] = useState<string | null>(\r\n activeMain?.id ?? null,\r\n );\r\n\r\n const toggleSection = (id: string) => {\r\n setExpandedSection((prev) => (prev === id ? null : id));\r\n };\r\n\r\n const [isMobileOpen, setIsMobileOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") setIsMobileOpen(false);\r\n };\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isMobileOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"\";\r\n }\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isMobileOpen]);\r\n\r\n const closeMobileNav = () => setIsMobileOpen(false);\r\n\r\n return (\r\n <div className=\"flex min-h-screen\">\r\n <aside\r\n className={`w-64 bg-white border-r border-gray-200 flex flex-col fixed h-full z-50 transition-transform duration-300 ease-in-out md:translate-x-0 ${\r\n isMobileOpen ? \"translate-x-0\" : \"-translate-x-full\"\r\n }`}\r\n >\r\n {brand && (\r\n <div className=\"p-[6.5px] border-b border-gray-100\">\r\n <div className=\"flex flex-row gap-2 items-center\">\r\n {brand.logo &&\r\n (typeof brand.logo === \"string\" ? (\r\n <img\r\n src={brand.logo}\r\n alt={brand.name ?? \"\"}\r\n className=\"w-12.5 h-12.5\"\r\n />\r\n ) : (\r\n brand.logo\r\n ))}\r\n {brand.name && (\r\n <p className=\"text-gray-500 text-base font-semibold\">\r\n {brand.name}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <nav className=\"flex-1 p-4 overflow-y-auto\">\r\n <ul className=\"space-y-1\">\r\n {mainItems.map((item) => {\r\n const active = isActive(item.href, currentPath);\r\n const isExpanded = expandedSection === item.id;\r\n const hasSubItems = item.subItems && item.subItems.length > 0;\r\n\r\n return (\r\n <li key={item.id}>\r\n <div className=\"flex items-center gap-1\">\r\n <a\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors flex-1 ${\r\n active\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {item.icon &&\r\n (typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(\r\n item.icon as ComponentType<{ size?: number }>,\r\n { size: 20 },\r\n )\r\n ))}\r\n {item.label}\r\n </a>\r\n {active && hasSubItems && (\r\n <button\r\n onClick={() => toggleSection(item.id)}\r\n className={`p-1.5 rounded-lg transition-colors ${\r\n active\r\n ? \"text-black hover:bg-gray-100\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n title={isExpanded ? \"Réduire\" : \"Développer\"}\r\n >\r\n {toggleIcon ? (\r\n <span\r\n className={`inline-block transition-transform duration-200 ${\r\n isExpanded ? \"rotate-0\" : \"-rotate-90\"\r\n }`}\r\n >\r\n {toggleIcon}\r\n </span>\r\n ) : (\r\n <span className=\"text-xs\">\r\n {isExpanded ? \"▼\" : \"▶\"}\r\n </span>\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {active && hasSubItems && (\r\n <div\r\n className={`grid transition-all duration-300 ease-in-out ${\r\n isExpanded ? \"grid-rows-[1fr]\" : \"grid-rows-[0fr]\"\r\n }`}\r\n >\r\n <div className=\"overflow-hidden\">\r\n <ul className=\"ml-4 mt-1 space-y-1 pl-2\">\r\n {item.subItems!.map((sub) => (\r\n <li key={sub.id}>\r\n <a\r\n href={sub.href}\r\n onClick={closeMobileNav}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${\r\n isExactActive(sub.href, currentPath)\r\n ? \"bg-gray-200 text-black\"\r\n : \"text-gray-500 hover:bg-gray-100\"\r\n }`}\r\n >\r\n {sub.label}\r\n </a>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n </div>\r\n )}\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {footer && footer.length > 0 && (\r\n <div className=\"p-4 border-t border-gray-100 space-y-1\">\r\n {footer.map((item) => (\r\n <a\r\n key={item.label}\r\n href={item.href}\r\n onClick={closeMobileNav}\r\n className=\"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-100 transition-colors\"\r\n >\r\n {typeof item.icon === \"string\" ? (\r\n <span className=\"text-lg\">{item.icon}</span>\r\n ) : isValidElement(item.icon) ? (\r\n item.icon\r\n ) : (\r\n createElement(item.icon as ComponentType<{ size?: number }>, {\r\n size: 20,\r\n })\r\n )}\r\n {item.label}\r\n </a>\r\n ))}\r\n </div>\r\n )}\r\n </aside>\r\n\r\n {isMobileOpen && (\r\n <div\r\n className=\"fixed inset-0 z-40 bg-black/50 md:hidden\"\r\n onClick={closeMobileNav}\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n\r\n <div className=\"flex-1 ml-64 max-md:ml-0 min-w-0\">\r\n {headerTitle && (\r\n <header className=\"h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6 fixed top-0 right-0 left-64 max-md:left-0 z-20\">\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n className=\"md:hidden p-2 -ml-2 rounded-lg hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <h1 className=\"text-base font-semibold text-gray-500\">\r\n {headerTitle}\r\n </h1>\r\n </div>\r\n {brand?.tagline && (\r\n <span className=\"text-sm text-gray-500 max-md:hidden\">\r\n {brand.tagline}\r\n </span>\r\n )}\r\n </header>\r\n )}\r\n {!headerTitle && (\r\n <button\r\n className=\"md:hidden fixed top-4 left-4 z-10 p-2 rounded-lg bg-white border border-gray-200 shadow-sm hover:bg-gray-100 transition-colors\"\r\n onClick={() => setIsMobileOpen(!isMobileOpen)}\r\n aria-label={isMobileOpen ? \"Fermer le menu\" : \"Menu\"}\r\n aria-expanded={isMobileOpen}\r\n >\r\n {isMobileOpen ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n strokeWidth={2}\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n d=\"M4 6h16M4 12h16M4 18h16\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n <main\r\n className={(headerTitle ? \"p-6 pt-20\" : \"p-6\") + \" overflow-x-auto\"}\r\n >\r\n {children}\r\n </main>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { SideNav, type SideNavStaticConfig } from \"../layouts/side-nav\";\n\nexport function createSideNav(config: SideNavStaticConfig) {\n return function ConfiguredSideNav({\n children,\n currentPath,\n }: {\n children: React.ReactNode;\n currentPath: string;\n }) {\n return (\n <SideNav {...config} currentPath={currentPath}>\n {children}\n </SideNav>\n );\n };\n}\n","\"use client\";\r\n\r\nimport { Printer, ChevronLeft, ChevronRight } from \"lucide-react\";\r\nimport clsx from \"clsx\";\r\nimport { useState, useMemo, useCallback } from \"react\";\r\nimport { ErrorDisplay } from \"../feedback/error-display\";\r\nimport { ApiError } from \"../../../utils/src/fetcher\";\r\n\r\nexport type Column<T> = {\r\n header: string;\r\n accessor?: keyof T;\r\n render?: (row: T) => React.ReactNode;\r\n excludeFromPrint?: boolean;\r\n};\r\n\r\ntype TableProps<T> = {\r\n data: T[];\r\n columns: Column<T>[];\r\n loading?: boolean;\r\n error?: ApiError | null;\r\n label?: string;\r\n printable?: boolean;\r\n pageSize?: number;\r\n pageSizeOptions?: number[];\r\n showPagination?: boolean;\r\n};\r\n\r\nconst VISIBLE_PAGES = 5;\r\n\r\nexport function Table<T>({\r\n data,\r\n columns,\r\n loading,\r\n error,\r\n label,\r\n printable,\r\n pageSize = 5,\r\n pageSizeOptions = [5, 10, 20],\r\n showPagination = true,\r\n}: TableProps<T>) {\r\n const [tooltip, setTooltip] = useState<{\r\n content: string;\r\n x: number;\r\n y: number;\r\n } | null>(null);\r\n const [page, setPage] = useState(1);\r\n const [perPage, setPerPage] = useState(pageSize);\r\n\r\n const totalPages = useMemo(\r\n () => Math.max(1, Math.ceil(data.length / perPage)),\r\n [data.length, perPage],\r\n );\r\n\r\n const safePage = Math.min(page, totalPages);\r\n\r\n const displayData = useMemo(\r\n () => data.slice((safePage - 1) * perPage, safePage * perPage),\r\n [data, safePage, perPage],\r\n );\r\n\r\n const paginationRange = useMemo(() => {\r\n const half = Math.floor(VISIBLE_PAGES / 2);\r\n let start = Math.max(1, safePage - half);\r\n let end = Math.min(totalPages, start + VISIBLE_PAGES - 1);\r\n if (end - start + 1 < VISIBLE_PAGES) {\r\n start = Math.max(1, end - VISIBLE_PAGES + 1);\r\n }\r\n const range: (number | \"...\")[] = [];\r\n if (start > 1) {\r\n range.push(1);\r\n if (start > 2) range.push(\"...\");\r\n }\r\n for (let i = start; i <= end; i++) range.push(i);\r\n if (end < totalPages) {\r\n if (end < totalPages - 1) range.push(\"...\");\r\n range.push(totalPages);\r\n }\r\n return range;\r\n }, [safePage, totalPages]);\r\n\r\n const handlePageSizeChange = useCallback((value: number) => {\r\n setPerPage(value);\r\n setPage(1);\r\n }, []);\r\n\r\n const colCount = columns.length;\r\n const colWidth = colCount > 0 ? `${Math.round(100 / colCount)}%` : \"auto\";\r\n\r\n const handleMouseEnter = (\r\n e: React.MouseEvent<HTMLDivElement>,\r\n content: string,\r\n ) => {\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n setTooltip({\r\n content,\r\n x: rect.left + rect.width / 2,\r\n y: rect.top,\r\n });\r\n };\r\n\r\n const handleMouseLeave = () => {\r\n setTooltip(null);\r\n };\r\n\r\n const banner = error ? (\r\n <div className=\"mb-4\">\r\n <ErrorDisplay key={error.message} error={error} />\r\n </div>\r\n ) : null;\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Chargement...\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!data || data.length === 0) {\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <div className=\"flex items-center justify-center py-20 text-gray-500\">\r\n Aucun élément\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n {banner}\r\n <div className=\"flex items-center justify-between mb-2\">\r\n {label && (\r\n <div className=\"text-sm font-semibold text-gray-700\">\r\n {label}: {data.length}\r\n </div>\r\n )}\r\n {printable && (\r\n <button\r\n onClick={() => window.print()}\r\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 transition-colors print:hidden\"\r\n >\r\n <Printer className=\"w-4 h-4\" />\r\n Imprimer\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"rounded-lg shadow-md border border-gray-200\">\r\n <table className=\"w-full table-fixed divide-y divide-gray-200 print:table-fixed\">\r\n <thead className=\"bg-blue-500 rounded-t-lg\">\r\n <tr>\r\n {columns.map((col, index) => (\r\n <th\r\n key={index}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-3 text-left text-xs font-bold text-white uppercase tracking-wider truncate\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {col.header}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody\r\n className={clsx(\r\n \"bg-white divide-y divide-gray-200\",\r\n printable && \"print:hidden\",\r\n )}\r\n >\r\n {displayData.map((row, rowIndex) => (\r\n <tr\r\n key={rowIndex}\r\n className=\"hover:bg-gray-100 transition-colors duration-200\"\r\n >\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n const textContent =\r\n typeof cellContent === \"string\" ? cellContent : \"\";\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {typeof cellContent === \"string\" ? (\r\n <div\r\n className=\"truncate\"\r\n onMouseEnter={(e) => handleMouseEnter(e, textContent)}\r\n onMouseLeave={handleMouseLeave}\r\n >\r\n {cellContent}\r\n </div>\r\n ) : (\r\n cellContent\r\n )}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n {printable && (\r\n <tbody className=\"hidden print:table-row-group\">\r\n {data.map((row, rowIndex) => (\r\n <tr key={rowIndex}>\r\n {columns.map((col, colIndex) => {\r\n const cellContent = col.render\r\n ? col.render(row)\r\n : String(row[col.accessor!]);\r\n\r\n return (\r\n <td\r\n key={colIndex}\r\n style={{ width: colWidth }}\r\n className={clsx(\r\n \"px-6 py-4 text-sm text-gray-700\",\r\n col.excludeFromPrint && \"print:hidden\",\r\n )}\r\n >\r\n {cellContent}\r\n </td>\r\n );\r\n })}\r\n </tr>\r\n ))}\r\n </tbody>\r\n )}\r\n </table>\r\n </div>\r\n\r\n {showPagination && totalPages > 1 && (\r\n <div className=\"flex items-center justify-between mt-4 text-sm print:hidden\">\r\n <div className=\"flex items-center gap-2 text-gray-600\">\r\n <span>Lignes par page :</span>\r\n <select\r\n value={perPage}\r\n onChange={(e) => handlePageSizeChange(Number(e.target.value))}\r\n className=\"border border-gray-300 rounded px-2 py-1 text-sm bg-white focus:outline-none focus:ring-2 focus:ring-blue-400\"\r\n >\r\n {pageSizeOptions.map((opt) => (\r\n <option key={opt} value={opt}>\r\n {opt}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setPage((p) => Math.max(1, p - 1))}\r\n disabled={safePage <= 1}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage <= 1\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronLeft className=\"w-4 h-4\" />\r\n </button>\r\n\r\n {paginationRange.map((item, i) =>\r\n item === \"...\" ? (\r\n <span key={`ellipsis-${i}`} className=\"px-2 text-gray-400\">\r\n ...\r\n </span>\r\n ) : (\r\n <button\r\n key={item}\r\n onClick={() => setPage(item)}\r\n className={clsx(\r\n \"min-w-8 px-2 py-1 rounded text-sm font-medium transition-colors\",\r\n item === safePage\r\n ? \"bg-blue-500 text-white\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n {item}\r\n </button>\r\n ),\r\n )}\r\n\r\n <button\r\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\r\n disabled={safePage >= totalPages}\r\n className={clsx(\r\n \"p-1.5 rounded transition-colors\",\r\n safePage >= totalPages\r\n ? \"text-gray-300 cursor-not-allowed\"\r\n : \"text-gray-600 hover:bg-gray-100\",\r\n )}\r\n >\r\n <ChevronRight className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"text-gray-500\">\r\n Page {safePage} sur {totalPages}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {tooltip && (\r\n <div\r\n className=\"fixed z-20 px-3 py-2 text-sm text-white bg-gray-800 rounded-lg shadow-lg pointer-events-none whitespace-nowrap\"\r\n style={{\r\n left: tooltip.x,\r\n top: tooltip.y - 8,\r\n transform: \"translate(-50%, -100%)\",\r\n }}\r\n >\r\n {tooltip.content}\r\n </div>\r\n )}\r\n <style>{`\r\n @media print {\r\n body * { visibility: hidden; }\r\n .w-full.overflow-x-auto { visibility: visible; }\r\n .w-full.overflow-x-auto * { visibility: visible; }\r\n .w-full.overflow-x-auto { position: absolute; left: 0; top: 0; width: 100%; }\r\n }\r\n `}</style>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport { ApiError } from \"../../../utils/src\";\r\nimport { useState } from \"react\";\r\n\r\ninterface ErrorDisplayProps {\r\n error: ApiError | null;\r\n}\r\n\r\nexport function ErrorDisplay({ error }: ErrorDisplayProps) {\r\n const [dismissed, setDismissed] = useState(false);\r\n\r\n if (!error || dismissed) return null;\r\n\r\n return (\r\n <div className=\"w-full overflow-x-auto\">\r\n <div className=\"rounded-lg shadow-md border border-red-200 bg-red-50\">\r\n <div className=\"flex items-start justify-between gap-4 px-4 py-4\">\r\n <div className=\"flex flex-col gap-1\">\r\n <p className=\"text-red-700 font-medium\">Erreur</p>\r\n <p className=\"text-red-600 text-sm\">{error.message}</p>\r\n </div>\r\n <button\r\n onClick={() => setDismissed(true)}\r\n className=\"text-red-400 hover:text-red-600 shrink-0 cursor-pointer\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport React, { useState, useRef, useEffect } from \"react\";\r\nimport { Ellipsis } from \"lucide-react\";\r\n\r\nexport type TableAction<T> = {\r\n label: string;\r\n icon: React.ReactNode;\r\n callback: (row: T) => void;\r\n color?: string;\r\n};\r\n\r\ntype ActionsMenuProps<T> = {\r\n row: T;\r\n actions: TableAction<T>[];\r\n};\r\n\r\nexport function ActionsMenu<T>({ row, actions }: ActionsMenuProps<T>) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const buttonRef = useRef<HTMLButtonElement>(null);\r\n const menuRef = useRef<HTMLDivElement>(null);\r\n\r\n // Fermer le menu si clic en dehors\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n menuRef.current &&\r\n buttonRef.current &&\r\n !menuRef.current.contains(event.target as Node) &&\r\n !buttonRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n\r\n document.addEventListener(\"mousedown\", handleClickOutside);\r\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\r\n }, []);\r\n\r\n const toggleMenu = () => {\r\n if (buttonRef.current) {\r\n const rect = buttonRef.current.getBoundingClientRect();\r\n const menuWidth = 180;\r\n const menuHeight = actions.length * 40;\r\n\r\n const spaceBelow = window.innerHeight - rect.bottom;\r\n const spaceRight = window.innerWidth - rect.left;\r\n\r\n let top = rect.bottom;\r\n let left = rect.left;\r\n\r\n // If not enough space below, show above\r\n if (spaceBelow < menuHeight + 20) {\r\n top = rect.top - menuHeight;\r\n }\r\n\r\n // If not enough space on the right, align to the left\r\n if (spaceRight < menuWidth + 20) {\r\n left = rect.left - menuWidth + 30;\r\n }\r\n\r\n setCoords({ top, left });\r\n }\r\n setIsOpen(!isOpen);\r\n };\r\n\r\n return (\r\n <>\r\n <button\r\n ref={buttonRef}\r\n onClick={toggleMenu}\r\n className=\"p-1 hover:bg-gray-100 rounded-full\"\r\n >\r\n <Ellipsis className=\"w-5 h-5\" />\r\n </button>\r\n\r\n {isOpen && (\r\n <div\r\n ref={menuRef}\r\n className=\"fixed bg-white border border-gray-200 rounded shadow-lg z-20\"\r\n style={{\r\n top: coords.top,\r\n left: coords.left,\r\n minWidth: 180,\r\n }}\r\n >\r\n {actions.map((action, idx) => (\r\n <button\r\n key={idx}\r\n className={`flex items-center gap-2 px-4 py-2 w-full text-sm hover:bg-gray-100 ${\r\n action.color || \"text-gray-700\"\r\n }`}\r\n onClick={() => {\r\n action.callback(row);\r\n setIsOpen(false);\r\n }}\r\n >\r\n {action.icon}\r\n {action.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { X } from \"lucide-react\";\r\nimport React, { useEffect } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\n\r\ntype ModalProps = {\r\n title: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n children: React.ReactNode | ((requestClose: () => void) => React.ReactNode);\r\n};\r\n\r\nexport function Modal({ title, isOpen, onClose, children }: ModalProps) {\r\n const requestClose = () => {\r\n onClose();\r\n };\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n document.body.style.overflow = \"hidden\";\r\n }\r\n\r\n return () => {\r\n document.body.style.overflow = \"\";\r\n };\r\n }, [isOpen]);\r\n\r\n useEffect(() => {\r\n function handleEsc(e: KeyboardEvent) {\r\n if (e.key === \"Escape\") {\r\n onClose();\r\n }\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener(\"keydown\", handleEsc);\r\n }\r\n\r\n return () => {\r\n document.removeEventListener(\"keydown\", handleEsc);\r\n };\r\n }, [isOpen, onClose]);\r\n\r\n if (!isOpen) return null;\r\n\r\n const content =\r\n typeof children === \"function\" ? children(requestClose) : children;\r\n\r\n return createPortal(\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\r\n <div\r\n className=\"absolute inset-0 bg-black/20 backdrop-blur-sm\"\r\n onClick={onClose}\r\n />\r\n\r\n <div className=\"relative bg-white rounded-lg shadow-lg w-full max-w-2xl mx-4 p-6 flex flex-col max-h-[85vh]\">\r\n <div className=\"flex items-center justify-between mb-4 border-b-2 border-gray-400 pb-3 sticky top-0 bg-white z-10\">\r\n <h2 className=\"text-lg font-semibold text-gray-900\">{title}</h2>\r\n\r\n <button\r\n onClick={onClose}\r\n className=\"text-gray-500 hover:text-gray-700 text-xl cursor-pointer\"\r\n >\r\n <X />\r\n </button>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto flex-1 min-h-0\">{content}</div>\r\n </div>\r\n </div>,\r\n document.body,\r\n );\r\n}\r\n","export class ApiError extends Error {\r\n public status: number;\r\n public code?: string;\r\n public data?: unknown;\r\n\r\n constructor(params: {\r\n message: string;\r\n status: number;\r\n code?: string;\r\n data?: unknown;\r\n }) {\r\n super(params.message);\r\n this.status = params.status;\r\n this.code = params.code;\r\n this.data = params.data;\r\n }\r\n}\r\n\r\ntype BackendErrorShape = {\r\n code?: string;\r\n status?: number;\r\n message?: string;\r\n};\r\n\r\nexport type FetcherOptions = RequestInit & {\r\n skipJsonParsing?: boolean;\r\n};\r\n\r\nexport async function fetcher<T = unknown>(\r\n url: string,\r\n options: FetcherOptions = {},\r\n): Promise<T> {\r\n const { headers, skipJsonParsing = false, ...rest } = options;\r\n\r\n const response = await fetch(url, {\r\n credentials: \"include\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...headers,\r\n },\r\n ...rest,\r\n });\r\n\r\n let responseData: unknown = null;\r\n const contentType = response.headers.get(\"content-type\");\r\n\r\n if (!skipJsonParsing && contentType?.includes(\"application/json\")) {\r\n responseData = await response.json();\r\n }\r\n\r\n if (!response.ok) {\r\n const backendError = responseData as BackendErrorShape;\r\n\r\n throw new ApiError({\r\n message: backendError?.message || \"Une erreur est survenue\",\r\n status: backendError?.status || response.status,\r\n code: backendError?.code,\r\n data: responseData,\r\n });\r\n }\r\n\r\n return responseData as T;\r\n}\r\n","export class HttpError extends Error {\r\n status: number;\r\n code?: string;\r\n\r\n constructor(message: string, status = 400, code?: string) {\r\n super(message);\r\n\r\n this.name = \"HttpError\";\r\n this.status = status;\r\n this.code = code;\r\n\r\n Object.setPrototypeOf(this, HttpError.prototype);\r\n }\r\n}\r\n","import { HttpError } from \"./http-error\";\r\n\r\nconst GENERIC_MESSAGE = \"Erreur serveur\";\r\n\r\nfunction shouldShowDetails(showDetails?: boolean): boolean {\r\n return showDetails ?? process.env.NODE_ENV !== \"production\";\r\n}\r\n\r\nfunction sanitizedResponse(\r\n message: string,\r\n code: string,\r\n status: number,\r\n showDetails?: boolean,\r\n) {\r\n return Response.json(\r\n {\r\n message: showDetails ? message : GENERIC_MESSAGE,\r\n code: showDetails ? code : \"INTERNAL_ERROR\",\r\n status,\r\n },\r\n { status },\r\n );\r\n}\r\n\r\n/**\r\n * Transforme n'importe quelle erreur en réponse JSON standardisée\r\n * @param error L'erreur levée\r\n * @param defaultStatus Statut HTTP par défaut si non défini\r\n * @param showDetails Force l'affichage des détails (true) ou le mode sécurisé (false). Par défaut : automatique selon NODE_ENV\r\n * @returns Response JSON\r\n */\r\nexport function handleServerError(\r\n error: unknown,\r\n defaultStatus = 500,\r\n showDetails?: boolean,\r\n) {\r\n const details = shouldShowDetails(showDetails);\r\n\r\n console.error(\"Erreur capturée :\", error);\r\n\r\n // Cas HttpError personnalisé — toujours visible (erreur intentionnelle)\r\n if (error instanceof HttpError) {\r\n const status = error.status ?? defaultStatus;\r\n return Response.json(\r\n {\r\n message: error.message,\r\n code: error.code ?? \"INTERNAL_ERROR\",\r\n status,\r\n },\r\n { status },\r\n );\r\n }\r\n\r\n // Cas classique : objet Error\r\n if (error instanceof Error) {\r\n return sanitizedResponse(\r\n error.message,\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n }\r\n\r\n // Cas objet brut ou autre type\r\n if (typeof error === \"object\" && error !== null) {\r\n return sanitizedResponse(\r\n JSON.stringify(error),\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n }\r\n\r\n // Cas fallback : string ou autre\r\n return sanitizedResponse(\r\n String(error),\r\n \"INTERNAL_ERROR\",\r\n defaultStatus,\r\n details,\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx","useState","useState","jsx","jsxs","jsx","jsxs","useState","useState","useEffect","jsx","jsxs","X","useEffect","jsx","jsxs"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ramses1er/cbk-toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"clsx": "^2.1.1"
|
|
18
|
+
},
|
|
16
19
|
"peerDependencies": {
|
|
17
20
|
"lucide-react": "^1.21.0",
|
|
18
21
|
"react": ">=18",
|
|
@@ -25,9 +28,6 @@
|
|
|
25
28
|
"lucide-react": "^1.21.0",
|
|
26
29
|
"tsup": "^8.5.0"
|
|
27
30
|
},
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"next": "16.2.9"
|
|
30
|
-
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup",
|
|
33
33
|
"dev": "tsup --watch",
|