@tsed/react-formio 3.0.0-alpha.10 → 3.0.0-alpha.12

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 (215) hide show
  1. package/dist/atoms/icon/Icon.js.map +1 -1
  2. package/dist/chunks/index.js +33 -30
  3. package/dist/chunks/index.js.map +1 -1
  4. package/dist/chunks/index.module.js +16 -16
  5. package/dist/chunks/index.module.js.map +1 -1
  6. package/dist/chunks/react-select-animated.esm.js +1204 -1101
  7. package/dist/chunks/react-select-animated.esm.js.map +1 -1
  8. package/dist/hooks/keyboard.constants.d.ts +38 -0
  9. package/dist/hooks/keyboard.constants.js +7 -0
  10. package/dist/hooks/keyboard.constants.js.map +1 -0
  11. package/dist/hooks/useKeyboardControls.d.ts +12 -0
  12. package/dist/hooks/useKeyboardControls.js +35 -0
  13. package/dist/hooks/useKeyboardControls.js.map +1 -0
  14. package/dist/hooks/useTooltip.js.map +1 -1
  15. package/dist/interfaces/Operation.d.ts +12 -2
  16. package/dist/molecules/alert/Alert.js.map +1 -1
  17. package/dist/molecules/button/Button.d.ts +18 -5
  18. package/dist/molecules/button/Button.js +22 -26
  19. package/dist/molecules/button/Button.js.map +1 -1
  20. package/dist/molecules/card/Card.js +7 -5
  21. package/dist/molecules/card/Card.js.map +1 -1
  22. package/dist/molecules/forms/form-control/FormControl.js.map +1 -1
  23. package/dist/molecules/forms/input-tags/InputTags.js +14 -14
  24. package/dist/molecules/forms/input-tags/InputTags.js.map +1 -1
  25. package/dist/molecules/forms/input-tags/components/ChoicesTags.js +26 -26
  26. package/dist/molecules/forms/input-tags/components/ChoicesTags.js.map +1 -1
  27. package/dist/molecules/forms/input-tags/components/ReactTags.js +289 -300
  28. package/dist/molecules/forms/input-tags/components/ReactTags.js.map +1 -1
  29. package/dist/molecules/forms/input-text/InputText.js +3 -3
  30. package/dist/molecules/forms/input-text/InputText.js.map +1 -1
  31. package/dist/molecules/forms/select/Select.js.map +1 -1
  32. package/dist/molecules/forms/select/components/ChoicesSelect.js +71 -73
  33. package/dist/molecules/forms/select/components/ChoicesSelect.js.map +1 -1
  34. package/dist/molecules/forms/select/components/HtmlSelect.js.map +1 -1
  35. package/dist/molecules/forms/select/components/ReactSelect.js +13 -14
  36. package/dist/molecules/forms/select/components/ReactSelect.js.map +1 -1
  37. package/dist/molecules/forms/select/components/choices.template.js +2340 -2257
  38. package/dist/molecules/forms/select/components/choices.template.js.map +1 -1
  39. package/dist/molecules/forms/select/hooks/useOptions.js.map +1 -1
  40. package/dist/molecules/loader/Loader.js.map +1 -1
  41. package/dist/molecules/modal/Modal.js +23 -24
  42. package/dist/molecules/modal/Modal.js.map +1 -1
  43. package/dist/molecules/pagination/Pagination.js +19 -19
  44. package/dist/molecules/pagination/Pagination.js.map +1 -1
  45. package/dist/molecules/pagination/PaginationButton.js.map +1 -1
  46. package/dist/molecules/pagination/utils/getPageNumbers.js.map +1 -1
  47. package/dist/molecules/table/Table.d.ts +11 -3
  48. package/dist/molecules/table/Table.js +31 -32
  49. package/dist/molecules/table/Table.js.map +1 -1
  50. package/dist/molecules/table/components/DefaultArrowSort.js.map +1 -1
  51. package/dist/molecules/table/components/DefaultCell.js.map +1 -1
  52. package/dist/molecules/table/components/DefaultCellFooter.js.map +1 -1
  53. package/dist/molecules/table/components/DefaultCellHeader.js.map +1 -1
  54. package/dist/molecules/table/components/DefaultCellOperations.d.ts +12 -4
  55. package/dist/molecules/table/components/DefaultCellOperations.js +13 -7
  56. package/dist/molecules/table/components/DefaultCellOperations.js.map +1 -1
  57. package/dist/molecules/table/components/DefaultFilter.js.map +1 -1
  58. package/dist/molecules/table/components/DefaultOperationButton.d.ts +12 -4
  59. package/dist/molecules/table/components/DefaultOperationButton.js +1 -1
  60. package/dist/molecules/table/components/DefaultOperationButton.js.map +1 -1
  61. package/dist/molecules/table/filters/RangeFilter.js +23 -24
  62. package/dist/molecules/table/filters/RangeFilter.js.map +1 -1
  63. package/dist/molecules/table/filters/SelectFilter.js +11 -13
  64. package/dist/molecules/table/filters/SelectFilter.js.map +1 -1
  65. package/dist/molecules/table/filters/TextFieldFilter.js.map +1 -1
  66. package/dist/molecules/table/hooks/useTable.d.ts +12 -4
  67. package/dist/molecules/table/hooks/useTable.js +7 -7
  68. package/dist/molecules/table/hooks/useTable.js.map +1 -1
  69. package/dist/molecules/table/hooks/useUniqValues.js.map +1 -1
  70. package/dist/molecules/table/utils/mapFormToColumns.js +20 -21
  71. package/dist/molecules/table/utils/mapFormToColumns.js.map +1 -1
  72. package/dist/molecules/tabs/Tab.d.ts +13 -0
  73. package/dist/molecules/tabs/Tab.js +66 -0
  74. package/dist/molecules/tabs/Tab.js.map +1 -0
  75. package/dist/molecules/tabs/TabList.d.ts +2 -0
  76. package/dist/molecules/tabs/TabList.js +23 -0
  77. package/dist/molecules/tabs/TabList.js.map +1 -0
  78. package/dist/molecules/tabs/TabPanel.d.ts +9 -0
  79. package/dist/molecules/tabs/TabPanel.js +27 -0
  80. package/dist/molecules/tabs/TabPanel.js.map +1 -0
  81. package/dist/molecules/tabs/Tabs.d.ts +4 -16
  82. package/dist/molecules/tabs/Tabs.js +7 -67
  83. package/dist/molecules/tabs/Tabs.js.map +1 -1
  84. package/dist/molecules/tabs/TabsBody.d.ts +1 -0
  85. package/dist/molecules/tabs/TabsBody.js +10 -0
  86. package/dist/molecules/tabs/TabsBody.js.map +1 -0
  87. package/dist/molecules/tabs/TabsLegacy.d.ts +17 -0
  88. package/dist/molecules/tabs/TabsLegacy.js +49 -0
  89. package/dist/molecules/tabs/TabsLegacy.js.map +1 -0
  90. package/dist/molecules/tabs/all.d.ts +5 -0
  91. package/dist/molecules/tabs/all.js +13 -0
  92. package/dist/molecules/tabs/all.js.map +1 -0
  93. package/dist/molecules/tabs/context/TabControl.d.ts +52 -0
  94. package/dist/molecules/tabs/context/TabControl.js +85 -0
  95. package/dist/molecules/tabs/context/TabControl.js.map +1 -0
  96. package/dist/molecules/tabs/hooks/tabControl.d.ts +44 -0
  97. package/dist/molecules/tabs/hooks/tabControl.js +34 -0
  98. package/dist/molecules/tabs/hooks/tabControl.js.map +1 -0
  99. package/dist/organisms/form/Form.js.map +1 -1
  100. package/dist/organisms/form/access/FormAccess.js +41 -41
  101. package/dist/organisms/form/access/FormAccess.js.map +1 -1
  102. package/dist/organisms/form/access/FormAccess.schema.js.map +1 -1
  103. package/dist/organisms/form/access/FormAccess.utils.js +2 -2
  104. package/dist/organisms/form/access/FormAccess.utils.js.map +1 -1
  105. package/dist/organisms/form/{action → actions}/FormAction.js +7 -8
  106. package/dist/organisms/form/actions/FormAction.js.map +1 -0
  107. package/dist/organisms/form/builder/FormBuilder.js.map +1 -1
  108. package/dist/organisms/form/builder/FormEdit.d.ts +3 -1
  109. package/dist/organisms/form/builder/FormEdit.js +38 -35
  110. package/dist/organisms/form/builder/FormEdit.js.map +1 -1
  111. package/dist/organisms/form/builder/FormEdit.reducer.js.map +1 -1
  112. package/dist/organisms/form/builder/FormEditCtas.js +34 -34
  113. package/dist/organisms/form/builder/FormEditCtas.js.map +1 -1
  114. package/dist/organisms/form/builder/FormParameters.js.map +1 -1
  115. package/dist/organisms/form/builder/useFormBuilder.js +41 -38
  116. package/dist/organisms/form/builder/useFormBuilder.js.map +1 -1
  117. package/dist/organisms/form/builder/useFormEdit.js +1 -1
  118. package/dist/organisms/form/builder/useFormEdit.js.map +1 -1
  119. package/dist/organisms/form/exports/FormExport.d.ts +5 -0
  120. package/dist/organisms/form/exports/FormExport.js +55 -0
  121. package/dist/organisms/form/exports/FormExport.js.map +1 -0
  122. package/dist/organisms/form/preview/FormPreview.d.ts +6 -0
  123. package/dist/organisms/form/preview/FormPreview.js +11 -0
  124. package/dist/organisms/form/preview/FormPreview.js.map +1 -0
  125. package/dist/organisms/form/settings/FormSettings.js +24 -24
  126. package/dist/organisms/form/settings/FormSettings.js.map +1 -1
  127. package/dist/organisms/form/settings/FormSettings.schema.js.map +1 -1
  128. package/dist/organisms/form/settings/FormSettings.utils.js.map +1 -1
  129. package/dist/organisms/form/useForm.js +664 -661
  130. package/dist/organisms/form/useForm.js.map +1 -1
  131. package/dist/organisms/modal/RemoveModal.js +16 -17
  132. package/dist/organisms/modal/RemoveModal.js.map +1 -1
  133. package/dist/organisms/table/actions/ActionsTable.js.map +1 -1
  134. package/dist/organisms/table/forms/FormsTable.js.map +1 -1
  135. package/dist/organisms/table/forms/components/FormsCell.js.map +1 -1
  136. package/dist/organisms/table/submissions/SubmissionsTable.d.ts +11 -3
  137. package/dist/organisms/table/submissions/SubmissionsTable.js +4 -1
  138. package/dist/organisms/table/submissions/SubmissionsTable.js.map +1 -1
  139. package/dist/organisms/views/FormViews.d.ts +24 -0
  140. package/dist/organisms/views/FormViews.js +96 -0
  141. package/dist/organisms/views/FormViews.js.map +1 -0
  142. package/dist/registries/components.js.map +1 -1
  143. package/dist/utils/getEventValue.js.map +1 -1
  144. package/dist/utils/iconClass.js.map +1 -1
  145. package/dist/utils/mapPagination.js.map +1 -1
  146. package/dist/utils/stopPropagationWrapper.js.map +1 -1
  147. package/package.json +7 -7
  148. package/src/atoms/icon/Icon.stories.tsx +1 -1
  149. package/src/hooks/keyboard.constants.ts +40 -0
  150. package/src/hooks/useKeyboardControls.spec.tsx +208 -0
  151. package/src/hooks/useKeyboardControls.ts +84 -0
  152. package/src/interfaces/Operation.ts +9 -3
  153. package/src/molecules/button/Button.stories.tsx +1 -1
  154. package/src/molecules/button/Button.tsx +43 -24
  155. package/src/molecules/card/Card.tsx +4 -0
  156. package/src/molecules/forms/form-control/FormControl.stories.tsx +1 -1
  157. package/src/molecules/forms/input-tags/InputTags.tsx +1 -1
  158. package/src/molecules/forms/input-tags/components/ChoicesTags.stories.tsx +1 -1
  159. package/src/molecules/forms/input-tags/components/ReactTags.stories.tsx +1 -1
  160. package/src/molecules/forms/input-text/InputText.stories.tsx +2 -2
  161. package/src/molecules/forms/select/components/ChoicesSelect.stories.tsx +2 -2
  162. package/src/molecules/forms/select/components/HtmlSelect.stories.tsx +2 -2
  163. package/src/molecules/forms/select/components/ReactSelect.stories.tsx +2 -2
  164. package/src/molecules/loader/Loader.stories.tsx +1 -1
  165. package/src/molecules/modal/Modal.stories.tsx +1 -1
  166. package/src/molecules/pagination/Pagination.stories.tsx +1 -8
  167. package/src/molecules/pagination/Pagination.tsx +0 -1
  168. package/src/molecules/table/Table.stories.tsx +36 -3
  169. package/src/molecules/table/Table.tsx +12 -6
  170. package/src/molecules/table/components/DefaultCellOperations.tsx +13 -7
  171. package/src/molecules/table/components/DefaultOperationButton.tsx +5 -4
  172. package/src/molecules/table/filters/SelectFilter.tsx +1 -1
  173. package/src/molecules/table/hooks/useTable.tsx +5 -5
  174. package/src/molecules/tabs/Tab.tsx +106 -0
  175. package/src/molecules/tabs/TabList.tsx +37 -0
  176. package/src/molecules/tabs/TabPanel.tsx +37 -0
  177. package/src/molecules/tabs/Tabs.spec.tsx +126 -73
  178. package/src/molecules/tabs/Tabs.stories.tsx +298 -65
  179. package/src/molecules/tabs/Tabs.tsx +10 -81
  180. package/src/molecules/tabs/TabsBody.tsx +11 -0
  181. package/src/molecules/tabs/TabsLegacy.stories.tsx +103 -0
  182. package/src/molecules/tabs/TabsLegacy.tsx +84 -0
  183. package/src/molecules/tabs/all.ts +5 -0
  184. package/src/molecules/tabs/context/TabControl.tsx +166 -0
  185. package/src/molecules/tabs/hooks/tabControl.spec.tsx +388 -0
  186. package/src/molecules/tabs/hooks/tabControl.ts +52 -0
  187. package/src/organisms/__fixtures__/form-firstname.fixture.json +1 -0
  188. package/src/organisms/__fixtures__/form.fixture.json +1 -0
  189. package/src/organisms/form/Form.stories.tsx +94 -118
  190. package/src/organisms/form/access/FormAccess.stories.tsx +2 -2
  191. package/src/organisms/form/actions/FormAction.stories.tsx +422 -0
  192. package/src/organisms/form/builder/FormBuilder.stories.tsx +4 -1
  193. package/src/organisms/form/builder/FormEdit.stories.tsx +1 -1
  194. package/src/organisms/form/builder/FormEdit.tsx +7 -1
  195. package/src/organisms/form/builder/useFormBuilder.ts +5 -1
  196. package/src/organisms/form/builder/useFormEdit.ts +1 -1
  197. package/src/organisms/form/exports/FormExport.stories.tsx +71 -0
  198. package/src/organisms/form/exports/FormExport.tsx +58 -0
  199. package/src/organisms/form/preview/FormPreview.stories.tsx +61 -0
  200. package/src/organisms/form/preview/FormPreview.tsx +21 -0
  201. package/src/organisms/modal/RemoveModal.stories.tsx +1 -1
  202. package/src/organisms/table/actions/ActionsTable.stories.tsx +38 -36
  203. package/src/organisms/table/submissions/SubmissionsTable.stories.tsx +103 -57
  204. package/src/organisms/table/submissions/SubmissionsTable.tsx +10 -4
  205. package/src/organisms/views/FormViews.stories.tsx +224 -0
  206. package/src/organisms/views/FormViews.tsx +146 -0
  207. package/vite.config.mts +2 -2
  208. package/dist/organisms/form/action/FormAction.js.map +0 -1
  209. package/src/organisms/form/action/FormAction.stories.tsx +0 -364
  210. package/tsconfig.app.json +0 -11
  211. package/tsconfig.json +0 -21
  212. package/tsconfig.node.json +0 -13
  213. package/tsconfig.spec.json +0 -14
  214. /package/dist/organisms/form/{action → actions}/FormAction.d.ts +0 -0
  215. /package/src/organisms/form/{action → actions}/FormAction.tsx +0 -0
@@ -1,92 +1,21 @@
1
1
  import classnames from "classnames";
2
- import { PropsWithChildren } from "react";
2
+ import type { CSSProperties, PropsWithChildren } from "react";
3
3
 
4
- import { iconClass } from "../../utils/iconClass";
5
-
6
- export function ButtonTab({ icon, back, onClick, isActive, reverse, children, className, after }: PropsWithChildren<any>) {
7
- return (
8
- <div
9
- title={"button-wrapper"}
10
- className={classnames("tw-tabs__button-wrapper", isActive ? "-active" : "", back ? "-back" : "", className)}
11
- >
12
- <button
13
- title={"button-tab"}
14
- className={classnames("tw-tabs__button", reverse ? "-reverse" : "", isActive ? "-active" : "", back ? "-back" : "")}
15
- onClick={onClick}
16
- >
17
- {icon && <i className={classnames(iconClass(undefined, icon), "tw-tabs__button-icon")} />}
18
- <span className={"tw-tabs__button-label"}>{children}</span>
19
- {after}
20
- </button>
21
- <div className={classnames("tw-tabs__button-border", isActive ? "-active" : "")} />
22
- </div>
23
- );
24
- }
25
-
26
- export interface TabsItemProps extends Record<string, any> {
27
- label?: string;
28
- icon?: string;
29
- }
4
+ import { registerComponent } from "../../registries/components.js";
5
+ import { TabsProvider } from "./context/TabControl.js";
30
6
 
31
7
  export interface TabsProps extends Record<string, any> {
32
- headerChildren?: any;
33
- AddButton?: any;
34
- current?: TabsItemProps;
35
- items?: TabsItemProps[];
36
- style?: any;
8
+ style?: CSSProperties;
37
9
  className?: string;
38
- reverse?: boolean;
39
- Button?: any;
40
- onClick?: (item: TabsItemProps) => void;
41
- i18n?: (f: string) => string;
10
+ selected?: number;
42
11
  }
43
12
 
44
- export function Tabs({
45
- style,
46
- current,
47
- items = [],
48
- children,
49
- HeaderChildren,
50
- AddButton,
51
- Button = ButtonTab,
52
- className,
53
- onClick,
54
- i18n = (f) => f,
55
- ...additionalProps
56
- }: PropsWithChildren<TabsProps>) {
13
+ export function Tabs({ style, selected, children, className }: PropsWithChildren<TabsProps>) {
57
14
  return (
58
- <div data-testid={"tabs-comp"} className={`tw-tabs ${className}`} style={style}>
59
- <div>
60
- <nav className='tw-tabs__header'>
61
- <div className='tw-tabs__header-wrapper'>
62
- <div className='tw-tabs__header-border' />
63
- {items
64
- .filter((item) => item.label || item.icon)
65
- .map((item, index) => {
66
- return (
67
- <Button
68
- key={index}
69
- back={item.back}
70
- isActive={current?.action === item.action}
71
- exact={item.exact}
72
- onClick={() => {
73
- onClick && onClick(item);
74
- }}
75
- {...additionalProps}
76
- {...item}
77
- >
78
- {i18n(item.label || "")}
79
- </Button>
80
- );
81
- })}
82
- {AddButton && <AddButton {...additionalProps} current={current} />}
83
- </div>
84
- </nav>
85
- {HeaderChildren && <HeaderChildren {...additionalProps} current={current} />}
86
- </div>
87
- <div title={"tab-body"} className={"tw-tabs__body"}>
88
- {children}
89
- </div>
15
+ <div data-testid={"Tabs"} className={classnames("tw-tabs", className)} style={style}>
16
+ <TabsProvider selected={selected}>{children}</TabsProvider>
90
17
  </div>
91
18
  );
92
19
  }
20
+
21
+ registerComponent("Tabs", Tabs);
@@ -0,0 +1,11 @@
1
+ import { registerComponent } from "../../registries/components.js";
2
+
3
+ export function TabsBody(props: React.PropsWithChildren<{}>) {
4
+ return (
5
+ <div title={"tabs-body"} data-testid={"TabsBody"} className={"tw-tabs__body"}>
6
+ {props.children}
7
+ </div>
8
+ );
9
+ }
10
+
11
+ registerComponent("TabsBody", TabsBody);
@@ -0,0 +1,103 @@
1
+ import "./all.js";
2
+
3
+ import { Meta, StoryObj } from "@storybook/react-vite";
4
+
5
+ import { TabsLegacy } from "./TabsLegacy.js";
6
+
7
+ /**
8
+ * TabsLegacy component.
9
+ *
10
+ * You can import this component and use it like:
11
+ *
12
+ * ```tsx
13
+ * import {Tabs} from "@tsed/react-formio/molecules/tabs/TabsLegacy";
14
+ * ```
15
+ *
16
+ * TabsLegacy component support DI container and can be used with custom component. Here is the list of components that you can override:
17
+ *
18
+ * - Tab
19
+ * - TabList
20
+ * - TabPanel
21
+ * - Tabs
22
+ * - TabsBody
23
+ *
24
+ * ```tsx
25
+ * function CustomTab() {
26
+ *
27
+ * }
28
+ *
29
+ * registerComponent("Tab", CustomTab);
30
+ * ```
31
+ */
32
+ export default {
33
+ title: "TabsLegacy",
34
+ component: TabsLegacy,
35
+ argTypes: {},
36
+ parameters: {},
37
+ render: (args: any) => {
38
+ return (
39
+ <div className={"border-gray-300 border-1 shadow"}>
40
+ <TabsLegacy {...args} i18n={(f) => f} />
41
+ </div>
42
+ );
43
+ }
44
+ } satisfies Meta<typeof TabsLegacy>;
45
+
46
+ type Story = StoryObj<typeof TabsLegacy>;
47
+
48
+ export const Sandbox: Story = {
49
+ args: {
50
+ items: [
51
+ {
52
+ action: "edit",
53
+ exact: true,
54
+ icon: "edit",
55
+ label: "Edit",
56
+ children: <div className='bg-red-100 p-5'>Edit</div>
57
+ },
58
+ {
59
+ action: "submissions",
60
+ exact: false,
61
+ icon: "data",
62
+ label: "Data",
63
+ children: <div className='bg-orange-100 p-5'>Data</div>
64
+ },
65
+ {
66
+ action: "preview",
67
+ exact: true,
68
+ icon: "test-tube",
69
+ label: "Preview",
70
+ children: <div className='bg-yellow-100 p-5'>Preview</div>
71
+ },
72
+ {
73
+ action: "actions",
74
+ exact: false,
75
+ icon: "paper-plane",
76
+ label: "Actions",
77
+ children: <div className='bg-green-100 p-5'>Actions</div>
78
+ },
79
+ {
80
+ action: "access",
81
+ exact: true,
82
+ icon: "lock",
83
+ label: "Access",
84
+ children: <div className='bg-blue-100 p-5'>Access</div>
85
+ },
86
+ {
87
+ action: "export",
88
+ exact: true,
89
+ icon: "download",
90
+ label: "Export",
91
+ children: <div className='bg-purple-100 p-5'>Export</div>
92
+ },
93
+ {
94
+ action: "delete",
95
+ exact: true,
96
+ icon: "trash",
97
+ label: "Delete",
98
+ roles: ["administrator", "owner"],
99
+ children: <div className='bg-gray-100 p-5'>Trash</div>
100
+ }
101
+ ]
102
+ }
103
+ };
@@ -0,0 +1,84 @@
1
+ import "./all.js";
2
+
3
+ import { CSSProperties, ReactNode } from "react";
4
+
5
+ import { getComponent } from "../../registries/components.js";
6
+ import type { Tab as DefaultTab } from "./Tab.js";
7
+ import type { TabList as DefaultTabList } from "./TabList.js";
8
+ import type { TabPanel as DefaultTabPanel } from "./TabPanel.js";
9
+ import type { Tabs as DefaultTabs } from "./Tabs.js";
10
+ import type { TabsBody as DefaultTabsBody } from "./TabsBody.js";
11
+
12
+ export interface TabsItemProps extends Record<string, any> {
13
+ label?: string;
14
+ icon?: string;
15
+ children?: ReactNode;
16
+ }
17
+
18
+ export interface TabsLegacyProps extends Record<string, any> {
19
+ AddButton?: any;
20
+ current?: TabsItemProps;
21
+ items?: TabsItemProps[];
22
+ style?: CSSProperties;
23
+ className?: string;
24
+ reverse?: boolean;
25
+ onClick?: (item: TabsItemProps) => void;
26
+ i18n?: (f: string) => string;
27
+ }
28
+
29
+ export function TabsLegacy({
30
+ style,
31
+ current,
32
+ items = [],
33
+ HeaderChildren,
34
+ AddButton,
35
+ className,
36
+ onClick,
37
+ i18n = (f) => f,
38
+ reverse,
39
+ after,
40
+ ...additionalProps
41
+ }: TabsLegacyProps) {
42
+ const Tab = getComponent<typeof DefaultTab>("Tab");
43
+ const TabsBody = getComponent<typeof DefaultTabsBody>("TabsBody");
44
+ const TabList = getComponent<typeof DefaultTabList>("TabList");
45
+ const TabPanel = getComponent<typeof DefaultTabPanel>("TabPanel");
46
+ const Tabs = getComponent<typeof DefaultTabs>("Tabs");
47
+ const tabs = items.filter((item) => item.label || item.icon);
48
+
49
+ return (
50
+ <Tabs className={className} style={style}>
51
+ <div>
52
+ <TabList>
53
+ {tabs.map((item, index) => {
54
+ return (
55
+ <Tab
56
+ key={index}
57
+ onClick={() => {
58
+ onClick && onClick(item);
59
+ }}
60
+ icon={item.icon}
61
+ value={index}
62
+ className={reverse ? "-reverse" : ""}
63
+ after={after}
64
+ >
65
+ {i18n(item.label || "")}
66
+ </Tab>
67
+ );
68
+ })}
69
+ {AddButton && <AddButton {...additionalProps} current={current} />}
70
+ </TabList>
71
+ {HeaderChildren && <HeaderChildren {...additionalProps} current={current} />}
72
+ </div>
73
+ <TabsBody>
74
+ {tabs.map((item, index) => {
75
+ return (
76
+ <TabPanel key={index} value={index}>
77
+ {item.children || item.content}
78
+ </TabPanel>
79
+ );
80
+ })}
81
+ </TabsBody>
82
+ </Tabs>
83
+ );
84
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./Tab";
2
+ export * from "./TabList";
3
+ export * from "./TabPanel";
4
+ export * from "./Tabs";
5
+ export * from "./TabsBody";
@@ -0,0 +1,166 @@
1
+ "use client";
2
+
3
+ import { createContext, type Dispatch, type PropsWithChildren, type RefObject, useCallback, useId, useReducer } from "react";
4
+
5
+ type RefTab<T extends HTMLElement = HTMLElement> = RefObject<T>;
6
+ type RefTabs<T extends HTMLElement = HTMLElement> = Map<number, RefTab<T>>;
7
+
8
+ type TabsUpdateAction = {
9
+ type: "update";
10
+ payload: number;
11
+ };
12
+
13
+ type TabsRegisterAction<T extends HTMLElement = HTMLElement> = {
14
+ type: "register";
15
+ payload: { value: number; ref: RefObject<T> };
16
+ };
17
+
18
+ type TabsUnregisterAction = {
19
+ type: "unregister";
20
+ payload: { value: number };
21
+ };
22
+
23
+ type TabsAction<T extends HTMLElement = HTMLElement> =
24
+ | { type: "start" | "end" | "previous" | "next" }
25
+ | TabsUpdateAction
26
+ | TabsRegisterAction<T>
27
+ | TabsUnregisterAction;
28
+
29
+ interface TabsState<T extends HTMLElement = HTMLElement> {
30
+ uid: string;
31
+ value: number;
32
+ refs: RefTabs<T>;
33
+ }
34
+
35
+ interface TabControl<T extends HTMLElement = HTMLElement> extends TabsState<T> {
36
+ uid: string;
37
+ value: number;
38
+ refs: RefTabs<T>;
39
+ dispatch: Dispatch<TabsAction>;
40
+ register: (value: number, ref: RefTab<T>) => void;
41
+ unregister: (value: number) => void;
42
+ }
43
+
44
+ function next(state: TabsState) {
45
+ const keys = [...state.refs.keys()];
46
+ const index = keys.findIndex((value) => value === state.value);
47
+ const nextIndex = (index + 1) % keys.length;
48
+
49
+ return { ...state, value: keys[nextIndex] };
50
+ }
51
+
52
+ function previous(state: TabsState) {
53
+ const keys = [...state.refs.keys()];
54
+ const index = keys.findIndex((value) => value === state.value);
55
+ const previousIndex = (index - 1 + keys.length) % keys.length;
56
+
57
+ return { ...state, value: keys[previousIndex] };
58
+ }
59
+
60
+ function start(state: TabsState) {
61
+ const keys = [...state.refs.keys()];
62
+ const firstIndex = keys[0];
63
+
64
+ return {
65
+ ...state,
66
+ value: firstIndex
67
+ };
68
+ }
69
+
70
+ function end(state: TabsState) {
71
+ const keys = [...state.refs.keys()];
72
+ const lastIndex = keys[keys.length - 1];
73
+
74
+ return {
75
+ ...state,
76
+ value: lastIndex
77
+ };
78
+ }
79
+
80
+ function unregister(state: TabsState, action: TabsUnregisterAction) {
81
+ const deletedRefs = new Map(state.refs);
82
+ deletedRefs.delete(action.payload.value);
83
+
84
+ return {
85
+ ...state,
86
+ refs: deletedRefs
87
+ };
88
+ }
89
+
90
+ function register(state: TabsState, action: TabsRegisterAction) {
91
+ return {
92
+ ...state,
93
+ refs: new Map(state.refs).set(action.payload.value, action.payload.ref)
94
+ };
95
+ }
96
+
97
+ function update(state: TabsState, action: TabsUpdateAction) {
98
+ return { ...state, value: action.payload };
99
+ }
100
+
101
+ const actions = {
102
+ next,
103
+ previous,
104
+ start,
105
+ end,
106
+ register,
107
+ unregister,
108
+ update
109
+ };
110
+
111
+ function tabsReducer(state: TabsState, action: TabsAction): TabsState {
112
+ if (action.type in actions) {
113
+ const actionFunction = actions[action.type as keyof typeof actions] as (state: TabsState, action: TabsAction) => TabsState;
114
+
115
+ return actionFunction(state, action);
116
+ }
117
+
118
+ return state;
119
+ }
120
+
121
+ export const TabControlContext = createContext<TabControl>({
122
+ uid: "",
123
+ value: 0,
124
+ refs: new Map(),
125
+ dispatch: () => {
126
+ console.warn("Tab Controller Context dispatch used outside of Provider");
127
+ },
128
+ register: () => {
129
+ console.warn("Tab Controller Context register used outside of Provider");
130
+ },
131
+ unregister: () => {
132
+ console.warn("Tab Controller Context unregister used outside of Provider");
133
+ }
134
+ });
135
+
136
+ TabControlContext.displayName = "TabControlContext";
137
+
138
+ export interface TabsProviderProps {
139
+ selected?: number;
140
+ /**
141
+ * The selected tab value
142
+ * @deprecated Min props as no effect on the Tabs component and will be removed in future versions
143
+ */
144
+ min?: number;
145
+
146
+ /**
147
+ * The selected tab value
148
+ * @deprecated Max props as no effect on the Tabs component and will be removed in future versions
149
+ */
150
+ max?: number;
151
+ }
152
+
153
+ export function TabsProvider({ selected = 0, children }: PropsWithChildren<TabsProviderProps>) {
154
+ const uid = useId();
155
+ const [state, dispatch] = useReducer(tabsReducer, { uid, value: selected, refs: new Map() });
156
+
157
+ const register = useCallback(<T extends HTMLElement>(value: number, ref: RefTab<T>) => {
158
+ dispatch({ type: "register", payload: { value, ref } });
159
+ }, []);
160
+
161
+ const unregister = useCallback((value: number) => {
162
+ dispatch({ type: "unregister", payload: { value } });
163
+ }, []);
164
+
165
+ return <TabControlContext.Provider value={{ ...state, dispatch, register, unregister }}>{children}</TabControlContext.Provider>;
166
+ }