@mkt-loitd/react-table-grid-custom 1.0.3 → 1.0.7
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 +95 -115
- package/dist/index.css +97 -0
- package/dist/index.d.mts +132 -3
- package/dist/index.d.ts +132 -3
- package/dist/index.js +269 -2
- package/dist/index.mjs +257 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,64 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
📦 React Table Grid Custom
|
|
2
2
|
|
|
3
|
-
A powerful,
|
|
3
|
+
A powerful, flexible React Table component built on top of react-data-grid, designed for Next.js and TypeScript projects.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Supports pagination, sorting, row selection, context menu, column visibility, and Mantine UI.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
✨ Features
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
✅ Built on react-data-grid
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
* ✅ Fully written in **TypeScript**
|
|
13
|
-
* ✅ Pagination & sorting
|
|
14
|
-
* ✅ Row selection (checkbox)
|
|
15
|
-
* ✅ Internationalization (`react-i18next`)
|
|
16
|
-
* ✅ Mantine UI integration
|
|
17
|
-
* ✅ Optimized for **Next.js (App Router & Pages Router)**
|
|
18
|
-
* ✅ Tree-shakeable & ESM/CJS support
|
|
11
|
+
✅ 100% TypeScript
|
|
19
12
|
|
|
20
|
-
|
|
13
|
+
✅ Pagination & sorting
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
✅ Row selection (checkbox)
|
|
16
|
+
|
|
17
|
+
✅ Context menu (right click)
|
|
18
|
+
|
|
19
|
+
✅ Show / hide columns
|
|
20
|
+
|
|
21
|
+
✅ Mantine UI integration
|
|
22
|
+
|
|
23
|
+
✅ Optimized for Next.js 13+ (App Router & Pages Router)
|
|
24
|
+
|
|
25
|
+
✅ ESM + CJS support
|
|
26
|
+
|
|
27
|
+
✅ Tree-shakeable (sideEffects: false)
|
|
28
|
+
|
|
29
|
+
📦 Installation
|
|
30
|
+
npm install @mkt-loitd/react-table-grid-custom
|
|
23
31
|
|
|
24
|
-
```bash
|
|
25
|
-
npm install @loitd/react-table-grid-custom
|
|
26
|
-
```
|
|
27
32
|
|
|
28
33
|
or
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```
|
|
35
|
+
yarn add @mkt-loitd/react-table-grid-custom
|
|
36
|
+
|
|
33
37
|
|
|
34
38
|
or
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
pnpm add @mkt-loitd/react-table-grid-custom
|
|
41
|
+
|
|
42
|
+
🔗 Repository
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
👉 GitHub:
|
|
45
|
+
https://github.com/loitd140201/react-table
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
⚠️ Peer Dependencies
|
|
43
48
|
|
|
44
49
|
Make sure your project already has:
|
|
45
50
|
|
|
46
|
-
```bash
|
|
47
51
|
react >= 18
|
|
48
52
|
react-dom >= 18
|
|
49
53
|
next >= 13
|
|
50
|
-
```
|
|
51
54
|
|
|
52
|
-
These are required but **not bundled** with the library.
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
These packages are required but not bundled.
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
🚀 Basic Usage
|
|
59
|
+
'use client'
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
import
|
|
61
|
+
import { ReactTableGridCustom } from '@mkt-loitd/react-table-grid-custom'
|
|
62
|
+
import type { TColumnsTable } from '@mkt-loitd/react-table-grid-custom'
|
|
60
63
|
|
|
61
|
-
const columns = [
|
|
64
|
+
const columns: TColumnsTable<any> = [
|
|
62
65
|
{ key: 'id', name: 'ID' },
|
|
63
66
|
{ key: 'name', name: 'Name' },
|
|
64
67
|
{ key: 'email', name: 'Email' }
|
|
@@ -82,103 +85,80 @@ export default function Example() {
|
|
|
82
85
|
</div>
|
|
83
86
|
)
|
|
84
87
|
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## 🧩 Props
|
|
90
|
-
|
|
91
|
-
### `ReactTableGridCustom<T>`
|
|
92
|
-
|
|
93
|
-
| Prop | Type | Description |
|
|
94
|
-
| -------------------------- | ------------------------ | ------------------------ |
|
|
95
|
-
| `columns` | `TColumnsTable<T>` | Column definitions |
|
|
96
|
-
| `data` | `T[]` | Table data |
|
|
97
|
-
| `page` | `number` | Current page |
|
|
98
|
-
| `pageSize` | `number` | Items per page |
|
|
99
|
-
| `total` | `number` | Total records |
|
|
100
|
-
| `onChange` | `(page: number) => void` | Page change callback |
|
|
101
|
-
| `selectedRows` | `ReadonlySet<Key>` | Selected rows |
|
|
102
|
-
| `fetching` | `boolean` | Show loading overlay |
|
|
103
|
-
| `hiddenPagination` | `boolean` | Hide pagination |
|
|
104
|
-
| `hiddenSTT` | `boolean` | Hide index column |
|
|
105
|
-
| `classNameWapperTable` | `string` | Custom wrapper class |
|
|
106
|
-
| `classNamePaginationTable` | `string` | Pagination wrapper class |
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## 🌍 Internationalization (i18n)
|
|
111
|
-
|
|
112
|
-
This component supports `react-i18next`.
|
|
113
|
-
|
|
114
|
-
Make sure you have:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
npm install react-i18next i18next
|
|
118
|
-
```
|
|
119
88
|
|
|
120
|
-
|
|
89
|
+
🧩 Main Component
|
|
90
|
+
ReactTableGridCustom<T>
|
|
91
|
+
import type { IReactTableGridCustom } from '@mkt-loitd/react-table-grid-custom'
|
|
92
|
+
|
|
93
|
+
Props
|
|
94
|
+
Prop Type Description
|
|
95
|
+
columns TColumnsTable<T> Column definitions
|
|
96
|
+
data T[] Table data
|
|
97
|
+
page number Current page
|
|
98
|
+
pageSize number Records per page
|
|
99
|
+
total number Total records
|
|
100
|
+
onChange (page: number) => void Page change callback
|
|
101
|
+
selectedRows ReadonlySet<Key> Selected rows
|
|
102
|
+
fetching boolean Show loading overlay
|
|
103
|
+
hiddenPagination boolean Hide pagination
|
|
104
|
+
hiddenSTT boolean Hide index (STT) column
|
|
105
|
+
classNameWapperTable string Wrapper table class
|
|
106
|
+
classNamePaginationTable string Pagination wrapper class
|
|
107
|
+
🧩 Context Menu Wrapper
|
|
108
|
+
TableStyleContextWapper
|
|
109
|
+
import {
|
|
110
|
+
TableStyleContextWapper,
|
|
111
|
+
type TableStyleWapperProps
|
|
112
|
+
} from '@mkt-loitd/react-table-grid-custom'
|
|
113
|
+
|
|
114
|
+
Example
|
|
115
|
+
<TableStyleContextWapper
|
|
116
|
+
clsTablecustom="h-full"
|
|
117
|
+
renderContext={{
|
|
118
|
+
renderData: true,
|
|
119
|
+
onClick: (key, row) => {
|
|
120
|
+
console.log(key, row)
|
|
121
|
+
}
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
<ReactTableGridCustom {...props} />
|
|
125
|
+
</TableStyleContextWapper>
|
|
126
|
+
|
|
127
|
+
🎨 Styling
|
|
128
|
+
|
|
129
|
+
Built with Mantine UI
|
|
130
|
+
|
|
131
|
+
Fully compatible with Tailwind CSS
|
|
132
|
+
|
|
133
|
+
Uses default styles from react-data-grid
|
|
121
134
|
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"display": "Display",
|
|
125
|
-
"to": "to",
|
|
126
|
-
"in": "in",
|
|
127
|
-
"data": "records"
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## 🎨 Styling
|
|
134
|
-
|
|
135
|
-
* Uses **Mantine** components
|
|
136
|
-
* Fully compatible with **Tailwind CSS**
|
|
137
|
-
* Includes default styles from `react-data-grid`
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
135
|
import 'react-data-grid/lib/styles.css'
|
|
141
|
-
```
|
|
142
136
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
📁 Package Structure
|
|
138
|
+
dist/
|
|
139
|
+
README.md
|
|
146
140
|
|
|
147
|
-
|
|
141
|
+
🛠 Development
|
|
148
142
|
npm run dev
|
|
149
|
-
|
|
143
|
+
|
|
150
144
|
|
|
151
145
|
Build package:
|
|
152
146
|
|
|
153
|
-
```bash
|
|
154
147
|
npm run build
|
|
155
|
-
```
|
|
156
148
|
|
|
157
|
-
Test publish locally:
|
|
158
149
|
|
|
159
|
-
|
|
160
|
-
npm pack
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## 📁 Package Output
|
|
166
|
-
|
|
167
|
-
When published, the package includes only:
|
|
150
|
+
Test locally:
|
|
168
151
|
|
|
169
|
-
|
|
170
|
-
dist/
|
|
171
|
-
README.md
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
---
|
|
152
|
+
npm pack
|
|
175
153
|
|
|
176
|
-
|
|
154
|
+
📄 License
|
|
177
155
|
|
|
178
156
|
ISC © LoiTD
|
|
179
157
|
|
|
180
|
-
|
|
158
|
+
💬 Support
|
|
181
159
|
|
|
182
|
-
|
|
160
|
+
🐞 Issues:
|
|
161
|
+
https://github.com/loitd140201/react-table/issues
|
|
183
162
|
|
|
184
|
-
|
|
163
|
+
📦 Repository:
|
|
164
|
+
https://github.com/loitd140201/react-table
|
package/dist/index.css
CHANGED
|
@@ -55,3 +55,100 @@ div[aria-sort] > span {
|
|
|
55
55
|
position: sticky !important;
|
|
56
56
|
right: 0 !important;
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
/* src/component/ui/ContextMenu/ContextMenu.css */
|
|
60
|
+
.shadow-menu {
|
|
61
|
+
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
|
62
|
+
animation: open 0.3s;
|
|
63
|
+
transform-origin: top left;
|
|
64
|
+
}
|
|
65
|
+
.shadow-submenu {
|
|
66
|
+
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
|
67
|
+
}
|
|
68
|
+
@keyframes open {
|
|
69
|
+
from {
|
|
70
|
+
transform: scale(0);
|
|
71
|
+
}
|
|
72
|
+
to {
|
|
73
|
+
transform: scale(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* node_modules/tippy.js/dist/tippy.css */
|
|
78
|
+
.tippy-box[data-animation=fade][data-state=hidden] {
|
|
79
|
+
opacity: 0;
|
|
80
|
+
}
|
|
81
|
+
[data-tippy-root] {
|
|
82
|
+
max-width: calc(100vw - 10px);
|
|
83
|
+
}
|
|
84
|
+
.tippy-box {
|
|
85
|
+
position: relative;
|
|
86
|
+
background-color: #333;
|
|
87
|
+
color: #fff;
|
|
88
|
+
border-radius: 4px;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
line-height: 1.4;
|
|
91
|
+
white-space: normal;
|
|
92
|
+
outline: 0;
|
|
93
|
+
transition-property:
|
|
94
|
+
transform,
|
|
95
|
+
visibility,
|
|
96
|
+
opacity;
|
|
97
|
+
}
|
|
98
|
+
.tippy-box[data-placement^=top] > .tippy-arrow {
|
|
99
|
+
bottom: 0;
|
|
100
|
+
}
|
|
101
|
+
.tippy-box[data-placement^=top] > .tippy-arrow:before {
|
|
102
|
+
bottom: -7px;
|
|
103
|
+
left: 0;
|
|
104
|
+
border-width: 8px 8px 0;
|
|
105
|
+
border-top-color: initial;
|
|
106
|
+
transform-origin: center top;
|
|
107
|
+
}
|
|
108
|
+
.tippy-box[data-placement^=bottom] > .tippy-arrow {
|
|
109
|
+
top: 0;
|
|
110
|
+
}
|
|
111
|
+
.tippy-box[data-placement^=bottom] > .tippy-arrow:before {
|
|
112
|
+
top: -7px;
|
|
113
|
+
left: 0;
|
|
114
|
+
border-width: 0 8px 8px;
|
|
115
|
+
border-bottom-color: initial;
|
|
116
|
+
transform-origin: center bottom;
|
|
117
|
+
}
|
|
118
|
+
.tippy-box[data-placement^=left] > .tippy-arrow {
|
|
119
|
+
right: 0;
|
|
120
|
+
}
|
|
121
|
+
.tippy-box[data-placement^=left] > .tippy-arrow:before {
|
|
122
|
+
border-width: 8px 0 8px 8px;
|
|
123
|
+
border-left-color: initial;
|
|
124
|
+
right: -7px;
|
|
125
|
+
transform-origin: center left;
|
|
126
|
+
}
|
|
127
|
+
.tippy-box[data-placement^=right] > .tippy-arrow {
|
|
128
|
+
left: 0;
|
|
129
|
+
}
|
|
130
|
+
.tippy-box[data-placement^=right] > .tippy-arrow:before {
|
|
131
|
+
left: -7px;
|
|
132
|
+
border-width: 8px 8px 8px 0;
|
|
133
|
+
border-right-color: initial;
|
|
134
|
+
transform-origin: center right;
|
|
135
|
+
}
|
|
136
|
+
.tippy-box[data-inertia][data-state=visible] {
|
|
137
|
+
transition-timing-function: cubic-bezier(.54, 1.5, .38, 1.11);
|
|
138
|
+
}
|
|
139
|
+
.tippy-arrow {
|
|
140
|
+
width: 16px;
|
|
141
|
+
height: 16px;
|
|
142
|
+
color: #333;
|
|
143
|
+
}
|
|
144
|
+
.tippy-arrow:before {
|
|
145
|
+
content: "";
|
|
146
|
+
position: absolute;
|
|
147
|
+
border-color: transparent;
|
|
148
|
+
border-style: solid;
|
|
149
|
+
}
|
|
150
|
+
.tippy-content {
|
|
151
|
+
position: relative;
|
|
152
|
+
padding: 5px 9px;
|
|
153
|
+
z-index: 1;
|
|
154
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
1
2
|
import { Key, Dispatch, SetStateAction, ReactNode, JSX } from 'react';
|
|
2
3
|
import { ColumnOrColumnGroup, DataGridProps } from 'react-data-grid';
|
|
3
4
|
import { PaginationRootProps } from '@mantine/core';
|
|
5
|
+
import { TFunction } from 'i18next';
|
|
6
|
+
import { UseMutateFunction } from '@tanstack/react-query';
|
|
4
7
|
|
|
5
8
|
type TColumnsTable<T = unknown, SR = unknown> = readonly ColumnOrColumnGroup<NoInfer<T>, NoInfer<SR>>[];
|
|
6
9
|
interface IPaginationParams$1 {
|
|
@@ -10,7 +13,7 @@ interface IPaginationParams$1 {
|
|
|
10
13
|
interface IObjectDynamic {
|
|
11
14
|
[key: string]: any;
|
|
12
15
|
}
|
|
13
|
-
interface ISetConfigPagination extends IPaginationParams$1, IObjectDynamic {
|
|
16
|
+
interface ISetConfigPagination$1 extends IPaginationParams$1, IObjectDynamic {
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
interface IPaginationText {
|
|
@@ -27,7 +30,7 @@ interface IReactTableGridCustom<T = unknown, SR = unknown, K extends Key = Key>
|
|
|
27
30
|
data?: T[];
|
|
28
31
|
/** Nếu hàm onChange nên dùng useCallback */
|
|
29
32
|
onChange?: Pick<PaginationRootProps, 'onChange'>['onChange'];
|
|
30
|
-
setConfigPagination?: Dispatch<SetStateAction<ISetConfigPagination>>;
|
|
33
|
+
setConfigPagination?: Dispatch<SetStateAction<ISetConfigPagination$1>>;
|
|
31
34
|
/** Nếu hàm rowKeyGetter nên dùng useCallback*/
|
|
32
35
|
rowKeyGetter?: string | Maybe<(row: NoInfer<T>) => K>;
|
|
33
36
|
hiddenPaginationText?: boolean;
|
|
@@ -41,6 +44,132 @@ interface IReactTableGridCustom<T = unknown, SR = unknown, K extends Key = Key>
|
|
|
41
44
|
type ReactTableGridCustomComponent = <T, SR = unknown, K extends Key = Key>(props: IReactTableGridCustom<T, SR, K>) => JSX.Element;
|
|
42
45
|
declare const ReactTableGridCustom: ReactTableGridCustomComponent;
|
|
43
46
|
|
|
47
|
+
interface ContextMenuProps {
|
|
48
|
+
selector: string;
|
|
49
|
+
children?: ReactNode;
|
|
50
|
+
zIndex?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface IMainResponse<T = any> {
|
|
54
|
+
success?: boolean;
|
|
55
|
+
status?: 'success' | 'error' | 'warning';
|
|
56
|
+
data?: T;
|
|
57
|
+
payload?: {
|
|
58
|
+
data?: T;
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
};
|
|
61
|
+
message?: {
|
|
62
|
+
key: string;
|
|
63
|
+
[key: string]: any;
|
|
64
|
+
};
|
|
65
|
+
error?: any;
|
|
66
|
+
}
|
|
67
|
+
interface IFieldUpdateAndCheck<T = any, F = any, V = any> {
|
|
68
|
+
id?: string | number;
|
|
69
|
+
field?: F;
|
|
70
|
+
value?: V;
|
|
71
|
+
data?: T;
|
|
72
|
+
[key: string]: any;
|
|
73
|
+
}
|
|
74
|
+
interface Account {
|
|
75
|
+
id?: string | number;
|
|
76
|
+
username?: string;
|
|
77
|
+
password?: string;
|
|
78
|
+
email?: string;
|
|
79
|
+
status?: string;
|
|
80
|
+
[key: string]: any;
|
|
81
|
+
}
|
|
82
|
+
interface Post {
|
|
83
|
+
id?: string | number;
|
|
84
|
+
title?: string;
|
|
85
|
+
content?: string;
|
|
86
|
+
createdAt?: number;
|
|
87
|
+
[key: string]: any;
|
|
88
|
+
}
|
|
89
|
+
interface AppSettings {
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}
|
|
92
|
+
interface ISetConfigPagination {
|
|
93
|
+
page?: number;
|
|
94
|
+
limit?: number;
|
|
95
|
+
total?: number;
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
}
|
|
98
|
+
type ITaskName = string;
|
|
99
|
+
|
|
100
|
+
interface IActionUiUtilBy {
|
|
101
|
+
action?: string;
|
|
102
|
+
[key: string]: any;
|
|
103
|
+
}
|
|
104
|
+
interface IPayloadStartAction {
|
|
105
|
+
action?: string;
|
|
106
|
+
[key: string]: any;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface Proxy {
|
|
110
|
+
id?: string;
|
|
111
|
+
host?: string;
|
|
112
|
+
port?: number;
|
|
113
|
+
username?: string;
|
|
114
|
+
password?: string;
|
|
115
|
+
protocol?: string;
|
|
116
|
+
provider?: string;
|
|
117
|
+
[key: string]: any;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface IPayloadRemoveProxy {
|
|
121
|
+
ids: string[];
|
|
122
|
+
}
|
|
123
|
+
interface IPayloadService {
|
|
124
|
+
updateByClipboard?: UseMutateFunction<IMainResponse<string[]>, Error, IFieldUpdateAndCheck<Account, string[], keyof Account>, unknown>;
|
|
125
|
+
removeFieldBy?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, Array<keyof Account>, string[]>, unknown>;
|
|
126
|
+
copyByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, string, string[]>, unknown>;
|
|
127
|
+
actionBy?: UseMutateFunction<IMainResponse<string[]>, Error, IFieldUpdateAndCheck<Account, IActionUiUtilBy, string[]>, unknown>;
|
|
128
|
+
updateAccountByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, Partial<Account>, string[]>, unknown>;
|
|
129
|
+
deleteProxy?: UseMutateFunction<IMainResponse<boolean>, Error, IPayloadRemoveProxy, unknown>;
|
|
130
|
+
removePostByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Post, undefined, string[]>, unknown>;
|
|
131
|
+
startAction?: UseMutateFunction<IMainResponse<boolean>, Error, IPayloadStartAction, unknown>;
|
|
132
|
+
updateSettings?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<AppSettings, object, boolean>, unknown>;
|
|
133
|
+
useCopyProxyByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Proxy, string, string[]>[], unknown>;
|
|
134
|
+
exportLinkSuccess?: UseMutateFunction<IMainResponse<boolean>, Error, ITaskName, unknown>;
|
|
135
|
+
setAction?: Dispatch<SetStateAction<ITaskName>>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type IDispatchState<T> = Dispatch<SetStateAction<T>>;
|
|
139
|
+
|
|
140
|
+
interface IExpandValue extends IPayloadService {
|
|
141
|
+
t?: TFunction<'translation', undefined>;
|
|
142
|
+
setConfigSearch?: IDispatchState<ISetConfigPagination>;
|
|
143
|
+
setSelectedRecords?: Dispatch<ReadonlySet<string>>;
|
|
144
|
+
setIsShowEdit?: Dispatch<SetStateAction<boolean>>;
|
|
145
|
+
setIsOpenEditContent?: Dispatch<SetStateAction<boolean>>;
|
|
146
|
+
setIsCopy?: Dispatch<SetStateAction<boolean>>;
|
|
147
|
+
setIsChangeCate?: Dispatch<SetStateAction<boolean>>;
|
|
148
|
+
setIsBackup?: Dispatch<SetStateAction<boolean>>;
|
|
149
|
+
}
|
|
150
|
+
type configContextMenuType = {
|
|
151
|
+
Icon: (prop?: any) => ReactNode;
|
|
152
|
+
action: string;
|
|
153
|
+
onClick?: (value: string[], expandValue: IExpandValue) => void;
|
|
154
|
+
children?: configContextMenuType[];
|
|
155
|
+
};
|
|
156
|
+
interface RenderContextMenuProps {
|
|
157
|
+
renderData?: configContextMenuType[];
|
|
158
|
+
valueClickItem?: any;
|
|
159
|
+
expandValue?: IExpandValue;
|
|
160
|
+
classWapper?: boolean;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface TableStyleWapperProps {
|
|
164
|
+
children?: ReactNode;
|
|
165
|
+
contextMenuProps?: Omit<ContextMenuProps, 'selector' | 'children'> & {
|
|
166
|
+
selector?: string;
|
|
167
|
+
};
|
|
168
|
+
renderContext?: RenderContextMenuProps;
|
|
169
|
+
clsTablecustom?: string;
|
|
170
|
+
}
|
|
171
|
+
declare const TableStyleContextWapper: react.NamedExoticComponent<TableStyleWapperProps>;
|
|
172
|
+
|
|
44
173
|
interface IPaginationParams {
|
|
45
174
|
pageSize?: number;
|
|
46
175
|
page?: number;
|
|
@@ -68,4 +197,4 @@ interface UseShowHideColumnReturn<T, SR> {
|
|
|
68
197
|
handleChangeLocation?: (arr: string[]) => void;
|
|
69
198
|
}
|
|
70
199
|
|
|
71
|
-
export { type ICalculatorTotalPage, type IPaginationParams, type IReactTableGridCustom, type ISTTParams, type Maybe, ReactTableGridCustom, type TColumnsTable, type UseShowHideColumnParameter, type UseShowHideColumnReturn };
|
|
200
|
+
export { type ICalculatorTotalPage, type IPaginationParams, type IReactTableGridCustom, type ISTTParams, type Maybe, ReactTableGridCustom, type TColumnsTable, TableStyleContextWapper, type TableStyleWapperProps, type UseShowHideColumnParameter, type UseShowHideColumnReturn };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
1
2
|
import { Key, Dispatch, SetStateAction, ReactNode, JSX } from 'react';
|
|
2
3
|
import { ColumnOrColumnGroup, DataGridProps } from 'react-data-grid';
|
|
3
4
|
import { PaginationRootProps } from '@mantine/core';
|
|
5
|
+
import { TFunction } from 'i18next';
|
|
6
|
+
import { UseMutateFunction } from '@tanstack/react-query';
|
|
4
7
|
|
|
5
8
|
type TColumnsTable<T = unknown, SR = unknown> = readonly ColumnOrColumnGroup<NoInfer<T>, NoInfer<SR>>[];
|
|
6
9
|
interface IPaginationParams$1 {
|
|
@@ -10,7 +13,7 @@ interface IPaginationParams$1 {
|
|
|
10
13
|
interface IObjectDynamic {
|
|
11
14
|
[key: string]: any;
|
|
12
15
|
}
|
|
13
|
-
interface ISetConfigPagination extends IPaginationParams$1, IObjectDynamic {
|
|
16
|
+
interface ISetConfigPagination$1 extends IPaginationParams$1, IObjectDynamic {
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
interface IPaginationText {
|
|
@@ -27,7 +30,7 @@ interface IReactTableGridCustom<T = unknown, SR = unknown, K extends Key = Key>
|
|
|
27
30
|
data?: T[];
|
|
28
31
|
/** Nếu hàm onChange nên dùng useCallback */
|
|
29
32
|
onChange?: Pick<PaginationRootProps, 'onChange'>['onChange'];
|
|
30
|
-
setConfigPagination?: Dispatch<SetStateAction<ISetConfigPagination>>;
|
|
33
|
+
setConfigPagination?: Dispatch<SetStateAction<ISetConfigPagination$1>>;
|
|
31
34
|
/** Nếu hàm rowKeyGetter nên dùng useCallback*/
|
|
32
35
|
rowKeyGetter?: string | Maybe<(row: NoInfer<T>) => K>;
|
|
33
36
|
hiddenPaginationText?: boolean;
|
|
@@ -41,6 +44,132 @@ interface IReactTableGridCustom<T = unknown, SR = unknown, K extends Key = Key>
|
|
|
41
44
|
type ReactTableGridCustomComponent = <T, SR = unknown, K extends Key = Key>(props: IReactTableGridCustom<T, SR, K>) => JSX.Element;
|
|
42
45
|
declare const ReactTableGridCustom: ReactTableGridCustomComponent;
|
|
43
46
|
|
|
47
|
+
interface ContextMenuProps {
|
|
48
|
+
selector: string;
|
|
49
|
+
children?: ReactNode;
|
|
50
|
+
zIndex?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface IMainResponse<T = any> {
|
|
54
|
+
success?: boolean;
|
|
55
|
+
status?: 'success' | 'error' | 'warning';
|
|
56
|
+
data?: T;
|
|
57
|
+
payload?: {
|
|
58
|
+
data?: T;
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
};
|
|
61
|
+
message?: {
|
|
62
|
+
key: string;
|
|
63
|
+
[key: string]: any;
|
|
64
|
+
};
|
|
65
|
+
error?: any;
|
|
66
|
+
}
|
|
67
|
+
interface IFieldUpdateAndCheck<T = any, F = any, V = any> {
|
|
68
|
+
id?: string | number;
|
|
69
|
+
field?: F;
|
|
70
|
+
value?: V;
|
|
71
|
+
data?: T;
|
|
72
|
+
[key: string]: any;
|
|
73
|
+
}
|
|
74
|
+
interface Account {
|
|
75
|
+
id?: string | number;
|
|
76
|
+
username?: string;
|
|
77
|
+
password?: string;
|
|
78
|
+
email?: string;
|
|
79
|
+
status?: string;
|
|
80
|
+
[key: string]: any;
|
|
81
|
+
}
|
|
82
|
+
interface Post {
|
|
83
|
+
id?: string | number;
|
|
84
|
+
title?: string;
|
|
85
|
+
content?: string;
|
|
86
|
+
createdAt?: number;
|
|
87
|
+
[key: string]: any;
|
|
88
|
+
}
|
|
89
|
+
interface AppSettings {
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
}
|
|
92
|
+
interface ISetConfigPagination {
|
|
93
|
+
page?: number;
|
|
94
|
+
limit?: number;
|
|
95
|
+
total?: number;
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
}
|
|
98
|
+
type ITaskName = string;
|
|
99
|
+
|
|
100
|
+
interface IActionUiUtilBy {
|
|
101
|
+
action?: string;
|
|
102
|
+
[key: string]: any;
|
|
103
|
+
}
|
|
104
|
+
interface IPayloadStartAction {
|
|
105
|
+
action?: string;
|
|
106
|
+
[key: string]: any;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface Proxy {
|
|
110
|
+
id?: string;
|
|
111
|
+
host?: string;
|
|
112
|
+
port?: number;
|
|
113
|
+
username?: string;
|
|
114
|
+
password?: string;
|
|
115
|
+
protocol?: string;
|
|
116
|
+
provider?: string;
|
|
117
|
+
[key: string]: any;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface IPayloadRemoveProxy {
|
|
121
|
+
ids: string[];
|
|
122
|
+
}
|
|
123
|
+
interface IPayloadService {
|
|
124
|
+
updateByClipboard?: UseMutateFunction<IMainResponse<string[]>, Error, IFieldUpdateAndCheck<Account, string[], keyof Account>, unknown>;
|
|
125
|
+
removeFieldBy?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, Array<keyof Account>, string[]>, unknown>;
|
|
126
|
+
copyByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, string, string[]>, unknown>;
|
|
127
|
+
actionBy?: UseMutateFunction<IMainResponse<string[]>, Error, IFieldUpdateAndCheck<Account, IActionUiUtilBy, string[]>, unknown>;
|
|
128
|
+
updateAccountByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Account, Partial<Account>, string[]>, unknown>;
|
|
129
|
+
deleteProxy?: UseMutateFunction<IMainResponse<boolean>, Error, IPayloadRemoveProxy, unknown>;
|
|
130
|
+
removePostByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Post, undefined, string[]>, unknown>;
|
|
131
|
+
startAction?: UseMutateFunction<IMainResponse<boolean>, Error, IPayloadStartAction, unknown>;
|
|
132
|
+
updateSettings?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<AppSettings, object, boolean>, unknown>;
|
|
133
|
+
useCopyProxyByField?: UseMutateFunction<IMainResponse<boolean>, Error, IFieldUpdateAndCheck<Proxy, string, string[]>[], unknown>;
|
|
134
|
+
exportLinkSuccess?: UseMutateFunction<IMainResponse<boolean>, Error, ITaskName, unknown>;
|
|
135
|
+
setAction?: Dispatch<SetStateAction<ITaskName>>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type IDispatchState<T> = Dispatch<SetStateAction<T>>;
|
|
139
|
+
|
|
140
|
+
interface IExpandValue extends IPayloadService {
|
|
141
|
+
t?: TFunction<'translation', undefined>;
|
|
142
|
+
setConfigSearch?: IDispatchState<ISetConfigPagination>;
|
|
143
|
+
setSelectedRecords?: Dispatch<ReadonlySet<string>>;
|
|
144
|
+
setIsShowEdit?: Dispatch<SetStateAction<boolean>>;
|
|
145
|
+
setIsOpenEditContent?: Dispatch<SetStateAction<boolean>>;
|
|
146
|
+
setIsCopy?: Dispatch<SetStateAction<boolean>>;
|
|
147
|
+
setIsChangeCate?: Dispatch<SetStateAction<boolean>>;
|
|
148
|
+
setIsBackup?: Dispatch<SetStateAction<boolean>>;
|
|
149
|
+
}
|
|
150
|
+
type configContextMenuType = {
|
|
151
|
+
Icon: (prop?: any) => ReactNode;
|
|
152
|
+
action: string;
|
|
153
|
+
onClick?: (value: string[], expandValue: IExpandValue) => void;
|
|
154
|
+
children?: configContextMenuType[];
|
|
155
|
+
};
|
|
156
|
+
interface RenderContextMenuProps {
|
|
157
|
+
renderData?: configContextMenuType[];
|
|
158
|
+
valueClickItem?: any;
|
|
159
|
+
expandValue?: IExpandValue;
|
|
160
|
+
classWapper?: boolean;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface TableStyleWapperProps {
|
|
164
|
+
children?: ReactNode;
|
|
165
|
+
contextMenuProps?: Omit<ContextMenuProps, 'selector' | 'children'> & {
|
|
166
|
+
selector?: string;
|
|
167
|
+
};
|
|
168
|
+
renderContext?: RenderContextMenuProps;
|
|
169
|
+
clsTablecustom?: string;
|
|
170
|
+
}
|
|
171
|
+
declare const TableStyleContextWapper: react.NamedExoticComponent<TableStyleWapperProps>;
|
|
172
|
+
|
|
44
173
|
interface IPaginationParams {
|
|
45
174
|
pageSize?: number;
|
|
46
175
|
page?: number;
|
|
@@ -68,4 +197,4 @@ interface UseShowHideColumnReturn<T, SR> {
|
|
|
68
197
|
handleChangeLocation?: (arr: string[]) => void;
|
|
69
198
|
}
|
|
70
199
|
|
|
71
|
-
export { type ICalculatorTotalPage, type IPaginationParams, type IReactTableGridCustom, type ISTTParams, type Maybe, ReactTableGridCustom, type TColumnsTable, type UseShowHideColumnParameter, type UseShowHideColumnReturn };
|
|
200
|
+
export { type ICalculatorTotalPage, type IPaginationParams, type IReactTableGridCustom, type ISTTParams, type Maybe, ReactTableGridCustom, type TColumnsTable, TableStyleContextWapper, type TableStyleWapperProps, type UseShowHideColumnParameter, type UseShowHideColumnReturn };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,12 +17,21 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
|
-
ReactTableGridCustom: () => ReactTableGridCustom
|
|
33
|
+
ReactTableGridCustom: () => ReactTableGridCustom,
|
|
34
|
+
TableStyleContextWapper: () => TableStyleContextWapper
|
|
24
35
|
});
|
|
25
36
|
module.exports = __toCommonJS(index_exports);
|
|
26
37
|
|
|
@@ -292,7 +303,263 @@ var ReactTableGridCustomInner = ({
|
|
|
292
303
|
var ReactTableGridCustom = (0, import_react2.memo)(
|
|
293
304
|
ReactTableGridCustomInner
|
|
294
305
|
);
|
|
306
|
+
|
|
307
|
+
// src/component/TableStyleContextWapper.tsx
|
|
308
|
+
var import_react7 = require("react");
|
|
309
|
+
|
|
310
|
+
// src/component/ui/ContextMenu/ContextMenu.tsx
|
|
311
|
+
var import_react3 = require("react");
|
|
312
|
+
var import_react_dom = require("react-dom");
|
|
313
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
314
|
+
var ContextMenu = ({ selector, children, zIndex = 40 }) => {
|
|
315
|
+
const menuRef = (0, import_react3.useRef)(null);
|
|
316
|
+
const closeMenu = (0, import_react3.useCallback)(() => {
|
|
317
|
+
const contextMenuElem = menuRef.current;
|
|
318
|
+
const elementParent = document.querySelector(selector);
|
|
319
|
+
if (contextMenuElem && contextMenuElem.classList.contains("shadow-menu")) {
|
|
320
|
+
contextMenuElem.classList.remove("shadow-menu");
|
|
321
|
+
contextMenuElem.style.opacity = "0";
|
|
322
|
+
contextMenuElem.style.visibility = "hidden";
|
|
323
|
+
}
|
|
324
|
+
if (elementParent) {
|
|
325
|
+
elementParent.style.removeProperty("overflow");
|
|
326
|
+
}
|
|
327
|
+
}, [menuRef.current]);
|
|
328
|
+
(0, import_react3.useEffect)(() => {
|
|
329
|
+
const elementParent = document.querySelector(selector);
|
|
330
|
+
if (elementParent) {
|
|
331
|
+
const clickMenu = (e) => {
|
|
332
|
+
const contextMenuElem = menuRef.current;
|
|
333
|
+
if (contextMenuElem) {
|
|
334
|
+
contextMenuElem.style.opacity = "1";
|
|
335
|
+
contextMenuElem.style.visibility = "visible";
|
|
336
|
+
const { width: widthContextMenu, height: heightContextMenu } = contextMenuElem.getBoundingClientRect();
|
|
337
|
+
elementParent.style.overflow = "hidden";
|
|
338
|
+
const maxWidth = window.innerWidth;
|
|
339
|
+
const maxHeight = window.innerHeight;
|
|
340
|
+
const remainingLeft = maxWidth - e.clientX;
|
|
341
|
+
const isLeft = remainingLeft >= widthContextMenu;
|
|
342
|
+
const showTop = heightContextMenu + e.clientY <= maxHeight;
|
|
343
|
+
const showBottom = e.clientY - heightContextMenu >= 0;
|
|
344
|
+
const isCenter = !(showTop || showBottom);
|
|
345
|
+
isCenter;
|
|
346
|
+
const styleOrigin = {
|
|
347
|
+
x: "left",
|
|
348
|
+
y: "top"
|
|
349
|
+
};
|
|
350
|
+
if (isLeft) {
|
|
351
|
+
contextMenuElem.style.left = `${e.clientX}px`;
|
|
352
|
+
styleOrigin.x = "left";
|
|
353
|
+
} else {
|
|
354
|
+
contextMenuElem.style.left = `${e.clientX - widthContextMenu}px`;
|
|
355
|
+
styleOrigin.x = "right";
|
|
356
|
+
}
|
|
357
|
+
if (showTop) {
|
|
358
|
+
contextMenuElem.style.top = `${e.clientY}px`;
|
|
359
|
+
styleOrigin.y = "top";
|
|
360
|
+
} else if (showBottom) {
|
|
361
|
+
contextMenuElem.style.top = `${e.clientY - heightContextMenu}px`;
|
|
362
|
+
styleOrigin.y = "bottom";
|
|
363
|
+
} else {
|
|
364
|
+
const HalfHeight = heightContextMenu / 2;
|
|
365
|
+
const calculatorTop = HalfHeight + e.clientY;
|
|
366
|
+
const showTopCenter = calculatorTop <= maxHeight;
|
|
367
|
+
const calculatorBottom = e.clientY - HalfHeight;
|
|
368
|
+
const showBottom2 = calculatorBottom >= 0;
|
|
369
|
+
let topNew = calculatorBottom;
|
|
370
|
+
if (!showBottom2 && showTopCenter) {
|
|
371
|
+
topNew = topNew - calculatorBottom;
|
|
372
|
+
} else if (!showTopCenter && showBottom2) {
|
|
373
|
+
const ts = calculatorTop - maxHeight;
|
|
374
|
+
topNew = topNew - ts;
|
|
375
|
+
}
|
|
376
|
+
contextMenuElem.style.top = `${topNew}px`;
|
|
377
|
+
styleOrigin.y = "center";
|
|
378
|
+
}
|
|
379
|
+
contextMenuElem.style.transformOrigin = `${styleOrigin.y} ${styleOrigin.x}`;
|
|
380
|
+
if (!contextMenuElem.classList.contains("shadow-menu")) {
|
|
381
|
+
contextMenuElem.classList.add("shadow-menu");
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
elementParent.addEventListener("contextmenu", clickMenu);
|
|
386
|
+
window.addEventListener("click", closeMenu);
|
|
387
|
+
return () => {
|
|
388
|
+
elementParent.removeEventListener("contextmenu", clickMenu);
|
|
389
|
+
window.removeEventListener("click", closeMenu);
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return () => {
|
|
393
|
+
};
|
|
394
|
+
}, []);
|
|
395
|
+
return (0, import_react_dom.createPortal)(
|
|
396
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
397
|
+
"div",
|
|
398
|
+
{
|
|
399
|
+
className: "fixed z-40 w-fit",
|
|
400
|
+
ref: menuRef,
|
|
401
|
+
style: { opacity: 0, visibility: "hidden", zIndex },
|
|
402
|
+
children
|
|
403
|
+
}
|
|
404
|
+
),
|
|
405
|
+
document.body
|
|
406
|
+
);
|
|
407
|
+
};
|
|
408
|
+
var ContextMenu_default = ContextMenu;
|
|
409
|
+
|
|
410
|
+
// src/component/ui/ContextMenu/RenderContextMenu.tsx
|
|
411
|
+
var import_react6 = require("react");
|
|
412
|
+
|
|
413
|
+
// src/component/ui/ContextMenu/ContextMenuItem.tsx
|
|
414
|
+
var import_react_i18next3 = require("react-i18next");
|
|
415
|
+
var import_md = require("react-icons/md");
|
|
416
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
417
|
+
var ContextMenuItem = ({
|
|
418
|
+
currentValue,
|
|
419
|
+
expandValue,
|
|
420
|
+
valueClickItem,
|
|
421
|
+
show,
|
|
422
|
+
isArrow
|
|
423
|
+
}) => {
|
|
424
|
+
const { t } = (0, import_react_i18next3.useTranslation)();
|
|
425
|
+
const Icon = currentValue.Icon;
|
|
426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
427
|
+
"div",
|
|
428
|
+
{
|
|
429
|
+
className: `cursor-pointer p-2 flex items-center space-x-2 relative ${show ? "bg-[#555] text-white" : "hover:bg-[#555] hover:text-white"}`,
|
|
430
|
+
onClick: () => {
|
|
431
|
+
var _a;
|
|
432
|
+
expandValue && valueClickItem && (currentValue == null ? void 0 : currentValue.onClick) && ((_a = currentValue == null ? void 0 : currentValue.onClick) == null ? void 0 : _a.call(currentValue, valueClickItem, expandValue));
|
|
433
|
+
},
|
|
434
|
+
children: [
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 20 }),
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm flex-1", children: t(`${currentValue.action}`) }),
|
|
437
|
+
isArrow && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_md.MdKeyboardArrowRight, { size: 20 })
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
);
|
|
441
|
+
};
|
|
442
|
+
var ContextMenuItem_default = ContextMenuItem;
|
|
443
|
+
|
|
444
|
+
// src/component/ui/ContextMenu/DropdownContextChild.tsx
|
|
445
|
+
var import_react4 = __toESM(require("@tippyjs/react"));
|
|
446
|
+
var import_react5 = require("react");
|
|
447
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
448
|
+
var DropdownContextChild = ({ button, children, ...rest }) => {
|
|
449
|
+
const id = (0, import_react5.useId)();
|
|
450
|
+
const instanceRef = (0, import_react5.useRef)(null);
|
|
451
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
452
|
+
import_react4.default,
|
|
453
|
+
{
|
|
454
|
+
theme: "drop-down",
|
|
455
|
+
className: "!bg-transparent !text-inherit !border-r-0 [&>*]:!p-0",
|
|
456
|
+
appendTo: document.body,
|
|
457
|
+
arrow: false,
|
|
458
|
+
placement: "auto",
|
|
459
|
+
interactive: true,
|
|
460
|
+
allowHTML: true,
|
|
461
|
+
content: children,
|
|
462
|
+
...rest,
|
|
463
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
464
|
+
"div",
|
|
465
|
+
{
|
|
466
|
+
id: `div-${id}`,
|
|
467
|
+
onClick: () => {
|
|
468
|
+
var _a;
|
|
469
|
+
(_a = instanceRef == null ? void 0 : instanceRef.current) == null ? void 0 : _a.show();
|
|
470
|
+
},
|
|
471
|
+
children: button
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
};
|
|
477
|
+
var DropdownContextChild_default = DropdownContextChild;
|
|
478
|
+
|
|
479
|
+
// src/component/ui/ContextMenu/RenderContextMenu.tsx
|
|
480
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
481
|
+
var RenderContextMenu = ({
|
|
482
|
+
renderData,
|
|
483
|
+
valueClickItem,
|
|
484
|
+
expandValue = {}
|
|
485
|
+
}) => {
|
|
486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white shadow-submenu p-1 min-w-[250px] border", children: renderData == null ? void 0 : renderData.map((menuAction, index) => {
|
|
487
|
+
const [isShow, setIsShow] = (0, import_react6.useState)(false);
|
|
488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react6.Fragment, { children: [
|
|
489
|
+
!(menuAction == null ? void 0 : menuAction.children) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
490
|
+
ContextMenuItem_default,
|
|
491
|
+
{
|
|
492
|
+
currentValue: menuAction,
|
|
493
|
+
expandValue,
|
|
494
|
+
valueClickItem
|
|
495
|
+
}
|
|
496
|
+
),
|
|
497
|
+
(menuAction == null ? void 0 : menuAction.children) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
498
|
+
DropdownContextChild_default,
|
|
499
|
+
{
|
|
500
|
+
appendTo: "parent",
|
|
501
|
+
placement: "right",
|
|
502
|
+
offset: [0, 5],
|
|
503
|
+
onShow: () => setIsShow(true),
|
|
504
|
+
onHide: () => setIsShow(false),
|
|
505
|
+
button: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
506
|
+
ContextMenuItem_default,
|
|
507
|
+
{
|
|
508
|
+
currentValue: menuAction,
|
|
509
|
+
expandValue,
|
|
510
|
+
valueClickItem,
|
|
511
|
+
show: isShow,
|
|
512
|
+
isArrow: true
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dropdown-context-child absolute -top-[20px] -left-1", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
516
|
+
RenderContextMenu,
|
|
517
|
+
{
|
|
518
|
+
renderData: menuAction == null ? void 0 : menuAction.children,
|
|
519
|
+
expandValue,
|
|
520
|
+
valueClickItem
|
|
521
|
+
}
|
|
522
|
+
) })
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] }, index);
|
|
526
|
+
}) });
|
|
527
|
+
};
|
|
528
|
+
var RenderContextMenu_default = RenderContextMenu;
|
|
529
|
+
|
|
530
|
+
// src/component/TableStyleContextWapper.tsx
|
|
531
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
532
|
+
var TableStyleContextMenuWapper = ({
|
|
533
|
+
children,
|
|
534
|
+
contextMenuProps,
|
|
535
|
+
clsTablecustom,
|
|
536
|
+
renderContext
|
|
537
|
+
}) => {
|
|
538
|
+
const idWapper = (0, import_react7.useId)();
|
|
539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
540
|
+
"div",
|
|
541
|
+
{
|
|
542
|
+
id: `wapper_menu_context-${idWapper}`,
|
|
543
|
+
className: `border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom != null ? clsTablecustom : ""}`,
|
|
544
|
+
children: [
|
|
545
|
+
(renderContext == null ? void 0 : renderContext.renderData) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
546
|
+
ContextMenu_default,
|
|
547
|
+
{
|
|
548
|
+
selector: `[id="wapper_menu_context-${idWapper}"] .rdg`,
|
|
549
|
+
...contextMenuProps,
|
|
550
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(RenderContextMenu_default, { ...renderContext })
|
|
551
|
+
}
|
|
552
|
+
),
|
|
553
|
+
children
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
);
|
|
557
|
+
};
|
|
558
|
+
var TableStyleContextWapper = (0, import_react7.memo)(
|
|
559
|
+
TableStyleContextMenuWapper
|
|
560
|
+
);
|
|
295
561
|
// Annotate the CommonJS export names for ESM import in node:
|
|
296
562
|
0 && (module.exports = {
|
|
297
|
-
ReactTableGridCustom
|
|
563
|
+
ReactTableGridCustom,
|
|
564
|
+
TableStyleContextWapper
|
|
298
565
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -276,6 +276,262 @@ var ReactTableGridCustomInner = ({
|
|
|
276
276
|
var ReactTableGridCustom = memo(
|
|
277
277
|
ReactTableGridCustomInner
|
|
278
278
|
);
|
|
279
|
+
|
|
280
|
+
// src/component/TableStyleContextWapper.tsx
|
|
281
|
+
import { memo as memo2, useId as useId2 } from "react";
|
|
282
|
+
|
|
283
|
+
// src/component/ui/ContextMenu/ContextMenu.tsx
|
|
284
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
285
|
+
import { createPortal } from "react-dom";
|
|
286
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
287
|
+
var ContextMenu = ({ selector, children, zIndex = 40 }) => {
|
|
288
|
+
const menuRef = useRef2(null);
|
|
289
|
+
const closeMenu = useCallback2(() => {
|
|
290
|
+
const contextMenuElem = menuRef.current;
|
|
291
|
+
const elementParent = document.querySelector(selector);
|
|
292
|
+
if (contextMenuElem && contextMenuElem.classList.contains("shadow-menu")) {
|
|
293
|
+
contextMenuElem.classList.remove("shadow-menu");
|
|
294
|
+
contextMenuElem.style.opacity = "0";
|
|
295
|
+
contextMenuElem.style.visibility = "hidden";
|
|
296
|
+
}
|
|
297
|
+
if (elementParent) {
|
|
298
|
+
elementParent.style.removeProperty("overflow");
|
|
299
|
+
}
|
|
300
|
+
}, [menuRef.current]);
|
|
301
|
+
useEffect2(() => {
|
|
302
|
+
const elementParent = document.querySelector(selector);
|
|
303
|
+
if (elementParent) {
|
|
304
|
+
const clickMenu = (e) => {
|
|
305
|
+
const contextMenuElem = menuRef.current;
|
|
306
|
+
if (contextMenuElem) {
|
|
307
|
+
contextMenuElem.style.opacity = "1";
|
|
308
|
+
contextMenuElem.style.visibility = "visible";
|
|
309
|
+
const { width: widthContextMenu, height: heightContextMenu } = contextMenuElem.getBoundingClientRect();
|
|
310
|
+
elementParent.style.overflow = "hidden";
|
|
311
|
+
const maxWidth = window.innerWidth;
|
|
312
|
+
const maxHeight = window.innerHeight;
|
|
313
|
+
const remainingLeft = maxWidth - e.clientX;
|
|
314
|
+
const isLeft = remainingLeft >= widthContextMenu;
|
|
315
|
+
const showTop = heightContextMenu + e.clientY <= maxHeight;
|
|
316
|
+
const showBottom = e.clientY - heightContextMenu >= 0;
|
|
317
|
+
const isCenter = !(showTop || showBottom);
|
|
318
|
+
isCenter;
|
|
319
|
+
const styleOrigin = {
|
|
320
|
+
x: "left",
|
|
321
|
+
y: "top"
|
|
322
|
+
};
|
|
323
|
+
if (isLeft) {
|
|
324
|
+
contextMenuElem.style.left = `${e.clientX}px`;
|
|
325
|
+
styleOrigin.x = "left";
|
|
326
|
+
} else {
|
|
327
|
+
contextMenuElem.style.left = `${e.clientX - widthContextMenu}px`;
|
|
328
|
+
styleOrigin.x = "right";
|
|
329
|
+
}
|
|
330
|
+
if (showTop) {
|
|
331
|
+
contextMenuElem.style.top = `${e.clientY}px`;
|
|
332
|
+
styleOrigin.y = "top";
|
|
333
|
+
} else if (showBottom) {
|
|
334
|
+
contextMenuElem.style.top = `${e.clientY - heightContextMenu}px`;
|
|
335
|
+
styleOrigin.y = "bottom";
|
|
336
|
+
} else {
|
|
337
|
+
const HalfHeight = heightContextMenu / 2;
|
|
338
|
+
const calculatorTop = HalfHeight + e.clientY;
|
|
339
|
+
const showTopCenter = calculatorTop <= maxHeight;
|
|
340
|
+
const calculatorBottom = e.clientY - HalfHeight;
|
|
341
|
+
const showBottom2 = calculatorBottom >= 0;
|
|
342
|
+
let topNew = calculatorBottom;
|
|
343
|
+
if (!showBottom2 && showTopCenter) {
|
|
344
|
+
topNew = topNew - calculatorBottom;
|
|
345
|
+
} else if (!showTopCenter && showBottom2) {
|
|
346
|
+
const ts = calculatorTop - maxHeight;
|
|
347
|
+
topNew = topNew - ts;
|
|
348
|
+
}
|
|
349
|
+
contextMenuElem.style.top = `${topNew}px`;
|
|
350
|
+
styleOrigin.y = "center";
|
|
351
|
+
}
|
|
352
|
+
contextMenuElem.style.transformOrigin = `${styleOrigin.y} ${styleOrigin.x}`;
|
|
353
|
+
if (!contextMenuElem.classList.contains("shadow-menu")) {
|
|
354
|
+
contextMenuElem.classList.add("shadow-menu");
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
elementParent.addEventListener("contextmenu", clickMenu);
|
|
359
|
+
window.addEventListener("click", closeMenu);
|
|
360
|
+
return () => {
|
|
361
|
+
elementParent.removeEventListener("contextmenu", clickMenu);
|
|
362
|
+
window.removeEventListener("click", closeMenu);
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
return () => {
|
|
366
|
+
};
|
|
367
|
+
}, []);
|
|
368
|
+
return createPortal(
|
|
369
|
+
/* @__PURE__ */ jsx4(
|
|
370
|
+
"div",
|
|
371
|
+
{
|
|
372
|
+
className: "fixed z-40 w-fit",
|
|
373
|
+
ref: menuRef,
|
|
374
|
+
style: { opacity: 0, visibility: "hidden", zIndex },
|
|
375
|
+
children
|
|
376
|
+
}
|
|
377
|
+
),
|
|
378
|
+
document.body
|
|
379
|
+
);
|
|
380
|
+
};
|
|
381
|
+
var ContextMenu_default = ContextMenu;
|
|
382
|
+
|
|
383
|
+
// src/component/ui/ContextMenu/RenderContextMenu.tsx
|
|
384
|
+
import { Fragment as Fragment2, useState as useState2 } from "react";
|
|
385
|
+
|
|
386
|
+
// src/component/ui/ContextMenu/ContextMenuItem.tsx
|
|
387
|
+
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
388
|
+
import { MdKeyboardArrowRight } from "react-icons/md";
|
|
389
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
390
|
+
var ContextMenuItem = ({
|
|
391
|
+
currentValue,
|
|
392
|
+
expandValue,
|
|
393
|
+
valueClickItem,
|
|
394
|
+
show,
|
|
395
|
+
isArrow
|
|
396
|
+
}) => {
|
|
397
|
+
const { t } = useTranslation3();
|
|
398
|
+
const Icon = currentValue.Icon;
|
|
399
|
+
return /* @__PURE__ */ jsxs3(
|
|
400
|
+
"div",
|
|
401
|
+
{
|
|
402
|
+
className: `cursor-pointer p-2 flex items-center space-x-2 relative ${show ? "bg-[#555] text-white" : "hover:bg-[#555] hover:text-white"}`,
|
|
403
|
+
onClick: () => {
|
|
404
|
+
var _a;
|
|
405
|
+
expandValue && valueClickItem && (currentValue == null ? void 0 : currentValue.onClick) && ((_a = currentValue == null ? void 0 : currentValue.onClick) == null ? void 0 : _a.call(currentValue, valueClickItem, expandValue));
|
|
406
|
+
},
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ jsx5(Icon, { size: 20 }),
|
|
409
|
+
/* @__PURE__ */ jsx5("span", { className: "text-sm flex-1", children: t(`${currentValue.action}`) }),
|
|
410
|
+
isArrow && /* @__PURE__ */ jsx5(MdKeyboardArrowRight, { size: 20 })
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
};
|
|
415
|
+
var ContextMenuItem_default = ContextMenuItem;
|
|
416
|
+
|
|
417
|
+
// src/component/ui/ContextMenu/DropdownContextChild.tsx
|
|
418
|
+
import Tippy from "@tippyjs/react";
|
|
419
|
+
import { useId, useRef as useRef3 } from "react";
|
|
420
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
421
|
+
var DropdownContextChild = ({ button, children, ...rest }) => {
|
|
422
|
+
const id = useId();
|
|
423
|
+
const instanceRef = useRef3(null);
|
|
424
|
+
return /* @__PURE__ */ jsx6(
|
|
425
|
+
Tippy,
|
|
426
|
+
{
|
|
427
|
+
theme: "drop-down",
|
|
428
|
+
className: "!bg-transparent !text-inherit !border-r-0 [&>*]:!p-0",
|
|
429
|
+
appendTo: document.body,
|
|
430
|
+
arrow: false,
|
|
431
|
+
placement: "auto",
|
|
432
|
+
interactive: true,
|
|
433
|
+
allowHTML: true,
|
|
434
|
+
content: children,
|
|
435
|
+
...rest,
|
|
436
|
+
children: /* @__PURE__ */ jsx6(
|
|
437
|
+
"div",
|
|
438
|
+
{
|
|
439
|
+
id: `div-${id}`,
|
|
440
|
+
onClick: () => {
|
|
441
|
+
var _a;
|
|
442
|
+
(_a = instanceRef == null ? void 0 : instanceRef.current) == null ? void 0 : _a.show();
|
|
443
|
+
},
|
|
444
|
+
children: button
|
|
445
|
+
}
|
|
446
|
+
)
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
};
|
|
450
|
+
var DropdownContextChild_default = DropdownContextChild;
|
|
451
|
+
|
|
452
|
+
// src/component/ui/ContextMenu/RenderContextMenu.tsx
|
|
453
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
454
|
+
var RenderContextMenu = ({
|
|
455
|
+
renderData,
|
|
456
|
+
valueClickItem,
|
|
457
|
+
expandValue = {}
|
|
458
|
+
}) => {
|
|
459
|
+
return /* @__PURE__ */ jsx7("div", { className: "bg-white shadow-submenu p-1 min-w-[250px] border", children: renderData == null ? void 0 : renderData.map((menuAction, index) => {
|
|
460
|
+
const [isShow, setIsShow] = useState2(false);
|
|
461
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
462
|
+
!(menuAction == null ? void 0 : menuAction.children) && /* @__PURE__ */ jsx7(
|
|
463
|
+
ContextMenuItem_default,
|
|
464
|
+
{
|
|
465
|
+
currentValue: menuAction,
|
|
466
|
+
expandValue,
|
|
467
|
+
valueClickItem
|
|
468
|
+
}
|
|
469
|
+
),
|
|
470
|
+
(menuAction == null ? void 0 : menuAction.children) && /* @__PURE__ */ jsx7(
|
|
471
|
+
DropdownContextChild_default,
|
|
472
|
+
{
|
|
473
|
+
appendTo: "parent",
|
|
474
|
+
placement: "right",
|
|
475
|
+
offset: [0, 5],
|
|
476
|
+
onShow: () => setIsShow(true),
|
|
477
|
+
onHide: () => setIsShow(false),
|
|
478
|
+
button: /* @__PURE__ */ jsx7(
|
|
479
|
+
ContextMenuItem_default,
|
|
480
|
+
{
|
|
481
|
+
currentValue: menuAction,
|
|
482
|
+
expandValue,
|
|
483
|
+
valueClickItem,
|
|
484
|
+
show: isShow,
|
|
485
|
+
isArrow: true
|
|
486
|
+
}
|
|
487
|
+
),
|
|
488
|
+
children: /* @__PURE__ */ jsx7("div", { className: "dropdown-context-child absolute -top-[20px] -left-1", children: /* @__PURE__ */ jsx7(
|
|
489
|
+
RenderContextMenu,
|
|
490
|
+
{
|
|
491
|
+
renderData: menuAction == null ? void 0 : menuAction.children,
|
|
492
|
+
expandValue,
|
|
493
|
+
valueClickItem
|
|
494
|
+
}
|
|
495
|
+
) })
|
|
496
|
+
}
|
|
497
|
+
)
|
|
498
|
+
] }, index);
|
|
499
|
+
}) });
|
|
500
|
+
};
|
|
501
|
+
var RenderContextMenu_default = RenderContextMenu;
|
|
502
|
+
|
|
503
|
+
// src/component/TableStyleContextWapper.tsx
|
|
504
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
505
|
+
var TableStyleContextMenuWapper = ({
|
|
506
|
+
children,
|
|
507
|
+
contextMenuProps,
|
|
508
|
+
clsTablecustom,
|
|
509
|
+
renderContext
|
|
510
|
+
}) => {
|
|
511
|
+
const idWapper = useId2();
|
|
512
|
+
return /* @__PURE__ */ jsxs5(
|
|
513
|
+
"div",
|
|
514
|
+
{
|
|
515
|
+
id: `wapper_menu_context-${idWapper}`,
|
|
516
|
+
className: `border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom != null ? clsTablecustom : ""}`,
|
|
517
|
+
children: [
|
|
518
|
+
(renderContext == null ? void 0 : renderContext.renderData) && /* @__PURE__ */ jsx8(
|
|
519
|
+
ContextMenu_default,
|
|
520
|
+
{
|
|
521
|
+
selector: `[id="wapper_menu_context-${idWapper}"] .rdg`,
|
|
522
|
+
...contextMenuProps,
|
|
523
|
+
children: /* @__PURE__ */ jsx8(RenderContextMenu_default, { ...renderContext })
|
|
524
|
+
}
|
|
525
|
+
),
|
|
526
|
+
children
|
|
527
|
+
]
|
|
528
|
+
}
|
|
529
|
+
);
|
|
530
|
+
};
|
|
531
|
+
var TableStyleContextWapper = memo2(
|
|
532
|
+
TableStyleContextMenuWapper
|
|
533
|
+
);
|
|
279
534
|
export {
|
|
280
|
-
ReactTableGridCustom
|
|
535
|
+
ReactTableGridCustom,
|
|
536
|
+
TableStyleContextWapper
|
|
281
537
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mkt-loitd/react-table-grid-custom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "React Table Grid Custom component",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"private": false,
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@mantine/core": "^8.3.10",
|
|
38
38
|
"@tanstack/react-query": "^5.90.12",
|
|
39
|
+
"@tippyjs/react": "^4.2.6",
|
|
39
40
|
"clsx": "^2.1.1",
|
|
40
41
|
"formik": "^2.4.9",
|
|
41
42
|
"i18next": "^25.7.3",
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
"moment": "^2.30.1",
|
|
45
46
|
"react-data-grid": "^7.0.0-beta.59",
|
|
46
47
|
"react-i18next": "^16.5.0",
|
|
48
|
+
"react-icons": "^5.5.0",
|
|
47
49
|
"react-select": "^5.10.2",
|
|
48
50
|
"tailwind-merge": "^3.4.0",
|
|
49
51
|
"typeorm": "^0.3.28"
|