@appcorp/shadcn 2.0.0 → 2.0.1
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/components/app-sidebar.js +1 -34
- package/components/audio.js +1 -13
- package/components/dashboard.js +1 -29
- package/components/drawer-generic.js +1 -39
- package/components/enhanced-checkbox.js +1 -39
- package/components/enhanced-combobox.js +1 -271
- package/components/enhanced-drawer-footer.js +1 -30
- package/components/enhanced-drawer-header.js +1 -7
- package/components/enhanced-dropzone-impl.js +1 -218
- package/components/enhanced-dropzone.js +1 -8
- package/components/enhanced-input.js +1 -40
- package/components/enhanced-label.js +1 -22
- package/components/enhanced-radio.js +1 -15
- package/components/enhanced-select.js +1 -33
- package/components/enhanced-slider.js +1 -33
- package/components/enhanced-switch.js +1 -42
- package/components/enhanced-table-footer-action.js +1 -102
- package/components/enhanced-table-footer-page.js +1 -124
- package/components/enhanced-table-footer-pagination.js +1 -108
- package/components/enhanced-table-header-action.js +1 -32
- package/components/enhanced-table-header-search.js +1 -10
- package/components/enhanced-table.js +1 -301
- package/components/enhanced-textarea.js +1 -40
- package/components/field.js +1 -96
- package/components/image-resize-dialog.js +1 -82
- package/components/nav-main.js +1 -40
- package/components/nav-projects.js +1 -39
- package/components/nav-user.js +1 -52
- package/components/show-toast.js +1 -7
- package/components/sidebar.js +1 -257
- package/components/team-switcher.js +1 -42
- package/components/theme-provider.js +1 -112
- package/components/timeline.js +1 -13
- package/components/tooltip.js +1 -36
- package/components/ui/accordion.js +1 -37
- package/components/ui/alert-dialog.js +1 -63
- package/components/ui/alert.js +1 -41
- package/components/ui/area-chart-v1-impl.js +1 -75
- package/components/ui/area-chart-v1.js +1 -5
- package/components/ui/aspect-ratio.js +1 -4
- package/components/ui/avatar.js +1 -31
- package/components/ui/badge.js +1 -32
- package/components/ui/breadcrumb.js +1 -54
- package/components/ui/button.js +1 -44
- package/components/ui/calendar-impl.js +1 -55
- package/components/ui/calendar.js +1 -6
- package/components/ui/card.js +1 -44
- package/components/ui/carousel-impl.js +1 -117
- package/components/ui/carousel.js +1 -9
- package/components/ui/chart-impl.js +6 -161
- package/components/ui/chart.js +1 -10
- package/components/ui/checkbox.js +1 -24
- package/components/ui/collapsible.js +1 -6
- package/components/ui/combobox.js +1 -52
- package/components/ui/command-impl.js +1 -63
- package/components/ui/command.js +1 -13
- package/components/ui/context-menu.js +1 -80
- package/components/ui/dialog.js +1 -57
- package/components/ui/drawer-impl.js +1 -56
- package/components/ui/drawer.js +1 -14
- package/components/ui/dropdown-menu.js +1 -82
- package/components/ui/form.d.ts +1 -1
- package/components/ui/form.js +1 -78
- package/components/ui/hover-card.js +1 -23
- package/components/ui/input-otp-impl.js +1 -43
- package/components/ui/input-otp.js +1 -8
- package/components/ui/input.js +1 -19
- package/components/ui/label.js +1 -23
- package/components/ui/language-selector.js +1 -25
- package/components/ui/menubar.js +1 -103
- package/components/ui/navigation-menu.js +1 -59
- package/components/ui/pagination.js +1 -60
- package/components/ui/popover.js +1 -25
- package/components/ui/progress.js +1 -22
- package/components/ui/radio-group.js +1 -29
- package/components/ui/resizable-impl.js +1 -27
- package/components/ui/resizable.js +1 -7
- package/components/ui/scroll-area.js +1 -32
- package/components/ui/select.js +1 -71
- package/components/ui/separator.js +1 -21
- package/components/ui/sheet.js +1 -71
- package/components/ui/skeleton.js +1 -18
- package/components/ui/slider.js +1 -32
- package/components/ui/sonner.js +1 -28
- package/components/ui/switch.js +1 -22
- package/components/ui/table.js +1 -55
- package/components/ui/tabs.js +1 -32
- package/components/ui/textarea.js +1 -19
- package/components/ui/theme-switcher.js +1 -102
- package/components/ui/toggle.js +1 -39
- package/data/admin-dashboard.js +1 -301
- package/hooks/use-enhanced-combobox.js +1 -73
- package/hooks/use-mobile.js +1 -15
- package/hooks/use-outside-click.js +1 -19
- package/lib/themes.js +1 -147
- package/lib/toast-utils.js +1 -170
- package/lib/utils.js +1 -5
- package/package.json +2 -2
- package/utils/transform-breadcrumbs.js +1 -7
- package/utils/transform-navitems.js +1 -18
|
@@ -1,124 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Enhanced Table Footer Page Component
|
|
3
|
-
*
|
|
4
|
-
* Displays pagination information with internationalization and RTL/LTR support.
|
|
5
|
-
* Automatically adapts text direction and order based on locale.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Full i18n support with fallback text
|
|
9
|
-
* - RTL/LTR layout adaptation
|
|
10
|
-
* - Loading state indicator
|
|
11
|
-
* - Accessibility attributes
|
|
12
|
-
* - Custom translation overrides
|
|
13
|
-
*/
|
|
14
|
-
import React from "react";
|
|
15
|
-
export const EnhancedTableFooterPage = ({ currentPage, isRTL = false, loading, loadingLabel = "Loading", ofLabel = "of", pageLabel = "Page", totalPages, className = "", testIdWrapper, testIdCurrent, testIdPageLabel, testIdOfLabel, testIdTotal, testIdLoadingWrapper, testIdLoadingSpinner, }) => {
|
|
16
|
-
return (React.createElement("div", { className: `flex items-center gap-2 ${isRTL ? "rtl" : "ltr"} ${className}`, dir: isRTL ? "rtl" : "ltr", role: "status", "aria-live": "polite", "aria-label": `${pageLabel} ${currentPage} ${ofLabel} ${totalPages}`, "data-testid": testIdWrapper },
|
|
17
|
-
React.createElement("span", { className: "text-sm text-muted-foreground" }, isRTL ? (
|
|
18
|
-
// RTL layout: Numbers read right-to-left but maintain logical order
|
|
19
|
-
React.createElement("span", { className: "inline-flex items-center gap-1" },
|
|
20
|
-
React.createElement("span", { "data-testid": testIdTotal }, totalPages),
|
|
21
|
-
React.createElement("span", { "data-testid": testIdOfLabel }, ofLabel),
|
|
22
|
-
React.createElement("span", { "data-testid": testIdCurrent }, currentPage),
|
|
23
|
-
React.createElement("span", { "data-testid": testIdPageLabel }, pageLabel))) : (
|
|
24
|
-
// LTR layout: "Page currentPage of totalPages"
|
|
25
|
-
React.createElement("span", { className: "inline-flex items-center gap-1" },
|
|
26
|
-
React.createElement("span", { "data-testid": testIdPageLabel }, pageLabel),
|
|
27
|
-
React.createElement("span", { "data-testid": testIdCurrent }, currentPage),
|
|
28
|
-
React.createElement("span", { "data-testid": testIdOfLabel }, ofLabel),
|
|
29
|
-
React.createElement("span", { "data-testid": testIdTotal }, totalPages)))),
|
|
30
|
-
loading && (React.createElement("div", { className: `flex items-center gap-2 ${isRTL ? "order-first" : "order-last"}`, "aria-label": loadingLabel, "data-testid": testIdLoadingWrapper },
|
|
31
|
-
React.createElement("div", { className: "w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin", role: "progressbar", "aria-label": loadingLabel, "data-testid": testIdLoadingSpinner })))));
|
|
32
|
-
};
|
|
33
|
-
// ============================================================================
|
|
34
|
-
// USAGE EXAMPLES
|
|
35
|
-
// ============================================================================
|
|
36
|
-
/*
|
|
37
|
-
Example 1: Basic usage with automatic i18n
|
|
38
|
-
<EnhancedTableFooterPage
|
|
39
|
-
currentPage={2}
|
|
40
|
-
totalPages={10}
|
|
41
|
-
loading={false}
|
|
42
|
-
/>
|
|
43
|
-
|
|
44
|
-
Example 2: With custom translations
|
|
45
|
-
<EnhancedTableFooterPage
|
|
46
|
-
currentPage={1}
|
|
47
|
-
totalPages={5}
|
|
48
|
-
loading={true}
|
|
49
|
-
translationMap={{
|
|
50
|
-
pageLabel: "صفحہ", // Urdu for "Page"
|
|
51
|
-
ofLabel: "کا", // Urdu for "of"
|
|
52
|
-
loadingLabel: "لوڈ ہو رہا ہے" // Urdu for "Loading"
|
|
53
|
-
}}
|
|
54
|
-
/>
|
|
55
|
-
|
|
56
|
-
Example 3: With custom styling
|
|
57
|
-
<EnhancedTableFooterPage
|
|
58
|
-
currentPage={3}
|
|
59
|
-
totalPages={7}
|
|
60
|
-
loading={false}
|
|
61
|
-
className="bg-gray-50 p-2 rounded-md"
|
|
62
|
-
/>
|
|
63
|
-
|
|
64
|
-
Translation Keys (Already Added to messages files):
|
|
65
|
-
English (en.json):
|
|
66
|
-
{
|
|
67
|
-
"common": {
|
|
68
|
-
"page": "Page",
|
|
69
|
-
"of": "of",
|
|
70
|
-
"loading": "Loading"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
Urdu (ur.json):
|
|
75
|
-
{
|
|
76
|
-
"common": {
|
|
77
|
-
"page": "صفحہ",
|
|
78
|
-
"of": "کا",
|
|
79
|
-
"loading": "لوڈ ہو رہا ہے"
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
RTL Layout Features:
|
|
84
|
-
- Automatic text direction detection and application
|
|
85
|
-
- Proper order of page information in RTL languages
|
|
86
|
-
- RTL-aware loading indicator positioning
|
|
87
|
-
- Accessibility attributes for screen readers
|
|
88
|
-
- Direction-specific CSS classes and DOM attributes
|
|
89
|
-
*/
|
|
90
|
-
// ============================================================================
|
|
91
|
-
// COMPONENT ENHANCEMENTS SUMMARY
|
|
92
|
-
// ============================================================================
|
|
93
|
-
/*
|
|
94
|
-
Enhancements Applied:
|
|
95
|
-
|
|
96
|
-
1. **Internationalization (i18n)**
|
|
97
|
-
- Full translation support using next-intl
|
|
98
|
-
- Fallback text for missing translations
|
|
99
|
-
- Custom translation override capability
|
|
100
|
-
|
|
101
|
-
2. **RTL/LTR Layout Support**
|
|
102
|
-
- Automatic layout detection using useRTL hook
|
|
103
|
-
- Proper text ordering for RTL languages
|
|
104
|
-
- Direction-aware CSS classes and attributes
|
|
105
|
-
- RTL-appropriate visual element positioning
|
|
106
|
-
|
|
107
|
-
3. **Accessibility Improvements**
|
|
108
|
-
- ARIA labels for screen readers
|
|
109
|
-
- Role attributes for semantic meaning
|
|
110
|
-
- Live region announcements for dynamic content
|
|
111
|
-
- Proper labeling of interactive elements
|
|
112
|
-
|
|
113
|
-
4. **Developer Experience**
|
|
114
|
-
- Comprehensive JSDoc documentation
|
|
115
|
-
- Usage examples and patterns
|
|
116
|
-
- TypeScript interface improvements
|
|
117
|
-
- Flexible customization options
|
|
118
|
-
|
|
119
|
-
5. **Code Quality**
|
|
120
|
-
- Clean, readable component structure
|
|
121
|
-
- Consistent naming conventions
|
|
122
|
-
- Performance-optimized rendering
|
|
123
|
-
- Maintainable and extensible design
|
|
124
|
-
*/
|
|
1
|
+
"use strict";import e from"react";export const EnhancedTableFooterPage=({currentPage:a,isRTL:t=!1,loading:p,loadingLabel:l="Loading",ofLabel:r="of",pageLabel:n="Page",totalPages:s,className:E="",testIdWrapper:o,testIdCurrent:d,testIdPageLabel:i,testIdOfLabel:m,testIdTotal:c,testIdLoadingWrapper:f,testIdLoadingSpinner:x})=>e.createElement("div",{className:`flex items-center gap-2 ${t?"rtl":"ltr"} ${E}`,dir:t?"rtl":"ltr",role:"status","aria-live":"polite","aria-label":`${n} ${a} ${r} ${s}`,"data-testid":o},e.createElement("span",{className:"text-sm text-muted-foreground"},t?e.createElement("span",{className:"inline-flex items-center gap-1"},e.createElement("span",{"data-testid":c},s),e.createElement("span",{"data-testid":m},r),e.createElement("span",{"data-testid":d},a),e.createElement("span",{"data-testid":i},n)):e.createElement("span",{className:"inline-flex items-center gap-1"},e.createElement("span",{"data-testid":i},n),e.createElement("span",{"data-testid":d},a),e.createElement("span",{"data-testid":m},r),e.createElement("span",{"data-testid":c},s))),p&&e.createElement("div",{className:`flex items-center gap-2 ${t?"order-first":"order-last"}`,"aria-label":l,"data-testid":f},e.createElement("div",{className:"w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin",role:"progressbar","aria-label":l,"data-testid":x})));
|
|
@@ -1,108 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Enhanced Table Footer Pagination Component
|
|
3
|
-
*
|
|
4
|
-
* Displays rows per page selector with internationalization and RTL/LTR support.
|
|
5
|
-
* Automatically adapts text direction and layout based on locale.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Full i18n support with fallback text
|
|
9
|
-
* - RTL/LTR layout adaptation
|
|
10
|
-
* - Loading state handling
|
|
11
|
-
* - Accessibility attributes
|
|
12
|
-
* - Custom translation overrides
|
|
13
|
-
* - Responsive design
|
|
14
|
-
*/
|
|
15
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "./ui/select";
|
|
16
|
-
import React from "react";
|
|
17
|
-
export const EnhancedTableFooterPagination = ({ handleOnSelect, isRTL = false, listOptions, loading, nodeSelectKey, pageLimit, rowsPerPageLabel = "Rows per page:", className = "", testIdWrapper, testIdLabel, testIdSelectTrigger, testIdSelectValue, testIdSelectContent, testIdOptionPrefix, }) => {
|
|
18
|
-
return (React.createElement("div", { className: `flex items-center gap-2 ${className}`, dir: isRTL ? "rtl" : "ltr", "data-testid": testIdWrapper },
|
|
19
|
-
React.createElement("label", { htmlFor: `page-limit-select-${nodeSelectKey}`, className: "text-sm text-muted-foreground whitespace-nowrap", "data-testid": testIdLabel }, rowsPerPageLabel),
|
|
20
|
-
React.createElement(Select, { value: String(pageLimit), onValueChange: (value) => handleOnSelect(nodeSelectKey, { option: value }), disabled: loading },
|
|
21
|
-
React.createElement(SelectTrigger, { id: `page-limit-select-${nodeSelectKey}`, className: "w-20", "aria-label": `${rowsPerPageLabel} ${pageLimit}`, "data-testid": testIdSelectTrigger },
|
|
22
|
-
React.createElement(SelectValue, { "data-testid": testIdSelectValue })),
|
|
23
|
-
React.createElement(SelectContent, { "data-testid": testIdSelectContent }, listOptions.map((option) => (React.createElement(SelectItem, { key: option.option, value: option.option, "aria-label": `${option.option} rows per page`, "data-testid": testIdOptionPrefix
|
|
24
|
-
? `${testIdOptionPrefix}-${option.option}`
|
|
25
|
-
: undefined }, option.option)))))));
|
|
26
|
-
};
|
|
27
|
-
// ============================================================================
|
|
28
|
-
// USAGE EXAMPLES
|
|
29
|
-
// ============================================================================
|
|
30
|
-
/*
|
|
31
|
-
Example 1: Basic usage with automatic i18n
|
|
32
|
-
<EnhancedTableFooterPagination
|
|
33
|
-
handleOnSelect={(key, value) => console.log(key, value)}
|
|
34
|
-
listOptions={[{ option: "10" }, { option: "25" }, { option: "50" }]}
|
|
35
|
-
loading={false}
|
|
36
|
-
nodeSelectKey="pageLimit"
|
|
37
|
-
pageLimit={10}
|
|
38
|
-
totalPages={5}
|
|
39
|
-
/>
|
|
40
|
-
|
|
41
|
-
Example 2: With custom label text
|
|
42
|
-
<EnhancedTableFooterPagination
|
|
43
|
-
handleOnSelect={handlePageLimitChange}
|
|
44
|
-
listOptions={pageLimitOptions}
|
|
45
|
-
loading={isLoading}
|
|
46
|
-
nodeSelectKey="pageLimit"
|
|
47
|
-
pageLimit={currentPageLimit}
|
|
48
|
-
totalPages={totalPages}
|
|
49
|
-
labelText="Items per page:"
|
|
50
|
-
/>
|
|
51
|
-
|
|
52
|
-
Example 3: With custom styling and RTL support
|
|
53
|
-
<EnhancedTableFooterPagination
|
|
54
|
-
handleOnSelect={handlePageLimitChange}
|
|
55
|
-
listOptions={pageLimitOptions}
|
|
56
|
-
loading={false}
|
|
57
|
-
nodeSelectKey="pageLimit"
|
|
58
|
-
pageLimit={25}
|
|
59
|
-
totalPages={10}
|
|
60
|
-
className="bg-gray-50 p-2 rounded-md"
|
|
61
|
-
/>
|
|
62
|
-
|
|
63
|
-
RTL Layout Features:
|
|
64
|
-
- Automatic text direction detection and application
|
|
65
|
-
- Element order reversal for RTL languages
|
|
66
|
-
- Proper label-select association
|
|
67
|
-
- Accessibility attributes for screen readers
|
|
68
|
-
- Direction-specific CSS classes and DOM attributes
|
|
69
|
-
*/
|
|
70
|
-
// ============================================================================
|
|
71
|
-
// COMPONENT ENHANCEMENTS SUMMARY
|
|
72
|
-
// ============================================================================
|
|
73
|
-
/*
|
|
74
|
-
Enhancements Applied:
|
|
75
|
-
|
|
76
|
-
1. **Internationalization (i18n)**
|
|
77
|
-
- Translation support using next-intl
|
|
78
|
-
- Fallback text for missing translations
|
|
79
|
-
- Custom label text override capability
|
|
80
|
-
- Translatable "Rows per page:" label
|
|
81
|
-
|
|
82
|
-
2. **RTL/LTR Layout Support**
|
|
83
|
-
- Automatic layout detection using useRTL hook
|
|
84
|
-
- Element order reversal for RTL languages (flex-row-reverse)
|
|
85
|
-
- Direction-aware CSS classes and attributes
|
|
86
|
-
- Proper text direction handling
|
|
87
|
-
|
|
88
|
-
3. **Accessibility Improvements**
|
|
89
|
-
- Proper label-select association with htmlFor/id
|
|
90
|
-
- ARIA labels for screen readers
|
|
91
|
-
- Descriptive aria-label for select options
|
|
92
|
-
- Semantic HTML structure with label element
|
|
93
|
-
|
|
94
|
-
4. **Developer Experience**
|
|
95
|
-
- Comprehensive JSDoc documentation
|
|
96
|
-
- Usage examples and patterns
|
|
97
|
-
- TypeScript interface improvements
|
|
98
|
-
- Flexible customization options
|
|
99
|
-
|
|
100
|
-
5. **Code Quality**
|
|
101
|
-
- Clean, readable component structure
|
|
102
|
-
- Consistent naming conventions
|
|
103
|
-
- Performance-optimized rendering
|
|
104
|
-
- Maintainable and extensible design
|
|
105
|
-
|
|
106
|
-
Translation Key Required:
|
|
107
|
-
- common.rowsPerPage: "Rows per page:" / "ہر صفحے میں قطاریں:"
|
|
108
|
-
*/
|
|
1
|
+
"use strict";import{Select as $,SelectContent as f,SelectItem as b,SelectTrigger as h,SelectValue as w}from"./ui/select";import t from"react";export const EnhancedTableFooterPagination=({handleOnSelect:n,isRTL:m=!1,listOptions:c,loading:s,nodeSelectKey:a,pageLimit:l,rowsPerPageLabel:r="Rows per page:",className:d="",testIdWrapper:o,testIdLabel:p,testIdSelectTrigger:g,testIdSelectValue:u,testIdSelectContent:E,testIdOptionPrefix:i})=>t.createElement("div",{className:`flex items-center gap-2 ${d}`,dir:m?"rtl":"ltr","data-testid":o},t.createElement("label",{htmlFor:`page-limit-select-${a}`,className:"text-sm text-muted-foreground whitespace-nowrap","data-testid":p},r),t.createElement($,{value:String(l),onValueChange:e=>n(a,{option:e}),disabled:s},t.createElement(h,{id:`page-limit-select-${a}`,className:"w-20","aria-label":`${r} ${l}`,"data-testid":g},t.createElement(w,{"data-testid":u})),t.createElement(f,{"data-testid":E},c.map(e=>t.createElement(b,{key:e.option,value:e.option,"aria-label":`${e.option} rows per page`,"data-testid":i?`${i}-${e.option}`:void 0},e.option)))));
|
|
@@ -1,32 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { X } from "lucide-react";
|
|
3
|
-
import { Badge } from "./ui/badge";
|
|
4
|
-
import { Button } from "./ui/button";
|
|
5
|
-
import { cn } from "../lib/utils";
|
|
6
|
-
export const EnhancedTableHeaderAction = ({ headerActions, numberOfFilters, onClearFilters, testIdWrapper, testIdActionPrefix, testIdFilterBadge, testIdClearFilters, }) => {
|
|
7
|
-
return (React.createElement(React.Fragment, null, headerActions.length > 0 && (React.createElement("div", { className: "flex gap-2", "data-testid": testIdWrapper }, headerActions
|
|
8
|
-
.filter((action) => action.enabled !== false)
|
|
9
|
-
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
10
|
-
.map((action, index) => {
|
|
11
|
-
const isFilterButton = action.label
|
|
12
|
-
.toLowerCase()
|
|
13
|
-
.includes("filter");
|
|
14
|
-
const showFilterIndicators = isFilterButton &&
|
|
15
|
-
typeof numberOfFilters === "number" &&
|
|
16
|
-
numberOfFilters > 0;
|
|
17
|
-
return (React.createElement("div", { key: action.id || action.key || index, className: "relative" },
|
|
18
|
-
React.createElement(Button, { variant: action.variant || "default", "data-testid": testIdActionPrefix
|
|
19
|
-
? `${testIdActionPrefix}-${index}`
|
|
20
|
-
: undefined, onClick: () => { var _a; return (_a = action.handleOnClick) === null || _a === void 0 ? void 0 : _a.call(action, undefined); } }, action.label),
|
|
21
|
-
showFilterIndicators && (React.createElement(React.Fragment, null,
|
|
22
|
-
React.createElement("div", { className: "absolute -top-2 -left-2 group" },
|
|
23
|
-
React.createElement(Badge, { variant: "secondary", className: cn("h-5 w-5 flex items-center justify-center p-0 text-xs rounded-full transition-all relative", onClearFilters && "cursor-pointer"), "data-testid": testIdFilterBadge, onClick: onClearFilters
|
|
24
|
-
? (e) => {
|
|
25
|
-
e.stopPropagation();
|
|
26
|
-
onClearFilters();
|
|
27
|
-
}
|
|
28
|
-
: undefined },
|
|
29
|
-
React.createElement("span", { className: cn("transition-opacity absolute", onClearFilters && "group-hover:opacity-0") }, numberOfFilters),
|
|
30
|
-
onClearFilters && (React.createElement(X, { className: "h-3 w-3 absolute opacity-0 group-hover:opacity-100 transition-opacity", "data-testid": testIdClearFilters }))))))));
|
|
31
|
-
})))));
|
|
32
|
-
};
|
|
1
|
+
"use strict";import t from"react";import{X as u}from"lucide-react";import{Badge as f}from"./ui/badge";import{Button as v}from"./ui/button";import{cn as s}from"../lib/utils";export const EnhancedTableHeaderAction=({headerActions:o,numberOfFilters:n,onClearFilters:a,testIdWrapper:d,testIdActionPrefix:i,testIdFilterBadge:c,testIdClearFilters:m})=>t.createElement(t.Fragment,null,o.length>0&&t.createElement("div",{className:"flex gap-2","data-testid":d},o.filter(e=>e.enabled!==!1).sort((e,l)=>(e.order||0)-(l.order||0)).map((e,l)=>{const p=e.label.toLowerCase().includes("filter")&&typeof n=="number"&&n>0;return t.createElement("div",{key:e.id||e.key||l,className:"relative"},t.createElement(v,{variant:e.variant||"default","data-testid":i?`${i}-${l}`:void 0,onClick:()=>{var r;return(r=e.handleOnClick)===null||r===void 0?void 0:r.call(e,void 0)}},e.label),p&&t.createElement(t.Fragment,null,t.createElement("div",{className:"absolute -top-2 -left-2 group"},t.createElement(f,{variant:"secondary",className:s("h-5 w-5 flex items-center justify-center p-0 text-xs rounded-full transition-all relative",a&&"cursor-pointer"),"data-testid":c,onClick:a?r=>{r.stopPropagation(),a()}:void 0},t.createElement("span",{className:s("transition-opacity absolute",a&&"group-hover:opacity-0")},n),a&&t.createElement(u,{className:"h-3 w-3 absolute opacity-0 group-hover:opacity-100 transition-opacity","data-testid":m})))))})));
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Search } from "lucide-react";
|
|
3
|
-
import { Input } from "./ui/input";
|
|
4
|
-
export const EnhancedTableHeaderSearch = ({ handleSearchInput, loading, searchDisabled = false, searchEnabled = true, searchId = "table-search", searchPlaceholder = "Search...", searchValue, testIdWrapper, testIdInput, testIdIcon, testIdLoading, }) => {
|
|
5
|
-
return (React.createElement(React.Fragment, null, searchEnabled && (React.createElement("div", { className: "flex items-center gap-2 max-w-xl", "data-testid": testIdWrapper },
|
|
6
|
-
React.createElement("div", { className: "relative flex-1" },
|
|
7
|
-
React.createElement(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground", "data-testid": testIdIcon }),
|
|
8
|
-
React.createElement(Input, { id: searchId, placeholder: searchPlaceholder, value: searchValue, onChange: (e) => handleSearchInput("search", e.target.value), disabled: searchDisabled || loading, className: "pl-9", "data-testid": testIdInput }),
|
|
9
|
-
loading && testIdLoading && (React.createElement("span", { className: "sr-only", "data-testid": testIdLoading })))))));
|
|
10
|
-
};
|
|
1
|
+
"use strict";import e from"react";import{Search as f}from"lucide-react";import{Input as h}from"./ui/input";export const EnhancedTableHeaderSearch=({handleSearchInput:r,loading:a,searchDisabled:l=!1,searchEnabled:s=!0,searchId:m="table-search",searchPlaceholder:c="Search...",searchValue:n,testIdWrapper:d,testIdInput:o,testIdIcon:i,testIdLoading:t})=>e.createElement(e.Fragment,null,s&&e.createElement("div",{className:"flex items-center gap-2 max-w-xl","data-testid":d},e.createElement("div",{className:"relative flex-1"},e.createElement(f,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground","data-testid":i}),e.createElement(h,{id:m,placeholder:c,value:n,onChange:p=>r("search",p.target.value),disabled:l||a,className:"pl-9","data-testid":o}),a&&t&&e.createElement("span",{className:"sr-only","data-testid":t}))));
|
|
@@ -1,301 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { MoreHorizontal } from "lucide-react";
|
|
4
|
-
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "./ui/table";
|
|
5
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "./ui/dropdown-menu";
|
|
6
|
-
import { cn } from "../lib/utils";
|
|
7
|
-
import { EnhancedTableFooterAction } from "./enhanced-table-footer-action";
|
|
8
|
-
import { EnhancedTableFooterPage } from "./enhanced-table-footer-page";
|
|
9
|
-
import { EnhancedTableFooterPagination } from "./enhanced-table-footer-pagination";
|
|
10
|
-
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
|
|
11
|
-
import { EnhancedTableHeaderAction } from "./enhanced-table-header-action";
|
|
12
|
-
import { EnhancedTableHeaderSearch } from "./enhanced-table-header-search";
|
|
13
|
-
import { Badge } from "./ui/badge";
|
|
14
|
-
// Centralized component type values for table cell rendering
|
|
15
|
-
export var COMPONENT_TYPE;
|
|
16
|
-
(function (COMPONENT_TYPE) {
|
|
17
|
-
COMPONENT_TYPE["ID"] = "ID";
|
|
18
|
-
COMPONENT_TYPE["BOLD_TEXT"] = "BOLD_TEXT";
|
|
19
|
-
COMPONENT_TYPE["TEXT"] = "TEXT";
|
|
20
|
-
COMPONENT_TYPE["OBJECT"] = "OBJECT";
|
|
21
|
-
COMPONENT_TYPE["MULTIPLE_TEXT_LINES"] = "MULTIPLE_TEXT_LINES";
|
|
22
|
-
COMPONENT_TYPE["CREATED_UPDATED_AT"] = "CREATED_UPDATED_AT";
|
|
23
|
-
COMPONENT_TYPE["ACTIONS"] = "ACTIONS";
|
|
24
|
-
COMPONENT_TYPE["BOOLEAN"] = "BOOLEAN";
|
|
25
|
-
})(COMPONENT_TYPE || (COMPONENT_TYPE = {}));
|
|
26
|
-
export const EnhancedTable = ({ currentPage, handleNextOnClick, handleOnSelect, handlePreviousOnClick, handleSearchInput, headerActions, isNextDisabled, isPreviousDisabled, isRTL = false, listOptions, loading, nodeSelectKey = "pageLimit", numberOfFilters, onClearFilters, pageLimit, rowActions, searchDisabled = false, searchEnabled = true, searchId = "table-search", searchPlaceholder = "Search...", searchValue, tableBodyCols, tableBodyRows, tableDescription, tableHeading, tableHeadItems, totalPages, translationLabels = {}, testIdWrapper, testIdHeading, testIdTableDescription, testIdSearch, testIdHeaderActions, testIdHeaderActionPrefix, testIdHeaderActionFilterBadge, testIdHeaderActionClearFilters, testIdTableWrapper, testIdRowPrefix, testIdCellPrefix, testIdRowActionPrefix, testIdNoResults, testIdLoadingRowPrefix, testIdPaginationWrapper, testIdFooterPagination, testIdFooterPage, testIdFooterAction, testIdWrapperRtl, testIdHeadingRtl, testIdTableDescriptionRtl, testIdSearchRtl, testIdHeaderActionsRtl, testIdHeaderActionPrefixRtl, testIdHeaderActionFilterBadgeRtl, testIdHeaderActionClearFiltersRtl, testIdTableWrapperRtl, testIdRowPrefixRtl, testIdCellPrefixRtl, testIdRowActionPrefixRtl, testIdNoResultsRtl, testIdLoadingRowPrefixRtl, testIdPaginationWrapperRtl, testIdFooterPaginationRtl, testIdFooterPageRtl, testIdFooterActionRtl, }) => {
|
|
27
|
-
// Default translation values
|
|
28
|
-
const defaultLabels = {
|
|
29
|
-
booleanYes: "Yes",
|
|
30
|
-
booleanNo: "No",
|
|
31
|
-
noResultsFound: "No results found.",
|
|
32
|
-
previousPage: "Previous page",
|
|
33
|
-
nextPage: "Next page",
|
|
34
|
-
page: "Page",
|
|
35
|
-
of: "of",
|
|
36
|
-
loading: "Loading",
|
|
37
|
-
rowsPerPage: "Rows per page:",
|
|
38
|
-
};
|
|
39
|
-
// Merge provided labels with defaults
|
|
40
|
-
const labels = Object.assign(Object.assign({}, defaultLabels), translationLabels);
|
|
41
|
-
// Resolve which test ids to use depending on `isRTL` mode.
|
|
42
|
-
const _testIdWrapper = isRTL
|
|
43
|
-
? (testIdWrapperRtl !== null && testIdWrapperRtl !== void 0 ? testIdWrapperRtl : testIdWrapper)
|
|
44
|
-
: testIdWrapper;
|
|
45
|
-
const _testIdHeading = isRTL
|
|
46
|
-
? (testIdHeadingRtl !== null && testIdHeadingRtl !== void 0 ? testIdHeadingRtl : testIdHeading)
|
|
47
|
-
: testIdHeading;
|
|
48
|
-
const _testIdTableDescription = isRTL
|
|
49
|
-
? (testIdTableDescriptionRtl !== null && testIdTableDescriptionRtl !== void 0 ? testIdTableDescriptionRtl : testIdTableDescription)
|
|
50
|
-
: testIdTableDescription;
|
|
51
|
-
const _testIdSearch = isRTL
|
|
52
|
-
? (testIdSearchRtl !== null && testIdSearchRtl !== void 0 ? testIdSearchRtl : testIdSearch)
|
|
53
|
-
: testIdSearch;
|
|
54
|
-
const _testIdHeaderActions = isRTL
|
|
55
|
-
? (testIdHeaderActionsRtl !== null && testIdHeaderActionsRtl !== void 0 ? testIdHeaderActionsRtl : testIdHeaderActions)
|
|
56
|
-
: testIdHeaderActions;
|
|
57
|
-
const _testIdHeaderActionPrefix = isRTL
|
|
58
|
-
? (testIdHeaderActionPrefixRtl !== null && testIdHeaderActionPrefixRtl !== void 0 ? testIdHeaderActionPrefixRtl : testIdHeaderActionPrefix)
|
|
59
|
-
: testIdHeaderActionPrefix;
|
|
60
|
-
const _testIdHeaderActionFilterBadge = isRTL
|
|
61
|
-
? (testIdHeaderActionFilterBadgeRtl !== null && testIdHeaderActionFilterBadgeRtl !== void 0 ? testIdHeaderActionFilterBadgeRtl : testIdHeaderActionFilterBadge)
|
|
62
|
-
: testIdHeaderActionFilterBadge;
|
|
63
|
-
const _testIdHeaderActionClearFilters = isRTL
|
|
64
|
-
? (testIdHeaderActionClearFiltersRtl !== null && testIdHeaderActionClearFiltersRtl !== void 0 ? testIdHeaderActionClearFiltersRtl : testIdHeaderActionClearFilters)
|
|
65
|
-
: testIdHeaderActionClearFilters;
|
|
66
|
-
const _testIdTableWrapper = isRTL
|
|
67
|
-
? (testIdTableWrapperRtl !== null && testIdTableWrapperRtl !== void 0 ? testIdTableWrapperRtl : testIdTableWrapper)
|
|
68
|
-
: testIdTableWrapper;
|
|
69
|
-
const _testIdRowPrefix = isRTL
|
|
70
|
-
? (testIdRowPrefixRtl !== null && testIdRowPrefixRtl !== void 0 ? testIdRowPrefixRtl : testIdRowPrefix)
|
|
71
|
-
: testIdRowPrefix;
|
|
72
|
-
const _testIdCellPrefix = isRTL
|
|
73
|
-
? (testIdCellPrefixRtl !== null && testIdCellPrefixRtl !== void 0 ? testIdCellPrefixRtl : testIdCellPrefix)
|
|
74
|
-
: testIdCellPrefix;
|
|
75
|
-
const _testIdRowActionPrefix = isRTL
|
|
76
|
-
? (testIdRowActionPrefixRtl !== null && testIdRowActionPrefixRtl !== void 0 ? testIdRowActionPrefixRtl : testIdRowActionPrefix)
|
|
77
|
-
: testIdRowActionPrefix;
|
|
78
|
-
const _testIdNoResults = isRTL
|
|
79
|
-
? (testIdNoResultsRtl !== null && testIdNoResultsRtl !== void 0 ? testIdNoResultsRtl : testIdNoResults)
|
|
80
|
-
: testIdNoResults;
|
|
81
|
-
const _testIdLoadingRowPrefix = isRTL
|
|
82
|
-
? (testIdLoadingRowPrefixRtl !== null && testIdLoadingRowPrefixRtl !== void 0 ? testIdLoadingRowPrefixRtl : testIdLoadingRowPrefix)
|
|
83
|
-
: testIdLoadingRowPrefix;
|
|
84
|
-
const _testIdPaginationWrapper = isRTL
|
|
85
|
-
? (testIdPaginationWrapperRtl !== null && testIdPaginationWrapperRtl !== void 0 ? testIdPaginationWrapperRtl : testIdPaginationWrapper)
|
|
86
|
-
: testIdPaginationWrapper;
|
|
87
|
-
const _testIdFooterPagination = isRTL
|
|
88
|
-
? (testIdFooterPaginationRtl !== null && testIdFooterPaginationRtl !== void 0 ? testIdFooterPaginationRtl : testIdFooterPagination)
|
|
89
|
-
: testIdFooterPagination;
|
|
90
|
-
const _testIdFooterPage = isRTL
|
|
91
|
-
? (testIdFooterPageRtl !== null && testIdFooterPageRtl !== void 0 ? testIdFooterPageRtl : testIdFooterPage)
|
|
92
|
-
: testIdFooterPage;
|
|
93
|
-
const _testIdFooterAction = isRTL
|
|
94
|
-
? (testIdFooterActionRtl !== null && testIdFooterActionRtl !== void 0 ? testIdFooterActionRtl : testIdFooterAction)
|
|
95
|
-
: testIdFooterAction;
|
|
96
|
-
const renderCellContent = (row, col, rowIndex) => {
|
|
97
|
-
var _a, _b;
|
|
98
|
-
// Helper to safely resolve nested keys (max depth 3)
|
|
99
|
-
const resolveValue = (source, key) => {
|
|
100
|
-
if (!key)
|
|
101
|
-
return source;
|
|
102
|
-
if (typeof key === "string") {
|
|
103
|
-
// Handle colon-separated nested keys
|
|
104
|
-
if (key.includes(":")) {
|
|
105
|
-
const keys = key.split(":");
|
|
106
|
-
let cur = source;
|
|
107
|
-
for (const k of keys) {
|
|
108
|
-
if (cur == null || typeof cur !== "object")
|
|
109
|
-
return undefined;
|
|
110
|
-
cur = cur[k];
|
|
111
|
-
}
|
|
112
|
-
return cur;
|
|
113
|
-
}
|
|
114
|
-
// Simple key access
|
|
115
|
-
if (source && typeof source === "object")
|
|
116
|
-
return source[key];
|
|
117
|
-
return undefined;
|
|
118
|
-
}
|
|
119
|
-
// array of keys - try each until we find a defined value
|
|
120
|
-
for (const k of key) {
|
|
121
|
-
const val = resolveValue(source, k);
|
|
122
|
-
if (val != null)
|
|
123
|
-
return val;
|
|
124
|
-
}
|
|
125
|
-
return undefined;
|
|
126
|
-
};
|
|
127
|
-
const getProp = (obj, prop) => {
|
|
128
|
-
if (obj &&
|
|
129
|
-
typeof obj === "object" &&
|
|
130
|
-
prop in obj)
|
|
131
|
-
return obj[prop];
|
|
132
|
-
return undefined;
|
|
133
|
-
};
|
|
134
|
-
// Resolve value (supports nested key arrays)
|
|
135
|
-
const value = resolveValue(row, col.key);
|
|
136
|
-
// Normalize componentType so external string enums (like VISTA_TABLE_CELL_TYPE)
|
|
137
|
-
// remain compatible with this table. Unknown/unsupported types fall back to TEXT.
|
|
138
|
-
const normalizeComponentType = (c) => {
|
|
139
|
-
var _a;
|
|
140
|
-
if (!c)
|
|
141
|
-
return undefined;
|
|
142
|
-
if (Object.values(COMPONENT_TYPE).includes(c))
|
|
143
|
-
return c;
|
|
144
|
-
// Map common external values to our ComponentType using object notation
|
|
145
|
-
const MAP = {
|
|
146
|
-
ID: COMPONENT_TYPE.ID,
|
|
147
|
-
BOLD_TEXT: COMPONENT_TYPE.BOLD_TEXT,
|
|
148
|
-
BOOLEAN: COMPONENT_TYPE.BOOLEAN,
|
|
149
|
-
ACTIONS: COMPONENT_TYPE.ACTIONS,
|
|
150
|
-
TEXT: COMPONENT_TYPE.TEXT,
|
|
151
|
-
OBJECT: COMPONENT_TYPE.OBJECT,
|
|
152
|
-
MULTIPLE_TEXT_LINES: COMPONENT_TYPE.MULTIPLE_TEXT_LINES,
|
|
153
|
-
CREATED_UPDATED_AT: COMPONENT_TYPE.CREATED_UPDATED_AT,
|
|
154
|
-
};
|
|
155
|
-
return (_a = MAP[String(c)]) !== null && _a !== void 0 ? _a : COMPONENT_TYPE.TEXT;
|
|
156
|
-
};
|
|
157
|
-
const normalizedType = normalizeComponentType(col.componentType);
|
|
158
|
-
if (normalizedType === COMPONENT_TYPE.ACTIONS) {
|
|
159
|
-
return (React.createElement(DropdownMenu, null,
|
|
160
|
-
React.createElement(DropdownMenuTrigger, { asChild: true },
|
|
161
|
-
React.createElement(MoreHorizontal, { className: "h-4 w-4" })),
|
|
162
|
-
React.createElement(DropdownMenuContent, { align: "end" }, rowActions
|
|
163
|
-
.filter(({ enabled }) => typeof enabled === "function" ? enabled(row) : enabled)
|
|
164
|
-
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
165
|
-
.map((action, index) => (React.createElement(DropdownMenuItem, { key: action.id || action.key || index, "data-testid": _testIdRowActionPrefix
|
|
166
|
-
? `${_testIdRowActionPrefix}-${rowIndex}-${index}`
|
|
167
|
-
: undefined, className: cn(action.variant === "destructive" &&
|
|
168
|
-
"text-destructive focus:text-destructive"), onClick: () => { var _a; return (_a = action.handleOnClick) === null || _a === void 0 ? void 0 : _a.call(action, row); } }, action.label))))));
|
|
169
|
-
}
|
|
170
|
-
if (normalizedType === COMPONENT_TYPE.ID) {
|
|
171
|
-
return (React.createElement(Popover, null,
|
|
172
|
-
React.createElement(PopoverTrigger, { asChild: true },
|
|
173
|
-
React.createElement("span", { className: "text-xs text-muted-foreground font-mono" }, typeof value === "string"
|
|
174
|
-
? `${value.substring(0, 8)}...`
|
|
175
|
-
: String(value || ""))),
|
|
176
|
-
React.createElement(PopoverContent, null,
|
|
177
|
-
React.createElement("span", { className: "text-xs text-muted-foreground font-mono" }, col.textFormatter
|
|
178
|
-
? col.textFormatter(value, row)
|
|
179
|
-
: String(value)))));
|
|
180
|
-
}
|
|
181
|
-
if (normalizedType === COMPONENT_TYPE.BOLD_TEXT) {
|
|
182
|
-
const formatted = col.textFormatter
|
|
183
|
-
? col.textFormatter(value, row)
|
|
184
|
-
: String(value || "");
|
|
185
|
-
return React.createElement("span", { className: "font-semibold" }, formatted);
|
|
186
|
-
}
|
|
187
|
-
if (normalizedType === COMPONENT_TYPE.BOOLEAN) {
|
|
188
|
-
const isTrue = Boolean(value);
|
|
189
|
-
return (React.createElement(Badge, { variant: "secondary", className: cn("text-white font-medium", isTrue
|
|
190
|
-
? "bg-green-500 hover:bg-green-600"
|
|
191
|
-
: "bg-red-500 hover:bg-red-600") }, isTrue ? labels.booleanYes : labels.booleanNo));
|
|
192
|
-
}
|
|
193
|
-
// OBJECT => nested property path supplied as array of colon-separated strings
|
|
194
|
-
// e.g., ["user:company", "profile:department"] with fallback support
|
|
195
|
-
// If first path is undefined, try the next one. If all undefined, render '-'
|
|
196
|
-
if (normalizedType === COMPONENT_TYPE.OBJECT) {
|
|
197
|
-
let nested;
|
|
198
|
-
// Key must be an array of colon-separated strings
|
|
199
|
-
if (Array.isArray(col.key)) {
|
|
200
|
-
// Try each key path until we find a defined value
|
|
201
|
-
for (const keyPath of col.key) {
|
|
202
|
-
if (typeof keyPath === "string" && keyPath.includes(":")) {
|
|
203
|
-
const keys = keyPath.split(":");
|
|
204
|
-
let cur = row;
|
|
205
|
-
let found = true;
|
|
206
|
-
for (const k of keys) {
|
|
207
|
-
if (cur == null || typeof cur !== "object") {
|
|
208
|
-
found = false;
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
cur = cur[k];
|
|
212
|
-
}
|
|
213
|
-
if (found && cur != null) {
|
|
214
|
-
nested = cur;
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
// If all paths are undefined, render '-'
|
|
221
|
-
if (nested == null)
|
|
222
|
-
return React.createElement("span", null, "-");
|
|
223
|
-
// If nested is an object, try to find a primitive value
|
|
224
|
-
if (typeof nested === "object") {
|
|
225
|
-
const primitive = Object.values(nested).find((v) => ["string", "number", "boolean"].includes(typeof v));
|
|
226
|
-
const toRender = primitive !== null && primitive !== void 0 ? primitive : JSON.stringify(nested);
|
|
227
|
-
return (React.createElement("span", null, col.textFormatter
|
|
228
|
-
? col.textFormatter(toRender, row)
|
|
229
|
-
: String(toRender)));
|
|
230
|
-
}
|
|
231
|
-
// Nested is a primitive value
|
|
232
|
-
return (React.createElement("span", null, col.textFormatter ? col.textFormatter(nested, row) : String(nested)));
|
|
233
|
-
} // MULTIPLE_TEXT_LINES => col.key is an array of keys, render up to 3 lines
|
|
234
|
-
if (normalizedType === COMPONENT_TYPE.MULTIPLE_TEXT_LINES) {
|
|
235
|
-
const keys = Array.isArray(col.key) ? col.key : [];
|
|
236
|
-
const lines = keys.slice(0, 3).map((k) => {
|
|
237
|
-
const v = resolveValue(row, k);
|
|
238
|
-
return v == null ? "" : String(v);
|
|
239
|
-
});
|
|
240
|
-
return (React.createElement("div", { className: "flex flex-col" }, lines.map((line, idx) => (React.createElement("span", { key: idx, className: "text-sm" }, col.textFormatter ? col.textFormatter(line, row) : line)))));
|
|
241
|
-
}
|
|
242
|
-
// CREATED_UPDATED_AT => show createdAt and updatedAt from the object (or nested object)
|
|
243
|
-
if (normalizedType === COMPONENT_TYPE.CREATED_UPDATED_AT) {
|
|
244
|
-
const target = resolveValue(row, col.key);
|
|
245
|
-
const created = (_a = getProp(target, "createdAt")) !== null && _a !== void 0 ? _a : getProp(row, "createdAt");
|
|
246
|
-
const updated = (_b = getProp(target, "updatedAt")) !== null && _b !== void 0 ? _b : getProp(row, "updatedAt");
|
|
247
|
-
const fmt = (d) => {
|
|
248
|
-
if (d == null)
|
|
249
|
-
return "";
|
|
250
|
-
const date = d instanceof Date ? d : new Date(String(d));
|
|
251
|
-
if (isNaN(date.getTime()))
|
|
252
|
-
return String(d);
|
|
253
|
-
return date.toLocaleString();
|
|
254
|
-
};
|
|
255
|
-
return (React.createElement("div", { className: "flex flex-col text-sm text-muted-foreground" },
|
|
256
|
-
React.createElement("span", null, fmt(created)),
|
|
257
|
-
React.createElement("span", null, fmt(updated))));
|
|
258
|
-
}
|
|
259
|
-
return (React.createElement("span", null, col.textFormatter
|
|
260
|
-
? col.textFormatter(value, row)
|
|
261
|
-
: String(value || "")));
|
|
262
|
-
};
|
|
263
|
-
// Create loading skeleton rows
|
|
264
|
-
const renderLoadingRows = () => {
|
|
265
|
-
return Array.from({ length: pageLimit || 5 }).map((_, index) => (React.createElement(TableRow, { key: `loading-${index}`, className: "hover:bg-muted/50", "data-testid": _testIdLoadingRowPrefix
|
|
266
|
-
? `${_testIdLoadingRowPrefix}-${index}`
|
|
267
|
-
: undefined }, tableHeadItems.map((_, colIndex) => (React.createElement(TableCell, { key: colIndex, className: "py-4" },
|
|
268
|
-
React.createElement("div", { className: "h-4 bg-muted animate-pulse rounded w-full" })))))));
|
|
269
|
-
};
|
|
270
|
-
return (React.createElement("div", { className: "space-y-4", "data-testid": _testIdWrapper },
|
|
271
|
-
React.createElement("div", { className: "flex items-center justify-between" },
|
|
272
|
-
React.createElement("div", { className: "space-y-1" },
|
|
273
|
-
React.createElement("h2", { className: "text-2xl font-bold tracking-tight", "data-testid": _testIdHeading }, tableHeading),
|
|
274
|
-
tableDescription && (React.createElement("p", { className: "text-muted-foreground", "data-testid": _testIdTableDescription }, tableDescription))),
|
|
275
|
-
React.createElement("div", { className: "flex flex-row items-center justify-end gap-2" },
|
|
276
|
-
React.createElement("div", { "data-testid": _testIdSearch },
|
|
277
|
-
React.createElement(EnhancedTableHeaderSearch, { handleSearchInput: handleSearchInput, loading: loading, searchDisabled: searchDisabled, searchEnabled: searchEnabled, searchId: searchId, searchPlaceholder: searchPlaceholder, searchValue: searchValue })),
|
|
278
|
-
React.createElement("div", { "data-testid": _testIdHeaderActions },
|
|
279
|
-
React.createElement(EnhancedTableHeaderAction, { headerActions: headerActions, numberOfFilters: numberOfFilters, onClearFilters: onClearFilters, testIdActionPrefix: _testIdHeaderActionPrefix, testIdClearFilters: _testIdHeaderActionClearFilters, testIdFilterBadge: _testIdHeaderActionFilterBadge })))),
|
|
280
|
-
React.createElement("div", { className: "border rounded-md", "data-testid": _testIdTableWrapper },
|
|
281
|
-
React.createElement(Table, null,
|
|
282
|
-
React.createElement(TableHeader, null,
|
|
283
|
-
React.createElement(TableRow, null, tableHeadItems.map((header, index) => (React.createElement(TableHead, { key: index, style: { width: header.width }, className: cn("font-medium", index === 0 && "rounded-tl-md", index === tableHeadItems.length - 1 && "rounded-tr-md") }, header.label))))),
|
|
284
|
-
React.createElement(TableBody, null, loading ? (renderLoadingRows()) : tableBodyRows.length === 0 ? (React.createElement(TableRow, null,
|
|
285
|
-
React.createElement(TableCell, { colSpan: tableHeadItems.length, className: "h-24 text-center text-muted-foreground", "data-testid": _testIdNoResults }, labels.noResultsFound))) : (tableBodyRows.map((row, rowIndex) => (React.createElement(TableRow, { key: rowIndex, className: "hover:bg-muted/50", "data-testid": _testIdRowPrefix
|
|
286
|
-
? `${_testIdRowPrefix}-${rowIndex}`
|
|
287
|
-
: undefined }, tableBodyCols.map((col, colIndex) => (React.createElement(TableCell, { key: colIndex, className: cn("py-4 cursor-pointer"), "data-testid": _testIdCellPrefix
|
|
288
|
-
? `${_testIdCellPrefix}-${rowIndex}-${colIndex}`
|
|
289
|
-
: undefined, onClick: (e) => {
|
|
290
|
-
var _a;
|
|
291
|
-
return (_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText(e.currentTarget.textContent || "");
|
|
292
|
-
} }, renderCellContent(row, col, rowIndex))))))))))),
|
|
293
|
-
React.createElement("div", { className: "flex items-center justify-between", "data-testid": _testIdPaginationWrapper },
|
|
294
|
-
React.createElement("div", { "data-testid": _testIdFooterPagination },
|
|
295
|
-
React.createElement(EnhancedTableFooterPagination, { handleOnSelect: handleOnSelect, isRTL: isRTL, listOptions: listOptions, loading: loading, nodeSelectKey: nodeSelectKey, pageLimit: pageLimit, rowsPerPageLabel: labels.rowsPerPage, totalPages: totalPages })),
|
|
296
|
-
React.createElement("div", { className: "flex items-center gap-4" },
|
|
297
|
-
React.createElement("div", { "data-testid": _testIdFooterPage },
|
|
298
|
-
React.createElement(EnhancedTableFooterPage, { currentPage: currentPage, isRTL: isRTL, loading: loading, loadingLabel: labels.loading, ofLabel: labels.of, pageLabel: labels.page, totalPages: totalPages })),
|
|
299
|
-
React.createElement("div", { "data-testid": _testIdFooterAction },
|
|
300
|
-
React.createElement(EnhancedTableFooterAction, { handleNextOnClick: handleNextOnClick, handlePreviousOnClick: handlePreviousOnClick, isNextDisabled: isNextDisabled, isPreviousDisabled: isPreviousDisabled, isRTL: isRTL, loading: loading, nextPageLabel: labels.nextPage, previousPageLabel: labels.previousPage }))))));
|
|
301
|
-
};
|
|
1
|
+
"use strict";"use client";import e from"react";import{MoreHorizontal as We}from"lucide-react";import{Table as He,TableBody as Ie,TableCell as z,TableHead as Re,TableHeader as et,TableRow as _}from"./ui/table";import{DropdownMenu as tt,DropdownMenuContent as nt,DropdownMenuItem as at,DropdownMenuTrigger as rt}from"./ui/dropdown-menu";import{cn as h}from"../lib/utils";import{EnhancedTableFooterAction as lt}from"./enhanced-table-footer-action";import{EnhancedTableFooterPage as ot}from"./enhanced-table-footer-page";import{EnhancedTableFooterPagination as mt}from"./enhanced-table-footer-pagination";import{Popover as st,PopoverContent as ut,PopoverTrigger as ct}from"./ui/popover";import{EnhancedTableHeaderAction as it}from"./enhanced-table-header-action";import{EnhancedTableHeaderSearch as dt}from"./enhanced-table-header-search";import{Badge as ft}from"./ui/badge";export var COMPONENT_TYPE;(function(s){s.ID="ID",s.BOLD_TEXT="BOLD_TEXT",s.TEXT="TEXT",s.OBJECT="OBJECT",s.MULTIPLE_TEXT_LINES="MULTIPLE_TEXT_LINES",s.CREATED_UPDATED_AT="CREATED_UPDATED_AT",s.ACTIONS="ACTIONS",s.BOOLEAN="BOOLEAN"})(COMPONENT_TYPE||(COMPONENT_TYPE={}));export const EnhancedTable=({currentPage:s,handleNextOnClick:Ee,handleOnSelect:ve,handlePreviousOnClick:pe,handleSearchInput:ge,headerActions:Te,isNextDisabled:be,isPreviousDisabled:ye,isRTL:l=!1,listOptions:_e,loading:v,nodeSelectKey:he="pageLimit",numberOfFilters:Ne,onClearFilters:xe,pageLimit:V,rowActions:De,searchDisabled:Ae=!1,searchEnabled:Se=!0,searchId:ke="table-search",searchPlaceholder:Oe="Search...",searchValue:Ce,tableBodyCols:Le,tableBodyRows:K,tableDescription:q,tableHeading:Be,tableHeadItems:g,totalPages:G,translationLabels:Xe={},testIdWrapper:Q,testIdHeading:Z,testIdTableDescription:w,testIdSearch:Y,testIdHeaderActions:W,testIdHeaderActionPrefix:H,testIdHeaderActionFilterBadge:I,testIdHeaderActionClearFilters:R,testIdTableWrapper:ee,testIdRowPrefix:te,testIdCellPrefix:ne,testIdRowActionPrefix:ae,testIdNoResults:re,testIdLoadingRowPrefix:le,testIdPaginationWrapper:oe,testIdFooterPagination:me,testIdFooterPage:se,testIdFooterAction:ue,testIdWrapperRtl:N,testIdHeadingRtl:x,testIdTableDescriptionRtl:D,testIdSearchRtl:A,testIdHeaderActionsRtl:S,testIdHeaderActionPrefixRtl:k,testIdHeaderActionFilterBadgeRtl:O,testIdHeaderActionClearFiltersRtl:C,testIdTableWrapperRtl:L,testIdRowPrefixRtl:B,testIdCellPrefixRtl:X,testIdRowActionPrefixRtl:$,testIdNoResultsRtl:F,testIdLoadingRowPrefixRtl:P,testIdPaginationWrapperRtl:U,testIdFooterPaginationRtl:j,testIdFooterPageRtl:J,testIdFooterActionRtl:M})=>{const i=Object.assign(Object.assign({},{booleanYes:"Yes",booleanNo:"No",noResultsFound:"No results found.",previousPage:"Previous page",nextPage:"Next page",page:"Page",of:"of",loading:"Loading",rowsPerPage:"Rows per page:"}),Xe),$e=l?N??Q:Q,Fe=l?x??Z:Z,Pe=l?D??w:w,Ue=l?A??Y:Y,je=l?S??W:W,Je=l?k??H:H,Me=l?O??I:I,ze=l?C??R:R,Ve=l?L??ee:ee,ce=l?B??te:te,ie=l?X??ne:ne,de=l?$??ae:ae,Ke=l?F??re:re,fe=l?P??le:le,qe=l?U??oe:oe,Ge=l?j??me:me,Qe=l?J??se:se,Ze=l?M??ue:ue,we=(o,n,T)=>{var d,p;const f=(t,a)=>{if(!a)return t;if(typeof a=="string"){if(a.includes(":")){const m=a.split(":");let r=t;for(const c of m){if(r==null||typeof r!="object")return;r=r[c]}return r}return t&&typeof t=="object"?t[a]:void 0}for(const m of a){const r=f(t,m);if(r!=null)return r}},b=(t,a)=>{if(t&&typeof t=="object"&&a in t)return t[a]},u=f(o,n.key),E=(t=>{var a;return t?Object.values(COMPONENT_TYPE).includes(t)?t:(a={ID:COMPONENT_TYPE.ID,BOLD_TEXT:COMPONENT_TYPE.BOLD_TEXT,BOOLEAN:COMPONENT_TYPE.BOOLEAN,ACTIONS:COMPONENT_TYPE.ACTIONS,TEXT:COMPONENT_TYPE.TEXT,OBJECT:COMPONENT_TYPE.OBJECT,MULTIPLE_TEXT_LINES:COMPONENT_TYPE.MULTIPLE_TEXT_LINES,CREATED_UPDATED_AT:COMPONENT_TYPE.CREATED_UPDATED_AT}[String(t)])!==null&&a!==void 0?a:COMPONENT_TYPE.TEXT:void 0})(n.componentType);if(E===COMPONENT_TYPE.ACTIONS)return e.createElement(tt,null,e.createElement(rt,{asChild:!0},e.createElement(We,{className:"h-4 w-4"})),e.createElement(nt,{align:"end"},De.filter(({enabled:t})=>typeof t=="function"?t(o):t).sort((t,a)=>(t.order||0)-(a.order||0)).map((t,a)=>e.createElement(at,{key:t.id||t.key||a,"data-testid":de?`${de}-${T}-${a}`:void 0,className:h(t.variant==="destructive"&&"text-destructive focus:text-destructive"),onClick:()=>{var m;return(m=t.handleOnClick)===null||m===void 0?void 0:m.call(t,o)}},t.label))));if(E===COMPONENT_TYPE.ID)return e.createElement(st,null,e.createElement(ct,{asChild:!0},e.createElement("span",{className:"text-xs text-muted-foreground font-mono"},typeof u=="string"?`${u.substring(0,8)}...`:String(u||""))),e.createElement(ut,null,e.createElement("span",{className:"text-xs text-muted-foreground font-mono"},n.textFormatter?n.textFormatter(u,o):String(u))));if(E===COMPONENT_TYPE.BOLD_TEXT){const t=n.textFormatter?n.textFormatter(u,o):String(u||"");return e.createElement("span",{className:"font-semibold"},t)}if(E===COMPONENT_TYPE.BOOLEAN){const t=!!u;return e.createElement(ft,{variant:"secondary",className:h("text-white font-medium",t?"bg-green-500 hover:bg-green-600":"bg-red-500 hover:bg-red-600")},t?i.booleanYes:i.booleanNo)}if(E===COMPONENT_TYPE.OBJECT){let t;if(Array.isArray(n.key)){for(const a of n.key)if(typeof a=="string"&&a.includes(":")){const m=a.split(":");let r=o,c=!0;for(const y of m){if(r==null||typeof r!="object"){c=!1;break}r=r[y]}if(c&&r!=null){t=r;break}}}if(t==null)return e.createElement("span",null,"-");if(typeof t=="object"){const a=Object.values(t).find(r=>["string","number","boolean"].includes(typeof r)),m=a??JSON.stringify(t);return e.createElement("span",null,n.textFormatter?n.textFormatter(m,o):String(m))}return e.createElement("span",null,n.textFormatter?n.textFormatter(t,o):String(t))}if(E===COMPONENT_TYPE.MULTIPLE_TEXT_LINES){const a=(Array.isArray(n.key)?n.key:[]).slice(0,3).map(m=>{const r=f(o,m);return r==null?"":String(r)});return e.createElement("div",{className:"flex flex-col"},a.map((m,r)=>e.createElement("span",{key:r,className:"text-sm"},n.textFormatter?n.textFormatter(m,o):m)))}if(E===COMPONENT_TYPE.CREATED_UPDATED_AT){const t=f(o,n.key),a=(d=b(t,"createdAt"))!==null&&d!==void 0?d:b(o,"createdAt"),m=(p=b(t,"updatedAt"))!==null&&p!==void 0?p:b(o,"updatedAt"),r=c=>{if(c==null)return"";const y=c instanceof Date?c:new Date(String(c));return isNaN(y.getTime())?String(c):y.toLocaleString()};return e.createElement("div",{className:"flex flex-col text-sm text-muted-foreground"},e.createElement("span",null,r(a)),e.createElement("span",null,r(m)))}return e.createElement("span",null,n.textFormatter?n.textFormatter(u,o):String(u||""))},Ye=()=>Array.from({length:V||5}).map((o,n)=>e.createElement(_,{key:`loading-${n}`,className:"hover:bg-muted/50","data-testid":fe?`${fe}-${n}`:void 0},g.map((T,d)=>e.createElement(z,{key:d,className:"py-4"},e.createElement("div",{className:"h-4 bg-muted animate-pulse rounded w-full"})))));return e.createElement("div",{className:"space-y-4","data-testid":$e},e.createElement("div",{className:"flex items-center justify-between"},e.createElement("div",{className:"space-y-1"},e.createElement("h2",{className:"text-2xl font-bold tracking-tight","data-testid":Fe},Be),q&&e.createElement("p",{className:"text-muted-foreground","data-testid":Pe},q)),e.createElement("div",{className:"flex flex-row items-center justify-end gap-2"},e.createElement("div",{"data-testid":Ue},e.createElement(dt,{handleSearchInput:ge,loading:v,searchDisabled:Ae,searchEnabled:Se,searchId:ke,searchPlaceholder:Oe,searchValue:Ce})),e.createElement("div",{"data-testid":je},e.createElement(it,{headerActions:Te,numberOfFilters:Ne,onClearFilters:xe,testIdActionPrefix:Je,testIdClearFilters:ze,testIdFilterBadge:Me})))),e.createElement("div",{className:"border rounded-md","data-testid":Ve},e.createElement(He,null,e.createElement(et,null,e.createElement(_,null,g.map((o,n)=>e.createElement(Re,{key:n,style:{width:o.width},className:h("font-medium",n===0&&"rounded-tl-md",n===g.length-1&&"rounded-tr-md")},o.label)))),e.createElement(Ie,null,v?Ye():K.length===0?e.createElement(_,null,e.createElement(z,{colSpan:g.length,className:"h-24 text-center text-muted-foreground","data-testid":Ke},i.noResultsFound)):K.map((o,n)=>e.createElement(_,{key:n,className:"hover:bg-muted/50","data-testid":ce?`${ce}-${n}`:void 0},Le.map((T,d)=>e.createElement(z,{key:d,className:h("py-4 cursor-pointer"),"data-testid":ie?`${ie}-${n}-${d}`:void 0,onClick:p=>{var f;return(f=navigator.clipboard)===null||f===void 0?void 0:f.writeText(p.currentTarget.textContent||"")}},we(o,T,n)))))))),e.createElement("div",{className:"flex items-center justify-between","data-testid":qe},e.createElement("div",{"data-testid":Ge},e.createElement(mt,{handleOnSelect:ve,isRTL:l,listOptions:_e,loading:v,nodeSelectKey:he,pageLimit:V,rowsPerPageLabel:i.rowsPerPage,totalPages:G})),e.createElement("div",{className:"flex items-center gap-4"},e.createElement("div",{"data-testid":Qe},e.createElement(ot,{currentPage:s,isRTL:l,loading:v,loadingLabel:i.loading,ofLabel:i.of,pageLabel:i.page,totalPages:G})),e.createElement("div",{"data-testid":Ze},e.createElement(lt,{handleNextOnClick:Ee,handlePreviousOnClick:pe,isNextDisabled:be,isPreviousDisabled:ye,isRTL:l,loading:v,nextPageLabel:i.nextPage,previousPageLabel:i.previousPage})))))};
|