@inventreedb/ui 0.11.2 → 1.4.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.
Files changed (158) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/.vite/manifest.json +92 -5
  3. package/dist/components/Boundary.js +16 -7
  4. package/dist/components/Boundary.js.map +1 -1
  5. package/dist/components/InvenTreeTable.js +4 -3
  6. package/dist/components/InvenTreeTable.js.map +1 -1
  7. package/dist/components/RowActions.js +3 -2
  8. package/dist/components/RowActions.js.map +1 -1
  9. package/dist/components/StylishText.d.ts +6 -0
  10. package/dist/components/StylishText.js +36 -0
  11. package/dist/components/StylishText.js.map +1 -0
  12. package/dist/components/nav/DetailDrawer.css.d.ts +1 -0
  13. package/dist/components/nav/DetailDrawer.css.js +6 -0
  14. package/dist/components/nav/DetailDrawer.css.js.map +1 -0
  15. package/dist/components/nav/DetailDrawer.d.ts +22 -0
  16. package/dist/components/nav/DetailDrawer.js +66 -0
  17. package/dist/components/nav/DetailDrawer.js.map +1 -0
  18. package/dist/enums/ApiEndpoints.d.ts +1 -0
  19. package/dist/enums/ApiEndpoints.js +1 -0
  20. package/dist/enums/ApiEndpoints.js.map +1 -1
  21. package/dist/enums/ModelInformation.js +1 -0
  22. package/dist/enums/ModelInformation.js.map +1 -1
  23. package/dist/enums/ModelType.d.ts +9 -0
  24. package/dist/enums/ModelType.js.map +1 -1
  25. package/dist/enums/Roles.d.ts +1 -0
  26. package/dist/enums/Roles.js +1 -0
  27. package/dist/enums/Roles.js.map +1 -1
  28. package/dist/functions/Events.js +4 -3
  29. package/dist/functions/Events.js.map +1 -1
  30. package/dist/functions/Navigation.js +5 -2
  31. package/dist/functions/Navigation.js.map +1 -1
  32. package/dist/functions/Plugins.js +4 -2
  33. package/dist/functions/Plugins.js.map +1 -1
  34. package/dist/hooks/MonitorBackgroundTask.js +10 -8
  35. package/dist/hooks/MonitorBackgroundTask.js.map +1 -1
  36. package/dist/hooks/MonitorDataOutput.js +4 -3
  37. package/dist/hooks/MonitorDataOutput.js.map +1 -1
  38. package/dist/hooks/UseFilterSet.js +7 -6
  39. package/dist/hooks/UseFilterSet.js.map +1 -1
  40. package/dist/hooks/UseTable.js +1 -1
  41. package/dist/index.d.ts +5 -1
  42. package/dist/index.js +8 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/node_modules/@mantine/hooks/esm/use-debounced-value/use-debounced-value.js +40 -15
  45. package/dist/node_modules/@mantine/hooks/esm/use-debounced-value/use-debounced-value.js.map +1 -1
  46. package/dist/node_modules/@mantine/hooks/esm/use-document-visibility/use-document-visibility.js +1 -1
  47. package/dist/node_modules/@mantine/hooks/esm/use-document-visibility/use-document-visibility.js.map +1 -1
  48. package/dist/node_modules/@mantine/hooks/esm/use-local-storage/create-storage.js +57 -62
  49. package/dist/node_modules/@mantine/hooks/esm/use-local-storage/create-storage.js.map +1 -1
  50. package/dist/node_modules/@mantine/hooks/esm/use-local-storage/use-local-storage.js.map +1 -1
  51. package/dist/node_modules/@mantine/hooks/esm/use-window-event/use-window-event.js +5 -3
  52. package/dist/node_modules/@mantine/hooks/esm/use-window-event/use-window-event.js.map +1 -1
  53. package/dist/node_modules/@mantine/hooks/esm/utils/random-id/random-id.js.map +1 -1
  54. package/dist/node_modules/@remix-run/router/dist/router.js +458 -0
  55. package/dist/node_modules/@remix-run/router/dist/router.js.map +1 -0
  56. package/dist/node_modules/@sentry/browser/build/npm/esm/prod/report-dialog.js +2 -2
  57. package/dist/node_modules/@sentry/browser/build/npm/esm/prod/report-dialog.js.map +1 -1
  58. package/dist/node_modules/@sentry/core/build/esm/scope.js +6 -5
  59. package/dist/node_modules/@sentry/core/build/esm/scope.js.map +1 -1
  60. package/dist/node_modules/@sentry/core/build/esm/utils/chain-and-copy-promiselike.js +1 -1
  61. package/dist/node_modules/@sentry/core/build/esm/utils/chain-and-copy-promiselike.js.map +1 -1
  62. package/dist/node_modules/@sentry/core/build/esm/utils/is.js +1 -1
  63. package/dist/node_modules/@sentry/core/build/esm/utils/is.js.map +1 -1
  64. package/dist/node_modules/@sentry/core/build/esm/utils/misc.js +1 -1
  65. package/dist/node_modules/@sentry/core/build/esm/utils/misc.js.map +1 -1
  66. package/dist/node_modules/@sentry/core/build/esm/utils/randomSafeContext.js +1 -1
  67. package/dist/node_modules/@sentry/core/build/esm/utils/randomSafeContext.js.map +1 -1
  68. package/dist/node_modules/@sentry/core/build/esm/utils/time.js +1 -1
  69. package/dist/node_modules/@sentry/core/build/esm/utils/time.js.map +1 -1
  70. package/dist/node_modules/@tabler/icons-react/dist/esm/createReactComponent.js +6 -0
  71. package/dist/node_modules/@tabler/icons-react/dist/esm/createReactComponent.js.map +1 -1
  72. package/dist/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.js +6 -0
  73. package/dist/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.js.map +1 -1
  74. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustments.js +6 -0
  75. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustments.js.map +1 -1
  76. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js +6 -0
  77. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowRight.js.map +1 -1
  78. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.js +6 -0
  79. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.js.map +1 -1
  80. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.js +14 -0
  81. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.js.map +1 -0
  82. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.js +6 -0
  83. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleCheck.js.map +1 -1
  84. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleX.js +6 -0
  85. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleX.js.map +1 -1
  86. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.js +6 -0
  87. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.js.map +1 -1
  88. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.js +6 -0
  89. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.js.map +1 -1
  90. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.js +6 -0
  91. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.js.map +1 -1
  92. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconExclamationCircle.js +6 -0
  93. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconExclamationCircle.js.map +1 -1
  94. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.js +6 -0
  95. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.js.map +1 -1
  96. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.js +6 -0
  97. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.js.map +1 -1
  98. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.js +6 -0
  99. package/dist/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.js.map +1 -1
  100. package/dist/node_modules/@tanstack/query-core/build/modern/focusManager.js +31 -20
  101. package/dist/node_modules/@tanstack/query-core/build/modern/focusManager.js.map +1 -1
  102. package/dist/node_modules/@tanstack/query-core/build/modern/onlineManager.js +27 -17
  103. package/dist/node_modules/@tanstack/query-core/build/modern/onlineManager.js.map +1 -1
  104. package/dist/node_modules/@tanstack/query-core/build/modern/queryObserver.js +179 -177
  105. package/dist/node_modules/@tanstack/query-core/build/modern/queryObserver.js.map +1 -1
  106. package/dist/node_modules/@tanstack/query-core/build/modern/timeoutManager.js +31 -21
  107. package/dist/node_modules/@tanstack/query-core/build/modern/timeoutManager.js.map +1 -1
  108. package/dist/node_modules/@tanstack/react-query/build/modern/errorBoundaryUtils.js +1 -1
  109. package/dist/node_modules/@tanstack/react-query/build/modern/errorBoundaryUtils.js.map +1 -1
  110. package/dist/node_modules/@tanstack/react-query/build/modern/suspense.js +1 -1
  111. package/dist/node_modules/@tanstack/react-query/build/modern/suspense.js.map +1 -1
  112. package/dist/node_modules/@tanstack/react-query/build/modern/useBaseQuery.js +7 -4
  113. package/dist/node_modules/@tanstack/react-query/build/modern/useBaseQuery.js.map +1 -1
  114. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +10 -1
  115. package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +1 -1
  116. package/dist/node_modules/react/cjs/react-jsx-runtime.production.js +10 -1
  117. package/dist/node_modules/react/cjs/react-jsx-runtime.production.js.map +1 -1
  118. package/dist/node_modules/react-router/dist/index.js +714 -0
  119. package/dist/node_modules/react-router/dist/index.js.map +1 -0
  120. package/dist/node_modules/react-router-dom/dist/index.js +536 -0
  121. package/dist/node_modules/react-router-dom/dist/index.js.map +1 -0
  122. package/dist/node_modules/zustand/esm/react/shallow.js +13 -0
  123. package/dist/node_modules/zustand/esm/react/shallow.js.map +1 -0
  124. package/dist/node_modules/zustand/esm/vanilla/shallow.js +57 -0
  125. package/dist/node_modules/zustand/esm/vanilla/shallow.js.map +1 -0
  126. package/dist/states/LocalLibState.d.ts +17 -0
  127. package/dist/states/LocalLibState.js +16 -0
  128. package/dist/states/LocalLibState.js.map +1 -0
  129. package/dist/states/StoredTableState.js +2 -1
  130. package/dist/states/StoredTableState.js.map +1 -1
  131. package/dist/states/types.d.ts +3 -0
  132. package/dist/types/Forms.d.ts +13 -6
  133. package/dist/types/Panel.d.ts +26 -0
  134. package/dist/types/Plugins.d.ts +14 -2
  135. package/dist/types/Plugins.js +2 -2
  136. package/dist/types/Plugins.js.map +1 -1
  137. package/dist/types/Rendering.d.ts +53 -0
  138. package/dist/types/Tables.d.ts +5 -1
  139. package/dist/ui.css +4 -0
  140. package/lib/components/Boundary.tsx +6 -3
  141. package/lib/components/RowActions.tsx +2 -2
  142. package/lib/components/StylishText.tsx +46 -0
  143. package/lib/components/nav/DetailDrawer.css.ts +6 -0
  144. package/lib/components/nav/DetailDrawer.tsx +108 -0
  145. package/lib/enums/ApiEndpoints.tsx +1 -0
  146. package/lib/enums/ModelInformation.tsx +1 -0
  147. package/lib/enums/ModelType.tsx +13 -0
  148. package/lib/enums/Roles.tsx +1 -0
  149. package/lib/hooks/UseFilterSet.tsx +8 -8
  150. package/lib/index.ts +16 -0
  151. package/lib/states/LocalLibState.tsx +23 -0
  152. package/lib/states/types.tsx +7 -0
  153. package/lib/types/Forms.tsx +13 -6
  154. package/lib/types/Panel.tsx +30 -0
  155. package/lib/types/Plugins.tsx +20 -1
  156. package/lib/types/Rendering.tsx +60 -0
  157. package/lib/types/Tables.tsx +5 -1
  158. package/package.json +20 -17
@@ -64,7 +64,7 @@ export type TableState = {
64
64
  */
65
65
  export type TableColumnProps<T = any> = {
66
66
  accessor?: string;
67
- title?: string;
67
+ title?: string | ReactNode;
68
68
  ordering?: string;
69
69
  sortable?: boolean;
70
70
  switchable?: boolean;
@@ -131,12 +131,14 @@ export type RowViewProps = RowAction & RowModelProps;
131
131
  * @param barcodeActions : any[] - List of barcode actions
132
132
  * @param tableFilters : TableFilter[] - List of custom filters
133
133
  * @param tableActions : any[] - List of custom action groups
134
+ * @param isRecordSelectable : (record: any, index: number) => boolean - Callback function to determine if a row is selectable
134
135
  * @param detailAction: boolean - Enable detail action for each row (default = true)
135
136
  * @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
136
137
  * @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
137
138
  * @param onRowClick : (record: any, index: number, event: any) => void - Callback function when a row is clicked
138
139
  * @param onCellClick : (event: any, record: any, index: number, column: any, columnIndex: number) => void - Callback function when a cell is clicked
139
140
  * @param modelType: ModelType - The model type for the table
141
+ * @param height: string | number - Height of the table (default = 'auto')
140
142
  * @param minHeight: number - Minimum height of the table (default 300px)
141
143
  * @param noHeader: boolean - Hide the table header
142
144
  */
@@ -160,6 +162,7 @@ export type InvenTreeTableProps<T = any> = {
160
162
  barcodeActions?: React.ReactNode[];
161
163
  tableFilters?: TableFilter[];
162
164
  tableActions?: React.ReactNode[];
165
+ isRecordSelectable?: (record: T, index: number) => boolean;
163
166
  rowExpansion?: DataTableRowExpansionProps<T>;
164
167
  dataFormatter?: (data: any) => any;
165
168
  rowActions?: (record: T) => RowAction[];
@@ -170,6 +173,7 @@ export type InvenTreeTableProps<T = any> = {
170
173
  rowStyle?: (record: T, index: number) => MantineStyleProp | undefined;
171
174
  modelField?: string;
172
175
  onCellContextMenu?: (record: T, event: any) => void;
176
+ height?: string | number;
173
177
  minHeight?: number;
174
178
  noHeader?: boolean;
175
179
  };
package/dist/ui.css ADDED
@@ -0,0 +1,4 @@
1
+ ._1ucptpx0 {
2
+ display: flex;
3
+ flex: 1;
4
+ }
@@ -1,5 +1,5 @@
1
1
  import { t } from '@lingui/core/macro';
2
- import { Alert } from '@mantine/core';
2
+ import { Alert, Stack } from '@mantine/core';
3
3
  import { ErrorBoundary, type FallbackRender } from '@sentry/react';
4
4
  import { IconExclamationCircle } from '@tabler/icons-react';
5
5
  import { type ReactNode, useCallback } from 'react';
@@ -11,9 +11,12 @@ export function DefaultFallback({
11
11
  <Alert
12
12
  color='red'
13
13
  icon={<IconExclamationCircle />}
14
- title={`${t`Error rendering component`}: ${title}`}
14
+ title={`INVE-E17: ${t`Error rendering component`}: ${title}`}
15
15
  >
16
- {t`An error occurred while rendering this component. Refer to the console for more information.`}
16
+ <Stack gap='xs'>
17
+ {t`An error occurred while rendering this component. Refer to the console for more information.`}
18
+ {t`Try reloading the page, or contact your administrator if the problem persists.`}
19
+ </Stack>
17
20
  </Alert>
18
21
  );
19
22
  }
@@ -139,8 +139,8 @@ export function RowActions({
139
139
  aria-label={`row-action-menu-${index ?? ''}`}
140
140
  onClick={openMenu}
141
141
  disabled={disabled}
142
- variant='subtle'
143
- color='gray'
142
+ variant='transparent'
143
+ size='sm'
144
144
  >
145
145
  <IconDots />
146
146
  </ActionIcon>
@@ -0,0 +1,46 @@
1
+ import {
2
+ type MantineSize,
3
+ Text,
4
+ darken,
5
+ getThemeColor,
6
+ useMantineTheme
7
+ } from '@mantine/core';
8
+ import { useMemo } from 'react';
9
+ import type { JSX } from 'react';
10
+
11
+ // Hook that memoizes the gradient color based on the primary color of the theme
12
+ const useThematicGradient = () => {
13
+ const theme = useMantineTheme();
14
+
15
+ const primary = useMemo(() => {
16
+ return getThemeColor(theme.primaryColor, theme);
17
+ }, [theme]);
18
+
19
+ const secondary = useMemo(() => darken(primary, 0.25), [primary]);
20
+
21
+ return useMemo(() => {
22
+ return { primary, secondary };
23
+ }, [primary, secondary]);
24
+ };
25
+
26
+ // A stylish text component that uses the primary color of the theme
27
+ export function StylishText({
28
+ children,
29
+ size
30
+ }: Readonly<{
31
+ children: JSX.Element | string;
32
+ size?: MantineSize;
33
+ }>) {
34
+ const { primary, secondary } = useThematicGradient();
35
+
36
+ return (
37
+ <Text
38
+ fw={700}
39
+ size={size ?? 'xl'}
40
+ variant='gradient'
41
+ gradient={{ from: primary.toString(), to: secondary.toString() }}
42
+ >
43
+ {children}
44
+ </Text>
45
+ );
46
+ }
@@ -0,0 +1,6 @@
1
+ import { style } from '@vanilla-extract/css';
2
+
3
+ export const flex = style({
4
+ display: 'flex',
5
+ flex: 1
6
+ });
@@ -0,0 +1,108 @@
1
+ import { ActionIcon, Divider, Drawer, Group, Stack, Text } from '@mantine/core';
2
+ import { IconChevronLeft } from '@tabler/icons-react';
3
+ import { useCallback, useMemo } from 'react';
4
+ import { Link, Route, Routes, useNavigate, useParams } from 'react-router-dom';
5
+ import type { To } from 'react-router-dom';
6
+
7
+ import type { UiSizeType } from '../../types/Core';
8
+
9
+ import { useShallow } from 'zustand/react/shallow';
10
+ import { useLocalLibState } from '../../states/LocalLibState';
11
+ import { StylishText } from '../StylishText';
12
+ import * as classes from './DetailDrawer.css';
13
+
14
+ /**
15
+ * @param title - drawer title
16
+ * @param position - drawer position
17
+ * @param renderContent - function used to render the drawer content
18
+ * @param urlPrefix - set an additional url segment, useful when multiple drawers are rendered on one page (e.g. "user/")
19
+ */
20
+ export interface DrawerProps {
21
+ title: string;
22
+ position?: 'right' | 'left';
23
+ renderContent: (id?: string) => React.ReactNode;
24
+ urlPrefix?: string;
25
+ size?: UiSizeType;
26
+ closeOnEscape?: boolean;
27
+ }
28
+
29
+ export function DetailDrawerComponent({
30
+ title,
31
+ position = 'right',
32
+ size,
33
+ closeOnEscape = true,
34
+ renderContent
35
+ }: Readonly<DrawerProps>) {
36
+ const navigate = useNavigate();
37
+ const { id } = useParams();
38
+
39
+ const content = renderContent(id);
40
+ const opened = useMemo(() => !!id && !!content, [id, content]);
41
+
42
+ const [detailDrawerStack, addDetailDrawer] = useLocalLibState(
43
+ useShallow((state) => [state.detailDrawerStack, state.addDetailDrawer])
44
+ );
45
+
46
+ return (
47
+ <Drawer
48
+ opened={opened}
49
+ onClose={() => {
50
+ navigate('../');
51
+ addDetailDrawer(false);
52
+ }}
53
+ position={position}
54
+ closeOnEscape={closeOnEscape}
55
+ size={size}
56
+ classNames={{ root: classes.flex, body: classes.flex }}
57
+ scrollAreaComponent={Stack}
58
+ title={
59
+ <Group>
60
+ {detailDrawerStack > 0 && (
61
+ <ActionIcon
62
+ variant='outline'
63
+ onClick={() => {
64
+ navigate(-1);
65
+ addDetailDrawer(-1);
66
+ }}
67
+ >
68
+ <IconChevronLeft />
69
+ </ActionIcon>
70
+ )}
71
+ <StylishText size='xl'>{title}</StylishText>
72
+ </Group>
73
+ }
74
+ >
75
+ <Stack gap={'xs'} className={classes.flex}>
76
+ <Divider />
77
+ {content}
78
+ </Stack>
79
+ </Drawer>
80
+ );
81
+ }
82
+
83
+ export function DetailDrawer(props: Readonly<DrawerProps>) {
84
+ return (
85
+ <Routes>
86
+ <Route path=':id?/' element={<DetailDrawerComponent {...props} />} />
87
+ </Routes>
88
+ );
89
+ }
90
+
91
+ export function DetailDrawerLink({
92
+ to,
93
+ text
94
+ }: Readonly<{ to: To; text: string }>) {
95
+ const addDetailDrawer = useLocalLibState(
96
+ useShallow((state) => state.addDetailDrawer)
97
+ );
98
+
99
+ const onNavigate = useCallback(() => {
100
+ addDetailDrawer(1);
101
+ }, [addDetailDrawer]);
102
+
103
+ return (
104
+ <Link to={to} onClick={onNavigate}>
105
+ <Text>{text}</Text>
106
+ </Link>
107
+ );
108
+ }
@@ -153,6 +153,7 @@ export enum ApiEndpoints {
153
153
  stock_merge = 'stock/merge/',
154
154
  stock_assign = 'stock/assign/',
155
155
  stock_status = 'stock/status/',
156
+ stock_convert = 'stock/:id/convert/',
156
157
  stock_install = 'stock/:id/install/',
157
158
  stock_uninstall = 'stock/:id/uninstall/',
158
159
  stock_serialize = 'stock/:id/serialize/',
@@ -186,6 +186,7 @@ export const ModelInformationDict: ModelDict = {
186
186
  label_multiple: () => t`Sales Order Shipments`,
187
187
  url_overview: '/sales/index/shipments',
188
188
  url_detail: '/sales/shipment/:pk/',
189
+ admin_url: '/order/salesordershipment/',
189
190
  api_endpoint: ApiEndpoints.sales_order_shipment_list,
190
191
  supports_barcode: true,
191
192
  icon: 'shipment'
@@ -38,3 +38,16 @@ export enum ModelType {
38
38
  selectionentry = 'selectionentry',
39
39
  error = 'error'
40
40
  }
41
+
42
+ export enum PluginPanelKey {
43
+ // settings / admin
44
+ admincenter = 'admincenter',
45
+ systemsettings = 'systemsettings',
46
+ usersettings = 'usersettings',
47
+ // generic
48
+ core = 'core',
49
+ // landing pages
50
+ purchasing = 'purchasing',
51
+ sales = 'sales',
52
+ manufacturing = 'manufacturing'
53
+ }
@@ -5,6 +5,7 @@ import { t } from '@lingui/core/macro';
5
5
  */
6
6
  export enum UserRoles {
7
7
  admin = 'admin',
8
+ bom = 'bom',
8
9
  build = 'build',
9
10
  part = 'part',
10
11
  part_category = 'part_category',
@@ -1,5 +1,5 @@
1
1
  import { useLocalStorage } from '@mantine/hooks';
2
- import { useCallback, useMemo } from 'react';
2
+ import { useCallback, useEffect, useMemo } from 'react';
3
3
  import type { FilterSetState, TableFilter } from '../types/Filters';
4
4
 
5
5
  export default function useFilterSet(
@@ -16,15 +16,15 @@ export default function useFilterSet(
16
16
  getInitialValueInEffect: false
17
17
  });
18
18
 
19
- const activeFilters: TableFilter[] = useMemo(() => {
19
+ useEffect(() => {
20
20
  if (storedFilters == null) {
21
- // If there are no stored filters, set initial values
22
- const filters = initialFilters || [];
23
- setStoredFilters(filters);
24
- return filters;
21
+ setStoredFilters(initialFilters || []);
25
22
  }
26
- return storedFilters || [];
27
- }, [storedFilters]);
23
+ }, [storedFilters, initialFilters, setStoredFilters]);
24
+
25
+ const activeFilters: TableFilter[] = useMemo(() => {
26
+ return storedFilters ?? initialFilters ?? [];
27
+ }, [storedFilters, initialFilters]);
28
28
 
29
29
  // Callback to clear all active filters from the table
30
30
  const clearActiveFilters = useCallback(() => {
package/lib/index.ts CHANGED
@@ -21,11 +21,18 @@ export type {
21
21
  StockAdjustmentFormsContext
22
22
  } from './types/Plugins';
23
23
 
24
+ export type {
25
+ PanelIndicatorType,
26
+ PanelType,
27
+ PanelGroupType
28
+ } from './types/Panel';
29
+
24
30
  export type {
25
31
  RowAction,
26
32
  RowViewProps,
27
33
  TableColumn,
28
34
  TableColumnProps,
35
+ TableState,
29
36
  InvenTreeTableProps,
30
37
  InvenTreeTableRenderProps
31
38
  } from './types/Tables';
@@ -131,8 +138,17 @@ export {
131
138
  type TableStateExtraProps
132
139
  } from './hooks/UseTable';
133
140
 
141
+ export {
142
+ type DrawerProps,
143
+ DetailDrawer,
144
+ DetailDrawerLink,
145
+ DetailDrawerComponent
146
+ } from './components/nav/DetailDrawer';
147
+ export { StylishText } from './components/StylishText';
148
+
134
149
  // State management
135
150
  export {
136
151
  type StoredTableStateProps,
137
152
  useStoredTableState
138
153
  } from './states/StoredTableState';
154
+ export { useLocalLibState } from './states/LocalLibState';
@@ -0,0 +1,23 @@
1
+ import { create } from 'zustand';
2
+ import { persist } from 'zustand/middleware';
3
+
4
+ export const useLocalLibState = create<LocalLibStateProps>()(
5
+ persist(
6
+ (set, get) => ({
7
+ detailDrawerStack: 0,
8
+ addDetailDrawer: (value) => {
9
+ set({
10
+ detailDrawerStack:
11
+ value === false ? 0 : get().detailDrawerStack + value
12
+ });
13
+ }
14
+ }),
15
+ {
16
+ name: 'session-settings-inventreedb_lib'
17
+ }
18
+ )
19
+ );
20
+ export interface LocalLibStateProps {
21
+ detailDrawerStack: number;
22
+ addDetailDrawer: (value: number | false) => void;
23
+ }
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { InstanceRenderInterface } from '../types/Rendering';
3
+
4
+ export type setRenderProps = (
5
+ model: string,
6
+ renderer: (props: Readonly<InstanceRenderInterface>) => ReactNode
7
+ ) => void;
@@ -37,7 +37,6 @@ export type ApiFormFieldHeader = {
37
37
  * - All other attributes are optional, and may be provided by the API
38
38
  * - However, they can be overridden by the user
39
39
  *
40
- * @param name : The name of the field
41
40
  * @param label : The label to display for the field
42
41
  * @param value : The value of the field
43
42
  * @param default : The default value of the field
@@ -46,16 +45,22 @@ export type ApiFormFieldHeader = {
46
45
  * @param api_url : The API endpoint to fetch data from (for related fields)
47
46
  * @param pk_field : The primary key field for the related field (default = "pk")
48
47
  * @param model : The model to use for related fields
48
+ * @param custom_model : Optional custom model name (plugins may register renderers for custom models)
49
+ * @param modelRenderer : Optional function to render the related model instance (for related fields)
49
50
  * @param filters : Optional API filters to apply to related fields
51
+ * @param child: Optional definition of a child field (for nested objects)
52
+ * @param children: Optional definitions of child fields (for nested objects with multiple fields)
50
53
  * @param required : Whether the field is required
51
- * @param allow_null: Whether the field allows null values
52
- * @param allow_blank: Whether the field allows blank values
54
+ * @param error : Optional error message to display
53
55
  * @param hidden : Whether the field is hidden
54
56
  * @param disabled : Whether the field is disabled
55
- * @param error : Optional error message to display
57
+ * @param allow_null: Whether the field allows null values
58
+ * @param allow_blank: Whether the field allows blank values
56
59
  * @param exclude : Whether to exclude the field from the submitted data
60
+ * @param read_only : Whether the field is read-only
57
61
  * @param placeholder : The placeholder text to display
58
62
  * @param placeholderAutofill: Whether to allow auto-filling of the placeholder value
63
+ * @param addCreateFields : Fields to display when creating a new related object (for related fields)
59
64
  * @param description : The description to display for the field
60
65
  * @param preFieldContent : Content to render before the field
61
66
  * @param postFieldContent : Content to render after the field
@@ -63,11 +68,11 @@ export type ApiFormFieldHeader = {
63
68
  * @param rightSection : Content to render in the right section of the field
64
69
  * @param autoFill: Whether to automatically fill the field with data from the API
65
70
  * @param autoFillFilters: Optional filters to apply when auto-filling the field
71
+ * @param adjustValue : Callback function to adjust the value of the field before it is sent to the API
66
72
  * @param onValueChange : Callback function to call when the field value changes
67
73
  * @param adjustFilters : Callback function to adjust the filters for a related field before a query is made
68
- * @param adjustValue : Callback function to adjust the value of the field before it is sent to the API
69
74
  * @param addRow : Callback function to add a new row to a table field
70
- * @param onKeyDown : Callback function to get which key was pressed in the form to handle submission on enter
75
+ * @param headers : Optional definitions of table headers (for table fields)
71
76
  * @param singleFetchFunction : Optional function to fetch a single value for this field (used for fetching the initial value when editing an existing object)
72
77
  */
73
78
  export type ApiFormFieldType = {
@@ -97,6 +102,7 @@ export type ApiFormFieldType = {
97
102
  api_url?: string;
98
103
  pk_field?: string;
99
104
  model?: ModelType;
105
+ custom_model?: string;
100
106
  modelRenderer?: (instance: any) => ReactNode;
101
107
  filters?: any;
102
108
  child?: ApiFormFieldType;
@@ -114,6 +120,7 @@ export type ApiFormFieldType = {
114
120
  placeholderAutofill?: boolean;
115
121
  placeholderWarningCompare?: string | number;
116
122
  placeholderWarning?: string;
123
+ addCreateFields?: ApiFormFieldSet;
117
124
  description?: string;
118
125
  preFieldContent?: JSX.Element;
119
126
  postFieldContent?: JSX.Element;
@@ -0,0 +1,30 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ // The type of indicator dot to be shown against a panel
4
+ export type PanelIndicatorType = 'info' | 'warning' | 'danger' | null;
5
+
6
+ /**
7
+ * Type used to specify a single panel in a panel group
8
+ */
9
+ export type PanelType = {
10
+ name: string;
11
+ label: string;
12
+ controls?: ReactNode;
13
+ icon?: ReactNode;
14
+ notification_dot?: PanelIndicatorType | (() => Promise<PanelIndicatorType>);
15
+ content?: ReactNode;
16
+ hidden?: boolean;
17
+ disabled?: boolean;
18
+ showHeadline?: boolean;
19
+ supportsDirty?: boolean;
20
+ };
21
+
22
+ /**
23
+ * Type used to specify a group of panels
24
+ */
25
+ export type PanelGroupType = {
26
+ id: string;
27
+ label: string;
28
+ panelIDs?: string[];
29
+ panels?: PanelType[];
30
+ };
@@ -2,16 +2,24 @@ import type { I18n } from '@lingui/core';
2
2
  import type { MantineColorScheme, MantineTheme } from '@mantine/core';
3
3
  import type { QueryClient } from '@tanstack/react-query';
4
4
  import type { AxiosInstance } from 'axios';
5
+ import type { JSX } from 'react';
5
6
  import type { NavigateFunction } from 'react-router-dom';
6
7
  import type { ModelDict } from '../enums/ModelInformation';
7
8
  import type { ModelType } from '../enums/ModelType';
9
+ import type { setRenderProps } from '../states/types';
8
10
  import type {
9
11
  ApiFormModalProps,
12
+ ApiFormProps,
10
13
  BulkEditApiFormModalProps,
11
14
  StockOperationProps
12
15
  } from './Forms';
13
16
  import type { UseModalReturn } from './Modals';
14
- import type { RenderInstanceProps } from './Rendering';
17
+ import type {
18
+ RemoteInstanceProps,
19
+ RenderInlineModelProps,
20
+ RenderInstanceProps,
21
+ ThumbnailProps
22
+ } from './Rendering';
15
23
  import type { SettingsStateProps } from './Settings';
16
24
  import type { InvenTreeTableRenderProps } from './Tables';
17
25
  import type { UserStateProps } from './User';
@@ -46,6 +54,7 @@ export type InvenTreeFormsContext = {
46
54
  create: (props: ApiFormModalProps) => UseModalReturn;
47
55
  delete: (props: ApiFormModalProps) => UseModalReturn;
48
56
  edit: (props: ApiFormModalProps) => UseModalReturn;
57
+ editApiForm: (props: { id?: string; props: ApiFormProps }) => React.ReactNode;
49
58
  stockActions: StockAdjustmentFormsContext;
50
59
  };
51
60
 
@@ -97,6 +106,13 @@ export type InvenTreePluginContext = {
97
106
  globalSettings: SettingsStateProps;
98
107
  modelInformation: ModelDict;
99
108
  renderInstance: (props: Readonly<RenderInstanceProps>) => React.ReactNode;
109
+ renderRemoteInstance: (
110
+ props: Readonly<RemoteInstanceProps>
111
+ ) => React.ReactNode;
112
+ renderInlineModel: (
113
+ props: Readonly<RenderInlineModelProps>
114
+ ) => React.ReactNode;
115
+ thumbnail: (props: Readonly<ThumbnailProps>) => JSX.Element;
100
116
  host: string;
101
117
  i18n: I18n;
102
118
  locale: string;
@@ -104,6 +120,9 @@ export type InvenTreePluginContext = {
104
120
  theme: MantineTheme;
105
121
  colorScheme: MantineColorScheme;
106
122
  forms: InvenTreeFormsContext;
123
+ stateFnc: {
124
+ setRenderer: setRenderProps;
125
+ };
107
126
  tables: InvenTreeTablesContext<any>;
108
127
  importer: ImporterDrawerContext;
109
128
  model?: ModelType | string;
@@ -1,4 +1,11 @@
1
+ import type {
2
+ QueryObserverResult,
3
+ UseQueryResult
4
+ } from '@tanstack/react-query';
5
+ import type { ReactNode } from 'react';
6
+ import type { ApiEndpoints } from '..';
1
7
  import type { ModelType } from '../enums/ModelType';
8
+ import type { PathParams } from './Core';
2
9
 
3
10
  /**
4
11
  * Interface for rendering a model instance.
@@ -22,4 +29,57 @@ export type ModelRendererDict = EnumDictionary<
22
29
 
23
30
  export type RenderInstanceProps = {
24
31
  model: ModelType | undefined;
32
+ custom_model?: string;
25
33
  } & InstanceRenderInterface;
34
+
35
+ export interface UseInstanceResult {
36
+ instance: any;
37
+ setInstance: (instance: any) => void;
38
+ refreshInstance: () => void;
39
+ refreshInstancePromise: () => Promise<QueryObserverResult<any, any>>;
40
+ instanceQuery: UseQueryResult;
41
+ isLoaded: boolean;
42
+ }
43
+
44
+ export interface useInstanceProps {
45
+ endpoint: ApiEndpoints;
46
+ pk?: string | number | undefined;
47
+ hasPrimaryKey?: boolean;
48
+ params?: any;
49
+ pathParams?: PathParams;
50
+ disabled?: boolean;
51
+ defaultValue?: any;
52
+ refetchOnMount?: boolean;
53
+ refetchOnWindowFocus?: boolean;
54
+ updateInterval?: number;
55
+ }
56
+
57
+ export interface RemoteInstanceProps {
58
+ model: ModelType;
59
+ modelUrl?: string;
60
+ modelRenderer?: (instance: any) => ReactNode;
61
+ pk: number;
62
+ }
63
+ export interface ThumbnailProps {
64
+ src?: string;
65
+ alt?: string;
66
+ size?: number;
67
+ text?: ReactNode;
68
+ align?: string;
69
+ link?: string;
70
+ hover?: boolean;
71
+ hoverSize?: number;
72
+ }
73
+
74
+ export interface RenderInlineModelProps {
75
+ primary: ReactNode;
76
+ secondary?: ReactNode;
77
+ showSecondary?: boolean;
78
+ prefix?: ReactNode;
79
+ suffix?: ReactNode;
80
+ image?: string;
81
+ labels?: string[];
82
+ url?: string;
83
+ navigate?: any;
84
+ tooltip?: string;
85
+ }
@@ -100,7 +100,7 @@ export type TableState = {
100
100
  */
101
101
  export type TableColumnProps<T = any> = {
102
102
  accessor?: string;
103
- title?: string;
103
+ title?: string | ReactNode;
104
104
  ordering?: string;
105
105
  sortable?: boolean;
106
106
  switchable?: boolean;
@@ -173,12 +173,14 @@ export type RowViewProps = RowAction & RowModelProps;
173
173
  * @param barcodeActions : any[] - List of barcode actions
174
174
  * @param tableFilters : TableFilter[] - List of custom filters
175
175
  * @param tableActions : any[] - List of custom action groups
176
+ * @param isRecordSelectable : (record: any, index: number) => boolean - Callback function to determine if a row is selectable
176
177
  * @param detailAction: boolean - Enable detail action for each row (default = true)
177
178
  * @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
178
179
  * @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
179
180
  * @param onRowClick : (record: any, index: number, event: any) => void - Callback function when a row is clicked
180
181
  * @param onCellClick : (event: any, record: any, index: number, column: any, columnIndex: number) => void - Callback function when a cell is clicked
181
182
  * @param modelType: ModelType - The model type for the table
183
+ * @param height: string | number - Height of the table (default = 'auto')
182
184
  * @param minHeight: number - Minimum height of the table (default 300px)
183
185
  * @param noHeader: boolean - Hide the table header
184
186
  */
@@ -202,6 +204,7 @@ export type InvenTreeTableProps<T = any> = {
202
204
  barcodeActions?: React.ReactNode[];
203
205
  tableFilters?: TableFilter[];
204
206
  tableActions?: React.ReactNode[];
207
+ isRecordSelectable?: (record: T, index: number) => boolean;
205
208
  rowExpansion?: DataTableRowExpansionProps<T>;
206
209
  dataFormatter?: (data: any) => any;
207
210
  rowActions?: (record: T) => RowAction[];
@@ -212,6 +215,7 @@ export type InvenTreeTableProps<T = any> = {
212
215
  rowStyle?: (record: T, index: number) => MantineStyleProp | undefined;
213
216
  modelField?: string;
214
217
  onCellContextMenu?: (record: T, event: any) => void;
218
+ height?: string | number;
215
219
  minHeight?: number;
216
220
  noHeader?: boolean;
217
221
  };