@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.
Files changed (115) hide show
  1. package/dist/hooks/keyboard.constants.d.ts +38 -0
  2. package/dist/hooks/keyboard.constants.js +7 -0
  3. package/dist/hooks/keyboard.constants.js.map +1 -0
  4. package/dist/hooks/useKeyboardControls.d.ts +12 -0
  5. package/dist/hooks/useKeyboardControls.js +35 -0
  6. package/dist/hooks/useKeyboardControls.js.map +1 -0
  7. package/dist/interfaces/Operation.d.ts +12 -2
  8. package/dist/molecules/button/Button.d.ts +18 -5
  9. package/dist/molecules/button/Button.js +29 -30
  10. package/dist/molecules/button/Button.js.map +1 -1
  11. package/dist/molecules/card/Card.js +7 -5
  12. package/dist/molecules/card/Card.js.map +1 -1
  13. package/dist/molecules/forms/input-tags/InputTags.js +14 -14
  14. package/dist/molecules/forms/input-tags/InputTags.js.map +1 -1
  15. package/dist/molecules/table/Table.d.ts +11 -3
  16. package/dist/molecules/table/Table.js +8 -3
  17. package/dist/molecules/table/Table.js.map +1 -1
  18. package/dist/molecules/table/components/DefaultCellOperations.d.ts +12 -4
  19. package/dist/molecules/table/components/DefaultCellOperations.js +12 -6
  20. package/dist/molecules/table/components/DefaultCellOperations.js.map +1 -1
  21. package/dist/molecules/table/components/DefaultOperationButton.d.ts +12 -4
  22. package/dist/molecules/table/components/DefaultOperationButton.js.map +1 -1
  23. package/dist/molecules/table/hooks/useTable.d.ts +12 -4
  24. package/dist/molecules/table/hooks/useTable.js.map +1 -1
  25. package/dist/molecules/tabs/Tab.d.ts +13 -0
  26. package/dist/molecules/tabs/Tab.js +67 -0
  27. package/dist/molecules/tabs/Tab.js.map +1 -0
  28. package/dist/molecules/tabs/TabList.d.ts +2 -0
  29. package/dist/molecules/tabs/TabList.js +24 -0
  30. package/dist/molecules/tabs/TabList.js.map +1 -0
  31. package/dist/molecules/tabs/TabPanel.d.ts +9 -0
  32. package/dist/molecules/tabs/TabPanel.js +27 -0
  33. package/dist/molecules/tabs/TabPanel.js.map +1 -0
  34. package/dist/molecules/tabs/Tabs.d.ts +4 -16
  35. package/dist/molecules/tabs/Tabs.js +7 -67
  36. package/dist/molecules/tabs/Tabs.js.map +1 -1
  37. package/dist/molecules/tabs/TabsBody.d.ts +1 -0
  38. package/dist/molecules/tabs/TabsBody.js +10 -0
  39. package/dist/molecules/tabs/TabsBody.js.map +1 -0
  40. package/dist/molecules/tabs/TabsLegacy.d.ts +17 -0
  41. package/dist/molecules/tabs/TabsLegacy.js +49 -0
  42. package/dist/molecules/tabs/TabsLegacy.js.map +1 -0
  43. package/dist/molecules/tabs/all.d.ts +5 -0
  44. package/dist/molecules/tabs/all.js +13 -0
  45. package/dist/molecules/tabs/all.js.map +1 -0
  46. package/dist/molecules/tabs/context/TabControl.d.ts +52 -0
  47. package/dist/molecules/tabs/context/TabControl.js +85 -0
  48. package/dist/molecules/tabs/context/TabControl.js.map +1 -0
  49. package/dist/molecules/tabs/hooks/tabControl.d.ts +44 -0
  50. package/dist/molecules/tabs/hooks/tabControl.js +34 -0
  51. package/dist/molecules/tabs/hooks/tabControl.js.map +1 -0
  52. package/dist/organisms/form/actions/FormAction.js.map +1 -0
  53. package/dist/organisms/form/builder/FormEdit.d.ts +3 -1
  54. package/dist/organisms/form/builder/FormEdit.js +38 -35
  55. package/dist/organisms/form/builder/FormEdit.js.map +1 -1
  56. package/dist/organisms/form/builder/useFormEdit.js +17 -17
  57. package/dist/organisms/form/builder/useFormEdit.js.map +1 -1
  58. package/dist/organisms/form/exports/FormExport.d.ts +5 -0
  59. package/dist/organisms/form/exports/FormExport.js +55 -0
  60. package/dist/organisms/form/exports/FormExport.js.map +1 -0
  61. package/dist/organisms/form/preview/FormPreview.d.ts +6 -0
  62. package/dist/organisms/form/preview/FormPreview.js +11 -0
  63. package/dist/organisms/form/preview/FormPreview.js.map +1 -0
  64. package/dist/organisms/table/submissions/SubmissionsTable.d.ts +11 -3
  65. package/dist/organisms/table/submissions/SubmissionsTable.js +4 -1
  66. package/dist/organisms/table/submissions/SubmissionsTable.js.map +1 -1
  67. package/dist/organisms/views/FormViews.d.ts +24 -0
  68. package/dist/organisms/views/FormViews.js +96 -0
  69. package/dist/organisms/views/FormViews.js.map +1 -0
  70. package/package.json +3 -3
  71. package/src/hooks/keyboard.constants.ts +40 -0
  72. package/src/hooks/useKeyboardControls.spec.tsx +208 -0
  73. package/src/hooks/useKeyboardControls.ts +84 -0
  74. package/src/interfaces/Operation.ts +9 -3
  75. package/src/molecules/button/Button.tsx +43 -24
  76. package/src/molecules/card/Card.tsx +4 -0
  77. package/src/molecules/forms/input-tags/InputTags.tsx +1 -1
  78. package/src/molecules/pagination/Pagination.stories.tsx +0 -7
  79. package/src/molecules/table/Table.stories.tsx +34 -1
  80. package/src/molecules/table/Table.tsx +12 -6
  81. package/src/molecules/table/components/DefaultCellOperations.tsx +13 -7
  82. package/src/molecules/table/components/DefaultOperationButton.tsx +5 -4
  83. package/src/molecules/table/hooks/useTable.tsx +5 -5
  84. package/src/molecules/tabs/Tab.tsx +106 -0
  85. package/src/molecules/tabs/TabList.tsx +37 -0
  86. package/src/molecules/tabs/TabPanel.tsx +37 -0
  87. package/src/molecules/tabs/Tabs.spec.tsx +126 -73
  88. package/src/molecules/tabs/Tabs.stories.tsx +298 -65
  89. package/src/molecules/tabs/Tabs.tsx +10 -81
  90. package/src/molecules/tabs/TabsBody.tsx +11 -0
  91. package/src/molecules/tabs/TabsLegacy.stories.tsx +103 -0
  92. package/src/molecules/tabs/TabsLegacy.tsx +84 -0
  93. package/src/molecules/tabs/all.ts +5 -0
  94. package/src/molecules/tabs/context/TabControl.tsx +166 -0
  95. package/src/molecules/tabs/hooks/tabControl.spec.tsx +388 -0
  96. package/src/molecules/tabs/hooks/tabControl.ts +52 -0
  97. package/src/organisms/__fixtures__/form-firstname.fixture.json +1 -0
  98. package/src/organisms/__fixtures__/form.fixture.json +1 -0
  99. package/src/organisms/form/actions/FormAction.stories.tsx +422 -0
  100. package/src/organisms/form/builder/FormEdit.tsx +7 -1
  101. package/src/organisms/form/builder/useFormEdit.ts +1 -1
  102. package/src/organisms/form/exports/FormExport.stories.tsx +71 -0
  103. package/src/organisms/form/exports/FormExport.tsx +58 -0
  104. package/src/organisms/form/preview/FormPreview.stories.tsx +61 -0
  105. package/src/organisms/form/preview/FormPreview.tsx +21 -0
  106. package/src/organisms/table/actions/ActionsTable.stories.tsx +36 -34
  107. package/src/organisms/table/submissions/SubmissionsTable.stories.tsx +103 -57
  108. package/src/organisms/table/submissions/SubmissionsTable.tsx +10 -4
  109. package/src/organisms/views/FormViews.stories.tsx +224 -0
  110. package/src/organisms/views/FormViews.tsx +146 -0
  111. package/dist/organisms/form/action/FormAction.js.map +0 -1
  112. package/src/organisms/form/action/FormAction.stories.tsx +0 -364
  113. /package/dist/organisms/form/{action → actions}/FormAction.d.ts +0 -0
  114. /package/dist/organisms/form/{action → actions}/FormAction.js +0 -0
  115. /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 PermissionsResolver<Data = any> = (data: Data, ctx: any) => void;
6
- // export type OnClickOperation<Data = any> = (data: Data, operation: Operation) => void;
6
+ export type CellMetadata = Record<string, unknown>;
7
7
 
8
- export interface Operation<Data = any> {
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 LegacyRef, type PropsWithChildren } from "react";
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
- export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
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
- export const Button = forwardRef(
32
- ({ variant, className, children, ...props }: PropsWithChildren<ButtonProps>, ref: LegacyRef<HTMLButtonElement>) => {
33
- return (
34
- <button
35
- {...props}
36
- ref={ref}
37
- className={cx(
38
- "btn flex gap-1",
39
- {
40
- disabled: props.disabled
41
- },
42
- `btn-${variant}`,
43
- className
44
- )}
45
- disabled={props.disabled}
46
- onClick={(evt) => !props.disabled && props.onClick?.(evt)}
47
- >
48
- {children}
49
- </button>
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
- console.log("VALUE", props.value);
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, RowData } from "@tanstack/react-table";
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 RowData = any> extends UseTableProps<Data> {
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 RowData = any>({ className, enableFooter, children, ...props }: PropsWithChildren<TableProps<Data>>) {
20
- const { tableInstance, i18n } = useTable(props);
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 = any> {
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?: Record<string, unknown>;
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({ info, metadata, operations, i18n, onClick }: DefaultCellOperationsProps) {
16
- const Button = getComponent<typeof DefaultOperationButton>("OperationButton");
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 = any> extends Omit<HTMLAttributes<HTMLButtonElement>, "onClick"> {
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?: Record<string, unknown>;
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 RowData> extends TableOptions<Data> {
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 RowData>(props: UseTableProps<Data>) {
31
- const Operations = getComponent<typeof DefaultCellOperations>("CellOperations");
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({