@tcn/ui-transfer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI_USAGE.md +16 -0
- package/README.md +3 -0
- package/dist/components/available_list/available_list.d.ts +11 -0
- package/dist/components/available_list/available_list.d.ts.map +1 -0
- package/dist/components/available_list/available_list.js +22 -0
- package/dist/components/available_list/available_list.js.map +1 -0
- package/dist/components/available_list/index.d.ts +2 -0
- package/dist/components/available_list/index.d.ts.map +1 -0
- package/dist/components/available_list/index.js +5 -0
- package/dist/components/available_list/index.js.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +13 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/manage_list_item/addable_item.d.ts +5 -0
- package/dist/components/manage_list_item/addable_item.d.ts.map +1 -0
- package/dist/components/manage_list_item/addable_item.js +19 -0
- package/dist/components/manage_list_item/addable_item.js.map +1 -0
- package/dist/components/manage_list_item/index.d.ts +4 -0
- package/dist/components/manage_list_item/index.d.ts.map +1 -0
- package/dist/components/manage_list_item/index.js +9 -0
- package/dist/components/manage_list_item/index.js.map +1 -0
- package/dist/components/manage_list_item/manage_list_item.d.ts +11 -0
- package/dist/components/manage_list_item/manage_list_item.d.ts.map +1 -0
- package/dist/components/manage_list_item/manage_list_item.js +33 -0
- package/dist/components/manage_list_item/manage_list_item.js.map +1 -0
- package/dist/components/manage_list_item/removable_item.d.ts +5 -0
- package/dist/components/manage_list_item/removable_item.d.ts.map +1 -0
- package/dist/components/manage_list_item/removable_item.js +22 -0
- package/dist/components/manage_list_item/removable_item.js.map +1 -0
- package/dist/components/selected_list/index.d.ts +2 -0
- package/dist/components/selected_list/index.d.ts.map +1 -0
- package/dist/components/selected_list/index.js +5 -0
- package/dist/components/selected_list/index.js.map +1 -0
- package/dist/components/selected_list/selected_list.d.ts +13 -0
- package/dist/components/selected_list/selected_list.d.ts.map +1 -0
- package/dist/components/selected_list/selected_list.js +28 -0
- package/dist/components/selected_list/selected_list.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/removable_item.css +1 -0
- package/dist/transfer_list/index.d.ts +2 -0
- package/dist/transfer_list/index.d.ts.map +1 -0
- package/dist/transfer_list/index.js +5 -0
- package/dist/transfer_list/index.js.map +1 -0
- package/dist/transfer_list/transfer_list.d.ts +6 -0
- package/dist/transfer_list/transfer_list.d.ts.map +1 -0
- package/dist/transfer_list/transfer_list.js +12 -0
- package/dist/transfer_list/transfer_list.js.map +1 -0
- package/dist/transfer_table/components/available_table.d.ts +17 -0
- package/dist/transfer_table/components/available_table.d.ts.map +1 -0
- package/dist/transfer_table/components/available_table.js +68 -0
- package/dist/transfer_table/components/available_table.js.map +1 -0
- package/dist/transfer_table/components/available_table_filter_panel.d.ts +13 -0
- package/dist/transfer_table/components/available_table_filter_panel.d.ts.map +1 -0
- package/dist/transfer_table/components/available_table_filter_panel.js +39 -0
- package/dist/transfer_table/components/available_table_filter_panel.js.map +1 -0
- package/dist/transfer_table/components/available_table_header.d.ts +13 -0
- package/dist/transfer_table/components/available_table_header.d.ts.map +1 -0
- package/dist/transfer_table/components/available_table_header.js +43 -0
- package/dist/transfer_table/components/available_table_header.js.map +1 -0
- package/dist/transfer_table/components/selected_column.d.ts +15 -0
- package/dist/transfer_table/components/selected_column.d.ts.map +1 -0
- package/dist/transfer_table/components/selected_column.js +93 -0
- package/dist/transfer_table/components/selected_column.js.map +1 -0
- package/dist/transfer_table/components/selected_item.d.ts +8 -0
- package/dist/transfer_table/components/selected_item.d.ts.map +1 -0
- package/dist/transfer_table/components/selected_item.js +39 -0
- package/dist/transfer_table/components/selected_item.js.map +1 -0
- package/dist/transfer_table/index.d.ts +4 -0
- package/dist/transfer_table/index.d.ts.map +1 -0
- package/dist/transfer_table/index.js +7 -0
- package/dist/transfer_table/index.js.map +1 -0
- package/dist/transfer_table/transfer_table.d.ts +4 -0
- package/dist/transfer_table/transfer_table.d.ts.map +1 -0
- package/dist/transfer_table/transfer_table.js +82 -0
- package/dist/transfer_table/transfer_table.js.map +1 -0
- package/dist/transfer_table/transfer_table_presenter.d.ts +46 -0
- package/dist/transfer_table/transfer_table_presenter.d.ts.map +1 -0
- package/dist/transfer_table/transfer_table_presenter.js +98 -0
- package/dist/transfer_table/transfer_table_presenter.js.map +1 -0
- package/dist/transfer_table/types.d.ts +30 -0
- package/dist/transfer_table/types.d.ts.map +1 -0
- package/dist/transfer_table/types.js +2 -0
- package/dist/transfer_table/types.js.map +1 -0
- package/dist/transfer_table.css +1 -0
- package/dist/transfer_table.module-CI4PvlY3.js +5 -0
- package/dist/transfer_table.module-CI4PvlY3.js.map +1 -0
- package/package.json +81 -0
- package/src/__stories__/available_list.stories.tsx +41 -0
- package/src/__stories__/sample_data.ts +101 -0
- package/src/__stories__/selected_list.stories.tsx +41 -0
- package/src/__stories__/transfer_list.stories.tsx +13 -0
- package/src/__stories__/transfer_table.stories.tsx +128 -0
- package/src/__tests__/sanity.test.ts +7 -0
- package/src/components/available_list/available_list.tsx +39 -0
- package/src/components/available_list/index.ts +5 -0
- package/src/components/index.ts +19 -0
- package/src/components/manage_list_item/addable_item.tsx +22 -0
- package/src/components/manage_list_item/index.ts +7 -0
- package/src/components/manage_list_item/manage_list_item.tsx +43 -0
- package/src/components/manage_list_item/removable_item.module.css +3 -0
- package/src/components/manage_list_item/removable_item.tsx +25 -0
- package/src/components/selected_list/index.ts +5 -0
- package/src/components/selected_list/selected_list.tsx +50 -0
- package/src/index.ts +22 -0
- package/src/transfer_list/index.ts +1 -0
- package/src/transfer_list/transfer_list.tsx +14 -0
- package/src/transfer_table/components/available_table.tsx +80 -0
- package/src/transfer_table/components/available_table_filter_panel.tsx +62 -0
- package/src/transfer_table/components/available_table_header.tsx +60 -0
- package/src/transfer_table/components/selected_column.tsx +120 -0
- package/src/transfer_table/components/selected_item.tsx +58 -0
- package/src/transfer_table/index.ts +6 -0
- package/src/transfer_table/transfer_table.module.css +41 -0
- package/src/transfer_table/transfer_table.tsx +77 -0
- package/src/transfer_table/transfer_table_presenter.ts +164 -0
- package/src/transfer_table/types.ts +35 -0
- package/tsconfig.json +7 -0
- package/types/file_types.d.ts +106 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './transfer_table.css';const e = "_tcn-transfer-table_22a0c1f", t = "_tcn-table-available-table_449024c", a = "_selected-item_1b75356", l = "_selected-item-new_f5e0db7", c = { "tcn-transfer-table": e, "tcn-table-available-table": t, "selected-item": a, "selected-item-new": l };
|
|
2
|
+
export {
|
|
3
|
+
c as s
|
|
4
|
+
};
|
|
5
|
+
//# sourceMappingURL=transfer_table.module-CI4PvlY3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer_table.module-CI4PvlY3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tcn/ui-transfer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "React transfer list and transfer table components",
|
|
6
|
+
"author": "TCN",
|
|
7
|
+
"license": "Apache-2.0",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"access": "public",
|
|
12
|
+
"blackcatConfig": {
|
|
13
|
+
"storybook": {
|
|
14
|
+
"publish": true,
|
|
15
|
+
"title": "UI Transfer",
|
|
16
|
+
"port": 6400
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src",
|
|
22
|
+
"types",
|
|
23
|
+
"README.md",
|
|
24
|
+
"AI_USAGE.md",
|
|
25
|
+
"ai-docs",
|
|
26
|
+
"!ai-docs/*.local.md",
|
|
27
|
+
"tsconfig.json"
|
|
28
|
+
],
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"@bc-monorepo/source": "./src/index.ts",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"sideEffects": [
|
|
41
|
+
"**/*.css"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"clsx": "^2.1.1",
|
|
45
|
+
"@tcn/icons": "2.4.0",
|
|
46
|
+
"@tcn/ui-table": "4.0.0",
|
|
47
|
+
"@tcn/state": "1.3.4",
|
|
48
|
+
"@tcn/resource-store": "2.5.8"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@tcn/ui": "0.19.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"react": "^18.2.0",
|
|
55
|
+
"react-dom": "^18.2.0",
|
|
56
|
+
"@tcn/ui": "^0.19.0",
|
|
57
|
+
"@tcn/ui-table": "^4.0.0"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"start": "pnpm storybook",
|
|
61
|
+
"build": "vite build",
|
|
62
|
+
"clean": "rm -rf dist storybook-static",
|
|
63
|
+
"clean:all": "pnpm clean && rm -rf node_modules",
|
|
64
|
+
"test": "vitest run",
|
|
65
|
+
"test:coverage": "vitest run --coverage",
|
|
66
|
+
"check:all": "concurrently 'pnpm check:types' 'pnpm run biome check .'",
|
|
67
|
+
"check:types": "tsc --project tsconfig.typecheck.json --noEmit",
|
|
68
|
+
"check:format": "pnpm run biome format .",
|
|
69
|
+
"check:lint": "pnpm run biome lint .",
|
|
70
|
+
"check:imports": "pnpm run biome check --formatter-enabled=false --linter-enabled=false --assist-enabled=true",
|
|
71
|
+
"fix:all": "pnpm run biome check --write",
|
|
72
|
+
"fix:format": "pnpm run biome format --write",
|
|
73
|
+
"fix:lint": "pnpm run biome lint --write",
|
|
74
|
+
"fix:imports": "pnpm run biome check --write --unsafe --formatter-enabled=false --linter-enabled=false --assist-enabled=true",
|
|
75
|
+
"publish:dry-run": "pnpm build && pnpm publish --dry-run --force --no-git-checks",
|
|
76
|
+
"biome": "pnpm exec biome",
|
|
77
|
+
"storybook": "bash ../../scripts/ensure-blackcat-addon-built.sh && storybook dev",
|
|
78
|
+
"storybook:silent": "storybook dev --no-open --disable-telemetry --quiet",
|
|
79
|
+
"storybook:build": "storybook build"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react-vite';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { AvailableList } from '../components/index.js';
|
|
4
|
+
import { VStack } from '@tcn/ui/stacks';
|
|
5
|
+
|
|
6
|
+
const meta: Meta = {
|
|
7
|
+
title: 'Components/AvailableList',
|
|
8
|
+
};
|
|
9
|
+
export default meta;
|
|
10
|
+
|
|
11
|
+
interface Fruit {
|
|
12
|
+
id: number;
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const initialItems: Fruit[] = [
|
|
17
|
+
{ id: 1, name: 'Apple' },
|
|
18
|
+
{ id: 2, name: 'Banana' },
|
|
19
|
+
{ id: 3, name: 'Cherry' },
|
|
20
|
+
{ id: 4, name: 'Date' },
|
|
21
|
+
{ id: 5, name: 'Elderberry' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export function Default() {
|
|
25
|
+
const [items, setItems] = useState(initialItems);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<VStack hAlign="center">
|
|
29
|
+
<AvailableList
|
|
30
|
+
maxWidth={400}
|
|
31
|
+
items={items}
|
|
32
|
+
getItemKey={item => item.id}
|
|
33
|
+
renderItem={item => <span>{item.name}</span>}
|
|
34
|
+
onClickItem={item => {
|
|
35
|
+
alert(`Added: ${item.name}`);
|
|
36
|
+
setItems(prev => prev.filter(i => i.id !== item.id));
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
</VStack>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StaticDataSource,
|
|
3
|
+
StaticNumberField,
|
|
4
|
+
StaticStringField,
|
|
5
|
+
} from '@tcn/resource-store';
|
|
6
|
+
import { TableColumnProps } from '@tcn/ui-table';
|
|
7
|
+
|
|
8
|
+
export enum UserType {
|
|
9
|
+
AccountOwner = 'Account Owner',
|
|
10
|
+
Manager = 'Manager',
|
|
11
|
+
Agent = 'Agent',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ExampleItem {
|
|
15
|
+
name: string;
|
|
16
|
+
userType: UserType;
|
|
17
|
+
permissionGroup: string;
|
|
18
|
+
huntGroup: number;
|
|
19
|
+
profileGroup: string;
|
|
20
|
+
skills: string;
|
|
21
|
+
labels: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const mockData: ExampleItem[] = [
|
|
25
|
+
{
|
|
26
|
+
name: 'John Doe',
|
|
27
|
+
userType: UserType.AccountOwner,
|
|
28
|
+
permissionGroup: 'Permission Group 1',
|
|
29
|
+
huntGroup: 1,
|
|
30
|
+
profileGroup: 'Profile Group 1',
|
|
31
|
+
skills: 'Skill 1, Skill 2, Skill 3',
|
|
32
|
+
labels: 'Label 1, Label 2, Label 3',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Jane Smith',
|
|
36
|
+
userType: UserType.Manager,
|
|
37
|
+
permissionGroup: 'Permission Group 2',
|
|
38
|
+
huntGroup: 2,
|
|
39
|
+
profileGroup: 'Profile Group 2',
|
|
40
|
+
skills: 'Skill 4, Skill 5, Skill 6',
|
|
41
|
+
labels: 'Label 4, Label 5, Label 6',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Jim Beam',
|
|
45
|
+
userType: UserType.Agent,
|
|
46
|
+
permissionGroup: 'Permission Group 3',
|
|
47
|
+
huntGroup: 3,
|
|
48
|
+
profileGroup: 'Profile Group 3',
|
|
49
|
+
skills: 'Skill 7, Skill 8, Skill 9',
|
|
50
|
+
labels: 'Label 7, Label 8, Label 9',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Jane Doe',
|
|
54
|
+
userType: UserType.AccountOwner,
|
|
55
|
+
permissionGroup: 'Permission Group 1',
|
|
56
|
+
huntGroup: 1,
|
|
57
|
+
profileGroup: 'Profile Group 1',
|
|
58
|
+
skills: 'Skill 1, Skill 2, Skill 3',
|
|
59
|
+
labels: 'Label 1, Label 2, Label 3',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'Bob Johnson',
|
|
63
|
+
userType: UserType.Manager,
|
|
64
|
+
permissionGroup: 'Permission Group 2',
|
|
65
|
+
huntGroup: 4,
|
|
66
|
+
profileGroup: 'Profile Group 2',
|
|
67
|
+
skills: 'Skill 10, Skill 11',
|
|
68
|
+
labels: 'Label 10',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Alice Williams',
|
|
72
|
+
userType: UserType.Agent,
|
|
73
|
+
permissionGroup: 'Permission Group 3',
|
|
74
|
+
huntGroup: 5,
|
|
75
|
+
profileGroup: 'Profile Group 3',
|
|
76
|
+
skills: 'Skill 12, Skill 13, Skill 14',
|
|
77
|
+
labels: 'Label 11, Label 12',
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export function createMockDataSource(items: ExampleItem[]) {
|
|
82
|
+
return new StaticDataSource<ExampleItem>(items, [
|
|
83
|
+
new StaticStringField('name', i => i.name),
|
|
84
|
+
new StaticStringField('userType', i => i.userType),
|
|
85
|
+
new StaticStringField('permissionGroup', i => i.permissionGroup),
|
|
86
|
+
new StaticNumberField('huntGroup', i => i.huntGroup),
|
|
87
|
+
new StaticStringField('profileGroup', i => i.profileGroup),
|
|
88
|
+
new StaticStringField('skills', i => i.skills),
|
|
89
|
+
new StaticStringField('labels', i => i.labels),
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const mockDataColumns: TableColumnProps<ExampleItem>[] = [
|
|
94
|
+
{ heading: 'Name', fieldName: 'name', canSort: true },
|
|
95
|
+
{ heading: 'User Type', fieldName: 'userType', canSort: true },
|
|
96
|
+
{ heading: 'Permission Group', fieldName: 'permissionGroup', canSort: true },
|
|
97
|
+
{ heading: 'Hunt Group', fieldName: 'huntGroup', canSort: true },
|
|
98
|
+
{ heading: 'Profile Group', fieldName: 'profileGroup', canSort: true },
|
|
99
|
+
{ heading: 'Skills', fieldName: 'skills', canSort: true },
|
|
100
|
+
{ heading: 'Labels', fieldName: 'labels', canSort: true },
|
|
101
|
+
];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react-vite';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { SelectedList } from '../components/index.js';
|
|
4
|
+
import { VStack } from '@tcn/ui/stacks';
|
|
5
|
+
|
|
6
|
+
const meta: Meta = {
|
|
7
|
+
title: 'Components/SelectedList',
|
|
8
|
+
};
|
|
9
|
+
export default meta;
|
|
10
|
+
|
|
11
|
+
interface Fruit {
|
|
12
|
+
id: number;
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const initialItems: Fruit[] = [
|
|
17
|
+
{ id: 1, name: 'Apple' },
|
|
18
|
+
{ id: 2, name: 'Banana' },
|
|
19
|
+
{ id: 3, name: 'Cherry' },
|
|
20
|
+
{ id: 4, name: 'Date' },
|
|
21
|
+
{ id: 5, name: 'Elderberry' },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export function Default() {
|
|
25
|
+
const [items, setItems] = useState(initialItems);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<VStack hAlign="center">
|
|
29
|
+
<SelectedList
|
|
30
|
+
maxWidth={400}
|
|
31
|
+
items={items}
|
|
32
|
+
getItemKey={item => item.id}
|
|
33
|
+
renderItem={item => <span>{item.name}</span>}
|
|
34
|
+
onClickItem={item => {
|
|
35
|
+
alert(`Removed: ${item.name}`);
|
|
36
|
+
setItems(prev => prev.filter(i => i.id !== item.id));
|
|
37
|
+
}}
|
|
38
|
+
/>
|
|
39
|
+
</VStack>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TransferList } from '../transfer_list/index.js';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof TransferList> = {
|
|
6
|
+
title: 'Components/TransferList',
|
|
7
|
+
component: TransferList,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof TransferList>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react-vite';
|
|
2
|
+
import { ChevronLeftIcon } from '@tcn/icons/chevron_left_icon.js';
|
|
3
|
+
import { StringFieldFilter } from '@tcn/ui-table';
|
|
4
|
+
import { Button } from '@tcn/ui/actions';
|
|
5
|
+
import { Header, Scaffold } from '@tcn/ui/layouts';
|
|
6
|
+
import { ZStack } from '@tcn/ui/stacks';
|
|
7
|
+
import { Panel } from '@tcn/ui/surfaces';
|
|
8
|
+
import { Title } from '@tcn/ui/typography';
|
|
9
|
+
import React, { useState } from 'react';
|
|
10
|
+
import { TransferTable } from '../transfer_table/transfer_table.js';
|
|
11
|
+
import { TransferTablePresenter } from '../transfer_table/transfer_table_presenter.js';
|
|
12
|
+
import {
|
|
13
|
+
type ExampleItem,
|
|
14
|
+
createMockDataSource,
|
|
15
|
+
mockData,
|
|
16
|
+
mockDataColumns,
|
|
17
|
+
} from './sample_data.js';
|
|
18
|
+
|
|
19
|
+
const meta: Meta = {
|
|
20
|
+
title: 'Components/TransferTable',
|
|
21
|
+
};
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
const StoryWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
25
|
+
return (
|
|
26
|
+
<ZStack maxHeight="800px" padding="24px">
|
|
27
|
+
{children}
|
|
28
|
+
</ZStack>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function Default() {
|
|
33
|
+
const [presenter] = useState(
|
|
34
|
+
() =>
|
|
35
|
+
new TransferTablePresenter<ExampleItem>({
|
|
36
|
+
dataSource: createMockDataSource(mockData),
|
|
37
|
+
columns: mockDataColumns,
|
|
38
|
+
getItemKey: item => item.name,
|
|
39
|
+
selectedItemRender: item => <div>{item.name}</div>,
|
|
40
|
+
onClickCancel: () => alert('Cancel'),
|
|
41
|
+
onClickAdd: items => alert(`Add ${items.length} item(s)`),
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<StoryWrapper>
|
|
47
|
+
<TransferTable {...presenter.getProps()} />
|
|
48
|
+
</StoryWrapper>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function WithFilterPanel() {
|
|
53
|
+
const [presenter] = useState(
|
|
54
|
+
() =>
|
|
55
|
+
new TransferTablePresenter<ExampleItem>({
|
|
56
|
+
dataSource: createMockDataSource(mockData),
|
|
57
|
+
columns: mockDataColumns,
|
|
58
|
+
getItemKey: item => item.name,
|
|
59
|
+
selectedItemRender: item => <div>{item.name}</div>,
|
|
60
|
+
filterChildren: [
|
|
61
|
+
<StringFieldFilter key="name" fieldName="name" label="Name" />,
|
|
62
|
+
<StringFieldFilter key="skills" fieldName="skills" label="Skills" />,
|
|
63
|
+
],
|
|
64
|
+
onClickCancel: () => alert('Cancel'),
|
|
65
|
+
onClickAdd: items => alert(`Add ${items.length} item(s)`),
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<StoryWrapper>
|
|
71
|
+
<TransferTable {...presenter.getProps()} />
|
|
72
|
+
</StoryWrapper>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function InPanel() {
|
|
77
|
+
const [presenter] = useState(
|
|
78
|
+
() =>
|
|
79
|
+
new TransferTablePresenter<ExampleItem>({
|
|
80
|
+
dataSource: createMockDataSource(mockData),
|
|
81
|
+
columns: mockDataColumns,
|
|
82
|
+
getItemKey: item => item.name,
|
|
83
|
+
selectedItemRender: item => <div>{item.name}</div>,
|
|
84
|
+
filterChildren: [
|
|
85
|
+
<StringFieldFilter key="name" fieldName="name" label="Name" />,
|
|
86
|
+
<StringFieldFilter key="skills" fieldName="skills" label="Skills" />,
|
|
87
|
+
],
|
|
88
|
+
onClickCancel: () => alert('Cancel'),
|
|
89
|
+
onClickAdd: items => alert(`Add ${items.length} item(s)`),
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<StoryWrapper>
|
|
95
|
+
<Panel>
|
|
96
|
+
<Header>
|
|
97
|
+
<Button utility hierarchy="tertiary" onClick={() => alert('Back')}>
|
|
98
|
+
<ChevronLeftIcon />
|
|
99
|
+
</Button>
|
|
100
|
+
<Title>Entity Settings</Title>
|
|
101
|
+
</Header>
|
|
102
|
+
<Scaffold>
|
|
103
|
+
<TransferTable {...presenter.getProps()} />
|
|
104
|
+
</Scaffold>
|
|
105
|
+
</Panel>
|
|
106
|
+
</StoryWrapper>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function Empty() {
|
|
111
|
+
const [presenter] = useState(
|
|
112
|
+
() =>
|
|
113
|
+
new TransferTablePresenter<ExampleItem>({
|
|
114
|
+
dataSource: createMockDataSource([]),
|
|
115
|
+
columns: mockDataColumns,
|
|
116
|
+
getItemKey: item => item.name,
|
|
117
|
+
selectedItemRender: item => <div>{item.name}</div>,
|
|
118
|
+
onClickCancel: () => alert('Cancel'),
|
|
119
|
+
onClickAdd: items => alert(`Add ${items.length} item(s)`),
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<StoryWrapper>
|
|
125
|
+
<TransferTable {...presenter.getProps()} />
|
|
126
|
+
</StoryWrapper>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { List, type ListProps } from '@tcn/ui/layouts';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { AddableItem } from '../manage_list_item/index.js';
|
|
5
|
+
|
|
6
|
+
export interface AvailableListOwnProps<T> {
|
|
7
|
+
items: T[];
|
|
8
|
+
getItemKey: (item: T) => string | number;
|
|
9
|
+
renderItem: (item: T) => React.ReactNode;
|
|
10
|
+
onClickItem: (item: T) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type AvailableListProps<T> = AvailableListOwnProps<T> & ListProps;
|
|
14
|
+
|
|
15
|
+
function AvailableListInner<T>(
|
|
16
|
+
{
|
|
17
|
+
items,
|
|
18
|
+
getItemKey,
|
|
19
|
+
renderItem,
|
|
20
|
+
onClickItem,
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: AvailableListProps<T>,
|
|
24
|
+
ref: React.ForwardedRef<HTMLDivElement>
|
|
25
|
+
) {
|
|
26
|
+
return (
|
|
27
|
+
<List ref={ref} className={clsx('tcn-available-list', className)} {...props}>
|
|
28
|
+
{items.map(item => (
|
|
29
|
+
<AddableItem key={getItemKey(item)} item={item} onClickItem={onClickItem}>
|
|
30
|
+
{renderItem(item)}
|
|
31
|
+
</AddableItem>
|
|
32
|
+
))}
|
|
33
|
+
</List>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const AvailableList = React.forwardRef(AvailableListInner) as <T>(
|
|
38
|
+
props: AvailableListProps<T> & React.RefAttributes<HTMLDivElement>
|
|
39
|
+
) => React.ReactElement | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ManageListItem,
|
|
3
|
+
type ManageListItemOwnProps,
|
|
4
|
+
type ManageListItemProps,
|
|
5
|
+
RemovableItem,
|
|
6
|
+
type RemovableItemProps,
|
|
7
|
+
AddableItem,
|
|
8
|
+
type AddableItemProps,
|
|
9
|
+
} from './manage_list_item/index.js';
|
|
10
|
+
export {
|
|
11
|
+
SelectedList,
|
|
12
|
+
type SelectedListOwnProps,
|
|
13
|
+
type SelectedListProps,
|
|
14
|
+
} from './selected_list/index.js';
|
|
15
|
+
export {
|
|
16
|
+
AvailableList,
|
|
17
|
+
type AvailableListOwnProps,
|
|
18
|
+
type AvailableListProps,
|
|
19
|
+
} from './available_list/index.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ArrowRightIcon } from '@tcn/icons/arrow_right_icon.js';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ManageListItem, type ManageListItemProps } from './manage_list_item.js';
|
|
4
|
+
|
|
5
|
+
export type AddableItemProps<T> = ManageListItemProps<T>;
|
|
6
|
+
|
|
7
|
+
function AddableItemInner<T>(
|
|
8
|
+
{ endAdornment, ...props }: AddableItemProps<T>,
|
|
9
|
+
ref: React.ForwardedRef<HTMLDivElement>
|
|
10
|
+
) {
|
|
11
|
+
return (
|
|
12
|
+
<ManageListItem
|
|
13
|
+
ref={ref}
|
|
14
|
+
endAdornment={endAdornment ?? <ArrowRightIcon />}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const AddableItem = React.forwardRef(AddableItemInner) as <T>(
|
|
21
|
+
props: AddableItemProps<T> & React.RefAttributes<HTMLDivElement>
|
|
22
|
+
) => React.ReactElement | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ManageListItem,
|
|
3
|
+
type ManageListItemOwnProps,
|
|
4
|
+
type ManageListItemProps,
|
|
5
|
+
} from './manage_list_item.js';
|
|
6
|
+
export { RemovableItem, type RemovableItemProps } from './removable_item.js';
|
|
7
|
+
export { AddableItem, type AddableItemProps } from './addable_item.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Item, type ItemProps } from '@tcn/ui/layouts';
|
|
2
|
+
import { Spacer } from '@tcn/ui/stacks';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
export interface ManageListItemOwnProps<T> {
|
|
7
|
+
item: T;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
onClickItem: (item: T) => void;
|
|
10
|
+
endAdornment?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ManageListItemProps<T> = ManageListItemOwnProps<T> &
|
|
14
|
+
Omit<ItemProps, 'children'>;
|
|
15
|
+
|
|
16
|
+
function ManageListItemInner<T>(
|
|
17
|
+
{
|
|
18
|
+
item,
|
|
19
|
+
children,
|
|
20
|
+
onClickItem,
|
|
21
|
+
endAdornment,
|
|
22
|
+
className,
|
|
23
|
+
...props
|
|
24
|
+
}: ManageListItemProps<T>,
|
|
25
|
+
ref: React.ForwardedRef<HTMLDivElement>
|
|
26
|
+
) {
|
|
27
|
+
return (
|
|
28
|
+
<Item
|
|
29
|
+
ref={ref}
|
|
30
|
+
className={clsx('tcn-manage-list-item', className)}
|
|
31
|
+
onClick={() => onClickItem(item)}
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
<Spacer />
|
|
36
|
+
{endAdornment}
|
|
37
|
+
</Item>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const ManageListItem = React.forwardRef(ManageListItemInner) as <T>(
|
|
42
|
+
props: ManageListItemProps<T> & React.RefAttributes<HTMLDivElement>
|
|
43
|
+
) => React.ReactElement | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CrossCircleIcon } from '@tcn/icons/cross_circle_icon.js';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { ManageListItem, type ManageListItemProps } from './manage_list_item.js';
|
|
5
|
+
import styles from './removable_item.module.css';
|
|
6
|
+
|
|
7
|
+
export type RemovableItemProps<T> = ManageListItemProps<T>;
|
|
8
|
+
|
|
9
|
+
function RemovableItemInner<T>(
|
|
10
|
+
{ endAdornment, className, ...props }: RemovableItemProps<T>,
|
|
11
|
+
ref: React.ForwardedRef<HTMLDivElement>
|
|
12
|
+
) {
|
|
13
|
+
return (
|
|
14
|
+
<ManageListItem
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={clsx(styles['removable-item'], className)}
|
|
17
|
+
endAdornment={endAdornment ?? <CrossCircleIcon />}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const RemovableItem = React.forwardRef(RemovableItemInner) as <T>(
|
|
24
|
+
props: RemovableItemProps<T> & React.RefAttributes<HTMLDivElement>
|
|
25
|
+
) => React.ReactElement | null;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { List, type ListProps } from '@tcn/ui/layouts';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { RemovableItem } from '../manage_list_item/index.js';
|
|
5
|
+
|
|
6
|
+
export interface SelectedListOwnProps<T> {
|
|
7
|
+
items: T[];
|
|
8
|
+
getItemKey: (item: T) => string | number;
|
|
9
|
+
renderItem: (item: T) => React.ReactNode;
|
|
10
|
+
onClickItem: (item: T) => void;
|
|
11
|
+
/** Override the default RemovableItem rendering per item. Receives the item and its rendered content. */
|
|
12
|
+
renderListItem?: (item: T, content: React.ReactNode) => React.ReactElement;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type SelectedListProps<T> = SelectedListOwnProps<T> & ListProps;
|
|
16
|
+
|
|
17
|
+
function SelectedListInner<T>(
|
|
18
|
+
{
|
|
19
|
+
items,
|
|
20
|
+
getItemKey,
|
|
21
|
+
renderItem,
|
|
22
|
+
onClickItem,
|
|
23
|
+
renderListItem,
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: SelectedListProps<T>,
|
|
27
|
+
ref: React.ForwardedRef<HTMLDivElement>
|
|
28
|
+
) {
|
|
29
|
+
return (
|
|
30
|
+
<List ref={ref} className={clsx('tcn-selected-list', className)} {...props}>
|
|
31
|
+
{items.map(item => {
|
|
32
|
+
const content = renderItem(item);
|
|
33
|
+
if (renderListItem) {
|
|
34
|
+
return React.cloneElement(renderListItem(item, content), {
|
|
35
|
+
key: getItemKey(item),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return (
|
|
39
|
+
<RemovableItem key={getItemKey(item)} item={item} onClickItem={onClickItem}>
|
|
40
|
+
{content}
|
|
41
|
+
</RemovableItem>
|
|
42
|
+
);
|
|
43
|
+
})}
|
|
44
|
+
</List>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const SelectedList = React.forwardRef(SelectedListInner) as <T>(
|
|
49
|
+
props: SelectedListProps<T> & React.RefAttributes<HTMLDivElement>
|
|
50
|
+
) => React.ReactElement | null;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ManageListItem,
|
|
3
|
+
type ManageListItemOwnProps,
|
|
4
|
+
type ManageListItemProps,
|
|
5
|
+
RemovableItem,
|
|
6
|
+
type RemovableItemProps,
|
|
7
|
+
AddableItem,
|
|
8
|
+
type AddableItemProps,
|
|
9
|
+
SelectedList,
|
|
10
|
+
type SelectedListOwnProps,
|
|
11
|
+
type SelectedListProps,
|
|
12
|
+
AvailableList,
|
|
13
|
+
type AvailableListOwnProps,
|
|
14
|
+
type AvailableListProps,
|
|
15
|
+
} from './components/index.js';
|
|
16
|
+
export { TransferList, type TransferListProps } from './transfer_list/index.js';
|
|
17
|
+
export {
|
|
18
|
+
TransferTable,
|
|
19
|
+
TransferTablePresenter,
|
|
20
|
+
type SelectedItemsUpdate,
|
|
21
|
+
type TransferTableProps,
|
|
22
|
+
} from './transfer_table/index.js';
|