nillud-data-table 1.3.6 → 1.4.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 +80 -66
- package/dist/export/export-excel/index.d.ts +24 -10
- package/dist/export/export-excel/index.js +55 -19
- package/dist/index.d.ts +6 -0
- package/dist/index.js +37 -19
- package/dist/styles.css +9 -0
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
# [React](https://react.dev/)
|
1
|
+
# [React](https://react.dev/) DataTable Component [](https://www.npmjs.com/package/data-table-lib)
|
2
2
|
|
3
3
|
## Возможности
|
4
4
|
|
5
5
|
✅ Сортировка и фильтрация
|
6
|
-
✅ Поддержка
|
6
|
+
✅ Поддержка кастомных фильтров
|
7
|
+
✅ Редактируемые ячейки
|
8
|
+
✅ Кастомизация контента в ячейках, возможность внедрять React-компоненты
|
9
|
+
✅ Открытые стили, свободное редактирование
|
7
10
|
✅ Группировка строк и заголовков
|
8
|
-
✅ Поддержка кастомных ячеек и фильтров
|
9
11
|
✅ Локальное сохранение состояния (localStorage)
|
10
12
|
✅ Поддержка React и TypeScript
|
13
|
+
✅ Поддержка экспорта в Excel и Word (Необходимо подключить отдельные модули)
|
11
14
|
|
12
15
|
## Установка
|
13
16
|
|
@@ -20,7 +23,6 @@ yarn add nillud-data-table
|
|
20
23
|
## Начало работы
|
21
24
|
|
22
25
|
#### **Быстрый пример (Quick Start)**
|
23
|
-
Сделай короткий рабочий пример (без кастомных кнопок, модалок и т. д.) — для тех, кто просто хочет запустить:
|
24
26
|
|
25
27
|
```tsx
|
26
28
|
import { DataTable } from 'nillud-data-table'
|
@@ -34,8 +36,6 @@ const data = [{ name: 'Иван' }]
|
|
34
36
|
|
35
37
|
#### **Развернутый пример**
|
36
38
|
|
37
|
-
Вызов со всеми пропсами:
|
38
|
-
|
39
39
|
```tsx
|
40
40
|
import { DataTable } from 'nillud-data-table'
|
41
41
|
import 'nillud-data-table/styles.css'
|
@@ -47,26 +47,15 @@ const columns = [{ field: 'name', title: 'Имя' }]
|
|
47
47
|
const data = [{ name: 'Иван' }]
|
48
48
|
|
49
49
|
<DataTable
|
50
|
+
tableData={tableData}
|
51
|
+
columns={columns}
|
50
52
|
tableName='custom-modal'
|
51
53
|
loading={loading}
|
52
|
-
loadingElement={
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
paginationCounts={[10, 20, 30, 40, 50, 0]}
|
57
|
-
scrollable
|
54
|
+
loadingElement={<div>Loading...</div>}
|
55
|
+
isFooter={true}
|
56
|
+
paginationCounts={[10, 50, 100, 0]}
|
57
|
+
scrollable={true}
|
58
58
|
scrollHeight={410}
|
59
|
-
excelBtn
|
60
|
-
wordBtn
|
61
|
-
WordExportComponent={WordExport}
|
62
|
-
ExportExcelComponent={ExportExcel}
|
63
|
-
downloadSectionLeftSideContent={<button className='base-button' onClick={() => setCanvas(true)}>OffCanvas</button>}
|
64
|
-
excelCustomColumns={[
|
65
|
-
{
|
66
|
-
key: 'name',
|
67
|
-
width: 50
|
68
|
-
}
|
69
|
-
]}
|
70
59
|
headerGroup={[{title: 'Личные данные', cols: 3}, {title: 'Объект', cols: 3}]}
|
71
60
|
groupBy={'status'}
|
72
61
|
isTitles={true}
|
@@ -75,25 +64,20 @@ const data = [{ name: 'Иван' }]
|
|
75
64
|
|
76
65
|
Доступные пропсы компонента:
|
77
66
|
|
78
|
-
| props | required | type | Описание
|
79
|
-
| :--- | :---: | :---: | :---
|
80
|
-
| [columns](#columns) | true | array [\{\}] | Принимает в себя массив объектов
|
81
|
-
| [tableData](#tabledata) | true | array [\{\}] | Принимает в себя массив объектов
|
82
|
-
| [tableName](#tablename) | true | string | Наименование таблицы для хранения значений в localStorage
|
83
|
-
| [loading](#loading) | - | boolean | Состояние загрузки, принимает в себя state типа boolean
|
84
|
-
| [loadingElement](#loadingelement) | - | React Element| Кастомный лоадер
|
85
|
-
| [isFooter](#isfooter) | - | boolean | Отображение footer
|
86
|
-
| [paginationCounts](#paginationcounts) | - | array<number> | Принимает массив чисел, число - количество строк для пагинации, (0 это все)
|
87
|
-
| [scrollable](#scrollable) | - | boolean | Зафиксировать высоту таблицы и добавить скролл
|
88
|
-
| [scrollHeight](#scrollheight) | - | number | Высота тела таблицы, работает, если scrollable: true
|
89
|
-
| [
|
90
|
-
| [exportCustomColumns](#exportcustomcolumns) | - | array [\{\}] | Принимает в себя массив объектов (\{\ key: string, width: number \}\) |
|
91
|
-
| [excelBtn](#excelbtn) | - | boolean | Показывать кнопку экспорта Excel |
|
92
|
-
| [wordBtn](#wordbtn) | - | boolean | Показывать кнопку экспорта Word |
|
93
|
-
| [downloadSectionLeftSideContent](#downloadsectionleftsidecontent) | - | React Element| Отображать контент с левой стороны от кнопок экспорта |
|
94
|
-
| [headerGroup](#headergroup) | - | array [\{\}] | Группировка столбцов (\{\ title: string, cols: number \}\) |
|
67
|
+
| props | required | type | Описание |
|
68
|
+
| :--- | :---: | :---: | :--- |
|
69
|
+
| [columns](#columns) | true | array [\{\}] | Принимает в себя массив объектов |
|
70
|
+
| [tableData](#tabledata) | true | array [\{\}] | Принимает в себя массив объектов |
|
71
|
+
| [tableName](#tablename) | true | string | Наименование таблицы для хранения значений в localStorage |
|
72
|
+
| [loading](#loading) | - | boolean | Состояние загрузки, принимает в себя state типа boolean |
|
73
|
+
| [loadingElement](#loadingelement) | - | React Element| Кастомный лоадер |
|
74
|
+
| [isFooter](#isfooter) | - | boolean | Отображение footer |
|
75
|
+
| [paginationCounts](#paginationcounts) | - | array<number> | Принимает массив чисел, число - количество строк для пагинации, (0 это все) |
|
76
|
+
| [scrollable](#scrollable) | - | boolean | Зафиксировать высоту таблицы и добавить скролл |
|
77
|
+
| [scrollHeight](#scrollheight) | - | number | Высота тела таблицы, работает, если scrollable: true |
|
78
|
+
| [headerGroup](#headergroup) | - | array [\{\}] | Группировка столбцов (\{\ title: string, cols: number \}\) |
|
95
79
|
| [groupBy](#groupby) | - | string | Группировка данных, указывается заголовок столбца, по которому нужна группировка |
|
96
|
-
| [isTitles](#istitles) | - | boolean | Заголовки при наведении на ячейку, по умолчанию false
|
80
|
+
| [isTitles](#istitles) | - | boolean | Заголовки при наведении на ячейку, по умолчанию false |
|
97
81
|
|
98
82
|
Типы описаны components/data-table/DataTable.types.ts
|
99
83
|
|
@@ -113,6 +97,12 @@ const data = [{ name: 'Иван' }]
|
|
113
97
|
|
114
98
|
```tsx
|
115
99
|
const columns = [
|
100
|
+
{
|
101
|
+
field: '',
|
102
|
+
title: '',
|
103
|
+
width: 50,
|
104
|
+
selectable: true
|
105
|
+
},
|
116
106
|
{
|
117
107
|
field: 'id',
|
118
108
|
title: '№',
|
@@ -123,6 +113,7 @@ const columns = [
|
|
123
113
|
field: 'name',
|
124
114
|
title: 'Наименование',
|
125
115
|
filterable: false,
|
116
|
+
isSelectableCell: false,
|
126
117
|
formatter: function (cell, row) {
|
127
118
|
return (
|
128
119
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
@@ -131,14 +122,12 @@ const columns = [
|
|
131
122
|
</div>
|
132
123
|
)
|
133
124
|
},
|
134
|
-
exportCustomCell: function (cell, row) {
|
135
|
-
return `${cell} - ${row.date_to}`
|
136
|
-
},
|
137
125
|
},
|
138
126
|
{
|
139
127
|
field: 'address',
|
140
128
|
title: 'Адрес',
|
141
|
-
headerFilter: headerFilterAddress
|
129
|
+
headerFilter: headerFilterAddress,
|
130
|
+
editable: true
|
142
131
|
},
|
143
132
|
{
|
144
133
|
field: 'obj',
|
@@ -150,18 +139,22 @@ const columns = [
|
|
150
139
|
|
151
140
|
Доступные ключи объекта:
|
152
141
|
|
153
|
-
| key
|
154
|
-
| :---
|
155
|
-
| [field](#field)
|
156
|
-
| [title](#title)
|
157
|
-
| [width](#width)
|
158
|
-
| [autoinc](#autoinc)
|
159
|
-
| [formatter](#formatter)
|
160
|
-
| [
|
161
|
-
| [
|
162
|
-
| [
|
163
|
-
| [
|
164
|
-
| [
|
142
|
+
| key | required | type | description |
|
143
|
+
| :--- | :---: | :---: | :--- |
|
144
|
+
| [field](#field) | true | string | Устанавливает связь по ключу в массиве данных tableData |
|
145
|
+
| [title](#title) | true | string | Устанавливает заголовок столбца |
|
146
|
+
| [width](#width) | - | number | Принимает числовое значение, ограничивает ширину столбца в пикселях |
|
147
|
+
| [autoinc](#autoinc) | - | bool | Форматирует значения в столбце по порядку в таблице, начиная с 1 |
|
148
|
+
| [formatter](#formatter) | - | func | Кастомное форматирование, принимает в себя функцию, описание далее |
|
149
|
+
| [headerFormatter](#headerFormatter) | - | func | Кастомное форматирование заголовка колонки, принимает в себя функцию, описание далее |
|
150
|
+
| [exportCustomCell](#exportCustomCell) | - | func | Кастомное форматирование для Excel и Word, принимает в себя функцию, описание далее |
|
151
|
+
| [headerFilter](#headerFilter) | - | func | Кастомный фильтр, принимает в себя функуцию, описание далее |
|
152
|
+
| [sortable](#sortable) | - | bool | Убирает возможность сортировки, по умолчанию true |
|
153
|
+
| [filterable](#filterable) | - | bool | Убирает возможность фильтрации, по умолчанию true |
|
154
|
+
| [selectable](#selectable) | - | bool | Добавляет возможность отмечать строки таблицы |
|
155
|
+
| [isSelectableCell](#isSelectableCell) | - | bool | При активном selectable убирает у ячейки функцию отметить строку при нажатии |
|
156
|
+
| [filterPlaceholder](#filterPlaceholder)| - | string | Задать плейсхолдер для фильтра в инпуте колонки |
|
157
|
+
| [editable](#editable) | - | bool | Добавляет возможность редактирования ячейки |
|
165
158
|
|
166
159
|
#### field
|
167
160
|
|
@@ -233,7 +226,24 @@ const columns = [
|
|
233
226
|
return (
|
234
227
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
235
228
|
<span style={{ marginBottom: 3 }}>{cell}</span>
|
236
|
-
<span style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => { setModalShow(true); setRowData(row) }}><PenEdit /></span>
|
229
|
+
<span style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => { setModalShow(true); setRowData(row); }}><PenEdit /></span>
|
230
|
+
</div>
|
231
|
+
)
|
232
|
+
},
|
233
|
+
}
|
234
|
+
```
|
235
|
+
|
236
|
+
#### headerFormatter
|
237
|
+
|
238
|
+
Кастомное отображение заголовка таблицы. Принимает в себя функцию с аргументом column.title, должна возвращать React Component.
|
239
|
+
|
240
|
+
```tsx
|
241
|
+
{
|
242
|
+
...,
|
243
|
+
headerFormatter: function (column) {
|
244
|
+
return (
|
245
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
246
|
+
<div>Something {column} <Icon size={20} /></div>
|
237
247
|
</div>
|
238
248
|
)
|
239
249
|
},
|
@@ -325,6 +335,18 @@ const headerFilterAddress = (headerValue, rowValue) => {
|
|
325
335
|
const selectedData = tableRef.current.getSelectedData()
|
326
336
|
```
|
327
337
|
|
338
|
+
#### isSelectableCell
|
339
|
+
|
340
|
+
Наличие функции выбора строки при активном **selectable**, в случе если есть логика кнопки или какого то действия, при котором не надо выполнять select строки
|
341
|
+
|
342
|
+
#### filterPlaceholder
|
343
|
+
|
344
|
+
Добавление плейсхолдера для инпута фильтрации в заголовке колонки
|
345
|
+
|
346
|
+
#### editable
|
347
|
+
|
348
|
+
Добавляет возможность редактирования строки. По умолчанию **false**
|
349
|
+
|
328
350
|
### tableData
|
329
351
|
|
330
352
|
Обязательный параметр, принимает в себя массив объектов. В простой реализации таблицы в массиве **tableData** объекты должны содержать ключи равные значениям ключа **field** объекта в массиве **columns**
|
@@ -576,12 +598,4 @@ options = {{
|
|
576
598
|
exportCustomColumns={[{...}, {...}]}
|
577
599
|
wordOptions={{...}}
|
578
600
|
/>
|
579
|
-
```
|
580
|
-
|
581
|
-
##### downloadSectionLeftSideContent
|
582
|
-
|
583
|
-
Необязательный параметр. Передается **React.Component**. Отображает компонент с левой стороны от кнопок экспорта. Создано для экономии места
|
584
|
-
|
585
|
-
```tsx
|
586
|
-
downloadSectionLeftSideContent={<button className='base-button' onClick={() => setCanvas(true)}>OffCanvas</button>}
|
587
601
|
```
|
@@ -1,35 +1,49 @@
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
2
2
|
import { ReactElement } from 'react';
|
3
|
+
import { CellValue } from 'exceljs';
|
3
4
|
|
4
5
|
type TableElement = {
|
5
6
|
[key: string]: string | number;
|
6
7
|
};
|
7
|
-
type TableData = Array<TableElement>;
|
8
8
|
type Column = {
|
9
9
|
field: string;
|
10
10
|
title: string;
|
11
11
|
width?: number;
|
12
12
|
autoinc?: boolean;
|
13
|
-
formatter?: (cell: string, row: TableElement) => ReactElement;
|
14
|
-
|
15
|
-
|
13
|
+
formatter?: (cell: string, row: TableElement, column: Column) => ReactElement;
|
14
|
+
headerFormatter?: (column: string) => ReactElement;
|
15
|
+
exportCustomCell?: (title: string, row: TableElement) => string;
|
16
|
+
cellAlignment?: CellAlignment;
|
17
|
+
headerFilter?: (headerValue: string, rowValue: string) => boolean;
|
16
18
|
sortable?: boolean;
|
17
19
|
filterable?: boolean;
|
20
|
+
selectable?: boolean;
|
21
|
+
isSelectableCell?: boolean;
|
22
|
+
filterPlaceholder?: string;
|
23
|
+
editable?: boolean;
|
18
24
|
};
|
19
25
|
type CustomColumn = {
|
20
|
-
header
|
26
|
+
header?: string;
|
21
27
|
key: string;
|
22
28
|
width?: number;
|
29
|
+
exportCustomCell?: (value: string, row: TableElement) => string | CellValue;
|
23
30
|
[key: string]: any;
|
24
31
|
};
|
25
|
-
type
|
32
|
+
type CellAlignment = {
|
33
|
+
vertical: 'top' | 'middle' | 'bottom';
|
34
|
+
horizontal: 'left' | 'center' | 'right';
|
35
|
+
};
|
26
36
|
type ExcelExportTypes = {
|
27
37
|
columns: Array<Column>;
|
28
|
-
excelData
|
29
|
-
|
30
|
-
|
38
|
+
excelData?: Array<TableElement>;
|
39
|
+
tableRef?: any;
|
40
|
+
titleFile: string;
|
41
|
+
title?: string;
|
42
|
+
text?: string;
|
43
|
+
exportCustomColumns?: Array<CustomColumn>;
|
44
|
+
customHeight?: number;
|
31
45
|
};
|
32
46
|
|
33
|
-
declare const ExportExcel: ({ columns, excelData, title, exportCustomColumns }: ExcelExportTypes) => react_jsx_runtime.JSX.Element;
|
47
|
+
declare const ExportExcel: ({ columns, excelData, tableRef, titleFile, title, text, exportCustomColumns, customHeight }: ExcelExportTypes) => react_jsx_runtime.JSX.Element;
|
34
48
|
|
35
49
|
export { type ExcelExportTypes, ExportExcel };
|
@@ -1,7 +1,7 @@
|
|
1
1
|
// components/export/export-excel/exportUtils.ts
|
2
2
|
var generateExcelColumns = (columns, exportCustomColumns) => {
|
3
|
-
let excelColumns = columns.map((column) => ({
|
4
|
-
|
3
|
+
let excelColumns = columns.filter((column) => column.title !== "").map((column) => ({
|
4
|
+
title: column.title,
|
5
5
|
key: column.field,
|
6
6
|
width: 20
|
7
7
|
}));
|
@@ -29,13 +29,18 @@ var applyHeaderStyles = (row, columnCount) => {
|
|
29
29
|
};
|
30
30
|
}
|
31
31
|
};
|
32
|
-
var applyRowStyles = (row, columnCount) => {
|
33
|
-
row.height =
|
32
|
+
var applyRowStyles = (row, columnCount, height = 40, columns) => {
|
33
|
+
row.height = height;
|
34
34
|
row.font = { size: 12 };
|
35
35
|
row.alignment = { vertical: "middle", horizontal: "center" };
|
36
36
|
for (let i = 1; i <= columnCount; i++) {
|
37
37
|
const cell = row.getCell(i);
|
38
|
-
|
38
|
+
const column = columns[i - 1];
|
39
|
+
cell.alignment = {
|
40
|
+
wrapText: true,
|
41
|
+
vertical: column.cellAlignment ? column.cellAlignment.vertical : "middle",
|
42
|
+
horizontal: column.cellAlignment ? column.cellAlignment.horizontal : "center"
|
43
|
+
};
|
39
44
|
cell.border = {
|
40
45
|
top: { style: "thin" },
|
41
46
|
left: { style: "thin" },
|
@@ -44,14 +49,21 @@ var applyRowStyles = (row, columnCount) => {
|
|
44
49
|
};
|
45
50
|
}
|
46
51
|
};
|
47
|
-
var generateExcelDataRows = (columns, data) => {
|
48
|
-
return data.map((element) => {
|
49
|
-
|
50
|
-
|
52
|
+
var generateExcelDataRows = (columns, data, exportCustomColumns) => {
|
53
|
+
return data.map((element, rowIndex) => {
|
54
|
+
return columns.map((col, colIndex) => {
|
55
|
+
const isAutoinc = col.autoinc;
|
56
|
+
if (isAutoinc) return rowIndex + 1;
|
51
57
|
const value = element[col.field];
|
52
|
-
|
58
|
+
const customCol = exportCustomColumns == null ? void 0 : exportCustomColumns.find((custom) => custom.key === col.field);
|
59
|
+
if (customCol == null ? void 0 : customCol.exportCustomCell) {
|
60
|
+
return customCol.exportCustomCell(String(value != null ? value : ""), element);
|
61
|
+
}
|
62
|
+
if (typeof col.exportCustomCell !== "undefined") {
|
63
|
+
return col.exportCustomCell(String(value != null ? value : ""), element);
|
64
|
+
}
|
65
|
+
return value != null ? value : "";
|
53
66
|
});
|
54
|
-
return rowData;
|
55
67
|
});
|
56
68
|
};
|
57
69
|
var setColumnAutoWidths = (sheet) => {
|
@@ -70,10 +82,11 @@ var setColumnAutoWidths = (sheet) => {
|
|
70
82
|
// components/export/export-excel/ExportExcel.tsx
|
71
83
|
import ExcelJS from "exceljs";
|
72
84
|
import { jsx } from "react/jsx-runtime";
|
73
|
-
var ExportExcel = ({ columns, excelData, title, exportCustomColumns }) => {
|
85
|
+
var ExportExcel = ({ columns, excelData, tableRef, titleFile, title, text, exportCustomColumns, customHeight }) => {
|
74
86
|
const exportExcel = async () => {
|
87
|
+
const tableData = excelData || tableRef.current.getData();
|
75
88
|
const workbook = new ExcelJS.Workbook();
|
76
|
-
const sheet = workbook.addWorksheet(
|
89
|
+
const sheet = workbook.addWorksheet(titleFile, {
|
77
90
|
pageSetup: {
|
78
91
|
fitToPage: true,
|
79
92
|
fitToHeight: 2,
|
@@ -85,18 +98,41 @@ var ExportExcel = ({ columns, excelData, title, exportCustomColumns }) => {
|
|
85
98
|
evenFooter: "\u0421\u0442\u0440\u0430\u043D\u0438\u0446\u0430 &P \u0438\u0437 &N"
|
86
99
|
}
|
87
100
|
});
|
101
|
+
sheet.properties.defaultRowHeight = 20;
|
102
|
+
let tableHeaderRow = 1;
|
103
|
+
if (title) {
|
104
|
+
sheet.getCell("A1").value = title;
|
105
|
+
sheet.getRow(1).height = 25;
|
106
|
+
sheet.getRow(1).alignment = { vertical: "middle" };
|
107
|
+
sheet.getCell("A1").font = {
|
108
|
+
size: 18,
|
109
|
+
bold: true
|
110
|
+
};
|
111
|
+
tableHeaderRow++;
|
112
|
+
}
|
113
|
+
if (text) {
|
114
|
+
sheet.getCell("A2").value = text;
|
115
|
+
sheet.getRow(2).height = 15;
|
116
|
+
sheet.getRow(2).alignment = { vertical: "middle" };
|
117
|
+
sheet.getCell("A2").font = {
|
118
|
+
size: 12
|
119
|
+
};
|
120
|
+
tableHeaderRow++;
|
121
|
+
}
|
122
|
+
if (title || text) tableHeaderRow++;
|
88
123
|
const excelColumns = generateExcelColumns(columns, exportCustomColumns);
|
89
124
|
sheet.columns = excelColumns;
|
90
|
-
const headerRow = sheet.getRow(
|
125
|
+
const headerRow = sheet.getRow(tableHeaderRow);
|
126
|
+
headerRow.values = excelColumns.map((col) => col.title);
|
91
127
|
applyHeaderStyles(headerRow, sheet.columns.length);
|
92
|
-
const dataRows = generateExcelDataRows(columns,
|
128
|
+
const dataRows = generateExcelDataRows(columns, tableData);
|
93
129
|
dataRows.forEach((data) => {
|
94
130
|
const row = sheet.addRow(data);
|
95
|
-
applyRowStyles(row, sheet.columns.length);
|
131
|
+
applyRowStyles(row, sheet.columns.length, customHeight, columns);
|
96
132
|
});
|
97
133
|
setColumnAutoWidths(sheet);
|
98
|
-
if (
|
99
|
-
sheet.pageSetup.fitToHeight = Math.floor(
|
134
|
+
if (tableData.length > 15) {
|
135
|
+
sheet.pageSetup.fitToHeight = Math.floor(tableData.length / 15);
|
100
136
|
} else {
|
101
137
|
sheet.pageSetup.fitToHeight = 1;
|
102
138
|
}
|
@@ -107,7 +143,7 @@ var ExportExcel = ({ columns, excelData, title, exportCustomColumns }) => {
|
|
107
143
|
const url = window.URL.createObjectURL(blob);
|
108
144
|
const anchor = document.createElement("a");
|
109
145
|
anchor.href = url;
|
110
|
-
anchor.download = `${
|
146
|
+
anchor.download = `${titleFile}.xlsx`;
|
111
147
|
anchor.click();
|
112
148
|
window.URL.revokeObjectURL(url);
|
113
149
|
});
|
package/dist/index.d.ts
CHANGED
@@ -4,6 +4,10 @@ type TableElement = {
|
|
4
4
|
[key: string]: string | number;
|
5
5
|
};
|
6
6
|
type TableData = Array<TableElement>;
|
7
|
+
type CellAlignment = {
|
8
|
+
vertical: 'top' | 'middle' | 'bottom';
|
9
|
+
horizontal: 'left' | 'center' | 'right';
|
10
|
+
};
|
7
11
|
type Column = {
|
8
12
|
field: string;
|
9
13
|
title: string;
|
@@ -12,12 +16,14 @@ type Column = {
|
|
12
16
|
formatter?: (cell: string, row: TableElement, column: Column) => ReactElement;
|
13
17
|
headerFormatter?: (column: string) => ReactElement;
|
14
18
|
exportCustomCell?: (title: string, row: TableElement) => string;
|
19
|
+
cellAlignment?: CellAlignment;
|
15
20
|
headerFilter?: (headerValue: string, rowValue: string) => boolean;
|
16
21
|
sortable?: boolean;
|
17
22
|
filterable?: boolean;
|
18
23
|
selectable?: boolean;
|
19
24
|
isSelectableCell?: boolean;
|
20
25
|
filterPlaceholder?: string;
|
26
|
+
editable?: boolean;
|
21
27
|
};
|
22
28
|
type Columns = Column[];
|
23
29
|
type TableProps = {
|
package/dist/index.js
CHANGED
@@ -104,7 +104,7 @@ var TableHeader_default = React.memo(Header);
|
|
104
104
|
import React2 from "react";
|
105
105
|
|
106
106
|
// components/data-table/Cell.tsx
|
107
|
-
import {
|
107
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
108
108
|
var Cell = ({
|
109
109
|
row,
|
110
110
|
column,
|
@@ -112,23 +112,50 @@ var Cell = ({
|
|
112
112
|
displayId,
|
113
113
|
isTitles,
|
114
114
|
isRowSelected,
|
115
|
-
onRowSelect
|
115
|
+
onRowSelect,
|
116
|
+
isSelectable
|
116
117
|
}) => {
|
117
118
|
const rawValue = row[column.field];
|
118
119
|
const stringValue = typeof rawValue !== "undefined" && rawValue !== null ? String(rawValue) : "";
|
119
|
-
const
|
120
|
-
const
|
120
|
+
const isAutoinc = !!column.autoinc;
|
121
|
+
const isFormatted = typeof column.formatter !== "undefined";
|
122
|
+
const isEditable = !!column.editable;
|
123
|
+
const isColumnSelectable = !!column.selectable;
|
124
|
+
const formattedContent = column.formatter && column.formatter(stringValue, row, column);
|
125
|
+
const CellWithData = ({ children }) => /* @__PURE__ */ jsx5(
|
121
126
|
"div",
|
122
127
|
{
|
123
128
|
className: "ndt-cell",
|
124
129
|
title: isTitles && stringValue ? stringValue : "",
|
125
|
-
onClick: typeof column.isSelectableCell === "undefined" || column.isSelectableCell ? onRowSelect : () => {
|
130
|
+
onClick: isSelectable && (typeof column.isSelectableCell === "undefined" || column.isSelectableCell || column.editable) ? onRowSelect : () => {
|
126
131
|
},
|
127
|
-
children
|
132
|
+
children
|
133
|
+
}
|
134
|
+
);
|
135
|
+
const EditableCell = () => /* @__PURE__ */ jsx5(
|
136
|
+
"input",
|
137
|
+
{
|
138
|
+
className: "ndt-cell ndt-cell-editable",
|
139
|
+
defaultValue: stringValue ? String(stringValue) : "",
|
140
|
+
onChange: (e) => {
|
141
|
+
row[column.field] = e.target.value;
|
142
|
+
}
|
128
143
|
}
|
129
144
|
);
|
130
|
-
const
|
131
|
-
|
145
|
+
const SelectableCell = () => /* @__PURE__ */ jsx5("div", { className: "ndt-cell ndt-checkbox-cell", onClick: onRowSelect, children: /* @__PURE__ */ jsx5("input", { type: "checkbox", checked: !!isRowSelected, onChange: () => {
|
146
|
+
} }) });
|
147
|
+
switch (true) {
|
148
|
+
case isAutoinc:
|
149
|
+
return /* @__PURE__ */ jsx5(CellWithData, { children: displayId + 1 });
|
150
|
+
case isFormatted:
|
151
|
+
return /* @__PURE__ */ jsx5(CellWithData, { children: formattedContent });
|
152
|
+
case isEditable:
|
153
|
+
return /* @__PURE__ */ jsx5(EditableCell, {});
|
154
|
+
case isColumnSelectable:
|
155
|
+
return /* @__PURE__ */ jsx5(SelectableCell, {});
|
156
|
+
default:
|
157
|
+
return /* @__PURE__ */ jsx5(CellWithData, { children: stringValue });
|
158
|
+
}
|
132
159
|
};
|
133
160
|
var Cell_default = Cell;
|
134
161
|
|
@@ -158,7 +185,8 @@ var Row = ({
|
|
158
185
|
displayId,
|
159
186
|
isTitles,
|
160
187
|
isRowSelected,
|
161
|
-
onRowSelect
|
188
|
+
onRowSelect,
|
189
|
+
isSelectable: !!isSelectable
|
162
190
|
},
|
163
191
|
`cell-${rowId}-${id}`
|
164
192
|
))
|
@@ -545,12 +573,8 @@ var DataTable = forwardRef(({
|
|
545
573
|
try {
|
546
574
|
const s = localStorage.getItem(`${tableName}-sort-by`);
|
547
575
|
const f = localStorage.getItem(`${tableName}-filters`);
|
548
|
-
const c = localStorage.getItem(`${tableName}-counts`);
|
549
|
-
const p = localStorage.getItem(`${tableName}-page`);
|
550
576
|
if (s) setSortBy(JSON.parse(s));
|
551
577
|
if (f) setFilters(JSON.parse(f));
|
552
|
-
if (c) setPaginationSize(c === "all" ? 0 : Number(c));
|
553
|
-
if (p) setPaginationPage(Number(p));
|
554
578
|
} catch (e) {
|
555
579
|
console.error("Error parsing localStorage data:", e);
|
556
580
|
setSortBy({ col: "", type: "asc" });
|
@@ -599,12 +623,6 @@ var DataTable = forwardRef(({
|
|
599
623
|
useDebouncedEffect(() => {
|
600
624
|
localStorage.setItem(`${tableName}-sort-by`, JSON.stringify(sortBy));
|
601
625
|
}, [sortBy, tableName], 500);
|
602
|
-
useEffect2(() => {
|
603
|
-
localStorage.setItem(`${tableName}-counts`, paginationSize === 0 ? "all" : paginationSize.toString());
|
604
|
-
}, [paginationSize, tableName]);
|
605
|
-
useEffect2(() => {
|
606
|
-
localStorage.setItem(`${tableName}-page`, paginationPage.toString());
|
607
|
-
}, [paginationPage, tableName]);
|
608
626
|
useImperativeHandle(ref, () => ({
|
609
627
|
getData: () => processedData,
|
610
628
|
getCurrentData: () => displayData,
|
package/dist/styles.css
CHANGED
@@ -110,6 +110,15 @@
|
|
110
110
|
font-size: 16px;
|
111
111
|
font-weight: 400;
|
112
112
|
}
|
113
|
+
.ndt-table-container .ndt-table .ndt-table-body .ndt-table-row .ndt-cell.ndt-cell-editable {
|
114
|
+
border: none;
|
115
|
+
background-color: transparent;
|
116
|
+
}
|
117
|
+
.ndt-table-container .ndt-table .ndt-table-body .ndt-table-row .ndt-cell.ndt-cell-editable:focus, .ndt-table-container .ndt-table .ndt-table-body .ndt-table-row .ndt-cell.ndt-cell-editable:focus-visible, .ndt-table-container .ndt-table .ndt-table-body .ndt-table-row .ndt-cell.ndt-cell-editable:active {
|
118
|
+
outline: 1px solid rgba(34, 34, 34, 0.6);
|
119
|
+
border: none;
|
120
|
+
box-shadow: none;
|
121
|
+
}
|
113
122
|
.ndt-table-container .ndt-table .ndt-table-body .ndt-table-row .ndt-cell:not(:last-child) {
|
114
123
|
border-right: 1px solid #ddd;
|
115
124
|
}
|
package/dist/styles.css.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sourceRoot":"","sources":["../components/data-table/styles/data-table.scss"],"names":[],"mappings":";AACI;EACI;EACA;;AAEA;AAAA;EAEI;;AAGJ;AAAA;EAEI;;AAGJ;EACI;;AAEA;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAMR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAMhB;EACI;;AAEA;EACI;EACA;EACA;;AAGA;EACI;AACA;;AAGJ;EACI;AACA;EACA;AACA;;AAGJ;EACI;AACA;EACA;AACA;;AAGJ;EACI;AACA;;AAKJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;AAGJ;EACI;;AAEA;EAEI;;AAIR;EAEI;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAMhB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;;AAGI;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EAGI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;;AAEA;EACI;;AAEA;EACI;EACA;EACA;;;AAUhC;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAEA;EAGI;EACA;EACA;;AAIR;EACI;;AAEA;EAGI;EACA;EACA;;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAIA;EACI","file":"styles.css"}
|
1
|
+
{"version":3,"sourceRoot":"","sources":["../components/data-table/styles/data-table.scss"],"names":[],"mappings":";AACI;EACI;EACA;;AAEA;AAAA;EAEI;;AAGJ;AAAA;EAEI;;AAGJ;EACI;;AAEA;EACI;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAMR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAMhB;EACI;;AAEA;EACI;EACA;EACA;;AAGA;EACI;AACA;;AAGJ;EACI;AACA;EACA;AACA;;AAGJ;EACI;AACA;EACA;AACA;;AAGJ;EACI;AACA;;AAKJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;AAGJ;EACI;;AAEA;EAEI;;AAIR;EAEI;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAEA;EAGI;EACA;EACA;;AAIR;EACI;;AAMhB;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;;AAGI;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EAGI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;;AAEA;EACI;;AAEA;EACI;EACA;EACA;;;AAUhC;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAEA;EAGI;EACA;EACA;;AAIR;EACI;;AAEA;EAGI;EACA;EACA;;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAIA;EACI","file":"styles.css"}
|