@tcn/ui-table 2.2.0 → 2.3.0
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 +1 -1
- package/dist/cell.css +1 -0
- package/dist/cell.module-WpHnQBVu.js +5 -0
- package/dist/cell.module-WpHnQBVu.js.map +1 -0
- package/dist/components/cells/data_cell.d.ts +3 -2
- package/dist/components/cells/data_cell.d.ts.map +1 -0
- package/dist/components/cells/data_cell.js +18 -10
- package/dist/components/cells/data_cell.js.map +1 -1
- package/dist/components/cells/footer_cell.d.ts +3 -2
- package/dist/components/cells/footer_cell.d.ts.map +1 -0
- package/dist/components/cells/footer_cell.js +18 -10
- package/dist/components/cells/footer_cell.js.map +1 -1
- package/dist/components/cells/header_cell.d.ts +3 -2
- package/dist/components/cells/header_cell.d.ts.map +1 -0
- package/dist/components/cells/header_cell.js +52 -18
- package/dist/components/cells/header_cell.js.map +1 -1
- package/dist/components/cells/sticky_row_data_cell.d.ts +3 -2
- package/dist/components/cells/sticky_row_data_cell.d.ts.map +1 -0
- package/dist/components/cells/sticky_row_data_cell.js +26 -11
- package/dist/components/cells/sticky_row_data_cell.js.map +1 -1
- package/dist/components/cells/sticky_row_fill_cell.d.ts +2 -2
- package/dist/components/cells/sticky_row_fill_cell.d.ts.map +1 -0
- package/dist/components/cells/sticky_row_fill_cell.js +15 -5
- package/dist/components/cells/sticky_row_fill_cell.js.map +1 -1
- package/dist/components/global_search.d.ts +2 -2
- package/dist/components/global_search.d.ts.map +1 -0
- package/dist/components/global_search.js +26 -9
- package/dist/components/global_search.js.map +1 -1
- package/dist/components/global_search_presenter.d.ts +2 -1
- package/dist/components/global_search_presenter.d.ts.map +1 -0
- package/dist/components/global_search_presenter.js +20 -18
- package/dist/components/global_search_presenter.js.map +1 -1
- package/dist/components/table/table.d.ts +3 -2
- package/dist/components/table/table.d.ts.map +1 -0
- package/dist/components/table/table.js +140 -77
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/table/table_column.d.ts +1 -1
- package/dist/components/table/table_column.d.ts.map +1 -0
- package/dist/components/table/table_column.js +6 -5
- package/dist/components/table/table_column.js.map +1 -1
- package/dist/components/table/table_presenter.d.ts +3 -2
- package/dist/components/table/table_presenter.d.ts.map +1 -0
- package/dist/components/table/table_presenter.js +45 -62
- package/dist/components/table/table_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/date_field_filter.d.ts +2 -2
- package/dist/components/table_filter_panel/field_filters/date_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/date_field_filter.js +59 -33
- package/dist/components/table_filter_panel/field_filters/date_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.d.ts +4 -3
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.js +57 -91
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/field_filter_props.d.ts +1 -0
- package/dist/components/table_filter_panel/field_filters/field_filter_props.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/field_filter_strategy.d.ts +1 -0
- package/dist/components/table_filter_panel/field_filters/field_filter_strategy.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/mulit_select_field_filter.d.ts +3 -3
- package/dist/components/table_filter_panel/field_filters/mulit_select_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/mulit_select_field_filter.js +52 -29
- package/dist/components/table_filter_panel/field_filters/mulit_select_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.d.ts +3 -2
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.js +53 -70
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/number_field_filter.d.ts +3 -3
- package/dist/components/table_filter_panel/field_filters/number_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/number_field_filter.js +47 -23
- package/dist/components/table_filter_panel/field_filters/number_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.d.ts +5 -4
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.js +53 -58
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter.d.ts +2 -2
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter.js +61 -31
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.d.ts +4 -3
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.js +57 -91
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/select_field_filter.d.ts +3 -3
- package/dist/components/table_filter_panel/field_filters/select_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/select_field_filter.js +49 -24
- package/dist/components/table_filter_panel/field_filters/select_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.d.ts +3 -2
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.js +49 -53
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/string_field_filter.d.ts +3 -3
- package/dist/components/table_filter_panel/field_filters/string_field_filter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/string_field_filter.js +62 -33
- package/dist/components/table_filter_panel/field_filters/string_field_filter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.d.ts +5 -4
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.js +54 -59
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/field_filters/use_field_filter_strategy.d.ts +2 -1
- package/dist/components/table_filter_panel/field_filters/use_field_filter_strategy.d.ts.map +1 -0
- package/dist/components/table_filter_panel/field_filters/use_field_filter_strategy.js +13 -19
- package/dist/components/table_filter_panel/field_filters/use_field_filter_strategy.js.map +1 -1
- package/dist/components/table_filter_panel/table_filter_panel.d.ts +5 -4
- package/dist/components/table_filter_panel/table_filter_panel.d.ts.map +1 -0
- package/dist/components/table_filter_panel/table_filter_panel.js +15 -11
- package/dist/components/table_filter_panel/table_filter_panel.js.map +1 -1
- package/dist/components/table_filter_panel/table_filter_panel_presenter.d.ts +2 -2
- package/dist/components/table_filter_panel/table_filter_panel_presenter.d.ts.map +1 -0
- package/dist/components/table_filter_panel/table_filter_panel_presenter.js +45 -62
- package/dist/components/table_filter_panel/table_filter_panel_presenter.js.map +1 -1
- package/dist/components/table_filter_panel/types.d.ts +1 -0
- package/dist/components/table_filter_panel/types.d.ts.map +1 -0
- package/dist/components/table_filter_panel/types.js +5 -2
- package/dist/components/table_filter_panel/types.js.map +1 -1
- package/dist/components/table_pager.d.ts +2 -2
- package/dist/components/table_pager.d.ts.map +1 -0
- package/dist/components/table_pager.js +22 -20
- package/dist/components/table_pager.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -13
- package/dist/index.js.map +1 -1
- package/dist/table.css +1 -0
- package/dist/table_pager.css +1 -0
- package/package.json +61 -61
- package/src/__stories__/aip_table.stories.tsx +190 -0
- package/src/__stories__/auth_provider.tsx +14 -0
- package/src/__stories__/demo.stories.tsx +137 -0
- package/src/__stories__/sample_data.ts +1398 -0
- package/src/__stories__/table.stories.tsx +423 -0
- package/src/__tests__/sanity.test.ts +7 -0
- package/src/components/cells/data_cell.tsx +25 -0
- package/src/components/cells/footer_cell.tsx +25 -0
- package/src/components/cells/header_cell.tsx +77 -0
- package/src/components/cells/sticky_row_data_cell.tsx +31 -0
- package/src/components/cells/sticky_row_fill_cell.tsx +16 -0
- package/src/components/global_search.tsx +33 -0
- package/src/components/global_search_presenter.ts +24 -0
- package/{dist → src}/components/table/table.module.css +3 -2
- package/src/components/table/table.tsx +183 -0
- package/src/components/table/table_column.tsx +27 -0
- package/src/components/table/table_presenter.test.ts +161 -0
- package/src/components/table/table_presenter.ts +103 -0
- package/src/components/table_filter_panel/field_filters/date_field_filter.tsx +70 -0
- package/src/components/table_filter_panel/field_filters/date_field_filter_presenter.test.ts +583 -0
- package/src/components/table_filter_panel/field_filters/date_field_filter_presenter.ts +110 -0
- package/src/components/table_filter_panel/field_filters/field_filter_props.ts +5 -0
- package/src/components/table_filter_panel/field_filters/field_filter_strategy.ts +14 -0
- package/src/components/table_filter_panel/field_filters/mulit_select_field_filter.tsx +68 -0
- package/src/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.test.ts +444 -0
- package/src/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.ts +90 -0
- package/src/components/table_filter_panel/field_filters/number_field_filter.tsx +53 -0
- package/src/components/table_filter_panel/field_filters/number_field_filter_presenter.test.ts +431 -0
- package/src/components/table_filter_panel/field_filters/number_field_filter_presenter.ts +80 -0
- package/src/components/table_filter_panel/field_filters/number_range_field_filter.tsx +68 -0
- package/src/components/table_filter_panel/field_filters/number_range_field_filter_presenter.test.ts +582 -0
- package/src/components/table_filter_panel/field_filters/number_range_field_filter_presenter.ts +110 -0
- package/src/components/table_filter_panel/field_filters/select_field_filter.tsx +57 -0
- package/src/components/table_filter_panel/field_filters/select_field_filter_presenter.test.ts +365 -0
- package/src/components/table_filter_panel/field_filters/select_field_filter_presenter.ts +74 -0
- package/src/components/table_filter_panel/field_filters/string_field_filter.tsx +70 -0
- package/src/components/table_filter_panel/field_filters/string_field_filter_presenter.test.ts +296 -0
- package/src/components/table_filter_panel/field_filters/string_field_filter_presenter.ts +81 -0
- package/src/components/table_filter_panel/field_filters/use_field_filter_strategy.tsx +30 -0
- package/src/components/table_filter_panel/table_filter_panel.stories.tsx +46 -0
- package/src/components/table_filter_panel/table_filter_panel.tsx +26 -0
- package/src/components/table_filter_panel/table_filter_panel_presenter.ts +77 -0
- package/src/components/table_filter_panel/types.ts +3 -0
- package/src/components/table_pager.tsx +39 -0
- package/src/index.ts +16 -0
- package/tsconfig.json +36 -0
- package/types/file_types.d.ts +54 -0
- package/types/react_color.d.ts +61 -0
- package/dist/__stories__/aip_table.stories.d.ts +0 -5
- package/dist/__stories__/aip_table.stories.js +0 -96
- package/dist/__stories__/aip_table.stories.js.map +0 -1
- package/dist/__stories__/auth_provider.d.ts +0 -4
- package/dist/__stories__/auth_provider.js +0 -10
- package/dist/__stories__/auth_provider.js.map +0 -1
- package/dist/__stories__/demo.stories.d.ts +0 -6
- package/dist/__stories__/demo.stories.js +0 -94
- package/dist/__stories__/demo.stories.js.map +0 -1
- package/dist/__stories__/sample_data.d.ts +0 -36
- package/dist/__stories__/sample_data.js +0 -1385
- package/dist/__stories__/sample_data.js.map +0 -1
- package/dist/__stories__/table.stories.d.ts +0 -12
- package/dist/__stories__/table.stories.js +0 -272
- package/dist/__stories__/table.stories.js.map +0 -1
- package/dist/components/table/table_presenter.test.d.ts +0 -1
- package/dist/components/table/table_presenter.test.js +0 -125
- package/dist/components/table/table_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.test.js +0 -434
- package/dist/components/table_filter_panel/field_filters/date_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/field_filter_props.js +0 -2
- package/dist/components/table_filter_panel/field_filters/field_filter_props.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/field_filter_strategy.js +0 -2
- package/dist/components/table_filter_panel/field_filters/field_filter_strategy.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.test.js +0 -332
- package/dist/components/table_filter_panel/field_filters/multi_select_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.test.js +0 -347
- package/dist/components/table_filter_panel/field_filters/number_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.test.js +0 -452
- package/dist/components/table_filter_panel/field_filters/number_range_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.test.js +0 -285
- package/dist/components/table_filter_panel/field_filters/select_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.test.d.ts +0 -1
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.test.js +0 -232
- package/dist/components/table_filter_panel/field_filters/string_field_filter_presenter.test.js.map +0 -1
- package/dist/components/table_filter_panel/table_filter_panel.stories.d.ts +0 -6
- package/dist/components/table_filter_panel/table_filter_panel.stories.js +0 -25
- package/dist/components/table_filter_panel/table_filter_panel.stories.js.map +0 -1
- /package/{dist → src}/__stories__/table.module.css +0 -0
- /package/{dist → src}/components/cells/cell.module.css +0 -0
- /package/{dist → src}/components/table_pager.module.css +0 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react-vite';
|
|
2
|
+
import React, { useCallback, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
StaticDataSource,
|
|
6
|
+
StaticDateField,
|
|
7
|
+
StaticNumberField,
|
|
8
|
+
StaticStringField,
|
|
9
|
+
} from '@tcn/resource-store';
|
|
10
|
+
import { useSignalValue } from '@tcn/state';
|
|
11
|
+
import { Button } from '@tcn/ui/actions';
|
|
12
|
+
import { Box, HStack, Spacer, VStack } from '@tcn/ui/stacks';
|
|
13
|
+
import { VPanel } from '@tcn/ui/surfaces';
|
|
14
|
+
import { Title } from '@tcn/ui/typography';
|
|
15
|
+
import { GlobalSearch } from '../components/global_search.js';
|
|
16
|
+
import { Table } from '../components/table/table.js';
|
|
17
|
+
import { TableColumn } from '../components/table/table_column.js';
|
|
18
|
+
import { DateFieldFilter } from '../components/table_filter_panel/field_filters/date_field_filter.js';
|
|
19
|
+
import { NumberFieldFilter } from '../components/table_filter_panel/field_filters/number_field_filter.js';
|
|
20
|
+
import { NumberRangeFieldFilter } from '../components/table_filter_panel/field_filters/number_range_field_filter.js';
|
|
21
|
+
import { StringFieldFilter } from '../components/table_filter_panel/field_filters/string_field_filter.js';
|
|
22
|
+
import { TableFilterPanel } from '../components/table_filter_panel/table_filter_panel.js';
|
|
23
|
+
import { TablePager } from '../components/table_pager.js';
|
|
24
|
+
import { DataItem, items, stickyItems } from './sample_data.js';
|
|
25
|
+
import styles from './table.module.css';
|
|
26
|
+
|
|
27
|
+
const meta: Meta = {
|
|
28
|
+
title: 'Table',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function Basic() {
|
|
32
|
+
const [source] = useState(() => {
|
|
33
|
+
return new StaticDataSource<DataItem>(items, [
|
|
34
|
+
new StaticStringField('name', i => i.name),
|
|
35
|
+
new StaticNumberField('age', i => i.age),
|
|
36
|
+
new StaticStringField('email', i => i.email),
|
|
37
|
+
new StaticStringField('city', i => i.city),
|
|
38
|
+
new StaticStringField('country', i => i.country),
|
|
39
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
40
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Table
|
|
46
|
+
dataSource={source}
|
|
47
|
+
onRowClick={item => {
|
|
48
|
+
alert(`Clicked ${item.name}`);
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<TableColumn heading="Name" fieldName="name" />
|
|
52
|
+
<TableColumn heading="Age" fieldName="age" />
|
|
53
|
+
<TableColumn heading="Email" fieldName="email" />
|
|
54
|
+
<TableColumn heading="City" fieldName="city" />
|
|
55
|
+
<TableColumn heading="Country" fieldName="country" />
|
|
56
|
+
<TableColumn heading="Occupation" fieldName="occupation" />
|
|
57
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
58
|
+
<div>Other kinds of children don't render</div>
|
|
59
|
+
</Table>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function WithSort() {
|
|
64
|
+
const [source] = useState(() => {
|
|
65
|
+
return new StaticDataSource<DataItem>(items, [
|
|
66
|
+
new StaticStringField('name', i => i.name),
|
|
67
|
+
new StaticNumberField('age', i => i.age),
|
|
68
|
+
new StaticStringField('email', i => i.email),
|
|
69
|
+
new StaticStringField('city', i => i.city),
|
|
70
|
+
new StaticStringField('country', i => i.country),
|
|
71
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
72
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const currentResults = useSignalValue(source.broadcasts.currentResults);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<Table
|
|
80
|
+
dataSource={source}
|
|
81
|
+
onRowClick={item => {
|
|
82
|
+
alert(`Clicked ${item.name}`);
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<TableColumn heading="Name" footer="Some Names" fieldName="name" canSort />
|
|
86
|
+
<TableColumn
|
|
87
|
+
heading="Age"
|
|
88
|
+
footer={`Average Age: ${Math.round(currentResults.reduce((sum, i) => sum + i.age, 0) / currentResults.length)}`}
|
|
89
|
+
fieldName="age"
|
|
90
|
+
canSort
|
|
91
|
+
width={120}
|
|
92
|
+
/>
|
|
93
|
+
<TableColumn heading="Email" fieldName="email" canSort />
|
|
94
|
+
<TableColumn heading="City" fieldName="city" canSort />
|
|
95
|
+
<TableColumn heading="Country" fieldName="country" canSort />
|
|
96
|
+
<TableColumn heading="Occupation" fieldName="occupation" canSort />
|
|
97
|
+
<TableColumn heading="Active" fieldName="isActive" canSort />
|
|
98
|
+
</Table>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function WithRowHighlighting() {
|
|
103
|
+
const [source] = useState(() => {
|
|
104
|
+
return new StaticDataSource<DataItem>(items, [
|
|
105
|
+
new StaticStringField('name', i => i.name),
|
|
106
|
+
new StaticNumberField('age', i => i.age),
|
|
107
|
+
new StaticStringField('id', i => i.id),
|
|
108
|
+
new StaticStringField('email', i => i.email),
|
|
109
|
+
new StaticStringField('city', i => i.city),
|
|
110
|
+
new StaticStringField('country', i => i.country),
|
|
111
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
112
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
113
|
+
]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const [selectedRow, setSelectedRow] = useState<string | null>(null);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div>
|
|
120
|
+
<Table
|
|
121
|
+
dataSource={source}
|
|
122
|
+
isRowHighlighted={row => {
|
|
123
|
+
return row.id === selectedRow;
|
|
124
|
+
}}
|
|
125
|
+
onRowClick={item => setSelectedRow(item.id)}
|
|
126
|
+
>
|
|
127
|
+
<TableColumn heading="Name" fieldName="name" />
|
|
128
|
+
<TableColumn heading="Age" fieldName="age" />
|
|
129
|
+
<TableColumn heading="Email" fieldName="email" />
|
|
130
|
+
<TableColumn heading="City" fieldName="city" />
|
|
131
|
+
<TableColumn heading="Country" fieldName="country" />
|
|
132
|
+
<TableColumn heading="Occupation" fieldName="occupation" />
|
|
133
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
134
|
+
</Table>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function ComplexHeadersAndFooters() {
|
|
140
|
+
const [source] = useState(() => {
|
|
141
|
+
return new StaticDataSource<DataItem>(items, [
|
|
142
|
+
new StaticStringField('name', i => i.name),
|
|
143
|
+
new StaticNumberField('age', i => i.age),
|
|
144
|
+
new StaticStringField('email', i => i.email),
|
|
145
|
+
new StaticStringField('city', i => i.city),
|
|
146
|
+
new StaticStringField('country', i => i.country),
|
|
147
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
148
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
149
|
+
]);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<Table dataSource={source}>
|
|
154
|
+
<TableColumn
|
|
155
|
+
heading={
|
|
156
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
157
|
+
<span>👤</span>
|
|
158
|
+
<span>Name</span>
|
|
159
|
+
</div>
|
|
160
|
+
}
|
|
161
|
+
footer={
|
|
162
|
+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
163
|
+
<span>Total:</span>
|
|
164
|
+
<span>{items.length}</span>
|
|
165
|
+
</div>
|
|
166
|
+
}
|
|
167
|
+
fieldName="name"
|
|
168
|
+
render={(i: DataItem) => i.name}
|
|
169
|
+
/>
|
|
170
|
+
<TableColumn
|
|
171
|
+
heading={
|
|
172
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
173
|
+
<span>🎂</span>
|
|
174
|
+
<span>Age</span>
|
|
175
|
+
</div>
|
|
176
|
+
}
|
|
177
|
+
footer={
|
|
178
|
+
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
179
|
+
<span>Average:</span>
|
|
180
|
+
<span>
|
|
181
|
+
{Math.round(items.reduce((sum, i) => sum + i.age, 0) / items.length)}
|
|
182
|
+
</span>
|
|
183
|
+
</div>
|
|
184
|
+
}
|
|
185
|
+
fieldName="age"
|
|
186
|
+
render={(i: DataItem) => i.age}
|
|
187
|
+
/>
|
|
188
|
+
<TableColumn heading="Email" fieldName="email" render={(i: DataItem) => i.email} />
|
|
189
|
+
<TableColumn heading="City" fieldName="city" render={(i: DataItem) => i.city} />
|
|
190
|
+
<TableColumn
|
|
191
|
+
heading="Country"
|
|
192
|
+
fieldName="country"
|
|
193
|
+
render={(i: DataItem) => i.country}
|
|
194
|
+
/>
|
|
195
|
+
<TableColumn
|
|
196
|
+
heading="Occupation"
|
|
197
|
+
fieldName="occupation"
|
|
198
|
+
render={(i: DataItem) => i.occupation}
|
|
199
|
+
/>
|
|
200
|
+
<TableColumn
|
|
201
|
+
heading="Active"
|
|
202
|
+
fieldName="isActive"
|
|
203
|
+
render={(i: DataItem) => (i.isActive ? 'Yes' : 'No')}
|
|
204
|
+
/>
|
|
205
|
+
</Table>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function WithStickyActionsColumn() {
|
|
210
|
+
const [source] = useState(() => {
|
|
211
|
+
return new StaticDataSource<DataItem>(items, [
|
|
212
|
+
new StaticStringField('name', i => i.name),
|
|
213
|
+
new StaticNumberField('age', i => i.age),
|
|
214
|
+
new StaticStringField('email', i => i.email),
|
|
215
|
+
new StaticStringField('city', i => i.city),
|
|
216
|
+
new StaticStringField('country', i => i.country),
|
|
217
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
218
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
219
|
+
]);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<div style={{ width: '600px', height: '400px' }}>
|
|
224
|
+
<Table
|
|
225
|
+
dataSource={source}
|
|
226
|
+
onRowClick={item => {
|
|
227
|
+
alert(`Clicked ${item.name}`);
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
<TableColumn heading="Age" fieldName="age" sticky="start" />
|
|
231
|
+
<TableColumn heading="Name" fieldName="name" />
|
|
232
|
+
<TableColumn heading="Email" fieldName="email" />
|
|
233
|
+
<TableColumn heading="City" fieldName="city" />
|
|
234
|
+
<TableColumn heading="Country" fieldName="country" />
|
|
235
|
+
<TableColumn heading="Occupation" fieldName="occupation" />
|
|
236
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
237
|
+
<TableColumn
|
|
238
|
+
heading="Actions"
|
|
239
|
+
sticky="end"
|
|
240
|
+
width={120}
|
|
241
|
+
render={(item: DataItem) => (
|
|
242
|
+
<div style={{ display: 'flex', gap: '4px', justifyContent: 'center' }}>
|
|
243
|
+
<button
|
|
244
|
+
onClick={e => {
|
|
245
|
+
e.stopPropagation();
|
|
246
|
+
alert(`Edit ${item.name}`);
|
|
247
|
+
}}
|
|
248
|
+
style={{
|
|
249
|
+
padding: '4px 8px',
|
|
250
|
+
fontSize: '12px',
|
|
251
|
+
border: '1px solid #ccc',
|
|
252
|
+
borderRadius: '4px',
|
|
253
|
+
background: '#f0f0f0',
|
|
254
|
+
cursor: 'pointer',
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
Edit
|
|
258
|
+
</button>
|
|
259
|
+
<button
|
|
260
|
+
onClick={e => {
|
|
261
|
+
e.stopPropagation();
|
|
262
|
+
alert(`Delete ${item.name}`);
|
|
263
|
+
}}
|
|
264
|
+
style={{
|
|
265
|
+
padding: '4px 8px',
|
|
266
|
+
fontSize: '12px',
|
|
267
|
+
border: '1px solid #ff6b6b',
|
|
268
|
+
borderRadius: '4px',
|
|
269
|
+
background: '#ff6b6b',
|
|
270
|
+
color: 'white',
|
|
271
|
+
cursor: 'pointer',
|
|
272
|
+
}}
|
|
273
|
+
>
|
|
274
|
+
Delete
|
|
275
|
+
</button>
|
|
276
|
+
</div>
|
|
277
|
+
)}
|
|
278
|
+
/>
|
|
279
|
+
</Table>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function WithTableHeaderAndTableFooter() {
|
|
285
|
+
const [source] = useState(() => {
|
|
286
|
+
return new StaticDataSource<DataItem>(items, [
|
|
287
|
+
new StaticStringField('name', i => i.name),
|
|
288
|
+
new StaticNumberField('age', i => i.age),
|
|
289
|
+
new StaticStringField('email', i => i.email),
|
|
290
|
+
new StaticStringField('city', i => i.city),
|
|
291
|
+
new StaticStringField('country', i => i.country),
|
|
292
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
293
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
294
|
+
]);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
<VPanel>
|
|
299
|
+
<HStack className={styles.header} padding="8px" vAlign="center">
|
|
300
|
+
<Title>The Table</Title>
|
|
301
|
+
<Spacer />
|
|
302
|
+
<GlobalSearch dataSource={source} />
|
|
303
|
+
</HStack>
|
|
304
|
+
<VStack height="flex">
|
|
305
|
+
<Table
|
|
306
|
+
dataSource={source}
|
|
307
|
+
onRowClick={item => {
|
|
308
|
+
alert(`Clicked ${item.name}`);
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
<TableColumn heading="Name" fieldName="name" />
|
|
312
|
+
<TableColumn heading="Age" fieldName="age" />
|
|
313
|
+
<TableColumn heading="Email" fieldName="email" />
|
|
314
|
+
<TableColumn heading="City" fieldName="city" />
|
|
315
|
+
<TableColumn heading="Country" fieldName="country" />
|
|
316
|
+
<TableColumn heading="Occupation" fieldName="occupation" />
|
|
317
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
318
|
+
</Table>
|
|
319
|
+
</VStack>
|
|
320
|
+
<HStack padding="8px">
|
|
321
|
+
<TablePager dataSource={source} />
|
|
322
|
+
</HStack>
|
|
323
|
+
</VPanel>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function WithStickyItems() {
|
|
328
|
+
const [stickyThings, setStickyThings] = useState([...stickyItems]);
|
|
329
|
+
|
|
330
|
+
const [source] = useState(() => {
|
|
331
|
+
const source = new StaticDataSource<DataItem>(items, [
|
|
332
|
+
new StaticStringField('name', i => i.name),
|
|
333
|
+
new StaticNumberField('age', i => i.age),
|
|
334
|
+
new StaticStringField('email', i => i.email),
|
|
335
|
+
new StaticStringField('city', i => i.city),
|
|
336
|
+
new StaticStringField('country', i => i.country),
|
|
337
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
338
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
339
|
+
]);
|
|
340
|
+
source.setPageSize(80);
|
|
341
|
+
return source;
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const dismissStickyThing = useCallback((item: DataItem) => {
|
|
345
|
+
setStickyThings(currentStickyThings =>
|
|
346
|
+
currentStickyThings.filter(i => i.id !== item.id)
|
|
347
|
+
);
|
|
348
|
+
}, []);
|
|
349
|
+
|
|
350
|
+
return (
|
|
351
|
+
<VStack height="100%">
|
|
352
|
+
<Table dataSource={source} stickyItems={stickyThings}>
|
|
353
|
+
<TableColumn heading="Name" fieldName="name" sticky="start" />
|
|
354
|
+
<TableColumn heading="Age" fieldName="age" width={150} />
|
|
355
|
+
<TableColumn heading="Email" fieldName="email" width={300} />
|
|
356
|
+
<TableColumn heading="City" fieldName="city" width={300} />
|
|
357
|
+
<TableColumn heading="Country" fieldName="country" width={200} />
|
|
358
|
+
<TableColumn heading="Occupation" fieldName="occupation" width={200} />
|
|
359
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
360
|
+
<TableColumn
|
|
361
|
+
heading="Actions"
|
|
362
|
+
sticky="end"
|
|
363
|
+
width={120}
|
|
364
|
+
render={(item: DataItem) => {
|
|
365
|
+
if (stickyThings.includes(item)) {
|
|
366
|
+
return <Button onClick={() => dismissStickyThing(item)}>x</Button>;
|
|
367
|
+
}
|
|
368
|
+
return null;
|
|
369
|
+
}}
|
|
370
|
+
/>
|
|
371
|
+
</Table>
|
|
372
|
+
<TablePager dataSource={source} />
|
|
373
|
+
</VStack>
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export function WithFilterPanel() {
|
|
378
|
+
const [source] = useState(() => {
|
|
379
|
+
const source = new StaticDataSource<DataItem>(items, [
|
|
380
|
+
new StaticStringField('name', i => i.name),
|
|
381
|
+
new StaticNumberField('age', i => i.age),
|
|
382
|
+
new StaticStringField('email', i => i.email),
|
|
383
|
+
new StaticStringField('city', i => i.city),
|
|
384
|
+
new StaticDateField('birthdate', i => i.birthdate),
|
|
385
|
+
new StaticStringField('occupation', i => i.occupation),
|
|
386
|
+
new StaticStringField('isActive', i => (i.isActive ? 'Yes' : 'No')),
|
|
387
|
+
]);
|
|
388
|
+
source.setPageSize(80);
|
|
389
|
+
return source;
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
return (
|
|
393
|
+
<VStack height="100%">
|
|
394
|
+
<HStack height="100%" vAlign="start" gap="8px">
|
|
395
|
+
<Box width="300px" height="100%" enableResizeOnEnd>
|
|
396
|
+
<TableFilterPanel dataSource={source}>
|
|
397
|
+
<StringFieldFilter fieldName="name" label="Name (string)" />
|
|
398
|
+
<NumberFieldFilter fieldName="age" label="Age (number)" />
|
|
399
|
+
<DateFieldFilter fieldName="birthdate" label="Birthdate (date range)" />
|
|
400
|
+
<NumberRangeFieldFilter fieldName="age" label="Age (number range)" />
|
|
401
|
+
</TableFilterPanel>
|
|
402
|
+
</Box>
|
|
403
|
+
<Table dataSource={source} height="100%" width="flex">
|
|
404
|
+
<TableColumn heading="Name" fieldName="name" sticky="start" />
|
|
405
|
+
<TableColumn heading="Age" fieldName="age" width={150} canSort />
|
|
406
|
+
<TableColumn heading="Email" fieldName="email" width={300} />
|
|
407
|
+
<TableColumn heading="City" fieldName="city" width={300} />
|
|
408
|
+
<TableColumn
|
|
409
|
+
heading="Birthdate"
|
|
410
|
+
fieldName="birthdate"
|
|
411
|
+
width={300}
|
|
412
|
+
render={(i: DataItem) => i.birthdate.toLocaleDateString()}
|
|
413
|
+
/>
|
|
414
|
+
<TableColumn heading="Occupation" fieldName="occupation" width={200} />
|
|
415
|
+
<TableColumn heading="Active" fieldName="isActive" />
|
|
416
|
+
</Table>
|
|
417
|
+
</HStack>
|
|
418
|
+
<TablePager dataSource={source} />
|
|
419
|
+
</VStack>
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export default meta;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import cellStyles from './cell.module.css';
|
|
4
|
+
|
|
5
|
+
export type DataCellProps = {
|
|
6
|
+
content: React.ReactNode;
|
|
7
|
+
sticky?: 'start' | 'end';
|
|
8
|
+
width?: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function DataCell({ content, sticky, width }: DataCellProps) {
|
|
12
|
+
return (
|
|
13
|
+
<td className={cellStyles['table-cell']} data-stick-to={sticky}>
|
|
14
|
+
<div
|
|
15
|
+
style={{
|
|
16
|
+
width: `${width}px`,
|
|
17
|
+
minWidth: `${width}px`,
|
|
18
|
+
maxWidth: `${width}px`,
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
{content}
|
|
22
|
+
</div>
|
|
23
|
+
</td>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import cellStyles from './cell.module.css';
|
|
4
|
+
|
|
5
|
+
export type FooterCellProps = {
|
|
6
|
+
content: React.ReactNode;
|
|
7
|
+
sticky?: 'start' | 'end';
|
|
8
|
+
width?: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function FooterCell({ content, sticky, width }: FooterCellProps) {
|
|
12
|
+
return (
|
|
13
|
+
<td className={cellStyles['table-cell']} data-stick-to={sticky}>
|
|
14
|
+
<div
|
|
15
|
+
style={{
|
|
16
|
+
width: `${width}px`,
|
|
17
|
+
minWidth: `${width}px`,
|
|
18
|
+
maxWidth: `${width}px`,
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
{content}
|
|
22
|
+
</div>
|
|
23
|
+
</td>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Box, HStack } from '@tcn/ui/stacks';
|
|
4
|
+
|
|
5
|
+
import { TwoClassSortDownIcon } from '@tcn/icons/two_class_sort_down_icon.js';
|
|
6
|
+
import { TwoClassSortFilledIcon } from '@tcn/icons/two_class_sort_filled_icon.js';
|
|
7
|
+
import { TwoClassSortUpIcon } from '@tcn/icons/two_class_sort_up_icon.js';
|
|
8
|
+
import { Button } from '@tcn/ui/actions';
|
|
9
|
+
import cellStyles from './cell.module.css';
|
|
10
|
+
|
|
11
|
+
export type HeaderCellProps = {
|
|
12
|
+
heading: React.ReactNode;
|
|
13
|
+
index: number;
|
|
14
|
+
sticky?: 'start' | 'end';
|
|
15
|
+
onResize?: (width: number) => void;
|
|
16
|
+
width?: number;
|
|
17
|
+
sortMode?: 'none' | 'asc' | 'desc';
|
|
18
|
+
onSortModeChange?: () => void;
|
|
19
|
+
canSort?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function HeaderCell({
|
|
23
|
+
heading,
|
|
24
|
+
sticky,
|
|
25
|
+
onResize,
|
|
26
|
+
width,
|
|
27
|
+
sortMode,
|
|
28
|
+
onSortModeChange,
|
|
29
|
+
canSort,
|
|
30
|
+
}: HeaderCellProps) {
|
|
31
|
+
const zIndex = sticky != null ? 2 : 1;
|
|
32
|
+
|
|
33
|
+
const handleResize = useCallback(
|
|
34
|
+
(newSize: number) => {
|
|
35
|
+
onResize?.(Math.max(newSize, 20));
|
|
36
|
+
},
|
|
37
|
+
[onResize]
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<th
|
|
42
|
+
className={cellStyles['table-cell']}
|
|
43
|
+
data-stick-to={sticky}
|
|
44
|
+
style={{ width: `${width}px`, zIndex }}
|
|
45
|
+
>
|
|
46
|
+
<Box
|
|
47
|
+
padding="4px 6px"
|
|
48
|
+
overflow="hidden"
|
|
49
|
+
minWidth="20px"
|
|
50
|
+
enableResizeOnEnd
|
|
51
|
+
onWidthResize={handleResize}
|
|
52
|
+
style={{ width: `${width}px`, minWidth: '20px' }}
|
|
53
|
+
onClick={e => e.stopPropagation()}
|
|
54
|
+
height="30px"
|
|
55
|
+
>
|
|
56
|
+
<HStack>
|
|
57
|
+
<Box className="ellipsis" style={{ alignItems: 'center', display: 'flex' }}>
|
|
58
|
+
{heading}
|
|
59
|
+
</Box>
|
|
60
|
+
<Box width="auto" height="auto">
|
|
61
|
+
{canSort && (
|
|
62
|
+
<Button onClick={() => onSortModeChange?.()} hierarchy="tertiary">
|
|
63
|
+
{sortMode === 'asc' ? (
|
|
64
|
+
<TwoClassSortDownIcon />
|
|
65
|
+
) : sortMode === 'desc' ? (
|
|
66
|
+
<TwoClassSortUpIcon />
|
|
67
|
+
) : (
|
|
68
|
+
<TwoClassSortFilledIcon />
|
|
69
|
+
)}
|
|
70
|
+
</Button>
|
|
71
|
+
)}
|
|
72
|
+
</Box>
|
|
73
|
+
</HStack>
|
|
74
|
+
</Box>
|
|
75
|
+
</th>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cellStyles from './cell.module.css';
|
|
3
|
+
|
|
4
|
+
export type StickyRowDataCellProps = {
|
|
5
|
+
content: React.ReactNode;
|
|
6
|
+
sticky?: 'start' | 'end';
|
|
7
|
+
width?: number;
|
|
8
|
+
top?: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function StickyRowDataCell({
|
|
12
|
+
content,
|
|
13
|
+
sticky,
|
|
14
|
+
width,
|
|
15
|
+
top,
|
|
16
|
+
}: StickyRowDataCellProps) {
|
|
17
|
+
return (
|
|
18
|
+
<td
|
|
19
|
+
className={cellStyles['sticky-row-table-cell']}
|
|
20
|
+
data-stick-to={sticky}
|
|
21
|
+
style={{
|
|
22
|
+
width: `${width}px`,
|
|
23
|
+
minWidth: `${width}px`,
|
|
24
|
+
maxWidth: `${width}px`,
|
|
25
|
+
top: `${top}px`,
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<div>{content}</div>
|
|
29
|
+
</td>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cellStyles from './cell.module.css';
|
|
3
|
+
|
|
4
|
+
export type StyckyRowFillCellProps = {
|
|
5
|
+
top?: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function StickyRowFillCell({ top }: StyckyRowFillCellProps) {
|
|
9
|
+
return (
|
|
10
|
+
<td
|
|
11
|
+
className={cellStyles['sticky-row-table-cell']}
|
|
12
|
+
data-stick-to="start"
|
|
13
|
+
style={{ top: `${top}px` }}
|
|
14
|
+
></td>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { DataSource } from '@tcn/resource-store';
|
|
4
|
+
import { useSignalValue } from '@tcn/state';
|
|
5
|
+
import { Input, InputProps } from '@tcn/ui/inputs';
|
|
6
|
+
import { GlobalSearchPresenter } from './global_search_presenter.js';
|
|
7
|
+
|
|
8
|
+
export interface GlobalSearchOwnProps<T> {
|
|
9
|
+
dataSource: DataSource<T>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type GlobalSearchProps<T> = GlobalSearchOwnProps<T> &
|
|
13
|
+
Omit<InputProps, 'value' | 'onChange'>;
|
|
14
|
+
|
|
15
|
+
export function GlobalSearch<T = any>({
|
|
16
|
+
dataSource,
|
|
17
|
+
width = 'auto',
|
|
18
|
+
placeholder = 'Search',
|
|
19
|
+
...rest
|
|
20
|
+
}: GlobalSearchProps<T>) {
|
|
21
|
+
const [presenter] = useState(() => new GlobalSearchPresenter<T>(dataSource));
|
|
22
|
+
const value = useSignalValue(presenter.broadcasts.value);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Input
|
|
26
|
+
width={width}
|
|
27
|
+
placeholder={placeholder}
|
|
28
|
+
value={value ?? ''}
|
|
29
|
+
onChange={e => presenter.setValue(e)}
|
|
30
|
+
{...rest}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DataSource } from '@tcn/resource-store';
|
|
2
|
+
import { Signal } from '@tcn/state';
|
|
3
|
+
|
|
4
|
+
export class GlobalSearchPresenter<T = unknown> {
|
|
5
|
+
private _dataSource: DataSource<T>;
|
|
6
|
+
private _value = new Signal<string | null>(null);
|
|
7
|
+
|
|
8
|
+
private _broadcasts = {
|
|
9
|
+
value: this._value.broadcast,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
constructor(dataSource: DataSource<T>) {
|
|
13
|
+
this._dataSource = dataSource;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get broadcasts() {
|
|
17
|
+
return this._broadcasts;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async setValue(value: string | null) {
|
|
21
|
+
this._dataSource.setGlobalSearch(value ?? '');
|
|
22
|
+
this._value.set(value ?? '');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
.table-body-wrapper {
|
|
2
2
|
box-shadow: var(--table-box-shadow, inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5));
|
|
3
|
-
font-family:
|
|
4
|
-
|
|
3
|
+
font-family:
|
|
4
|
+
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell,
|
|
5
|
+
"Open Sans", "Helvetica Neue", sans-serif;
|
|
5
6
|
color: #333;
|
|
6
7
|
}
|
|
7
8
|
|