@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.
Files changed (43) hide show
  1. package/README.md +133 -0
  2. package/dist/__stories__/aip_table.stories.d.ts +5 -0
  3. package/dist/__stories__/aip_table.stories.js +88 -0
  4. package/dist/__stories__/aip_table.stories.js.map +1 -0
  5. package/dist/__stories__/auth_provider.d.ts +4 -0
  6. package/dist/__stories__/auth_provider.js +10 -0
  7. package/dist/__stories__/auth_provider.js.map +1 -0
  8. package/dist/__stories__/table.stories.d.ts +7 -0
  9. package/dist/__stories__/table.stories.js +63 -0
  10. package/dist/__stories__/table.stories.js.map +1 -0
  11. package/dist/_components/cells/cell.module.css +43 -0
  12. package/dist/_components/cells/data_cell.d.ts +7 -0
  13. package/dist/_components/cells/data_cell.js +11 -0
  14. package/dist/_components/cells/data_cell.js.map +1 -0
  15. package/dist/_components/cells/footer_cell.d.ts +7 -0
  16. package/dist/_components/cells/footer_cell.js +11 -0
  17. package/dist/_components/cells/footer_cell.js.map +1 -0
  18. package/dist/_components/cells/header_cell.d.ts +12 -0
  19. package/dist/_components/cells/header_cell.js +14 -0
  20. package/dist/_components/cells/header_cell.js.map +1 -0
  21. package/dist/_components/table_body/table_body.d.ts +12 -0
  22. package/dist/_components/table_body/table_body.js +67 -0
  23. package/dist/_components/table_body/table_body.js.map +1 -0
  24. package/dist/_components/table_body/table_body.module.css +241 -0
  25. package/dist/_components/table_body/table_body_presenter.d.ts +32 -0
  26. package/dist/_components/table_body/table_body_presenter.js +55 -0
  27. package/dist/_components/table_body/table_body_presenter.js.map +1 -0
  28. package/dist/_components/table_body/table_body_presenter.test.d.ts +1 -0
  29. package/dist/_components/table_body/table_body_presenter.test.js +125 -0
  30. package/dist/_components/table_body/table_body_presenter.test.js.map +1 -0
  31. package/dist/_components/table_body/table_column.d.ts +19 -0
  32. package/dist/_components/table_body/table_column.js +6 -0
  33. package/dist/_components/table_body/table_column.js.map +1 -0
  34. package/dist/_components/table_footer.d.ts +6 -0
  35. package/dist/_components/table_footer.js +13 -0
  36. package/dist/_components/table_footer.js.map +1 -0
  37. package/dist/_components/table_header.d.ts +7 -0
  38. package/dist/_components/table_header.js +14 -0
  39. package/dist/_components/table_header.js.map +1 -0
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.js +5 -0
  42. package/dist/index.js.map +1 -0
  43. 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,5 @@
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 default meta;
@@ -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,4 @@
1
+ import { Signal } from '@tcn/state';
2
+ import React from 'react';
3
+ export declare const AuthContext: React.Context<Signal<string> | null>;
4
+ export declare function useToken(): Signal<string>;
@@ -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,7 @@
1
+ import React from 'react';
2
+ export type DataCellProps = {
3
+ content: React.ReactNode;
4
+ sticky?: 'start' | 'end';
5
+ width?: number;
6
+ };
7
+ export declare function DataCell({ content, sticky, width }: DataCellProps): React.JSX.Element;
@@ -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,7 @@
1
+ import React from 'react';
2
+ export type FooterCellProps = {
3
+ content: React.ReactNode;
4
+ sticky?: 'start' | 'end';
5
+ width?: number;
6
+ };
7
+ export declare function FooterCell({ content, sticky, width }: FooterCellProps): React.JSX.Element;
@@ -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,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,6 @@
1
+ // This component never gets rendered. It is given as children to the
2
+ // table body as configuration
3
+ export function TableColumn(_props) {
4
+ return null;
5
+ }
6
+ //# sourceMappingURL=table_column.js.map
@@ -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,6 @@
1
+ import React from 'react';
2
+ import { DataSource } from '@tcn-internal/resource-store';
3
+ export type TableFooterProps<T> = {
4
+ dataSource: DataSource<T>;
5
+ };
6
+ export declare function TableFooter<T>({ dataSource }: TableFooterProps<T>): React.JSX.Element;
@@ -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"}
@@ -0,0 +1,4 @@
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';
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
+ }