@nccirtu/tablefy 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +34 -0
  2. package/cli/templates/tablefy/data-table-empty.tsx +0 -1
  3. package/cli/templates/tablefy/data-table-header.tsx +0 -1
  4. package/cli/templates/tablefy/data-table-pagination.tsx +0 -1
  5. package/dist/columns/actions-column.d.ts +3 -3
  6. package/dist/columns/base-column.d.ts +2 -2
  7. package/dist/columns/checkbox-column.d.ts +1 -1
  8. package/dist/columns/columns/actions-column.d.ts +3 -3
  9. package/dist/columns/columns/base-column.d.ts +2 -2
  10. package/dist/columns/columns/checkbox-column.d.ts +1 -1
  11. package/dist/columns/columns/date-column.d.ts +5 -5
  12. package/dist/columns/columns/icon-column.d.ts +7 -7
  13. package/dist/columns/columns/image-column.d.ts +7 -7
  14. package/dist/columns/columns/link-column.d.ts +6 -6
  15. package/dist/columns/columns/number-column.d.ts +3 -3
  16. package/dist/columns/columns/progress-column.d.ts +7 -7
  17. package/dist/columns/columns/text-column.d.ts +3 -3
  18. package/dist/columns/columns/types.d.ts +5 -5
  19. package/dist/columns/date-column.d.ts +5 -5
  20. package/dist/columns/icon-column.d.ts +7 -7
  21. package/dist/columns/image-column.d.ts +7 -7
  22. package/dist/columns/index.esm.js +189 -167
  23. package/dist/columns/index.esm.js.map +1 -1
  24. package/dist/columns/index.js +189 -167
  25. package/dist/columns/index.js.map +1 -1
  26. package/dist/columns/link-column.d.ts +6 -6
  27. package/dist/columns/number-column.d.ts +3 -3
  28. package/dist/columns/progress-column.d.ts +7 -7
  29. package/dist/columns/text-column.d.ts +3 -3
  30. package/dist/columns/types.d.ts +5 -5
  31. package/dist/index.esm.js +189 -167
  32. package/dist/index.esm.js.map +1 -1
  33. package/dist/index.js +189 -167
  34. package/dist/index.js.map +1 -1
  35. package/package.json +1 -1
@@ -23,7 +23,7 @@ class BaseColumn {
23
23
  sortable: false,
24
24
  searchable: false,
25
25
  hidden: false,
26
- align: 'left',
26
+ align: "left",
27
27
  };
28
28
  }
29
29
  // Fluent API Methods
@@ -44,15 +44,15 @@ class BaseColumn {
44
44
  return this;
45
45
  }
46
46
  alignLeft() {
47
- this.config.align = 'left';
47
+ this.config.align = "left";
48
48
  return this;
49
49
  }
50
50
  alignCenter() {
51
- this.config.align = 'center';
51
+ this.config.align = "center";
52
52
  return this;
53
53
  }
54
54
  alignRight() {
55
- this.config.align = 'right';
55
+ this.config.align = "right";
56
56
  return this;
57
57
  }
58
58
  width(width) {
@@ -73,11 +73,11 @@ class BaseColumn {
73
73
  }
74
74
  // Hilfsfunktion für Alignment-Klassen
75
75
  getAlignmentClass() {
76
- const baseClasses = 'text-sm text-muted-foreground';
76
+ const baseClasses = "text-sm text-muted-foreground";
77
77
  switch (this.config.align) {
78
- case 'center':
78
+ case "center":
79
79
  return `${baseClasses} text-center`;
80
- case 'right':
80
+ case "right":
81
81
  return `${baseClasses} text-right`;
82
82
  default:
83
83
  return `${baseClasses} text-left`;
@@ -278,8 +278,9 @@ class CheckboxColumn {
278
278
  }
279
279
  build() {
280
280
  return {
281
- id: 'select',
282
- header: ({ table }) => (jsx(Checkbox, { checked: table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'), onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value), "aria-label": "Alle ausw\u00E4hlen" })),
281
+ id: "select",
282
+ header: ({ table }) => (jsx(Checkbox, { checked: table.getIsAllPageRowsSelected() ||
283
+ (table.getIsSomePageRowsSelected() && "indeterminate"), onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value), "aria-label": "Alle ausw\u00E4hlen" })),
283
284
  cell: ({ row }) => (jsx(Checkbox, { checked: row.getIsSelected(), onCheckedChange: (value) => row.toggleSelected(!!value), "aria-label": "Zeile ausw\u00E4hlen" })),
284
285
  enableSorting: false,
285
286
  enableHiding: false,
@@ -290,8 +291,8 @@ class CheckboxColumn {
290
291
  class DateColumn extends BaseColumn {
291
292
  constructor(accessor) {
292
293
  super(accessor);
293
- this.config.format = 'short';
294
- this.config.locale = 'de-DE';
294
+ this.config.format = "short";
295
+ this.config.locale = "de-DE";
295
296
  this.config.showIcon = false;
296
297
  }
297
298
  static make(accessor) {
@@ -311,52 +312,62 @@ class DateColumn extends BaseColumn {
311
312
  }
312
313
  // Shortcuts
313
314
  short() {
314
- return this.format('short');
315
+ return this.format("short");
315
316
  }
316
317
  long() {
317
- return this.format('long');
318
+ return this.format("long");
318
319
  }
319
320
  relative() {
320
- return this.format('relative');
321
+ return this.format("relative");
321
322
  }
322
323
  time() {
323
- return this.format('time');
324
+ return this.format("time");
324
325
  }
325
326
  datetime() {
326
- return this.format('datetime');
327
+ return this.format("datetime");
327
328
  }
328
329
  formatDate(date, format, locale) {
329
- if (format === 'relative') {
330
+ if (format === "relative") {
330
331
  return this.getRelativeTime(date);
331
332
  }
332
333
  const formatOptions = {
333
- short: { day: '2-digit', month: '2-digit', year: 'numeric' },
334
- long: { day: 'numeric', month: 'long', year: 'numeric' },
335
- time: { hour: '2-digit', minute: '2-digit' },
336
- datetime: { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' },
334
+ short: { day: "2-digit", month: "2-digit", year: "numeric" },
335
+ long: { day: "numeric", month: "long", year: "numeric" },
336
+ time: { hour: "2-digit", minute: "2-digit" },
337
+ datetime: {
338
+ day: "2-digit",
339
+ month: "2-digit",
340
+ year: "numeric",
341
+ hour: "2-digit",
342
+ minute: "2-digit",
343
+ },
344
+ };
345
+ const options = formatOptions[format] || {
346
+ day: "2-digit",
347
+ month: "2-digit",
348
+ year: "numeric",
337
349
  };
338
- const options = formatOptions[format] || { day: '2-digit', month: '2-digit', year: 'numeric' };
339
350
  return new Intl.DateTimeFormat(locale, options).format(date);
340
351
  }
341
352
  getRelativeTime(date) {
342
353
  const now = new Date();
343
354
  const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
344
355
  const intervals = [
345
- { label: 'Jahr', seconds: 31536000 },
346
- { label: 'Monat', seconds: 2592000 },
347
- { label: 'Woche', seconds: 604800 },
348
- { label: 'Tag', seconds: 86400 },
349
- { label: 'Stunde', seconds: 3600 },
350
- { label: 'Minute', seconds: 60 },
356
+ { label: "Jahr", seconds: 31536000 },
357
+ { label: "Monat", seconds: 2592000 },
358
+ { label: "Woche", seconds: 604800 },
359
+ { label: "Tag", seconds: 86400 },
360
+ { label: "Stunde", seconds: 3600 },
361
+ { label: "Minute", seconds: 60 },
351
362
  ];
352
363
  for (const interval of intervals) {
353
364
  const count = Math.floor(diffInSeconds / interval.seconds);
354
365
  if (count >= 1) {
355
- const plural = count > 1 ? (interval.label === 'Monat' ? 'e' : 'en') : '';
366
+ const plural = count > 1 ? (interval.label === "Monat" ? "e" : "en") : "";
356
367
  return `vor ${count} ${interval.label}${plural}`;
357
368
  }
358
369
  }
359
- return 'gerade eben';
370
+ return "gerade eben";
360
371
  }
361
372
  build() {
362
373
  const config = this.config;
@@ -366,9 +377,9 @@ class DateColumn extends BaseColumn {
366
377
  header: ({ column }) => {
367
378
  const displayLabel = label || String(accessor);
368
379
  if (!sortable) {
369
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
380
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
370
381
  }
371
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
382
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
372
383
  },
373
384
  cell: ({ getValue }) => {
374
385
  const value = getValue();
@@ -377,10 +388,10 @@ class DateColumn extends BaseColumn {
377
388
  }
378
389
  const date = value instanceof Date ? value : new Date(value);
379
390
  if (isNaN(date.getTime())) {
380
- return jsx("span", { className: "text-muted-foreground", children: "Ung\u00FCltiges Datum" });
391
+ return (jsx("span", { className: "text-muted-foreground", children: "Ung\u00FCltiges Datum" }));
381
392
  }
382
- const formatted = this.formatDate(date, format || 'short', locale || 'de-DE');
383
- return (jsxs("span", { className: cn('flex items-center gap-2', this.getAlignmentClass(), this.config.cellClassName), children: [showIcon && jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), formatted] }));
393
+ const formatted = this.formatDate(date, format || "short", locale || "de-DE");
394
+ return (jsxs("span", { className: cn("flex items-center gap-2", this.getAlignmentClass(), this.config.cellClassName), children: [showIcon && jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), formatted] }));
384
395
  },
385
396
  };
386
397
  }
@@ -403,11 +414,11 @@ class IconColumn extends BaseColumn {
403
414
  super(accessor);
404
415
  const config = this.config;
405
416
  config.states = {};
406
- config.size = 'md';
417
+ config.size = "md";
407
418
  config.showLabel = false;
408
419
  config.showTooltip = true;
409
420
  config.withBackground = false;
410
- config.align = 'center';
421
+ config.align = "center";
411
422
  }
412
423
  static make(accessor) {
413
424
  return new IconColumn(accessor);
@@ -459,14 +470,14 @@ class IconColumn extends BaseColumn {
459
470
  c.states = {
460
471
  true: {
461
472
  icon: config?.trueIcon || this.createCheckIcon(),
462
- label: config?.trueLabel || 'Ja',
463
- color: config?.trueColor || 'text-green-500',
473
+ label: config?.trueLabel || "Ja",
474
+ color: config?.trueColor || "text-green-500",
464
475
  bgColor: config?.trueBgColor,
465
476
  },
466
477
  false: {
467
478
  icon: config?.falseIcon || this.createXIcon(),
468
- label: config?.falseLabel || 'Nein',
469
- color: config?.falseColor || 'text-red-500',
479
+ label: config?.falseLabel || "Nein",
480
+ color: config?.falseColor || "text-red-500",
470
481
  bgColor: config?.falseBgColor,
471
482
  },
472
483
  };
@@ -477,15 +488,15 @@ class IconColumn extends BaseColumn {
477
488
  return this.states({
478
489
  active: {
479
490
  icon: this.createCircleIcon(),
480
- label: 'Aktiv',
481
- color: 'text-green-500',
482
- tooltip: 'Status: Aktiv',
491
+ label: "Aktiv",
492
+ color: "text-green-500",
493
+ tooltip: "Status: Aktiv",
483
494
  },
484
495
  inactive: {
485
496
  icon: this.createCircleIcon(),
486
- label: 'Inaktiv',
487
- color: 'text-gray-400',
488
- tooltip: 'Status: Inaktiv',
497
+ label: "Inaktiv",
498
+ color: "text-gray-400",
499
+ tooltip: "Status: Inaktiv",
489
500
  },
490
501
  });
491
502
  }
@@ -494,27 +505,27 @@ class IconColumn extends BaseColumn {
494
505
  return this.states({
495
506
  online: {
496
507
  icon: this.createCircleIcon(),
497
- label: 'Online',
498
- color: 'text-green-500',
499
- bgColor: 'bg-green-500',
508
+ label: "Online",
509
+ color: "text-green-500",
510
+ bgColor: "bg-green-500",
500
511
  },
501
512
  offline: {
502
513
  icon: this.createCircleIcon(),
503
- label: 'Offline',
504
- color: 'text-gray-400',
505
- bgColor: 'bg-gray-400',
514
+ label: "Offline",
515
+ color: "text-gray-400",
516
+ bgColor: "bg-gray-400",
506
517
  },
507
518
  away: {
508
519
  icon: this.createCircleIcon(),
509
- label: 'Abwesend',
510
- color: 'text-yellow-500',
511
- bgColor: 'bg-yellow-500',
520
+ label: "Abwesend",
521
+ color: "text-yellow-500",
522
+ bgColor: "bg-yellow-500",
512
523
  },
513
524
  busy: {
514
525
  icon: this.createCircleIcon(),
515
- label: 'Beschäftigt',
516
- color: 'text-red-500',
517
- bgColor: 'bg-red-500',
526
+ label: "Beschäftigt",
527
+ color: "text-red-500",
528
+ bgColor: "bg-red-500",
518
529
  },
519
530
  });
520
531
  }
@@ -523,23 +534,23 @@ class IconColumn extends BaseColumn {
523
534
  return this.states({
524
535
  low: {
525
536
  icon: this.createArrowDownIcon(),
526
- label: 'Niedrig',
527
- color: 'text-blue-500',
537
+ label: "Niedrig",
538
+ color: "text-blue-500",
528
539
  },
529
540
  medium: {
530
541
  icon: this.createMinusIcon(),
531
- label: 'Mittel',
532
- color: 'text-yellow-500',
542
+ label: "Mittel",
543
+ color: "text-yellow-500",
533
544
  },
534
545
  high: {
535
546
  icon: this.createArrowUpIcon(),
536
- label: 'Hoch',
537
- color: 'text-orange-500',
547
+ label: "Hoch",
548
+ color: "text-orange-500",
538
549
  },
539
550
  critical: {
540
551
  icon: this.createAlertIcon(),
541
- label: 'Kritisch',
542
- color: 'text-red-500',
552
+ label: "Kritisch",
553
+ color: "text-red-500",
543
554
  },
544
555
  });
545
556
  }
@@ -548,18 +559,18 @@ class IconColumn extends BaseColumn {
548
559
  return this.states({
549
560
  verified: {
550
561
  icon: this.createShieldCheckIcon(),
551
- label: 'Verifiziert',
552
- color: 'text-green-500',
562
+ label: "Verifiziert",
563
+ color: "text-green-500",
553
564
  },
554
565
  pending: {
555
566
  icon: this.createClockIcon(),
556
- label: 'Ausstehend',
557
- color: 'text-yellow-500',
567
+ label: "Ausstehend",
568
+ color: "text-yellow-500",
558
569
  },
559
570
  rejected: {
560
571
  icon: this.createShieldXIcon(),
561
- label: 'Abgelehnt',
562
- color: 'text-red-500',
572
+ label: "Abgelehnt",
573
+ color: "text-red-500",
563
574
  },
564
575
  });
565
576
  }
@@ -596,33 +607,33 @@ class IconColumn extends BaseColumn {
596
607
  }
597
608
  build() {
598
609
  const config = this.config;
599
- const { accessor, label, sortable, states, size, showLabel, showTooltip, withBackground, defaultIcon, defaultLabel } = config;
610
+ const { accessor, label, sortable, states, size, showLabel, showTooltip, withBackground, defaultIcon, defaultLabel, } = config;
600
611
  const sizeClasses = {
601
- xs: 'h-3 w-3',
602
- sm: 'h-4 w-4',
603
- md: 'h-5 w-5',
604
- lg: 'h-6 w-6',
612
+ xs: "h-3 w-3",
613
+ sm: "h-4 w-4",
614
+ md: "h-5 w-5",
615
+ lg: "h-6 w-6",
605
616
  };
606
617
  const bgSizeClasses = {
607
- xs: 'h-5 w-5',
608
- sm: 'h-6 w-6',
609
- md: 'h-8 w-8',
610
- lg: 'h-10 w-10',
618
+ xs: "h-5 w-5",
619
+ sm: "h-6 w-6",
620
+ md: "h-8 w-8",
621
+ lg: "h-10 w-10",
611
622
  };
612
623
  const iconInBgSizeClasses = {
613
- xs: 'h-2.5 w-2.5',
614
- sm: 'h-3 w-3',
615
- md: 'h-4 w-4',
616
- lg: 'h-5 w-5',
624
+ xs: "h-2.5 w-2.5",
625
+ sm: "h-3 w-3",
626
+ md: "h-4 w-4",
627
+ lg: "h-5 w-5",
617
628
  };
618
629
  return {
619
630
  accessorKey: accessor,
620
631
  header: ({ column }) => {
621
632
  const displayLabel = label || String(accessor);
622
633
  if (!sortable) {
623
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
634
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
624
635
  }
625
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
636
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
626
637
  },
627
638
  cell: ({ getValue }) => {
628
639
  const value = String(getValue());
@@ -630,16 +641,16 @@ class IconColumn extends BaseColumn {
630
641
  // Default verwenden wenn State nicht gefunden
631
642
  const icon = stateConfig?.icon || defaultIcon;
632
643
  const stateLabel = stateConfig?.label || defaultLabel || value;
633
- const color = stateConfig?.color || 'text-muted-foreground';
644
+ const color = stateConfig?.color || "text-muted-foreground";
634
645
  const bgColor = stateConfig?.bgColor;
635
646
  const tooltip = stateConfig?.tooltip || stateLabel;
636
647
  if (!icon) {
637
648
  return jsx("span", { className: "text-muted-foreground", children: "\u2014" });
638
649
  }
639
650
  // Icon als Element rendern (falls LucideIcon übergeben wurde)
640
- const IconElement = typeof icon === 'function' ? icon : null;
641
- const renderedIcon = IconElement ? jsx(IconElement, { className: "h-full w-full" }) : icon;
642
- const iconElement = (jsxs("div", { className: cn('flex items-center gap-2', this.getAlignmentClass(), this.config.cellClassName), children: [withBackground ? (jsx("div", { className: cn('inline-flex items-center justify-center rounded-md', bgSizeClasses[size || 'md'], bgColor || 'bg-blue-50'), children: jsx("div", { className: cn(iconInBgSizeClasses[size || 'md'], color), children: renderedIcon }) })) : (jsx("div", { className: cn(sizeClasses[size || 'md'], color), children: renderedIcon })), showLabel && jsx("span", { className: cn('text-sm', color), children: stateLabel })] }));
651
+ const IconElement = typeof icon === "function" ? icon : null;
652
+ const renderedIcon = IconElement ? (jsx(IconElement, { className: "h-full w-full" })) : icon;
653
+ const iconElement = (jsxs("div", { className: cn("flex items-center gap-2", this.getAlignmentClass(), this.config.cellClassName), children: [withBackground ? (jsx("div", { className: cn("inline-flex items-center justify-center rounded-md", bgSizeClasses[size || "md"], bgColor || "bg-blue-50"), children: jsx("div", { className: cn(iconInBgSizeClasses[size || "md"], color), children: renderedIcon }) })) : (jsx("div", { className: cn(sizeClasses[size || "md"], color), children: renderedIcon })), showLabel && (jsx("span", { className: cn("text-sm", color), children: stateLabel }))] }));
643
654
  if (showTooltip) {
644
655
  return (jsx(TooltipProvider, { children: jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: iconElement }), jsx(TooltipContent, { children: jsx("p", { children: tooltip }) })] }) }));
645
656
  }
@@ -652,8 +663,8 @@ class IconColumn extends BaseColumn {
652
663
  class ImageColumn extends BaseColumn {
653
664
  constructor(accessor) {
654
665
  super(accessor);
655
- this.config.size = 'md';
656
- this.config.rounded = 'md';
666
+ this.config.size = "md";
667
+ this.config.rounded = "md";
657
668
  }
658
669
  static make(accessor) {
659
670
  return new ImageColumn(accessor);
@@ -667,10 +678,10 @@ class ImageColumn extends BaseColumn {
667
678
  return this;
668
679
  }
669
680
  circular() {
670
- return this.rounded('full');
681
+ return this.rounded("full");
671
682
  }
672
683
  square() {
673
- return this.rounded('none');
684
+ return this.rounded("none");
674
685
  }
675
686
  fallback(url) {
676
687
  this.config.fallback = url;
@@ -684,24 +695,24 @@ class ImageColumn extends BaseColumn {
684
695
  const config = this.config;
685
696
  const { accessor, label, size, rounded, fallback, alt } = config;
686
697
  const sizeClasses = {
687
- sm: 'h-8 w-8',
688
- md: 'h-10 w-10',
689
- lg: 'h-12 w-12',
698
+ sm: "h-8 w-8",
699
+ md: "h-10 w-10",
700
+ lg: "h-12 w-12",
690
701
  };
691
702
  const roundedClasses = {
692
- none: 'rounded-none',
693
- sm: 'rounded-sm',
694
- md: 'rounded-md',
695
- lg: 'rounded-lg',
696
- full: 'rounded-full',
703
+ none: "rounded-none",
704
+ sm: "rounded-sm",
705
+ md: "rounded-md",
706
+ lg: "rounded-lg",
707
+ full: "rounded-full",
697
708
  };
698
709
  return {
699
710
  accessorKey: accessor,
700
- header: () => jsx("span", { className: cn('text-muted-foreground font-medium', this.config.headerClassName), children: label || '' }),
711
+ header: () => (jsx("span", { className: cn("text-muted-foreground font-medium", this.config.headerClassName), children: label || "" })),
701
712
  cell: ({ getValue, row }) => {
702
713
  const src = getValue();
703
- const altText = alt ? alt(row.original) : 'Bild';
704
- return (jsx("img", { src: src || fallback || '/placeholder.png', alt: altText, className: cn('object-cover', sizeClasses[size || 'md'], roundedClasses[rounded || 'md'], this.config.cellClassName), onError: (e) => {
714
+ const altText = alt ? alt(row.original) : "Bild";
715
+ return (jsx("img", { src: src || fallback || "/placeholder.png", alt: altText, className: cn("object-cover", sizeClasses[size || "md"], roundedClasses[rounded || "md"], this.config.cellClassName), onError: (e) => {
705
716
  if (fallback) {
706
717
  e.target.src = fallback;
707
718
  }
@@ -729,7 +740,7 @@ class LinkColumn extends BaseColumn {
729
740
  const config = this.config;
730
741
  config.external = false;
731
742
  config.showExternalIcon = false;
732
- config.underline = 'hover';
743
+ config.underline = "hover";
733
744
  config.openInNewTab = false;
734
745
  }
735
746
  static make(accessor) {
@@ -780,20 +791,20 @@ class LinkColumn extends BaseColumn {
780
791
  }
781
792
  build() {
782
793
  const config = this.config;
783
- const { accessor, label, sortable, href, icon, showExternalIcon, underline, openInNewTab, onClick } = config;
794
+ const { accessor, label, sortable, href, icon, showExternalIcon, underline, openInNewTab, onClick, } = config;
784
795
  const underlineClasses = {
785
- always: 'underline',
786
- hover: 'hover:underline',
787
- never: 'no-underline',
796
+ always: "underline",
797
+ hover: "hover:underline",
798
+ never: "no-underline",
788
799
  };
789
800
  return {
790
801
  accessorKey: accessor,
791
802
  header: ({ column }) => {
792
803
  const displayLabel = label || String(accessor);
793
804
  if (!sortable) {
794
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
805
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
795
806
  }
796
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
807
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
797
808
  },
798
809
  cell: ({ getValue, row }) => {
799
810
  const value = getValue();
@@ -801,7 +812,7 @@ class LinkColumn extends BaseColumn {
801
812
  return jsx("span", { className: "text-muted-foreground", children: "\u2014" });
802
813
  }
803
814
  // URL berechnen
804
- const url = typeof href === 'function' ? href(row.original) : href || value;
815
+ const url = typeof href === "function" ? href(row.original) : href || value;
805
816
  const handleClick = (e) => {
806
817
  if (onClick) {
807
818
  e.preventDefault();
@@ -809,8 +820,12 @@ class LinkColumn extends BaseColumn {
809
820
  }
810
821
  };
811
822
  // Alignment ohne text-muted-foreground für Links
812
- const alignmentClass = this.config.align === 'center' ? 'text-center' : this.config.align === 'right' ? 'text-right' : 'text-left';
813
- return (jsxs("a", { href: url, target: openInNewTab ? '_blank' : undefined, rel: openInNewTab ? 'noopener noreferrer' : undefined, onClick: onClick ? handleClick : undefined, className: cn('inline-flex items-center gap-1.5 text-sm text-blue-500', underlineClasses[underline || 'hover'], 'hover:text-blue-500/80', alignmentClass, this.config.cellClassName), children: [icon, jsx("span", { children: value }), showExternalIcon && jsx(ExternalLink, { className: "text-muted-foreground h-3 w-3" })] }));
823
+ const alignmentClass = this.config.align === "center"
824
+ ? "text-center"
825
+ : this.config.align === "right"
826
+ ? "text-right"
827
+ : "text-left";
828
+ return (jsxs("a", { href: url, target: openInNewTab ? "_blank" : undefined, rel: openInNewTab ? "noopener noreferrer" : undefined, onClick: onClick ? handleClick : undefined, className: cn("inline-flex items-center gap-1.5 text-sm text-blue-500", underlineClasses[underline || "hover"], "hover:text-blue-500/80", alignmentClass, this.config.cellClassName), children: [icon, jsx("span", { children: value }), showExternalIcon && (jsx(ExternalLink, { className: "text-muted-foreground h-3 w-3" }))] }));
814
829
  },
815
830
  };
816
831
  }
@@ -819,9 +834,9 @@ class LinkColumn extends BaseColumn {
819
834
  class NumberColumn extends BaseColumn {
820
835
  constructor(accessor) {
821
836
  super(accessor);
822
- this.config.align = 'right'; // Zahlen standardmäßig rechtsbündig
837
+ this.config.align = "right"; // Zahlen standardmäßig rechtsbündig
823
838
  this.config.decimals = 0;
824
- this.config.locale = 'de-DE';
839
+ this.config.locale = "de-DE";
825
840
  }
826
841
  static make(accessor) {
827
842
  return new NumberColumn(accessor);
@@ -835,7 +850,7 @@ class NumberColumn extends BaseColumn {
835
850
  return this;
836
851
  }
837
852
  // Währungsformatierung
838
- money(currency = 'EUR') {
853
+ money(currency = "EUR") {
839
854
  this.config.currency = currency;
840
855
  this.config.decimals = 2;
841
856
  return this;
@@ -855,15 +870,15 @@ class NumberColumn extends BaseColumn {
855
870
  }
856
871
  build() {
857
872
  const config = this.config;
858
- const { accessor, label, sortable, decimals, locale, currency, percent, prefix, suffix } = config;
873
+ const { accessor, label, sortable, decimals, locale, currency, percent, prefix, suffix, } = config;
859
874
  return {
860
875
  accessorKey: accessor,
861
876
  header: ({ column }) => {
862
877
  const displayLabel = label || String(accessor);
863
878
  if (!sortable) {
864
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
879
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
865
880
  }
866
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
881
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
867
882
  },
868
883
  cell: ({ getValue }) => {
869
884
  const value = getValue();
@@ -873,7 +888,7 @@ class NumberColumn extends BaseColumn {
873
888
  let formatted;
874
889
  if (currency) {
875
890
  formatted = new Intl.NumberFormat(locale, {
876
- style: 'currency',
891
+ style: "currency",
877
892
  currency,
878
893
  minimumFractionDigits: decimals,
879
894
  maximumFractionDigits: decimals,
@@ -881,7 +896,7 @@ class NumberColumn extends BaseColumn {
881
896
  }
882
897
  else if (percent) {
883
898
  formatted = new Intl.NumberFormat(locale, {
884
- style: 'percent',
899
+ style: "percent",
885
900
  minimumFractionDigits: decimals,
886
901
  maximumFractionDigits: decimals,
887
902
  }).format(value / 100);
@@ -892,8 +907,8 @@ class NumberColumn extends BaseColumn {
892
907
  maximumFractionDigits: decimals,
893
908
  }).format(value);
894
909
  }
895
- const displayValue = `${prefix || ''}${formatted}${suffix || ''}`;
896
- return jsx("span", { className: cn('tabular-nums', this.getAlignmentClass(), this.config.cellClassName), children: displayValue });
910
+ const displayValue = `${prefix || ""}${formatted}${suffix || ""}`;
911
+ return (jsx("span", { className: cn("tabular-nums", this.getAlignmentClass(), this.config.cellClassName), children: displayValue }));
897
912
  },
898
913
  };
899
914
  }
@@ -906,8 +921,8 @@ class ProgressColumn extends BaseColumn {
906
921
  config.max = 100;
907
922
  config.showValue = false;
908
923
  config.showPercentage = true;
909
- config.size = 'md';
910
- config.color = 'default';
924
+ config.size = "md";
925
+ config.color = "default";
911
926
  }
912
927
  static make(accessor) {
913
928
  return new ProgressColumn(accessor);
@@ -951,10 +966,10 @@ class ProgressColumn extends BaseColumn {
951
966
  config.color = (value, max) => {
952
967
  const percent = (value / max) * 100;
953
968
  if (percent <= danger)
954
- return 'danger';
969
+ return "danger";
955
970
  if (percent <= warning)
956
- return 'warning';
957
- return 'success';
971
+ return "warning";
972
+ return "success";
958
973
  };
959
974
  return this;
960
975
  }
@@ -965,10 +980,10 @@ class ProgressColumn extends BaseColumn {
965
980
  config.color = (value, max) => {
966
981
  const percent = (value / max) * 100;
967
982
  if (percent >= danger)
968
- return 'danger';
983
+ return "danger";
969
984
  if (percent >= warning)
970
- return 'warning';
971
- return 'success';
985
+ return "warning";
986
+ return "success";
972
987
  };
973
988
  return this;
974
989
  }
@@ -979,26 +994,26 @@ class ProgressColumn extends BaseColumn {
979
994
  }
980
995
  build() {
981
996
  const config = this.config;
982
- const { accessor, label, sortable, max, showValue, showPercentage, size, color, format } = config;
997
+ const { accessor, label, sortable, max, showValue, showPercentage, size, color, format, } = config;
983
998
  const sizeClasses = {
984
- sm: 'h-1.5',
985
- md: 'h-2',
986
- lg: 'h-3',
999
+ sm: "h-1.5",
1000
+ md: "h-2",
1001
+ lg: "h-3",
987
1002
  };
988
1003
  const colorClasses = {
989
- default: '[&>div]:bg-primary',
990
- success: '[&>div]:bg-green-500',
991
- warning: '[&>div]:bg-yellow-500',
992
- danger: '[&>div]:bg-red-500',
1004
+ default: "[&>div]:bg-primary",
1005
+ success: "[&>div]:bg-green-500",
1006
+ warning: "[&>div]:bg-yellow-500",
1007
+ danger: "[&>div]:bg-red-500",
993
1008
  };
994
1009
  return {
995
1010
  accessorKey: accessor,
996
1011
  header: ({ column }) => {
997
1012
  const displayLabel = label || String(accessor);
998
1013
  if (!sortable) {
999
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
1014
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
1000
1015
  }
1001
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
1016
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
1002
1017
  },
1003
1018
  cell: ({ getValue }) => {
1004
1019
  const value = getValue();
@@ -1008,9 +1023,11 @@ class ProgressColumn extends BaseColumn {
1008
1023
  }
1009
1024
  const percentage = Math.min(100, Math.max(0, (value / maxValue) * 100));
1010
1025
  // Farbe berechnen
1011
- const currentColor = typeof color === 'function' ? color(value, maxValue) : color || 'default';
1026
+ const currentColor = typeof color === "function"
1027
+ ? color(value, maxValue)
1028
+ : color || "default";
1012
1029
  // Label erstellen
1013
- let labelText = '';
1030
+ let labelText = "";
1014
1031
  if (format) {
1015
1032
  labelText = format(value, maxValue);
1016
1033
  }
@@ -1020,7 +1037,7 @@ class ProgressColumn extends BaseColumn {
1020
1037
  else if (showPercentage) {
1021
1038
  labelText = `${Math.round(percentage)}%`;
1022
1039
  }
1023
- return (jsxs("div", { className: cn('flex min-w-[120px] items-center gap-3', this.config.cellClassName), children: [jsx(Progress, { value: percentage, className: cn('flex-1', sizeClasses[size || 'md'], colorClasses[currentColor]) }), labelText && jsx("span", { className: "text-muted-foreground min-w-[3rem] text-right text-sm tabular-nums", children: labelText })] }));
1040
+ return (jsxs("div", { className: cn("flex min-w-[120px] items-center gap-3", this.config.cellClassName), children: [jsx(Progress, { value: percentage, className: cn("flex-1", sizeClasses[size || "md"], colorClasses[currentColor]) }), labelText && (jsx("span", { className: "text-muted-foreground min-w-[3rem] text-right text-sm tabular-nums", children: labelText }))] }));
1024
1041
  },
1025
1042
  };
1026
1043
  }
@@ -1063,7 +1080,9 @@ class TextColumn extends BaseColumn {
1063
1080
  const existingFormatter = this.config.formatter;
1064
1081
  this.config.formatter = (value, row) => {
1065
1082
  const result = existingFormatter ? existingFormatter(value, row) : value;
1066
- return typeof result === 'string' ? result.toUpperCase() : result;
1083
+ return typeof result === "string"
1084
+ ? result.toUpperCase()
1085
+ : result;
1067
1086
  };
1068
1087
  return this;
1069
1088
  }
@@ -1071,7 +1090,9 @@ class TextColumn extends BaseColumn {
1071
1090
  const existingFormatter = this.config.formatter;
1072
1091
  this.config.formatter = (value, row) => {
1073
1092
  const result = existingFormatter ? existingFormatter(value, row) : value;
1074
- return typeof result === 'string' ? result.toLowerCase() : result;
1093
+ return typeof result === "string"
1094
+ ? result.toLowerCase()
1095
+ : result;
1075
1096
  };
1076
1097
  return this;
1077
1098
  }
@@ -1079,23 +1100,23 @@ class TextColumn extends BaseColumn {
1079
1100
  const existingFormatter = this.config.formatter;
1080
1101
  this.config.formatter = (value, row) => {
1081
1102
  const result = existingFormatter ? existingFormatter(value, row) : value;
1082
- if (typeof result === 'string' && result.length > chars) {
1083
- return result.slice(0, chars) + '...';
1103
+ if (typeof result === "string" && result.length > chars) {
1104
+ return result.slice(0, chars) + "...";
1084
1105
  }
1085
1106
  return result;
1086
1107
  };
1087
1108
  return this;
1088
1109
  }
1089
1110
  build() {
1090
- const { accessor, label, sortable, prefix, suffix, placeholder, formatter } = this.config;
1111
+ const { accessor, label, sortable, prefix, suffix, placeholder, formatter, } = this.config;
1091
1112
  return {
1092
1113
  accessorKey: accessor,
1093
1114
  header: ({ column }) => {
1094
1115
  const displayLabel = label || String(accessor);
1095
1116
  if (!sortable) {
1096
- return (jsx("span", { className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
1117
+ return (jsx("span", { className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: displayLabel }));
1097
1118
  }
1098
- return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), className: cn('text-muted-foreground font-medium', this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
1119
+ return (jsxs(Button, { variant: "table_header", size: "table_header", onClick: () => column.toggleSorting(column.getIsSorted() === "asc"), className: cn("text-muted-foreground font-medium", this.getAlignmentClass(), this.config.headerClassName), children: [displayLabel, jsx(ArrowUpDown, { className: "ml-2 h-4 w-4" })] }));
1099
1120
  },
1100
1121
  cell: ({ row, getValue }) => {
1101
1122
  let value = getValue();
@@ -1104,12 +1125,12 @@ class TextColumn extends BaseColumn {
1104
1125
  value = formatter(value, row);
1105
1126
  }
1106
1127
  // Placeholder wenn leer
1107
- if (value === null || value === undefined || value === '') {
1108
- return (jsx("span", { className: cn('text-muted-foreground', this.getAlignmentClass(), this.config.cellClassName), children: placeholder || '' }));
1128
+ if (value === null || value === undefined || value === "") {
1129
+ return (jsx("span", { className: cn("text-muted-foreground", this.getAlignmentClass(), this.config.cellClassName), children: placeholder || "" }));
1109
1130
  }
1110
1131
  // Prefix/Suffix hinzufügen
1111
- const displayValue = `${prefix || ''}${value}${suffix || ''}`;
1112
- return jsx("span", { className: cn(this.getAlignmentClass(), this.config.cellClassName), children: displayValue });
1132
+ const displayValue = `${prefix || ""}${value}${suffix || ""}`;
1133
+ return (jsx("span", { className: cn(this.getAlignmentClass(), this.config.cellClassName), children: displayValue }));
1113
1134
  },
1114
1135
  };
1115
1136
  }
@@ -1118,7 +1139,7 @@ class TextColumn extends BaseColumn {
1118
1139
  class ActionsColumn {
1119
1140
  config = {
1120
1141
  actions: [],
1121
- label: 'Aktionen',
1142
+ label: "Aktionen",
1122
1143
  };
1123
1144
  static make() {
1124
1145
  return new ActionsColumn();
@@ -1138,16 +1159,16 @@ class ActionsColumn {
1138
1159
  }
1139
1160
  // Shortcuts für gängige Actions
1140
1161
  view(onClick) {
1141
- return this.action({ label: 'Anzeigen', onClick });
1162
+ return this.action({ label: "Anzeigen", onClick });
1142
1163
  }
1143
1164
  edit(onClick) {
1144
- return this.action({ label: 'Bearbeiten', onClick });
1165
+ return this.action({ label: "Bearbeiten", onClick });
1145
1166
  }
1146
1167
  delete(onClick) {
1147
1168
  return this.action({
1148
- label: 'Löschen',
1169
+ label: "Löschen",
1149
1170
  onClick,
1150
- variant: 'destructive',
1171
+ variant: "destructive",
1151
1172
  separator: true,
1152
1173
  });
1153
1174
  }
@@ -1163,21 +1184,22 @@ class ActionsColumn {
1163
1184
  build() {
1164
1185
  const { actions, label, triggerIcon } = this.config;
1165
1186
  return {
1166
- id: 'actions',
1187
+ id: "actions",
1167
1188
  header: () => jsx("span", { className: "sr-only", children: label }),
1168
1189
  cell: ({ row }) => {
1169
1190
  const data = row.original;
1170
1191
  const visibleActions = actions.filter((action) => !action.hidden || !action.hidden(data));
1171
1192
  if (visibleActions.length === 0)
1172
1193
  return null;
1173
- return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", className: "h-10 w-10 p-0", children: [jsx("span", { className: "sr-only", children: label }), triggerIcon || jsx(MoreHorizontal, { className: "h-8 w-8" })] }) }), jsx(DropdownMenuContent, { align: "end", children: visibleActions.map((action, index) => (jsxs("div", { children: [jsxs(DropdownMenuItem, { disabled: action.disabled?.(data), className: cn(action.variant === 'destructive' && 'text-destructive focus:text-destructive'), onClick: () => {
1194
+ return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", className: "h-10 w-10 p-0", children: [jsx("span", { className: "sr-only", children: label }), triggerIcon || jsx(MoreHorizontal, { className: "h-8 w-8" })] }) }), jsx(DropdownMenuContent, { align: "end", children: visibleActions.map((action, index) => (jsxs("div", { children: [jsxs(DropdownMenuItem, { disabled: action.disabled?.(data), className: cn(action.variant === "destructive" &&
1195
+ "text-destructive focus:text-destructive"), onClick: () => {
1174
1196
  if (action.href) {
1175
1197
  window.location.href = action.href(data);
1176
1198
  }
1177
1199
  else if (action.onClick) {
1178
1200
  action.onClick(data);
1179
1201
  }
1180
- }, children: [action.icon && jsx("span", { className: "mr-2", children: action.icon }), action.label] }), action.separator && index < visibleActions.length - 1 && jsx(DropdownMenuSeparator, {})] }, index))) })] }));
1202
+ }, children: [action.icon && jsx("span", { className: "mr-2", children: action.icon }), action.label] }), action.separator && index < visibleActions.length - 1 && (jsx(DropdownMenuSeparator, {}))] }, index))) })] }));
1181
1203
  },
1182
1204
  };
1183
1205
  }