@contractspec/lib.ui-kit-web 3.1.0 → 3.2.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.
@@ -1,5 +1,1258 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
+
4
+ // ui/button.tsx
5
+ import { Slot } from "@radix-ui/react-slot";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@contractspec/lib.ui-kit-core/utils";
8
+ import { jsxDEV } from "react/jsx-dev-runtime";
9
+ var buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-hidden focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
13
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
14
+ outline: "border bg-background shadow-2xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
15
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
16
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
17
+ link: "text-primary underline-offset-4 hover:underline"
18
+ },
19
+ size: {
20
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
21
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
22
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
23
+ icon: "size-9"
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ variant: "default",
28
+ size: "default"
29
+ }
30
+ });
31
+ function Button({
32
+ className,
33
+ variant,
34
+ size,
35
+ asChild = false,
36
+ ref,
37
+ ...props
38
+ }) {
39
+ if (asChild) {
40
+ return /* @__PURE__ */ jsxDEV(Slot, {
41
+ "data-slot": "button",
42
+ className: cn(buttonVariants({ variant, size, className })),
43
+ ...props
44
+ }, undefined, false, undefined, this);
45
+ }
46
+ return /* @__PURE__ */ jsxDEV("button", {
47
+ ref,
48
+ "data-slot": "button",
49
+ className: cn(buttonVariants({ variant, size, className })),
50
+ ...props
51
+ }, undefined, false, undefined, this);
52
+ }
53
+ // ui/select.tsx
54
+ import * as SelectPrimitive from "@radix-ui/react-select";
55
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
56
+ import { cn as cn2 } from "@contractspec/lib.ui-kit-core/utils";
57
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
58
+ "use client";
59
+ function Select({
60
+ ...props
61
+ }) {
62
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Root, {
63
+ "data-slot": "select",
64
+ ...props
65
+ }, undefined, false, undefined, this);
66
+ }
67
+ function SelectGroup({
68
+ ...props
69
+ }) {
70
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Group, {
71
+ "data-slot": "select-group",
72
+ ...props
73
+ }, undefined, false, undefined, this);
74
+ }
75
+ function SelectValue({
76
+ ...props
77
+ }) {
78
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Value, {
79
+ "data-slot": "select-value",
80
+ ...props
81
+ }, undefined, false, undefined, this);
82
+ }
83
+ function SelectTrigger({
84
+ className,
85
+ size = "default",
86
+ children,
87
+ ...props
88
+ }) {
89
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Trigger, {
90
+ "data-slot": "select-trigger",
91
+ "data-size": size,
92
+ className: cn2("aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive border-input focus-visible:border-ring focus-visible:ring-ring/50 data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-2xs outline-hidden transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
93
+ ...props,
94
+ children: [
95
+ children,
96
+ /* @__PURE__ */ jsxDEV2(SelectPrimitive.Icon, {
97
+ asChild: true,
98
+ children: /* @__PURE__ */ jsxDEV2(ChevronDownIcon, {
99
+ className: "size-4 opacity-50"
100
+ }, undefined, false, undefined, this)
101
+ }, undefined, false, undefined, this)
102
+ ]
103
+ }, undefined, true, undefined, this);
104
+ }
105
+ function SelectContent({
106
+ className,
107
+ children,
108
+ position = "popper",
109
+ ...props
110
+ }) {
111
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Portal, {
112
+ children: /* @__PURE__ */ jsxDEV2(SelectPrimitive.Content, {
113
+ "data-slot": "select-content",
114
+ className: cn2("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
115
+ position,
116
+ ...props,
117
+ children: [
118
+ /* @__PURE__ */ jsxDEV2(SelectScrollUpButton, {}, undefined, false, undefined, this),
119
+ /* @__PURE__ */ jsxDEV2(SelectPrimitive.Viewport, {
120
+ className: cn2("p-1", position === "popper" && "h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1"),
121
+ children
122
+ }, undefined, false, undefined, this),
123
+ /* @__PURE__ */ jsxDEV2(SelectScrollDownButton, {}, undefined, false, undefined, this)
124
+ ]
125
+ }, undefined, true, undefined, this)
126
+ }, undefined, false, undefined, this);
127
+ }
128
+ function SelectLabel({
129
+ className,
130
+ ...props
131
+ }) {
132
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Label, {
133
+ "data-slot": "select-label",
134
+ className: cn2("text-muted-foreground px-2 py-1.5 text-xs", className),
135
+ ...props
136
+ }, undefined, false, undefined, this);
137
+ }
138
+ function SelectItem({
139
+ className,
140
+ children,
141
+ ...props
142
+ }) {
143
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Item, {
144
+ "data-slot": "select-item",
145
+ className: cn2("focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-xs py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
146
+ ...props,
147
+ children: [
148
+ /* @__PURE__ */ jsxDEV2("span", {
149
+ className: "absolute right-2 flex size-3.5 items-center justify-center",
150
+ children: /* @__PURE__ */ jsxDEV2(SelectPrimitive.ItemIndicator, {
151
+ children: /* @__PURE__ */ jsxDEV2(CheckIcon, {
152
+ className: "size-4"
153
+ }, undefined, false, undefined, this)
154
+ }, undefined, false, undefined, this)
155
+ }, undefined, false, undefined, this),
156
+ /* @__PURE__ */ jsxDEV2(SelectPrimitive.ItemText, {
157
+ children
158
+ }, undefined, false, undefined, this)
159
+ ]
160
+ }, undefined, true, undefined, this);
161
+ }
162
+ function SelectSeparator({
163
+ className,
164
+ ...props
165
+ }) {
166
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.Separator, {
167
+ "data-slot": "select-separator",
168
+ className: cn2("bg-border pointer-events-none -mx-1 my-1 h-px", className),
169
+ ...props
170
+ }, undefined, false, undefined, this);
171
+ }
172
+ function SelectScrollUpButton({
173
+ className,
174
+ ...props
175
+ }) {
176
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.ScrollUpButton, {
177
+ "data-slot": "select-scroll-up-button",
178
+ className: cn2("flex cursor-default items-center justify-center py-1", className),
179
+ ...props,
180
+ children: /* @__PURE__ */ jsxDEV2(ChevronUpIcon, {
181
+ className: "size-4"
182
+ }, undefined, false, undefined, this)
183
+ }, undefined, false, undefined, this);
184
+ }
185
+ function SelectScrollDownButton({
186
+ className,
187
+ ...props
188
+ }) {
189
+ return /* @__PURE__ */ jsxDEV2(SelectPrimitive.ScrollDownButton, {
190
+ "data-slot": "select-scroll-down-button",
191
+ className: cn2("flex cursor-default items-center justify-center py-1", className),
192
+ ...props,
193
+ children: /* @__PURE__ */ jsxDEV2(ChevronDownIcon, {
194
+ className: "size-4"
195
+ }, undefined, false, undefined, this)
196
+ }, undefined, false, undefined, this);
197
+ }
198
+ // ui/label.tsx
199
+ import * as LabelPrimitive from "@radix-ui/react-label";
200
+ import { cn as cn3 } from "@contractspec/lib.ui-kit-core/utils";
201
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
202
+ "use client";
203
+ function Label2({
204
+ className,
205
+ ...props
206
+ }) {
207
+ return /* @__PURE__ */ jsxDEV3(LabelPrimitive.Root, {
208
+ "data-slot": "label",
209
+ className: cn3("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className),
210
+ ...props
211
+ }, undefined, false, undefined, this);
212
+ }
213
+ // ui/atoms/FilterSelect/FilterSelect.tsx
214
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
215
+ var FilterSelect = ({
216
+ value,
217
+ options,
218
+ onChange,
219
+ placeholder = "S\xE9lectionner...",
220
+ label,
221
+ disabled = false,
222
+ className = "",
223
+ showCounts = false
224
+ }) => {
225
+ return /* @__PURE__ */ jsxDEV4("div", {
226
+ className: `space-y-2 ${className}`,
227
+ children: [
228
+ label && /* @__PURE__ */ jsxDEV4(Label2, {
229
+ className: "text-foreground text-base font-medium",
230
+ children: label
231
+ }, undefined, false, undefined, this),
232
+ /* @__PURE__ */ jsxDEV4(Select, {
233
+ value,
234
+ onValueChange: onChange,
235
+ disabled,
236
+ children: [
237
+ /* @__PURE__ */ jsxDEV4(SelectTrigger, {
238
+ className: "w-full",
239
+ children: /* @__PURE__ */ jsxDEV4(SelectValue, {
240
+ placeholder
241
+ }, undefined, false, undefined, this)
242
+ }, undefined, false, undefined, this),
243
+ /* @__PURE__ */ jsxDEV4(SelectContent, {
244
+ className: "bg-background",
245
+ children: [
246
+ /* @__PURE__ */ jsxDEV4(SelectItem, {
247
+ value: "all",
248
+ children: [
249
+ "Tous",
250
+ showCounts && /* @__PURE__ */ jsxDEV4("span", {
251
+ className: "text-muted-foreground ml-2 text-sm",
252
+ children: [
253
+ "(",
254
+ options.reduce((sum, option) => sum + (option.count || 0), 0),
255
+ ")"
256
+ ]
257
+ }, undefined, true, undefined, this)
258
+ ]
259
+ }, undefined, true, undefined, this),
260
+ options.map((option) => /* @__PURE__ */ jsxDEV4(SelectItem, {
261
+ value: option.value,
262
+ children: /* @__PURE__ */ jsxDEV4("div", {
263
+ className: "flex w-full items-center justify-between",
264
+ children: [
265
+ /* @__PURE__ */ jsxDEV4("span", {
266
+ children: option.label
267
+ }, undefined, false, undefined, this),
268
+ showCounts && option.count !== undefined && /* @__PURE__ */ jsxDEV4("span", {
269
+ className: "text-muted-foreground ml-2 text-sm",
270
+ children: [
271
+ "(",
272
+ option.count,
273
+ ")"
274
+ ]
275
+ }, undefined, true, undefined, this)
276
+ ]
277
+ }, undefined, true, undefined, this)
278
+ }, option.value, false, undefined, this))
279
+ ]
280
+ }, undefined, true, undefined, this)
281
+ ]
282
+ }, undefined, true, undefined, this)
283
+ ]
284
+ }, undefined, true, undefined, this);
285
+ };
286
+ // ui/atoms/Pagination/Pagination.tsx
287
+ import {
288
+ ChevronLeft,
289
+ ChevronRight,
290
+ ChevronsLeft,
291
+ ChevronsRight
292
+ } from "lucide-react";
293
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
294
+ var Pagination = ({
295
+ currentPage,
296
+ totalPages,
297
+ totalItems,
298
+ itemsPerPage,
299
+ onPageChange,
300
+ onItemsPerPageChange,
301
+ disabled = false,
302
+ className = "",
303
+ showItemsPerPage = true,
304
+ itemsPerPageOptions = [10, 25, 50, 100]
305
+ }) => {
306
+ const startItem = (currentPage - 1) * itemsPerPage + 1;
307
+ const endItem = Math.min(currentPage * itemsPerPage, totalItems);
308
+ const canGoPrevious = currentPage > 1 && !disabled;
309
+ const canGoNext = currentPage < totalPages && !disabled;
310
+ const getVisiblePageNumbers = () => {
311
+ if (totalPages <= 7) {
312
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
313
+ }
314
+ if (currentPage <= 3) {
315
+ return [1, 2, 3, 4, 5, -1, totalPages];
316
+ }
317
+ if (currentPage >= totalPages - 2) {
318
+ return [
319
+ 1,
320
+ -1,
321
+ totalPages - 4,
322
+ totalPages - 3,
323
+ totalPages - 2,
324
+ totalPages - 1,
325
+ totalPages
326
+ ];
327
+ }
328
+ return [
329
+ 1,
330
+ -1,
331
+ currentPage - 1,
332
+ currentPage,
333
+ currentPage + 1,
334
+ -1,
335
+ totalPages
336
+ ];
337
+ };
338
+ if (totalPages === 0)
339
+ return null;
340
+ return /* @__PURE__ */ jsxDEV5("div", {
341
+ className: `flex flex-col items-center justify-between gap-4 sm:flex-row ${className}`,
342
+ children: [
343
+ /* @__PURE__ */ jsxDEV5("div", {
344
+ className: "text-muted-foreground order-2 text-base sm:order-1",
345
+ children: [
346
+ "Affichage de ",
347
+ startItem,
348
+ " \xE0 ",
349
+ endItem,
350
+ " sur ",
351
+ totalItems,
352
+ " r\xE9sultats"
353
+ ]
354
+ }, undefined, true, undefined, this),
355
+ /* @__PURE__ */ jsxDEV5("div", {
356
+ className: "order-1 flex items-center gap-2 sm:order-2",
357
+ children: [
358
+ /* @__PURE__ */ jsxDEV5(Button, {
359
+ variant: "outline",
360
+ size: "sm",
361
+ onClick: () => onPageChange(1),
362
+ disabled: !canGoPrevious,
363
+ className: "hidden h-8 w-8 p-0 sm:flex",
364
+ children: [
365
+ /* @__PURE__ */ jsxDEV5(ChevronsLeft, {
366
+ className: "h-4 w-4"
367
+ }, undefined, false, undefined, this),
368
+ /* @__PURE__ */ jsxDEV5("span", {
369
+ className: "sr-only",
370
+ children: "Premi\xE8re page"
371
+ }, undefined, false, undefined, this)
372
+ ]
373
+ }, undefined, true, undefined, this),
374
+ /* @__PURE__ */ jsxDEV5(Button, {
375
+ variant: "outline",
376
+ size: "sm",
377
+ onClick: () => onPageChange(currentPage - 1),
378
+ disabled: !canGoPrevious,
379
+ className: "h-8 w-8 p-0",
380
+ children: [
381
+ /* @__PURE__ */ jsxDEV5(ChevronLeft, {
382
+ className: "h-4 w-4"
383
+ }, undefined, false, undefined, this),
384
+ /* @__PURE__ */ jsxDEV5("span", {
385
+ className: "sr-only",
386
+ children: "Page pr\xE9c\xE9dente"
387
+ }, undefined, false, undefined, this)
388
+ ]
389
+ }, undefined, true, undefined, this),
390
+ /* @__PURE__ */ jsxDEV5("div", {
391
+ className: "flex items-center gap-1",
392
+ children: getVisiblePageNumbers().map((page, index) => {
393
+ if (page === -1) {
394
+ return /* @__PURE__ */ jsxDEV5("span", {
395
+ className: "text-muted-foreground px-2 py-1",
396
+ children: "..."
397
+ }, `ellipsis-${index}`, false, undefined, this);
398
+ }
399
+ return /* @__PURE__ */ jsxDEV5(Button, {
400
+ variant: page === currentPage ? "default" : "outline",
401
+ size: "sm",
402
+ onClick: () => onPageChange(page),
403
+ disabled,
404
+ className: "h-8 min-w-8 px-2",
405
+ children: page
406
+ }, page, false, undefined, this);
407
+ })
408
+ }, undefined, false, undefined, this),
409
+ /* @__PURE__ */ jsxDEV5(Button, {
410
+ variant: "outline",
411
+ size: "sm",
412
+ onClick: () => onPageChange(currentPage + 1),
413
+ disabled: !canGoNext,
414
+ className: "h-8 w-8 p-0",
415
+ children: [
416
+ /* @__PURE__ */ jsxDEV5(ChevronRight, {
417
+ className: "h-4 w-4"
418
+ }, undefined, false, undefined, this),
419
+ /* @__PURE__ */ jsxDEV5("span", {
420
+ className: "sr-only",
421
+ children: "Page suivante"
422
+ }, undefined, false, undefined, this)
423
+ ]
424
+ }, undefined, true, undefined, this),
425
+ /* @__PURE__ */ jsxDEV5(Button, {
426
+ variant: "outline",
427
+ size: "sm",
428
+ onClick: () => onPageChange(totalPages),
429
+ disabled: !canGoNext,
430
+ className: "hidden h-8 w-8 p-0 sm:flex",
431
+ children: [
432
+ /* @__PURE__ */ jsxDEV5(ChevronsRight, {
433
+ className: "h-4 w-4"
434
+ }, undefined, false, undefined, this),
435
+ /* @__PURE__ */ jsxDEV5("span", {
436
+ className: "sr-only",
437
+ children: "Derni\xE8re page"
438
+ }, undefined, false, undefined, this)
439
+ ]
440
+ }, undefined, true, undefined, this)
441
+ ]
442
+ }, undefined, true, undefined, this),
443
+ showItemsPerPage && onItemsPerPageChange && /* @__PURE__ */ jsxDEV5("div", {
444
+ className: "order-3 flex items-center gap-2 text-base",
445
+ children: [
446
+ /* @__PURE__ */ jsxDEV5("span", {
447
+ className: "text-muted-foreground",
448
+ children: "Afficher:"
449
+ }, undefined, false, undefined, this),
450
+ /* @__PURE__ */ jsxDEV5(Select, {
451
+ value: itemsPerPage.toString(),
452
+ onValueChange: (value) => onItemsPerPageChange(parseInt(value)),
453
+ disabled,
454
+ children: [
455
+ /* @__PURE__ */ jsxDEV5(SelectTrigger, {
456
+ className: "h-8 w-16",
457
+ children: /* @__PURE__ */ jsxDEV5(SelectValue, {}, undefined, false, undefined, this)
458
+ }, undefined, false, undefined, this),
459
+ /* @__PURE__ */ jsxDEV5(SelectContent, {
460
+ className: "bg-background",
461
+ children: itemsPerPageOptions.map((option) => /* @__PURE__ */ jsxDEV5(SelectItem, {
462
+ value: option.toString(),
463
+ children: option
464
+ }, option, false, undefined, this))
465
+ }, undefined, false, undefined, this)
466
+ ]
467
+ }, undefined, true, undefined, this)
468
+ ]
469
+ }, undefined, true, undefined, this)
470
+ ]
471
+ }, undefined, true, undefined, this);
472
+ };
473
+ // ui/input.tsx
474
+ import { cn as cn4 } from "@contractspec/lib.ui-kit-core/utils";
475
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
476
+ function Input({ className, type, ...props }) {
477
+ return /* @__PURE__ */ jsxDEV6("input", {
478
+ type,
479
+ "data-slot": "input",
480
+ className: cn4("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className),
481
+ ...props
482
+ }, undefined, false, undefined, this);
483
+ }
484
+ // ui/atoms/SearchInput/SearchInput.tsx
485
+ import { Search, X } from "lucide-react";
486
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
487
+ var SearchInput = ({
488
+ value,
489
+ onChange,
490
+ placeholder = "Rechercher...",
491
+ onClear,
492
+ disabled = false,
493
+ className = "",
494
+ autoFocus = false
495
+ }) => {
496
+ const handleClear = () => {
497
+ onChange("");
498
+ onClear?.();
499
+ };
500
+ return /* @__PURE__ */ jsxDEV7("div", {
501
+ className: `relative w-full ${className}`,
502
+ children: [
503
+ /* @__PURE__ */ jsxDEV7("div", {
504
+ className: "pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3",
505
+ children: /* @__PURE__ */ jsxDEV7(Search, {
506
+ className: "text-muted-foreground h-4 w-4"
507
+ }, undefined, false, undefined, this)
508
+ }, undefined, false, undefined, this),
509
+ /* @__PURE__ */ jsxDEV7(Input, {
510
+ type: "text",
511
+ value,
512
+ onChange: (e) => onChange(e.target.value),
513
+ placeholder,
514
+ disabled,
515
+ autoFocus,
516
+ className: "pr-10 pl-10"
517
+ }, undefined, false, undefined, this),
518
+ value && /* @__PURE__ */ jsxDEV7("div", {
519
+ className: "absolute inset-y-0 right-0 flex items-center pr-3",
520
+ children: /* @__PURE__ */ jsxDEV7(Button, {
521
+ type: "button",
522
+ variant: "ghost",
523
+ size: "sm",
524
+ onClick: handleClear,
525
+ disabled,
526
+ className: "h-6 w-6 p-0 hover:bg-transparent",
527
+ children: [
528
+ /* @__PURE__ */ jsxDEV7(X, {
529
+ className: "text-muted-foreground hover:text-foreground h-4 w-4"
530
+ }, undefined, false, undefined, this),
531
+ /* @__PURE__ */ jsxDEV7("span", {
532
+ className: "sr-only",
533
+ children: "Effacer la recherche"
534
+ }, undefined, false, undefined, this)
535
+ ]
536
+ }, undefined, true, undefined, this)
537
+ }, undefined, false, undefined, this)
538
+ ]
539
+ }, undefined, true, undefined, this);
540
+ };
541
+ // ui/card.tsx
542
+ import { cn as cn5 } from "@contractspec/lib.ui-kit-core/utils";
543
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
544
+ function Card({ className, ...props }) {
545
+ return /* @__PURE__ */ jsxDEV8("div", {
546
+ "data-slot": "card",
547
+ className: cn5("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-2xs", className),
548
+ ...props
549
+ }, undefined, false, undefined, this);
550
+ }
551
+ function CardHeader({
552
+ className,
553
+ ...props
554
+ }) {
555
+ return /* @__PURE__ */ jsxDEV8("div", {
556
+ "data-slot": "card-header",
557
+ className: cn5("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className),
558
+ ...props
559
+ }, undefined, false, undefined, this);
560
+ }
561
+ function CardTitle({
562
+ className,
563
+ ...props
564
+ }) {
565
+ return /* @__PURE__ */ jsxDEV8("div", {
566
+ "data-slot": "card-title",
567
+ className: cn5("leading-none font-semibold", className),
568
+ ...props
569
+ }, undefined, false, undefined, this);
570
+ }
571
+ function CardDescription({
572
+ className,
573
+ ...props
574
+ }) {
575
+ return /* @__PURE__ */ jsxDEV8("div", {
576
+ "data-slot": "card-description",
577
+ className: cn5("text-muted-foreground text-sm", className),
578
+ ...props
579
+ }, undefined, false, undefined, this);
580
+ }
581
+ function CardAction({
582
+ className,
583
+ ...props
584
+ }) {
585
+ return /* @__PURE__ */ jsxDEV8("div", {
586
+ "data-slot": "card-action",
587
+ className: cn5("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className),
588
+ ...props
589
+ }, undefined, false, undefined, this);
590
+ }
591
+ function CardContent({
592
+ className,
593
+ ...props
594
+ }) {
595
+ return /* @__PURE__ */ jsxDEV8("div", {
596
+ "data-slot": "card-content",
597
+ className: cn5("px-6", className),
598
+ ...props
599
+ }, undefined, false, undefined, this);
600
+ }
601
+ function CardFooter({
602
+ className,
603
+ ...props
604
+ }) {
605
+ return /* @__PURE__ */ jsxDEV8("div", {
606
+ "data-slot": "card-footer",
607
+ className: cn5("flex items-center px-6 [.border-t]:pt-6", className),
608
+ ...props
609
+ }, undefined, false, undefined, this);
610
+ }
611
+ // ui/collapsible.tsx
612
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
613
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
614
+ "use client";
615
+ function Collapsible({
616
+ ...props
617
+ }) {
618
+ return /* @__PURE__ */ jsxDEV9(CollapsiblePrimitive.Root, {
619
+ "data-slot": "collapsible",
620
+ ...props
621
+ }, undefined, false, undefined, this);
622
+ }
623
+ function CollapsibleTrigger2({
624
+ ...props
625
+ }) {
626
+ return /* @__PURE__ */ jsxDEV9(CollapsiblePrimitive.CollapsibleTrigger, {
627
+ "data-slot": "collapsible-trigger",
628
+ ...props
629
+ }, undefined, false, undefined, this);
630
+ }
631
+ function CollapsibleContent2({
632
+ ...props
633
+ }) {
634
+ return /* @__PURE__ */ jsxDEV9(CollapsiblePrimitive.CollapsibleContent, {
635
+ "data-slot": "collapsible-content",
636
+ ...props
637
+ }, undefined, false, undefined, this);
638
+ }
639
+ // ui/stack.tsx
640
+ import { cva as cva2 } from "class-variance-authority";
641
+ import { cn as cn6 } from "@contractspec/lib.ui-kit-core/utils";
642
+ import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
643
+ var vStackVariants = cva2("flex flex-col", {
644
+ variants: {
645
+ gap: {
646
+ none: "gap-0",
647
+ xs: "gap-1",
648
+ sm: "gap-2",
649
+ md: "gap-3",
650
+ lg: "gap-4",
651
+ xl: "gap-6",
652
+ "2xl": "gap-8"
653
+ },
654
+ align: {
655
+ start: "items-start",
656
+ center: "items-center",
657
+ end: "items-end",
658
+ stretch: "items-stretch"
659
+ },
660
+ justify: {
661
+ start: "justify-start",
662
+ center: "justify-center",
663
+ end: "justify-end",
664
+ between: "justify-between",
665
+ around: "justify-around",
666
+ evenly: "justify-evenly"
667
+ }
668
+ },
669
+ defaultVariants: {
670
+ gap: "md",
671
+ align: "stretch",
672
+ justify: "start"
673
+ }
674
+ });
675
+ function VStack({
676
+ className,
677
+ gap,
678
+ align,
679
+ justify,
680
+ as = "div",
681
+ ref,
682
+ ...props
683
+ }) {
684
+ const Comp = as;
685
+ return /* @__PURE__ */ jsxDEV10(Comp, {
686
+ ref,
687
+ className: cn6(vStackVariants({ gap, align, justify }), className),
688
+ ...props
689
+ }, undefined, false, undefined, this);
690
+ }
691
+ var hStackVariants = cva2("flex flex-row", {
692
+ variants: {
693
+ gap: {
694
+ none: "gap-0",
695
+ xs: "gap-1",
696
+ sm: "gap-2",
697
+ md: "gap-3",
698
+ lg: "gap-4",
699
+ xl: "gap-6",
700
+ "2xl": "gap-8"
701
+ },
702
+ align: {
703
+ start: "items-start",
704
+ center: "items-center",
705
+ end: "items-end",
706
+ stretch: "items-stretch",
707
+ baseline: "items-baseline"
708
+ },
709
+ justify: {
710
+ start: "justify-start",
711
+ center: "justify-center",
712
+ end: "justify-end",
713
+ between: "justify-between",
714
+ around: "justify-around",
715
+ evenly: "justify-evenly"
716
+ },
717
+ wrap: {
718
+ nowrap: "flex-nowrap",
719
+ wrap: "flex-wrap",
720
+ wrapReverse: "flex-wrap-reverse"
721
+ }
722
+ },
723
+ defaultVariants: {
724
+ gap: "md",
725
+ align: "center",
726
+ justify: "start",
727
+ wrap: "wrap"
728
+ }
729
+ });
730
+ function HStack({
731
+ className,
732
+ gap,
733
+ align,
734
+ justify,
735
+ wrap,
736
+ as = "div",
737
+ ref,
738
+ ...props
739
+ }) {
740
+ const Comp = as;
741
+ return /* @__PURE__ */ jsxDEV10(Comp, {
742
+ ref,
743
+ className: cn6(hStackVariants({ gap, align, justify, wrap }), className),
744
+ ...props
745
+ }, undefined, false, undefined, this);
746
+ }
747
+ var boxVariants = cva2("flex flex-row", {
748
+ variants: {
749
+ gap: {
750
+ none: "gap-0",
751
+ xs: "gap-1",
752
+ sm: "gap-2",
753
+ md: "gap-3",
754
+ lg: "gap-4",
755
+ xl: "gap-6",
756
+ "2xl": "gap-8"
757
+ },
758
+ align: {
759
+ start: "items-start",
760
+ center: "items-center",
761
+ end: "items-end",
762
+ stretch: "items-stretch",
763
+ baseline: "items-baseline"
764
+ },
765
+ justify: {
766
+ start: "justify-start",
767
+ center: "justify-center",
768
+ end: "justify-end",
769
+ between: "justify-between",
770
+ around: "justify-around",
771
+ evenly: "justify-evenly"
772
+ },
773
+ wrap: {
774
+ nowrap: "flex-nowrap",
775
+ wrap: "flex-wrap",
776
+ wrapReverse: "flex-wrap-reverse"
777
+ }
778
+ },
779
+ defaultVariants: {
780
+ gap: "md",
781
+ align: "center",
782
+ justify: "center",
783
+ wrap: "nowrap"
784
+ }
785
+ });
786
+ function Box({
787
+ className,
788
+ gap,
789
+ align,
790
+ justify,
791
+ wrap,
792
+ as = "div",
793
+ ref,
794
+ ...props
795
+ }) {
796
+ const Comp = as;
797
+ return /* @__PURE__ */ jsxDEV10(Comp, {
798
+ ref,
799
+ className: cn6(boxVariants({ gap, align, justify, wrap }), className),
800
+ ...props
801
+ }, undefined, false, undefined, this);
802
+ }
803
+ // ui/separator.tsx
804
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
805
+ import { cn as cn7 } from "@contractspec/lib.ui-kit-core/utils";
806
+ import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
807
+ "use client";
808
+ function Separator2({
809
+ className,
810
+ orientation = "horizontal",
811
+ decorative = true,
812
+ ...props
813
+ }) {
814
+ return /* @__PURE__ */ jsxDEV11(SeparatorPrimitive.Root, {
815
+ "data-slot": "separator",
816
+ decorative,
817
+ orientation,
818
+ className: cn7("bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", className),
819
+ ...props
820
+ }, undefined, false, undefined, this);
821
+ }
822
+ // ui/molecules/SearchAndFilter/SearchAndFilter.tsx
823
+ import { useState } from "react";
824
+ import { ChevronDown, ChevronUp, Filter } from "lucide-react";
825
+ import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime";
826
+ var SearchAndFilter = ({
827
+ searchValue,
828
+ onSearchChange,
829
+ searchPlaceholder,
830
+ filters = [],
831
+ isLoading = false,
832
+ disabled = false,
833
+ className = "",
834
+ collapsible = true,
835
+ defaultCollapsed = false
836
+ }) => {
837
+ const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
838
+ const hasFilters = filters.length > 0;
839
+ const activeFiltersCount = filters.filter((f) => f.value).length;
840
+ const shouldUseCollapsible = collapsible && hasFilters;
841
+ console.log("SearchAndFilter", { filters });
842
+ const FilterComponents = () => /* @__PURE__ */ jsxDEV12("div", {
843
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
844
+ children: filters.map((filter) => /* @__PURE__ */ jsxDEV12(FilterSelect, {
845
+ value: filter.value,
846
+ options: filter.options,
847
+ onChange: filter.onChange,
848
+ label: filter.label,
849
+ disabled: disabled || isLoading,
850
+ showCounts: filter.showCounts,
851
+ className: "min-w-0"
852
+ }, filter.key, false, undefined, this))
853
+ }, undefined, false, undefined, this);
854
+ return /* @__PURE__ */ jsxDEV12("div", {
855
+ className: `space-y-4 ${className}`,
856
+ children: [
857
+ /* @__PURE__ */ jsxDEV12("div", {
858
+ className: "flex flex-col gap-4 sm:flex-row",
859
+ children: [
860
+ /* @__PURE__ */ jsxDEV12("div", {
861
+ className: "flex-1",
862
+ children: /* @__PURE__ */ jsxDEV12(SearchInput, {
863
+ value: searchValue,
864
+ onChange: onSearchChange,
865
+ placeholder: searchPlaceholder,
866
+ disabled: disabled || isLoading,
867
+ className: "w-full"
868
+ }, undefined, false, undefined, this)
869
+ }, undefined, false, undefined, this),
870
+ shouldUseCollapsible && /* @__PURE__ */ jsxDEV12(Collapsible, {
871
+ open: !isCollapsed,
872
+ onOpenChange: setIsCollapsed,
873
+ className: "sm:hidden",
874
+ children: [
875
+ /* @__PURE__ */ jsxDEV12(CollapsibleTrigger2, {
876
+ asChild: true,
877
+ children: /* @__PURE__ */ jsxDEV12(Button, {
878
+ variant: "outline",
879
+ className: "sm:hidden",
880
+ disabled: disabled || isLoading,
881
+ children: [
882
+ /* @__PURE__ */ jsxDEV12(Filter, {
883
+ className: "mr-2 h-4 w-4"
884
+ }, undefined, false, undefined, this),
885
+ "Filtres",
886
+ activeFiltersCount > 0 && /* @__PURE__ */ jsxDEV12("span", {
887
+ className: "bg-primary text-primary-foreground ml-2 flex h-5 w-5 items-center justify-center rounded-full text-sm",
888
+ children: activeFiltersCount
889
+ }, undefined, false, undefined, this),
890
+ isCollapsed ? /* @__PURE__ */ jsxDEV12(ChevronDown, {
891
+ className: "ml-2 h-4 w-4"
892
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV12(ChevronUp, {
893
+ className: "ml-2 h-4 w-4"
894
+ }, undefined, false, undefined, this)
895
+ ]
896
+ }, undefined, true, undefined, this)
897
+ }, undefined, false, undefined, this),
898
+ /* @__PURE__ */ jsxDEV12(CollapsibleContent2, {
899
+ className: "mt-4 space-y-4",
900
+ children: /* @__PURE__ */ jsxDEV12(FilterComponents, {}, undefined, false, undefined, this)
901
+ }, undefined, false, undefined, this)
902
+ ]
903
+ }, undefined, true, undefined, this)
904
+ ]
905
+ }, undefined, true, undefined, this),
906
+ hasFilters && /* @__PURE__ */ jsxDEV12("div", {
907
+ className: "hidden sm:block",
908
+ children: /* @__PURE__ */ jsxDEV12(FilterComponents, {}, undefined, false, undefined, this)
909
+ }, undefined, false, undefined, this),
910
+ activeFiltersCount > 0 && /* @__PURE__ */ jsxDEV12("div", {
911
+ className: "flex flex-wrap items-center gap-2",
912
+ children: [
913
+ /* @__PURE__ */ jsxDEV12("span", {
914
+ className: "text-muted-foreground text-base",
915
+ children: "Filtres actifs:"
916
+ }, undefined, false, undefined, this),
917
+ filters.filter((f) => f.value).map((filter) => {
918
+ const selectedOption = filter.options.find((opt) => opt.value === filter.value);
919
+ return /* @__PURE__ */ jsxDEV12(Button, {
920
+ variant: "secondary",
921
+ size: "sm",
922
+ onClick: () => filter.onChange(""),
923
+ disabled: disabled || isLoading,
924
+ className: "h-7 px-2 text-sm",
925
+ children: [
926
+ filter.label,
927
+ ": ",
928
+ selectedOption?.label,
929
+ /* @__PURE__ */ jsxDEV12("span", {
930
+ className: "ml-1",
931
+ children: "\xD7"
932
+ }, undefined, false, undefined, this)
933
+ ]
934
+ }, filter.key, true, undefined, this);
935
+ })
936
+ ]
937
+ }, undefined, true, undefined, this)
938
+ ]
939
+ }, undefined, true, undefined, this);
940
+ };
941
+ // ui/organisms/ListPage/ListPage.tsx
942
+ import Link from "next/link";
943
+ import { AlertTriangle, Loader2, Plus, RefreshCcw } from "lucide-react";
944
+ import { jsxDEV as jsxDEV13, Fragment } from "react/jsx-dev-runtime";
945
+ function ListPage({
946
+ title,
947
+ description,
948
+ header,
949
+ items,
950
+ totalItems,
951
+ totalPages,
952
+ isLoading,
953
+ isFetching,
954
+ error,
955
+ listState,
956
+ searchPlaceholder,
957
+ filters = [],
958
+ onRefresh,
959
+ primaryAction,
960
+ toolbar,
961
+ renderItem,
962
+ renderEmpty,
963
+ renderStats,
964
+ className = "",
965
+ itemClassName = ""
966
+ }) {
967
+ const {
968
+ searchQuery,
969
+ setSearchQuery,
970
+ filters: filterValues,
971
+ setFilter,
972
+ currentPage,
973
+ itemsPerPage,
974
+ setCurrentPage,
975
+ setItemsPerPage
976
+ } = listState;
977
+ if (isLoading && !items.length) {
978
+ return /* @__PURE__ */ jsxDEV13(VStack, {
979
+ className: `space-y-4 md:space-y-6 ${className}`,
980
+ children: [
981
+ header ? header : /* @__PURE__ */ jsxDEV13(VStack, {
982
+ className: "gap-1",
983
+ children: [
984
+ /* @__PURE__ */ jsxDEV13("h1", {
985
+ className: "text-2xl font-bold md:text-3xl",
986
+ children: title
987
+ }, undefined, false, undefined, this),
988
+ description && /* @__PURE__ */ jsxDEV13("p", {
989
+ className: "text-muted-foreground text-base",
990
+ children: description
991
+ }, undefined, false, undefined, this)
992
+ ]
993
+ }, undefined, true, undefined, this),
994
+ /* @__PURE__ */ jsxDEV13("div", {
995
+ className: "flex min-h-[400px] items-center justify-center",
996
+ children: /* @__PURE__ */ jsxDEV13(Card, {
997
+ children: /* @__PURE__ */ jsxDEV13(CardContent, {
998
+ className: "flex items-center gap-4 p-6",
999
+ children: [
1000
+ /* @__PURE__ */ jsxDEV13(Loader2, {
1001
+ className: "text-primary h-8 w-8 animate-spin"
1002
+ }, undefined, false, undefined, this),
1003
+ /* @__PURE__ */ jsxDEV13("div", {
1004
+ children: [
1005
+ /* @__PURE__ */ jsxDEV13("h3", {
1006
+ className: "font-medium",
1007
+ children: "Chargement..."
1008
+ }, undefined, false, undefined, this),
1009
+ /* @__PURE__ */ jsxDEV13("p", {
1010
+ className: "text-muted-foreground text-base",
1011
+ children: "R\xE9cup\xE9ration des donn\xE9es en cours"
1012
+ }, undefined, false, undefined, this)
1013
+ ]
1014
+ }, undefined, true, undefined, this)
1015
+ ]
1016
+ }, undefined, true, undefined, this)
1017
+ }, undefined, false, undefined, this)
1018
+ }, undefined, false, undefined, this)
1019
+ ]
1020
+ }, undefined, true, undefined, this);
1021
+ }
1022
+ if (error && !items.length) {
1023
+ return /* @__PURE__ */ jsxDEV13(VStack, {
1024
+ className: `space-y-4 md:space-y-6 ${className}`,
1025
+ children: [
1026
+ header ? header : /* @__PURE__ */ jsxDEV13(VStack, {
1027
+ className: "gap-1",
1028
+ children: [
1029
+ /* @__PURE__ */ jsxDEV13("h1", {
1030
+ className: "text-2xl font-bold md:text-3xl",
1031
+ children: title
1032
+ }, undefined, false, undefined, this),
1033
+ description && /* @__PURE__ */ jsxDEV13("p", {
1034
+ className: "text-muted-foreground text-base",
1035
+ children: description
1036
+ }, undefined, false, undefined, this)
1037
+ ]
1038
+ }, undefined, true, undefined, this),
1039
+ /* @__PURE__ */ jsxDEV13("div", {
1040
+ className: "flex min-h-[400px] items-center justify-center",
1041
+ children: /* @__PURE__ */ jsxDEV13(Card, {
1042
+ children: /* @__PURE__ */ jsxDEV13(CardContent, {
1043
+ className: "flex flex-col items-center gap-4 p-6 text-center",
1044
+ children: [
1045
+ /* @__PURE__ */ jsxDEV13(AlertTriangle, {
1046
+ className: "text-destructive h-12 w-12"
1047
+ }, undefined, false, undefined, this),
1048
+ /* @__PURE__ */ jsxDEV13("div", {
1049
+ children: [
1050
+ /* @__PURE__ */ jsxDEV13("h3", {
1051
+ className: "font-medium",
1052
+ children: "Erreur de chargement"
1053
+ }, undefined, false, undefined, this),
1054
+ /* @__PURE__ */ jsxDEV13("p", {
1055
+ className: "text-muted-foreground text-base",
1056
+ children: error.message || "Une erreur est survenue"
1057
+ }, undefined, false, undefined, this)
1058
+ ]
1059
+ }, undefined, true, undefined, this),
1060
+ onRefresh && /* @__PURE__ */ jsxDEV13(Button, {
1061
+ onClick: onRefresh,
1062
+ variant: "outline",
1063
+ size: "sm",
1064
+ children: [
1065
+ /* @__PURE__ */ jsxDEV13(RefreshCcw, {
1066
+ className: "mr-2 h-4 w-4"
1067
+ }, undefined, false, undefined, this),
1068
+ "R\xE9essayer"
1069
+ ]
1070
+ }, undefined, true, undefined, this)
1071
+ ]
1072
+ }, undefined, true, undefined, this)
1073
+ }, undefined, false, undefined, this)
1074
+ }, undefined, false, undefined, this)
1075
+ ]
1076
+ }, undefined, true, undefined, this);
1077
+ }
1078
+ const filterConfigs = filters.map((filter) => ({
1079
+ key: filter.key,
1080
+ label: filter.label,
1081
+ value: filterValues[filter.key] || "",
1082
+ options: filter.options,
1083
+ onChange: (value) => {
1084
+ setFilter(filter.key, value === "all" ? "" : value);
1085
+ },
1086
+ showCounts: filter.showCounts
1087
+ }));
1088
+ return /* @__PURE__ */ jsxDEV13(VStack, {
1089
+ className: `space-y-4 md:space-y-6 ${className}`,
1090
+ children: [
1091
+ header ? header : /* @__PURE__ */ jsxDEV13(HStack, {
1092
+ className: "items-center justify-between",
1093
+ children: [
1094
+ /* @__PURE__ */ jsxDEV13(VStack, {
1095
+ className: "gap-1",
1096
+ children: [
1097
+ /* @__PURE__ */ jsxDEV13("h1", {
1098
+ className: "text-2xl font-bold md:text-3xl",
1099
+ children: title
1100
+ }, undefined, false, undefined, this),
1101
+ description && /* @__PURE__ */ jsxDEV13("p", {
1102
+ className: "text-muted-foreground text-base",
1103
+ children: description
1104
+ }, undefined, false, undefined, this)
1105
+ ]
1106
+ }, undefined, true, undefined, this),
1107
+ /* @__PURE__ */ jsxDEV13(HStack, {
1108
+ className: "items-center gap-4",
1109
+ children: [
1110
+ toolbar,
1111
+ (isLoading || isFetching) && /* @__PURE__ */ jsxDEV13("div", {
1112
+ className: "text-muted-foreground flex items-center gap-2 text-base",
1113
+ children: [
1114
+ /* @__PURE__ */ jsxDEV13(Loader2, {
1115
+ className: "h-4 w-4 animate-spin"
1116
+ }, undefined, false, undefined, this),
1117
+ /* @__PURE__ */ jsxDEV13("span", {
1118
+ className: "hidden sm:inline",
1119
+ children: "Mise \xE0 jour..."
1120
+ }, undefined, false, undefined, this)
1121
+ ]
1122
+ }, undefined, true, undefined, this),
1123
+ onRefresh && /* @__PURE__ */ jsxDEV13(Button, {
1124
+ variant: "outline",
1125
+ size: "sm",
1126
+ onClick: onRefresh,
1127
+ disabled: Boolean(isLoading),
1128
+ "aria-label": "Rafra\xEEchir",
1129
+ children: [
1130
+ /* @__PURE__ */ jsxDEV13(RefreshCcw, {
1131
+ className: `mr-2 h-4 w-4 ${isLoading || isFetching ? "animate-spin" : ""}`
1132
+ }, undefined, false, undefined, this),
1133
+ /* @__PURE__ */ jsxDEV13("span", {
1134
+ className: "hidden sm:inline",
1135
+ children: "Rafra\xEEchir"
1136
+ }, undefined, false, undefined, this)
1137
+ ]
1138
+ }, undefined, true, undefined, this),
1139
+ primaryAction && /* @__PURE__ */ jsxDEV13(Fragment, {
1140
+ children: primaryAction.href ? /* @__PURE__ */ jsxDEV13(Link, {
1141
+ href: primaryAction.href,
1142
+ children: /* @__PURE__ */ jsxDEV13(Button, {
1143
+ children: [
1144
+ primaryAction.icon || /* @__PURE__ */ jsxDEV13(Plus, {
1145
+ className: "mr-2 h-4 w-4"
1146
+ }, undefined, false, undefined, this),
1147
+ /* @__PURE__ */ jsxDEV13("span", {
1148
+ className: "hidden sm:inline",
1149
+ children: primaryAction.label
1150
+ }, undefined, false, undefined, this),
1151
+ /* @__PURE__ */ jsxDEV13("span", {
1152
+ className: "sm:hidden",
1153
+ children: "Nouveau"
1154
+ }, undefined, false, undefined, this)
1155
+ ]
1156
+ }, undefined, true, undefined, this)
1157
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13(Button, {
1158
+ onClick: primaryAction.onClick,
1159
+ children: [
1160
+ primaryAction.icon || /* @__PURE__ */ jsxDEV13(Plus, {
1161
+ className: "mr-2 h-4 w-4"
1162
+ }, undefined, false, undefined, this),
1163
+ /* @__PURE__ */ jsxDEV13("span", {
1164
+ className: "hidden sm:inline",
1165
+ children: primaryAction.label
1166
+ }, undefined, false, undefined, this),
1167
+ /* @__PURE__ */ jsxDEV13("span", {
1168
+ className: "sm:hidden",
1169
+ children: "Nouveau"
1170
+ }, undefined, false, undefined, this)
1171
+ ]
1172
+ }, undefined, true, undefined, this)
1173
+ }, undefined, false, undefined, this)
1174
+ ]
1175
+ }, undefined, true, undefined, this)
1176
+ ]
1177
+ }, undefined, true, undefined, this),
1178
+ renderStats && /* @__PURE__ */ jsxDEV13(Fragment, {
1179
+ children: [
1180
+ renderStats(items),
1181
+ /* @__PURE__ */ jsxDEV13(Separator2, {}, undefined, false, undefined, this)
1182
+ ]
1183
+ }, undefined, true, undefined, this),
1184
+ /* @__PURE__ */ jsxDEV13(SearchAndFilter, {
1185
+ searchValue: searchQuery,
1186
+ onSearchChange: setSearchQuery,
1187
+ searchPlaceholder,
1188
+ filters: filterConfigs,
1189
+ isLoading
1190
+ }, undefined, false, undefined, this),
1191
+ items.length === 0 && !isLoading ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxDEV13(Card, {
1192
+ children: /* @__PURE__ */ jsxDEV13(CardContent, {
1193
+ className: "flex flex-col items-center gap-4 p-8 text-center",
1194
+ children: [
1195
+ /* @__PURE__ */ jsxDEV13("div", {
1196
+ className: "bg-muted flex h-12 w-12 items-center justify-center rounded-full",
1197
+ children: /* @__PURE__ */ jsxDEV13("div", {
1198
+ className: "bg-muted-foreground/20 h-6 w-6 rounded-full"
1199
+ }, undefined, false, undefined, this)
1200
+ }, undefined, false, undefined, this),
1201
+ /* @__PURE__ */ jsxDEV13("div", {
1202
+ children: [
1203
+ /* @__PURE__ */ jsxDEV13("h3", {
1204
+ className: "font-medium",
1205
+ children: "Aucun \xE9l\xE9ment trouv\xE9"
1206
+ }, undefined, false, undefined, this),
1207
+ /* @__PURE__ */ jsxDEV13("p", {
1208
+ className: "text-muted-foreground text-base",
1209
+ children: searchQuery || Object.values(filterValues).some((v) => v) ? "Essayez de modifier vos crit\xE8res de recherche" : "Commencez par cr\xE9er votre premier \xE9l\xE9ment"
1210
+ }, undefined, false, undefined, this)
1211
+ ]
1212
+ }, undefined, true, undefined, this),
1213
+ primaryAction && !searchQuery && !Object.values(filterValues).some((v) => v) && /* @__PURE__ */ jsxDEV13(Fragment, {
1214
+ children: primaryAction.href ? /* @__PURE__ */ jsxDEV13(Link, {
1215
+ href: primaryAction.href,
1216
+ children: /* @__PURE__ */ jsxDEV13(Button, {
1217
+ children: [
1218
+ primaryAction.icon || /* @__PURE__ */ jsxDEV13(Plus, {
1219
+ className: "mr-2 h-4 w-4"
1220
+ }, undefined, false, undefined, this),
1221
+ primaryAction.label
1222
+ ]
1223
+ }, undefined, true, undefined, this)
1224
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13(Button, {
1225
+ onClick: primaryAction.onClick,
1226
+ children: [
1227
+ primaryAction.icon || /* @__PURE__ */ jsxDEV13(Plus, {
1228
+ className: "mr-2 h-4 w-4"
1229
+ }, undefined, false, undefined, this),
1230
+ primaryAction.label
1231
+ ]
1232
+ }, undefined, true, undefined, this)
1233
+ }, undefined, false, undefined, this)
1234
+ ]
1235
+ }, undefined, true, undefined, this)
1236
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13(Fragment, {
1237
+ children: [
1238
+ /* @__PURE__ */ jsxDEV13("div", {
1239
+ className: `space-y-4 ${itemClassName}`,
1240
+ children: items.map((item, index) => renderItem(item, index))
1241
+ }, undefined, false, undefined, this),
1242
+ totalPages > 1 && /* @__PURE__ */ jsxDEV13(Pagination, {
1243
+ currentPage,
1244
+ totalPages,
1245
+ totalItems,
1246
+ itemsPerPage,
1247
+ onPageChange: setCurrentPage,
1248
+ onItemsPerPageChange: setItemsPerPage,
1249
+ disabled: isLoading
1250
+ }, undefined, false, undefined, this)
1251
+ ]
1252
+ }, undefined, true, undefined, this)
1253
+ ]
1254
+ }, undefined, true, undefined, this);
1255
+ }
3
1256
  export {
4
1257
  ListPage
5
1258
  };