react-restyle-components 0.4.47 → 0.4.48
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/lib/index.js +3 -1
- package/lib/src/core-components/index.js +1 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/Accordion.js +15 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/AccordionContext.js +6 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/AccordionSection.js +39 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/Header.js +39 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/elements.js +94 -57
- package/lib/src/core-components/src/components/Accordion/AccordionSection/hooks/useCurrentAccordionIndex.js +13 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/index.js +3 -1
- package/lib/src/core-components/src/components/Accordion/AccordionSection/types.js +9 -1
- package/lib/src/core-components/src/components/Accordion/Collapsible/Collapsible2.component.js +249 -1
- package/lib/src/core-components/src/components/Action/types.js +8 -1
- package/lib/src/core-components/src/components/AlertBanner/AlertBanner.js +45 -1
- package/lib/src/core-components/src/components/AlertBanner/elements.js +120 -45
- package/lib/src/core-components/src/components/AlertBanner/index.js +2 -1
- package/lib/src/core-components/src/components/AlertBanner/types.js +10 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-group-by-multiple-select-multiple-fields-display/auto-complete-filter-group-by-multiple-select-multiple-fields-display.component.d.ts +3 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-group-by-multiple-select-multiple-fields-display/auto-complete-filter-group-by-multiple-select-multiple-fields-display.component.js +466 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-multi-select-multi-fields-display-drag-drop/auto-complete-filter-multi-select-multi-fields-display-drag-drop.component.js +229 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-multi-select-selected-top-display/auto-complete-filter-multi-select-selected-top-display.component.js +174 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-multiple-select-multiple-fields-display/auto-complete-filter-multiple-select-multiple-fields-display.component.js +129 -2
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-single-select/auto-complete-filter-single-select.component.js +55 -1
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-filter-single-select-multiple-fields-display/auto-complete-filter-single-select-multiple-fields-display.component.js +308 -2
- package/lib/src/core-components/src/components/AutoComplete/auto-complete-group-by/auto-complete-group-by.component.js +115 -1
- package/lib/src/core-components/src/components/AutoComplete/autocomplete/autocomplete.js +442 -2
- package/lib/src/core-components/src/components/AutoComplete/index.js +8 -1
- package/lib/src/core-components/src/components/Avatar/Avatar.js +148 -14
- package/lib/src/core-components/src/components/Badge/Badge.js +25 -2
- package/lib/src/core-components/src/components/Badge/InnerBadge/Inline.js +25 -1
- package/lib/src/core-components/src/components/Badge/InnerBadge/InnerBadge.js +25 -1
- package/lib/src/core-components/src/components/Badge/InnerBadge/elements.js +78 -32
- package/lib/src/core-components/src/components/Badge/InnerBadge/index.js +1 -1
- package/lib/src/core-components/src/components/Badge/index.js +1 -1
- package/lib/src/core-components/src/components/Badge/types.js +5 -1
- package/lib/src/core-components/src/components/Breadcrumb/Breadcrumb.js +83 -1
- package/lib/src/core-components/src/components/Breadcrumb/elements.js +166 -94
- package/lib/src/core-components/src/components/Breadcrumb/index.js +3 -1
- package/lib/src/core-components/src/components/Breadcrumb/types.js +3 -1
- package/lib/src/core-components/src/components/Button/button.component.js +18 -1
- package/lib/src/core-components/src/components/Button/buttonGroup/buttonGroup.component.js +4 -1
- package/lib/src/core-components/src/components/Button/index.js +2 -1
- package/lib/src/core-components/src/components/Button/types.js +1 -1
- package/lib/src/core-components/src/components/Chip/Chip.js +64 -1
- package/lib/src/core-components/src/components/Chip/elements.js +148 -48
- package/lib/src/core-components/src/components/Chip/index.js +2 -1
- package/lib/src/core-components/src/components/Chip/types.js +4 -1
- package/lib/src/core-components/src/components/Divider/Divider.js +25 -1
- package/lib/src/core-components/src/components/Divider/elements.js +68 -31
- package/lib/src/core-components/src/components/Divider/index.js +2 -1
- package/lib/src/core-components/src/components/Divider/types.js +4 -1
- package/lib/src/core-components/src/components/DynamicGrid/DynamicGrid.js +147 -1
- package/lib/src/core-components/src/components/DynamicGrid/GridContainer.js +24 -17
- package/lib/src/core-components/src/components/DynamicGrid/elements.js +162 -100
- package/lib/src/core-components/src/components/DynamicGrid/index.js +3 -1
- package/lib/src/core-components/src/components/DynamicGrid/types.js +28 -1
- package/lib/src/core-components/src/components/DynamicGrid/utils.js +193 -1
- package/lib/src/core-components/src/components/FormField/FormField.js +103 -1
- package/lib/src/core-components/src/components/FormField/components/CheckboxGroupInput.js +37 -1
- package/lib/src/core-components/src/components/FormField/components/CheckboxInput.js +8 -1
- package/lib/src/core-components/src/components/FormField/components/CssMultilineInput.js +192 -1
- package/lib/src/core-components/src/components/FormField/components/DatePickerInput.js +99 -1
- package/lib/src/core-components/src/components/FormField/components/DropdownInput.js +70 -1
- package/lib/src/core-components/src/components/FormField/components/OtpInput.js +81 -1
- package/lib/src/core-components/src/components/FormField/components/PasswordInput.js +40 -1
- package/lib/src/core-components/src/components/FormField/components/PinInput.js +75 -1
- package/lib/src/core-components/src/components/FormField/components/RadioInput.js +54 -1
- package/lib/src/core-components/src/components/FormField/components/TextDropdownInput.js +94 -1
- package/lib/src/core-components/src/components/FormField/components/ToggleInput.js +36 -1
- package/lib/src/core-components/src/components/FormField/components/index.js +11 -1
- package/lib/src/core-components/src/components/FormField/css-properties.js +161 -1
- package/lib/src/core-components/src/components/FormField/index.js +2 -1
- package/lib/src/core-components/src/components/Icon/Icon.js +159 -1
- package/lib/src/core-components/src/components/Icon/index.js +2 -1
- package/lib/src/core-components/src/components/Icon/types.js +9 -1
- package/lib/src/core-components/src/components/Loader/loader.component.js +215 -2
- package/lib/src/core-components/src/components/Masonry/Masonry.js +73 -1
- package/lib/src/core-components/src/components/Masonry/elements.js +46 -29
- package/lib/src/core-components/src/components/Masonry/hooks.js +100 -1
- package/lib/src/core-components/src/components/Masonry/index.js +3 -1
- package/lib/src/core-components/src/components/Masonry/types.js +1 -1
- package/lib/src/core-components/src/components/Modal/BasicModal/modal.component.js +116 -1
- package/lib/src/core-components/src/components/Modal/index.js +2 -1
- package/lib/src/core-components/src/components/Modal/modal-confirm/modal-confirm.component.js +147 -1
- package/lib/src/core-components/src/components/Picker/color-picker/color-picker.component.js +12 -1
- package/lib/src/core-components/src/components/Picker/color-picker-modal/color-picker-modal.component.js +40 -1
- package/lib/src/core-components/src/components/Picker/index.js +2 -1
- package/lib/src/core-components/src/components/Selection/index.js +4 -1
- package/lib/src/core-components/src/components/Selection/multi-select/multi-select.component.js +49 -1
- package/lib/src/core-components/src/components/Selection/multi-select-with-field/multi-select-with-field.component.js +58 -1
- package/lib/src/core-components/src/components/Selection/multi-selection-dropdown/multi-selection-dropdown.component.js +43 -1
- package/lib/src/core-components/src/components/Selection/single-select/single-select.component.js +87 -1
- package/lib/src/core-components/src/components/Skeleton/Skeleton.js +51 -1
- package/lib/src/core-components/src/components/Skeleton/elements.js +143 -54
- package/lib/src/core-components/src/components/Skeleton/index.js +2 -1
- package/lib/src/core-components/src/components/Skeleton/types.js +4 -1
- package/lib/src/core-components/src/components/SpeedDial/SpeedDial.js +128 -1
- package/lib/src/core-components/src/components/SpeedDial/elements.js +132 -62
- package/lib/src/core-components/src/components/SpeedDial/index.js +2 -1
- package/lib/src/core-components/src/components/SpeedDial/types.js +3 -1
- package/lib/src/core-components/src/components/Stepper2/stepper.component.js +139 -1
- package/lib/src/core-components/src/components/Switch/Switch.js +26 -1
- package/lib/src/core-components/src/components/Switch/elements.js +103 -34
- package/lib/src/core-components/src/components/Switch/index.js +2 -1
- package/lib/src/core-components/src/components/Switch/types.js +3 -1
- package/lib/src/core-components/src/components/Table/Table.js +1489 -1
- package/lib/src/core-components/src/components/Table/columnReorder.js +332 -36
- package/lib/src/core-components/src/components/Table/columnResize.js +284 -21
- package/lib/src/core-components/src/components/Table/elements.js +277 -173
- package/lib/src/core-components/src/components/Table/filters.js +555 -30
- package/lib/src/core-components/src/components/Table/hooks.js +536 -2
- package/lib/src/core-components/src/components/Table/index.js +6 -1
- package/lib/src/core-components/src/components/Table/types.js +1 -1
- package/lib/src/core-components/src/components/Tabs/tabs.component.js +22 -1
- package/lib/src/core-components/src/components/Tags1/Tags.component.js +118 -1
- package/lib/src/core-components/src/components/Tags1/types.js +20 -1
- package/lib/src/core-components/src/components/Timer1/timer.component.js +76 -1
- package/lib/src/core-components/src/components/Toast/Toast.js +50 -1
- package/lib/src/core-components/src/components/Toast/elements.js +122 -41
- package/lib/src/core-components/src/components/Toast/index.js +2 -1
- package/lib/src/core-components/src/components/Toast/types.js +9 -1
- package/lib/src/core-components/src/components/Tooltip/Tooltip.js +200 -1
- package/lib/src/core-components/src/components/Tooltip/elements.js +117 -55
- package/lib/src/core-components/src/components/Tooltip/index.js +2 -1
- package/lib/src/core-components/src/components/Tooltip/types.js +17 -1
- package/lib/src/core-components/src/components/Tooltip/utils.js +140 -1
- package/lib/src/core-components/src/components/TreeSelect/TreeSelect.js +303 -1
- package/lib/src/core-components/src/components/TreeSelect/elements.js +216 -117
- package/lib/src/core-components/src/components/TreeSelect/hooks.js +252 -1
- package/lib/src/core-components/src/components/TreeSelect/index.js +3 -1
- package/lib/src/core-components/src/components/TreeSelect/types.js +1 -1
- package/lib/src/core-components/src/components/ag-grid/AgGrid.js +1057 -1
- package/lib/src/core-components/src/components/ag-grid/elements.js +790 -396
- package/lib/src/core-components/src/components/ag-grid/hooks.js +1220 -4
- package/lib/src/core-components/src/components/ag-grid/index.js +15 -1
- package/lib/src/core-components/src/components/ag-grid/types.js +6 -1
- package/lib/src/core-components/src/components/index.js +31 -1
- package/lib/src/core-components/src/components/pdf/pdf-images.components.js +7 -1
- package/lib/src/core-components/src/components/pdf/pdf-table.components.js +48 -5
- package/lib/src/core-components/src/components/pdf/pdf-typography.components.js +70 -1
- package/lib/src/core-components/src/components/pdf/pdf-wrapped-view.components.js +50 -1
- package/lib/src/core-components/src/core-components/Avatar.js +33 -4
- package/lib/src/core-components/src/core-components/CoreButton/CoreButton.js +10 -1
- package/lib/src/core-components/src/core-components/CoreButton/elements.js +176 -67
- package/lib/src/core-components/src/core-components/CoreButton/index.js +3 -1
- package/lib/src/core-components/src/core-components/CoreButton/types.js +6 -1
- package/lib/src/core-components/src/core-components/CoreButton/utils.js +12 -1
- package/lib/src/core-components/src/core-components/Divider/Divider.js +19 -4
- package/lib/src/core-components/src/core-components/Divider/index.js +1 -1
- package/lib/src/core-components/src/core-components/SelectionCardStrip/index.js +1 -1
- package/lib/src/core-components/src/core-components/SelectionCardStrip/selectionCardStrip.js +33 -10
- package/lib/src/core-components/src/core-components/StateLayer.js +5 -3
- package/lib/src/core-components/src/core-components/ToggleCore/elements.js +50 -25
- package/lib/src/core-components/src/core-components/ToggleCore/index.js +2 -1
- package/lib/src/core-components/src/core-components/ToggleCore/toggleCore.js +14 -1
- package/lib/src/core-components/src/core-components/atoms/Input/Input.js +22 -1
- package/lib/src/core-components/src/core-components/atoms/Label/Label.js +21 -1
- package/lib/src/core-components/src/core-components/atoms/Textarea/Textarea.js +19 -1
- package/lib/src/core-components/src/core-components/index.js +3 -1
- package/lib/src/core-components/src/helpers/constants.js +11 -1
- package/lib/src/core-components/src/hooks/index.js +1 -1
- package/lib/src/core-components/src/hooks/outside.hook.js +28 -1
- package/lib/src/core-components/src/index.js +12 -1
- package/lib/src/core-components/src/tc.global.css +1 -0
- package/lib/src/core-components/src/tc.module.css +1 -1
- package/lib/src/core-components/src/utils/abstracts/breakpoints/index.js +28 -1
- package/lib/src/core-components/src/utils/abstracts/colors/index.js +49 -1
- package/lib/src/core-components/src/utils/abstracts/index.js +5 -1
- package/lib/src/core-components/src/utils/abstracts/space/index.js +26 -1
- package/lib/src/core-components/src/utils/abstracts/theme/ThemeBoundary.js +8 -1
- package/lib/src/core-components/src/utils/abstracts/theme/default-themes.js +30 -1
- package/lib/src/core-components/src/utils/abstracts/theme/index.js +3 -1
- package/lib/src/core-components/src/utils/abstracts/theme/theme.js +30 -1
- package/lib/src/core-components/src/utils/abstracts/theme/types.js +1 -1
- package/lib/src/core-components/src/utils/abstracts/theme/useTheme.js +17 -1
- package/lib/src/core-components/src/utils/abstracts/typography/index.js +25 -1
- package/lib/src/core-components/src/utils/context/DefaultsProvider.js +8 -1
- package/lib/src/core-components/src/utils/context/InternalProvider.js +24 -1
- package/lib/src/core-components/src/utils/context/index.js +2 -1
- package/lib/src/core-components/src/utils/designTokens.js +128 -1
- package/lib/src/core-components/src/utils/helpers/attachSubComponents.js +23 -1
- package/lib/src/core-components/src/utils/helpers/flattenChildren.js +11 -1
- package/lib/src/core-components/src/utils/helpers/getChildByType.js +3 -1
- package/lib/src/core-components/src/utils/helpers/index.js +5 -1
- package/lib/src/core-components/src/utils/helpers/isComponentType.js +16 -1
- package/lib/src/core-components/src/utils/helpers/separateChildrenByType.js +12 -1
- package/lib/src/core-components/src/utils/hooks/index.js +18 -1
- package/lib/src/core-components/src/utils/hooks/useClickOutside.js +18 -1
- package/lib/src/core-components/src/utils/hooks/useCombinedRefs.js +17 -1
- package/lib/src/core-components/src/utils/hooks/useDebouncedCallback.js +12 -1
- package/lib/src/core-components/src/utils/hooks/useDebouncedValue.js +20 -1
- package/lib/src/core-components/src/utils/hooks/useDeprecation.js +40 -1
- package/lib/src/core-components/src/utils/hooks/useDeviceDetect.js +10 -1
- package/lib/src/core-components/src/utils/hooks/useDeviceForm.js +24 -1
- package/lib/src/core-components/src/utils/hooks/useDisableBodyScroll.js +16 -1
- package/lib/src/core-components/src/utils/hooks/useHoverState.js +36 -1
- package/lib/src/core-components/src/utils/hooks/useId.js +7 -1
- package/lib/src/core-components/src/utils/hooks/useIsBrowser.js +11 -1
- package/lib/src/core-components/src/utils/hooks/useMediaQuery.js +16 -1
- package/lib/src/core-components/src/utils/hooks/useOverflow.js +22 -1
- package/lib/src/core-components/src/utils/hooks/useSafeLayoutEffect.js +5 -1
- package/lib/src/core-components/src/utils/hooks/useScrollingUp.js +18 -1
- package/lib/src/core-components/src/utils/hooks/useTrapFocus.js +30 -1
- package/lib/src/core-components/src/utils/hooks/useWindowDimensions.js +23 -1
- package/lib/src/core-components/src/utils/index.js +9 -1
- package/lib/src/core-components/src/utils/stories/Wrappers.js +23 -8
- package/lib/src/core-components/src/utils/stories/cleanProps.js +5 -1
- package/lib/src/core-components/src/utils/stories/index.js +4 -1
- package/lib/src/core-components/src/utils/stories/sleep.js +4 -1
- package/lib/src/core-components/src/utils/stories/view-ports.js +50 -1
- package/lib/src/core-components/src/utils/styling/calcWidthOfColumns.js +5 -1
- package/lib/src/core-components/src/utils/styling/createGridContainer.js +12 -6
- package/lib/src/core-components/src/utils/styling/createTransition.js +7 -2
- package/lib/src/core-components/src/utils/styling/forwardProps.js +10 -1
- package/lib/src/core-components/src/utils/styling/index.js +5 -1
- package/lib/src/core-components/src/utils/styling/pxToRem.js +6 -1
- package/lib/src/core-components/src/utils/testing/getComputedStyle.js +3 -1
- package/lib/src/core-components/src/utils/testing/index.js +1 -1
- package/lib/src/core-components/src/utils/utility.util.js +14 -1
- package/lib/src/core-components/tailwind.config.js +233 -1
- package/lib/src/core-hooks/index.js +3 -1
- package/lib/src/core-hooks/src/useClickOutside/useClickOutside.hook.js +46 -1
- package/lib/src/core-hooks/src/useDebounce/useDebounce.hook.js +30 -1
- package/lib/src/core-hooks/src/usePreventEKey/usePreventEKey.hook.js +8 -1
- package/lib/src/core-utils/index.js +7 -1
- package/lib/src/core-utils/src/calculation/calculation.util.js +89 -1
- package/lib/src/core-utils/src/colors/color.util.js +15 -1
- package/lib/src/core-utils/src/convert/numberToWords/numToWords.util.js +145 -1
- package/lib/src/core-utils/src/convert/typography/camelCaseToTitleCase.util.js +5 -1
- package/lib/src/core-utils/src/form-helper/form-helper.util.js +82 -1
- package/lib/src/core-utils/src/index.js +7 -1
- package/lib/src/core-utils/src/utility/utility.util.js +12 -1
- package/lib/src/core-utils/src/uuid/uuid.util.js +8 -1
- package/package.json +1 -1
|
@@ -1 +1,1489 @@
|
|
|
1
|
-
"use strict";"use client";import{jsx as n,jsxs as c}from"react/jsx-runtime";import Fr,{forwardRef as kr,useState as z,useCallback as u,useMemo as ce,useEffect as Q,useRef as L}from"react";import{TableRoot as xr,Toolbar as mr,ToolbarGroup as ft,SearchInput as Sr,ToolbarButton as te,TableWrapper as vr,StyledTable as wr,TableHeader as Rr,HeaderRow as $r,HeaderCell as Ke,TableBody as Er,TableRow as Tr,TableCell as Je,TableCellContent as Dr,Checkbox as _t,ExpandButton as Pr,ExpandedRow as Lr,ExpandedCell as Nr,TableFooter as Mr,FooterRow as jr,FooterCell as Ye,PaginationWrapper as Wr,PaginationInfo as zr,PaginationControls as Br,PageButton as he,PageSizeSelect as Ar,QuickJumper as Or,EmptyState as Hr,LoadingOverlay as Vr,LoadingSpinner as Ir,EditableCell as Kr,CellEditor as Jr,ColumnTogglePanel as Zt,ColumnToggleHeader as en,ColumnToggleSearch as tn,ColumnToggleList as nn,ColumnToggleItem as pt,ColumnToggleDragHandle as rn,SelectionIndicator as Yr,SelectionCount as Ur}from"./elements";import{useSortState as qr,useFilterState as Gr,usePaginationState as Qr,useRowSelection as Xr,useRowExpansion as _r,useColumnVisibility as Zr,useTableDebounce as ei,sortData as ti,filterData as gt,paginateData as ni,getNestedValue as B,exportToCSV as ri,exportToExcel as ii}from"./hooks";import{getFilterComponent as oi}from"./filters";import{Tooltip as li}from"../Tooltip";import{useColumnResize as ai,getColumnStyle as on}from"./columnResize";const si=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n("circle",{cx:"11",cy:"11",r:"8"}),n("path",{d:"M21 21l-4.35-4.35",strokeLinecap:"round"})]}),di=({size:O=16,color:X="white"})=>n("svg",{viewBox:"0 0 16 16",fill:X,style:{width:O,height:O,display:"block"},children:n("path",{fillRule:"evenodd",d:"M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5z"})}),ci=({size:O=16,color:X="white"})=>n("svg",{viewBox:"0 0 16 16",fill:X,style:{width:O,height:O,display:"block"},children:n("path",{fillRule:"evenodd",d:"M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"})}),ln=({order:O})=>{const X=()=>{switch(O){case"asc":return{up:18,down:12};case"desc":return{up:12,down:18};default:return{up:16,down:16}}},{up:ne,down:fe}=X();return c("div",{style:{display:"flex",flexDirection:"row",alignItems:"center",justifyContent:"center",gap:0},children:[n(di,{size:ne,color:"white"}),n(ci,{size:fe,color:"white"})]})},hi=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M15 18l-6-6 6-6",strokeLinecap:"round",strokeLinejoin:"round"})}),fi=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M9 18l6-6-6-6",strokeLinecap:"round",strokeLinejoin:"round"})}),pi=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M11 17l-5-5 5-5M18 17l-5-5 5-5",strokeLinecap:"round",strokeLinejoin:"round"})}),gi=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M13 7l5 5-5 5M6 7l5 5-5 5",strokeLinecap:"round",strokeLinejoin:"round"})}),ui=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M9 18l6-6-6-6",strokeLinecap:"round",strokeLinejoin:"round"})}),an=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M18 6L6 18M6 6l12 12",strokeLinecap:"round",strokeLinejoin:"round"})}),Ci=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M22 3H2l8 9.46V19l4 2v-8.54L22 3z",strokeLinecap:"round",strokeLinejoin:"round"})}),yi=()=>n("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:n("path",{d:"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3",strokeLinecap:"round",strokeLinejoin:"round"})}),bi=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n("rect",{x:"3",y:"3",width:"7",height:"18",rx:"1"}),n("rect",{x:"14",y:"3",width:"7",height:"18",rx:"1"})]}),Fi=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",children:[n("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}),n("path",{d:"M3 9h18M9 3v18",strokeLinecap:"round"})]}),ki=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n("path",{d:"M23 4v6h-6M1 20v-6h6",strokeLinecap:"round",strokeLinejoin:"round"}),n("path",{d:"M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15",strokeLinecap:"round",strokeLinejoin:"round"})]}),xi=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n("path",{d:"M6 9V2h12v7M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2",strokeLinecap:"round",strokeLinejoin:"round"}),n("rect",{x:"6",y:"14",width:"12",height:"8"})]}),so=()=>c("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n("circle",{cx:"12",cy:"12",r:"10"}),n("path",{d:"M12 8v4M12 16h.01",strokeLinecap:"round",strokeLinejoin:"round"})]});export const Table=kr(function(X,ne){const{id:fe,data:C,columns:F,keyField:M="_id",loading:sn=!1,loadingIndicator:dn,pagination:we=!0,paginationConfig:ut,totalSize:A,remote:Ct=!0,defaultSort:cn,sort:hn,filterable:fn=!1,defaultFilters:pn,filters:gn,defaultShowFilters:un=!0,showFilters:yt,onShowFiltersChange:bt,showFilterToggle:Ft=!0,searchable:kt=!0,searchPlaceholder:Cn="Search...",defaultSearchValue:yn="",searchValue:bn,searchDebounce:Fn=300,rowSelection:H,expandable:g,editMode:V="dblclick",showEditIcon:kn=!1,onCellEdit:xt,exportable:xn=!0,exportFileName:mn="table_export",exportFormat:Ue="csv",columnToggle:Sn=!1,bordered:vn=!0,striped:wn=!1,hover:Rn=!0,compact:v=!1,cellPadding:Re,stickyHeader:mt=!1,maxHeight:$n,rowClassName:qe,rowStyle:Ge,classNames:k={},styles:x={},className:En,style:Tn,emptyText:Dn="No data available",onChange:D,onPageChange:$e,onSortChange:St,onFilterChange:Ee,onSearch:vt,onRowClick:Qe,onRowDoubleClick:Xe,onClearFilters:wt,toolbar:Te,hideToolbar:Pn=!1,showFooter:Ln=!1,caption:Rt,isDelete:mi=!1,isEditModify:Si,isUpdate:vi,isExport:Nn,isSelectRow:$t,getNonSelectableRows:Mn,nonSelectableStyle:jn,isView:wi=!1,fileName:Wn,hideExcelSheet:De=!1,onSelectedRow:zn,selectedRowStyle:Bn,selectedRowClassName:An,onUpdateItem:pe,onPageSizeChange:Pe,onFilter:_e,clearAllFilter:On,onDelete:Ri,onEdit:$i,onView:Ei,dynamicStylingFields:Ti,fieldTypeConfig:re,showRowNumber:ge=!1,rowNumberWidth:Et=50,rowNumberTitle:Hn="#",rowNumberRender:Tt,toolbarPosition:Di="top",toolbarLeft:Vn,toolbarRight:In,toolbarCenter:Kn,refreshable:Jn=!1,onRefresh:Yn,printable:Un=!1,onPrint:qn,size:Pi="medium",error:Li,onRetry:Ni,skeletonLoading:Mi=!1,skeletonRowCount:ji=5,hideHeader:Wi=!1,highlightedRowKeys:zi=[],highlightRowStyle:Bi,highlightRowClassName:Ai,onRowMouseEnter:Oi,onRowMouseLeave:Hi,onCellClick:Vi,onHeaderClick:Ii,resizable:j=!0,resizeConfig:Le,reorderable:$=!0,reorderConfig:Dt,...Pt}=X,Gn=Nn??xn,Ze=Wn??mn,_=ce(()=>A!==void 0&&A>0&&A<=C.length?!1:Ct,[Ct,A,C.length]),d=$t?{mode:"checkbox",selectedRowStyle:Bn||H?.selectedRowStyle,selectedRowClassName:An||H?.selectedRowClassName,...H,getCheckboxProps:e=>{const t=e[M],r=Mn?.includes(t),i=H?.getCheckboxProps?.(e);return{...i,disabled:r||i?.disabled}},onChange:(e,t)=>{H?.onChange?.(e,t)}}:H,et=ce(()=>d?d.allowEditingCells||[]:[],[d]),ie=et.length>0,oe=u(e=>ie?et.includes(e):!1,[ie,et]),I=we?{page:0,pageSize:10,showSizeChanger:!0,showQuickJumper:!0,showTotal:!0,pageSizeOptions:[10,20,30,50],...ut}:ut,Ki={small:{padding:"4px 8px",fontSize:"12px"},medium:{padding:"8px 12px",fontSize:"14px"},large:{padding:"12px 16px",fontSize:"16px"}},Qn=L(null),Ne=L(null),Lt=L(0),[Xn,Nt]=z(yn),[_n,Zn]=z(un),[K,ue]=z(!1),[Me,Mt]=z(""),[er,tt]=z("none"),[J,le]=z(null),[jt,Y]=z(null),[w,je]=z(F);Q(()=>{const e=w.map(r=>r.dataField).sort().join(","),t=F.map(r=>r.dataField).sort().join(",");if(e!==t){const r=new Map(F.map(o=>[o.dataField,o])),i=new Set(w.map(o=>o.dataField)),l=w.filter(o=>r.has(o.dataField)).map(o=>r.get(o.dataField)),h=F.filter(o=>!i.has(o.dataField));je([...l,...h])}else{const r=new Map(F.map(i=>[i.dataField,i]));je(w.map(i=>r.get(i.dataField)||i))}},[F]),Q(()=>{if(!K)return;const e=t=>{Ne.current&&!Ne.current.contains(t.target)&&ue(!1)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[K]);const nt=yt!==void 0,rt=nt?yt:_n,Ji=u(()=>{const e=!rt;nt||Zn(e),bt?.(e)},[rt,nt,bt]),[U,E]=z(null),[W,q]=z(null),We=L(new Map);Q(()=>{We.current.clear()},[U]);const ae=bn??Xn,P=ei(ae,Fn),{sort:m,handleSort:Wt}=qr(cn,hn),{filters:S,setFilter:zt,clearFilters:Bt}=Gr(pn,gn),Ce=L(!1),ze=L("filter"),At=L(_e),tr=L(null),ye=L(null),be=L(null);Q(()=>{const e=t=>{be.current&&!be.current.contains(t.target)&&(ye.current=null)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[]),Q(()=>{const e=()=>{if(ye.current&&be.current){const r=be.current.querySelector(`[data-filter-field="${ye.current}"]`);if(r&&document.activeElement!==r){r.focus();const i=r.value?.length||0;r.setSelectionRange(i,i)}}},t=[requestAnimationFrame(()=>e()),setTimeout(()=>e(),50),setTimeout(()=>e(),150)];return()=>{t.forEach(r=>{typeof r=="number"&&(cancelAnimationFrame(r),clearTimeout(r))})}},[C]);const{page:y,pageSize:T,totalPages:Yi,goToPage:Ot,goToNextPage:Ui,goToPrevPage:qi,goToFirstPage:Gi,goToLastPage:Qi,changePageSize:Ht}=Qr(I?.page||0,I?.pageSize||10,A??C.length),{selectedKeys:Z,isSelected:nr,toggleRow:Be,toggleAll:Vt,isAllSelected:it,isIndeterminate:rr}=Xr(C,d?.keyField||M,d?.mode||"none",d?.selectedRowKeys,d?.getCheckboxProps),{expandedKeys:Xi,isExpanded:ir,toggleExpand:Fe}=_r(g?.keyField||M,g?.defaultExpandedRowKeys,g?.expandedRowKeys,g?.accordion),{visibleColumns:se,toggleColumn:Ae,isColumnHidden:ee}=Zr(F,fe),{columnWidths:Oe,getResizeHandle:_i,resetWidths:Zi,isResizing:It}=ai({columns:se,config:Le,enabled:j,tableId:fe}),or=ce(()=>w.filter(e=>!ee(e.dataField)),[w,ee]),ot=$?or:se;Q(()=>{At.current=_e},[_e]);const Kt=L(P),Jt=L(JSON.stringify(S));Q(()=>{if(!Ce.current)return;const e=JSON.stringify(S),t=Kt.current!==P,r=Jt.current!==e;if(!t&&!r){Ce.current=!1;return}Kt.current=P,Jt.current=e;const i={};Object.keys(S).forEach(o=>{const a=S[o];a!=null&&a!==""&&(i[o]=a)});const l=Object.keys(i).length>0,h={...i};ze.current==="search"&&P&&(h.srText=P),At.current?.(ze.current,h,y+1,T),Ce.current=!1},[P,S,y,T]),Q(()=>{const e=Z.size,t=Lt.current;e>t?tt("up"):e<t&&tt("down"),Lt.current=e;const r=setTimeout(()=>{tt("none")},300);return()=>clearTimeout(r)},[Z.size]);const lt=ce(()=>{if(_)return C;let e=[...C];return e=gt(e,S,F,P),e=ti(e,m,F),we&&(e=ni(e,y,T)),e},[C,S,m,y,T,P,_,we,F]),ke=ce(()=>A!==void 0&&A>0?A:_?C.length:gt(C,S,F,P).length,[C,S,F,P,_,A]),at=u(e=>{Nt(e),vt?.(e),Ce.current=!0,ze.current="search",D?.({type:"search",search:e})},[vt,D]),st=u(e=>{if(!e.sort)return;const t=Wt(e.dataField,m.order);St?.(t),D?.({type:"sort",sort:t})},[m,Wt,St,D]),Yt=u((e,t)=>{zt(e,t);const r={...S,[e]:t};Ee?.(r),Ce.current=!0,ze.current="filter",D?.({type:"filter",filters:r})},[S,zt,Ee,D]),Ut=u(()=>{Bt(),Nt(""),wt?.(),On?.(),Ee?.({}),D?.({type:"filter",filters:{}}),tr.current=null},[Bt,wt,Ee,D]),de=u(e=>{Ot(e);const t=e+1;Pe?.(t,T),$e?.(t,T),D?.({type:"pagination",pagination:{page:t,pageSize:T}})},[Ot,T,Pe,$e,D]),lr=u(e=>{Ht(e),Pe?.(1,e),$e?.(1,e),D?.({type:"pagination",pagination:{page:1,pageSize:e}})},[Ht,Pe,$e,D]),ar=u((e,t,r)=>{if(!d?.getCheckboxProps?.(e)?.disabled){if(d?.mode==="single"){const l=Be(e);l&&d?.onChange?.(l.selectedKeys,l.selectedRows)}if(g?.expandRowByClick){const l=Fe(e);l&&g.onExpandChange?.(l.expandedKeys,l.expanded,e)}Qe?.(e,t,r)}},[H,g,Be,Fe,Qe,d]),xe=u((e,t,r,i)=>{const l=!!e.editorRenderer;if(e.editable===void 0)return{isEditable:l};if(e.editable===!1)return{isEditable:!1};if(e.editable===!0)return{isEditable:!0};const h=B(t,e.dataField),o=e.editable(h,t,r,i);return typeof o=="boolean"?{isEditable:o}:{isEditable:!0,customEditor:o}},[]),sr=u((e,t,r,i,l)=>{if(d&&!!d.getCheckboxProps?.(e)?.disabled&&(!ie||!oe(r.dataField)))return;const{isEditable:h}=xe(r,e,t,i);r.events?.onDoubleClick?.(l,e,t,r,i),V!=="none"&&(d?!!d.getCheckboxProps?.(e)?.disabled?oe(r.dataField)&&V==="dblclick"&&(E({row:t,field:r.dataField}),q(B(e,r.dataField))):h&&V==="dblclick"&&(E({row:t,field:r.dataField}),q(B(e,r.dataField))):h&&V==="dblclick"&&(E({row:t,field:r.dataField}),q(B(e,r.dataField)))),Xe?.(e,t,l)},[V,Xe,xe,d]),dr=u((e,t,r,i,l)=>{if(d&&!!d.getCheckboxProps?.(e)?.disabled&&(!ie||!oe(r.dataField)))return;const{isEditable:h}=xe(r,e,t,i);l&&r.events?.onClick?.(l,e,t,r,i),V==="click"&&(d?!!d.getCheckboxProps?.(e)?.disabled?oe(r.dataField)&&(E({row:t,field:r.dataField}),q(B(e,r.dataField))):h&&(E({row:t,field:r.dataField}),q(B(e,r.dataField))):h&&(E({row:t,field:r.dataField}),q(B(e,r.dataField))))},[V,xe,d]),dt=u((e,t,r)=>{if(U){if(r.validator){const l=r.validator(W,e);if(l!==!0){alert(typeof l=="string"?l:"Invalid value"),E(null);return}}const i=e[M];xt?.(W,r.dataField,e,t),pe?.(W,r.dataField,i)}E(null)},[U,W,xt,pe,M]),cr=(e,t)=>t.split(".").reduce((r,i)=>r?.[i],e),qt=u((e,t,r)=>{const i=re?.[t],l=typeof i=="string"?{type:i}:i;switch(l?.type||"string"){case"array":return l?.fields&&l.fields.length>0?Array.isArray(e)?e.slice(0,l.maxItems||e.length).map(s=>typeof s=="object"&&l.fields?l.fields.map(p=>s[p]).filter(Boolean).join(", "):typeof s=="string"?s:"").filter(Boolean).join(l.separator||"; "):e||"":Array.isArray(e)?e.map(s=>typeof s=="object"?JSON.stringify(s):s).join("; "):e||"";case"object":if(!e||typeof e!="object")return"";const o=l?.fields||l?.keys||[],a=l?.labelMap||{};return o.length>0?o.map(s=>{const p=cr(e,s);return p!=null?`${a[s]||s}: ${p}`:null}).filter(Boolean).join(", "):Object.entries(e).map(([s,p])=>typeof p=="boolean"?`${s}: ${p?"Yes":"No"}`:`${s}: ${p}`).join(", ");case"date":if(!e)return"";try{const s=new Date(e),p=l?.dateFormat||"YYYY-MM-DD HH:mm:ss";return s.toISOString().slice(0,19).replace("T"," ")}catch{return String(e)}case"number":return e!=null?String(Number(e)):"";case"boolean":return typeof e=="boolean"?e?"Yes":"No":"";default:return typeof e=="boolean"?e?"Yes":"No":e!=null?String(e):""}},[re]),Gt=u(async()=>{const e=_?C:gt(C,S,F,P);let t=se.filter(i=>i.csvExport!==!1);Array.isArray(De)&&(t=t.filter(i=>!De.includes(i.dataField))),re&&(t=t.filter(i=>{const l=re[i.dataField],h=typeof l=="string"?{type:l}:l;return!(h?.hideFromExport||h?.csvExport===!1)}));const r=t.map(i=>{const l=re?.[i.dataField],h=typeof l=="string"?{type:l}:l;return i.csvFormatter?i:h?.exportFormatter?{...i,csvFormatter:h.exportFormatter}:h?.type?{...i,csvFormatter:(o,a)=>qt(o,i.dataField,a)}:i});Ue==="excel"?await ii(e,r,Ze):ri(e,r,Ze)},[C,S,F,P,se,De,re,qt,Ze,_,Ue]),hr=u((e,t)=>{t.stopPropagation();const r=Be(e);r&&d?.onChange?.(r.selectedKeys,r.selectedRows)},[Be,H]),fr=u(()=>{const e=Vt(!it);e&&d?.onChange?.(e.selectedKeys,e.selectedRows)},[Vt,it,d]),pr=u((e,t)=>{if(d?.getCheckboxProps?.(e)?.disabled)return;t.stopPropagation();const i=Fe(e);g?.onExpandChange?.(i.expandedKeys,i.expanded,e)},[Fe,g,d]),me=ce(()=>w.filter(e=>e.dataField!==M&&e.text.toLowerCase().includes(Me.toLowerCase())),[w,M,Me]),Qt=u(e=>e[M],[M]),Xt=u((e,t,r,i)=>{const l=B(e,t.dataField);if(U?.row===r&&U?.field===t.dataField){if(t.editorRenderer){const o=e[M],a=`${o??r}-${t.dataField}`;if(!We.current.has(a)){const s={value:W,onUpdate:p=>{q(p),pe?.(p,t.dataField,o),E(null)},onCancel:()=>E(null),onBlur:()=>{W!==l&&pe?.(W,t.dataField,o),E(null)},row:e,column:t,rowIndex:r,columnIndex:i,rowId:o,dataField:t.dataField,onUpdateItem:p=>{pe?.(p,t.dataField,o),E(null)}};We.current.set(a,t.editorRenderer(s,W,e,t,r,i))}return We.current.get(a)}return n(Jr,{type:t.editorType==="number"?"number":"text",value:W??"",onChange:o=>q(o.target.value),onBlur:()=>dt(e,r,t),onKeyDown:o=>{o.key==="Enter"&&dt(e,r,t),o.key==="Escape"&&E(null)},className:t.editorClasses,style:t.editorStyle,autoFocus:!0})}return t.formatter?t.formatter(l,e,r,i):l==null?"":typeof l=="boolean"?l?"Yes":"No":typeof l=="object"?JSON.stringify(l):String(l)},[U,W,dt]),gr=()=>{if(Pn)return null;if(typeof Te=="function")return Te({searchValue:ae,onSearch:at,onClearFilters:Ut,onExport:Gt});if(Te)return Te;const e=Object.keys(S).length>0||ae;return c(mr,{className:k.toolbar,style:x.toolbar,children:[c(ft,{children:[Vn,kt&&c(Sr,{children:[n(si,{}),n("input",{type:"text",value:ae,onChange:t=>at(t.target.value),onFocus:()=>{ye.current=null},placeholder:Cn})]}),kt&&n(te,{onClick:()=>at(""),disabled:!ae,style:{opacity:ae?1:.6},children:"Clear"}),n(te,{onClick:Ut,disabled:!e,style:{opacity:e?1:.6},children:"Clear all filters"}),Gn&&De!==!0&&c(te,{onClick:Gt,children:[n(yi,{}),Ue==="excel"?"Export Excel":"Export CSV"]}),Ft&&c("div",{ref:Ne,style:{position:"relative"},children:[n(li,{content:"Show/Hide Columns",position:"bottom",children:n(te,{$active:K,onClick:()=>ue(!K),"aria-label":"Toggle column visibility",style:{padding:"0 8px"},children:n(Ci,{})})}),K&&c(Zt,{children:[c(en,{children:[n("span",{children:"Show/Hide Columns"}),n("button",{onClick:()=>ue(!1),children:n(an,{})})]}),n(tn,{children:n("input",{type:"text",value:Me,onChange:t=>Mt(t.target.value),placeholder:"Search columns..."})}),c(nn,{children:[c(pt,{style:{borderBottom:"1px solid #e5e7eb",paddingBottom:8,marginBottom:4},children:[n("input",{type:"checkbox",checked:me.length>0&&me.every(t=>!ee(t.dataField)),onChange:t=>{me.forEach(r=>{t.target.checked?ee(r.dataField)&&Ae(r.dataField):ee(r.dataField)||Ae(r.dataField)})}}),n("span",{style:{fontWeight:600},children:"Select All"})]}),me.map((t,r)=>c(pt,{$reorderable:$,$isDragging:J===t.dataField,$isDragOver:jt===t.dataField,draggable:$,onDragStart:i=>{$&&(le(t.dataField),i.dataTransfer.effectAllowed="move",i.dataTransfer.setData("text/plain",t.dataField))},onDragEnd:()=>{le(null),Y(null)},onDragOver:i=>{$&&(i.preventDefault(),J&&J!==t.dataField&&Y(t.dataField))},onDragLeave:()=>{Y(null)},onDrop:i=>{if(!$)return;i.preventDefault();const l=i.dataTransfer.getData("text/plain");if(l&&l!==t.dataField){const h=w.findIndex(a=>a.dataField===l),o=w.findIndex(a=>a.dataField===t.dataField);if(h!==-1&&o!==-1){const a=[...w],[s]=a.splice(h,1);a.splice(o,0,s),je(a),Dt?.onReorder?.(a,h,o)}}le(null),Y(null)},children:[n("input",{type:"checkbox",checked:!ee(t.dataField),onChange:()=>Ae(t.dataField),onClick:i=>i.stopPropagation()}),n("span",{children:t.text}),$&&n(rn,{$isDragging:J===t.dataField,title:"Drag to reorder"})]},t.dataField))]})]})]})]}),Kn,c(ft,{children:[Jn&&c(te,{onClick:Yn,children:[n(ki,{}),"Refresh"]}),Un&&c(te,{onClick:qn,children:[n(xi,{}),"Print"]}),Sn&&c("div",{ref:Ft?void 0:Ne,style:{position:"relative"},children:[c(te,{$active:K,onClick:()=>ue(!K),children:[n(bi,{}),"Columns"]}),K&&c(Zt,{children:[c(en,{children:[n("span",{children:"Toggle Columns"}),n("button",{onClick:()=>ue(!1),children:n(an,{})})]}),n(tn,{children:n("input",{type:"text",value:Me,onChange:t=>Mt(t.target.value),placeholder:"Search columns..."})}),n(nn,{children:me.map((t,r)=>c(pt,{$reorderable:$,$isDragging:J===t.dataField,$isDragOver:jt===t.dataField,draggable:$,onDragStart:i=>{$&&(le(t.dataField),i.dataTransfer.effectAllowed="move",i.dataTransfer.setData("text/plain",t.dataField))},onDragEnd:()=>{le(null),Y(null)},onDragOver:i=>{$&&(i.preventDefault(),J&&J!==t.dataField&&Y(t.dataField))},onDragLeave:()=>{Y(null)},onDrop:i=>{if(!$)return;i.preventDefault();const l=i.dataTransfer.getData("text/plain");if(l&&l!==t.dataField){const h=w.findIndex(a=>a.dataField===l),o=w.findIndex(a=>a.dataField===t.dataField);if(h!==-1&&o!==-1){const a=[...w],[s]=a.splice(h,1);a.splice(o,0,s),je(a),Dt?.onReorder?.(a,h,o)}}le(null),Y(null)},children:[n("input",{type:"checkbox",checked:!ee(t.dataField),onChange:()=>Ae(t.dataField),onClick:i=>i.stopPropagation()}),n("span",{children:t.text}),$&&n(rn,{$isDragging:J===t.dataField,title:"Drag to reorder"})]},t.dataField))})]})]}),In]})]})},ur=()=>{if(!we)return null;const e=Math.ceil(ke/T)||1,t=ke>0?y*T+1:0,r=_?C.length:lt.length,i=Math.min(y*T+r,ke),l=I?.showTotal===!0?`Showing ${t} to ${i} of ${ke} Results`:typeof I?.showTotal=="function"?I.showTotal(ke,[t,i]):null,h=()=>{const o=[];if(e<=5)for(let s=0;s<e;s++)o.push(s);else if(y<3){for(let s=0;s<4;s++)o.push(s);o.push("..."),o.push(e-1)}else if(y>e-4){o.push(0),o.push("...");for(let s=e-4;s<e;s++)o.push(s)}else{o.push(0),o.push("...");for(let s=y-1;s<=y+1;s++)o.push(s);o.push("..."),o.push(e-1)}return o};return c(Wr,{className:k.pagination,style:x.pagination,children:[c(ft,{children:[(d?.mode==="checkbox"||$t)&&Z.size>0&&c(Yr,{onClick:()=>{const o=C.filter(a=>Z.has(Qt(a)));d?.onChange?.(Array.from(Z),o),zn?.(o)},children:[n(Ur,{$animate:er,children:Z.size},Z.size),n("span",{children:"Selected"})]}),I?.showSizeChanger!==!1&&n(Ar,{value:T,onChange:o=>lr(Number(o.target.value)),children:(I?.pageSizeOptions||[10,20,30,50]).map(o=>n("option",{value:o,children:o},o))})]}),c(Br,{children:[n(he,{onClick:()=>de(0),disabled:y===0,children:n(pi,{})}),n(he,{onClick:()=>de(y-1),disabled:y===0,children:n(hi,{})}),h().map((o,a)=>typeof o=="string"?n("span",{style:{padding:"0 4px",color:"white"},children:o},`ellipsis-${a}`):n(he,{$active:o===y,onClick:()=>de(o),children:o+1},o)),n(he,{onClick:()=>de(y+1),disabled:y>=e-1,children:n(fi,{})}),n(he,{onClick:()=>de(e-1),disabled:y>=e-1,children:n(gi,{})})]}),l&&n(zr,{children:l}),I?.showQuickJumper&&(()=>{const o=a=>{const s=parseInt(a.value,10);return!isNaN(s)&&s>=1&&s<=e?(de(s-1),a.value="",!0):!1};return c(Or,{children:["Go to",n("input",{type:"number",min:1,max:e,placeholder:`1-${e}`,onKeyDown:a=>{if(a.key==="Enter"){a.preventDefault();const s=a.target;o(s)&&s.blur()}},onBlur:a=>{const s=a.target;o(s)}}),n(he,{onClick:()=>{const a=document.querySelector(`#${fe} input[type="number"]`);a&&(o(a),a.blur())},style:{marginLeft:"4px",padding:"2px 8px"},children:"Go"})]})})()]})},Cr=(fn||F.some(e=>typeof e.filter=="function"||e.filterComponent||e.filter===!0))&&rt;return c(xr,{ref:e=>{typeof ne=="function"?ne(e):ne&&(ne.current=e),be.current=e},$bordered:vn,$compact:v,className:En||k.root,style:{...x.root,...Tn,position:"relative"},"aria-label":Pt["aria-label"],"aria-labelledby":Pt["aria-labelledby"],children:[sn&&n(Vr,{className:k.loading,style:x.loading,children:dn||n(Ir,{})}),gr(),n(vr,{$maxHeight:$n,$stickyHeader:mt,className:k.wrapper,style:x.wrapper,children:c(wr,{ref:Qn,$striped:wn,$hover:Rn,$compact:v,role:"grid",children:[Rt&&n("caption",{className:"sr-only",children:Rt}),n(Rr,{$sticky:mt,className:k.header,style:x.header,children:c($r,{className:k.headerRow,style:x.headerRow,children:[d?.mode==="checkbox"&&n(Ke,{$align:"center",$sortable:!1,$compact:v,$width:d.columnWidth||40,children:!d.hideSelectAll&&n(_t,{checked:it,ref:e=>{e&&(e.indeterminate=rr)},onChange:fr})}),g&&n(Ke,{$align:"center",$sortable:!1,$compact:v,$width:g.columnWidth||40}),ge&&n(Ke,{$align:"center",$sortable:!1,$compact:v,$width:Et,children:Hn}),ot.map((e,t)=>{const r=typeof e.filter=="function"||e.filter===!0||e.filterComponent||e.filterRenderer,i=r?(typeof e.filter=="function"?e.filter:null)||e.filterComponent||oi(e.filterType||"text"):null,l=a=>Yt(e.dataField,a),h=j?on(e,Oe,j,It):{};return c(Ke,{ref:a=>{if(a&&j){const s={current:a}}},$align:e.headerAlign||e.align||"left",$sortable:!!e.sort,$compact:v,$width:j&&Oe[e.dataField]?Oe[e.dataField]:e.width,$minWidth:e.minWidth,$pinned:e.pinned,$customClass:!!e.headerClasses,className:[e.headerClasses,k.headerCell].filter(Boolean).join(" "),style:{...typeof e.headerStyle=="function"?e.headerStyle(e):e.headerStyle||x.headerCell,...h,position:"relative"},role:"columnheader","aria-sort":m.field===e.dataField?m.order==="asc"?"ascending":m.order==="desc"?"descending":"none":void 0,"data-column":e.dataField,children:[(()=>{const a=typeof e.headerStyle=="function"?e.headerStyle(e):e.headerStyle,s=e.isHeaderTitle!==!1&&e.hideHeaderText!==!0&&!(a&&a.fontSize===0),p=e.isHeaderFilterComp!==!1&&Cr&&r&&i,b=e.isHeaderSort!==!1&&e.sort;return p?c("div",{style:{display:"flex",flexDirection:"column",gap:s?4:0,width:"100%",paddingRight:j?12:0,position:"relative",zIndex:2},children:[s&&n("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:4},children:n("span",{style:{color:"white",fontWeight:600,fontSize:12,whiteSpace:"nowrap",cursor:b?"pointer":"default",flex:1},onClick:()=>b&&st(e),children:e.headerFormatter?e.headerFormatter(e,t):e.headerText||e.text})}),c("div",{style:{display:"flex",alignItems:"center",justifyContent:"flex-start",gap:4,width:"100%",minHeight:24},children:[n("div",{style:{flex:b?"0 1 auto":1,width:b?"calc(100% - 48px)":"100%",minWidth:0,maxWidth:b?"calc(100% - 48px)":"100%",display:"flex",alignItems:"center",overflow:"hidden"},onClick:R=>R.stopPropagation(),children:e.filterRenderer?e.filterRenderer(l,e):n("div",{onFocusCapture:()=>{ye.current=e.dataField},"data-filter-wrapper":e.dataField,style:{width:"100%"},children:n(i,{column:e,value:S[e.dataField],onChange:l,onClear:()=>Yt(e.dataField,null)},`filter-${e.dataField}`)})}),b&&n("div",{style:{minWidth:40,minHeight:24,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,flexGrow:0,cursor:"pointer",marginLeft:"auto",position:"relative",overflow:"visible"},onClick:R=>{R.stopPropagation(),st(e)},title:`Sort by ${e.text}`,children:e.sortCaret?e.sortCaret(m.field===e.dataField?m.order:null,e):n(ln,{order:m.field===e.dataField?m.order:null,column:e})})]})]}):c("div",{style:{display:"flex",alignItems:"center",justifyContent:e.headerAlign||e.align||"left",gap:6,width:"100%",cursor:b?"pointer":"default",paddingRight:j?12:0,position:"relative",zIndex:2},onClick:()=>b&&st(e),children:[s&&n("span",{style:{color:"white",fontWeight:600,fontSize:12,whiteSpace:"nowrap",flex:1},children:e.headerFormatter?e.headerFormatter(e,t):e.headerText||e.text}),b&&n("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,minWidth:40,minHeight:24,position:"relative",overflow:"visible"},title:`Sort by ${e.text}`,children:e.sortCaret?e.sortCaret(m.field===e.dataField?m.order:null,e):n(ln,{order:m.field===e.dataField?m.order:null,column:e})})]})})(),j&&n("div",{style:{position:"absolute",top:0,right:0,bottom:0,width:6,cursor:"col-resize",zIndex:1,display:"flex",alignItems:"center",justifyContent:"center"},onMouseDown:a=>{a.preventDefault(),a.stopPropagation();const s=a.currentTarget.parentElement;if(s){const p=a.clientX,b=s.offsetWidth,R=e.dataField,He=N=>{const Ve=N.clientX-p,G=Math.max(50,Math.min(800,b+Ve));s.style.width=`${G}px`,s.style.minWidth=`${G}px`,s.style.maxWidth=`${G}px`,document.querySelectorAll(`[data-column="${R}"]`).forEach(Se=>{Se.style.width=`${G}px`,Se.style.minWidth=`${G}px`,Se.style.maxWidth=`${G}px`})},f=()=>{document.removeEventListener("mousemove",He),document.removeEventListener("mouseup",f),document.body.style.cursor="",document.body.style.userSelect="";const N=s.offsetWidth;Le?.onResizeEnd?.(R,N)};document.addEventListener("mousemove",He),document.addEventListener("mouseup",f),document.body.style.cursor="col-resize",document.body.style.userSelect="none",Le?.onResizeStart?.(R,b)}},children:n("div",{style:{width:3,height:"60%",background:"rgba(255,255,255,0.3)",borderRadius:2,transition:"background 0.2s"},onMouseEnter:a=>{a.currentTarget.style.background=Le?.handleHoverColor||"#3b82f6"},onMouseLeave:a=>{a.currentTarget.style.background="rgba(255,255,255,0.3)"}})})]},e.dataField)})]})}),n(Er,{className:k.body,style:x.body,children:lt.length===0?n("tr",{children:n("td",{colSpan:se.length+(d?.mode==="checkbox"?1:0)+(g?1:0)+(ge?1:0),children:c(Hr,{className:k.empty,style:x.empty,children:[n(Fi,{}),n("span",{children:Dn})]})})}):lt.map((e,t)=>{const r=Qt(e),i=nr(r),l=ir(r),h=d?.getCheckboxProps?.(e),o=g?.rowExpandable?.(e)??!0,a=typeof qe=="function"?qe(e,t):qe,s=typeof Ge=="function"?Ge(e,t):Ge,p=i?typeof d?.selectedRowStyle=="function"?d.selectedRowStyle(e):d?.selectedRowStyle:void 0,b=i&&p&&(p.backgroundColor||p.background),R=!!h?.disabled,He=R?jn||{backgroundColor:"#f3f4f6",opacity:.7}:void 0;return c(Fr.Fragment,{children:[c(Tr,{$selected:i,$clickable:!!Qe||d?.mode==="single"||g?.expandRowByClick===!0,$disabled:R,$hasCustomSelectedStyle:!!b,"data-custom-selected":b?"true":void 0,className:`${k.row||""} ${a||""} ${i?typeof d?.selectedRowClassName=="function"?d.selectedRowClassName(e):d?.selectedRowClassName||"":""}`,style:{...x.row,...s,...p,...He},onClick:f=>ar(e,t,f),onDoubleClick:f=>{R||Xe?.(e,t,f)},role:"row","aria-selected":i,children:[d?.mode==="checkbox"&&n(Je,{$align:"center",$compact:v,$padding:Re,$disabled:R,children:n(_t,{checked:i,disabled:h?.disabled,onChange:f=>hr(e,f),onClick:f=>f.stopPropagation()})}),g&&n(Je,{$align:"center",$compact:v,$padding:Re,$disabled:R,children:o&&n(Pr,{$expanded:l,onClick:f=>pr(e,f),children:g.expandIcon?g.expandIcon({expanded:l,row:e,onExpand:()=>Fe(e)}):n(ui,{})})}),ge&&n(Je,{$align:"center",$compact:v,$padding:Re,$disabled:R,style:{width:Et,color:"#6b7280",fontWeight:500},children:Tt?Tt(t+1,e):t+1+y*T}),ot.map((f,N)=>{const Ve=typeof f.classes=="function"?f.classes(B(e,f.dataField),e,t,N):f.classes,G=typeof f.style=="function"?f.style(B(e,f.dataField),e,t,N):f.style,Se=j?on(f,Oe,j,It):{},ct=xe(f,e,t,N),ht=!!h?.disabled;let Ie=ct.isEditable;d&&ht&&(ie?Ie=oe(f.dataField):Ie=!1);const yr=!!(d&&ht&&ie&&oe(f.dataField)),br=Ie&&V!=="none"?ct.customEditor?ct.customEditor:n(Kr,{$editing:U?.row===t&&U?.field===f.dataField,$showEditIcon:kn,children:Xt(e,f,t,N)}):Xt(e,f,t,N);return n(Je,{$align:f.align||"left",$compact:v,$padding:Re,$pinned:f.pinned,$hasCustomClass:!!Ve,$disabled:ht,$isEditable:Ie,$isInAllowedCells:yr,className:Ve||k.cell,style:{...x.cell,...G,...Se},"data-column":f.dataField,onClick:ve=>dr(e,t,f,N,ve),onDoubleClick:ve=>{ve.stopPropagation(),sr(e,t,f,N,ve)},role:"gridcell",children:n(Dr,{$hasFormatter:!!f.formatter,children:br})},f.dataField)})]}),g&&l&&o&&n(Lr,{children:n(Nr,{colSpan:se.length+(d?.mode==="checkbox"?1:0)+(g?1:0)+(ge?1:0),children:g.expandedRowRender?.(e,t,l)})})]},r)})}),Ln&&n(Mr,{className:k.footer,style:x.footer,children:c(jr,{className:k.footerRow,style:x.footerRow,children:[d?.mode==="checkbox"&&n(Ye,{$align:"center",$compact:v}),g&&n(Ye,{$align:"center",$compact:v}),ge&&n(Ye,{$align:"center",$compact:v}),ot.map(e=>n(Ye,{$align:e.align||"left",$compact:v,className:k.footerCell,style:x.footerCell,children:typeof e.footer=="function"?e.footer(e,C):e.footerFormatter?e.footerFormatter(e,C):e.footer},e.dataField))]})})]})}),ur()]})});Table.displayName="Table";export default Table;
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { forwardRef, useState, useCallback, useMemo, useEffect, useRef, } from 'react';
|
|
4
|
+
import { TableRoot, Toolbar, ToolbarGroup, SearchInput, ToolbarButton, TableWrapper, StyledTable, TableHeader, HeaderRow, HeaderCell, TableBody, TableRow, TableCell, TableCellContent, Checkbox, ExpandButton, ExpandedRow, ExpandedCell, TableFooter, FooterRow, FooterCell, PaginationWrapper, PaginationInfo, PaginationControls, PageButton, PageSizeSelect, QuickJumper, EmptyState, LoadingOverlay, LoadingSpinner, EditableCell, CellEditor, ColumnTogglePanel, ColumnToggleHeader, ColumnToggleSearch, ColumnToggleList, ColumnToggleItem, ColumnToggleDragHandle, SelectionIndicator, SelectionCount, } from './elements';
|
|
5
|
+
import { useSortState, useFilterState, usePaginationState, useRowSelection, useRowExpansion, useColumnVisibility, useTableDebounce, sortData, filterData, paginateData, getNestedValue, exportToCSV, exportToExcel, } from './hooks';
|
|
6
|
+
import { getFilterComponent } from './filters';
|
|
7
|
+
import { Tooltip } from '../Tooltip';
|
|
8
|
+
import { useColumnResize, getColumnStyle } from './columnResize';
|
|
9
|
+
// Column reorder is handled internally via popup drag & drop
|
|
10
|
+
// Icons
|
|
11
|
+
const SearchIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "M21 21l-4.35-4.35", strokeLinecap: "round" })] }));
|
|
12
|
+
// Arrow Up Icon with configurable size
|
|
13
|
+
// Arrow Up Icon - stroke-based arrow pointing up (like BsArrowUp)
|
|
14
|
+
const ArrowUpIcon = ({ size = 16, color = 'white', }) => (_jsx("svg", { viewBox: "0 0 16 16", fill: color, style: { width: size, height: size, display: 'block' }, children: _jsx("path", { fillRule: "evenodd", d: "M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5z" }) }));
|
|
15
|
+
// Arrow Down Icon - stroke-based arrow pointing down (like BsArrowDown)
|
|
16
|
+
const ArrowDownIcon = ({ size = 16, color = 'white', }) => (_jsx("svg", { viewBox: "0 0 16 16", fill: color, style: { width: size, height: size, display: 'block' }, children: _jsx("path", { fillRule: "evenodd", d: "M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z" }) }));
|
|
17
|
+
// Default sort caret component with arrow icons (matches BsArrowUp/BsArrowDown style)
|
|
18
|
+
const DefaultSortCaret = ({ order, }) => {
|
|
19
|
+
// Size configuration based on sort order (like your custom sortCaret)
|
|
20
|
+
const getSizeConfig = () => {
|
|
21
|
+
switch (order) {
|
|
22
|
+
case 'asc':
|
|
23
|
+
return { up: 18, down: 12 };
|
|
24
|
+
case 'desc':
|
|
25
|
+
return { up: 12, down: 18 };
|
|
26
|
+
default:
|
|
27
|
+
return { up: 16, down: 16 };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const { up, down } = getSizeConfig();
|
|
31
|
+
return (_jsxs("div", { style: {
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'row',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
gap: 0,
|
|
37
|
+
}, children: [_jsx(ArrowUpIcon, { size: up, color: "white" }), _jsx(ArrowDownIcon, { size: down, color: "white" })] }));
|
|
38
|
+
};
|
|
39
|
+
const ChevronLeftIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M15 18l-6-6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
40
|
+
const ChevronRightIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M9 18l6-6-6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
41
|
+
const ChevronsLeftIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M11 17l-5-5 5-5M18 17l-5-5 5-5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
42
|
+
const ChevronsRightIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M13 7l5 5-5 5M6 7l5 5-5 5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
43
|
+
const ExpandIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M9 18l6-6-6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
44
|
+
const CloseIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
45
|
+
const FilterIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M22 3H2l8 9.46V19l4 2v-8.54L22 3z", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
46
|
+
const DownloadIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
47
|
+
const ColumnsIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "3", width: "7", height: "18", rx: "1" }), _jsx("rect", { x: "14", y: "3", width: "7", height: "18", rx: "1" })] }));
|
|
48
|
+
const EmptyIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("path", { d: "M3 9h18M9 3v18", strokeLinecap: "round" })] }));
|
|
49
|
+
const RefreshIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M23 4v6h-6M1 20v-6h6", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
50
|
+
const PrintIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M6 9V2h12v7M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("rect", { x: "6", y: "14", width: "12", height: "8" })] }));
|
|
51
|
+
const ErrorIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M12 8v4M12 16h.01", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
52
|
+
export const Table = forwardRef(function TableComponent(props, ref) {
|
|
53
|
+
const { id, data, columns, keyField = '_id', loading = false, loadingIndicator, pagination = true, paginationConfig, totalSize, remote = true, defaultSort, sort: controlledSort, filterable = false, defaultFilters, filters: controlledFilters, defaultShowFilters = true, showFilters: controlledShowFilters, onShowFiltersChange, showFilterToggle = true, searchable = true, searchPlaceholder = 'Search...', defaultSearchValue = '', searchValue: controlledSearchValue, searchDebounce = 300, rowSelection, expandable, editMode = 'dblclick', showEditIcon = false, onCellEdit, exportable = true, exportFileName = 'table_export', exportFormat = 'csv', columnToggle = false, bordered = true, striped = false, hover = true, compact = false, cellPadding, stickyHeader = false, maxHeight, rowClassName, rowStyle, classNames = {}, styles = {}, className, style, emptyText = 'No data available', onChange, onPageChange, onSortChange, onFilterChange, onSearch, onRowClick, onRowDoubleClick, onClearFilters, toolbar, hideToolbar = false, showFooter = false, caption,
|
|
54
|
+
// Quick configuration props
|
|
55
|
+
isDelete = false, isEditModify, isUpdate, isExport, isSelectRow, getNonSelectableRows, nonSelectableStyle, isView = false, fileName, hideExcelSheet = false,
|
|
56
|
+
// Quick callbacks
|
|
57
|
+
onSelectedRow, selectedRowStyle, selectedRowClassName, onUpdateItem, onPageSizeChange, onFilter, clearAllFilter, onDelete, onEdit, onView,
|
|
58
|
+
// Dynamic configuration
|
|
59
|
+
dynamicStylingFields, fieldTypeConfig,
|
|
60
|
+
// Row number
|
|
61
|
+
showRowNumber = false, rowNumberWidth = 50, rowNumberTitle = '#', rowNumberRender,
|
|
62
|
+
// Toolbar customization
|
|
63
|
+
toolbarPosition = 'top', toolbarLeft, toolbarRight, toolbarCenter,
|
|
64
|
+
// Refresh
|
|
65
|
+
refreshable = false, onRefresh,
|
|
66
|
+
// Print
|
|
67
|
+
printable = false, onPrint,
|
|
68
|
+
// Size
|
|
69
|
+
size = 'medium',
|
|
70
|
+
// Error state
|
|
71
|
+
error, onRetry,
|
|
72
|
+
// Skeleton loading
|
|
73
|
+
skeletonLoading = false, skeletonRowCount = 5,
|
|
74
|
+
// Hide header
|
|
75
|
+
hideHeader = false,
|
|
76
|
+
// Highlighted rows
|
|
77
|
+
highlightedRowKeys = [], highlightRowStyle, highlightRowClassName,
|
|
78
|
+
// Events
|
|
79
|
+
onRowMouseEnter, onRowMouseLeave, onCellClick, onHeaderClick,
|
|
80
|
+
// Column Resizing
|
|
81
|
+
resizable = true, resizeConfig,
|
|
82
|
+
// Column Reordering
|
|
83
|
+
reorderable = true, reorderConfig, ...rest } = props;
|
|
84
|
+
// Resolve aliases
|
|
85
|
+
const resolvedExportable = isExport ?? exportable;
|
|
86
|
+
const resolvedExportFileName = fileName ?? exportFileName;
|
|
87
|
+
// Auto-detect remote mode: if totalSize <= data.length, use client-side (remote=false)
|
|
88
|
+
const resolvedRemote = useMemo(() => {
|
|
89
|
+
// If totalSize is provided and is <= data.length, all data is loaded - use client-side
|
|
90
|
+
if (totalSize !== undefined &&
|
|
91
|
+
totalSize > 0 &&
|
|
92
|
+
totalSize <= data.length) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
// Otherwise use the prop value (default: true)
|
|
96
|
+
return remote;
|
|
97
|
+
}, [remote, totalSize, data.length]);
|
|
98
|
+
// Handle isSelectRow shorthand
|
|
99
|
+
const resolvedRowSelection = isSelectRow
|
|
100
|
+
? {
|
|
101
|
+
mode: 'checkbox',
|
|
102
|
+
selectedRowStyle: selectedRowStyle || rowSelection?.selectedRowStyle,
|
|
103
|
+
selectedRowClassName: selectedRowClassName || rowSelection?.selectedRowClassName,
|
|
104
|
+
...rowSelection,
|
|
105
|
+
// Merge getNonSelectableRows with existing getCheckboxProps
|
|
106
|
+
getCheckboxProps: (row) => {
|
|
107
|
+
const rowKey = row[keyField];
|
|
108
|
+
const isNonSelectable = getNonSelectableRows?.includes(rowKey);
|
|
109
|
+
const existingProps = rowSelection?.getCheckboxProps?.(row);
|
|
110
|
+
return {
|
|
111
|
+
...existingProps,
|
|
112
|
+
disabled: isNonSelectable || existingProps?.disabled,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
onChange: (keys, rows) => {
|
|
116
|
+
rowSelection?.onChange?.(keys, rows);
|
|
117
|
+
// Note: onSelectedRow is only called when user clicks the "X Selected" button
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
: rowSelection;
|
|
121
|
+
// Normalize allowed editable cells for disabled rows
|
|
122
|
+
const allowedEditingFields = useMemo(() => resolvedRowSelection
|
|
123
|
+
? resolvedRowSelection.allowEditingCells || []
|
|
124
|
+
: [], [resolvedRowSelection]);
|
|
125
|
+
const hasAllowedEditingFields = allowedEditingFields.length > 0;
|
|
126
|
+
const isFieldAllowedForDisabledRow = useCallback((field) => hasAllowedEditingFields ? allowedEditingFields.includes(field) : false, [hasAllowedEditingFields, allowedEditingFields]);
|
|
127
|
+
// Default pagination config - users don't need to pass these
|
|
128
|
+
const resolvedPaginationConfig = pagination
|
|
129
|
+
? {
|
|
130
|
+
page: 0,
|
|
131
|
+
pageSize: 10,
|
|
132
|
+
showSizeChanger: true,
|
|
133
|
+
showQuickJumper: true,
|
|
134
|
+
showTotal: true,
|
|
135
|
+
pageSizeOptions: [10, 20, 30, 50],
|
|
136
|
+
...paginationConfig,
|
|
137
|
+
}
|
|
138
|
+
: paginationConfig;
|
|
139
|
+
// Size configuration
|
|
140
|
+
const sizeConfig = {
|
|
141
|
+
small: { padding: '4px 8px', fontSize: '12px' },
|
|
142
|
+
medium: { padding: '8px 12px', fontSize: '14px' },
|
|
143
|
+
large: { padding: '12px 16px', fontSize: '16px' },
|
|
144
|
+
};
|
|
145
|
+
// Refs
|
|
146
|
+
const tableRef = useRef(null);
|
|
147
|
+
const columnToggleRef = useRef(null);
|
|
148
|
+
const prevSelectionCountRef = useRef(0);
|
|
149
|
+
// State
|
|
150
|
+
const [internalSearchValue, setInternalSearchValue] = useState(defaultSearchValue);
|
|
151
|
+
const [internalShowFilters, setInternalShowFilters] = useState(defaultShowFilters);
|
|
152
|
+
const [columnToggleOpen, setColumnToggleOpen] = useState(false);
|
|
153
|
+
const [columnSearch, setColumnSearch] = useState('');
|
|
154
|
+
const [selectionAnimation, setSelectionAnimation] = useState('none');
|
|
155
|
+
// Column toggle reorder state
|
|
156
|
+
const [toggleDraggingColumn, setToggleDraggingColumn] = useState(null);
|
|
157
|
+
const [toggleDragOverColumn, setToggleDragOverColumn] = useState(null);
|
|
158
|
+
// Internal state for reordered columns (used in popup and for rendering)
|
|
159
|
+
const [reorderedColumns, setReorderedColumns] = useState(columns);
|
|
160
|
+
// Sync reorderedColumns when columns prop structure changes (columns added/removed)
|
|
161
|
+
// We only reset when the actual column dataFields change, not on every reference change
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const currentDataFields = reorderedColumns
|
|
164
|
+
.map((c) => c.dataField)
|
|
165
|
+
.sort()
|
|
166
|
+
.join(',');
|
|
167
|
+
const newDataFields = columns
|
|
168
|
+
.map((c) => c.dataField)
|
|
169
|
+
.sort()
|
|
170
|
+
.join(',');
|
|
171
|
+
if (currentDataFields !== newDataFields) {
|
|
172
|
+
// Columns structure changed - merge new columns while preserving order where possible
|
|
173
|
+
const newColumnMap = new Map(columns.map((c) => [c.dataField, c]));
|
|
174
|
+
const existingDataFields = new Set(reorderedColumns.map((c) => c.dataField));
|
|
175
|
+
// Keep existing order for columns that still exist, update their data
|
|
176
|
+
const preserved = reorderedColumns
|
|
177
|
+
.filter((c) => newColumnMap.has(c.dataField))
|
|
178
|
+
.map((c) => newColumnMap.get(c.dataField));
|
|
179
|
+
// Add new columns at the end
|
|
180
|
+
const added = columns.filter((c) => !existingDataFields.has(c.dataField));
|
|
181
|
+
setReorderedColumns([...preserved, ...added]);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Same columns but maybe different data - update column data while preserving order
|
|
185
|
+
const columnMap = new Map(columns.map((c) => [c.dataField, c]));
|
|
186
|
+
setReorderedColumns(reorderedColumns.map((c) => columnMap.get(c.dataField) || c));
|
|
187
|
+
}
|
|
188
|
+
}, [columns]);
|
|
189
|
+
// Close column toggle panel on outside click
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
if (!columnToggleOpen)
|
|
192
|
+
return;
|
|
193
|
+
const handleClickOutside = (event) => {
|
|
194
|
+
if (columnToggleRef.current &&
|
|
195
|
+
!columnToggleRef.current.contains(event.target)) {
|
|
196
|
+
setColumnToggleOpen(false);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
200
|
+
return () => {
|
|
201
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
202
|
+
};
|
|
203
|
+
}, [columnToggleOpen]);
|
|
204
|
+
// Filter visibility (controlled or uncontrolled)
|
|
205
|
+
const isFilterVisibilityControlled = controlledShowFilters !== undefined;
|
|
206
|
+
const showFilterRow = isFilterVisibilityControlled
|
|
207
|
+
? controlledShowFilters
|
|
208
|
+
: internalShowFilters;
|
|
209
|
+
const handleToggleFilters = useCallback(() => {
|
|
210
|
+
const newValue = !showFilterRow;
|
|
211
|
+
if (!isFilterVisibilityControlled) {
|
|
212
|
+
setInternalShowFilters(newValue);
|
|
213
|
+
}
|
|
214
|
+
onShowFiltersChange?.(newValue);
|
|
215
|
+
}, [showFilterRow, isFilterVisibilityControlled, onShowFiltersChange]);
|
|
216
|
+
const [editingCell, setEditingCell] = useState(null);
|
|
217
|
+
const [editValue, setEditValue] = useState(null);
|
|
218
|
+
// Cache custom editor render to avoid repeated renders while editing the same cell
|
|
219
|
+
const editorRendererCacheRef = useRef(new Map());
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
// Clear cache when editing target changes
|
|
222
|
+
editorRendererCacheRef.current.clear();
|
|
223
|
+
}, [editingCell]);
|
|
224
|
+
const searchValue = controlledSearchValue ?? internalSearchValue;
|
|
225
|
+
const debouncedSearchValue = useTableDebounce(searchValue, searchDebounce);
|
|
226
|
+
// Sort state
|
|
227
|
+
const { sort, handleSort } = useSortState(defaultSort, controlledSort);
|
|
228
|
+
// Filter state
|
|
229
|
+
const { filters, setFilter, clearFilters } = useFilterState(defaultFilters, controlledFilters);
|
|
230
|
+
// Track if onFilter should be called (only after user interaction)
|
|
231
|
+
const shouldCallOnFilter = useRef(false);
|
|
232
|
+
const filterTypeRef = useRef('filter');
|
|
233
|
+
const onFilterRef = useRef(onFilter);
|
|
234
|
+
// Track last called values to prevent duplicate calls
|
|
235
|
+
const lastOnFilterCallRef = useRef(null);
|
|
236
|
+
// Track focused filter field to restore focus after data changes
|
|
237
|
+
const focusedFilterFieldRef = useRef(null);
|
|
238
|
+
const tableContainerRef = useRef(null);
|
|
239
|
+
// Clear focus ref when clicking outside the table
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
const handleClickOutside = (event) => {
|
|
242
|
+
if (tableContainerRef.current &&
|
|
243
|
+
!tableContainerRef.current.contains(event.target)) {
|
|
244
|
+
focusedFilterFieldRef.current = null;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
248
|
+
return () => {
|
|
249
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
250
|
+
};
|
|
251
|
+
}, []);
|
|
252
|
+
// Restore filter focus after data changes
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
const restoreFocus = () => {
|
|
255
|
+
if (focusedFilterFieldRef.current && tableContainerRef.current) {
|
|
256
|
+
const filterInput = tableContainerRef.current.querySelector(`[data-filter-field="${focusedFilterFieldRef.current}"]`);
|
|
257
|
+
if (filterInput && document.activeElement !== filterInput) {
|
|
258
|
+
filterInput.focus();
|
|
259
|
+
// Move cursor to end of input
|
|
260
|
+
const len = filterInput.value?.length || 0;
|
|
261
|
+
filterInput.setSelectionRange(len, len);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
// Try multiple times with increasing delays to handle async renders
|
|
266
|
+
const timers = [
|
|
267
|
+
requestAnimationFrame(() => restoreFocus()),
|
|
268
|
+
setTimeout(() => restoreFocus(), 50),
|
|
269
|
+
setTimeout(() => restoreFocus(), 150),
|
|
270
|
+
];
|
|
271
|
+
return () => {
|
|
272
|
+
timers.forEach((timer) => {
|
|
273
|
+
if (typeof timer === 'number') {
|
|
274
|
+
cancelAnimationFrame(timer);
|
|
275
|
+
clearTimeout(timer);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
}, [data]);
|
|
280
|
+
// Pagination state
|
|
281
|
+
const { page, pageSize, totalPages, goToPage, goToNextPage, goToPrevPage, goToFirstPage, goToLastPage, changePageSize, } = usePaginationState(resolvedPaginationConfig?.page || 0, resolvedPaginationConfig?.pageSize || 10, totalSize ?? data.length);
|
|
282
|
+
// Row selection
|
|
283
|
+
const { selectedKeys, isSelected, toggleRow, toggleAll, isAllSelected, isIndeterminate, } = useRowSelection(data, resolvedRowSelection?.keyField || keyField, resolvedRowSelection?.mode || 'none', resolvedRowSelection?.selectedRowKeys, resolvedRowSelection?.getCheckboxProps);
|
|
284
|
+
// Row expansion
|
|
285
|
+
const { expandedKeys, isExpanded, toggleExpand } = useRowExpansion(expandable?.keyField || keyField, expandable?.defaultExpandedRowKeys, expandable?.expandedRowKeys, expandable?.accordion);
|
|
286
|
+
// Column visibility
|
|
287
|
+
const { visibleColumns, toggleColumn, isColumnHidden } = useColumnVisibility(columns, id);
|
|
288
|
+
// Column resizing hook
|
|
289
|
+
const { columnWidths, getResizeHandle, resetWidths: resetColumnWidths, isResizing, } = useColumnResize({
|
|
290
|
+
columns: visibleColumns,
|
|
291
|
+
config: resizeConfig,
|
|
292
|
+
enabled: resizable,
|
|
293
|
+
tableId: id,
|
|
294
|
+
});
|
|
295
|
+
// Get visible columns from reordered columns (filter hidden ones)
|
|
296
|
+
const visibleRereorderedColumns = useMemo(() => {
|
|
297
|
+
return reorderedColumns.filter((col) => !isColumnHidden(col.dataField));
|
|
298
|
+
}, [reorderedColumns, isColumnHidden]);
|
|
299
|
+
// Use reordered visible columns for rendering
|
|
300
|
+
const renderColumns = reorderable
|
|
301
|
+
? visibleRereorderedColumns
|
|
302
|
+
: visibleColumns;
|
|
303
|
+
// Keep onFilter ref updated
|
|
304
|
+
useEffect(() => {
|
|
305
|
+
onFilterRef.current = onFilter;
|
|
306
|
+
}, [onFilter]);
|
|
307
|
+
// Track previous values to detect actual changes
|
|
308
|
+
const prevSearchRef = useRef(debouncedSearchValue);
|
|
309
|
+
const prevFiltersRef = useRef(JSON.stringify(filters));
|
|
310
|
+
// Call onFilter when filter/search values actually change
|
|
311
|
+
// Note: filter components already debounce internally, so we use filters directly
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
if (!shouldCallOnFilter.current)
|
|
314
|
+
return;
|
|
315
|
+
const currentFiltersStr = JSON.stringify(filters);
|
|
316
|
+
const searchChanged = prevSearchRef.current !== debouncedSearchValue;
|
|
317
|
+
const filtersChanged = prevFiltersRef.current !== currentFiltersStr;
|
|
318
|
+
// Only proceed if search or filters actually changed
|
|
319
|
+
if (!searchChanged && !filtersChanged) {
|
|
320
|
+
shouldCallOnFilter.current = false;
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
// Update previous values
|
|
324
|
+
prevSearchRef.current = debouncedSearchValue;
|
|
325
|
+
prevFiltersRef.current = currentFiltersStr;
|
|
326
|
+
// Clean up filters - remove null, undefined, and empty string values
|
|
327
|
+
const cleanFilters = {};
|
|
328
|
+
Object.keys(filters).forEach((key) => {
|
|
329
|
+
const value = filters[key];
|
|
330
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
331
|
+
cleanFilters[key] = value;
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
const hasFilters = Object.keys(cleanFilters).length > 0;
|
|
335
|
+
// Build filter data based on what type of filter changed
|
|
336
|
+
// For 'search' type, include srText if not empty; for 'filter' type, only pass filters
|
|
337
|
+
const filterData = { ...cleanFilters };
|
|
338
|
+
if (filterTypeRef.current === 'search' && debouncedSearchValue) {
|
|
339
|
+
filterData.srText = debouncedSearchValue;
|
|
340
|
+
}
|
|
341
|
+
// Always call onFilter when filters change (including when cleared)
|
|
342
|
+
// Case 1: Global search cleared, column filters exist → filters only
|
|
343
|
+
// Case 2: Global search cleared, no column filters → empty filters (reload all)
|
|
344
|
+
// Case 3: Specific column cleared → remaining filters
|
|
345
|
+
// Note: page is 0-indexed internally, but onFilter expects 1-indexed page
|
|
346
|
+
onFilterRef.current?.(filterTypeRef.current, filterData, page + 1, pageSize);
|
|
347
|
+
// Reset the flag after processing to prevent duplicate calls
|
|
348
|
+
shouldCallOnFilter.current = false;
|
|
349
|
+
}, [debouncedSearchValue, filters, page, pageSize]);
|
|
350
|
+
// Track selection count changes for animation
|
|
351
|
+
useEffect(() => {
|
|
352
|
+
const currentCount = selectedKeys.size;
|
|
353
|
+
const prevCount = prevSelectionCountRef.current;
|
|
354
|
+
if (currentCount > prevCount) {
|
|
355
|
+
setSelectionAnimation('up');
|
|
356
|
+
}
|
|
357
|
+
else if (currentCount < prevCount) {
|
|
358
|
+
setSelectionAnimation('down');
|
|
359
|
+
}
|
|
360
|
+
prevSelectionCountRef.current = currentCount;
|
|
361
|
+
// Reset animation after it completes
|
|
362
|
+
const timer = setTimeout(() => {
|
|
363
|
+
setSelectionAnimation('none');
|
|
364
|
+
}, 300);
|
|
365
|
+
return () => clearTimeout(timer);
|
|
366
|
+
}, [selectedKeys.size]);
|
|
367
|
+
// Process data (filter, sort, paginate)
|
|
368
|
+
const processedData = useMemo(() => {
|
|
369
|
+
if (resolvedRemote) {
|
|
370
|
+
// Server-side processing - data is already processed
|
|
371
|
+
return data;
|
|
372
|
+
}
|
|
373
|
+
let result = [...data];
|
|
374
|
+
// Filter
|
|
375
|
+
result = filterData(result, filters, columns, debouncedSearchValue);
|
|
376
|
+
// Sort
|
|
377
|
+
result = sortData(result, sort, columns);
|
|
378
|
+
// Paginate
|
|
379
|
+
if (pagination) {
|
|
380
|
+
result = paginateData(result, page, pageSize);
|
|
381
|
+
}
|
|
382
|
+
return result;
|
|
383
|
+
}, [
|
|
384
|
+
data,
|
|
385
|
+
filters,
|
|
386
|
+
sort,
|
|
387
|
+
page,
|
|
388
|
+
pageSize,
|
|
389
|
+
debouncedSearchValue,
|
|
390
|
+
resolvedRemote,
|
|
391
|
+
pagination,
|
|
392
|
+
columns,
|
|
393
|
+
]);
|
|
394
|
+
// Calculate total for pagination
|
|
395
|
+
const calculatedTotal = useMemo(() => {
|
|
396
|
+
// If totalSize is explicitly provided, use it for server-side pagination
|
|
397
|
+
if (totalSize !== undefined && totalSize > 0)
|
|
398
|
+
return totalSize;
|
|
399
|
+
if (resolvedRemote)
|
|
400
|
+
return data.length;
|
|
401
|
+
return filterData(data, filters, columns, debouncedSearchValue).length;
|
|
402
|
+
}, [
|
|
403
|
+
data,
|
|
404
|
+
filters,
|
|
405
|
+
columns,
|
|
406
|
+
debouncedSearchValue,
|
|
407
|
+
resolvedRemote,
|
|
408
|
+
totalSize,
|
|
409
|
+
]);
|
|
410
|
+
// Handle search
|
|
411
|
+
const handleSearchChange = useCallback((value) => {
|
|
412
|
+
setInternalSearchValue(value);
|
|
413
|
+
onSearch?.(value);
|
|
414
|
+
// Enable debounced onFilter callback with 'search' type
|
|
415
|
+
shouldCallOnFilter.current = true;
|
|
416
|
+
filterTypeRef.current = 'search';
|
|
417
|
+
onChange?.({ type: 'search', search: value });
|
|
418
|
+
}, [onSearch, onChange]);
|
|
419
|
+
// Handle sort
|
|
420
|
+
const handleSortClick = useCallback((column) => {
|
|
421
|
+
if (!column.sort)
|
|
422
|
+
return;
|
|
423
|
+
const newSort = handleSort(column.dataField, sort.order);
|
|
424
|
+
onSortChange?.(newSort);
|
|
425
|
+
onChange?.({ type: 'sort', sort: newSort });
|
|
426
|
+
}, [sort, handleSort, onSortChange, onChange]);
|
|
427
|
+
// Handle filter
|
|
428
|
+
const handleFilterChange = useCallback((field, value) => {
|
|
429
|
+
setFilter(field, value);
|
|
430
|
+
const newFilters = { ...filters, [field]: value };
|
|
431
|
+
onFilterChange?.(newFilters);
|
|
432
|
+
// Enable debounced onFilter callback with 'filter' type
|
|
433
|
+
shouldCallOnFilter.current = true;
|
|
434
|
+
filterTypeRef.current = 'filter';
|
|
435
|
+
onChange?.({ type: 'filter', filters: newFilters });
|
|
436
|
+
}, [filters, setFilter, onFilterChange, onChange]);
|
|
437
|
+
// Handle clear all filters
|
|
438
|
+
const handleClearFilters = useCallback(() => {
|
|
439
|
+
clearFilters();
|
|
440
|
+
setInternalSearchValue('');
|
|
441
|
+
onClearFilters?.();
|
|
442
|
+
clearAllFilter?.();
|
|
443
|
+
onFilterChange?.({});
|
|
444
|
+
onChange?.({ type: 'filter', filters: {} });
|
|
445
|
+
// Reset the tracking ref so subsequent filters can trigger onFilter
|
|
446
|
+
lastOnFilterCallRef.current = null;
|
|
447
|
+
}, [clearFilters, onClearFilters, onFilterChange, onChange]);
|
|
448
|
+
// Handle page change
|
|
449
|
+
const handlePageChange = useCallback((newPage) => {
|
|
450
|
+
goToPage(newPage);
|
|
451
|
+
// Pass 1-indexed page number to callbacks (user-friendly)
|
|
452
|
+
const displayPage = newPage + 1;
|
|
453
|
+
// onPageSizeChange is the primary callback
|
|
454
|
+
onPageSizeChange?.(displayPage, pageSize);
|
|
455
|
+
onPageChange?.(displayPage, pageSize);
|
|
456
|
+
onChange?.({
|
|
457
|
+
type: 'pagination',
|
|
458
|
+
pagination: { page: displayPage, pageSize },
|
|
459
|
+
});
|
|
460
|
+
}, [goToPage, pageSize, onPageSizeChange, onPageChange, onChange]);
|
|
461
|
+
// Handle page size change
|
|
462
|
+
const handlePageSizeChange = useCallback((newSize) => {
|
|
463
|
+
changePageSize(newSize);
|
|
464
|
+
// Pass 1-indexed page number to callbacks (page 1 after size change)
|
|
465
|
+
onPageSizeChange?.(1, newSize);
|
|
466
|
+
onPageChange?.(1, newSize);
|
|
467
|
+
onChange?.({
|
|
468
|
+
type: 'pagination',
|
|
469
|
+
pagination: { page: 1, pageSize: newSize },
|
|
470
|
+
});
|
|
471
|
+
}, [changePageSize, onPageSizeChange, onPageChange, onChange]);
|
|
472
|
+
// Handle row click
|
|
473
|
+
const handleRowClick = useCallback((row, rowIndex, e) => {
|
|
474
|
+
// Prevent clicks on disabled rows
|
|
475
|
+
const checkboxProps = resolvedRowSelection?.getCheckboxProps?.(row);
|
|
476
|
+
if (checkboxProps?.disabled) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
// Selection handling - only for 'single' mode (checkbox mode uses checkbox click only)
|
|
480
|
+
if (resolvedRowSelection?.mode === 'single') {
|
|
481
|
+
const result = toggleRow(row);
|
|
482
|
+
if (result) {
|
|
483
|
+
resolvedRowSelection?.onChange?.(result.selectedKeys, result.selectedRows);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// Expand by click
|
|
487
|
+
if (expandable?.expandRowByClick) {
|
|
488
|
+
const result = toggleExpand(row);
|
|
489
|
+
if (result) {
|
|
490
|
+
expandable.onExpandChange?.(result.expandedKeys, result.expanded, row);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
onRowClick?.(row, rowIndex, e);
|
|
494
|
+
}, [rowSelection, expandable, toggleRow, toggleExpand, onRowClick, resolvedRowSelection]);
|
|
495
|
+
// Helper to check if cell is editable and get custom editor
|
|
496
|
+
const getCellEditableInfo = useCallback((column, row, rowIndex, colIndex) => {
|
|
497
|
+
// If editorRenderer is provided, column is editable by default (unless editable explicitly returns false)
|
|
498
|
+
const hasEditorRenderer = !!column.editorRenderer;
|
|
499
|
+
if (column.editable === undefined) {
|
|
500
|
+
// No editable prop - editable if has editorRenderer
|
|
501
|
+
return { isEditable: hasEditorRenderer };
|
|
502
|
+
}
|
|
503
|
+
if (column.editable === false) {
|
|
504
|
+
return { isEditable: false };
|
|
505
|
+
}
|
|
506
|
+
if (column.editable === true) {
|
|
507
|
+
return { isEditable: true };
|
|
508
|
+
}
|
|
509
|
+
// It's a function
|
|
510
|
+
const cellValue = getNestedValue(row, column.dataField);
|
|
511
|
+
const result = column.editable(cellValue, row, rowIndex, colIndex);
|
|
512
|
+
if (typeof result === 'boolean') {
|
|
513
|
+
return { isEditable: result };
|
|
514
|
+
}
|
|
515
|
+
// Result is a custom editor (ReactNode)
|
|
516
|
+
return { isEditable: true, customEditor: result };
|
|
517
|
+
}, []);
|
|
518
|
+
// Handle cell edit
|
|
519
|
+
const handleCellDoubleClick = useCallback((row, rowIndex, column, colIndex, e) => {
|
|
520
|
+
// Only apply allowed-cells logic if rowSelection is configured
|
|
521
|
+
if (resolvedRowSelection) {
|
|
522
|
+
// Check if row is disabled
|
|
523
|
+
const checkboxProps = resolvedRowSelection.getCheckboxProps?.(row);
|
|
524
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
525
|
+
// Only apply allowed-cells logic when row is disabled
|
|
526
|
+
if (isRowDisabled) {
|
|
527
|
+
// If no allowed cells provided, block all clicks
|
|
528
|
+
if (!hasAllowedEditingFields) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
// Only allow clicks on columns in allowed list
|
|
532
|
+
if (!isFieldAllowedForDisabledRow(column.dataField)) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Check if column is editable
|
|
538
|
+
const { isEditable } = getCellEditableInfo(column, row, rowIndex, colIndex);
|
|
539
|
+
// Call column's onDoubleClick event if defined
|
|
540
|
+
column.events?.onDoubleClick?.(e, row, rowIndex, column, colIndex);
|
|
541
|
+
// Handle cell editing
|
|
542
|
+
if (editMode !== 'none') {
|
|
543
|
+
// Only apply allowed-cells logic if rowSelection is configured and row is disabled
|
|
544
|
+
if (resolvedRowSelection) {
|
|
545
|
+
const checkboxProps = resolvedRowSelection.getCheckboxProps?.(row);
|
|
546
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
547
|
+
if (isRowDisabled) {
|
|
548
|
+
if (isFieldAllowedForDisabledRow(column.dataField)) {
|
|
549
|
+
if (editMode === 'dblclick') {
|
|
550
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
551
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// If row is disabled and no allowed cells, don't allow editing (already returned above)
|
|
555
|
+
}
|
|
556
|
+
else if (isEditable && editMode === 'dblclick') {
|
|
557
|
+
// Row is not disabled, allow normal editing
|
|
558
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
559
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else if (isEditable && editMode === 'dblclick') {
|
|
563
|
+
// No rowSelection configured, allow normal editing
|
|
564
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
565
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
// Call row double click callback
|
|
569
|
+
onRowDoubleClick?.(row, rowIndex, e);
|
|
570
|
+
}, [editMode, onRowDoubleClick, getCellEditableInfo, resolvedRowSelection]);
|
|
571
|
+
const handleCellClick = useCallback((row, rowIndex, column, colIndex, e) => {
|
|
572
|
+
// Only apply allowed-cells logic if rowSelection is configured
|
|
573
|
+
if (resolvedRowSelection) {
|
|
574
|
+
// Check if row is disabled
|
|
575
|
+
const checkboxProps = resolvedRowSelection.getCheckboxProps?.(row);
|
|
576
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
577
|
+
// Only apply allowed-cells logic when row is disabled
|
|
578
|
+
if (isRowDisabled) {
|
|
579
|
+
// If no allowed cells provided, block all clicks
|
|
580
|
+
if (!hasAllowedEditingFields) {
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
// Only allow clicks on columns in allowed list
|
|
584
|
+
if (!isFieldAllowedForDisabledRow(column.dataField)) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// Check if column is editable
|
|
590
|
+
const { isEditable } = getCellEditableInfo(column, row, rowIndex, colIndex);
|
|
591
|
+
// Call column's onClick event if defined
|
|
592
|
+
if (e) {
|
|
593
|
+
column.events?.onClick?.(e, row, rowIndex, column, colIndex);
|
|
594
|
+
}
|
|
595
|
+
// Handle cell editing on click
|
|
596
|
+
if (editMode === 'click') {
|
|
597
|
+
// Only apply allowed-cells logic if rowSelection is configured and row is disabled
|
|
598
|
+
if (resolvedRowSelection) {
|
|
599
|
+
const checkboxProps = resolvedRowSelection.getCheckboxProps?.(row);
|
|
600
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
601
|
+
if (isRowDisabled) {
|
|
602
|
+
if (isFieldAllowedForDisabledRow(column.dataField)) {
|
|
603
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
604
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
605
|
+
}
|
|
606
|
+
// If row is disabled and no allowed cells, don't allow editing (already returned above)
|
|
607
|
+
}
|
|
608
|
+
else if (isEditable) {
|
|
609
|
+
// Row is not disabled, allow normal editing
|
|
610
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
611
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else if (isEditable) {
|
|
615
|
+
// No rowSelection configured, allow normal editing
|
|
616
|
+
setEditingCell({ row: rowIndex, field: column.dataField });
|
|
617
|
+
setEditValue(getNestedValue(row, column.dataField));
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}, [editMode, getCellEditableInfo, resolvedRowSelection]);
|
|
621
|
+
const handleCellEditComplete = useCallback((row, rowIndex, column) => {
|
|
622
|
+
if (editingCell) {
|
|
623
|
+
// Validate
|
|
624
|
+
if (column.validator) {
|
|
625
|
+
const result = column.validator(editValue, row);
|
|
626
|
+
if (result !== true) {
|
|
627
|
+
alert(typeof result === 'string' ? result : 'Invalid value');
|
|
628
|
+
setEditingCell(null);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
const rowId = row[keyField];
|
|
633
|
+
onCellEdit?.(editValue, column.dataField, row, rowIndex);
|
|
634
|
+
onUpdateItem?.(editValue, column.dataField, rowId);
|
|
635
|
+
}
|
|
636
|
+
setEditingCell(null);
|
|
637
|
+
}, [editingCell, editValue, onCellEdit, onUpdateItem, keyField]);
|
|
638
|
+
// Helper to get nested value from object
|
|
639
|
+
const getNestedValueLocal = (obj, path) => {
|
|
640
|
+
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
641
|
+
};
|
|
642
|
+
// Process field value based on fieldTypeConfig (matching reference implementation)
|
|
643
|
+
const processFieldValue = useCallback((value, dataField, row) => {
|
|
644
|
+
const configOrType = fieldTypeConfig?.[dataField];
|
|
645
|
+
// Handle both object config and string shorthand (e.g., 'boolean', 'date')
|
|
646
|
+
const config = typeof configOrType === 'string'
|
|
647
|
+
? { type: configOrType }
|
|
648
|
+
: configOrType;
|
|
649
|
+
const fieldType = config?.type || 'string';
|
|
650
|
+
switch (fieldType) {
|
|
651
|
+
case 'array':
|
|
652
|
+
if (config?.fields && config.fields.length > 0) {
|
|
653
|
+
// Array of objects with specific fields to extract
|
|
654
|
+
if (!Array.isArray(value))
|
|
655
|
+
return value || '';
|
|
656
|
+
return value
|
|
657
|
+
.slice(0, config.maxItems || value.length)
|
|
658
|
+
.map((item) => {
|
|
659
|
+
if (typeof item === 'object' && config.fields) {
|
|
660
|
+
// Extract only specified fields from the object
|
|
661
|
+
return config.fields
|
|
662
|
+
.map((field) => item[field])
|
|
663
|
+
.filter(Boolean)
|
|
664
|
+
.join(', ');
|
|
665
|
+
}
|
|
666
|
+
else if (typeof item === 'string') {
|
|
667
|
+
return item;
|
|
668
|
+
}
|
|
669
|
+
return '';
|
|
670
|
+
})
|
|
671
|
+
.filter(Boolean)
|
|
672
|
+
.join(config.separator || '; ');
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
// Default array handling
|
|
676
|
+
if (!Array.isArray(value))
|
|
677
|
+
return value || '';
|
|
678
|
+
return value
|
|
679
|
+
.map((item) => typeof item === 'object' ? JSON.stringify(item) : item)
|
|
680
|
+
.join('; ');
|
|
681
|
+
}
|
|
682
|
+
case 'object':
|
|
683
|
+
if (!value || typeof value !== 'object')
|
|
684
|
+
return '';
|
|
685
|
+
const fields = config?.fields || config?.keys || [];
|
|
686
|
+
const labelMap = config?.labelMap || {};
|
|
687
|
+
if (fields.length > 0) {
|
|
688
|
+
// Extract specific fields with optional label mapping
|
|
689
|
+
return fields
|
|
690
|
+
.map((field) => {
|
|
691
|
+
const nestedValue = getNestedValueLocal(value, field);
|
|
692
|
+
if (nestedValue !== undefined && nestedValue !== null) {
|
|
693
|
+
const label = labelMap[field] || field;
|
|
694
|
+
return `${label}: ${nestedValue}`;
|
|
695
|
+
}
|
|
696
|
+
return null;
|
|
697
|
+
})
|
|
698
|
+
.filter(Boolean)
|
|
699
|
+
.join(', ');
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
// Default object handling
|
|
703
|
+
return Object.entries(value)
|
|
704
|
+
.map(([key, val]) => typeof val === 'boolean'
|
|
705
|
+
? `${key}: ${val ? 'Yes' : 'No'}`
|
|
706
|
+
: `${key}: ${val}`)
|
|
707
|
+
.join(', ');
|
|
708
|
+
}
|
|
709
|
+
case 'date':
|
|
710
|
+
if (!value)
|
|
711
|
+
return '';
|
|
712
|
+
try {
|
|
713
|
+
const date = new Date(value);
|
|
714
|
+
const format = config?.dateFormat || 'YYYY-MM-DD HH:mm:ss';
|
|
715
|
+
// Simple date formatting
|
|
716
|
+
return date.toISOString().slice(0, 19).replace('T', ' ');
|
|
717
|
+
}
|
|
718
|
+
catch {
|
|
719
|
+
return String(value);
|
|
720
|
+
}
|
|
721
|
+
case 'number':
|
|
722
|
+
return value !== undefined && value !== null
|
|
723
|
+
? String(Number(value))
|
|
724
|
+
: '';
|
|
725
|
+
case 'boolean':
|
|
726
|
+
return typeof value === 'boolean' ? (value ? 'Yes' : 'No') : '';
|
|
727
|
+
case 'string':
|
|
728
|
+
case 'text':
|
|
729
|
+
default:
|
|
730
|
+
if (typeof value === 'boolean')
|
|
731
|
+
return value ? 'Yes' : 'No';
|
|
732
|
+
return value !== undefined && value !== null ? String(value) : '';
|
|
733
|
+
}
|
|
734
|
+
}, [fieldTypeConfig]);
|
|
735
|
+
// Handle export
|
|
736
|
+
const handleExport = useCallback(async () => {
|
|
737
|
+
const exportData = resolvedRemote
|
|
738
|
+
? data
|
|
739
|
+
: filterData(data, filters, columns, debouncedSearchValue);
|
|
740
|
+
// Filter columns based on hideExcelSheet array and csvExport !== false
|
|
741
|
+
let exportColumns = visibleColumns.filter((col) => col.csvExport !== false);
|
|
742
|
+
if (Array.isArray(hideExcelSheet)) {
|
|
743
|
+
exportColumns = exportColumns.filter((col) => !hideExcelSheet.includes(col.dataField));
|
|
744
|
+
}
|
|
745
|
+
// Also filter based on fieldTypeConfig hideFromExport or csvExport
|
|
746
|
+
if (fieldTypeConfig) {
|
|
747
|
+
exportColumns = exportColumns.filter((col) => {
|
|
748
|
+
const configOrType = fieldTypeConfig[col.dataField];
|
|
749
|
+
const config = typeof configOrType === 'string'
|
|
750
|
+
? { type: configOrType }
|
|
751
|
+
: configOrType;
|
|
752
|
+
if (config?.hideFromExport)
|
|
753
|
+
return false;
|
|
754
|
+
if (config?.csvExport === false)
|
|
755
|
+
return false;
|
|
756
|
+
return true;
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
// Create enhanced columns with export formatters
|
|
760
|
+
const enhancedColumns = exportColumns.map((col) => {
|
|
761
|
+
const configOrType = fieldTypeConfig?.[col.dataField];
|
|
762
|
+
const config = typeof configOrType === 'string'
|
|
763
|
+
? { type: configOrType }
|
|
764
|
+
: configOrType;
|
|
765
|
+
// If column already has csvFormatter, use it
|
|
766
|
+
if (col.csvFormatter) {
|
|
767
|
+
return col;
|
|
768
|
+
}
|
|
769
|
+
// If config has exportFormatter, use it
|
|
770
|
+
if (config?.exportFormatter) {
|
|
771
|
+
return { ...col, csvFormatter: config.exportFormatter };
|
|
772
|
+
}
|
|
773
|
+
// If config has type, create formatter based on type
|
|
774
|
+
if (config?.type) {
|
|
775
|
+
return {
|
|
776
|
+
...col,
|
|
777
|
+
csvFormatter: (cell, row) => processFieldValue(cell, col.dataField, row),
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
return col;
|
|
781
|
+
});
|
|
782
|
+
// Export based on format
|
|
783
|
+
if (exportFormat === 'excel') {
|
|
784
|
+
await exportToExcel(exportData, enhancedColumns, resolvedExportFileName);
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
exportToCSV(exportData, enhancedColumns, resolvedExportFileName);
|
|
788
|
+
}
|
|
789
|
+
}, [
|
|
790
|
+
data,
|
|
791
|
+
filters,
|
|
792
|
+
columns,
|
|
793
|
+
debouncedSearchValue,
|
|
794
|
+
visibleColumns,
|
|
795
|
+
hideExcelSheet,
|
|
796
|
+
fieldTypeConfig,
|
|
797
|
+
processFieldValue,
|
|
798
|
+
resolvedExportFileName,
|
|
799
|
+
resolvedRemote,
|
|
800
|
+
exportFormat,
|
|
801
|
+
]);
|
|
802
|
+
// Handle checkbox change
|
|
803
|
+
const handleCheckboxChange = useCallback((row, e) => {
|
|
804
|
+
e.stopPropagation();
|
|
805
|
+
const result = toggleRow(row);
|
|
806
|
+
if (result) {
|
|
807
|
+
resolvedRowSelection?.onChange?.(result.selectedKeys, result.selectedRows);
|
|
808
|
+
}
|
|
809
|
+
}, [toggleRow, rowSelection]);
|
|
810
|
+
// Handle select all
|
|
811
|
+
const handleSelectAllChange = useCallback(() => {
|
|
812
|
+
const result = toggleAll(!isAllSelected);
|
|
813
|
+
if (result) {
|
|
814
|
+
resolvedRowSelection?.onChange?.(result.selectedKeys, result.selectedRows);
|
|
815
|
+
}
|
|
816
|
+
}, [toggleAll, isAllSelected, resolvedRowSelection]);
|
|
817
|
+
// Handle expand toggle
|
|
818
|
+
const handleExpandClick = useCallback((row, e) => {
|
|
819
|
+
// Prevent expand on disabled rows
|
|
820
|
+
const checkboxProps = resolvedRowSelection?.getCheckboxProps?.(row);
|
|
821
|
+
if (checkboxProps?.disabled) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
e.stopPropagation();
|
|
825
|
+
const result = toggleExpand(row);
|
|
826
|
+
expandable?.onExpandChange?.(result.expandedKeys, result.expanded, row);
|
|
827
|
+
}, [toggleExpand, expandable, resolvedRowSelection]);
|
|
828
|
+
// Filtered column list for toggle panel - use reorderedColumns to preserve reorder state
|
|
829
|
+
const filteredToggleColumns = useMemo(() => {
|
|
830
|
+
return reorderedColumns.filter((c) => c.dataField !== keyField &&
|
|
831
|
+
c.text.toLowerCase().includes(columnSearch.toLowerCase()));
|
|
832
|
+
}, [reorderedColumns, keyField, columnSearch]);
|
|
833
|
+
// Get row key
|
|
834
|
+
const getRowKey = useCallback((row) => row[keyField], [keyField]);
|
|
835
|
+
// Render cell content
|
|
836
|
+
const renderCellContent = useCallback((row, column, rowIndex, colIndex) => {
|
|
837
|
+
const value = getNestedValue(row, column.dataField);
|
|
838
|
+
const isEditing = editingCell?.row === rowIndex &&
|
|
839
|
+
editingCell?.field === column.dataField;
|
|
840
|
+
if (isEditing) {
|
|
841
|
+
// Check for custom editorRenderer
|
|
842
|
+
if (column.editorRenderer) {
|
|
843
|
+
const rowId = row[keyField];
|
|
844
|
+
const cacheKey = `${rowId ?? rowIndex}-${column.dataField}`;
|
|
845
|
+
if (!editorRendererCacheRef.current.has(cacheKey)) {
|
|
846
|
+
const editorProps = {
|
|
847
|
+
value: editValue,
|
|
848
|
+
onUpdate: (newValue) => {
|
|
849
|
+
setEditValue(newValue);
|
|
850
|
+
// Call onUpdateItem directly for custom editors
|
|
851
|
+
onUpdateItem?.(newValue, column.dataField, rowId);
|
|
852
|
+
setEditingCell(null);
|
|
853
|
+
},
|
|
854
|
+
onCancel: () => setEditingCell(null),
|
|
855
|
+
onBlur: () => {
|
|
856
|
+
// Only complete if value changed
|
|
857
|
+
if (editValue !== value) {
|
|
858
|
+
onUpdateItem?.(editValue, column.dataField, rowId);
|
|
859
|
+
}
|
|
860
|
+
setEditingCell(null);
|
|
861
|
+
},
|
|
862
|
+
row,
|
|
863
|
+
column,
|
|
864
|
+
rowIndex,
|
|
865
|
+
columnIndex: colIndex,
|
|
866
|
+
// Additional helpers for direct update
|
|
867
|
+
rowId,
|
|
868
|
+
dataField: column.dataField,
|
|
869
|
+
onUpdateItem: (newValue) => {
|
|
870
|
+
onUpdateItem?.(newValue, column.dataField, rowId);
|
|
871
|
+
setEditingCell(null);
|
|
872
|
+
},
|
|
873
|
+
};
|
|
874
|
+
editorRendererCacheRef.current.set(cacheKey, column.editorRenderer(editorProps, editValue, row, column, rowIndex, colIndex));
|
|
875
|
+
}
|
|
876
|
+
return editorRendererCacheRef.current.get(cacheKey);
|
|
877
|
+
}
|
|
878
|
+
// Default editor
|
|
879
|
+
return (_jsx(CellEditor, { type: column.editorType === 'number' ? 'number' : 'text', value: editValue ?? '', onChange: (e) => setEditValue(e.target.value), onBlur: () => handleCellEditComplete(row, rowIndex, column), onKeyDown: (e) => {
|
|
880
|
+
if (e.key === 'Enter') {
|
|
881
|
+
handleCellEditComplete(row, rowIndex, column);
|
|
882
|
+
}
|
|
883
|
+
if (e.key === 'Escape') {
|
|
884
|
+
setEditingCell(null);
|
|
885
|
+
}
|
|
886
|
+
}, className: column.editorClasses, style: column.editorStyle, autoFocus: true }));
|
|
887
|
+
}
|
|
888
|
+
if (column.formatter) {
|
|
889
|
+
return column.formatter(value, row, rowIndex, colIndex);
|
|
890
|
+
}
|
|
891
|
+
if (value === null || value === undefined)
|
|
892
|
+
return '';
|
|
893
|
+
if (typeof value === 'boolean')
|
|
894
|
+
return value ? 'Yes' : 'No';
|
|
895
|
+
if (typeof value === 'object')
|
|
896
|
+
return JSON.stringify(value);
|
|
897
|
+
return String(value);
|
|
898
|
+
}, [editingCell, editValue, handleCellEditComplete]);
|
|
899
|
+
// Render toolbar
|
|
900
|
+
const renderToolbar = () => {
|
|
901
|
+
if (hideToolbar)
|
|
902
|
+
return null;
|
|
903
|
+
if (typeof toolbar === 'function') {
|
|
904
|
+
return toolbar({
|
|
905
|
+
searchValue,
|
|
906
|
+
onSearch: handleSearchChange,
|
|
907
|
+
onClearFilters: handleClearFilters,
|
|
908
|
+
onExport: handleExport,
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
if (toolbar)
|
|
912
|
+
return toolbar;
|
|
913
|
+
const hasFilters = Object.keys(filters).length > 0 || searchValue;
|
|
914
|
+
return (_jsxs(Toolbar, { className: classNames.toolbar, style: styles.toolbar, children: [_jsxs(ToolbarGroup, { children: [toolbarLeft, searchable && (_jsxs(SearchInput, { children: [_jsx(SearchIcon, {}), _jsx("input", { type: "text", value: searchValue, onChange: (e) => handleSearchChange(e.target.value), onFocus: () => {
|
|
915
|
+
// Clear column filter focus when global search is focused
|
|
916
|
+
focusedFilterFieldRef.current = null;
|
|
917
|
+
}, placeholder: searchPlaceholder })] })), searchable && (_jsx(ToolbarButton, { onClick: () => handleSearchChange(''), disabled: !searchValue, style: { opacity: searchValue ? 1 : 0.6 }, children: "Clear" })), _jsx(ToolbarButton, { onClick: handleClearFilters, disabled: !hasFilters, style: { opacity: hasFilters ? 1 : 0.6 }, children: "Clear all filters" }), resolvedExportable && hideExcelSheet !== true && (_jsxs(ToolbarButton, { onClick: handleExport, children: [_jsx(DownloadIcon, {}), exportFormat === 'excel' ? 'Export Excel' : 'Export CSV'] })), showFilterToggle && (_jsxs("div", { ref: columnToggleRef, style: { position: 'relative' }, children: [_jsx(Tooltip, { content: "Show/Hide Columns", position: "bottom", children: _jsx(ToolbarButton, { "$active": columnToggleOpen, onClick: () => setColumnToggleOpen(!columnToggleOpen), "aria-label": "Toggle column visibility", style: { padding: '0 8px' }, children: _jsx(FilterIcon, {}) }) }), columnToggleOpen && (_jsxs(ColumnTogglePanel, { children: [_jsxs(ColumnToggleHeader, { children: [_jsx("span", { children: "Show/Hide Columns" }), _jsx("button", { onClick: () => setColumnToggleOpen(false), children: _jsx(CloseIcon, {}) })] }), _jsx(ColumnToggleSearch, { children: _jsx("input", { type: "text", value: columnSearch, onChange: (e) => setColumnSearch(e.target.value), placeholder: "Search columns..." }) }), _jsxs(ColumnToggleList, { children: [_jsxs(ColumnToggleItem, { style: {
|
|
918
|
+
borderBottom: '1px solid #e5e7eb',
|
|
919
|
+
paddingBottom: 8,
|
|
920
|
+
marginBottom: 4,
|
|
921
|
+
}, children: [_jsx("input", { type: "checkbox", checked: filteredToggleColumns.length > 0 &&
|
|
922
|
+
filteredToggleColumns.every((col) => !isColumnHidden(col.dataField)), onChange: (e) => {
|
|
923
|
+
filteredToggleColumns.forEach((col) => {
|
|
924
|
+
if (e.target.checked) {
|
|
925
|
+
if (isColumnHidden(col.dataField)) {
|
|
926
|
+
toggleColumn(col.dataField);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
else {
|
|
930
|
+
if (!isColumnHidden(col.dataField)) {
|
|
931
|
+
toggleColumn(col.dataField);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
} }), _jsx("span", { style: { fontWeight: 600 }, children: "Select All" })] }), filteredToggleColumns.map((column, index) => (_jsxs(ColumnToggleItem, { "$reorderable": reorderable, "$isDragging": toggleDraggingColumn === column.dataField, "$isDragOver": toggleDragOverColumn === column.dataField, draggable: reorderable, onDragStart: (e) => {
|
|
936
|
+
if (!reorderable)
|
|
937
|
+
return;
|
|
938
|
+
setToggleDraggingColumn(column.dataField);
|
|
939
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
940
|
+
e.dataTransfer.setData('text/plain', column.dataField);
|
|
941
|
+
}, onDragEnd: () => {
|
|
942
|
+
setToggleDraggingColumn(null);
|
|
943
|
+
setToggleDragOverColumn(null);
|
|
944
|
+
}, onDragOver: (e) => {
|
|
945
|
+
if (!reorderable)
|
|
946
|
+
return;
|
|
947
|
+
e.preventDefault();
|
|
948
|
+
if (toggleDraggingColumn &&
|
|
949
|
+
toggleDraggingColumn !== column.dataField) {
|
|
950
|
+
setToggleDragOverColumn(column.dataField);
|
|
951
|
+
}
|
|
952
|
+
}, onDragLeave: () => {
|
|
953
|
+
setToggleDragOverColumn(null);
|
|
954
|
+
}, onDrop: (e) => {
|
|
955
|
+
if (!reorderable)
|
|
956
|
+
return;
|
|
957
|
+
e.preventDefault();
|
|
958
|
+
const draggedField = e.dataTransfer.getData('text/plain');
|
|
959
|
+
if (draggedField &&
|
|
960
|
+
draggedField !== column.dataField) {
|
|
961
|
+
// Find indices
|
|
962
|
+
const fromIdx = reorderedColumns.findIndex((c) => c.dataField === draggedField);
|
|
963
|
+
const toIdx = reorderedColumns.findIndex((c) => c.dataField === column.dataField);
|
|
964
|
+
if (fromIdx !== -1 && toIdx !== -1) {
|
|
965
|
+
// Reorder columns
|
|
966
|
+
const newColumns = [...reorderedColumns];
|
|
967
|
+
const [removed] = newColumns.splice(fromIdx, 1);
|
|
968
|
+
newColumns.splice(toIdx, 0, removed);
|
|
969
|
+
// Update local state
|
|
970
|
+
setReorderedColumns(newColumns);
|
|
971
|
+
// Call reorder callback
|
|
972
|
+
reorderConfig?.onReorder?.(newColumns, fromIdx, toIdx);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
setToggleDraggingColumn(null);
|
|
976
|
+
setToggleDragOverColumn(null);
|
|
977
|
+
}, children: [_jsx("input", { type: "checkbox", checked: !isColumnHidden(column.dataField), onChange: () => toggleColumn(column.dataField), onClick: (e) => e.stopPropagation() }), _jsx("span", { children: column.text }), reorderable && (_jsx(ColumnToggleDragHandle, { "$isDragging": toggleDraggingColumn === column.dataField, title: "Drag to reorder" }))] }, column.dataField)))] })] }))] }))] }), toolbarCenter, _jsxs(ToolbarGroup, { children: [refreshable && (_jsxs(ToolbarButton, { onClick: onRefresh, children: [_jsx(RefreshIcon, {}), "Refresh"] })), printable && (_jsxs(ToolbarButton, { onClick: onPrint, children: [_jsx(PrintIcon, {}), "Print"] })), columnToggle && (_jsxs("div", { ref: !showFilterToggle ? columnToggleRef : undefined, style: { position: 'relative' }, children: [_jsxs(ToolbarButton, { "$active": columnToggleOpen, onClick: () => setColumnToggleOpen(!columnToggleOpen), children: [_jsx(ColumnsIcon, {}), "Columns"] }), columnToggleOpen && (_jsxs(ColumnTogglePanel, { children: [_jsxs(ColumnToggleHeader, { children: [_jsx("span", { children: "Toggle Columns" }), _jsx("button", { onClick: () => setColumnToggleOpen(false), children: _jsx(CloseIcon, {}) })] }), _jsx(ColumnToggleSearch, { children: _jsx("input", { type: "text", value: columnSearch, onChange: (e) => setColumnSearch(e.target.value), placeholder: "Search columns..." }) }), _jsx(ColumnToggleList, { children: filteredToggleColumns.map((column, index) => (_jsxs(ColumnToggleItem, { "$reorderable": reorderable, "$isDragging": toggleDraggingColumn === column.dataField, "$isDragOver": toggleDragOverColumn === column.dataField, draggable: reorderable, onDragStart: (e) => {
|
|
978
|
+
if (!reorderable)
|
|
979
|
+
return;
|
|
980
|
+
setToggleDraggingColumn(column.dataField);
|
|
981
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
982
|
+
e.dataTransfer.setData('text/plain', column.dataField);
|
|
983
|
+
}, onDragEnd: () => {
|
|
984
|
+
setToggleDraggingColumn(null);
|
|
985
|
+
setToggleDragOverColumn(null);
|
|
986
|
+
}, onDragOver: (e) => {
|
|
987
|
+
if (!reorderable)
|
|
988
|
+
return;
|
|
989
|
+
e.preventDefault();
|
|
990
|
+
if (toggleDraggingColumn &&
|
|
991
|
+
toggleDraggingColumn !== column.dataField) {
|
|
992
|
+
setToggleDragOverColumn(column.dataField);
|
|
993
|
+
}
|
|
994
|
+
}, onDragLeave: () => {
|
|
995
|
+
setToggleDragOverColumn(null);
|
|
996
|
+
}, onDrop: (e) => {
|
|
997
|
+
if (!reorderable)
|
|
998
|
+
return;
|
|
999
|
+
e.preventDefault();
|
|
1000
|
+
const draggedField = e.dataTransfer.getData('text/plain');
|
|
1001
|
+
if (draggedField &&
|
|
1002
|
+
draggedField !== column.dataField) {
|
|
1003
|
+
const fromIdx = reorderedColumns.findIndex((c) => c.dataField === draggedField);
|
|
1004
|
+
const toIdx = reorderedColumns.findIndex((c) => c.dataField === column.dataField);
|
|
1005
|
+
if (fromIdx !== -1 && toIdx !== -1) {
|
|
1006
|
+
const newColumns = [...reorderedColumns];
|
|
1007
|
+
const [removed] = newColumns.splice(fromIdx, 1);
|
|
1008
|
+
newColumns.splice(toIdx, 0, removed);
|
|
1009
|
+
// Update local state
|
|
1010
|
+
setReorderedColumns(newColumns);
|
|
1011
|
+
reorderConfig?.onReorder?.(newColumns, fromIdx, toIdx);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
setToggleDraggingColumn(null);
|
|
1015
|
+
setToggleDragOverColumn(null);
|
|
1016
|
+
}, children: [_jsx("input", { type: "checkbox", checked: !isColumnHidden(column.dataField), onChange: () => toggleColumn(column.dataField), onClick: (e) => e.stopPropagation() }), _jsx("span", { children: column.text }), reorderable && (_jsx(ColumnToggleDragHandle, { "$isDragging": toggleDraggingColumn === column.dataField, title: "Drag to reorder" }))] }, column.dataField))) })] }))] })), toolbarRight] })] }));
|
|
1017
|
+
};
|
|
1018
|
+
// Render pagination
|
|
1019
|
+
const renderPagination = () => {
|
|
1020
|
+
if (!pagination)
|
|
1021
|
+
return null;
|
|
1022
|
+
const actualTotalPages = Math.ceil(calculatedTotal / pageSize) || 1;
|
|
1023
|
+
const startItem = calculatedTotal > 0 ? page * pageSize + 1 : 0;
|
|
1024
|
+
// Use actual data length for endItem to show correct count
|
|
1025
|
+
const actualDataCount = resolvedRemote
|
|
1026
|
+
? data.length
|
|
1027
|
+
: processedData.length;
|
|
1028
|
+
const endItem = Math.min(page * pageSize + actualDataCount, calculatedTotal);
|
|
1029
|
+
const showTotal = resolvedPaginationConfig?.showTotal === true
|
|
1030
|
+
? `Showing ${startItem} to ${endItem} of ${calculatedTotal} Results`
|
|
1031
|
+
: typeof resolvedPaginationConfig?.showTotal === 'function'
|
|
1032
|
+
? resolvedPaginationConfig.showTotal(calculatedTotal, [
|
|
1033
|
+
startItem,
|
|
1034
|
+
endItem,
|
|
1035
|
+
])
|
|
1036
|
+
: null;
|
|
1037
|
+
// Generate page numbers
|
|
1038
|
+
const getPageNumbers = () => {
|
|
1039
|
+
const pages = [];
|
|
1040
|
+
const maxVisible = 5;
|
|
1041
|
+
if (actualTotalPages <= maxVisible) {
|
|
1042
|
+
for (let i = 0; i < actualTotalPages; i++)
|
|
1043
|
+
pages.push(i);
|
|
1044
|
+
}
|
|
1045
|
+
else {
|
|
1046
|
+
if (page < 3) {
|
|
1047
|
+
for (let i = 0; i < 4; i++)
|
|
1048
|
+
pages.push(i);
|
|
1049
|
+
pages.push('...');
|
|
1050
|
+
pages.push(actualTotalPages - 1);
|
|
1051
|
+
}
|
|
1052
|
+
else if (page > actualTotalPages - 4) {
|
|
1053
|
+
pages.push(0);
|
|
1054
|
+
pages.push('...');
|
|
1055
|
+
for (let i = actualTotalPages - 4; i < actualTotalPages; i++)
|
|
1056
|
+
pages.push(i);
|
|
1057
|
+
}
|
|
1058
|
+
else {
|
|
1059
|
+
pages.push(0);
|
|
1060
|
+
pages.push('...');
|
|
1061
|
+
for (let i = page - 1; i <= page + 1; i++)
|
|
1062
|
+
pages.push(i);
|
|
1063
|
+
pages.push('...');
|
|
1064
|
+
pages.push(actualTotalPages - 1);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return pages;
|
|
1068
|
+
};
|
|
1069
|
+
return (_jsxs(PaginationWrapper, { className: classNames.pagination, style: styles.pagination, children: [_jsxs(ToolbarGroup, { children: [(resolvedRowSelection?.mode === 'checkbox' || isSelectRow) &&
|
|
1070
|
+
selectedKeys.size > 0 && (_jsxs(SelectionIndicator, { onClick: () => {
|
|
1071
|
+
const selectedRows = data.filter((row) => selectedKeys.has(getRowKey(row)));
|
|
1072
|
+
resolvedRowSelection?.onChange?.(Array.from(selectedKeys), selectedRows);
|
|
1073
|
+
// Call onSelectedRow only when user clicks this button
|
|
1074
|
+
onSelectedRow?.(selectedRows);
|
|
1075
|
+
}, children: [_jsx(SelectionCount, { "$animate": selectionAnimation, children: selectedKeys.size }, selectedKeys.size), _jsx("span", { children: "Selected" })] })), resolvedPaginationConfig?.showSizeChanger !== false && (_jsx(PageSizeSelect, { value: pageSize, onChange: (e) => handlePageSizeChange(Number(e.target.value)), children: (resolvedPaginationConfig?.pageSizeOptions || [10, 20, 30, 50]).map((size) => (_jsx("option", { value: size, children: size }, size))) }))] }), _jsxs(PaginationControls, { children: [_jsx(PageButton, { onClick: () => handlePageChange(0), disabled: page === 0, children: _jsx(ChevronsLeftIcon, {}) }), _jsx(PageButton, { onClick: () => handlePageChange(page - 1), disabled: page === 0, children: _jsx(ChevronLeftIcon, {}) }), getPageNumbers().map((p, i) => typeof p === 'string' ? (_jsx("span", { style: { padding: '0 4px', color: 'white' }, children: p }, `ellipsis-${i}`)) : (_jsx(PageButton, { "$active": p === page, onClick: () => handlePageChange(p), children: p + 1 }, p))), _jsx(PageButton, { onClick: () => handlePageChange(page + 1), disabled: page >= actualTotalPages - 1, children: _jsx(ChevronRightIcon, {}) }), _jsx(PageButton, { onClick: () => handlePageChange(actualTotalPages - 1), disabled: page >= actualTotalPages - 1, children: _jsx(ChevronsRightIcon, {}) })] }), showTotal && _jsx(PaginationInfo, { children: showTotal }), resolvedPaginationConfig?.showQuickJumper &&
|
|
1076
|
+
(() => {
|
|
1077
|
+
const handleQuickJump = (input) => {
|
|
1078
|
+
const pageNum = parseInt(input.value, 10);
|
|
1079
|
+
if (!isNaN(pageNum) &&
|
|
1080
|
+
pageNum >= 1 &&
|
|
1081
|
+
pageNum <= actualTotalPages) {
|
|
1082
|
+
handlePageChange(pageNum - 1); // Convert to 0-indexed
|
|
1083
|
+
input.value = '';
|
|
1084
|
+
return true;
|
|
1085
|
+
}
|
|
1086
|
+
return false;
|
|
1087
|
+
};
|
|
1088
|
+
return (_jsxs(QuickJumper, { children: ["Go to", _jsx("input", { type: "number", min: 1, max: actualTotalPages, placeholder: `1-${actualTotalPages}`, onKeyDown: (e) => {
|
|
1089
|
+
if (e.key === 'Enter') {
|
|
1090
|
+
e.preventDefault();
|
|
1091
|
+
const target = e.target;
|
|
1092
|
+
if (handleQuickJump(target)) {
|
|
1093
|
+
target.blur();
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}, onBlur: (e) => {
|
|
1097
|
+
const target = e.target;
|
|
1098
|
+
handleQuickJump(target);
|
|
1099
|
+
} }), _jsx(PageButton, { onClick: () => {
|
|
1100
|
+
const input = document.querySelector(`#${id} input[type="number"]`);
|
|
1101
|
+
if (input) {
|
|
1102
|
+
handleQuickJump(input);
|
|
1103
|
+
input.blur();
|
|
1104
|
+
}
|
|
1105
|
+
}, style: { marginLeft: '4px', padding: '2px 8px' }, children: "Go" })] }));
|
|
1106
|
+
})()] }));
|
|
1107
|
+
};
|
|
1108
|
+
// Check if any columns have filters
|
|
1109
|
+
const hasFilterableColumns = filterable ||
|
|
1110
|
+
columns.some((c) => typeof c.filter === 'function' ||
|
|
1111
|
+
c.filterComponent ||
|
|
1112
|
+
c.filter === true);
|
|
1113
|
+
// Should show filter row - check if there are filterable columns AND filters are visible
|
|
1114
|
+
const shouldShowFilterRow = hasFilterableColumns && showFilterRow;
|
|
1115
|
+
return (_jsxs(TableRoot, { ref: (node) => {
|
|
1116
|
+
// Handle forwarded ref
|
|
1117
|
+
if (typeof ref === 'function') {
|
|
1118
|
+
ref(node);
|
|
1119
|
+
}
|
|
1120
|
+
else if (ref) {
|
|
1121
|
+
ref.current = node;
|
|
1122
|
+
}
|
|
1123
|
+
// Also store in our container ref
|
|
1124
|
+
tableContainerRef.current = node;
|
|
1125
|
+
}, "$bordered": bordered, "$compact": compact, className: className || classNames.root, style: { ...styles.root, ...style, position: 'relative' }, "aria-label": rest['aria-label'], "aria-labelledby": rest['aria-labelledby'], children: [loading && (_jsx(LoadingOverlay, { className: classNames.loading, style: styles.loading, children: loadingIndicator || _jsx(LoadingSpinner, {}) })), renderToolbar(), _jsx(TableWrapper, { "$maxHeight": maxHeight, "$stickyHeader": stickyHeader, className: classNames.wrapper, style: styles.wrapper, children: _jsxs(StyledTable, { ref: tableRef, "$striped": striped, "$hover": hover, "$compact": compact, role: "grid", children: [caption && _jsx("caption", { className: "sr-only", children: caption }), _jsx(TableHeader, { "$sticky": stickyHeader, className: classNames.header, style: styles.header, children: _jsxs(HeaderRow, { className: classNames.headerRow, style: styles.headerRow, children: [resolvedRowSelection?.mode === 'checkbox' && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": resolvedRowSelection.columnWidth || 40, children: !resolvedRowSelection.hideSelectAll && (_jsx(Checkbox, { checked: isAllSelected, ref: (el) => {
|
|
1126
|
+
if (el)
|
|
1127
|
+
el.indeterminate = isIndeterminate;
|
|
1128
|
+
}, onChange: handleSelectAllChange })) })), expandable && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": expandable.columnWidth || 40 })), showRowNumber && (_jsx(HeaderCell, { "$align": "center", "$sortable": false, "$compact": compact, "$width": rowNumberWidth, children: rowNumberTitle })), renderColumns.map((column, colIndex) => {
|
|
1129
|
+
// Determine if column has a filter
|
|
1130
|
+
const hasColumnFilter = typeof column.filter === 'function' ||
|
|
1131
|
+
column.filter === true ||
|
|
1132
|
+
column.filterComponent ||
|
|
1133
|
+
column.filterRenderer;
|
|
1134
|
+
// Get the filter component
|
|
1135
|
+
const FilterComponent = hasColumnFilter
|
|
1136
|
+
? (typeof column.filter === 'function'
|
|
1137
|
+
? column.filter
|
|
1138
|
+
: null) ||
|
|
1139
|
+
column.filterComponent ||
|
|
1140
|
+
getFilterComponent(column.filterType || 'text')
|
|
1141
|
+
: null;
|
|
1142
|
+
const onFilter = (value) => handleFilterChange(column.dataField, value);
|
|
1143
|
+
// Get resized column style
|
|
1144
|
+
const resizeStyle = resizable
|
|
1145
|
+
? getColumnStyle(column, columnWidths, resizable, isResizing)
|
|
1146
|
+
: {};
|
|
1147
|
+
// Render header cell with resize handle
|
|
1148
|
+
// Note: Using callback ref pattern for resize functionality
|
|
1149
|
+
const headerCellRef = (node) => {
|
|
1150
|
+
if (node && resizable) {
|
|
1151
|
+
// Store ref for resize handle
|
|
1152
|
+
const refObj = {
|
|
1153
|
+
current: node,
|
|
1154
|
+
};
|
|
1155
|
+
// Attach resize handle via DOM if needed
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
return (_jsxs(HeaderCell, { ref: headerCellRef, "$align": column.headerAlign || column.align || 'left', "$sortable": !!column.sort, "$compact": compact, "$width": resizable && columnWidths[column.dataField]
|
|
1159
|
+
? columnWidths[column.dataField]
|
|
1160
|
+
: column.width, "$minWidth": column.minWidth, "$pinned": column.pinned, "$customClass": !!column.headerClasses, className: [column.headerClasses, classNames.headerCell]
|
|
1161
|
+
.filter(Boolean)
|
|
1162
|
+
.join(' '), style: {
|
|
1163
|
+
...(typeof column.headerStyle === 'function'
|
|
1164
|
+
? column.headerStyle(column)
|
|
1165
|
+
: column.headerStyle || styles.headerCell),
|
|
1166
|
+
...resizeStyle,
|
|
1167
|
+
position: 'relative',
|
|
1168
|
+
}, role: "columnheader", "aria-sort": sort.field === column.dataField
|
|
1169
|
+
? sort.order === 'asc'
|
|
1170
|
+
? 'ascending'
|
|
1171
|
+
: sort.order === 'desc'
|
|
1172
|
+
? 'descending'
|
|
1173
|
+
: 'none'
|
|
1174
|
+
: undefined, "data-column": column.dataField, children: [(() => {
|
|
1175
|
+
// Check visibility props (default to true if not specified)
|
|
1176
|
+
const headerStyleObj = typeof column.headerStyle === 'function'
|
|
1177
|
+
? column.headerStyle(column)
|
|
1178
|
+
: column.headerStyle;
|
|
1179
|
+
// isHeaderTitle: show title (default true, false to hide)
|
|
1180
|
+
const showTitle = column.isHeaderTitle !== false &&
|
|
1181
|
+
column.hideHeaderText !== true &&
|
|
1182
|
+
!(headerStyleObj && headerStyleObj.fontSize === 0);
|
|
1183
|
+
// isHeaderFilterComp: show filter (default true)
|
|
1184
|
+
const showFilter = column.isHeaderFilterComp !== false &&
|
|
1185
|
+
shouldShowFilterRow &&
|
|
1186
|
+
hasColumnFilter &&
|
|
1187
|
+
FilterComponent;
|
|
1188
|
+
// isHeaderSort: show sort icon (default true)
|
|
1189
|
+
const showSort = column.isHeaderSort !== false && column.sort;
|
|
1190
|
+
// If no filter, show title and sort on single line
|
|
1191
|
+
if (!showFilter) {
|
|
1192
|
+
return (_jsxs("div", { style: {
|
|
1193
|
+
display: 'flex',
|
|
1194
|
+
alignItems: 'center',
|
|
1195
|
+
justifyContent: column.headerAlign || column.align || 'left',
|
|
1196
|
+
gap: 6,
|
|
1197
|
+
width: '100%',
|
|
1198
|
+
cursor: showSort ? 'pointer' : 'default',
|
|
1199
|
+
paddingRight: resizable ? 12 : 0,
|
|
1200
|
+
position: 'relative',
|
|
1201
|
+
zIndex: 2, // Above resize handle
|
|
1202
|
+
}, onClick: () => showSort && handleSortClick(column), children: [showTitle && (_jsx("span", { style: {
|
|
1203
|
+
color: 'white',
|
|
1204
|
+
fontWeight: 600,
|
|
1205
|
+
fontSize: 12,
|
|
1206
|
+
whiteSpace: 'nowrap',
|
|
1207
|
+
flex: 1,
|
|
1208
|
+
}, children: column.headerFormatter
|
|
1209
|
+
? column.headerFormatter(column, colIndex)
|
|
1210
|
+
: column.headerText || column.text })), showSort && (_jsx("div", { style: {
|
|
1211
|
+
display: 'flex',
|
|
1212
|
+
alignItems: 'center',
|
|
1213
|
+
justifyContent: 'center',
|
|
1214
|
+
flexShrink: 0,
|
|
1215
|
+
minWidth: 40,
|
|
1216
|
+
minHeight: 24,
|
|
1217
|
+
position: 'relative',
|
|
1218
|
+
overflow: 'visible',
|
|
1219
|
+
}, title: `Sort by ${column.text}`, children: column.sortCaret ? (column.sortCaret(sort.field === column.dataField
|
|
1220
|
+
? sort.order
|
|
1221
|
+
: null, column)) : (_jsx(DefaultSortCaret, { order: sort.field === column.dataField
|
|
1222
|
+
? sort.order
|
|
1223
|
+
: null, column: column })) }))] }));
|
|
1224
|
+
}
|
|
1225
|
+
// With filter: layout with filter + sort
|
|
1226
|
+
return (_jsxs("div", { style: {
|
|
1227
|
+
display: 'flex',
|
|
1228
|
+
flexDirection: 'column',
|
|
1229
|
+
gap: showTitle ? 4 : 0,
|
|
1230
|
+
width: '100%',
|
|
1231
|
+
paddingRight: resizable ? 12 : 0,
|
|
1232
|
+
position: 'relative',
|
|
1233
|
+
zIndex: 2, // Above resize handle
|
|
1234
|
+
}, children: [showTitle && (_jsx("div", { style: {
|
|
1235
|
+
display: 'flex',
|
|
1236
|
+
alignItems: 'center',
|
|
1237
|
+
justifyContent: 'space-between',
|
|
1238
|
+
gap: 4,
|
|
1239
|
+
}, children: _jsx("span", { style: {
|
|
1240
|
+
color: 'white',
|
|
1241
|
+
fontWeight: 600,
|
|
1242
|
+
fontSize: 12,
|
|
1243
|
+
whiteSpace: 'nowrap',
|
|
1244
|
+
cursor: showSort ? 'pointer' : 'default',
|
|
1245
|
+
flex: 1,
|
|
1246
|
+
}, onClick: () => showSort && handleSortClick(column), children: column.headerFormatter
|
|
1247
|
+
? column.headerFormatter(column, colIndex)
|
|
1248
|
+
: column.headerText || column.text }) })), _jsxs("div", { style: {
|
|
1249
|
+
display: 'flex',
|
|
1250
|
+
alignItems: 'center',
|
|
1251
|
+
justifyContent: 'flex-start',
|
|
1252
|
+
gap: 4,
|
|
1253
|
+
width: '100%',
|
|
1254
|
+
minHeight: 24,
|
|
1255
|
+
}, children: [_jsx("div", { style: {
|
|
1256
|
+
flex: showSort ? '0 1 auto' : 1,
|
|
1257
|
+
width: showSort
|
|
1258
|
+
? 'calc(100% - 48px)'
|
|
1259
|
+
: '100%',
|
|
1260
|
+
minWidth: 0,
|
|
1261
|
+
maxWidth: showSort
|
|
1262
|
+
? 'calc(100% - 48px)'
|
|
1263
|
+
: '100%',
|
|
1264
|
+
display: 'flex',
|
|
1265
|
+
alignItems: 'center',
|
|
1266
|
+
overflow: 'hidden',
|
|
1267
|
+
}, onClick: (e) => e.stopPropagation(), children: column.filterRenderer ? (column.filterRenderer(onFilter, column)) : (_jsx("div", { onFocusCapture: () => {
|
|
1268
|
+
focusedFilterFieldRef.current =
|
|
1269
|
+
column.dataField;
|
|
1270
|
+
}, "data-filter-wrapper": column.dataField, style: { width: '100%' }, children: _jsx(FilterComponent, { column: column, value: filters[column.dataField], onChange: onFilter, onClear: () => handleFilterChange(column.dataField, null) }, `filter-${column.dataField}`) })) }), showSort && (_jsx("div", { style: {
|
|
1271
|
+
minWidth: 40,
|
|
1272
|
+
minHeight: 24,
|
|
1273
|
+
display: 'flex',
|
|
1274
|
+
alignItems: 'center',
|
|
1275
|
+
justifyContent: 'center',
|
|
1276
|
+
flexShrink: 0,
|
|
1277
|
+
flexGrow: 0,
|
|
1278
|
+
cursor: 'pointer',
|
|
1279
|
+
marginLeft: 'auto',
|
|
1280
|
+
position: 'relative',
|
|
1281
|
+
overflow: 'visible',
|
|
1282
|
+
}, onClick: (e) => {
|
|
1283
|
+
e.stopPropagation();
|
|
1284
|
+
handleSortClick(column);
|
|
1285
|
+
}, title: `Sort by ${column.text}`, children: column.sortCaret ? (column.sortCaret(sort.field === column.dataField
|
|
1286
|
+
? sort.order
|
|
1287
|
+
: null, column)) : (_jsx(DefaultSortCaret, { order: sort.field === column.dataField
|
|
1288
|
+
? sort.order
|
|
1289
|
+
: null, column: column })) }))] })] }));
|
|
1290
|
+
})(), resizable && (_jsx("div", { style: {
|
|
1291
|
+
position: 'absolute',
|
|
1292
|
+
top: 0,
|
|
1293
|
+
right: 0,
|
|
1294
|
+
bottom: 0,
|
|
1295
|
+
width: 6,
|
|
1296
|
+
cursor: 'col-resize',
|
|
1297
|
+
zIndex: 1,
|
|
1298
|
+
display: 'flex',
|
|
1299
|
+
alignItems: 'center',
|
|
1300
|
+
justifyContent: 'center',
|
|
1301
|
+
}, onMouseDown: (e) => {
|
|
1302
|
+
e.preventDefault();
|
|
1303
|
+
e.stopPropagation();
|
|
1304
|
+
const cell = e.currentTarget
|
|
1305
|
+
.parentElement;
|
|
1306
|
+
if (cell) {
|
|
1307
|
+
const startX = e.clientX;
|
|
1308
|
+
const startWidth = cell.offsetWidth;
|
|
1309
|
+
const dataField = column.dataField;
|
|
1310
|
+
const handleMouseMove = (moveEvent) => {
|
|
1311
|
+
const deltaX = moveEvent.clientX - startX;
|
|
1312
|
+
const newWidth = Math.max(50, Math.min(800, startWidth + deltaX));
|
|
1313
|
+
// Update via CSS for smooth resize
|
|
1314
|
+
cell.style.width = `${newWidth}px`;
|
|
1315
|
+
cell.style.minWidth = `${newWidth}px`;
|
|
1316
|
+
cell.style.maxWidth = `${newWidth}px`;
|
|
1317
|
+
// Update body cells too
|
|
1318
|
+
document
|
|
1319
|
+
.querySelectorAll(`[data-column="${dataField}"]`)
|
|
1320
|
+
.forEach((el) => {
|
|
1321
|
+
el.style.width =
|
|
1322
|
+
`${newWidth}px`;
|
|
1323
|
+
el.style.minWidth =
|
|
1324
|
+
`${newWidth}px`;
|
|
1325
|
+
el.style.maxWidth =
|
|
1326
|
+
`${newWidth}px`;
|
|
1327
|
+
});
|
|
1328
|
+
};
|
|
1329
|
+
const handleMouseUp = () => {
|
|
1330
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
1331
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
1332
|
+
document.body.style.cursor = '';
|
|
1333
|
+
document.body.style.userSelect = '';
|
|
1334
|
+
// Trigger resize callback
|
|
1335
|
+
const finalWidth = cell.offsetWidth;
|
|
1336
|
+
resizeConfig?.onResizeEnd?.(dataField, finalWidth);
|
|
1337
|
+
};
|
|
1338
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
1339
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
1340
|
+
document.body.style.cursor = 'col-resize';
|
|
1341
|
+
document.body.style.userSelect = 'none';
|
|
1342
|
+
resizeConfig?.onResizeStart?.(dataField, startWidth);
|
|
1343
|
+
}
|
|
1344
|
+
}, children: _jsx("div", { style: {
|
|
1345
|
+
width: 3,
|
|
1346
|
+
height: '60%',
|
|
1347
|
+
background: 'rgba(255,255,255,0.3)',
|
|
1348
|
+
borderRadius: 2,
|
|
1349
|
+
transition: 'background 0.2s',
|
|
1350
|
+
}, onMouseEnter: (e) => {
|
|
1351
|
+
e.currentTarget.style.background =
|
|
1352
|
+
resizeConfig?.handleHoverColor || '#3b82f6';
|
|
1353
|
+
}, onMouseLeave: (e) => {
|
|
1354
|
+
e.currentTarget.style.background = 'rgba(255,255,255,0.3)';
|
|
1355
|
+
} }) }))] }, column.dataField));
|
|
1356
|
+
})] }) }), _jsx(TableBody, { className: classNames.body, style: styles.body, children: processedData.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: visibleColumns.length +
|
|
1357
|
+
(resolvedRowSelection?.mode === 'checkbox' ? 1 : 0) +
|
|
1358
|
+
(expandable ? 1 : 0) +
|
|
1359
|
+
(showRowNumber ? 1 : 0), children: _jsxs(EmptyState, { className: classNames.empty, style: styles.empty, children: [_jsx(EmptyIcon, {}), _jsx("span", { children: emptyText })] }) }) })) : (processedData.map((row, rowIndex) => {
|
|
1360
|
+
const rowKey = getRowKey(row);
|
|
1361
|
+
const rowSelected = isSelected(rowKey);
|
|
1362
|
+
const rowExpanded = isExpanded(rowKey);
|
|
1363
|
+
const checkboxProps = resolvedRowSelection?.getCheckboxProps?.(row);
|
|
1364
|
+
const isExpandable = expandable?.rowExpandable?.(row) ?? true;
|
|
1365
|
+
const rowClass = typeof rowClassName === 'function'
|
|
1366
|
+
? rowClassName(row, rowIndex)
|
|
1367
|
+
: rowClassName;
|
|
1368
|
+
const rowStyles = typeof rowStyle === 'function'
|
|
1369
|
+
? rowStyle(row, rowIndex)
|
|
1370
|
+
: rowStyle;
|
|
1371
|
+
const selectedStyle = rowSelected
|
|
1372
|
+
? typeof resolvedRowSelection?.selectedRowStyle ===
|
|
1373
|
+
'function'
|
|
1374
|
+
? resolvedRowSelection.selectedRowStyle(row)
|
|
1375
|
+
: resolvedRowSelection?.selectedRowStyle
|
|
1376
|
+
: undefined;
|
|
1377
|
+
// Check if custom selected style has a background color
|
|
1378
|
+
const hasCustomBgColor = rowSelected &&
|
|
1379
|
+
selectedStyle &&
|
|
1380
|
+
(selectedStyle.backgroundColor || selectedStyle.background);
|
|
1381
|
+
// Apply non-selectable style ONLY if row is disabled
|
|
1382
|
+
// When disabled: false or not disabled, no styles should be applied
|
|
1383
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
1384
|
+
const disabledStyle = isRowDisabled
|
|
1385
|
+
? nonSelectableStyle || {
|
|
1386
|
+
backgroundColor: '#f3f4f6',
|
|
1387
|
+
opacity: 0.7,
|
|
1388
|
+
}
|
|
1389
|
+
: undefined;
|
|
1390
|
+
return (_jsxs(React.Fragment, { children: [_jsxs(TableRow, { "$selected": rowSelected, "$clickable": !!onRowClick ||
|
|
1391
|
+
resolvedRowSelection?.mode === 'single' ||
|
|
1392
|
+
expandable?.expandRowByClick === true, "$disabled": isRowDisabled, "$hasCustomSelectedStyle": !!hasCustomBgColor, "data-custom-selected": hasCustomBgColor ? 'true' : undefined, className: `${classNames.row || ''} ${rowClass || ''} ${rowSelected
|
|
1393
|
+
? typeof resolvedRowSelection?.selectedRowClassName ===
|
|
1394
|
+
'function'
|
|
1395
|
+
? resolvedRowSelection.selectedRowClassName(row)
|
|
1396
|
+
: resolvedRowSelection?.selectedRowClassName || ''
|
|
1397
|
+
: ''}`, style: {
|
|
1398
|
+
...styles.row,
|
|
1399
|
+
...rowStyles,
|
|
1400
|
+
...selectedStyle,
|
|
1401
|
+
...disabledStyle,
|
|
1402
|
+
}, onClick: (e) => handleRowClick(row, rowIndex, e), onDoubleClick: (e) => {
|
|
1403
|
+
// Prevent double clicks ONLY on disabled rows
|
|
1404
|
+
// When disabled: false, allow normal behavior
|
|
1405
|
+
if (isRowDisabled) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
// Only trigger row-level double click if not handled by a cell
|
|
1409
|
+
// Cells handle their own double-clicks for editing
|
|
1410
|
+
onRowDoubleClick?.(row, rowIndex, e);
|
|
1411
|
+
}, role: "row", "aria-selected": rowSelected, children: [resolvedRowSelection?.mode === 'checkbox' && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, "$disabled": isRowDisabled, children: _jsx(Checkbox, { checked: rowSelected, disabled: checkboxProps?.disabled, onChange: (e) => handleCheckboxChange(row, e), onClick: (e) => e.stopPropagation() }) })), expandable && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, "$disabled": isRowDisabled, children: isExpandable && (_jsx(ExpandButton, { "$expanded": rowExpanded, onClick: (e) => handleExpandClick(row, e), children: expandable.expandIcon ? (expandable.expandIcon({
|
|
1412
|
+
expanded: rowExpanded,
|
|
1413
|
+
row,
|
|
1414
|
+
onExpand: () => toggleExpand(row),
|
|
1415
|
+
})) : (_jsx(ExpandIcon, {})) })) })), showRowNumber && (_jsx(TableCell, { "$align": "center", "$compact": compact, "$padding": cellPadding, "$disabled": isRowDisabled, style: {
|
|
1416
|
+
width: rowNumberWidth,
|
|
1417
|
+
color: '#6b7280',
|
|
1418
|
+
fontWeight: 500,
|
|
1419
|
+
}, children: rowNumberRender
|
|
1420
|
+
? rowNumberRender(rowIndex + 1, row)
|
|
1421
|
+
: rowIndex + 1 + page * pageSize })), renderColumns.map((column, colIndex) => {
|
|
1422
|
+
const cellClass = typeof column.classes === 'function'
|
|
1423
|
+
? column.classes(getNestedValue(row, column.dataField), row, rowIndex, colIndex)
|
|
1424
|
+
: column.classes;
|
|
1425
|
+
const cellStyle = typeof column.style === 'function'
|
|
1426
|
+
? column.style(getNestedValue(row, column.dataField), row, rowIndex, colIndex)
|
|
1427
|
+
: column.style;
|
|
1428
|
+
// Get resized column style for body cells
|
|
1429
|
+
const cellResizeStyle = resizable
|
|
1430
|
+
? getColumnStyle(column, columnWidths, resizable, isResizing)
|
|
1431
|
+
: {};
|
|
1432
|
+
// Check if column is editable (needed for disabled row handling)
|
|
1433
|
+
const editInfo = getCellEditableInfo(column, row, rowIndex, colIndex);
|
|
1434
|
+
// Determine if column is effectively editable:
|
|
1435
|
+
// - If rowSelection is configured AND row is disabled AND no allowed cells are provided: NOT editable (even if marked as editable)
|
|
1436
|
+
// - If rowSelection is configured AND row is disabled AND allowed cells are provided: editable only if in allowed list
|
|
1437
|
+
// - Otherwise: editable if marked as editable
|
|
1438
|
+
const isRowDisabled = !!checkboxProps?.disabled;
|
|
1439
|
+
let isEffectivelyEditable = editInfo.isEditable;
|
|
1440
|
+
// Only apply allow list logic if rowSelection is configured and row is disabled
|
|
1441
|
+
if (resolvedRowSelection && isRowDisabled) {
|
|
1442
|
+
if (!hasAllowedEditingFields) {
|
|
1443
|
+
// No allowed cells provided: disable all columns
|
|
1444
|
+
isEffectivelyEditable = false;
|
|
1445
|
+
}
|
|
1446
|
+
else {
|
|
1447
|
+
// Allowed cells provided: only those columns are editable
|
|
1448
|
+
const isAllowed = isFieldAllowedForDisabledRow(column.dataField);
|
|
1449
|
+
isEffectivelyEditable = isAllowed;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
// Check if column is in allowed list (for styling purposes)
|
|
1453
|
+
const isInAllowedCells = !!(resolvedRowSelection &&
|
|
1454
|
+
isRowDisabled &&
|
|
1455
|
+
hasAllowedEditingFields &&
|
|
1456
|
+
isFieldAllowedForDisabledRow(column.dataField));
|
|
1457
|
+
const cellContent = (() => {
|
|
1458
|
+
if (isEffectivelyEditable && editMode !== 'none') {
|
|
1459
|
+
// Check for custom editor
|
|
1460
|
+
if (editInfo.customEditor) {
|
|
1461
|
+
return editInfo.customEditor;
|
|
1462
|
+
}
|
|
1463
|
+
return (_jsx(EditableCell, { "$editing": editingCell?.row === rowIndex &&
|
|
1464
|
+
editingCell?.field === column.dataField, "$showEditIcon": showEditIcon, children: renderCellContent(row, column, rowIndex, colIndex) }));
|
|
1465
|
+
}
|
|
1466
|
+
return renderCellContent(row, column, rowIndex, colIndex);
|
|
1467
|
+
})();
|
|
1468
|
+
return (_jsx(TableCell, { "$align": column.align || 'left', "$compact": compact, "$padding": cellPadding, "$pinned": column.pinned, "$hasCustomClass": !!cellClass, "$disabled": isRowDisabled, "$isEditable": isEffectivelyEditable, "$isInAllowedCells": isInAllowedCells, className: cellClass || classNames.cell, style: {
|
|
1469
|
+
...styles.cell,
|
|
1470
|
+
...cellStyle,
|
|
1471
|
+
...cellResizeStyle,
|
|
1472
|
+
}, "data-column": column.dataField, onClick: (e) => handleCellClick(row, rowIndex, column, colIndex, e), onDoubleClick: (e) => {
|
|
1473
|
+
e.stopPropagation(); // Prevent row-level double-click from interfering
|
|
1474
|
+
handleCellDoubleClick(row, rowIndex, column, colIndex, e);
|
|
1475
|
+
}, role: "gridcell", children: _jsx(TableCellContent, { "$hasFormatter": !!column.formatter, children: cellContent }) }, column.dataField));
|
|
1476
|
+
})] }), expandable && rowExpanded && isExpandable && (_jsx(ExpandedRow, { children: _jsx(ExpandedCell, { colSpan: visibleColumns.length +
|
|
1477
|
+
(resolvedRowSelection?.mode === 'checkbox'
|
|
1478
|
+
? 1
|
|
1479
|
+
: 0) +
|
|
1480
|
+
(expandable ? 1 : 0) +
|
|
1481
|
+
(showRowNumber ? 1 : 0), children: expandable.expandedRowRender?.(row, rowIndex, rowExpanded) }) }))] }, rowKey));
|
|
1482
|
+
})) }), showFooter && (_jsx(TableFooter, { className: classNames.footer, style: styles.footer, children: _jsxs(FooterRow, { className: classNames.footerRow, style: styles.footerRow, children: [resolvedRowSelection?.mode === 'checkbox' && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), expandable && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), showRowNumber && (_jsx(FooterCell, { "$align": "center", "$compact": compact })), renderColumns.map((column) => (_jsx(FooterCell, { "$align": column.align || 'left', "$compact": compact, className: classNames.footerCell, style: styles.footerCell, children: typeof column.footer === 'function'
|
|
1483
|
+
? column.footer(column, data)
|
|
1484
|
+
: column.footerFormatter
|
|
1485
|
+
? column.footerFormatter(column, data)
|
|
1486
|
+
: column.footer }, column.dataField)))] }) }))] }) }), renderPagination()] }));
|
|
1487
|
+
});
|
|
1488
|
+
Table.displayName = 'Table';
|
|
1489
|
+
export default Table;
|