@tcn/ui-table 0.0.2
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 +133 -0
- package/dist/__stories__/aip_table.stories.d.ts +5 -0
- package/dist/__stories__/aip_table.stories.js +88 -0
- package/dist/__stories__/aip_table.stories.js.map +1 -0
- package/dist/__stories__/auth_provider.d.ts +4 -0
- package/dist/__stories__/auth_provider.js +10 -0
- package/dist/__stories__/auth_provider.js.map +1 -0
- package/dist/__stories__/table.stories.d.ts +7 -0
- package/dist/__stories__/table.stories.js +63 -0
- package/dist/__stories__/table.stories.js.map +1 -0
- package/dist/_components/cells/cell.module.css +43 -0
- package/dist/_components/cells/data_cell.d.ts +7 -0
- package/dist/_components/cells/data_cell.js +11 -0
- package/dist/_components/cells/data_cell.js.map +1 -0
- package/dist/_components/cells/footer_cell.d.ts +7 -0
- package/dist/_components/cells/footer_cell.js +11 -0
- package/dist/_components/cells/footer_cell.js.map +1 -0
- package/dist/_components/cells/header_cell.d.ts +12 -0
- package/dist/_components/cells/header_cell.js +14 -0
- package/dist/_components/cells/header_cell.js.map +1 -0
- package/dist/_components/table_body/table_body.d.ts +12 -0
- package/dist/_components/table_body/table_body.js +67 -0
- package/dist/_components/table_body/table_body.js.map +1 -0
- package/dist/_components/table_body/table_body.module.css +241 -0
- package/dist/_components/table_body/table_body_presenter.d.ts +32 -0
- package/dist/_components/table_body/table_body_presenter.js +55 -0
- package/dist/_components/table_body/table_body_presenter.js.map +1 -0
- package/dist/_components/table_body/table_body_presenter.test.d.ts +1 -0
- package/dist/_components/table_body/table_body_presenter.test.js +125 -0
- package/dist/_components/table_body/table_body_presenter.test.js.map +1 -0
- package/dist/_components/table_body/table_column.d.ts +19 -0
- package/dist/_components/table_body/table_column.js +6 -0
- package/dist/_components/table_body/table_column.js.map +1 -0
- package/dist/_components/table_footer.d.ts +6 -0
- package/dist/_components/table_footer.js +13 -0
- package/dist/_components/table_footer.js.map +1 -0
- package/dist/_components/table_header.d.ts +7 -0
- package/dist/_components/table_header.js +14 -0
- package/dist/_components/table_header.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
This repo contains classes and components used for implementing UI tables.
|
|
4
|
+
|
|
5
|
+
## Architectural Overview
|
|
6
|
+
|
|
7
|
+
This table contrasts with our past efforts in how we separate the business of data management from data rendering, and this approach has greatly simplified both the implementation and usage of the table.
|
|
8
|
+
|
|
9
|
+
All responsibilities relating to display (including localization and formatting) are handled here in the table itself, where we have access to our I18n and theme contexts.
|
|
10
|
+
|
|
11
|
+
Data handling is confined to the `DataSource` interface (discussed in more detail below).
|
|
12
|
+
|
|
13
|
+
We have thus eliminated all of the entanglement between presentation and data handling.
|
|
14
|
+
|
|
15
|
+
## Components
|
|
16
|
+
|
|
17
|
+
This package provides several components that can be used together or independently:
|
|
18
|
+
|
|
19
|
+
- `TableHeader`: Displays the table title and search functionality
|
|
20
|
+
- `TableBody`: The main table component that renders the data
|
|
21
|
+
- `TableColumn`: Configures how each column is displayed
|
|
22
|
+
- `TableFooter`: Shows pagination controls
|
|
23
|
+
|
|
24
|
+
The components are designed to work independently from each other, but may consume a common `DataSource`, allowing you to:
|
|
25
|
+
- Use them together for a complete table experience
|
|
26
|
+
- Implement your own header/footer components
|
|
27
|
+
- Customize the layout and styling
|
|
28
|
+
|
|
29
|
+
In other words, if you pass the `TableBody` and `TableFooter` the same `DataStore` instance, the paging controls in the footer will affect the `TableBody`.
|
|
30
|
+
|
|
31
|
+
### `TableBody`
|
|
32
|
+
|
|
33
|
+
The core component that renders the actual table (as a semantic HTML `<table>` element). It handles:
|
|
34
|
+
- Column configuration
|
|
35
|
+
- Data rendering
|
|
36
|
+
- Sorting
|
|
37
|
+
- Sticky columns
|
|
38
|
+
- Row highlighting
|
|
39
|
+
|
|
40
|
+
## Data Source
|
|
41
|
+
|
|
42
|
+
The `Table` components (except the `TableColumn`) require a `DataSource` which manages:
|
|
43
|
+
- Data fetching and updates
|
|
44
|
+
- Sorting
|
|
45
|
+
- Filtering
|
|
46
|
+
- Pagination
|
|
47
|
+
|
|
48
|
+
The `DataSource` interface and implementations are found in a separate `ResourceStore` module.
|
|
49
|
+
|
|
50
|
+
### Available Data Sources
|
|
51
|
+
|
|
52
|
+
1. `StaticDataSource`: For working with static data
|
|
53
|
+
2. `AIPDataSource`: For working with AIP-compliant REST resources
|
|
54
|
+
|
|
55
|
+
## Column Configuration
|
|
56
|
+
|
|
57
|
+
The `TableBody` is configured with `TableColumn` components that describe:
|
|
58
|
+
- Column position
|
|
59
|
+
- Header content
|
|
60
|
+
- Footer content
|
|
61
|
+
- Sorting behavior
|
|
62
|
+
- Cell rendering
|
|
63
|
+
- Sticky positioning
|
|
64
|
+
- Width
|
|
65
|
+
|
|
66
|
+
### Basic Column Example
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
const s = useStringTranslation();
|
|
70
|
+
|
|
71
|
+
<TableBody dataSource={personSource}>
|
|
72
|
+
<TableColumn
|
|
73
|
+
heading={s("Name")}
|
|
74
|
+
fieldName="name"
|
|
75
|
+
/>
|
|
76
|
+
</TableBody>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Column Props
|
|
80
|
+
|
|
81
|
+
| Prop | Type | Required | Description |
|
|
82
|
+
|------|------|----------|-------------|
|
|
83
|
+
| `heading` | `ReactNode` | Yes | Content to display in the column header |
|
|
84
|
+
| `footer` | `ReactNode` | No | Content to display in the column footer |
|
|
85
|
+
| `fieldName` | `string` | No* | Name of the field in the data source |
|
|
86
|
+
| `canSort` | `boolean` | No | Whether the column can be sorted |
|
|
87
|
+
| `render` | `(item: T) => ReactNode` | No | Custom render function for cell content |
|
|
88
|
+
| `sticky` | `"start" \| "end"` | No | Makes the column stick to the start or end |
|
|
89
|
+
| `width` | `number` | No | Column width in pixels |
|
|
90
|
+
|
|
91
|
+
\* Required if `canSort` is `true`
|
|
92
|
+
|
|
93
|
+
### Custom Cell Rendering
|
|
94
|
+
|
|
95
|
+
You can customize how cells are rendered using the `render` prop:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const d = useDateTranslation();
|
|
99
|
+
const s = useStringTranslation();
|
|
100
|
+
|
|
101
|
+
<TableBody dataSource={personSource}>
|
|
102
|
+
<TableColumn
|
|
103
|
+
heading={s("Birthdate")}
|
|
104
|
+
fieldName="birthdate"
|
|
105
|
+
render={(item) => d(item.birthdate)}
|
|
106
|
+
/>
|
|
107
|
+
</TableBody>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Action Columns
|
|
111
|
+
|
|
112
|
+
Columns that don't represent data (like action buttons):
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<TableBody dataSource={personSource}>
|
|
116
|
+
<TableColumn
|
|
117
|
+
heading={s("Actions")}
|
|
118
|
+
render={(item) => (
|
|
119
|
+
<Button onClick={() => myDomain.edit(item)}>
|
|
120
|
+
{s("Edit")}
|
|
121
|
+
</Button>
|
|
122
|
+
)}
|
|
123
|
+
sticky="end"
|
|
124
|
+
/>
|
|
125
|
+
</TableBody>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Styling
|
|
129
|
+
|
|
130
|
+
The table components use CSS modules for styling. You can:
|
|
131
|
+
- Override default styles using CSS modules
|
|
132
|
+
- Use the provided CSS variables for consistent theming
|
|
133
|
+
- Add custom classes to individual components
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { AIPDataSource } from '@tcn-internal/resource-store';
|
|
3
|
+
import { Button } from '@tcn/ui-controls';
|
|
4
|
+
import { Box, FlexBox, HStack, VStack } from '@tcn/ui-layout';
|
|
5
|
+
import { TableBody } from "../_components/table_body/table_body.js";
|
|
6
|
+
import { TableColumn } from "../_components/table_body/table_column.js";
|
|
7
|
+
import { TableFooter } from "../_components/table_footer.js";
|
|
8
|
+
import { TableHeader } from "../_components/table_header.js";
|
|
9
|
+
import { useSignalValue, useSignalValueEffect } from '@tcn/state';
|
|
10
|
+
import { useToken } from "./auth_provider.js";
|
|
11
|
+
const meta = {
|
|
12
|
+
title: 'AIP Table',
|
|
13
|
+
};
|
|
14
|
+
const resourceURL = 'https://api.dev.tcn.com/tcn/org/organizations/v1alpha1/organizations';
|
|
15
|
+
const resourceName = 'organizations';
|
|
16
|
+
export function Basic() {
|
|
17
|
+
const authToken = useToken();
|
|
18
|
+
const [source] = useState(() => {
|
|
19
|
+
const fields = [
|
|
20
|
+
{
|
|
21
|
+
fieldName: 'name',
|
|
22
|
+
sourceFieldName: 'name',
|
|
23
|
+
getValue: (i) => i.name,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
fieldName: 'displayName',
|
|
27
|
+
sourceFieldName: 'display_name',
|
|
28
|
+
getValue: (i) => i.displayName,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
fieldName: 'billingId',
|
|
32
|
+
sourceFieldName: 'billing_id',
|
|
33
|
+
getValue: (i) => i.billingId,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
fieldName: 'clientSid',
|
|
37
|
+
sourceFieldName: 'client_sid',
|
|
38
|
+
getValue: (i) => i.clientSid,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
fieldName: 'timeZone',
|
|
42
|
+
sourceFieldName: 'time_zone',
|
|
43
|
+
getValue: (i) => i.timeZone,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
fieldName: 'createTime',
|
|
47
|
+
sourceFieldName: 'create_time',
|
|
48
|
+
getValue: (i) => new Date(i.createTime),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
fieldName: 'updateTime',
|
|
52
|
+
sourceFieldName: 'update_time',
|
|
53
|
+
getValue: (i) => new Date(i.updateTime),
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
return new AIPDataSource({
|
|
57
|
+
resourceUrl: resourceURL,
|
|
58
|
+
resourceName,
|
|
59
|
+
fields,
|
|
60
|
+
authToken,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
const tokenValue = useSignalValue(authToken);
|
|
64
|
+
useSignalValueEffect(_ => {
|
|
65
|
+
source.execute();
|
|
66
|
+
}, authToken);
|
|
67
|
+
return (React.createElement(VStack, null,
|
|
68
|
+
React.createElement(HStack, { height: "auto" }, tokenValue === '' ? 'Sign in to load data' : ''),
|
|
69
|
+
React.createElement(VStack, { flex: true },
|
|
70
|
+
React.createElement(Box, { height: "auto" },
|
|
71
|
+
React.createElement(TableHeader, { title: "Organizations", dataSource: source })),
|
|
72
|
+
React.createElement(FlexBox, null,
|
|
73
|
+
React.createElement(TableBody, { dataSource: source },
|
|
74
|
+
React.createElement(TableColumn, { heading: "Name", fieldName: "name", render: (i) => i.name, width: 320, footer: "Note: not for display", sticky: "start" }),
|
|
75
|
+
React.createElement(TableColumn, { heading: "Display Name", fieldName: "display_name", width: 300, render: (i) => i.displayName }),
|
|
76
|
+
React.createElement(TableColumn, { heading: "Client SID", fieldName: "client_sid", width: 80, render: (i) => i.clientSid, canSort: true }),
|
|
77
|
+
React.createElement(TableColumn, { heading: "Random Stuff", footer: "Not derived from data", width: 300, render: () => Array.from({ length: Math.floor(Math.random() * 30) }, () => Math.floor(Math.random() * 94) + 32)
|
|
78
|
+
.map(num => String.fromCharCode(num))
|
|
79
|
+
.join('') }),
|
|
80
|
+
React.createElement(TableColumn, { heading: "Created Time", fieldName: "create_time", width: 200, render: (i) => i.createTime.toLocaleString() }),
|
|
81
|
+
React.createElement(TableColumn, { heading: "Update Time", fieldName: "update_time", width: 200, render: (i) => (React.createElement("div", { style: { color: 'red' } }, i.updateTime.toLocaleString())) }),
|
|
82
|
+
React.createElement(TableColumn, { heading: "Actions", width: 80, render: (i) => (React.createElement("div", null,
|
|
83
|
+
React.createElement(Button, { onClick: () => alert(`Edit ${i.name}`) }, "Edit"))), sticky: "end" }))),
|
|
84
|
+
React.createElement(Box, { height: "auto" },
|
|
85
|
+
React.createElement(TableFooter, { dataSource: source })))));
|
|
86
|
+
}
|
|
87
|
+
export default meta;
|
|
88
|
+
//# sourceMappingURL=aip_table.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aip_table.stories.js","sourceRoot":"","sources":["../../src/__stories__/aip_table.stories.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
export const AuthContext = React.createContext(null);
|
|
3
|
+
export function useToken() {
|
|
4
|
+
const token = useContext(AuthContext);
|
|
5
|
+
if (token == null) {
|
|
6
|
+
throw new Error('Token cannot be null.');
|
|
7
|
+
}
|
|
8
|
+
return token;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=auth_provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth_provider.js","sourceRoot":"","sources":["../../src/__stories__/auth_provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAwB,IAAI,CAAC,CAAC;AAE5E,MAAM,UAAU,QAAQ;IACtB,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAEtC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
declare const meta: Meta;
|
|
4
|
+
export declare function Basic(): React.JSX.Element;
|
|
5
|
+
export declare function WithSort(): React.JSX.Element;
|
|
6
|
+
export declare function ComplexHeadersAndFooters(): React.JSX.Element;
|
|
7
|
+
export default meta;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { StaticDataSource, StaticNumberField, StaticStringField, } from '@tcn-internal/resource-store';
|
|
3
|
+
import { useSignalValue } from '@tcn/state';
|
|
4
|
+
import { TableBody } from "../_components/table_body/table_body.js";
|
|
5
|
+
import { TableColumn } from "../_components/table_body/table_column.js";
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Table',
|
|
8
|
+
};
|
|
9
|
+
const items = [
|
|
10
|
+
{ id: 'one', name: 'Sam Spade', age: 22 },
|
|
11
|
+
{ id: 'two', name: 'Kelsior', age: 166 },
|
|
12
|
+
{ id: 'three', name: 'Tress', age: 17 },
|
|
13
|
+
{ id: 'four', name: 'Breeze', age: 45 },
|
|
14
|
+
{ id: 'five', name: 'Spook', age: 17 },
|
|
15
|
+
{ id: 'six', name: 'Anne', age: 32 },
|
|
16
|
+
{ id: 'seven', name: 'Hoid', age: 1934 },
|
|
17
|
+
{ id: 'eight', name: 'Vasher', age: 320 },
|
|
18
|
+
];
|
|
19
|
+
export function Basic() {
|
|
20
|
+
const [source] = useState(() => {
|
|
21
|
+
return new StaticDataSource(items, [
|
|
22
|
+
new StaticStringField('name', i => i.name),
|
|
23
|
+
new StaticNumberField('age', i => i.age),
|
|
24
|
+
]);
|
|
25
|
+
});
|
|
26
|
+
return (React.createElement(TableBody, { dataSource: source },
|
|
27
|
+
React.createElement(TableColumn, { heading: "Name", fieldName: "name" }),
|
|
28
|
+
React.createElement(TableColumn, { heading: "Age", fieldName: "age" }),
|
|
29
|
+
React.createElement("div", null, "Other kinds of children don't render")));
|
|
30
|
+
}
|
|
31
|
+
export function WithSort() {
|
|
32
|
+
const [source] = useState(() => {
|
|
33
|
+
return new StaticDataSource(items, [
|
|
34
|
+
new StaticStringField('name', i => i.name),
|
|
35
|
+
new StaticNumberField('age', i => i.age),
|
|
36
|
+
]);
|
|
37
|
+
});
|
|
38
|
+
const currentResults = useSignalValue(source.broadcasts.currentResults);
|
|
39
|
+
return (React.createElement(TableBody, { dataSource: source },
|
|
40
|
+
React.createElement(TableColumn, { heading: "Name", footer: "Some Names", fieldName: "name", canSort: true }),
|
|
41
|
+
React.createElement(TableColumn, { heading: "Age", footer: `Average Age: ${Math.round(currentResults.reduce((sum, i) => sum + i.age, 0) / currentResults.length)}`, fieldName: "age", canSort: true, width: 120 })));
|
|
42
|
+
}
|
|
43
|
+
export function ComplexHeadersAndFooters() {
|
|
44
|
+
const [source] = useState(() => {
|
|
45
|
+
return new StaticDataSource(items, [
|
|
46
|
+
new StaticStringField('name', i => i.name),
|
|
47
|
+
new StaticNumberField('age', i => i.age),
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
return (React.createElement(TableBody, { dataSource: source },
|
|
51
|
+
React.createElement(TableColumn, { heading: React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
|
|
52
|
+
React.createElement("span", null, "\uD83D\uDC64"),
|
|
53
|
+
React.createElement("span", null, "Name")), footer: React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between' } },
|
|
54
|
+
React.createElement("span", null, "Total:"),
|
|
55
|
+
React.createElement("span", null, items.length)), fieldName: "name", render: (i) => i.name }),
|
|
56
|
+
React.createElement(TableColumn, { heading: React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
|
|
57
|
+
React.createElement("span", null, "\uD83C\uDF82"),
|
|
58
|
+
React.createElement("span", null, "Age")), footer: React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between' } },
|
|
59
|
+
React.createElement("span", null, "Average:"),
|
|
60
|
+
React.createElement("span", null, Math.round(items.reduce((sum, i) => sum + i.age, 0) / items.length))), fieldName: "age", render: (i) => i.age })));
|
|
61
|
+
}
|
|
62
|
+
export default meta;
|
|
63
|
+
//# sourceMappingURL=table.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.stories.js","sourceRoot":"","sources":["../../src/__stories__/table.stories.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.table-cell[data-stick-to="start"] {
|
|
2
|
+
position: sticky;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: var(--start-offset, 0);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.table-cell[data-stick-to="end"] {
|
|
8
|
+
position: sticky;
|
|
9
|
+
top: 0;
|
|
10
|
+
right: var(--end-offset, 0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.table-cell[data-stick-to="start"]:dir(rtl) {
|
|
14
|
+
position: sticky;
|
|
15
|
+
top: 0;
|
|
16
|
+
right: var(--start-offset, 0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.table-cell[data-stick-to="end"]:dir(rtl) {
|
|
20
|
+
position: sticky;
|
|
21
|
+
top: 0;
|
|
22
|
+
left: var(--end-offset, 0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.table-cell[data-is-last-sticky-start="true"] {
|
|
26
|
+
border-inline-end: 1px solid #ccc;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:global(.dark-mode) .table-cell[data-is-last-sticky-start="true"] {
|
|
30
|
+
border-inline-end: 1px solid #202020;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.table-cell[data-is-last-sticky-end="true"] {
|
|
34
|
+
border-inline-start: 1px solid #ccc;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:global(.dark-mode) .table-cell[data-is-last-sticky-end="true"] {
|
|
38
|
+
border-inline-start: 1px solid #202020;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.table-cell[data-no-border="true"] {
|
|
42
|
+
border-inline: none;
|
|
43
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cellStyles from './cell.module.css';
|
|
3
|
+
export function DataCell({ content, sticky, width }) {
|
|
4
|
+
return (React.createElement("td", { className: cellStyles['table-cell'], "data-stick-to": sticky, style: {
|
|
5
|
+
width: `${width}px`,
|
|
6
|
+
minWidth: `${width}px`,
|
|
7
|
+
maxWidth: `${width}px`,
|
|
8
|
+
padding: '4px 6px',
|
|
9
|
+
} }, content));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=data_cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data_cell.js","sourceRoot":"","sources":["../../../src/_components/cells/data_cell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAQ3C,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAiB;IAChE,OAAO,CACL,4BACE,SAAS,EAAE,UAAU,CAAC,YAAY,CAAC,mBACpB,MAAM,EACrB,KAAK,EAAE;YACL,KAAK,EAAE,GAAG,KAAK,IAAI;YACnB,QAAQ,EAAE,GAAG,KAAK,IAAI;YACtB,QAAQ,EAAE,GAAG,KAAK,IAAI;YACtB,OAAO,EAAE,SAAS;SACnB,IAEA,OAAO,CACL,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import cellStyles from './cell.module.css';
|
|
3
|
+
export function FooterCell({ content, sticky, width }) {
|
|
4
|
+
return (React.createElement("td", { className: cellStyles['table-cell'], "data-stick-to": sticky, style: {
|
|
5
|
+
width: `${width}px`,
|
|
6
|
+
minWidth: `${width}px`,
|
|
7
|
+
maxWidth: `${width}px`,
|
|
8
|
+
padding: '4px 6px',
|
|
9
|
+
} }, content));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=footer_cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footer_cell.js","sourceRoot":"","sources":["../../../src/_components/cells/footer_cell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAQ3C,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAmB;IACpE,OAAO,CACL,4BACE,SAAS,EAAE,UAAU,CAAC,YAAY,CAAC,mBACpB,MAAM,EACrB,KAAK,EAAE;YACL,KAAK,EAAE,GAAG,KAAK,IAAI;YACnB,QAAQ,EAAE,GAAG,KAAK,IAAI;YACtB,QAAQ,EAAE,GAAG,KAAK,IAAI;YACtB,OAAO,EAAE,SAAS;SACnB,IAEA,OAAO,CACL,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type HeaderCellProps = {
|
|
3
|
+
heading: React.ReactNode;
|
|
4
|
+
index: number;
|
|
5
|
+
sticky?: 'start' | 'end';
|
|
6
|
+
onResize?: (width: number) => void;
|
|
7
|
+
width?: number;
|
|
8
|
+
sortMode?: 'none' | 'asc' | 'desc';
|
|
9
|
+
onSortModeChange?: () => void;
|
|
10
|
+
canSort?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare function HeaderCell({ heading, sticky, onResize, width, sortMode, onSortModeChange, canSort, }: HeaderCellProps): React.JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, FlexBox, HStack } from '@tcn/ui-layout';
|
|
3
|
+
import cellStyles from './cell.module.css';
|
|
4
|
+
export function HeaderCell({ heading, sticky, onResize, width, sortMode, onSortModeChange, canSort, }) {
|
|
5
|
+
const zIndex = sticky != null ? 2 : 1;
|
|
6
|
+
return (React.createElement("th", { className: cellStyles['table-cell'], "data-stick-to": sticky, style: { width: `${width}px`, zIndex } },
|
|
7
|
+
React.createElement(Box, { padding: "4px 6px", overflow: "hidden", enableResizeOnEnd: true, onWidthResize: newSize => onResize?.(newSize), style: { width: `${width}px` }, onClick: e => e.stopPropagation() },
|
|
8
|
+
React.createElement(HStack, { onClick: () => canSort && onSortModeChange?.() },
|
|
9
|
+
React.createElement(FlexBox, { shrinkWeight: 1, className: "ellipsis" }, heading),
|
|
10
|
+
React.createElement(Box, { width: "auto" },
|
|
11
|
+
sortMode === 'asc' && '↓',
|
|
12
|
+
sortMode === 'desc' && '↑')))));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=header_cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header_cell.js","sourceRoot":"","sources":["../../../src/_components/cells/header_cell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAa3C,MAAM,UAAU,UAAU,CAAC,EACzB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,OAAO,GACS;IAChB,MAAM,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,CACL,4BACE,SAAS,EAAE,UAAU,CAAC,YAAY,CAAC,mBACpB,MAAM,EACrB,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,MAAM,EAAE;QAEtC,oBAAC,GAAG,IACF,OAAO,EAAC,SAAS,EACjB,QAAQ,EAAC,QAAQ,EACjB,iBAAiB,QACjB,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAC7C,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,EAC9B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;YAEjC,oBAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,IAAI,gBAAgB,EAAE,EAAE;gBACpD,oBAAC,OAAO,IAAC,YAAY,EAAE,CAAC,EAAE,SAAS,EAAC,UAAU,IAC3C,OAAO,CACA;gBACV,oBAAC,GAAG,IAAC,KAAK,EAAC,MAAM;oBACd,QAAQ,KAAK,KAAK,IAAI,GAAG;oBACzB,QAAQ,KAAK,MAAM,IAAI,GAAG,CACvB,CACC,CACL,CACH,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { DataSource } from '@tcn-internal/resource-store';
|
|
3
|
+
import { TableColumnProps } from './table_column.js';
|
|
4
|
+
export type TableBodyProps<T> = {
|
|
5
|
+
dataSource: DataSource<T>;
|
|
6
|
+
children: ReactElement<TableColumnProps<T>>[];
|
|
7
|
+
height?: string;
|
|
8
|
+
width?: string;
|
|
9
|
+
zIndex?: number;
|
|
10
|
+
highlightedRows?: Set<number> | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function TableBody<T>({ dataSource, children, width, height, zIndex, highlightedRows, }: TableBodyProps<T>): React.JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { isValidElement, useState, useRef } from 'react';
|
|
2
|
+
import { Status, useRunnerStatus, useSignalValue } from '@tcn/state';
|
|
3
|
+
import { Text } from '@tcn/ui-core';
|
|
4
|
+
import { Box } from '@tcn/ui-layout';
|
|
5
|
+
import { DataCell } from '../cells/data_cell.js';
|
|
6
|
+
import { FooterCell } from '../cells/footer_cell.js';
|
|
7
|
+
import { HeaderCell } from '../cells/header_cell.js';
|
|
8
|
+
import styles from './table_body.module.css';
|
|
9
|
+
import { TableBodyPresenter } from './table_body_presenter.js';
|
|
10
|
+
import { TableColumn } from './table_column.js';
|
|
11
|
+
// @TODO: Props for loading and error states
|
|
12
|
+
function wrapContent(content) {
|
|
13
|
+
if (typeof content === 'string') {
|
|
14
|
+
return React.createElement(Text, null, content);
|
|
15
|
+
}
|
|
16
|
+
return content;
|
|
17
|
+
}
|
|
18
|
+
export function TableBody({ dataSource, children, width = '100%', height = '100%', zIndex, highlightedRows, }) {
|
|
19
|
+
const rows = useSignalValue(dataSource.broadcasts.currentResults);
|
|
20
|
+
const page = useSignalValue(dataSource.broadcasts.currentPageIndex);
|
|
21
|
+
const scrollerRef = useRef(null);
|
|
22
|
+
const columns = React.Children.toArray(children).filter((child) => isValidElement(child) && child.type === TableColumn);
|
|
23
|
+
const [presenter] = useState(() => new TableBodyPresenter({
|
|
24
|
+
dataSource,
|
|
25
|
+
columns: columns.map(column => ({
|
|
26
|
+
fieldName: column.props.fieldName,
|
|
27
|
+
width: column.props.width ?? 100,
|
|
28
|
+
sortMode: 'none',
|
|
29
|
+
canSort: column.props.canSort ?? false,
|
|
30
|
+
heading: column.props.heading,
|
|
31
|
+
footer: column.props.footer,
|
|
32
|
+
sticky: column.props.sticky,
|
|
33
|
+
render: column.props.render,
|
|
34
|
+
})),
|
|
35
|
+
scrollerRef,
|
|
36
|
+
}));
|
|
37
|
+
const columnInfo = useSignalValue(presenter.broadcasts.columnInfo);
|
|
38
|
+
const itemsStatus = useRunnerStatus(dataSource.broadcasts.currentResults);
|
|
39
|
+
return (React.createElement(Box, { ref: scrollerRef, zIndex: zIndex, className: styles['table-body-wrapper'], style: { overflow: 'auto' } },
|
|
40
|
+
React.createElement("table", { className: styles['table-body'], style: { width, height } },
|
|
41
|
+
React.createElement("thead", null,
|
|
42
|
+
React.createElement("tr", null,
|
|
43
|
+
columnInfo.map((column, index) => (React.createElement(HeaderCell, { key: `h-${index}`, index: index, heading: wrapContent(column.heading), sticky: column.sticky, onResize: newSize => presenter.setColumnWidth(index, newSize), width: column.width, sortMode: column.sortMode, onSortModeChange: () => presenter.setNextColumnSortMode(index), canSort: column.canSort }))),
|
|
44
|
+
React.createElement("th", { key: "fill", className: "fill" }))),
|
|
45
|
+
React.createElement("tbody", null,
|
|
46
|
+
itemsStatus === Status.SUCCESS &&
|
|
47
|
+
rows.map((item, rowIndex) => (React.createElement("tr", { key: `${page}-${rowIndex}`, "data-selected": highlightedRows?.has(rowIndex) },
|
|
48
|
+
columnInfo.map((col, colIndex) => {
|
|
49
|
+
const fieldName = col.fieldName;
|
|
50
|
+
const render = col.render;
|
|
51
|
+
const content = render
|
|
52
|
+
? render(item)
|
|
53
|
+
: fieldName
|
|
54
|
+
? item[fieldName]
|
|
55
|
+
: '';
|
|
56
|
+
return (React.createElement(DataCell, { key: `${page}-${rowIndex}-${colIndex}`, content: content, sticky: col.sticky, width: col.width }));
|
|
57
|
+
}),
|
|
58
|
+
React.createElement("td", { key: "fill", className: "fill" })))),
|
|
59
|
+
itemsStatus === Status.PENDING && 'Loading...',
|
|
60
|
+
itemsStatus === Status.ERROR && 'Error loading data',
|
|
61
|
+
React.createElement("tr", { key: "fill", className: "fill" })),
|
|
62
|
+
React.createElement("tfoot", null,
|
|
63
|
+
React.createElement("tr", null,
|
|
64
|
+
columnInfo.map((col, colIndex) => (React.createElement(FooterCell, { key: `footer-${colIndex}`, content: wrapContent(col.footer), sticky: col.sticky, width: col.width }))),
|
|
65
|
+
React.createElement("td", { key: "footer-fill", className: "fill" }))))));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=table_body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_body.js","sourceRoot":"","sources":["../../../src/_components/table_body/table_body.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
.table-body-wrapper {
|
|
2
|
+
box-shadow: var(--table-box-shadow, inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5));
|
|
3
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
|
|
4
|
+
Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
|
5
|
+
color: #333;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.table-body {
|
|
9
|
+
border-spacing: 0;
|
|
10
|
+
width: auto;
|
|
11
|
+
min-width: 100%;
|
|
12
|
+
height: auto;
|
|
13
|
+
min-height: 100%;
|
|
14
|
+
font-size: 12px;
|
|
15
|
+
table-layout: fixed;
|
|
16
|
+
background-color: #ebebeb;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
:global(.dark-mode) .table-body {
|
|
20
|
+
background-color: #333;
|
|
21
|
+
color: rgba(255, 255, 255, 0.9);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
td {
|
|
25
|
+
text-align: start;
|
|
26
|
+
padding: 8px;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
white-space: nowrap;
|
|
29
|
+
text-overflow: ellipsis;
|
|
30
|
+
padding: 0px 4px;
|
|
31
|
+
background-color: inherit;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.table-body tr {
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.table-body tr[data-clickable="true"] {
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.table-body thead tr th {
|
|
43
|
+
position: sticky;
|
|
44
|
+
top: 0px;
|
|
45
|
+
z-index: 1;
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.table-body thead {
|
|
50
|
+
position: sticky;
|
|
51
|
+
top: 0px;
|
|
52
|
+
z-index: 3;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.table-body tbody {
|
|
56
|
+
position: relative;
|
|
57
|
+
z-index: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.table-body tfoot {
|
|
61
|
+
position: relative;
|
|
62
|
+
z-index: 2;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.table-body th {
|
|
66
|
+
background-color: #f1f1f1; /* Light grey background */
|
|
67
|
+
color: #000; /* Black text color */
|
|
68
|
+
font-weight: normal;
|
|
69
|
+
text-align: start;
|
|
70
|
+
border-inline-start: 1px solid #ccc;
|
|
71
|
+
border-bottom: 1px solid #ccc;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.table-body th:first-child {
|
|
75
|
+
border-inline-start: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.table-body th:last-child {
|
|
79
|
+
border-inline: 1px solid #ccc;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:global(.dark-mode) .table-body th:last-child {
|
|
83
|
+
border-inline: 1px solid #202020;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.table-body td:last-child {
|
|
87
|
+
border-inline: 1px solid #ccc;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
:global(.dark-mode) .table-body td:last-child {
|
|
91
|
+
border-inline: 1px solid #202020;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:global(.dark-mode) .table-body th {
|
|
95
|
+
color: rgba(255, 255, 255, 0.9);
|
|
96
|
+
border-bottom: 1px solid #202020;
|
|
97
|
+
border-inline-start: 1px solid #202020;
|
|
98
|
+
background-color: #333;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.table-body td {
|
|
102
|
+
border-bottom: 1px solid #e0e0e0; /* Lighter border for cells */
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
:global(.dark-mode) .table-body td {
|
|
106
|
+
border-bottom: 1px solid #202020; /* Lighter border for cells */
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.table-body tr:nth-child(odd) {
|
|
110
|
+
background-color: #f1f1f1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.table-body tr:nth-child(even) {
|
|
114
|
+
background-color: rgba(255, 255, 255);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:global(.dark-mode) .table-body tr:nth-child(odd) {
|
|
118
|
+
background-color: #3b3b3b; /* Zebra striping for rows */
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
:global(.dark-mode) .table-body tr:nth-child(even) {
|
|
122
|
+
background-color: #2e2e2e;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Hover effect for rows */
|
|
126
|
+
.table-body tr:hover {
|
|
127
|
+
background-color: #dedede;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
:global(.dark-mode) .table-body tr:hover {
|
|
131
|
+
background-color: rgba(30, 30, 30, 1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Styling for the table's header row to mimic macOS window styling */
|
|
135
|
+
.table-body thead {
|
|
136
|
+
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Footer styling, if applicable */
|
|
140
|
+
.table-body tfoot td {
|
|
141
|
+
background-color: #f0f0f0;
|
|
142
|
+
font-weight: bold;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.table-body tr:global(.fill) {
|
|
146
|
+
height: auto;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.table-body tr td:global(.fill) {
|
|
150
|
+
width: auto;
|
|
151
|
+
min-width: none;
|
|
152
|
+
background-color: inherit;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.table-body tr th:global(.fill) {
|
|
156
|
+
width: auto;
|
|
157
|
+
background-color: inherit;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.table-body tfoot {
|
|
161
|
+
position: sticky;
|
|
162
|
+
bottom: 0px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.table-body tr[data-selected="true"] {
|
|
166
|
+
background-color: var(--accent-color, #549aff);
|
|
167
|
+
color: #fff;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
:global(.dark-mode) .table-body tr[data-selected="true"] {
|
|
171
|
+
background-color: var(--accent-color, #549aff);
|
|
172
|
+
color: #fff;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.table-body td,
|
|
176
|
+
.table-body th {
|
|
177
|
+
padding: 4px 6px;
|
|
178
|
+
max-height: 22px;
|
|
179
|
+
height: 22px;
|
|
180
|
+
font-size: 12px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
:global(.small-text) .table-body td,
|
|
184
|
+
:global(.small-text) .table-body th {
|
|
185
|
+
padding: 2px 4px;
|
|
186
|
+
max-height: 20px;
|
|
187
|
+
height: 20px;
|
|
188
|
+
font-size: 10px;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:global(.medium-small-text) .table-body td,
|
|
192
|
+
:global(.medium-small-text) .table-body th {
|
|
193
|
+
padding: 4px 6px;
|
|
194
|
+
max-height: 22px;
|
|
195
|
+
height: 22px;
|
|
196
|
+
font-size: 12px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
:global(.medium-text) .table-body td,
|
|
200
|
+
:global(.medium-text) .table-body th {
|
|
201
|
+
padding: 6px 8px;
|
|
202
|
+
max-height: 24px;
|
|
203
|
+
height: 24px;
|
|
204
|
+
font-size: 14px;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
:global(.medium-large-text) .table-body td,
|
|
208
|
+
:global(.medium-large-text) .table-body th {
|
|
209
|
+
padding: 8px 10px;
|
|
210
|
+
max-height: 26px;
|
|
211
|
+
height: 26px;
|
|
212
|
+
font-size: 16px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
:global(.large-text) .table-body td,
|
|
216
|
+
:global(.large-text) .table-body th {
|
|
217
|
+
padding: 10px 12px;
|
|
218
|
+
height: 28px;
|
|
219
|
+
max-height: 28px;
|
|
220
|
+
font-size: 18px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.table-body th {
|
|
224
|
+
padding: 0 !important;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.table-body tr th:global(.spacer) {
|
|
228
|
+
background-color: #f1f1f1;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
:global(.dark-mode) .table-body tr th:global(.spacer) {
|
|
232
|
+
background-color: #333;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.table-body tr th:global(.fill) {
|
|
236
|
+
background-color: #f1f1f1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
:global(.dark-mode) .table-body tr th:global(.fill) {
|
|
240
|
+
background-color: #333;
|
|
241
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
import { DataSource } from '@tcn-internal/resource-store';
|
|
3
|
+
type SortMode = 'none' | 'asc' | 'desc';
|
|
4
|
+
export type ColumnInfo = {
|
|
5
|
+
width: number;
|
|
6
|
+
render?: (item: any) => ReactNode;
|
|
7
|
+
sortMode: SortMode;
|
|
8
|
+
canSort: boolean;
|
|
9
|
+
heading: ReactNode;
|
|
10
|
+
footer?: ReactNode;
|
|
11
|
+
sticky?: 'start' | 'end';
|
|
12
|
+
fieldName?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare class TableBodyPresenter {
|
|
15
|
+
private _columnInfo;
|
|
16
|
+
private _dataSource;
|
|
17
|
+
private _broadcasts;
|
|
18
|
+
private _scrollerRef?;
|
|
19
|
+
private _pageSubscription?;
|
|
20
|
+
constructor({ dataSource, columns, scrollerRef, }: {
|
|
21
|
+
dataSource: DataSource<any>;
|
|
22
|
+
columns: ColumnInfo[];
|
|
23
|
+
scrollerRef?: RefObject<HTMLDivElement>;
|
|
24
|
+
});
|
|
25
|
+
get broadcasts(): {
|
|
26
|
+
columnInfo: import("@tcn/state").IBroadcast<ColumnInfo[]>;
|
|
27
|
+
};
|
|
28
|
+
setColumnWidth(index: number, width: number): void;
|
|
29
|
+
setColumnSortMode(index: number, sortMode: SortMode): void;
|
|
30
|
+
setNextColumnSortMode(index: number): void;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Signal } from '@tcn/state';
|
|
2
|
+
const sortModes = ['none', 'asc', 'desc'];
|
|
3
|
+
export class TableBodyPresenter {
|
|
4
|
+
_columnInfo = new Signal([]);
|
|
5
|
+
_dataSource;
|
|
6
|
+
_broadcasts = {
|
|
7
|
+
columnInfo: this._columnInfo.broadcast,
|
|
8
|
+
};
|
|
9
|
+
_scrollerRef;
|
|
10
|
+
_pageSubscription;
|
|
11
|
+
constructor({ dataSource, columns, scrollerRef, }) {
|
|
12
|
+
this._dataSource = dataSource;
|
|
13
|
+
this._columnInfo.set(columns);
|
|
14
|
+
this._scrollerRef = scrollerRef;
|
|
15
|
+
this._pageSubscription = this._dataSource.broadcasts.currentPageIndex.subscribe(_ => {
|
|
16
|
+
if (this._scrollerRef?.current) {
|
|
17
|
+
this._scrollerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
get broadcasts() {
|
|
22
|
+
return this._broadcasts;
|
|
23
|
+
}
|
|
24
|
+
setColumnWidth(index, width) {
|
|
25
|
+
this._columnInfo.transform(columnInfo => {
|
|
26
|
+
columnInfo[index].width = width;
|
|
27
|
+
return columnInfo;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
setColumnSortMode(index, sortMode) {
|
|
31
|
+
const column = this._columnInfo.get()[index];
|
|
32
|
+
const fieldName = column.fieldName;
|
|
33
|
+
if (!column.canSort) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!fieldName) {
|
|
37
|
+
// can't sort a field without a name
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this._dataSource.setFieldSort(fieldName, sortMode);
|
|
41
|
+
this._columnInfo.transform(columnInfo => {
|
|
42
|
+
columnInfo[index].sortMode = sortMode;
|
|
43
|
+
return columnInfo;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
setNextColumnSortMode(index) {
|
|
47
|
+
const column = this._columnInfo.get()[index];
|
|
48
|
+
const currentMode = column.sortMode;
|
|
49
|
+
const currentIndex = sortModes.indexOf(currentMode);
|
|
50
|
+
const nextIndex = (currentIndex + 1) % sortModes.length;
|
|
51
|
+
const nextMode = sortModes[nextIndex];
|
|
52
|
+
this.setColumnSortMode(index, nextMode);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=table_body_presenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_body_presenter.js","sourceRoot":"","sources":["../../../src/_components/table_body/table_body_presenter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,MAAM,EAAE,MAAM,YAAY,CAAC;AAInD,MAAM,SAAS,GAAe,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAatD,MAAM,OAAO,kBAAkB;IACrB,WAAW,GAAG,IAAI,MAAM,CAAe,EAAE,CAAC,CAAC;IAC3C,WAAW,CAAkB;IAC7B,WAAW,GAAG;QACpB,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS;KACvC,CAAC;IAEM,YAAY,CAA6B;IAEzC,iBAAiB,CAAyB;IAElD,YAAY,EACV,UAAU,EACV,OAAO,EACP,WAAW,GAKZ;QACC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAEhC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YAClF,IAAI,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;gBAC/B,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,cAAc,CAAC,KAAa,EAAE,KAAa;QACzC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;YACtC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;YAChC,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iBAAiB,CAAC,KAAa,EAAE,QAAkB;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,oCAAoC;YACpC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEnD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;YACtC,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACtC,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qBAAqB,CAAC,KAAa;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC;QACpC,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;QACxD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAEtC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { StaticDataSource, StaticStringField } from '@tcn-internal/resource-store';
|
|
2
|
+
import { Signal } from '@tcn/state';
|
|
3
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import { TableBodyPresenter } from './table_body_presenter.js';
|
|
5
|
+
describe('TableBodyPresenter', () => {
|
|
6
|
+
let dataSource;
|
|
7
|
+
let mockColumnInfo;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
dataSource = new StaticDataSource([], [
|
|
10
|
+
new StaticStringField('name', i => i.name),
|
|
11
|
+
new StaticStringField('age', i => i.age),
|
|
12
|
+
]);
|
|
13
|
+
mockColumnInfo = [
|
|
14
|
+
{
|
|
15
|
+
width: 100,
|
|
16
|
+
sortMode: 'none',
|
|
17
|
+
canSort: true,
|
|
18
|
+
heading: 'Name',
|
|
19
|
+
fieldName: 'name',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
width: 100,
|
|
23
|
+
sortMode: 'none',
|
|
24
|
+
canSort: false,
|
|
25
|
+
heading: 'Age',
|
|
26
|
+
fieldName: 'age',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
});
|
|
30
|
+
describe('constructor', () => {
|
|
31
|
+
it('initializes with provided data source and columns', () => {
|
|
32
|
+
const presenter = new TableBodyPresenter({
|
|
33
|
+
dataSource,
|
|
34
|
+
columns: mockColumnInfo,
|
|
35
|
+
});
|
|
36
|
+
const columnInfo = presenter.broadcasts.columnInfo.get();
|
|
37
|
+
expect(columnInfo).toEqual(mockColumnInfo);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('setColumnWidth', () => {
|
|
41
|
+
it('updates the width of the specified column', () => {
|
|
42
|
+
const presenter = new TableBodyPresenter({
|
|
43
|
+
dataSource,
|
|
44
|
+
columns: mockColumnInfo,
|
|
45
|
+
});
|
|
46
|
+
const newWidth = 200;
|
|
47
|
+
presenter.setColumnWidth(0, newWidth);
|
|
48
|
+
const columnInfo = presenter.broadcasts.columnInfo.get();
|
|
49
|
+
expect(columnInfo[0].width).toBe(newWidth);
|
|
50
|
+
expect(columnInfo[1].width).toBe(mockColumnInfo[1].width);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('setColumnSortMode', () => {
|
|
54
|
+
it('updates sort mode and calls setFieldSort when fieldName exists', () => {
|
|
55
|
+
const presenter = new TableBodyPresenter({
|
|
56
|
+
dataSource,
|
|
57
|
+
columns: mockColumnInfo,
|
|
58
|
+
});
|
|
59
|
+
const newSortMode = 'asc';
|
|
60
|
+
presenter.setColumnSortMode(0, newSortMode);
|
|
61
|
+
const columnInfo = presenter.broadcasts.columnInfo.get();
|
|
62
|
+
expect(columnInfo[0].sortMode).toBe(newSortMode);
|
|
63
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([['name', 'asc']]);
|
|
64
|
+
});
|
|
65
|
+
it('does not update sort mode or call setFieldSort when fieldName is missing', () => {
|
|
66
|
+
const columnsWithoutFieldName = [
|
|
67
|
+
{
|
|
68
|
+
width: 100,
|
|
69
|
+
sortMode: 'none',
|
|
70
|
+
canSort: true,
|
|
71
|
+
heading: 'Name',
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
const presenter = new TableBodyPresenter({
|
|
75
|
+
dataSource,
|
|
76
|
+
columns: columnsWithoutFieldName,
|
|
77
|
+
});
|
|
78
|
+
const newSortMode = 'asc';
|
|
79
|
+
presenter.setColumnSortMode(0, newSortMode);
|
|
80
|
+
const columnInfo = presenter.broadcasts.columnInfo.get();
|
|
81
|
+
expect(columnInfo[0].sortMode).toBe('none');
|
|
82
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([]);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('setNextColumnSortMode', () => {
|
|
86
|
+
it('cycles through sort modes in order: none -> asc -> desc -> none', () => {
|
|
87
|
+
const presenter = new TableBodyPresenter({
|
|
88
|
+
dataSource,
|
|
89
|
+
columns: mockColumnInfo,
|
|
90
|
+
});
|
|
91
|
+
// First click: none -> asc
|
|
92
|
+
presenter.setNextColumnSortMode(0);
|
|
93
|
+
expect(presenter.broadcasts.columnInfo.get()[0].sortMode).toBe('asc');
|
|
94
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([['name', 'asc']]);
|
|
95
|
+
// Second click: asc -> desc
|
|
96
|
+
presenter.setNextColumnSortMode(0);
|
|
97
|
+
expect(presenter.broadcasts.columnInfo.get()[0].sortMode).toBe('desc');
|
|
98
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([['name', 'desc']]);
|
|
99
|
+
// Third click: desc -> none
|
|
100
|
+
presenter.setNextColumnSortMode(0);
|
|
101
|
+
expect(presenter.broadcasts.columnInfo.get()[0].sortMode).toBe('none');
|
|
102
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
it('does not cycle sort modes for unsortable columns', () => {
|
|
105
|
+
const presenter = new TableBodyPresenter({
|
|
106
|
+
dataSource,
|
|
107
|
+
columns: mockColumnInfo,
|
|
108
|
+
});
|
|
109
|
+
presenter.setNextColumnSortMode(1);
|
|
110
|
+
expect(presenter.broadcasts.columnInfo.get()[1].sortMode).toBe('none');
|
|
111
|
+
expect(dataSource.broadcasts.sortStatus.get()).toEqual([]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('broadcasts', () => {
|
|
115
|
+
it('provides access to column info signal', () => {
|
|
116
|
+
const presenter = new TableBodyPresenter({
|
|
117
|
+
dataSource,
|
|
118
|
+
columns: mockColumnInfo,
|
|
119
|
+
});
|
|
120
|
+
expect(presenter.broadcasts.columnInfo).toBeInstanceOf(Signal);
|
|
121
|
+
expect(presenter.broadcasts.columnInfo.get()).toEqual(mockColumnInfo);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=table_body_presenter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_body_presenter.test.js","sourceRoot":"","sources":["../../../src/_components/table_body/table_body_presenter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
type BaseTableColumnProps<T> = {
|
|
3
|
+
heading: React.ReactNode;
|
|
4
|
+
footer?: React.ReactNode;
|
|
5
|
+
render?: (item: T) => React.ReactNode;
|
|
6
|
+
sticky?: 'start' | 'end';
|
|
7
|
+
width?: number;
|
|
8
|
+
};
|
|
9
|
+
type SortableTableColumnProps<T> = BaseTableColumnProps<T> & {
|
|
10
|
+
fieldName: string;
|
|
11
|
+
canSort: true;
|
|
12
|
+
};
|
|
13
|
+
type NonSortableTableColumnProps<T> = BaseTableColumnProps<T> & {
|
|
14
|
+
fieldName?: string;
|
|
15
|
+
canSort?: false;
|
|
16
|
+
};
|
|
17
|
+
export type TableColumnProps<T> = SortableTableColumnProps<T> | NonSortableTableColumnProps<T>;
|
|
18
|
+
export declare function TableColumn<T>(_props: TableColumnProps<T>): null;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_column.js","sourceRoot":"","sources":["../../../src/_components/table_body/table_column.tsx"],"names":[],"mappings":"AAsBA,qEAAqE;AACrE,8BAA8B;AAC9B,MAAM,UAAU,WAAW,CAAI,MAA2B;IACxD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSignalValue } from '@tcn/state';
|
|
3
|
+
import { Button } from '@tcn/ui-controls';
|
|
4
|
+
import { Box } from '@tcn/ui-layout';
|
|
5
|
+
export function TableFooter({ dataSource }) {
|
|
6
|
+
const pageIndex = useSignalValue(dataSource.broadcasts.currentPageIndex);
|
|
7
|
+
return (React.createElement(Box, null,
|
|
8
|
+
"Page: ",
|
|
9
|
+
pageIndex + 1,
|
|
10
|
+
React.createElement(Button, { onClick: () => dataSource.previousPage(), disabled: pageIndex === 0 }, "<"),
|
|
11
|
+
React.createElement(Button, { onClick: () => dataSource.nextPage() }, ">")));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=table_footer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_footer.js","sourceRoot":"","sources":["../../src/_components/table_footer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAMrC,MAAM,UAAU,WAAW,CAAI,EAAE,UAAU,EAAuB;IAChE,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAEzE,OAAO,CACL,oBAAC,GAAG;;QACK,SAAS,GAAG,CAAC;QACpB,oBAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,SAAS,KAAK,CAAC,QAElE;QACT,oBAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAe,CACvD,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DataSource } from '@tcn-internal/resource-store';
|
|
3
|
+
export type TableHeaderProps = {
|
|
4
|
+
title: string;
|
|
5
|
+
dataSource: DataSource<any>;
|
|
6
|
+
};
|
|
7
|
+
export declare function TableHeader({ title, dataSource }: TableHeaderProps): React.JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useSignalValue } from '@tcn/state';
|
|
3
|
+
import { Input } from '@tcn/ui-controls';
|
|
4
|
+
import { Text } from '@tcn/ui-core';
|
|
5
|
+
import { Box, FlexBox, HStack } from '@tcn/ui-layout';
|
|
6
|
+
export function TableHeader({ title, dataSource }) {
|
|
7
|
+
const filterString = useSignalValue(dataSource.broadcasts.filterString);
|
|
8
|
+
return (React.createElement(HStack, null,
|
|
9
|
+
React.createElement(FlexBox, { width: "auto" },
|
|
10
|
+
React.createElement(Text, { variant: "large" }, title)),
|
|
11
|
+
React.createElement(Box, { width: "300px" },
|
|
12
|
+
React.createElement(Input, { placeholder: "Search", value: filterString, onChange: e => dataSource.setFilterString(e) }))));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=table_header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table_header.js","sourceRoot":"","sources":["../../src/_components/table_header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAOtD,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAoB;IACjE,MAAM,YAAY,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAExE,OAAO,CACL,oBAAC,MAAM;QACL,oBAAC,OAAO,IAAC,KAAK,EAAC,MAAM;YACnB,oBAAC,IAAI,IAAC,OAAO,EAAC,OAAO,IAAE,KAAK,CAAQ,CAC5B;QACV,oBAAC,GAAG,IAAC,KAAK,EAAC,OAAO;YAChB,oBAAC,KAAK,IACJ,WAAW,EAAC,QAAQ,EACpB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,GAC5C,CACE,CACC,CACV,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { TableBody } from './_components/table_body/table_body.js';
|
|
2
|
+
export { TableColumn } from './_components/table_body/table_column.js';
|
|
3
|
+
export { TableFooter } from './_components/table_footer.js';
|
|
4
|
+
export { TableHeader } from './_components/table_header.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tcn/ui-table",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "TCN",
|
|
6
|
+
"description": "Blackcat UI Table",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/**/*"
|
|
9
|
+
],
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"peerDependencies": {
|
|
13
|
+
"react": "^18.2.0",
|
|
14
|
+
"react-dom": "^18.2.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"check-all": "concurrently 'yarn check-types' 'biome check .'",
|
|
18
|
+
"check-types": "tspc --project ./tsconfig.types.json --noEmit",
|
|
19
|
+
"check-format": "biome format .",
|
|
20
|
+
"check-lint": "biome lint .",
|
|
21
|
+
"fix-all": "biome check --write",
|
|
22
|
+
"fix-format": "biome format --write",
|
|
23
|
+
"fix-lint": "biome lint --write",
|
|
24
|
+
"fix-imports": "biome check --formatter-enabled=false --linter-enabled=false --organize-imports-enabled=true --write",
|
|
25
|
+
"build": "tspc && copyfiles -u 1 'src/**/*.css' dist/",
|
|
26
|
+
"build-types": "tspc --project ./tsconfig.types.json --emitDeclarationOnly",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test-coverage": "vitest run --coverage",
|
|
29
|
+
"storybook": "storybook dev -p 6006",
|
|
30
|
+
"build-storybook": "storybook build"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@biomejs/biome": "1.9.4",
|
|
34
|
+
"@chromatic-com/storybook": "^1.2.25",
|
|
35
|
+
"@storybook/addon-essentials": "^8.0.4",
|
|
36
|
+
"@storybook/addon-interactions": "^8.0.4",
|
|
37
|
+
"@storybook/addon-links": "^8.0.4",
|
|
38
|
+
"@storybook/addon-onboarding": "^8.0.4",
|
|
39
|
+
"@storybook/blocks": "^8.0.4",
|
|
40
|
+
"@storybook/react": "^8.0.4",
|
|
41
|
+
"@storybook/react-vite": "^8.0.4",
|
|
42
|
+
"@storybook/test": "^8.0.4",
|
|
43
|
+
"@storybook/testing-library": "^0.2.2",
|
|
44
|
+
"@tcn-internal/sb-tcn-auth-addon": "^0.0.1",
|
|
45
|
+
"@types/copyfiles": "^2",
|
|
46
|
+
"@types/node": "^20.11.30",
|
|
47
|
+
"@types/react": "^18.2.70",
|
|
48
|
+
"@types/react-dom": "^18.2.22",
|
|
49
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
50
|
+
"concurrently": "^8.2.2",
|
|
51
|
+
"copyfiles": "^2.4.1",
|
|
52
|
+
"react": "^18.2.0",
|
|
53
|
+
"react-dom": "^18.2.0",
|
|
54
|
+
"read-pkg-up": "^11.0.0",
|
|
55
|
+
"storybook": "^8.0.4",
|
|
56
|
+
"ts-patch": "^3.2.1",
|
|
57
|
+
"typescript": "5.4.3",
|
|
58
|
+
"typescript-transform-paths": "^3.5.1",
|
|
59
|
+
"vite": "^5.2.6",
|
|
60
|
+
"vite-css-modules": "^1.5.2",
|
|
61
|
+
"vitest": "^2.1.4"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@tcn-internal/resource-store": "1.0.4",
|
|
65
|
+
"@tcn/state": "^0.1.4",
|
|
66
|
+
"@tcn/ui-controls": "^0.2.34",
|
|
67
|
+
"@tcn/ui-core": "^0.4.1",
|
|
68
|
+
"@tcn/ui-layout": "^0.3.38",
|
|
69
|
+
"classnames": "^2.5.1"
|
|
70
|
+
},
|
|
71
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
72
|
+
}
|