@tsed/react-formio 3.0.0-alpha.10 → 3.0.0-alpha.11
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/dist/hooks/keyboard.constants.d.ts +38 -0
- package/dist/hooks/keyboard.constants.js +7 -0
- package/dist/hooks/keyboard.constants.js.map +1 -0
- package/dist/hooks/useKeyboardControls.d.ts +12 -0
- package/dist/hooks/useKeyboardControls.js +35 -0
- package/dist/hooks/useKeyboardControls.js.map +1 -0
- package/dist/interfaces/Operation.d.ts +12 -2
- package/dist/molecules/button/Button.d.ts +18 -5
- package/dist/molecules/button/Button.js +29 -30
- package/dist/molecules/button/Button.js.map +1 -1
- package/dist/molecules/card/Card.js +7 -5
- package/dist/molecules/card/Card.js.map +1 -1
- package/dist/molecules/forms/input-tags/InputTags.js +14 -14
- package/dist/molecules/forms/input-tags/InputTags.js.map +1 -1
- package/dist/molecules/table/Table.d.ts +11 -3
- package/dist/molecules/table/Table.js +8 -3
- package/dist/molecules/table/Table.js.map +1 -1
- package/dist/molecules/table/components/DefaultCellOperations.d.ts +12 -4
- package/dist/molecules/table/components/DefaultCellOperations.js +12 -6
- package/dist/molecules/table/components/DefaultCellOperations.js.map +1 -1
- package/dist/molecules/table/components/DefaultOperationButton.d.ts +12 -4
- package/dist/molecules/table/components/DefaultOperationButton.js.map +1 -1
- package/dist/molecules/table/hooks/useTable.d.ts +12 -4
- package/dist/molecules/table/hooks/useTable.js.map +1 -1
- package/dist/molecules/tabs/Tab.d.ts +13 -0
- package/dist/molecules/tabs/Tab.js +67 -0
- package/dist/molecules/tabs/Tab.js.map +1 -0
- package/dist/molecules/tabs/TabList.d.ts +2 -0
- package/dist/molecules/tabs/TabList.js +24 -0
- package/dist/molecules/tabs/TabList.js.map +1 -0
- package/dist/molecules/tabs/TabPanel.d.ts +9 -0
- package/dist/molecules/tabs/TabPanel.js +27 -0
- package/dist/molecules/tabs/TabPanel.js.map +1 -0
- package/dist/molecules/tabs/Tabs.d.ts +4 -16
- package/dist/molecules/tabs/Tabs.js +7 -67
- package/dist/molecules/tabs/Tabs.js.map +1 -1
- package/dist/molecules/tabs/TabsBody.d.ts +1 -0
- package/dist/molecules/tabs/TabsBody.js +10 -0
- package/dist/molecules/tabs/TabsBody.js.map +1 -0
- package/dist/molecules/tabs/TabsLegacy.d.ts +17 -0
- package/dist/molecules/tabs/TabsLegacy.js +49 -0
- package/dist/molecules/tabs/TabsLegacy.js.map +1 -0
- package/dist/molecules/tabs/all.d.ts +5 -0
- package/dist/molecules/tabs/all.js +13 -0
- package/dist/molecules/tabs/all.js.map +1 -0
- package/dist/molecules/tabs/context/TabControl.d.ts +52 -0
- package/dist/molecules/tabs/context/TabControl.js +85 -0
- package/dist/molecules/tabs/context/TabControl.js.map +1 -0
- package/dist/molecules/tabs/hooks/tabControl.d.ts +44 -0
- package/dist/molecules/tabs/hooks/tabControl.js +34 -0
- package/dist/molecules/tabs/hooks/tabControl.js.map +1 -0
- package/dist/organisms/form/actions/FormAction.js.map +1 -0
- package/dist/organisms/form/builder/FormEdit.d.ts +3 -1
- package/dist/organisms/form/builder/FormEdit.js +38 -35
- package/dist/organisms/form/builder/FormEdit.js.map +1 -1
- package/dist/organisms/form/builder/useFormEdit.js +17 -17
- package/dist/organisms/form/builder/useFormEdit.js.map +1 -1
- package/dist/organisms/form/exports/FormExport.d.ts +5 -0
- package/dist/organisms/form/exports/FormExport.js +55 -0
- package/dist/organisms/form/exports/FormExport.js.map +1 -0
- package/dist/organisms/form/preview/FormPreview.d.ts +6 -0
- package/dist/organisms/form/preview/FormPreview.js +11 -0
- package/dist/organisms/form/preview/FormPreview.js.map +1 -0
- package/dist/organisms/table/submissions/SubmissionsTable.d.ts +11 -3
- package/dist/organisms/table/submissions/SubmissionsTable.js +4 -1
- package/dist/organisms/table/submissions/SubmissionsTable.js.map +1 -1
- package/dist/organisms/views/FormViews.d.ts +24 -0
- package/dist/organisms/views/FormViews.js +96 -0
- package/dist/organisms/views/FormViews.js.map +1 -0
- package/package.json +3 -3
- package/src/hooks/keyboard.constants.ts +40 -0
- package/src/hooks/useKeyboardControls.spec.tsx +208 -0
- package/src/hooks/useKeyboardControls.ts +84 -0
- package/src/interfaces/Operation.ts +9 -3
- package/src/molecules/button/Button.tsx +43 -24
- package/src/molecules/card/Card.tsx +4 -0
- package/src/molecules/forms/input-tags/InputTags.tsx +1 -1
- package/src/molecules/pagination/Pagination.stories.tsx +0 -7
- package/src/molecules/table/Table.stories.tsx +34 -1
- package/src/molecules/table/Table.tsx +12 -6
- package/src/molecules/table/components/DefaultCellOperations.tsx +13 -7
- package/src/molecules/table/components/DefaultOperationButton.tsx +5 -4
- package/src/molecules/table/hooks/useTable.tsx +5 -5
- package/src/molecules/tabs/Tab.tsx +106 -0
- package/src/molecules/tabs/TabList.tsx +37 -0
- package/src/molecules/tabs/TabPanel.tsx +37 -0
- package/src/molecules/tabs/Tabs.spec.tsx +126 -73
- package/src/molecules/tabs/Tabs.stories.tsx +298 -65
- package/src/molecules/tabs/Tabs.tsx +10 -81
- package/src/molecules/tabs/TabsBody.tsx +11 -0
- package/src/molecules/tabs/TabsLegacy.stories.tsx +103 -0
- package/src/molecules/tabs/TabsLegacy.tsx +84 -0
- package/src/molecules/tabs/all.ts +5 -0
- package/src/molecules/tabs/context/TabControl.tsx +166 -0
- package/src/molecules/tabs/hooks/tabControl.spec.tsx +388 -0
- package/src/molecules/tabs/hooks/tabControl.ts +52 -0
- package/src/organisms/__fixtures__/form-firstname.fixture.json +1 -0
- package/src/organisms/__fixtures__/form.fixture.json +1 -0
- package/src/organisms/form/actions/FormAction.stories.tsx +422 -0
- package/src/organisms/form/builder/FormEdit.tsx +7 -1
- package/src/organisms/form/builder/useFormEdit.ts +1 -1
- package/src/organisms/form/exports/FormExport.stories.tsx +71 -0
- package/src/organisms/form/exports/FormExport.tsx +58 -0
- package/src/organisms/form/preview/FormPreview.stories.tsx +61 -0
- package/src/organisms/form/preview/FormPreview.tsx +21 -0
- package/src/organisms/table/actions/ActionsTable.stories.tsx +36 -34
- package/src/organisms/table/submissions/SubmissionsTable.stories.tsx +103 -57
- package/src/organisms/table/submissions/SubmissionsTable.tsx +10 -4
- package/src/organisms/views/FormViews.stories.tsx +224 -0
- package/src/organisms/views/FormViews.tsx +146 -0
- package/dist/organisms/form/action/FormAction.js.map +0 -1
- package/src/organisms/form/action/FormAction.stories.tsx +0 -364
- /package/dist/organisms/form/{action → actions}/FormAction.d.ts +0 -0
- /package/dist/organisms/form/{action → actions}/FormAction.js +0 -0
- /package/src/organisms/form/{action → actions}/FormAction.tsx +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { userEvent } from "@testing-library/user-event";
|
|
3
|
+
|
|
4
|
+
import { useKeyboardControls } from "./useKeyboardControls";
|
|
5
|
+
|
|
6
|
+
describe("useKeyboardControls()", () => {
|
|
7
|
+
const activate = vi.fn();
|
|
8
|
+
const start = vi.fn();
|
|
9
|
+
const end = vi.fn();
|
|
10
|
+
const up = vi.fn();
|
|
11
|
+
const down = vi.fn();
|
|
12
|
+
const left = vi.fn();
|
|
13
|
+
const right = vi.fn();
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
const Test = () => {
|
|
19
|
+
const handle = useKeyboardControls({ activate, start, end, up, down, left, right });
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div tabIndex={0} role='button' onKeyDown={handle}>
|
|
23
|
+
Test
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe("on Enter", () => {
|
|
29
|
+
it('call the "activate" callback', async () => {
|
|
30
|
+
render(<Test />);
|
|
31
|
+
|
|
32
|
+
const button = screen.getByRole("button");
|
|
33
|
+
button.focus();
|
|
34
|
+
|
|
35
|
+
await userEvent.keyboard("[Enter]{Enter}");
|
|
36
|
+
|
|
37
|
+
expect(activate).toHaveBeenCalledTimes(2);
|
|
38
|
+
expect(start).not.toHaveBeenCalled();
|
|
39
|
+
expect(end).not.toHaveBeenCalled();
|
|
40
|
+
expect(up).not.toHaveBeenCalled();
|
|
41
|
+
expect(down).not.toHaveBeenCalled();
|
|
42
|
+
expect(left).not.toHaveBeenCalled();
|
|
43
|
+
expect(right).not.toHaveBeenCalled();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("on Spacebar", () => {
|
|
48
|
+
it('call the "activate" callback', async () => {
|
|
49
|
+
render(<Test />);
|
|
50
|
+
|
|
51
|
+
const button = screen.getByRole("button");
|
|
52
|
+
button.focus();
|
|
53
|
+
|
|
54
|
+
await userEvent.keyboard("[Space]{ }{Spacebar}");
|
|
55
|
+
|
|
56
|
+
expect(activate).toHaveBeenCalledTimes(3);
|
|
57
|
+
expect(start).not.toHaveBeenCalled();
|
|
58
|
+
expect(end).not.toHaveBeenCalled();
|
|
59
|
+
expect(up).not.toHaveBeenCalled();
|
|
60
|
+
expect(down).not.toHaveBeenCalled();
|
|
61
|
+
expect(left).not.toHaveBeenCalled();
|
|
62
|
+
expect(right).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("on Home", () => {
|
|
67
|
+
it('call the "start" callback', async () => {
|
|
68
|
+
render(<Test />);
|
|
69
|
+
|
|
70
|
+
const button = screen.getByRole("button");
|
|
71
|
+
button.focus();
|
|
72
|
+
|
|
73
|
+
await userEvent.keyboard("[Home]");
|
|
74
|
+
|
|
75
|
+
expect(activate).not.toHaveBeenCalled();
|
|
76
|
+
expect(start).toHaveBeenCalledTimes(1);
|
|
77
|
+
expect(end).not.toHaveBeenCalled();
|
|
78
|
+
expect(up).not.toHaveBeenCalled();
|
|
79
|
+
expect(down).not.toHaveBeenCalled();
|
|
80
|
+
expect(left).not.toHaveBeenCalled();
|
|
81
|
+
expect(right).not.toHaveBeenCalled();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("on End", () => {
|
|
86
|
+
it('call the "end" callback', async () => {
|
|
87
|
+
render(<Test />);
|
|
88
|
+
|
|
89
|
+
const button = screen.getByRole("button");
|
|
90
|
+
button.focus();
|
|
91
|
+
|
|
92
|
+
await userEvent.keyboard("[End]");
|
|
93
|
+
|
|
94
|
+
expect(activate).not.toHaveBeenCalled();
|
|
95
|
+
expect(start).not.toHaveBeenCalled();
|
|
96
|
+
expect(end).toHaveBeenCalledTimes(1);
|
|
97
|
+
expect(up).not.toHaveBeenCalled();
|
|
98
|
+
expect(down).not.toHaveBeenCalled();
|
|
99
|
+
expect(left).not.toHaveBeenCalled();
|
|
100
|
+
expect(right).not.toHaveBeenCalled();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe("on Arrow Up", () => {
|
|
105
|
+
it('call the "up" callback', async () => {
|
|
106
|
+
render(<Test />);
|
|
107
|
+
|
|
108
|
+
const button = screen.getByRole("button");
|
|
109
|
+
button.focus();
|
|
110
|
+
|
|
111
|
+
await userEvent.keyboard("[ArrowUp]");
|
|
112
|
+
|
|
113
|
+
expect(activate).not.toHaveBeenCalled();
|
|
114
|
+
expect(start).not.toHaveBeenCalled();
|
|
115
|
+
expect(end).not.toHaveBeenCalled();
|
|
116
|
+
expect(up).toHaveBeenCalledTimes(1);
|
|
117
|
+
expect(down).not.toHaveBeenCalled();
|
|
118
|
+
expect(left).not.toHaveBeenCalled();
|
|
119
|
+
expect(right).not.toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("on Arrow Down", () => {
|
|
124
|
+
it('call the "down" callback', async () => {
|
|
125
|
+
render(<Test />);
|
|
126
|
+
|
|
127
|
+
const button = screen.getByRole("button");
|
|
128
|
+
button.focus();
|
|
129
|
+
|
|
130
|
+
await userEvent.keyboard("[ArrowDown]");
|
|
131
|
+
|
|
132
|
+
expect(activate).not.toHaveBeenCalled();
|
|
133
|
+
expect(start).not.toHaveBeenCalled();
|
|
134
|
+
expect(end).not.toHaveBeenCalled();
|
|
135
|
+
expect(up).not.toHaveBeenCalled();
|
|
136
|
+
expect(down).toHaveBeenCalledTimes(1);
|
|
137
|
+
expect(left).not.toHaveBeenCalled();
|
|
138
|
+
expect(right).not.toHaveBeenCalled();
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("on Arrow Left", () => {
|
|
143
|
+
it('call the "left" callback', async () => {
|
|
144
|
+
render(<Test />);
|
|
145
|
+
|
|
146
|
+
const button = screen.getByRole("button");
|
|
147
|
+
button.focus();
|
|
148
|
+
|
|
149
|
+
await userEvent.keyboard("[ArrowLeft]");
|
|
150
|
+
|
|
151
|
+
expect(activate).not.toHaveBeenCalled();
|
|
152
|
+
expect(start).not.toHaveBeenCalled();
|
|
153
|
+
expect(end).not.toHaveBeenCalled();
|
|
154
|
+
expect(up).not.toHaveBeenCalled();
|
|
155
|
+
expect(down).not.toHaveBeenCalled();
|
|
156
|
+
expect(left).toHaveBeenCalledTimes(1);
|
|
157
|
+
expect(right).not.toHaveBeenCalled();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("on Arrow Right", () => {
|
|
162
|
+
it('call the "right" callback', async () => {
|
|
163
|
+
render(<Test />);
|
|
164
|
+
|
|
165
|
+
const button = screen.getByRole("button");
|
|
166
|
+
button.focus();
|
|
167
|
+
|
|
168
|
+
await userEvent.keyboard("[ArrowRight]");
|
|
169
|
+
|
|
170
|
+
expect(activate).not.toHaveBeenCalled();
|
|
171
|
+
expect(start).not.toHaveBeenCalled();
|
|
172
|
+
expect(end).not.toHaveBeenCalled();
|
|
173
|
+
expect(up).not.toHaveBeenCalled();
|
|
174
|
+
expect(down).not.toHaveBeenCalled();
|
|
175
|
+
expect(left).not.toHaveBeenCalled();
|
|
176
|
+
expect(right).toHaveBeenCalledTimes(1);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe("without any callback", () => {
|
|
181
|
+
it("does nothing", async () => {
|
|
182
|
+
const Test = () => {
|
|
183
|
+
const handle = useKeyboardControls({ activate });
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<div tabIndex={0} role='button' onKeyDown={handle}>
|
|
187
|
+
Test
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
render(<Test />);
|
|
193
|
+
|
|
194
|
+
const button = screen.getByRole("button");
|
|
195
|
+
button.focus();
|
|
196
|
+
|
|
197
|
+
await userEvent.keyboard("[ArrowUp][ArrowUp][ArrowDown][ArrowDown][ArrowLeft][ArrowRight][ArrowLeft][ArrowRight]{b}{a}[Enter]");
|
|
198
|
+
|
|
199
|
+
expect(activate).toHaveBeenCalledTimes(1);
|
|
200
|
+
expect(start).not.toHaveBeenCalled();
|
|
201
|
+
expect(end).not.toHaveBeenCalled();
|
|
202
|
+
expect(up).not.toHaveBeenCalled();
|
|
203
|
+
expect(down).not.toHaveBeenCalled();
|
|
204
|
+
expect(left).not.toHaveBeenCalled();
|
|
205
|
+
expect(right).not.toHaveBeenCalledTimes(1);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type KeyboardEvent, useCallback } from "react";
|
|
4
|
+
|
|
5
|
+
import { CODE, KEY } from "./keyboard.constants";
|
|
6
|
+
|
|
7
|
+
interface Options {
|
|
8
|
+
up?: VoidFunction;
|
|
9
|
+
down?: VoidFunction;
|
|
10
|
+
left?: VoidFunction;
|
|
11
|
+
right?: VoidFunction;
|
|
12
|
+
start?: VoidFunction;
|
|
13
|
+
end?: VoidFunction;
|
|
14
|
+
activate?: VoidFunction;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const isActivateKey = (event: KeyboardEvent<HTMLDivElement | HTMLButtonElement>) => {
|
|
18
|
+
return (
|
|
19
|
+
event.key === KEY.ENTER ||
|
|
20
|
+
event.key === KEY.SPACE ||
|
|
21
|
+
event.key === KEY.SPACEBAR ||
|
|
22
|
+
event.code === CODE.ENTER ||
|
|
23
|
+
event.code === CODE.SPACE
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const voidFn = () => {};
|
|
28
|
+
|
|
29
|
+
export const useKeyboardControls = ({
|
|
30
|
+
up = voidFn,
|
|
31
|
+
down = voidFn,
|
|
32
|
+
left = voidFn,
|
|
33
|
+
right = voidFn,
|
|
34
|
+
start = voidFn,
|
|
35
|
+
end = voidFn,
|
|
36
|
+
activate = voidFn
|
|
37
|
+
}: Options) => {
|
|
38
|
+
const handleKeyDown = useCallback(
|
|
39
|
+
(event: KeyboardEvent<HTMLDivElement | HTMLButtonElement>) => {
|
|
40
|
+
if (isActivateKey(event)) {
|
|
41
|
+
return activate();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (event.code === CODE.HOME) {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
|
|
47
|
+
return start();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (event.code === CODE.END) {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
|
|
53
|
+
return end();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (event.code === CODE.ARROW_UP) {
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
|
|
59
|
+
return up();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (event.code === CODE.ARROW_DOWN) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
|
|
65
|
+
return down();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (event.code === CODE.ARROW_RIGHT) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
|
|
71
|
+
return right();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (event.code === CODE.ARROW_LEFT) {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
|
|
77
|
+
return left();
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
[activate, down, end, left, right, start, up]
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return handleKeyDown;
|
|
84
|
+
};
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import type { OperationButtonProps } from "../molecules/table/components/DefaultOperationButton.js";
|
|
4
|
+
import type { JSON } from "./SubmissionType.js";
|
|
4
5
|
|
|
5
|
-
export type
|
|
6
|
-
// export type OnClickOperation<Data = any> = (data: Data, operation: Operation) => void;
|
|
6
|
+
export type CellMetadata = Record<string, unknown>;
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export type PermissionsResolver<Data extends { [key: string]: JSON } = { [key: string]: JSON }> = (
|
|
9
|
+
data: Data,
|
|
10
|
+
metadata: CellMetadata,
|
|
11
|
+
operation: Operation<Data>
|
|
12
|
+
) => void;
|
|
13
|
+
|
|
14
|
+
export interface Operation<Data extends { [key: string]: JSON } = { [key: string]: JSON }> {
|
|
9
15
|
/**
|
|
10
16
|
* Action identifier
|
|
11
17
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cx from "classnames";
|
|
2
|
-
import { type ButtonHTMLAttributes, forwardRef, type
|
|
2
|
+
import { type ButtonHTMLAttributes, forwardRef, type PropsWithChildren } from "react";
|
|
3
3
|
|
|
4
4
|
import { registerComponent } from "../../registries/components";
|
|
5
5
|
|
|
@@ -24,31 +24,50 @@ export const BUTTON_VARIANTS = [
|
|
|
24
24
|
"outline-link"
|
|
25
25
|
];
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
interface BaseButtonProps<T extends HTMLElement> extends ButtonHTMLAttributes<T> {
|
|
28
|
+
tag?: "button" | "a" | "input" | "div";
|
|
28
29
|
variant?: (typeof BUTTON_VARIANTS)[keyof typeof BUTTON_VARIANTS] | string;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
32
|
+
interface HTMLAnchorProps extends BaseButtonProps<HTMLAnchorElement> {
|
|
33
|
+
tag: "a";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface HTMLButtonProps extends BaseButtonProps<HTMLButtonElement> {
|
|
37
|
+
tag?: "button";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface HTMLInputProps extends BaseButtonProps<HTMLInputElement> {
|
|
41
|
+
tag: "input";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface HTMLDivProps extends BaseButtonProps<HTMLDivElement> {
|
|
45
|
+
tag: "div";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type ButtonProps = HTMLAnchorProps | HTMLButtonProps | HTMLInputProps | HTMLDivProps;
|
|
49
|
+
|
|
50
|
+
export const Button = forwardRef(({ tag: Tag = "button", variant, className, children, ...props }: PropsWithChildren<ButtonProps>, ref) => {
|
|
51
|
+
return (
|
|
52
|
+
<Tag
|
|
53
|
+
{...(props as any)}
|
|
54
|
+
ref={ref as any}
|
|
55
|
+
className={cx(
|
|
56
|
+
"btn flex gap-1",
|
|
57
|
+
{
|
|
58
|
+
disabled: props.disabled
|
|
59
|
+
},
|
|
60
|
+
`btn-${variant}`,
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
disabled={props.disabled}
|
|
64
|
+
onClick={(evt) => !props.disabled && props.onClick?.(evt as any)}
|
|
65
|
+
>
|
|
66
|
+
{children}
|
|
67
|
+
</Tag>
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
Button.displayName = "Button";
|
|
53
72
|
|
|
54
73
|
registerComponent("Button", Button);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import classnames from "classnames";
|
|
2
2
|
import { PropsWithChildren } from "react";
|
|
3
3
|
|
|
4
|
+
import { registerComponent } from "../../registries/components.js";
|
|
5
|
+
|
|
4
6
|
export interface CardProps {
|
|
5
7
|
label: string;
|
|
6
8
|
className?: string;
|
|
@@ -18,3 +20,5 @@ export function Card({ children, label, className }: PropsWithChildren<CardProps
|
|
|
18
20
|
</div>
|
|
19
21
|
);
|
|
20
22
|
}
|
|
23
|
+
|
|
24
|
+
registerComponent("Card", Card);
|
|
@@ -9,7 +9,7 @@ export function InputTags<Data = string>(props: InputTagsProps) {
|
|
|
9
9
|
|
|
10
10
|
const FormControl = getComponent<typeof DefaultFormControl>("FormControl");
|
|
11
11
|
const Component = getComponent<ComponentType<InputTagsProps<Data>>>([`InputTags.${layout}`, "Input"]);
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
return (
|
|
14
14
|
<FormControl
|
|
15
15
|
id={id}
|
|
@@ -12,18 +12,11 @@ import { Pagination } from "./all";
|
|
|
12
12
|
*
|
|
13
13
|
* ```tsx
|
|
14
14
|
* import {Pagination} from "@tsed/react-formio/molecules/pagination/all"
|
|
15
|
-
* import {Pagination} from "@tsed/react-formio/molecules/form/select/Select/all"
|
|
16
15
|
*
|
|
17
16
|
* or
|
|
18
17
|
*
|
|
19
18
|
* import {Pagination} from "@tsed/react-formio/molecules/pagination/Pagination";
|
|
20
19
|
* import "@tsed/react-formio/molecules/pagination/PaginationButton";
|
|
21
|
-
*
|
|
22
|
-
* or
|
|
23
|
-
*
|
|
24
|
-
* import {Pagination} from "@tsed/react-formio/molecules/pagination/Pagination";
|
|
25
|
-
*
|
|
26
|
-
* registerComponent("PaginationButton", MyPaginationButton);
|
|
27
20
|
* ```
|
|
28
21
|
*
|
|
29
22
|
* Pagination component support DI container and can be used with custom PaginationButton component.
|
|
@@ -19,7 +19,40 @@ type ProductSubmission = SubmissionType<{
|
|
|
19
19
|
price?: number;
|
|
20
20
|
currency?: string;
|
|
21
21
|
}>;
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Table component.
|
|
24
|
+
*
|
|
25
|
+
* You can import this component and use it like:
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* import {Table} from "@tsed/react-formio/molecules/table/all"
|
|
29
|
+
*
|
|
30
|
+
* or
|
|
31
|
+
*
|
|
32
|
+
* import {Table} from "@tsed/react-formio/molecules/table/Table";
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Table component support DI container and can be used with custom component. Here is the list of components that you can override:
|
|
36
|
+
*
|
|
37
|
+
* - DefaultFilter
|
|
38
|
+
* - DefaultArrowSort
|
|
39
|
+
* - DefaultCell
|
|
40
|
+
* - DefaultCellOperations
|
|
41
|
+
* - DefaultOperationButton
|
|
42
|
+
* - DefaultCellHeader
|
|
43
|
+
* - DefaultCellFooter
|
|
44
|
+
* - TextFieldFilter
|
|
45
|
+
* - SelectFilter
|
|
46
|
+
* - RangeFilter
|
|
47
|
+
*
|
|
48
|
+
* ```tsx
|
|
49
|
+
* function CustomDefaultFilter() {
|
|
50
|
+
*
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* registerComponent("DefaultFilter", DefaultFilter);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
23
56
|
export default {
|
|
24
57
|
title: "Table",
|
|
25
58
|
component: Table,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { flexRender
|
|
1
|
+
import { flexRender } from "@tanstack/react-table";
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import { PropsWithChildren } from "react";
|
|
4
4
|
|
|
5
|
+
import type { JSON } from "../../interfaces/index.js";
|
|
5
6
|
import { getComponent } from "../../registries/components";
|
|
6
7
|
import type { Pagination as DefaultPagination } from "../pagination/Pagination";
|
|
7
8
|
import type { DefaultCellFooter } from "./components/DefaultCellFooter";
|
|
8
9
|
import type { DefaultCellHeader } from "./components/DefaultCellHeader";
|
|
9
10
|
import { useTable, UseTableProps } from "./hooks/useTable";
|
|
10
11
|
|
|
11
|
-
export interface TableProps<Data extends
|
|
12
|
+
export interface TableProps<Data extends { [key: string]: JSON } = { [key: string]: JSON }> extends UseTableProps<Data> {
|
|
12
13
|
className?: string;
|
|
13
14
|
|
|
14
15
|
enableFooter?: boolean;
|
|
@@ -16,8 +17,13 @@ export interface TableProps<Data extends RowData = any> extends UseTableProps<Da
|
|
|
16
17
|
pageSizes?: number[];
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export function Table<Data extends
|
|
20
|
-
|
|
20
|
+
export function Table<Data extends { [key: string]: JSON } = { [key: string]: JSON }>({
|
|
21
|
+
className,
|
|
22
|
+
enableFooter,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: PropsWithChildren<TableProps<Data>>) {
|
|
26
|
+
const { tableInstance, i18n } = useTable<Data>(props);
|
|
21
27
|
const CellHeader = getComponent<typeof DefaultCellHeader>("CellHeader");
|
|
22
28
|
const CellFooter = getComponent<typeof DefaultCellFooter>("CellFooter");
|
|
23
29
|
const Pagination = getComponent<typeof DefaultPagination>("Pagination");
|
|
@@ -76,7 +82,7 @@ export function Table<Data extends RowData = any>({ className, enableFooter, chi
|
|
|
76
82
|
)}
|
|
77
83
|
</table>
|
|
78
84
|
<div className={"overflow-hidden flex flex-wrap"}>
|
|
79
|
-
{props.data.length && pagination
|
|
85
|
+
{props.data.length && pagination ? (
|
|
80
86
|
<Pagination
|
|
81
87
|
className={"flex-1"}
|
|
82
88
|
canNextPage={tableInstance.getCanNextPage()}
|
|
@@ -92,7 +98,7 @@ export function Table<Data extends RowData = any>({ className, enableFooter, chi
|
|
|
92
98
|
onClickNextPage={() => tableInstance.nextPage()}
|
|
93
99
|
onPageSizeChange={(pageSize) => tableInstance.setPageSize(pageSize)}
|
|
94
100
|
/>
|
|
95
|
-
)}
|
|
101
|
+
) : null}
|
|
96
102
|
<div>{children}</div>
|
|
97
103
|
</div>
|
|
98
104
|
</div>
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
import type { CellContext } from "@tanstack/react-table";
|
|
2
2
|
|
|
3
|
-
import type { Operation } from "../../../interfaces";
|
|
3
|
+
import type { CellMetadata, JSON, Operation } from "../../../interfaces";
|
|
4
4
|
import { getComponent, registerComponent } from "../../../registries/components";
|
|
5
5
|
import type { DefaultOperationButton } from "./DefaultOperationButton";
|
|
6
6
|
|
|
7
|
-
export interface DefaultCellOperationsProps<Data =
|
|
7
|
+
export interface DefaultCellOperationsProps<Data extends { [key: string]: JSON } = { [key: string]: JSON }> {
|
|
8
8
|
info: CellContext<Data, unknown>;
|
|
9
9
|
operations: Operation<Data>[];
|
|
10
|
-
metadata?:
|
|
10
|
+
metadata?: CellMetadata;
|
|
11
11
|
i18n: (i18n: string) => string;
|
|
12
12
|
onClick?: (data: any, operation: Operation<Data>) => void;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function DefaultCellOperations
|
|
16
|
-
|
|
15
|
+
export function DefaultCellOperations<Data extends { [key: string]: JSON } = { [key: string]: JSON }>({
|
|
16
|
+
info,
|
|
17
|
+
metadata,
|
|
18
|
+
operations,
|
|
19
|
+
i18n,
|
|
20
|
+
onClick
|
|
21
|
+
}: DefaultCellOperationsProps<Data>) {
|
|
22
|
+
const Button = getComponent<typeof DefaultOperationButton<Data>>("OperationButton");
|
|
17
23
|
return (
|
|
18
24
|
<div className='btn-group'>
|
|
19
25
|
{operations
|
|
20
|
-
.filter(({ permissionsResolver }) => {
|
|
21
|
-
return !permissionsResolver || permissionsResolver(info.row.original, metadata);
|
|
26
|
+
.filter(({ permissionsResolver, ...operation }) => {
|
|
27
|
+
return !permissionsResolver || permissionsResolver(info.row.original, metadata || {}, operation);
|
|
22
28
|
})
|
|
23
29
|
.map((operation) => {
|
|
24
30
|
return (
|
|
@@ -2,20 +2,21 @@ import { CellContext } from "@tanstack/react-table";
|
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import { HTMLAttributes } from "react";
|
|
4
4
|
|
|
5
|
-
import { Operation } from "../../../interfaces";
|
|
5
|
+
import { type CellMetadata, type JSON, Operation } from "../../../interfaces";
|
|
6
6
|
import { registerComponent } from "../../../registries/components";
|
|
7
7
|
import { iconClass } from "../../../utils/iconClass";
|
|
8
8
|
import { stopPropagationWrapper } from "../../../utils/stopPropagationWrapper";
|
|
9
9
|
|
|
10
|
-
export interface OperationButtonProps<Data =
|
|
10
|
+
export interface OperationButtonProps<Data extends { [key: string]: JSON } = { [key: string]: JSON }>
|
|
11
|
+
extends Omit<HTMLAttributes<HTMLButtonElement>, "onClick"> {
|
|
11
12
|
operation: Operation<Data>;
|
|
12
13
|
info: CellContext<Data, unknown>;
|
|
13
|
-
metadata?:
|
|
14
|
+
metadata?: CellMetadata;
|
|
14
15
|
onClick: () => void;
|
|
15
16
|
i18n?: (i18n: string) => string;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
export function DefaultOperationButton(props: OperationButtonProps) {
|
|
19
|
+
export function DefaultOperationButton<Data extends { [key: string]: JSON } = { [key: string]: JSON }>(props: OperationButtonProps<Data>) {
|
|
19
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
21
|
const { i18n = (f: string) => f, onClick, operation, info, ...extraProps } = props;
|
|
21
22
|
const { className = "btn", buttonSize = "xs", buttonType = "primary", buttonOutline, action, title = "", icon = "" } = operation;
|
|
@@ -6,18 +6,18 @@ import {
|
|
|
6
6
|
getFilteredRowModel,
|
|
7
7
|
getPaginationRowModel,
|
|
8
8
|
getSortedRowModel,
|
|
9
|
-
type RowData,
|
|
10
9
|
type TableOptions,
|
|
11
10
|
type TableState,
|
|
12
11
|
useReactTable
|
|
13
12
|
} from "@tanstack/react-table";
|
|
14
13
|
import { useEffect } from "react";
|
|
15
14
|
|
|
16
|
-
import { Operation } from "../../../interfaces";
|
|
15
|
+
import { type JSON, Operation } from "../../../interfaces";
|
|
17
16
|
import { getComponent } from "../../../registries/components";
|
|
18
17
|
import type { DefaultCellOperations } from "../components/DefaultCellOperations";
|
|
19
18
|
|
|
20
|
-
export interface UseTableProps<Data extends
|
|
19
|
+
export interface UseTableProps<Data extends { [key: string]: JSON } = { [key: string]: JSON }>
|
|
20
|
+
extends Omit<TableOptions<Data>, "getCoreRowModel" | "onClick"> {
|
|
21
21
|
operations: Operation<Data>[];
|
|
22
22
|
metadata?: Record<string, unknown>;
|
|
23
23
|
i18n?: (i18n: string) => string;
|
|
@@ -27,8 +27,8 @@ export interface UseTableProps<Data extends RowData> extends TableOptions<Data>
|
|
|
27
27
|
pageSizes?: number[];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export function useTable<Data extends
|
|
31
|
-
const Operations = getComponent<typeof DefaultCellOperations
|
|
30
|
+
export function useTable<Data extends { [key: string]: JSON } = { [key: string]: JSON }>(props: UseTableProps<Data>) {
|
|
31
|
+
const Operations = getComponent<typeof DefaultCellOperations<Data>>("CellOperations");
|
|
32
32
|
const i18n = props.i18n || ((f: string) => f);
|
|
33
33
|
|
|
34
34
|
// const [pagination, setPagination] = useState({
|