@akshar-technosoft/ui 1.0.25 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +538 -215
- package/dist/components/date-helper.cjs.map +1 -1
- package/dist/components/date-helper.d.cts +36 -0
- package/dist/components/date-helper.d.ts +36 -0
- package/dist/components/date-helper.js.map +1 -1
- package/dist/components/general.cjs +1 -1
- package/dist/components/general.cjs.map +1 -1
- package/dist/components/general.d.cts +25 -0
- package/dist/components/general.d.ts +25 -0
- package/dist/components/general.js +1 -1
- package/dist/components/general.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +817 -28
- package/dist/index.d.ts +817 -28
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.cjs.map +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/package.json +94 -87
- package/dist/components/core/error.cjs +0 -3
- package/dist/components/core/error.cjs.map +0 -1
- package/dist/components/core/error.d.cts +0 -5
- package/dist/components/core/error.d.ts +0 -5
- package/dist/components/core/error.js +0 -3
- package/dist/components/core/error.js.map +0 -1
- package/dist/components/core/event-success.cjs +0 -3
- package/dist/components/core/event-success.cjs.map +0 -1
- package/dist/components/core/event-success.d.cts +0 -5
- package/dist/components/core/event-success.d.ts +0 -5
- package/dist/components/core/event-success.js +0 -3
- package/dist/components/core/event-success.js.map +0 -1
- package/dist/components/core/index.cjs +0 -3
- package/dist/components/core/index.cjs.map +0 -1
- package/dist/components/core/index.d.cts +0 -7
- package/dist/components/core/index.d.ts +0 -7
- package/dist/components/core/index.js +0 -3
- package/dist/components/core/index.js.map +0 -1
- package/dist/components/core/loader.cjs +0 -3
- package/dist/components/core/loader.cjs.map +0 -1
- package/dist/components/core/loader.d.cts +0 -5
- package/dist/components/core/loader.d.ts +0 -5
- package/dist/components/core/loader.js +0 -3
- package/dist/components/core/loader.js.map +0 -1
- package/dist/components/core/notfound.cjs +0 -3
- package/dist/components/core/notfound.cjs.map +0 -1
- package/dist/components/core/notfound.d.cts +0 -5
- package/dist/components/core/notfound.d.ts +0 -5
- package/dist/components/core/notfound.js +0 -3
- package/dist/components/core/notfound.js.map +0 -1
- package/dist/components/core/offline-content.cjs +0 -3
- package/dist/components/core/offline-content.cjs.map +0 -1
- package/dist/components/core/offline-content.d.cts +0 -5
- package/dist/components/core/offline-content.d.ts +0 -5
- package/dist/components/core/offline-content.js +0 -3
- package/dist/components/core/offline-content.js.map +0 -1
- package/dist/components/core/unauthorized.cjs +0 -3
- package/dist/components/core/unauthorized.cjs.map +0 -1
- package/dist/components/core/unauthorized.d.cts +0 -5
- package/dist/components/core/unauthorized.d.ts +0 -5
- package/dist/components/core/unauthorized.js +0 -3
- package/dist/components/core/unauthorized.js.map +0 -1
- package/dist/components/data/data-table/data-table-action-bar.cjs +0 -3
- package/dist/components/data/data-table/data-table-action-bar.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-action-bar.d.cts +0 -26
- package/dist/components/data/data-table/data-table-action-bar.d.ts +0 -26
- package/dist/components/data/data-table/data-table-action-bar.js +0 -3
- package/dist/components/data/data-table/data-table-action-bar.js.map +0 -1
- package/dist/components/data/data-table/data-table-column-header.cjs +0 -3
- package/dist/components/data/data-table/data-table-column-header.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-column-header.d.cts +0 -11
- package/dist/components/data/data-table/data-table-column-header.d.ts +0 -11
- package/dist/components/data/data-table/data-table-column-header.js +0 -3
- package/dist/components/data/data-table/data-table-column-header.js.map +0 -1
- package/dist/components/data/data-table/data-table-faceted-filter.cjs +0 -3
- package/dist/components/data/data-table/data-table-faceted-filter.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-faceted-filter.d.cts +0 -18
- package/dist/components/data/data-table/data-table-faceted-filter.d.ts +0 -18
- package/dist/components/data/data-table/data-table-faceted-filter.js +0 -3
- package/dist/components/data/data-table/data-table-faceted-filter.js.map +0 -1
- package/dist/components/data/data-table/data-table-pagination.cjs +0 -3
- package/dist/components/data/data-table/data-table-pagination.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-pagination.d.cts +0 -12
- package/dist/components/data/data-table/data-table-pagination.d.ts +0 -12
- package/dist/components/data/data-table/data-table-pagination.js +0 -3
- package/dist/components/data/data-table/data-table-pagination.js.map +0 -1
- package/dist/components/data/data-table/data-table-toolbar.cjs +0 -3
- package/dist/components/data/data-table/data-table-toolbar.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-toolbar.d.cts +0 -30
- package/dist/components/data/data-table/data-table-toolbar.d.ts +0 -30
- package/dist/components/data/data-table/data-table-toolbar.js +0 -3
- package/dist/components/data/data-table/data-table-toolbar.js.map +0 -1
- package/dist/components/data/data-table/data-table-types.cjs +0 -3
- package/dist/components/data/data-table/data-table-types.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-types.d.cts +0 -120
- package/dist/components/data/data-table/data-table-types.d.ts +0 -120
- package/dist/components/data/data-table/data-table-types.js +0 -2
- package/dist/components/data/data-table/data-table-types.js.map +0 -1
- package/dist/components/data/data-table/data-table-view-options.cjs +0 -3
- package/dist/components/data/data-table/data-table-view-options.cjs.map +0 -1
- package/dist/components/data/data-table/data-table-view-options.d.cts +0 -9
- package/dist/components/data/data-table/data-table-view-options.d.ts +0 -9
- package/dist/components/data/data-table/data-table-view-options.js +0 -3
- package/dist/components/data/data-table/data-table-view-options.js.map +0 -1
- package/dist/components/data/data-table/data-table.cjs +0 -3
- package/dist/components/data/data-table/data-table.cjs.map +0 -1
- package/dist/components/data/data-table/data-table.d.cts +0 -8
- package/dist/components/data/data-table/data-table.d.ts +0 -8
- package/dist/components/data/data-table/data-table.js +0 -3
- package/dist/components/data/data-table/data-table.js.map +0 -1
- package/dist/components/data/data-table/index.cjs +0 -3
- package/dist/components/data/data-table/index.cjs.map +0 -1
- package/dist/components/data/data-table/index.d.cts +0 -16
- package/dist/components/data/data-table/index.d.ts +0 -16
- package/dist/components/data/data-table/index.js +0 -3
- package/dist/components/data/data-table/index.js.map +0 -1
- package/dist/components/data/data-template/data-template-action-bar.cjs +0 -3
- package/dist/components/data/data-template/data-template-action-bar.cjs.map +0 -1
- package/dist/components/data/data-template/data-template-action-bar.d.cts +0 -14
- package/dist/components/data/data-template/data-template-action-bar.d.ts +0 -14
- package/dist/components/data/data-template/data-template-action-bar.js +0 -3
- package/dist/components/data/data-template/data-template-action-bar.js.map +0 -1
- package/dist/components/data/data-template/data-template-pagination.cjs +0 -3
- package/dist/components/data/data-template/data-template-pagination.cjs.map +0 -1
- package/dist/components/data/data-template/data-template-pagination.d.cts +0 -17
- package/dist/components/data/data-template/data-template-pagination.d.ts +0 -17
- package/dist/components/data/data-template/data-template-pagination.js +0 -3
- package/dist/components/data/data-template/data-template-pagination.js.map +0 -1
- package/dist/components/data/data-template/data-template-toolbar.cjs +0 -3
- package/dist/components/data/data-template/data-template-toolbar.cjs.map +0 -1
- package/dist/components/data/data-template/data-template-toolbar.d.cts +0 -27
- package/dist/components/data/data-template/data-template-toolbar.d.ts +0 -27
- package/dist/components/data/data-template/data-template-toolbar.js +0 -3
- package/dist/components/data/data-template/data-template-toolbar.js.map +0 -1
- package/dist/components/data/data-template/data-template-types.cjs +0 -3
- package/dist/components/data/data-template/data-template-types.cjs.map +0 -1
- package/dist/components/data/data-template/data-template-types.d.cts +0 -107
- package/dist/components/data/data-template/data-template-types.d.ts +0 -107
- package/dist/components/data/data-template/data-template-types.js +0 -2
- package/dist/components/data/data-template/data-template-types.js.map +0 -1
- package/dist/components/data/data-template/data-template.cjs +0 -3
- package/dist/components/data/data-template/data-template.cjs.map +0 -1
- package/dist/components/data/data-template/data-template.d.cts +0 -8
- package/dist/components/data/data-template/data-template.d.ts +0 -8
- package/dist/components/data/data-template/data-template.js +0 -3
- package/dist/components/data/data-template/data-template.js.map +0 -1
- package/dist/components/data/data-template/index.cjs +0 -3
- package/dist/components/data/data-template/index.cjs.map +0 -1
- package/dist/components/data/data-template/index.d.cts +0 -8
- package/dist/components/data/data-template/index.d.ts +0 -8
- package/dist/components/data/data-template/index.js +0 -3
- package/dist/components/data/data-template/index.js.map +0 -1
- package/dist/components/helper/date-filter.cjs +0 -3
- package/dist/components/helper/date-filter.cjs.map +0 -1
- package/dist/components/helper/date-filter.d.cts +0 -14
- package/dist/components/helper/date-filter.d.ts +0 -14
- package/dist/components/helper/date-filter.js +0 -3
- package/dist/components/helper/date-filter.js.map +0 -1
- package/dist/components/layouts/app-container.cjs +0 -3
- package/dist/components/layouts/app-container.cjs.map +0 -1
- package/dist/components/layouts/app-container.d.cts +0 -13
- package/dist/components/layouts/app-container.d.ts +0 -13
- package/dist/components/layouts/app-container.js +0 -3
- package/dist/components/layouts/app-container.js.map +0 -1
- package/dist/components/layouts/app-content.cjs +0 -3
- package/dist/components/layouts/app-content.cjs.map +0 -1
- package/dist/components/layouts/app-content.d.cts +0 -45
- package/dist/components/layouts/app-content.d.ts +0 -45
- package/dist/components/layouts/app-content.js +0 -3
- package/dist/components/layouts/app-content.js.map +0 -1
- package/dist/components/layouts/app-footer.cjs +0 -3
- package/dist/components/layouts/app-footer.cjs.map +0 -1
- package/dist/components/layouts/app-footer.d.cts +0 -18
- package/dist/components/layouts/app-footer.d.ts +0 -18
- package/dist/components/layouts/app-footer.js +0 -3
- package/dist/components/layouts/app-footer.js.map +0 -1
- package/dist/components/layouts/app-header.cjs +0 -3
- package/dist/components/layouts/app-header.cjs.map +0 -1
- package/dist/components/layouts/app-header.d.cts +0 -19
- package/dist/components/layouts/app-header.d.ts +0 -19
- package/dist/components/layouts/app-header.js +0 -3
- package/dist/components/layouts/app-header.js.map +0 -1
- package/dist/components/layouts/factories.cjs +0 -3
- package/dist/components/layouts/factories.cjs.map +0 -1
- package/dist/components/layouts/factories.d.cts +0 -18
- package/dist/components/layouts/factories.d.ts +0 -18
- package/dist/components/layouts/factories.js +0 -3
- package/dist/components/layouts/factories.js.map +0 -1
- package/dist/components/layouts/index.cjs +0 -3
- package/dist/components/layouts/index.cjs.map +0 -1
- package/dist/components/layouts/index.d.cts +0 -8
- package/dist/components/layouts/index.d.ts +0 -8
- package/dist/components/layouts/index.js +0 -3
- package/dist/components/layouts/index.js.map +0 -1
- package/dist/components/ui/badge.cjs +0 -3
- package/dist/components/ui/badge.cjs.map +0 -1
- package/dist/components/ui/badge.d.cts +0 -13
- package/dist/components/ui/badge.d.ts +0 -13
- package/dist/components/ui/badge.js +0 -3
- package/dist/components/ui/badge.js.map +0 -1
- package/dist/components/ui/button.cjs +0 -3
- package/dist/components/ui/button.cjs.map +0 -1
- package/dist/components/ui/button.d.cts +0 -14
- package/dist/components/ui/button.d.ts +0 -14
- package/dist/components/ui/button.js +0 -3
- package/dist/components/ui/button.js.map +0 -1
- package/dist/components/ui/calendar.cjs +0 -3
- package/dist/components/ui/calendar.cjs.map +0 -1
- package/dist/components/ui/calendar.d.cts +0 -13
- package/dist/components/ui/calendar.d.ts +0 -13
- package/dist/components/ui/calendar.js +0 -3
- package/dist/components/ui/calendar.js.map +0 -1
- package/dist/components/ui/card.cjs +0 -3
- package/dist/components/ui/card.cjs.map +0 -1
- package/dist/components/ui/card.d.cts +0 -12
- package/dist/components/ui/card.d.ts +0 -12
- package/dist/components/ui/card.js +0 -3
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/checkbox.cjs +0 -3
- package/dist/components/ui/checkbox.cjs.map +0 -1
- package/dist/components/ui/checkbox.d.cts +0 -7
- package/dist/components/ui/checkbox.d.ts +0 -7
- package/dist/components/ui/checkbox.js +0 -3
- package/dist/components/ui/checkbox.js.map +0 -1
- package/dist/components/ui/command.cjs +0 -3
- package/dist/components/ui/command.cjs.map +0 -1
- package/dist/components/ui/command.d.cts +0 -20
- package/dist/components/ui/command.d.ts +0 -20
- package/dist/components/ui/command.js +0 -3
- package/dist/components/ui/command.js.map +0 -1
- package/dist/components/ui/dialog.cjs +0 -3
- package/dist/components/ui/dialog.cjs.map +0 -1
- package/dist/components/ui/dialog.d.cts +0 -16
- package/dist/components/ui/dialog.d.ts +0 -16
- package/dist/components/ui/dialog.js +0 -3
- package/dist/components/ui/dialog.js.map +0 -1
- package/dist/components/ui/dropdown-menu.cjs +0 -3
- package/dist/components/ui/dropdown-menu.cjs.map +0 -1
- package/dist/components/ui/dropdown-menu.d.cts +0 -28
- package/dist/components/ui/dropdown-menu.d.ts +0 -28
- package/dist/components/ui/dropdown-menu.js +0 -3
- package/dist/components/ui/dropdown-menu.js.map +0 -1
- package/dist/components/ui/input.cjs +0 -3
- package/dist/components/ui/input.cjs.map +0 -1
- package/dist/components/ui/input.d.cts +0 -6
- package/dist/components/ui/input.d.ts +0 -6
- package/dist/components/ui/input.js +0 -3
- package/dist/components/ui/input.js.map +0 -1
- package/dist/components/ui/popover.cjs +0 -3
- package/dist/components/ui/popover.cjs.map +0 -1
- package/dist/components/ui/popover.d.cts +0 -10
- package/dist/components/ui/popover.d.ts +0 -10
- package/dist/components/ui/popover.js +0 -3
- package/dist/components/ui/popover.js.map +0 -1
- package/dist/components/ui/select.cjs +0 -3
- package/dist/components/ui/select.cjs.map +0 -1
- package/dist/components/ui/select.d.cts +0 -18
- package/dist/components/ui/select.d.ts +0 -18
- package/dist/components/ui/select.js +0 -3
- package/dist/components/ui/select.js.map +0 -1
- package/dist/components/ui/separator.cjs +0 -3
- package/dist/components/ui/separator.cjs.map +0 -1
- package/dist/components/ui/separator.d.cts +0 -7
- package/dist/components/ui/separator.d.ts +0 -7
- package/dist/components/ui/separator.js +0 -3
- package/dist/components/ui/separator.js.map +0 -1
- package/dist/components/ui/sheet.cjs +0 -3
- package/dist/components/ui/sheet.cjs.map +0 -1
- package/dist/components/ui/sheet.d.cts +0 -18
- package/dist/components/ui/sheet.d.ts +0 -18
- package/dist/components/ui/sheet.js +0 -3
- package/dist/components/ui/sheet.js.map +0 -1
- package/dist/components/ui/table.cjs +0 -3
- package/dist/components/ui/table.cjs.map +0 -1
- package/dist/components/ui/table.d.cts +0 -13
- package/dist/components/ui/table.d.ts +0 -13
- package/dist/components/ui/table.js +0 -3
- package/dist/components/ui/table.js.map +0 -1
- package/dist/components/ui/toggle.cjs +0 -3
- package/dist/components/ui/toggle.cjs.map +0 -1
- package/dist/components/ui/toggle.d.cts +0 -16
- package/dist/components/ui/toggle.d.ts +0 -16
- package/dist/components/ui/toggle.js +0 -3
- package/dist/components/ui/toggle.js.map +0 -1
- package/dist/components/ui/tooltip.cjs +0 -3
- package/dist/components/ui/tooltip.cjs.map +0 -1
- package/dist/components/ui/tooltip.d.cts +0 -10
- package/dist/components/ui/tooltip.d.ts +0 -10
- package/dist/components/ui/tooltip.js +0 -3
- package/dist/components/ui/tooltip.js.map +0 -1
- package/dist/context/app-meta/context.cjs +0 -3
- package/dist/context/app-meta/context.cjs.map +0 -1
- package/dist/context/app-meta/context.d.cts +0 -18
- package/dist/context/app-meta/context.d.ts +0 -18
- package/dist/context/app-meta/context.js +0 -3
- package/dist/context/app-meta/context.js.map +0 -1
- package/dist/context/app-meta/hooks.cjs +0 -3
- package/dist/context/app-meta/hooks.cjs.map +0 -1
- package/dist/context/app-meta/hooks.d.cts +0 -10
- package/dist/context/app-meta/hooks.d.ts +0 -10
- package/dist/context/app-meta/hooks.js +0 -3
- package/dist/context/app-meta/hooks.js.map +0 -1
- package/dist/context/app-meta/index.cjs +0 -3
- package/dist/context/app-meta/index.cjs.map +0 -1
- package/dist/context/app-meta/index.d.cts +0 -5
- package/dist/context/app-meta/index.d.ts +0 -5
- package/dist/context/app-meta/index.js +0 -3
- package/dist/context/app-meta/index.js.map +0 -1
- package/dist/context/app-meta/types.cjs +0 -3
- package/dist/context/app-meta/types.cjs.map +0 -1
- package/dist/context/app-meta/types.d.cts +0 -48
- package/dist/context/app-meta/types.d.ts +0 -48
- package/dist/context/app-meta/types.js +0 -2
- package/dist/context/app-meta/types.js.map +0 -1
- package/dist/context/index.cjs +0 -3
- package/dist/context/index.cjs.map +0 -1
- package/dist/context/index.d.cts +0 -5
- package/dist/context/index.d.ts +0 -5
- package/dist/context/index.js +0 -3
- package/dist/context/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,215 +1,538 @@
|
|
|
1
|
-
# @akshar-technosoft/ui
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
###
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
type
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
1
|
+
# @akshar-technosoft/ui
|
|
2
|
+
|
|
3
|
+
Type-safe React component library for data-heavy ERP screens: a full-featured `DataTable`, a card/grid `DataTemplate`, a composable page-layout system and utility components. Built on TypeScript, Tailwind CSS v4, TanStack Table v8 and Radix.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @akshar-technosoft/ui
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Colors ride the app's theme CSS variables (`--sidebar`, `--border`, `--background`…), so the library reskins with the app theme automatically. The consuming app's Tailwind must scan this package (via `@source` or content config) so the classes compile.
|
|
10
|
+
|
|
11
|
+
## Exports at a glance
|
|
12
|
+
|
|
13
|
+
| Export | What it is |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `DataTable`, `DataTableProps`, `GroupColumnDef` | The data table and its types |
|
|
16
|
+
| `DataTableActionBar`, `DataTableActionBarAction`, `DataTableActionBarSelection` | Floating bulk-action bar for selected rows |
|
|
17
|
+
| `getTableExportView`, `TableExportView`, `TableExportColumn` | Export snapshot builder (see [Export](#export)) |
|
|
18
|
+
| `readPersistedExternal`, `PersistConfig`, `PersistGroupRegistry` | Persist helpers (see [Persist](#persist)) |
|
|
19
|
+
| `DataTemplate`, `DataTemplateProps` + action-bar components | Card/grid sibling of DataTable |
|
|
20
|
+
| `AppContainer`, `AppHeader`, `AppContent`, `AppContentHeader`, `AppContentFooter`, `AppSheet`, `AppFooter` | Page layout system |
|
|
21
|
+
| `GeneralHelper` | Static utils: `formatDate`, `formatINR`, `toProperCase`, `copyToClipboard`, `CopyToClipboard`, `StatusBadge` |
|
|
22
|
+
| `Loader`, `ErrorComponent`, `NotFound`, `Unauthorized`, `OfflineUI`, `CurrencyTransfer` | Full-area state screens |
|
|
23
|
+
|
|
24
|
+
The JSDoc in `data-table-types.ts` is the authoritative per-prop reference; hover any prop in the IDE. This README explains how the pieces fit and the recipes that aren't obvious from types.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# DataTable
|
|
29
|
+
|
|
30
|
+
A client-side table: hand it `data`, it filters/sorts/paginates in memory. Server-side filtering is opt-in per filter (see [External filters](#external-server-filters)). Everything is plain props — no context, no provider.
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<DataTable
|
|
36
|
+
data={items}
|
|
37
|
+
columns={columns}
|
|
38
|
+
settings={{ showToolbar: true }}
|
|
39
|
+
pagination={{}}
|
|
40
|
+
filters={[{ key: "Status", type: "select", placeholder: "Status", options: statusOptions }]}
|
|
41
|
+
getRowId={(row) => String(row.Code)}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Columns
|
|
46
|
+
|
|
47
|
+
Columns are TanStack `ColumnDef`s plus extras (`GroupColumnDef`). The three identity fields, and when each is needed:
|
|
48
|
+
|
|
49
|
+
| Field | What it does | When you need it |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `accessorKey` | Points at a data field (dot paths like `"Party.Name"` work). Becomes the column id AND the value source for sorting, filtering, global search and export. | The normal case: the column shows one field. |
|
|
52
|
+
| `accessorFn` | Computes the column's value from the whole row. | The cell renders a composite (several fields together) but sorting / global search / export should still see it. |
|
|
53
|
+
| `id` | Explicit identity string. | Required when there is no `accessorKey` (display-only or `accessorFn` columns). It's what filters, aggregations and the Columns menu reference. |
|
|
54
|
+
|
|
55
|
+
`cell` controls **rendering only**. A column with just `id` + `cell` (an actions column, a JSX-composed cell) is invisible to sorting, global search and export — right for actions, usually wrong for composite data cells.
|
|
56
|
+
|
|
57
|
+
**Recipe — composite cell that global search can find.** A cell printing `LotNo`, `SKU` and `Category` together: give the column an `accessorFn` joining them. No filter config needed — global search matches accessor values.
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
{
|
|
61
|
+
id: "lotInfo",
|
|
62
|
+
accessorFn: (row) => `${row.LotNo} ${row.SKU} ${row.Category}`,
|
|
63
|
+
header: "Lot / SKU",
|
|
64
|
+
cell: ({ row }) => <LotCell data={row.original} />,
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Extras on `GroupColumnDef`:
|
|
69
|
+
|
|
70
|
+
- `headerAlign: 'left' | 'center' | 'right'` — header alignment (body cell alignment is your `cell`'s business).
|
|
71
|
+
- `columns: [...]` — nested columns under a grouped header row.
|
|
72
|
+
- `enablePinning: false` — remove this column from the pin menu.
|
|
73
|
+
- `customFooter: { content, align, className }` — a custom footer cell; `content` may be `(table) => ReactNode`. Beats the column's aggregation display.
|
|
74
|
+
- `exportValue` / `exportHeader` — see [Export](#export).
|
|
75
|
+
- `size` — fixed width in px; without it the column auto-sizes. Columns/Aggregations menus derive display names from the column id (`Party_Name` → "Party Name").
|
|
76
|
+
|
|
77
|
+
## Sorting
|
|
78
|
+
|
|
79
|
+
On by default (`enableSorting`). Clicking a sortable header cycles asc → desc → clear; the header's `⋯` menu offers Sort Ascending / Sort Descending / Clear Sort explicitly (the active one disabled). The active direction shows as an arrow at the header's right edge; the `⋯` button and a faint sort hint appear on hover in a gradient overlay (no space is reserved, no text shifts). Clicks on interactive elements inside custom JSX headers do not sort. The serial "No." column sorts by display index — rarely meaningful.
|
|
80
|
+
|
|
81
|
+
## Filters — the full story
|
|
82
|
+
|
|
83
|
+
The `filters` prop renders toolbar controls. **Filters live in the toolbar, so nothing renders without `settings.showToolbar: true`** (a dev warning fires) — the most common "my filter is missing" cause.
|
|
84
|
+
|
|
85
|
+
A filter takes one of two shapes:
|
|
86
|
+
|
|
87
|
+
### 1. Path filter — `key` (the common case)
|
|
88
|
+
|
|
89
|
+
`key` is a **dot path into the row data** (validated against your row type). It is NOT a column id, although the two often coincide. What happens depends on whether a column already owns that path:
|
|
90
|
+
|
|
91
|
+
- A column with the same `accessorKey` exists → the filter drives that column. Zero extra setup.
|
|
92
|
+
- No column owns the path → the table **auto-generates a hidden filter-only column** for it. You never touch `columns`.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
filters={[
|
|
96
|
+
{ key: "PartyDetails.Name", placeholder: "Party" }, // text contains (default)
|
|
97
|
+
{ key: "Status", type: "select", placeholder: "Status", options },
|
|
98
|
+
{ key: "Date", type: "daterange", placeholder: "Date", externalSearch: true },
|
|
99
|
+
]}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Hidden filter-only column internals (why they're free): they never render a cell (no render cost), do work only while their filter holds a value, are excluded from global search (no matches on data the user can't see) and from the Columns menu.
|
|
103
|
+
|
|
104
|
+
### 2. Custom filter — `id` + `filterFn`
|
|
105
|
+
|
|
106
|
+
When the match is not a plain contains on one field — a cell holding an **array of objects**, or one control matching **across several fields** — you own the predicate. `filterFn(row, value)` receives the full row original and returns whether it passes. `id` is any unique string (need not be a real field). It also rides a hidden filter-only column and AND-combines with everything else.
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
{
|
|
110
|
+
id: "lotNo", type: "text", placeholder: "Lot No",
|
|
111
|
+
filterFn: (row, v) =>
|
|
112
|
+
row.OrderCodeJson.some(l => String(l.LotNo).toLowerCase().includes(String(v).toLowerCase())),
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Recipe — one cell, two different filters
|
|
117
|
+
|
|
118
|
+
A cell shows Party and City together; you want independent Party and City filters. The cell is one column, but filters target **data paths**, not columns — declare two filters and you're done:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
filters={[
|
|
122
|
+
{ key: "Party.Name", placeholder: "Party" },
|
|
123
|
+
{ key: "Party.City", placeholder: "City" },
|
|
124
|
+
]}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Each rides its own hidden filter-only column (or a real column if one owns the path). They AND-combine. The visible cell is untouched. If the cell should ALSO match in global search, that's the separate `accessorFn` recipe under [Columns](#columns).
|
|
128
|
+
|
|
129
|
+
### Required vs optional
|
|
130
|
+
|
|
131
|
+
Required: `placeholder`, plus either `key` (path filter) or `id` + `filterFn` (custom filter). Everything else defaults:
|
|
132
|
+
|
|
133
|
+
| Field | Default | Notes |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `type` | `"text"` | `text` (case-insensitive contains) · `select` (needs `options`, matched exactly) · `date` / `daterange` (picker, `dateFormat` for display) · `number` |
|
|
136
|
+
| `placement` | `"bar"` | `"menu"` collapses the control into the global search's field picker; while active it shows a removable chip (`settings.showFilterChips`) |
|
|
137
|
+
| `externalSearch` | `false` | Run on the server instead (below) |
|
|
138
|
+
| `width`, `icon` | — | Cosmetic (width = Tailwind class on the control wrapper) |
|
|
139
|
+
| `shared`, `persist` | — / `true` | See [Persist](#persist) |
|
|
140
|
+
|
|
141
|
+
### External (server) filters
|
|
142
|
+
|
|
143
|
+
`externalSearch: true` = the value is **never applied to in-memory rows**; all staged external values are handed to `onExternalSearch(values)` so you re-query the API. Commit points are the control's natural ones: `select` fires on pick, `date`/`daterange` on Apply, `text` after a 500ms debounce. `values` is a map keyed by filter identity (`key`/`id`).
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
onExternalSearch={(values) => setSearchFilters(values)} // feed your query params
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Why one table-level callback and not per-filter?** A server query is ONE request carrying all params. Every commit hands you the **complete staged map** — with two external filters (say `Date` and `PartyName`), picking a date fires `{ Date: {...} }`, then typing a party fires `{ Date: {...}, PartyName: "xy" }`: both values together, every time. The page builds params in one place and runs one query; any number of external filters just adds keys to the same map. Clearing fires `{}`.
|
|
150
|
+
|
|
151
|
+
Local and external filters mix freely on one table: external narrows what you fetch, local narrows the fetched rows.
|
|
152
|
+
|
|
153
|
+
### Global search & the field picker
|
|
154
|
+
|
|
155
|
+
`enableGlobalFilter` (default on) renders the search box. It matches **accessor columns only** — a `cell`-only column is invisible to it (see the `accessorFn` recipe). It needs `enableFiltering` (the engine) to actually remove rows.
|
|
156
|
+
|
|
157
|
+
When any filter has `placement: 'menu'`, a **field picker** appears on the search box automatically: "All Fields" plus each menu filter. Picking a field swaps the free-text box for that filter's native typed control (select/date/etc.) and clears the free text so the two don't stack. `settings.groupedFilterLabel` renames the "all" label. Menu-placement filters with `enableGlobalFilter` off are unreachable (dev warning).
|
|
158
|
+
|
|
159
|
+
### Clearing
|
|
160
|
+
|
|
161
|
+
A ghost "Clear Filters" button appears next to the controls whenever anything filters rows (column filters, global search, staged external values); the Settings menu has the same action. Clearing resets local filters, global search text, external values, the field picker AND the persisted snapshot (including this table's shared slots).
|
|
162
|
+
|
|
163
|
+
## Pagination
|
|
164
|
+
|
|
165
|
+
The `pagination` prop's **presence enables it** — `{}` for defaults, omit to render all rows.
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
pagination={{ pageSize: 25, pageSizeOptions: [10, 25, 50, -1], showPageNumbers: true }}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Defaults: `pageSize: 10`, `pageSizeOptions: [10, 25, 50, 100, -1]`. `-1` renders "All"; `[]` hides the size selector. `showInfo` (default true) prints "Showing X to Y of Z". `showPageNumbers` (default false) adds numbered buttons with an ellipsis window; otherwise prev/next only.
|
|
172
|
+
|
|
173
|
+
## Selection
|
|
174
|
+
|
|
175
|
+
`enableRowSelection` (default on) adds the leading checkbox column.
|
|
176
|
+
|
|
177
|
+
- `selectionMode: "multiple"` (default) — checkboxes + a select-all header checkbox (indeterminate when partial; `enableHeaderCheckbox: false` greys it while per-row stays usable). `"single"` — radio, whole row clickable, previous selection cleared; `showCheckbox: false` hides the radio but keeps the row clickable.
|
|
178
|
+
- `isRowSelectable={(row) => boolean}` — failing rows grey out, select-all skips them, `onRowSelectionChange` never reports them.
|
|
179
|
+
- `onRowSelectionChange={(rows) => …}` — selected row originals on every change.
|
|
180
|
+
- `defaultSelectedRows={(row) => boolean}` — uncontrolled prefill, seeded once after the first non-empty data load, selectable rows only; re-seed by remounting with a React `key`.
|
|
181
|
+
|
|
182
|
+
**`getRowId` — read this if selection ever "moves" to the wrong rows.** Without it, selection is keyed by array index: any refetch/reorder/insert makes index 2 a different record, and the wrong rows light up. Point it at your record's identity — required for reliable `defaultSelectedRows` too:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
getRowId={(row) => String(row.Code)}
|
|
186
|
+
getRowId={(row) => `${row.Code}-${row.Type}`} // unique only as a pair
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Bulk actions on selected rows — the action bar via the render-prop. It portals to `document.body`, floats bottom-center, auto-shows while anything is selected, and Escape clears the selection:
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
<DataTable ...>
|
|
193
|
+
{(table) => (
|
|
194
|
+
<DataTableActionBar table={table}>
|
|
195
|
+
<DataTableActionBarSelection table={table} /> {/* "N selected" + clear */}
|
|
196
|
+
<DataTableActionBarAction tooltip="Issue" isPending={busy} onClick={...}>
|
|
197
|
+
Issue
|
|
198
|
+
</DataTableActionBarAction>
|
|
199
|
+
</DataTableActionBar>
|
|
200
|
+
)}
|
|
201
|
+
</DataTable>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Aggregations
|
|
205
|
+
|
|
206
|
+
Parent-controlled footer computations over the **filtered** rows: `sum`, `average`, `min`, `max`, `count`, `unique`, `median`.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
const [aggs, setAggs] = useState<AggregationConfigMap<Row>>({
|
|
210
|
+
Qty: { enabled: true, functions: ["sum"] },
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
<DataTable
|
|
214
|
+
aggregations={aggs}
|
|
215
|
+
onAggregationChange={(colId, config) => setAggs(prev => ({ ...prev, [colId]: config }))}
|
|
216
|
+
/>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The sticky footer row appears when any config is `enabled`; the serial column's footer cell then shows the total row count. Non-numeric cells are dropped (not coerced to 0). `config.accessor` overrides the value source; `config.format(value, func)` overrides display (default: counts as integers, others 2 decimals). A column's `customFooter` wins over its aggregation display, and the header shows a small calculator icon on aggregated columns.
|
|
220
|
+
|
|
221
|
+
The toolbar's **Aggregations menu** (user-facing toggles, per-column function submenu) renders only with `onAggregationChange` + `showToolbar` + at least one aggregatable column — auto-detected by sampling the first rows for numeric values, or forced with `meta: { aggregatable: true }` on the column.
|
|
222
|
+
|
|
223
|
+
## Pinning, visibility, resizing
|
|
224
|
+
|
|
225
|
+
- **Pinning** (`enableColumnPinning`, default on): per-column via the header `⋯` menu (Pin Right / Unpin), bulk reset in the Settings menu. Serial and select columns are always pinned left and re-asserted on every change. A pinned column is clamped to its live rendered width so sticky offsets stay true.
|
|
226
|
+
- **Visibility** (`enableColumnVisibility`, default on): the toolbar Columns menu toggles columns (grouped columns listed under their group); the header `⋯` menu offers Hide. Un-hiding lives only in the Columns menu — a hidden column has no header to click. `enableHiding: false` keeps a column out of all of it.
|
|
227
|
+
- **Resizing** (`enableColumnResizing`, default OFF): live drag handles on header right edges. Pinned columns are size-locked — resize first, pin after.
|
|
228
|
+
|
|
229
|
+
## Persist
|
|
230
|
+
|
|
231
|
+
Opt-in state persistence across unmount/back-navigation:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
persist="qc-completed" // shorthand for { key }
|
|
235
|
+
persist={{ key: "qc-completed", group: "inhouse", local: true }}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Persists:** column filter values, global search text, the field-picker selection, external (server) filter values, pagination (`pagination: false` to skip page state). **Never persists:** selection, sorting, visibility, pinning, sizing.
|
|
239
|
+
|
|
240
|
+
**How it works:** values are stored per **filter identity** (`key`/`id`), not as raw table state, in an in-memory map — a refresh starts clean. `local: true` mirrors to localStorage (`atsui:tbl:v1:*`), surviving refresh; note it's per-browser, not per-login. Restore is synchronous, seeded before first render — no flash of unfiltered data. Dates are revived from ISO strings. Per-filter opt-out: `persist: false` on that filter.
|
|
241
|
+
|
|
242
|
+
**`key` must be app-unique.** Two mounted tables on one key overwrite each other's state (dev warning). One page with two tables = two keys.
|
|
243
|
+
|
|
244
|
+
### Shared slots — one value across pages
|
|
245
|
+
|
|
246
|
+
`shared: "party"` on a filter publishes its VALUE into a named slot; every table in the same `persist.group` with a filter bound to that slot picks it up — even when the pages use different filter `key`s, or one side is an `externalSearch` filter (values are stored by identity, which is what makes this possible). Search a party on one page; the next page in the group opens already filtered to it. Two tables mounted at once live-sync through the slot.
|
|
247
|
+
|
|
248
|
+
`shared` REQUIRES `persist.group`. Slots never cross groups — "party" in group `inhouse` is not "party" in `sales`. A `shared` filter on a group-less table is inert and warns.
|
|
249
|
+
|
|
250
|
+
### Typing `group` / `shared` — the registry file
|
|
251
|
+
|
|
252
|
+
Augment `PersistGroupRegistry` once and both become validated unions instead of plain strings:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
// src/types/table-persist.d.ts
|
|
256
|
+
declare module "@akshar-technosoft/ui" {
|
|
257
|
+
interface PersistGroupRegistry {
|
|
258
|
+
inhouse: "party" | "material";
|
|
259
|
+
sales: "party";
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
After this `group: "inhose"` is a compile error and `shared` autocompletes.
|
|
265
|
+
|
|
266
|
+
### The double API call, and how to fix it
|
|
267
|
+
|
|
268
|
+
With persisted **external** filters, mount order is: the page fires its default query → the table replays restored external values through `onExternalSearch` → the page queries AGAIN with filters. Two requests, the first wasted.
|
|
269
|
+
|
|
270
|
+
**Fix A (proper):** seed the page's initial query params from the persisted values, so the FIRST request already carries them:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
import { readPersistedExternal } from "@akshar-technosoft/ui";
|
|
274
|
+
|
|
275
|
+
// before — default query fires unfiltered, then re-fires filtered
|
|
276
|
+
const [params, setParams] = useState({ Status: "Pending" });
|
|
277
|
+
|
|
278
|
+
// after — first query is already filtered
|
|
279
|
+
const [params, setParams] = useState(() => ({
|
|
280
|
+
Status: "Pending",
|
|
281
|
+
...readPersistedExternal("qc-completed"), // same key as the table's persist
|
|
282
|
+
}));
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The mount replay then commits the same values the query already used; with React Query the identical query key dedupes, and a manual fetch effect should compare params before refetching.
|
|
286
|
+
|
|
287
|
+
**Fix B (pragmatic):** don't persist that filter — `persist: false` on the external filter. The rest of the table still persists; the server filter starts clean each visit. Right when the double call is cheaper than the wiring.
|
|
288
|
+
|
|
289
|
+
## Export
|
|
290
|
+
|
|
291
|
+
The table never writes files. It hands you a clean snapshot and the app owns the writer — per-page, fully customizable Excel/CSV builders, no spreadsheet dependency inside the library:
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
onExport={(data, view) => buildQcExcel(view)} // Settings menu > Export (item appears only when onExport is passed)
|
|
295
|
+
|
|
296
|
+
// or anywhere you hold the table instance (onTableReady / children render-prop):
|
|
297
|
+
const view = getTableExportView(table);
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**What the two arguments are:**
|
|
301
|
+
|
|
302
|
+
- `data: T[]` — the filtered + sorted **row originals** (your objects, all pages, not just the visible one). It is literally `view.originals` — kept as the first arg so simple handlers can ignore `view`.
|
|
303
|
+
- `view: TableExportView<T>` — the ready-to-write snapshot:
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
{
|
|
307
|
+
columns: [ // VISIBLE columns only, in display + pin order,
|
|
308
|
+
{ id: "FullCPOSrNo", header: "Order No." }, // select/serialNumber excluded;
|
|
309
|
+
{ id: "Qty", header: "Qty" }, // header = exportHeader ?? string header ?? id
|
|
310
|
+
],
|
|
311
|
+
rows: [ // one array per row, values in `columns` order,
|
|
312
|
+
["CPO-101", 250], // native types kept (number/Date/boolean — real
|
|
313
|
+
["CPO-102", 480], // Excel cells, not strings)
|
|
314
|
+
],
|
|
315
|
+
originals: [ {...}, {...} ], // same rows as objects, same order as `rows`
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Rows come from the pre-pagination model: filtered and sorted, ALL pages. Typical writer: header row from `view.columns.map(c => c.header)`, data rows straight from `view.rows`; reach into `view.originals` when the sheet needs fields that aren't visible columns.
|
|
320
|
+
|
|
321
|
+
A column is included when it has an accessor or `exportValue`. Display-only columns are skipped unless `exportValue` supplies a flat value — also the tool for JSX composite cells:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
exportValue: (row) => `${row.RefNo} (${GeneralHelper.formatDate(row.RefDate)})`,
|
|
325
|
+
exportHeader: "Reference", // needed only when `header` is JSX
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Toolbar & the Settings menu
|
|
329
|
+
|
|
330
|
+
`showToolbar` (default OFF) is the largest master switch — it hosts the bar filters + chips + Clear Filters, the global search with field picker, the Aggregations menu, the Columns menu, the Settings menu and Refresh (`onRefresh`, disabled while `loading`). The header's per-column `⋯` menus work without it. The whole toolbar is one wrap row: overflowing controls drop line by line, the right cluster stays right-aligned.
|
|
331
|
+
|
|
332
|
+
`toolbarPosition: 'above-header' | 'below-header'` moves the toolbar inside the card as a sticky band that stacks with the `header` prop (band heights are measured at runtime for correct sticky offsets).
|
|
333
|
+
|
|
334
|
+
Settings (gear) menu: Export (when `onExport` given) · Clear All Sorting · Clear All Filters · Clear Aggregations · Reset All Pinning — each disabled while there's nothing to clear.
|
|
335
|
+
|
|
336
|
+
## Settings reference
|
|
337
|
+
|
|
338
|
+
Taxonomy: `show*` = a UI element/region is visible · `enable*` = a capability is on · bare adjectives = presentation.
|
|
339
|
+
|
|
340
|
+
| Setting | Default | Notes |
|
|
341
|
+
|---|---|---|
|
|
342
|
+
| `showHeader` | `true` | Off also removes sorting/pin/resize (they live in the header) |
|
|
343
|
+
| `showToolbar` | `false` | Master for search/filters/menus (above) |
|
|
344
|
+
| `showSerialNumbers` | `true` | "No." column — position in current view, not a record id |
|
|
345
|
+
| `showCheckbox` | `true` | Single-mode radio visibility (row stays clickable) |
|
|
346
|
+
| `showFilterChips` | `true` | Chips for active `placement:'menu'` filters |
|
|
347
|
+
| `enableSorting` | `true` | Header click cycle + `⋯` menu |
|
|
348
|
+
| `enableFiltering` | `true` | The engine; off = boxes render but no rows are removed |
|
|
349
|
+
| `enableGlobalFilter` | `true` | Search box (accessor columns only) |
|
|
350
|
+
| `enableColumnVisibility` | `true` | Columns menu + per-column Hide |
|
|
351
|
+
| `enableRowSelection` | `true` | Master for the whole selection group |
|
|
352
|
+
| `enableColumnResizing` | `false` | Live drag handles |
|
|
353
|
+
| `enableColumnPinning` | `true` | Master for pinning |
|
|
354
|
+
| `enableHeaderCheckbox` | `true` | `false` greys select-all only |
|
|
355
|
+
| `fixedCheckboxColumn` | `true` | Locks the select column's pin |
|
|
356
|
+
| `selectionMode` | `"multiple"` | or `"single"` |
|
|
357
|
+
| `striped` / `hoverable` / `compact` / `bordered` | `true` | Presentation |
|
|
358
|
+
| `fullHeight` | `false` | Card flexes to a bounded parent height (pair with `maxHeight`) |
|
|
359
|
+
| `toolbarPosition` | `'default'` | `'above-header'` / `'below-header'` |
|
|
360
|
+
| `groupedFilterLabel` | `"Global"` | Field picker "all" label |
|
|
361
|
+
|
|
362
|
+
## Complete props reference
|
|
363
|
+
|
|
364
|
+
Every prop `DataTable` accepts — this is the whole surface, nothing else exists:
|
|
365
|
+
|
|
366
|
+
| Prop | Type | Default | What it does |
|
|
367
|
+
|---|---|---|---|
|
|
368
|
+
| `data` | `T[]` | required | Row data, rendered client-side |
|
|
369
|
+
| `columns` | `GroupColumnDef<T>[]` | required | Column defs ([Columns](#columns)) |
|
|
370
|
+
| `filters` | `FilterConfig<T>[]` | — | Toolbar filter controls ([Filters](#filters--the-full-story)) |
|
|
371
|
+
| `pagination` | `PaginationConfig` | — | Presence enables paging ([Pagination](#pagination)) |
|
|
372
|
+
| `settings` | `TableSettings` | `{}` | Feature/presentation toggles (table above) |
|
|
373
|
+
| `header` | node or `{ content, align, className, showOnEmpty }` | — | Sticky title band inside the card; `showOnEmpty` (default true) keeps it on empty data |
|
|
374
|
+
| `footer` | `ReactNode` | — | Sticky full-width bottom band |
|
|
375
|
+
| `className` | `string` | — | Outer wrapper classes |
|
|
376
|
+
| `maxHeight` | `string` | `"100%"` | Scroll container cap — what makes header/footer sticky |
|
|
377
|
+
| `loading` | `boolean` | `false` | Spinner overlay over the card |
|
|
378
|
+
| `error` | `string` | — | Replaces the table with an error card (+ Try Again when `onRefresh` given) |
|
|
379
|
+
| `emptyMessage` | `string` | `"No data available"` | Empty-state text |
|
|
380
|
+
| `onRowSelectionChange` | `(rows: T[]) => void` | — | Selected originals on every change ([Selection](#selection)) |
|
|
381
|
+
| `onExport` | `(data, view) => void` | — | Enables the Settings-menu Export item ([Export](#export)) |
|
|
382
|
+
| `onRefresh` | `() => void` | — | Toolbar Refresh button + error-card Try Again |
|
|
383
|
+
| `onTableReady` | `(table) => void` | — | TanStack instance escape hatch; fires once per instance |
|
|
384
|
+
| `children` | `(table) => ReactNode` | — | Render-prop (action bar etc.) |
|
|
385
|
+
| `isRowSelectable` | `(row: T) => boolean` | — | Row-level selection gate |
|
|
386
|
+
| `getRowId` | `(row, index) => string` | — | Stable row identity ([Selection](#selection)) |
|
|
387
|
+
| `defaultSelectedRows` | `(row: T) => boolean` | — | Uncontrolled selection prefill, seeded once |
|
|
388
|
+
| `onExternalSearch` | `(values) => void` | — | Server-filter commit callback ([External filters](#external-server-filters)) |
|
|
389
|
+
| `aggregations` | `AggregationConfigMap<T>` | `{}` | Footer computations ([Aggregations](#aggregations)) |
|
|
390
|
+
| `onAggregationChange` | `(columnId, config) => void` | — | Enables the toolbar Aggregations menu |
|
|
391
|
+
| `rowClassName` | `(row: Row<T>) => string` | — | Per-row classes (status colouring) |
|
|
392
|
+
| `persist` | `string \| PersistConfig` | — | State persistence ([Persist](#persist)) |
|
|
393
|
+
|
|
394
|
+
`FilterConfig` fields (per filter):
|
|
395
|
+
|
|
396
|
+
| Field | Required | Notes |
|
|
397
|
+
|---|---|---|
|
|
398
|
+
| `placeholder` | yes | Label everywhere: control, chip, field picker |
|
|
399
|
+
| `key` | one of | Data dot-path (path filter) |
|
|
400
|
+
| `id` + `filterFn(row, value)` | one of | Custom predicate filter |
|
|
401
|
+
| `type` | no (`"text"`) | `text` / `select` / `date` / `daterange` / `number` |
|
|
402
|
+
| `options` | with `select` | `{ label, value }[]` |
|
|
403
|
+
| `placement` | no (`"bar"`) | `"menu"` = behind the field picker + chip |
|
|
404
|
+
| `externalSearch` | no (`false`) | Server-side |
|
|
405
|
+
| `width`, `icon`, `dateFormat` | no | Cosmetic |
|
|
406
|
+
| `shared` | no | Group-wide value slot (needs `persist.group`) |
|
|
407
|
+
| `persist` | no (`true`) | `false` = exclude from persistence |
|
|
408
|
+
|
|
409
|
+
`GroupColumnDef` extras beyond TanStack: `headerAlign`, `columns`, `enablePinning`, `customFooter`, `exportValue`, `exportHeader` ([Columns](#columns)). `PersistConfig`: `key` (required), `group`, `local`, `pagination` ([Persist](#persist)). `AggregationConfig`: `enabled`, `functions`, `format`, `accessor` ([Aggregations](#aggregations)). `PaginationConfig`: `pageSize`, `pageSizeOptions`, `showInfo`, `showPageNumbers` ([Pagination](#pagination)).
|
|
410
|
+
|
|
411
|
+
Action bar: `DataTableActionBar` takes `table`, `visible` (default: auto — shown while anything selected), `container` (portal target, default `document.body`) plus `motion.div` props; `DataTableActionBarAction` takes Button props plus `tooltip` and `isPending`; `DataTableActionBarSelection` takes `table`.
|
|
412
|
+
|
|
413
|
+
## Troubleshooting
|
|
414
|
+
|
|
415
|
+
- **Filter not rendering** → `settings.showToolbar: true` missing (dev warning fires).
|
|
416
|
+
- **Global search can't find a value that's visibly on screen** → that column has no accessor; add `accessorFn`.
|
|
417
|
+
- **A `key` filter does nothing** → the path doesn't match the data shape (it's a data path, not a column id).
|
|
418
|
+
- **Wrong rows selected after a refetch** → pass `getRowId`.
|
|
419
|
+
- **`shared` does nothing** → no `persist.group` on the table (warns).
|
|
420
|
+
- **Two tables fight over saved state** → same `persist.key` (warns).
|
|
421
|
+
- **Field picker missing** → needs `enableGlobalFilter` on AND at least one `placement: 'menu'` filter.
|
|
422
|
+
- **Two API calls on pages with persisted external filters** → see [the double API call](#the-double-api-call-and-how-to-fix-it).
|
|
423
|
+
- **Aggregations menu missing** → needs `onAggregationChange`, `showToolbar`, and a numeric (or `meta.aggregatable`) column.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
# DataTemplate
|
|
428
|
+
|
|
429
|
+
DataTable's sibling for card/grid layouts: same toolbar/search/filter/pagination shell, but YOU render each item. `fields` declares which keys are sortable/searchable; `filters` is a simpler flat-key config. Defaults that differ from DataTable: **`showToolbar` is `true`**, **selection is OFF** (`enableSelection: false`). Grid shape via `settings.gridCols` (`{ default: 3, sm: 1, md: 2, lg: 3, xl: 4, "2xl": 6 }`) and `gap`.
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
<DataTemplate
|
|
433
|
+
data={products}
|
|
434
|
+
template={(item, index, isSelected, toggleSelect) => (
|
|
435
|
+
<ProductCard item={item} selected={isSelected} onClick={toggleSelect} />
|
|
436
|
+
)}
|
|
437
|
+
fields={[{ key: "Name", label: "Name", searchable: true, sortable: true }]}
|
|
438
|
+
pagination={{}}
|
|
439
|
+
/>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
`onTemplateReady` / `children` receive a controller (`getSelectedItems`, `selectAll`, `clearSelection`, `getFilteredData`, `getTotalCount`, `getVisibleCount`, `refresh`, `exportData`), and it has its own `DataTemplateActionBar` family.
|
|
443
|
+
|
|
444
|
+
Full surface — props: `data`, `template`, `fields` (`{ key, label, type?, sortable?, filterable?, searchable? }`), `filters` (`{ key, label, type, options?, placeholder?, icon? }`), `pagination`, `settings`, `header`, `footer`, `className`, `loading`, `error`, `emptyMessage`, `emptyIcon`, `onSelectionChange`, `onExport(data)`, `onRefresh`, `onTemplateReady`, `children`. Settings: `enableSorting`, `enableFiltering`, `enableGlobalSearch`, `enableSelection` (default OFF), `enableExport`, `showToolbar` (default ON), `selectionMode`, `gridCols`, `gap`, `aspectRatio`, `minCardWidth`, `maxCardWidth`.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
# Layout system
|
|
449
|
+
|
|
450
|
+
Zero context, zero factories — plain composable components. The standard page:
|
|
451
|
+
|
|
452
|
+
```tsx
|
|
453
|
+
<AppContainer>
|
|
454
|
+
<AppHeader title="Quality Check" description="Pending takas" backAction={{ href: "/manufacturing" }}>
|
|
455
|
+
<Button>New Entry</Button> {/* lands right-aligned automatically */}
|
|
456
|
+
</AppHeader>
|
|
457
|
+
|
|
458
|
+
<AppContent> {/* fills remaining height, body scrolls */}
|
|
459
|
+
<AppContentHeader>…pinned band above the scroll…</AppContentHeader>
|
|
460
|
+
<DataTable ... />
|
|
461
|
+
<AppContentFooter>…pinned band below…</AppContentFooter>
|
|
462
|
+
<AppSheet open={open} onOpenChange={setOpen}>…side panel…</AppSheet>
|
|
463
|
+
</AppContent>
|
|
464
|
+
|
|
465
|
+
<AppFooter>
|
|
466
|
+
<span>3 selected</span> {/* leading children sit left */}
|
|
467
|
+
<div className="flex items-center gap-4"> {/* LAST child → pushed right */}
|
|
468
|
+
<Button variant="secondary">Cancel</Button>
|
|
469
|
+
<Button>Save</Button>
|
|
470
|
+
</div>
|
|
471
|
+
</AppFooter>
|
|
472
|
+
</AppContainer>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## AppContainer
|
|
476
|
+
|
|
477
|
+
Full-height flex column, `gap-2`. Props: `children`, `className`.
|
|
478
|
+
|
|
479
|
+
## AppHeader
|
|
480
|
+
|
|
481
|
+
Props: `title`, `description`, `backAction: { href?, onClick? }` (back-arrow button; `href` is a typed route once the router registry is augmented), `metadata: [{ label, value }]` (small label/value pairs under the title; falsy values skipped), `children`, `childrenClassName`, `className`.
|
|
482
|
+
|
|
483
|
+
The title block takes only the space it needs. `children` render inside a baked `flex flex-1 items-center justify-end gap-4 h-full` row — content lands right-aligned and vertically centered with no wrapper. Different layout: `childrenClassName="justify-between"` etc. (twMerge — yours wins), or a `<div className="flex-1" />` spacer / `mr-auto` on a child.
|
|
484
|
+
|
|
485
|
+
**Fragment gotcha (header AND footer):** a fragment `<>A B</>` as a direct child melts into multiple DOM children, and positional CSS (`gap`, `last-child`) treats them separately. Wrap grouped elements in a `div`.
|
|
486
|
+
|
|
487
|
+
## AppContent
|
|
488
|
+
|
|
489
|
+
The page's content slot: fills the remaining space of its flex parent (`flex-auto min-h-0`), rounded `bg-background` card, children scroll inside. Props: `className` (root — `p-0`, `border shadow-sm`, `flex-none` for a content-sized block), `contentClassName` (inner scroll wrapper — has `p-2`; pass `p-0` to drop it, `flex` to make the body a flex row).
|
|
490
|
+
|
|
491
|
+
Three **marker components** work only as DIRECT children — AppContent extracts them and renders the real thing; they render nothing on their own:
|
|
492
|
+
|
|
493
|
+
- `AppContentHeader` / `AppContentFooter` — pinned bands outside the scroll region (`border-b` / `border-t`, own `p-2`, `className` to adjust). For toolbars/summaries that must not scroll away.
|
|
494
|
+
- `AppSheet` — the side panel (one per AppContent, controlled only):
|
|
495
|
+
|
|
496
|
+
```tsx
|
|
497
|
+
<AppSheet open={open} onOpenChange={setOpen} side="right" className="w-[600px]">
|
|
498
|
+
<PartyDetail … />
|
|
499
|
+
</AppSheet>
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
| Prop | Default | Notes |
|
|
503
|
+
|---|---|---|
|
|
504
|
+
| `open` / `onOpenChange` | required | Controlled only |
|
|
505
|
+
| `side` | `"right"` | or `"left"` |
|
|
506
|
+
| `overlay` | `true` | Slides over the dimmed body; click outside closes. `overlay={false}` = push mode: the sheet takes its width and the body shrinks, animated both ways. Below 1024px push auto-falls back to overlay — a fixed panel would cramp the main content |
|
|
507
|
+
| `className` | `w-[420px] max-w-full` | Merged (twMerge): override width (`w-1/3`, `w-[600px]`) or add styling (`p-0`). Sheets want a FIXED comfortable width — the MAIN content is the responsive part |
|
|
508
|
+
|
|
509
|
+
## AppFooter
|
|
510
|
+
|
|
511
|
+
Flex row with `p-2`, `gap-4`, and **the last child pushed to the right edge** (`[&>*:last-child]:ml-auto`) — actions go last, anything before them sits left. Renders nothing without children. Override via `className`.
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
# Utilities & core components
|
|
516
|
+
|
|
517
|
+
`GeneralHelper` — static, no setup:
|
|
518
|
+
|
|
519
|
+
```tsx
|
|
520
|
+
GeneralHelper.formatDate(d) // "07-07-2026" (dd-mm-yyyy default)
|
|
521
|
+
GeneralHelper.formatDate(d, { format: "dd-mmm-yyyy" }) // "07-Jul-2026"; also "iso" | "long" | "short", separator option
|
|
522
|
+
GeneralHelper.formatINR(125000) // "₹ 1,25,000.00"
|
|
523
|
+
GeneralHelper.formatINR(125000, { compact: true }) // "₹ 1.25L" style for >= 1 lakh
|
|
524
|
+
GeneralHelper.toProperCase("mill process") // "Mill Process" (toProperCaseAdvanced handles separators)
|
|
525
|
+
GeneralHelper.copyToClipboard(text) // promise; <GeneralHelper.CopyToClipboard text=... /> for the button
|
|
526
|
+
<GeneralHelper.StatusBadge status="Completed" />
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
`Loader`, `ErrorComponent`, `NotFound`, `Unauthorized`, `OfflineUI` — full-area state screens. `CurrencyTransfer` — transfer/success display.
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
# For maintainers
|
|
534
|
+
|
|
535
|
+
- Behavior reference = the JSDoc in `data-table-types.ts`; keep it and this README in sync when the API moves.
|
|
536
|
+
- Monorepo dev loop: after lib edits `npm run build`, copy `dist/` into the consuming app's `node_modules/@akshar-technosoft/ui/dist/`, restart the TS server.
|
|
537
|
+
- The table renders with `border-separate` (sticky cells drift ~1px under `border-collapse`). Consequence: borders must live on CELLS — a `border-b` on `<tr>` never paints in this mode.
|
|
538
|
+
- Radix dropdown/menu contents are portaled to `body`, but React synthetic events still bubble through the COMPONENT tree — any click-handling wrapper around a menu needs `stopPropagation` on the menu content (the header's click-to-sort learned this the hard way).
|