@trackunit/react-table 0.0.84 → 0.0.85
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/index.cjs.js +122 -42
- package/index.esm.js +125 -45
- package/package.json +4 -4
- package/src/ActionSheet/ActionContainerAndOverflow.d.ts +19 -0
- package/src/ActionSheet/ActionSheet.d.ts +1 -1
- package/src/ActionSheet/ActionSheet.variants.d.ts +1 -0
- package/src/ActionSheet/ActionSheetElementUtils.d.ts +46 -0
- package/src/ActionSheet/Actions.d.ts +1 -0
package/index.cjs.js
CHANGED
|
@@ -6,8 +6,8 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
var i18nLibraryTranslation = require('@trackunit/i18n-library-translation');
|
|
7
7
|
var reactComponents = require('@trackunit/react-components');
|
|
8
8
|
var React = require('react');
|
|
9
|
-
var reactRouterDom = require('react-router-dom');
|
|
10
9
|
var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
|
|
10
|
+
var reactRouterDom = require('react-router-dom');
|
|
11
11
|
var reactTableBaseComponents = require('@trackunit/react-table-base-components');
|
|
12
12
|
var reactDom = require('react-dom');
|
|
13
13
|
var reactFormComponents = require('@trackunit/react-form-components');
|
|
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
|
|
|
34
34
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
35
35
|
|
|
36
36
|
var defaultTranslations = {
|
|
37
|
-
"table.actionsheet.selected": "selected",
|
|
37
|
+
"table.actionsheet.selected": "{{count}} selected",
|
|
38
38
|
"layout.actions.reset": "Reset",
|
|
39
39
|
"table.pagination.of": "of {{count}}",
|
|
40
40
|
"table.pagination.full": "Showing {{count}} of {{total}} results",
|
|
@@ -106,6 +106,40 @@ const setupLibraryTranslations = () => {
|
|
|
106
106
|
i18nLibraryTranslation.registerTranslations(translations);
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
const cvaActionSheet = cssClassVarianceUtilities.cvaMerge([
|
|
110
|
+
"w-[760px]",
|
|
111
|
+
"max-w-[80%]",
|
|
112
|
+
"animate-fade-in-fast",
|
|
113
|
+
"grid",
|
|
114
|
+
"grid-rows-2",
|
|
115
|
+
"grid-cols-[min-content,1fr,min-content]",
|
|
116
|
+
"sm:grid-cols-[min-content,1fr,min-content]",
|
|
117
|
+
"sm:grid-rows-1",
|
|
118
|
+
"p-2",
|
|
119
|
+
"bg-blue-600",
|
|
120
|
+
"gap-1",
|
|
121
|
+
"rounded-2xl",
|
|
122
|
+
"h-min",
|
|
123
|
+
"items-center",
|
|
124
|
+
"z-top",
|
|
125
|
+
"shadow-2xl",
|
|
126
|
+
"fixed",
|
|
127
|
+
"bottom-24",
|
|
128
|
+
"left-1/2",
|
|
129
|
+
"-translate-x-1/2",
|
|
130
|
+
]);
|
|
131
|
+
const cvaActionContainerAndOverflow = cssClassVarianceUtilities.cvaMerge([
|
|
132
|
+
"col-span-2",
|
|
133
|
+
"flex",
|
|
134
|
+
"flex-row-reverse",
|
|
135
|
+
"flex-nowrap",
|
|
136
|
+
"justify-end",
|
|
137
|
+
"gap-2",
|
|
138
|
+
"overflow-hidden",
|
|
139
|
+
"sm:col-span-1",
|
|
140
|
+
"sm:flex-row",
|
|
141
|
+
]);
|
|
142
|
+
|
|
109
143
|
/******************************************************************************
|
|
110
144
|
Copyright (c) Microsoft Corporation.
|
|
111
145
|
|
|
@@ -133,31 +167,93 @@ function __rest(s, e) {
|
|
|
133
167
|
return t;
|
|
134
168
|
}
|
|
135
169
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
"shadow-md",
|
|
148
|
-
"fixed",
|
|
149
|
-
"bottom-24",
|
|
150
|
-
"left-1/2",
|
|
151
|
-
"-translate-x-1/2",
|
|
152
|
-
]);
|
|
153
|
-
|
|
170
|
+
/**
|
|
171
|
+
* The button to show in the ActionSheet.
|
|
172
|
+
* Should not be used outside the ActionSheet component.
|
|
173
|
+
*
|
|
174
|
+
* @param {ActionButtonProps} props - The properties for the action button.
|
|
175
|
+
* @param {ActionModel} props.action - The action model defining what action to perform.
|
|
176
|
+
* @param {ReactNode} props.children - The children to render inside the button.
|
|
177
|
+
* @param {string} [props.id] - The optional ID for the button.
|
|
178
|
+
* @param {...any} [props.rest] - Any additional button properties.
|
|
179
|
+
* @returns {JSX.Element} - The action button component.
|
|
180
|
+
*/
|
|
154
181
|
const ActionButton = (_a) => {
|
|
155
|
-
var { action, children } = _a, rest = __rest(_a, ["action", "children"]);
|
|
182
|
+
var { action, children, id } = _a, rest = __rest(_a, ["action", "children", "id"]);
|
|
156
183
|
if (action.type === "route") {
|
|
157
|
-
return (jsxRuntime.jsx(reactComponents.Button, Object.assign({ renderAs: reactRouterDom.Link, to: action.url, variant: "transparent", color: "secondary" }, rest, { children: children })));
|
|
184
|
+
return (jsxRuntime.jsx(reactComponents.Button, Object.assign({ renderAs: reactRouterDom.Link, to: action.url, variant: "transparent", color: "secondary", id: id }, rest, { children: children })));
|
|
185
|
+
}
|
|
186
|
+
return (jsxRuntime.jsx(reactComponents.Button, Object.assign({ onClick: action.method, variant: "transparent", color: "secondary", id: id }, rest, { children: children })));
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Converts an action model to a MenuItem component.
|
|
190
|
+
* These should be shown in the more menu.
|
|
191
|
+
* Should not be used outside the ActionSheet component.
|
|
192
|
+
*
|
|
193
|
+
* @param {ActionModel} action - The action model to convert.
|
|
194
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
195
|
+
* @returns {JSX.Element} - The MenuItem component for the given action.
|
|
196
|
+
*/
|
|
197
|
+
const actionDataToMenuItem = (action, dataTestId) => {
|
|
198
|
+
const props = "url" in action
|
|
199
|
+
? {
|
|
200
|
+
dataTestId,
|
|
201
|
+
}
|
|
202
|
+
: {
|
|
203
|
+
id: action.id,
|
|
204
|
+
key: action.label,
|
|
205
|
+
dataTestId,
|
|
206
|
+
};
|
|
207
|
+
const item = (jsxRuntime.jsx(reactComponents.MenuItem, { props, onClick: "method" in action ? action.method : undefined, dataTestId: `${dataTestId}-action-label`, className: "flex justify-center", label: action.label, prefix: jsxRuntime.jsx(reactComponents.Icon, { name: action.icon, size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }) }, action.label));
|
|
208
|
+
if ("url" in action) {
|
|
209
|
+
return (jsxRuntime.jsx(reactRouterDom.Link, { id: action.id, to: action.url, children: item }, action.label));
|
|
158
210
|
}
|
|
159
|
-
return
|
|
211
|
+
return item;
|
|
160
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Converts an action model to an ActionButton component.
|
|
215
|
+
* These should be shown in the ActionSheet.
|
|
216
|
+
* Should not be used outside the ActionSheet component.
|
|
217
|
+
*
|
|
218
|
+
* @param {ActionModel} action - The action model to convert.
|
|
219
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
220
|
+
* @returns {JSX.Element} - The ActionButton component for the given action.
|
|
221
|
+
*/
|
|
222
|
+
const actionDataToActionButton = (action, dataTestId) => (jsxRuntime.jsxs(ActionButton, { action: action, dataTestId: action.label, className: "max-w-max flex-shrink-0", id: action.id, children: [jsxRuntime.jsx(reactComponents.Icon, { name: action.icon, color: "white", size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }), jsxRuntime.jsx(reactComponents.Text, { dataTestId: `${dataTestId}-action-label`, className: "!text-base text-white", children: action.label })] }, action.id));
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* `ActionContainerAndOverflow` renders a set of actions and a MoreMenu for overflow.
|
|
226
|
+
* It makes use of the `useOverflowItems` hook to determine which items should go into the overflow menu.
|
|
227
|
+
*
|
|
228
|
+
* @param {object} props - Props for the component.
|
|
229
|
+
* @param {ActionModel[]} props.actions - Array of action models to be rendered.
|
|
230
|
+
* @param {ReactElement<SidebarItemProps>[] | ReactElement<SidebarItemProps>} props.moreActions - Additional actions that can be rendered in the MoreMenu.
|
|
231
|
+
* @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
|
|
232
|
+
* @returns {ReactElement} The rendered component.
|
|
233
|
+
*/
|
|
234
|
+
const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
|
|
235
|
+
const children = React.useMemo(() => actions && actions.map(action => action && actionDataToActionButton(action, dataTestId)), [actions, dataTestId]);
|
|
236
|
+
const { overflowContainerRef, itemOverflowMap } = reactComponents.useOverflowItems({
|
|
237
|
+
children,
|
|
238
|
+
childUniqueIdentifierAttribute: "id",
|
|
239
|
+
threshold: 1,
|
|
240
|
+
});
|
|
241
|
+
const itemVisibilityClassName = (id) => {
|
|
242
|
+
if (itemOverflowMap[id]) {
|
|
243
|
+
return "invisible";
|
|
244
|
+
}
|
|
245
|
+
return "visible";
|
|
246
|
+
};
|
|
247
|
+
const overflowItemCount = Object.values(itemOverflowMap).filter(isOverflowing => isOverflowing).length;
|
|
248
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: cvaActionContainerAndOverflow(), ref: overflowContainerRef, children: React.Children.map(children, child => {
|
|
249
|
+
return React.cloneElement(child, {
|
|
250
|
+
className: `${child.props.className} ${itemVisibilityClassName(child.props.id)}`,
|
|
251
|
+
});
|
|
252
|
+
}) }), React.Children.count(moreActions) > 0 || overflowItemCount ? (jsxRuntime.jsx(reactComponents.MoreMenu, { popoverProps: { placement: "top-end" }, className: "p-0", iconButtonProps: { variant: "transparent", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, dataTestId: `${dataTestId}-more-menu`, children: jsxRuntime.jsxs(reactComponents.MenuList, { className: "relative -right-2", children: [moreActions ? moreActions : null, actions.map(action => {
|
|
253
|
+
return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
|
|
254
|
+
})] }) })) : null] }));
|
|
255
|
+
};
|
|
256
|
+
|
|
161
257
|
/**
|
|
162
258
|
* The Action Sheet appears when one or more items are selected from a table.
|
|
163
259
|
* It primarily accommodates 1-3 main actions that represent the most crucial and frequently accessed functions on the specific page.
|
|
@@ -168,25 +264,9 @@ const ActionButton = (_a) => {
|
|
|
168
264
|
*/
|
|
169
265
|
const ActionSheet = ({ actions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
|
|
170
266
|
const [t] = useTranslation();
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
React.useEffect(() => {
|
|
175
|
-
window.addEventListener("resize", wrapperSmallScreen);
|
|
176
|
-
return () => window.removeEventListener("resize", wrapperSmallScreen);
|
|
177
|
-
}, []);
|
|
178
|
-
const filteredActions = actions.filter(action => action !== undefined);
|
|
179
|
-
const actionsFilteredForScreenSize = smallScreen ? [filteredActions[0]] : filteredActions;
|
|
180
|
-
const moreActionsFilteredForScreenSize = smallScreen ? moreActions === null || moreActions === void 0 ? void 0 : moreActions.concat(filteredActions.slice(1)) : moreActions;
|
|
181
|
-
const actionDataToActionButton = (action, moreAction = false) => (jsxRuntime.jsxs(ActionButton, { action: action, dataTestId: action.label, className: "lg:mr-3", children: [jsxRuntime.jsx(reactComponents.Icon, { name: action.icon, color: moreAction ? "neutral" : "white", size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }), jsxRuntime.jsx(reactComponents.Text, { dataTestId: `${containerProps["data-testid"]}-action-label`, className: `${moreAction ? "text-inherit" : "!text-white"} !text-base`, children: action.label })] }, action.label));
|
|
182
|
-
const actionDataToMenuItem = (action) => {
|
|
183
|
-
const item = (jsxRuntime.jsx(reactComponents.MenuItem, { onClick: "method" in action ? action.method : undefined, dataTestId: `${containerProps["data-testid"]}-action-label`, label: action.label, className: "lg:mr-3", prefix: jsxRuntime.jsx(reactComponents.Icon, { name: action.icon, size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }) }, action.label));
|
|
184
|
-
if ("url" in action) {
|
|
185
|
-
return jsxRuntime.jsx(reactRouterDom.Link, { to: action.url, children: item });
|
|
186
|
-
}
|
|
187
|
-
return item;
|
|
188
|
-
};
|
|
189
|
-
return (jsxRuntime.jsxs("div", { className: cvaActionSheet({ className: containerProps.className }), "data-testid": containerProps["data-testid"], children: [jsxRuntime.jsx(reactComponents.IconButton, { icon: jsxRuntime.jsx(reactComponents.Icon, { name: "XMark", size: "small", color: "white", "data-testid": "close-icon" }), onClick: resetSelection, color: "secondary", variant: "transparent", circular: true, dataTestId: "XButton" }), jsxRuntime.jsxs(reactComponents.Text, { size: "large", className: "!lg:mr-28 !mr-4 w-max !text-white", children: [selections === null || selections === void 0 ? void 0 : selections.length, " ", t("table.actionsheet.selected")] }), actionsFilteredForScreenSize.map(action => action && actionDataToActionButton(action)), moreActionsFilteredForScreenSize && moreActionsFilteredForScreenSize.length > 0 && (jsxRuntime.jsx(reactComponents.MoreMenu, { popoverProps: { placement: "top-end" }, className: "p-0", iconButtonProps: { variant: "transparent", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, dataTestId: `${containerProps["data-testid"]}-more-menu`, children: jsxRuntime.jsx(reactComponents.MenuList, { className: "relative -right-2", children: moreActionsFilteredForScreenSize.map(action => actionDataToMenuItem(action)) }) }))] }));
|
|
267
|
+
return (jsxRuntime.jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsxRuntime.jsxs(reactComponents.Text, { size: "large", className: "border-primary-500 col-span-3 w-full border-b text-white sm:col-span-1 sm:w-max sm:border-0", children: [jsxRuntime.jsx(reactComponents.IconButton, { icon: jsxRuntime.jsx(reactComponents.Icon, { name: "XMark", size: "small", color: "white", "data-testid": "close-icon" }), onClick: resetSelection, color: "secondary", variant: "transparent", circular: true, dataTestId: "XButton" }), t("table.actionsheet.selected", { count: selections === null || selections === void 0 ? void 0 : selections.length })] }), jsxRuntime.jsx(ActionContainerAndOverflow, { dataTestId,
|
|
268
|
+
actions,
|
|
269
|
+
moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
|
|
190
270
|
};
|
|
191
271
|
|
|
192
272
|
/**
|
package/index.esm.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { jsxs,
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
|
|
3
|
-
import {
|
|
3
|
+
import { MenuItem, Icon, Text, Button, useOverflowItems, MoreMenu, MenuList, IconButton, Card, EmptyState, Spinner, Tooltip, Popover, PopoverTrigger, PopoverContent } from '@trackunit/react-components';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import {
|
|
6
|
-
import { Link } from 'react-router-dom';
|
|
5
|
+
import { useMemo, Children, cloneElement, useCallback, useEffect, useRef, createContext, memo as memo$2, isValidElement, useLayoutEffect, useContext, useState } from 'react';
|
|
7
6
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
7
|
+
import { Link } from 'react-router-dom';
|
|
8
8
|
import { TableRoot, Thead, Tr, Th, SortIndicator, ResizeHandle, Tbody, Td } from '@trackunit/react-table-base-components';
|
|
9
9
|
import { flushSync } from 'react-dom';
|
|
10
10
|
import { Toggle, RadioGroup, RadioItem } from '@trackunit/react-form-components';
|
|
11
11
|
import { SortOrder, validateStringAsAssetSortByProperty } from '@trackunit/react-core-contexts-api';
|
|
12
12
|
|
|
13
13
|
var defaultTranslations = {
|
|
14
|
-
"table.actionsheet.selected": "selected",
|
|
14
|
+
"table.actionsheet.selected": "{{count}} selected",
|
|
15
15
|
"layout.actions.reset": "Reset",
|
|
16
16
|
"table.pagination.of": "of {{count}}",
|
|
17
17
|
"table.pagination.full": "Showing {{count}} of {{total}} results",
|
|
@@ -83,6 +83,40 @@ const setupLibraryTranslations = () => {
|
|
|
83
83
|
registerTranslations(translations);
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
+
const cvaActionSheet = cvaMerge([
|
|
87
|
+
"w-[760px]",
|
|
88
|
+
"max-w-[80%]",
|
|
89
|
+
"animate-fade-in-fast",
|
|
90
|
+
"grid",
|
|
91
|
+
"grid-rows-2",
|
|
92
|
+
"grid-cols-[min-content,1fr,min-content]",
|
|
93
|
+
"sm:grid-cols-[min-content,1fr,min-content]",
|
|
94
|
+
"sm:grid-rows-1",
|
|
95
|
+
"p-2",
|
|
96
|
+
"bg-blue-600",
|
|
97
|
+
"gap-1",
|
|
98
|
+
"rounded-2xl",
|
|
99
|
+
"h-min",
|
|
100
|
+
"items-center",
|
|
101
|
+
"z-top",
|
|
102
|
+
"shadow-2xl",
|
|
103
|
+
"fixed",
|
|
104
|
+
"bottom-24",
|
|
105
|
+
"left-1/2",
|
|
106
|
+
"-translate-x-1/2",
|
|
107
|
+
]);
|
|
108
|
+
const cvaActionContainerAndOverflow = cvaMerge([
|
|
109
|
+
"col-span-2",
|
|
110
|
+
"flex",
|
|
111
|
+
"flex-row-reverse",
|
|
112
|
+
"flex-nowrap",
|
|
113
|
+
"justify-end",
|
|
114
|
+
"gap-2",
|
|
115
|
+
"overflow-hidden",
|
|
116
|
+
"sm:col-span-1",
|
|
117
|
+
"sm:flex-row",
|
|
118
|
+
]);
|
|
119
|
+
|
|
86
120
|
/******************************************************************************
|
|
87
121
|
Copyright (c) Microsoft Corporation.
|
|
88
122
|
|
|
@@ -110,31 +144,93 @@ function __rest(s, e) {
|
|
|
110
144
|
return t;
|
|
111
145
|
}
|
|
112
146
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"shadow-md",
|
|
125
|
-
"fixed",
|
|
126
|
-
"bottom-24",
|
|
127
|
-
"left-1/2",
|
|
128
|
-
"-translate-x-1/2",
|
|
129
|
-
]);
|
|
130
|
-
|
|
147
|
+
/**
|
|
148
|
+
* The button to show in the ActionSheet.
|
|
149
|
+
* Should not be used outside the ActionSheet component.
|
|
150
|
+
*
|
|
151
|
+
* @param {ActionButtonProps} props - The properties for the action button.
|
|
152
|
+
* @param {ActionModel} props.action - The action model defining what action to perform.
|
|
153
|
+
* @param {ReactNode} props.children - The children to render inside the button.
|
|
154
|
+
* @param {string} [props.id] - The optional ID for the button.
|
|
155
|
+
* @param {...any} [props.rest] - Any additional button properties.
|
|
156
|
+
* @returns {JSX.Element} - The action button component.
|
|
157
|
+
*/
|
|
131
158
|
const ActionButton = (_a) => {
|
|
132
|
-
var { action, children } = _a, rest = __rest(_a, ["action", "children"]);
|
|
159
|
+
var { action, children, id } = _a, rest = __rest(_a, ["action", "children", "id"]);
|
|
133
160
|
if (action.type === "route") {
|
|
134
|
-
return (jsx(Button, Object.assign({ renderAs: Link, to: action.url, variant: "transparent", color: "secondary" }, rest, { children: children })));
|
|
161
|
+
return (jsx(Button, Object.assign({ renderAs: Link, to: action.url, variant: "transparent", color: "secondary", id: id }, rest, { children: children })));
|
|
162
|
+
}
|
|
163
|
+
return (jsx(Button, Object.assign({ onClick: action.method, variant: "transparent", color: "secondary", id: id }, rest, { children: children })));
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Converts an action model to a MenuItem component.
|
|
167
|
+
* These should be shown in the more menu.
|
|
168
|
+
* Should not be used outside the ActionSheet component.
|
|
169
|
+
*
|
|
170
|
+
* @param {ActionModel} action - The action model to convert.
|
|
171
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
172
|
+
* @returns {JSX.Element} - The MenuItem component for the given action.
|
|
173
|
+
*/
|
|
174
|
+
const actionDataToMenuItem = (action, dataTestId) => {
|
|
175
|
+
const props = "url" in action
|
|
176
|
+
? {
|
|
177
|
+
dataTestId,
|
|
178
|
+
}
|
|
179
|
+
: {
|
|
180
|
+
id: action.id,
|
|
181
|
+
key: action.label,
|
|
182
|
+
dataTestId,
|
|
183
|
+
};
|
|
184
|
+
const item = (jsx(MenuItem, { props, onClick: "method" in action ? action.method : undefined, dataTestId: `${dataTestId}-action-label`, className: "flex justify-center", label: action.label, prefix: jsx(Icon, { name: action.icon, size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }) }, action.label));
|
|
185
|
+
if ("url" in action) {
|
|
186
|
+
return (jsx(Link, { id: action.id, to: action.url, children: item }, action.label));
|
|
135
187
|
}
|
|
136
|
-
return
|
|
188
|
+
return item;
|
|
137
189
|
};
|
|
190
|
+
/**
|
|
191
|
+
* Converts an action model to an ActionButton component.
|
|
192
|
+
* These should be shown in the ActionSheet.
|
|
193
|
+
* Should not be used outside the ActionSheet component.
|
|
194
|
+
*
|
|
195
|
+
* @param {ActionModel} action - The action model to convert.
|
|
196
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
197
|
+
* @returns {JSX.Element} - The ActionButton component for the given action.
|
|
198
|
+
*/
|
|
199
|
+
const actionDataToActionButton = (action, dataTestId) => (jsxs(ActionButton, { action: action, dataTestId: action.label, className: "max-w-max flex-shrink-0", id: action.id, children: [jsx(Icon, { name: action.icon, color: "white", size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }), jsx(Text, { dataTestId: `${dataTestId}-action-label`, className: "!text-base text-white", children: action.label })] }, action.id));
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* `ActionContainerAndOverflow` renders a set of actions and a MoreMenu for overflow.
|
|
203
|
+
* It makes use of the `useOverflowItems` hook to determine which items should go into the overflow menu.
|
|
204
|
+
*
|
|
205
|
+
* @param {object} props - Props for the component.
|
|
206
|
+
* @param {ActionModel[]} props.actions - Array of action models to be rendered.
|
|
207
|
+
* @param {ReactElement<SidebarItemProps>[] | ReactElement<SidebarItemProps>} props.moreActions - Additional actions that can be rendered in the MoreMenu.
|
|
208
|
+
* @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
|
|
209
|
+
* @returns {ReactElement} The rendered component.
|
|
210
|
+
*/
|
|
211
|
+
const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
|
|
212
|
+
const children = useMemo(() => actions && actions.map(action => action && actionDataToActionButton(action, dataTestId)), [actions, dataTestId]);
|
|
213
|
+
const { overflowContainerRef, itemOverflowMap } = useOverflowItems({
|
|
214
|
+
children,
|
|
215
|
+
childUniqueIdentifierAttribute: "id",
|
|
216
|
+
threshold: 1,
|
|
217
|
+
});
|
|
218
|
+
const itemVisibilityClassName = (id) => {
|
|
219
|
+
if (itemOverflowMap[id]) {
|
|
220
|
+
return "invisible";
|
|
221
|
+
}
|
|
222
|
+
return "visible";
|
|
223
|
+
};
|
|
224
|
+
const overflowItemCount = Object.values(itemOverflowMap).filter(isOverflowing => isOverflowing).length;
|
|
225
|
+
return (jsxs(Fragment, { children: [jsx("div", { className: cvaActionContainerAndOverflow(), ref: overflowContainerRef, children: Children.map(children, child => {
|
|
226
|
+
return cloneElement(child, {
|
|
227
|
+
className: `${child.props.className} ${itemVisibilityClassName(child.props.id)}`,
|
|
228
|
+
});
|
|
229
|
+
}) }), Children.count(moreActions) > 0 || overflowItemCount ? (jsx(MoreMenu, { popoverProps: { placement: "top-end" }, className: "p-0", iconButtonProps: { variant: "transparent", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, dataTestId: `${dataTestId}-more-menu`, children: jsxs(MenuList, { className: "relative -right-2", children: [moreActions ? moreActions : null, actions.map(action => {
|
|
230
|
+
return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
|
|
231
|
+
})] }) })) : null] }));
|
|
232
|
+
};
|
|
233
|
+
|
|
138
234
|
/**
|
|
139
235
|
* The Action Sheet appears when one or more items are selected from a table.
|
|
140
236
|
* It primarily accommodates 1-3 main actions that represent the most crucial and frequently accessed functions on the specific page.
|
|
@@ -145,25 +241,9 @@ const ActionButton = (_a) => {
|
|
|
145
241
|
*/
|
|
146
242
|
const ActionSheet = ({ actions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
|
|
147
243
|
const [t] = useTranslation();
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
useEffect(() => {
|
|
152
|
-
window.addEventListener("resize", wrapperSmallScreen);
|
|
153
|
-
return () => window.removeEventListener("resize", wrapperSmallScreen);
|
|
154
|
-
}, []);
|
|
155
|
-
const filteredActions = actions.filter(action => action !== undefined);
|
|
156
|
-
const actionsFilteredForScreenSize = smallScreen ? [filteredActions[0]] : filteredActions;
|
|
157
|
-
const moreActionsFilteredForScreenSize = smallScreen ? moreActions === null || moreActions === void 0 ? void 0 : moreActions.concat(filteredActions.slice(1)) : moreActions;
|
|
158
|
-
const actionDataToActionButton = (action, moreAction = false) => (jsxs(ActionButton, { action: action, dataTestId: action.label, className: "lg:mr-3", children: [jsx(Icon, { name: action.icon, color: moreAction ? "neutral" : "white", size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }), jsx(Text, { dataTestId: `${containerProps["data-testid"]}-action-label`, className: `${moreAction ? "text-inherit" : "!text-white"} !text-base`, children: action.label })] }, action.label));
|
|
159
|
-
const actionDataToMenuItem = (action) => {
|
|
160
|
-
const item = (jsx(MenuItem, { onClick: "method" in action ? action.method : undefined, dataTestId: `${containerProps["data-testid"]}-action-label`, label: action.label, className: "lg:mr-3", prefix: jsx(Icon, { name: action.icon, size: action.size, "data-testid": "action-icon", forwardedRef: action.forwardedRef, style: action.style }) }, action.label));
|
|
161
|
-
if ("url" in action) {
|
|
162
|
-
return jsx(Link, { to: action.url, children: item });
|
|
163
|
-
}
|
|
164
|
-
return item;
|
|
165
|
-
};
|
|
166
|
-
return (jsxs("div", { className: cvaActionSheet({ className: containerProps.className }), "data-testid": containerProps["data-testid"], children: [jsx(IconButton, { icon: jsx(Icon, { name: "XMark", size: "small", color: "white", "data-testid": "close-icon" }), onClick: resetSelection, color: "secondary", variant: "transparent", circular: true, dataTestId: "XButton" }), jsxs(Text, { size: "large", className: "!lg:mr-28 !mr-4 w-max !text-white", children: [selections === null || selections === void 0 ? void 0 : selections.length, " ", t("table.actionsheet.selected")] }), actionsFilteredForScreenSize.map(action => action && actionDataToActionButton(action)), moreActionsFilteredForScreenSize && moreActionsFilteredForScreenSize.length > 0 && (jsx(MoreMenu, { popoverProps: { placement: "top-end" }, className: "p-0", iconButtonProps: { variant: "transparent", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, dataTestId: `${containerProps["data-testid"]}-more-menu`, children: jsx(MenuList, { className: "relative -right-2", children: moreActionsFilteredForScreenSize.map(action => actionDataToMenuItem(action)) }) }))] }));
|
|
244
|
+
return (jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsxs(Text, { size: "large", className: "border-primary-500 col-span-3 w-full border-b text-white sm:col-span-1 sm:w-max sm:border-0", children: [jsx(IconButton, { icon: jsx(Icon, { name: "XMark", size: "small", color: "white", "data-testid": "close-icon" }), onClick: resetSelection, color: "secondary", variant: "transparent", circular: true, dataTestId: "XButton" }), t("table.actionsheet.selected", { count: selections === null || selections === void 0 ? void 0 : selections.length })] }), jsx(ActionContainerAndOverflow, { dataTestId,
|
|
245
|
+
actions,
|
|
246
|
+
moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
|
|
167
247
|
};
|
|
168
248
|
|
|
169
249
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-table",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"@trackunit/css-core": "0.0.99",
|
|
14
14
|
"@trackunit/i18n-library-translation": "0.0.89",
|
|
15
15
|
"@trackunit/iris-app-api": "0.0.126",
|
|
16
|
-
"@trackunit/react-components": "0.1.
|
|
16
|
+
"@trackunit/react-components": "0.1.190",
|
|
17
17
|
"@trackunit/react-core-contexts-api": "0.2.68",
|
|
18
18
|
"@trackunit/react-core-contexts-test": "0.1.125",
|
|
19
|
-
"@trackunit/react-form-components": "0.0.
|
|
20
|
-
"@trackunit/react-table-base-components": "0.0.
|
|
19
|
+
"@trackunit/react-form-components": "0.0.191",
|
|
20
|
+
"@trackunit/react-table-base-components": "0.0.68",
|
|
21
21
|
"@trackunit/shared-utils": "0.0.15",
|
|
22
22
|
"@trackunit/ui-icons": "0.0.78",
|
|
23
23
|
"immutability-helper": "3.1.1",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CommonProps, SidebarItemProps } from "@trackunit/react-components";
|
|
2
|
+
import { ReactElement } from "react";
|
|
3
|
+
import { ActionModel } from "./Actions";
|
|
4
|
+
interface ActionContainerAndOverflowProps extends CommonProps {
|
|
5
|
+
actions: ActionModel[];
|
|
6
|
+
moreActions?: ReactElement<SidebarItemProps>[] | ReactElement<SidebarItemProps>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `ActionContainerAndOverflow` renders a set of actions and a MoreMenu for overflow.
|
|
10
|
+
* It makes use of the `useOverflowItems` hook to determine which items should go into the overflow menu.
|
|
11
|
+
*
|
|
12
|
+
* @param {object} props - Props for the component.
|
|
13
|
+
* @param {ActionModel[]} props.actions - Array of action models to be rendered.
|
|
14
|
+
* @param {ReactElement<SidebarItemProps>[] | ReactElement<SidebarItemProps>} props.moreActions - Additional actions that can be rendered in the MoreMenu.
|
|
15
|
+
* @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
|
|
16
|
+
* @returns {ReactElement} The rendered component.
|
|
17
|
+
*/
|
|
18
|
+
export declare const ActionContainerAndOverflow: ({ actions, moreActions, dataTestId }: ActionContainerAndOverflowProps) => JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -5,7 +5,7 @@ export interface ActionSheetProps extends CommonProps {
|
|
|
5
5
|
/**
|
|
6
6
|
* Actions to be displayed in the ActionSheet as primary actions (normally visible)
|
|
7
7
|
*/
|
|
8
|
-
actions:
|
|
8
|
+
actions: ActionModel[];
|
|
9
9
|
/**
|
|
10
10
|
* Secondary Actions to be displayed in the ActionSheet via the more menu
|
|
11
11
|
*/
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ButtonCommonProps } from "@trackunit/react-components";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
import { ActionModel } from "./Actions";
|
|
4
|
+
interface ActionButtonProps extends ButtonCommonProps {
|
|
5
|
+
/**
|
|
6
|
+
* The action model defining what the action.
|
|
7
|
+
*/
|
|
8
|
+
action: ActionModel;
|
|
9
|
+
/**
|
|
10
|
+
* The children to render inside the button.
|
|
11
|
+
*/
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The button to show in the ActionSheet.
|
|
16
|
+
* Should not be used outside the ActionSheet component.
|
|
17
|
+
*
|
|
18
|
+
* @param {ActionButtonProps} props - The properties for the action button.
|
|
19
|
+
* @param {ActionModel} props.action - The action model defining what action to perform.
|
|
20
|
+
* @param {ReactNode} props.children - The children to render inside the button.
|
|
21
|
+
* @param {string} [props.id] - The optional ID for the button.
|
|
22
|
+
* @param {...any} [props.rest] - Any additional button properties.
|
|
23
|
+
* @returns {JSX.Element} - The action button component.
|
|
24
|
+
*/
|
|
25
|
+
export declare const ActionButton: ({ action, children, id, ...rest }: ActionButtonProps) => JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Converts an action model to a MenuItem component.
|
|
28
|
+
* These should be shown in the more menu.
|
|
29
|
+
* Should not be used outside the ActionSheet component.
|
|
30
|
+
*
|
|
31
|
+
* @param {ActionModel} action - The action model to convert.
|
|
32
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
33
|
+
* @returns {JSX.Element} - The MenuItem component for the given action.
|
|
34
|
+
*/
|
|
35
|
+
export declare const actionDataToMenuItem: (action: ActionModel, dataTestId?: string) => JSX.Element;
|
|
36
|
+
/**
|
|
37
|
+
* Converts an action model to an ActionButton component.
|
|
38
|
+
* These should be shown in the ActionSheet.
|
|
39
|
+
* Should not be used outside the ActionSheet component.
|
|
40
|
+
*
|
|
41
|
+
* @param {ActionModel} action - The action model to convert.
|
|
42
|
+
* @param {string} [dataTestId] - Optional data test ID.
|
|
43
|
+
* @returns {JSX.Element} - The ActionButton component for the given action.
|
|
44
|
+
*/
|
|
45
|
+
export declare const actionDataToActionButton: (action: ActionModel, dataTestId?: string) => JSX.Element;
|
|
46
|
+
export {};
|