@trackunit/react-table 0.0.539 → 0.0.545

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 CHANGED
@@ -115,15 +115,13 @@ const cvaActionSheet = cssClassVarianceUtilities.cvaMerge([
115
115
  "max-w-[80%]",
116
116
  "animate-fade-in-fast",
117
117
  "grid",
118
- "grid-rows-2",
119
- "grid-cols-[min-content,1fr,min-content]",
120
- "sm:grid-cols-[min-content,1fr,min-content]",
118
+ "grid-cols-[min-content,1fr]",
119
+ "sm:grid-cols-[min-content,min-content,1fr,min-content]",
121
120
  "sm:grid-rows-1",
122
121
  "p-2",
123
122
  "bg-primary-600",
124
123
  "gap-1",
125
124
  "rounded-2xl",
126
- "items-center",
127
125
  "z-top",
128
126
  "shadow-2xl",
129
127
  "fixed",
@@ -131,31 +129,41 @@ const cvaActionSheet = cssClassVarianceUtilities.cvaMerge([
131
129
  "left-1/2",
132
130
  "-translate-x-1/2",
133
131
  ]);
132
+ const cvaDivider = cssClassVarianceUtilities.cvaMerge(["border-blue-500", "row-start-2", "col-span-4", "sm:hidden", "min-h-px"]);
134
133
  const cvaActionContainerAndOverflow = cssClassVarianceUtilities.cvaMerge([
135
- "col-span-2",
134
+ "row-start-3",
135
+ "col-span-full",
136
136
  "flex",
137
- "flex-row-reverse",
138
- "flex-nowrap",
139
- "justify-end",
137
+ "flex-row",
140
138
  "gap-2",
141
139
  "overflow-hidden",
142
- "sm:col-span-1",
143
- "sm:flex-row",
144
- ]);
145
- const cvaActionSpinnerContainer = cssClassVarianceUtilities.cvaMerge(["p-0", "h-auto"]);
146
- const cvaActionSpinner = cssClassVarianceUtilities.cvaMerge([], {
140
+ "sm:row-start-1",
141
+ "sm:col-span-3",
142
+ "sm:justify-end",
143
+ ], {
147
144
  variants: {
148
- variant: {
149
- primary: ["border-white/[0.32]", "border-b-white"],
150
- "primary-danger": ["border-white/[0.32]", "border-b-white"],
151
- secondary: ["h-3.5", "w-3.5"],
152
- "secondary-danger": ["h-3.5", "w-3.5"],
153
- ghost: [],
154
- "ghost-neutral": [],
145
+ isDropdown: {
146
+ true: [],
147
+ false: ["col-span-2"],
155
148
  },
156
149
  },
157
- defaultVariants: {
158
- variant: "primary",
150
+ });
151
+ const cvaMoreContainer = cssClassVarianceUtilities.cvaMerge([
152
+ "row-start-4",
153
+ "col-span-full",
154
+ "sm:col-span-1",
155
+ "flex",
156
+ "flex-row",
157
+ "justify-between",
158
+ "gap-2",
159
+ "sm:row-start-1",
160
+ "sm:col-span-3",
161
+ ], {
162
+ variants: {
163
+ isDropdown: {
164
+ true: [],
165
+ false: ["row-start-3", "col-span-2", "place-self-end"],
166
+ },
159
167
  },
160
168
  });
161
169
 
@@ -165,16 +173,15 @@ const cvaActionSpinner = cssClassVarianceUtilities.cvaMerge([], {
165
173
  *
166
174
  * @param {ActionButtonProps} props - The properties for the action button.
167
175
  * @param {ActionModel} props.action - The action model defining what action to perform.
168
- * @param {ReactNode} props.children - The children to render inside the button.
169
176
  * @param {string} [props.id] - The optional ID for the button.
170
177
  * @param {...any} [props.rest] - Any additional button properties.
171
178
  * @returns {JSX.Element} - The action button component.
172
179
  */
173
- const ActionButton = ({ action, children, id, ...rest }) => {
180
+ const ActionButton = ({ action, id, ...rest }) => {
174
181
  if (action.type === "route") {
175
- return (jsxRuntime.jsx(reactComponents.Button, { asChild: true, id: id, variant: "ghost-neutral", ...rest, children: jsxRuntime.jsx(reactRouter.Link, { to: action.url, children: children }) }));
182
+ return (jsxRuntime.jsx(reactComponents.Button, { asChild: true, id: id, loading: action.loading, prefix: jsxRuntime.jsx(ActionIcon, { action: action }), ...rest, children: jsxRuntime.jsx(reactRouter.Link, { to: action.url, children: action.label }) }));
176
183
  }
177
- return (jsxRuntime.jsx(reactComponents.Button, { id: id, onClick: e => action.method(e), variant: "ghost-neutral", ...rest, children: children }));
184
+ return (jsxRuntime.jsx(reactComponents.Button, { id: id, loading: action.loading, onClick: e => action.method(e), prefix: jsxRuntime.jsx(ActionIcon, { action: action }), ...rest, children: action.label }));
178
185
  };
179
186
  /**
180
187
  * Converts an action model to a MenuItem component.
@@ -195,7 +202,7 @@ const actionDataToMenuItem = (action, dataTestId) => {
195
202
  key: action.label,
196
203
  dataTestId,
197
204
  };
198
- const item = (jsxRuntime.jsx(reactComponents.MenuItem, { props, className: "flex justify-center", dataTestId: `${dataTestId}-action-label`, label: action.label, onClick: "method" in action ? action.method : undefined, prefix: jsxRuntime.jsx(reactComponents.Icon, { "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style }), stopPropagation: false }, action.label));
205
+ const item = (jsxRuntime.jsx(reactComponents.MenuItem, { props, className: "flex justify-center", dataTestId: `${dataTestId}-action-label`, label: action.label, onClick: "method" in action ? action.method : undefined, prefix: action.icon ? (jsxRuntime.jsx(reactComponents.Icon, { "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style })) : null, stopPropagation: false }, action.label));
199
206
  if ("url" in action) {
200
207
  return (jsxRuntime.jsx(reactRouter.Link, { id: action.id, to: action.url, children: item }, action.label));
201
208
  }
@@ -210,7 +217,18 @@ const actionDataToMenuItem = (action, dataTestId) => {
210
217
  * @param {string} [dataTestId] - Optional data test ID.
211
218
  * @returns {JSX.Element} - The ActionButton component for the given action.
212
219
  */
213
- const actionDataToActionButton = (action, dataTestId) => (jsxRuntime.jsxs(ActionButton, { action: action, className: "max-w-max flex-shrink-0", dataTestId: action.dataTestId, disabled: action.loading, id: action.id, loading: action.loading, children: [action.loading ? (jsxRuntime.jsx(reactComponents.Spinner, { centering: "vertically", className: cvaActionSpinner({ variant: "primary" }), containerClassName: cvaActionSpinnerContainer(), size: "small" })) : (jsxRuntime.jsx(reactComponents.Icon, { color: "white", "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style })), jsxRuntime.jsx(reactComponents.Text, { className: "!text-base text-white", dataTestId: `${dataTestId}-action-label`, children: action.label })] }, action.id));
220
+ const actionDataToActionButton = (action) => (jsxRuntime.jsx(ActionButton, { action: action, className: "max-w-max flex-shrink-0", dataTestId: action.dataTestId || action.id, disabled: action.loading, id: action.id }, action.id));
221
+ /**
222
+ * Renders the icon for an action button.
223
+ * Should not be used outside the ActionSheet component.
224
+ *
225
+ * @param {InnerActionButtonProps} props - The properties for the action icon.
226
+ * @param {ActionModel} props.action - The action model defining what action to perform.
227
+ * @returns {JSX.Element | null} - The icon for the action button, or null if no icon is defined.
228
+ */
229
+ const ActionIcon = ({ action }) => {
230
+ return action.icon ? (jsxRuntime.jsx(reactComponents.Icon, { color: "white", "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: "small", style: action.style })) : null;
231
+ };
214
232
 
215
233
  /**
216
234
  * `ActionContainerAndOverflow` renders a set of actions and a MoreMenu for overflow.
@@ -222,8 +240,8 @@ const actionDataToActionButton = (action, dataTestId) => (jsxRuntime.jsxs(Action
222
240
  * @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
223
241
  * @returns {ReactElement} The rendered component.
224
242
  */
225
- const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
226
- const children = React.useMemo(() => actions.map(action => actionDataToActionButton(action, dataTestId)), [actions, dataTestId]);
243
+ const ActionContainerAndOverflow = ({ actions, dropdownActions, moreActions, dataTestId, }) => {
244
+ const children = React.useMemo(() => actions.map(action => actionDataToActionButton(action)), [actions]);
227
245
  const { overflowContainerRef, itemOverflowMap } = reactComponents.useOverflowItems({
228
246
  children,
229
247
  childUniqueIdentifierAttribute: "id",
@@ -236,13 +254,17 @@ const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
236
254
  return "visible";
237
255
  };
238
256
  const overflowItemCount = sharedUtils.objectValues(itemOverflowMap).filter(isOverflowing => isOverflowing).length;
239
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: cvaActionContainerAndOverflow(), ref: overflowContainerRef, children: React.Children.map(children, child => {
257
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: cvaActionContainerAndOverflow({ isDropdown: dropdownActions !== undefined }), ref: overflowContainerRef, children: React.Children.map(children, child => {
240
258
  return React.cloneElement(child, {
241
259
  className: `${child.props.className} ${itemVisibilityClassName(child.props.id)}`,
242
260
  });
243
- }) }), React.Children.count(moreActions) > 0 || overflowItemCount ? (jsxRuntime.jsx(reactComponents.MoreMenu, { className: "p-0", dataTestId: `${dataTestId}-more-menu`, iconButtonProps: { variant: "ghost", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, popoverProps: { placement: "top-end" }, children: close => (jsxRuntime.jsxs(reactComponents.MenuList, { className: "relative -right-2", onClick: close, children: [moreActions ? moreActions : null, actions.map(action => {
244
- return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
245
- })] })) })) : null] }));
261
+ }) }), jsxRuntime.jsxs("div", { className: cvaMoreContainer({ isDropdown: dropdownActions !== undefined }), children: [dropdownActions
262
+ ? dropdownActions.map(action => {
263
+ return (jsxRuntime.jsx(reactComponents.MoreMenu, { className: "p-0", customButton: jsxRuntime.jsx(reactComponents.Button, { dataTestId: action.dataTestId, id: action.id, loading: action.loading, onClick: action.method, prefix: jsxRuntime.jsx(ActionIcon, { action: action }), children: action.label }), dataTestId: `${dataTestId}-dropdown-more-menu`, popoverProps: { placement: "top-end" }, children: action.dropdown }, action.id));
264
+ })
265
+ : null, React.Children.count(moreActions) > 0 || overflowItemCount ? (jsxRuntime.jsx(reactComponents.MoreMenu, { className: "p-0", dataTestId: `${dataTestId}-more-menu`, iconButtonProps: { variant: "primary" }, iconProps: { color: "white", name: "EllipsisHorizontal" }, popoverProps: { placement: "top-end" }, children: close => (jsxRuntime.jsxs(reactComponents.MenuList, { className: "relative -right-2", onClick: close, children: [moreActions ? moreActions : null, actions.map(action => {
266
+ return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
267
+ })] })) })) : null] })] }));
246
268
  };
247
269
 
248
270
  /**
@@ -253,10 +275,11 @@ const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
253
275
  * @param {ActionSheetProps} props - The props for the ActionSheet component
254
276
  * @returns {JSX.Element} ActionSheet component
255
277
  */
256
- const ActionSheet = ({ actions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
278
+ const ActionSheet = ({ actions, dropdownActions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
257
279
  const [t] = useTranslation();
258
- return (jsxRuntime.jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsxRuntime.jsxs(reactComponents.Text, { className: "border-primary-500 col-span-3 w-full border-b text-white sm:col-span-1 sm:w-max sm:border-0", size: "large", children: [jsxRuntime.jsx(reactComponents.IconButton, { circular: true, dataTestId: "XButton", icon: jsxRuntime.jsx(reactComponents.Icon, { color: "white", "data-testid": "close-icon", name: "XMark", size: "small" }), onClick: resetSelection, variant: "ghost-neutral" }), t("table.actionsheet.selected", { count: selections.length })] }), jsxRuntime.jsx(ActionContainerAndOverflow, { dataTestId,
280
+ return (jsxRuntime.jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsxRuntime.jsx(reactComponents.Button, { className: "row-start-1", dataTestId: "XButton", onClick: resetSelection, prefix: jsxRuntime.jsx(reactComponents.Icon, { color: "white", "data-testid": "close-icon", name: "XMark", size: "small" }), children: t("table.actionsheet.selected", { count: selections.length }) }), jsxRuntime.jsx(reactComponents.Spacer, { border: true, className: cvaDivider() }), jsxRuntime.jsx(ActionContainerAndOverflow, { dataTestId,
259
281
  actions,
282
+ dropdownActions,
260
283
  moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
261
284
  };
262
285
 
package/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
- import { MenuItem, Icon, Spinner, Text, Button, useOverflowItems, MoreMenu, MenuList, IconButton, Card, cvaInteractableItem, EmptyState, Tooltip, Popover, PopoverTrigger, PopoverContent } from '@trackunit/react-components';
3
+ import { MenuItem, Icon, Button, useOverflowItems, MoreMenu, MenuList, Spacer, Card, Text, cvaInteractableItem, Spinner, EmptyState, Tooltip, Popover, PopoverTrigger, PopoverContent } from '@trackunit/react-components';
4
4
  import { objectValues, nonNullable, objectKeys, objectEntries } from '@trackunit/shared-utils';
5
5
  import * as React from 'react';
6
6
  import { useMemo, Children, cloneElement, useRef, useEffect, useState, useCallback } from 'react';
@@ -96,15 +96,13 @@ const cvaActionSheet = cvaMerge([
96
96
  "max-w-[80%]",
97
97
  "animate-fade-in-fast",
98
98
  "grid",
99
- "grid-rows-2",
100
- "grid-cols-[min-content,1fr,min-content]",
101
- "sm:grid-cols-[min-content,1fr,min-content]",
99
+ "grid-cols-[min-content,1fr]",
100
+ "sm:grid-cols-[min-content,min-content,1fr,min-content]",
102
101
  "sm:grid-rows-1",
103
102
  "p-2",
104
103
  "bg-primary-600",
105
104
  "gap-1",
106
105
  "rounded-2xl",
107
- "items-center",
108
106
  "z-top",
109
107
  "shadow-2xl",
110
108
  "fixed",
@@ -112,31 +110,41 @@ const cvaActionSheet = cvaMerge([
112
110
  "left-1/2",
113
111
  "-translate-x-1/2",
114
112
  ]);
113
+ const cvaDivider = cvaMerge(["border-blue-500", "row-start-2", "col-span-4", "sm:hidden", "min-h-px"]);
115
114
  const cvaActionContainerAndOverflow = cvaMerge([
116
- "col-span-2",
115
+ "row-start-3",
116
+ "col-span-full",
117
117
  "flex",
118
- "flex-row-reverse",
119
- "flex-nowrap",
120
- "justify-end",
118
+ "flex-row",
121
119
  "gap-2",
122
120
  "overflow-hidden",
123
- "sm:col-span-1",
124
- "sm:flex-row",
125
- ]);
126
- const cvaActionSpinnerContainer = cvaMerge(["p-0", "h-auto"]);
127
- const cvaActionSpinner = cvaMerge([], {
121
+ "sm:row-start-1",
122
+ "sm:col-span-3",
123
+ "sm:justify-end",
124
+ ], {
128
125
  variants: {
129
- variant: {
130
- primary: ["border-white/[0.32]", "border-b-white"],
131
- "primary-danger": ["border-white/[0.32]", "border-b-white"],
132
- secondary: ["h-3.5", "w-3.5"],
133
- "secondary-danger": ["h-3.5", "w-3.5"],
134
- ghost: [],
135
- "ghost-neutral": [],
126
+ isDropdown: {
127
+ true: [],
128
+ false: ["col-span-2"],
136
129
  },
137
130
  },
138
- defaultVariants: {
139
- variant: "primary",
131
+ });
132
+ const cvaMoreContainer = cvaMerge([
133
+ "row-start-4",
134
+ "col-span-full",
135
+ "sm:col-span-1",
136
+ "flex",
137
+ "flex-row",
138
+ "justify-between",
139
+ "gap-2",
140
+ "sm:row-start-1",
141
+ "sm:col-span-3",
142
+ ], {
143
+ variants: {
144
+ isDropdown: {
145
+ true: [],
146
+ false: ["row-start-3", "col-span-2", "place-self-end"],
147
+ },
140
148
  },
141
149
  });
142
150
 
@@ -146,16 +154,15 @@ const cvaActionSpinner = cvaMerge([], {
146
154
  *
147
155
  * @param {ActionButtonProps} props - The properties for the action button.
148
156
  * @param {ActionModel} props.action - The action model defining what action to perform.
149
- * @param {ReactNode} props.children - The children to render inside the button.
150
157
  * @param {string} [props.id] - The optional ID for the button.
151
158
  * @param {...any} [props.rest] - Any additional button properties.
152
159
  * @returns {JSX.Element} - The action button component.
153
160
  */
154
- const ActionButton = ({ action, children, id, ...rest }) => {
161
+ const ActionButton = ({ action, id, ...rest }) => {
155
162
  if (action.type === "route") {
156
- return (jsx(Button, { asChild: true, id: id, variant: "ghost-neutral", ...rest, children: jsx(Link, { to: action.url, children: children }) }));
163
+ return (jsx(Button, { asChild: true, id: id, loading: action.loading, prefix: jsx(ActionIcon, { action: action }), ...rest, children: jsx(Link, { to: action.url, children: action.label }) }));
157
164
  }
158
- return (jsx(Button, { id: id, onClick: e => action.method(e), variant: "ghost-neutral", ...rest, children: children }));
165
+ return (jsx(Button, { id: id, loading: action.loading, onClick: e => action.method(e), prefix: jsx(ActionIcon, { action: action }), ...rest, children: action.label }));
159
166
  };
160
167
  /**
161
168
  * Converts an action model to a MenuItem component.
@@ -176,7 +183,7 @@ const actionDataToMenuItem = (action, dataTestId) => {
176
183
  key: action.label,
177
184
  dataTestId,
178
185
  };
179
- const item = (jsx(MenuItem, { props, className: "flex justify-center", dataTestId: `${dataTestId}-action-label`, label: action.label, onClick: "method" in action ? action.method : undefined, prefix: jsx(Icon, { "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style }), stopPropagation: false }, action.label));
186
+ const item = (jsx(MenuItem, { props, className: "flex justify-center", dataTestId: `${dataTestId}-action-label`, label: action.label, onClick: "method" in action ? action.method : undefined, prefix: action.icon ? (jsx(Icon, { "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style })) : null, stopPropagation: false }, action.label));
180
187
  if ("url" in action) {
181
188
  return (jsx(Link, { id: action.id, to: action.url, children: item }, action.label));
182
189
  }
@@ -191,7 +198,18 @@ const actionDataToMenuItem = (action, dataTestId) => {
191
198
  * @param {string} [dataTestId] - Optional data test ID.
192
199
  * @returns {JSX.Element} - The ActionButton component for the given action.
193
200
  */
194
- const actionDataToActionButton = (action, dataTestId) => (jsxs(ActionButton, { action: action, className: "max-w-max flex-shrink-0", dataTestId: action.dataTestId, disabled: action.loading, id: action.id, loading: action.loading, children: [action.loading ? (jsx(Spinner, { centering: "vertically", className: cvaActionSpinner({ variant: "primary" }), containerClassName: cvaActionSpinnerContainer(), size: "small" })) : (jsx(Icon, { color: "white", "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: action.size, style: action.style })), jsx(Text, { className: "!text-base text-white", dataTestId: `${dataTestId}-action-label`, children: action.label })] }, action.id));
201
+ const actionDataToActionButton = (action) => (jsx(ActionButton, { action: action, className: "max-w-max flex-shrink-0", dataTestId: action.dataTestId || action.id, disabled: action.loading, id: action.id }, action.id));
202
+ /**
203
+ * Renders the icon for an action button.
204
+ * Should not be used outside the ActionSheet component.
205
+ *
206
+ * @param {InnerActionButtonProps} props - The properties for the action icon.
207
+ * @param {ActionModel} props.action - The action model defining what action to perform.
208
+ * @returns {JSX.Element | null} - The icon for the action button, or null if no icon is defined.
209
+ */
210
+ const ActionIcon = ({ action }) => {
211
+ return action.icon ? (jsx(Icon, { color: "white", "data-testid": "action-icon", forwardedRef: action.forwardedRef, name: action.icon, size: "small", style: action.style })) : null;
212
+ };
195
213
 
196
214
  /**
197
215
  * `ActionContainerAndOverflow` renders a set of actions and a MoreMenu for overflow.
@@ -203,8 +221,8 @@ const actionDataToActionButton = (action, dataTestId) => (jsxs(ActionButton, { a
203
221
  * @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
204
222
  * @returns {ReactElement} The rendered component.
205
223
  */
206
- const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
207
- const children = useMemo(() => actions.map(action => actionDataToActionButton(action, dataTestId)), [actions, dataTestId]);
224
+ const ActionContainerAndOverflow = ({ actions, dropdownActions, moreActions, dataTestId, }) => {
225
+ const children = useMemo(() => actions.map(action => actionDataToActionButton(action)), [actions]);
208
226
  const { overflowContainerRef, itemOverflowMap } = useOverflowItems({
209
227
  children,
210
228
  childUniqueIdentifierAttribute: "id",
@@ -217,13 +235,17 @@ const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
217
235
  return "visible";
218
236
  };
219
237
  const overflowItemCount = objectValues(itemOverflowMap).filter(isOverflowing => isOverflowing).length;
220
- return (jsxs(Fragment, { children: [jsx("div", { className: cvaActionContainerAndOverflow(), ref: overflowContainerRef, children: Children.map(children, child => {
238
+ return (jsxs(Fragment, { children: [jsx("div", { className: cvaActionContainerAndOverflow({ isDropdown: dropdownActions !== undefined }), ref: overflowContainerRef, children: Children.map(children, child => {
221
239
  return cloneElement(child, {
222
240
  className: `${child.props.className} ${itemVisibilityClassName(child.props.id)}`,
223
241
  });
224
- }) }), Children.count(moreActions) > 0 || overflowItemCount ? (jsx(MoreMenu, { className: "p-0", dataTestId: `${dataTestId}-more-menu`, iconButtonProps: { variant: "ghost", circular: true }, iconProps: { color: "white", name: "EllipsisHorizontal" }, popoverProps: { placement: "top-end" }, children: close => (jsxs(MenuList, { className: "relative -right-2", onClick: close, children: [moreActions ? moreActions : null, actions.map(action => {
225
- return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
226
- })] })) })) : null] }));
242
+ }) }), jsxs("div", { className: cvaMoreContainer({ isDropdown: dropdownActions !== undefined }), children: [dropdownActions
243
+ ? dropdownActions.map(action => {
244
+ return (jsx(MoreMenu, { className: "p-0", customButton: jsx(Button, { dataTestId: action.dataTestId, id: action.id, loading: action.loading, onClick: action.method, prefix: jsx(ActionIcon, { action: action }), children: action.label }), dataTestId: `${dataTestId}-dropdown-more-menu`, popoverProps: { placement: "top-end" }, children: action.dropdown }, action.id));
245
+ })
246
+ : null, Children.count(moreActions) > 0 || overflowItemCount ? (jsx(MoreMenu, { className: "p-0", dataTestId: `${dataTestId}-more-menu`, iconButtonProps: { variant: "primary" }, iconProps: { color: "white", name: "EllipsisHorizontal" }, popoverProps: { placement: "top-end" }, children: close => (jsxs(MenuList, { className: "relative -right-2", onClick: close, children: [moreActions ? moreActions : null, actions.map(action => {
247
+ return itemOverflowMap[action.id] ? actionDataToMenuItem(action, dataTestId) : null;
248
+ })] })) })) : null] })] }));
227
249
  };
228
250
 
229
251
  /**
@@ -234,10 +256,11 @@ const ActionContainerAndOverflow = ({ actions, moreActions, dataTestId }) => {
234
256
  * @param {ActionSheetProps} props - The props for the ActionSheet component
235
257
  * @returns {JSX.Element} ActionSheet component
236
258
  */
237
- const ActionSheet = ({ actions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
259
+ const ActionSheet = ({ actions, dropdownActions, moreActions = [], selections, resetSelection, className, dataTestId, }) => {
238
260
  const [t] = useTranslation();
239
- return (jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsxs(Text, { className: "border-primary-500 col-span-3 w-full border-b text-white sm:col-span-1 sm:w-max sm:border-0", size: "large", children: [jsx(IconButton, { circular: true, dataTestId: "XButton", icon: jsx(Icon, { color: "white", "data-testid": "close-icon", name: "XMark", size: "small" }), onClick: resetSelection, variant: "ghost-neutral" }), t("table.actionsheet.selected", { count: selections.length })] }), jsx(ActionContainerAndOverflow, { dataTestId,
261
+ return (jsxs("div", { className: cvaActionSheet({ className }), "data-testid": dataTestId, children: [jsx(Button, { className: "row-start-1", dataTestId: "XButton", onClick: resetSelection, prefix: jsx(Icon, { color: "white", "data-testid": "close-icon", name: "XMark", size: "small" }), children: t("table.actionsheet.selected", { count: selections.length }) }), jsx(Spacer, { border: true, className: cvaDivider() }), jsx(ActionContainerAndOverflow, { dataTestId,
240
262
  actions,
263
+ dropdownActions,
241
264
  moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
242
265
  };
243
266
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-table",
3
- "version": "0.0.539",
3
+ "version": "0.0.545",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -1,8 +1,9 @@
1
1
  import { CommonProps, SidebarItemProps } from "@trackunit/react-components";
2
2
  import { ReactElement } from "react";
3
- import { ActionModel } from "./Actions";
3
+ import { ActionModel, DropdownModel } from "./Actions";
4
4
  interface ActionContainerAndOverflowProps extends CommonProps {
5
5
  actions: ActionModel[];
6
+ dropdownActions?: DropdownModel[];
6
7
  moreActions?: ReactElement<SidebarItemProps>[] | ReactElement<SidebarItemProps>;
7
8
  }
8
9
  /**
@@ -15,5 +16,5 @@ interface ActionContainerAndOverflowProps extends CommonProps {
15
16
  * @param {string} [props.dataTestId] - Data test id for the component, useful in testing.
16
17
  * @returns {ReactElement} The rendered component.
17
18
  */
18
- export declare const ActionContainerAndOverflow: ({ actions, moreActions, dataTestId }: ActionContainerAndOverflowProps) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const ActionContainerAndOverflow: ({ actions, dropdownActions, moreActions, dataTestId, }: ActionContainerAndOverflowProps) => import("react/jsx-runtime").JSX.Element;
19
20
  export {};
@@ -1,5 +1,5 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
- import { ActionModel } from "./Actions";
2
+ import { ActionModel, DropdownModel } from "./Actions";
3
3
  export interface ActionSheetProps extends CommonProps {
4
4
  /**
5
5
  * Actions to be displayed in the ActionSheet as primary actions (normally visible)
@@ -9,6 +9,10 @@ export interface ActionSheetProps extends CommonProps {
9
9
  * Secondary Actions to be displayed in the ActionSheet via the more menu
10
10
  */
11
11
  moreActions?: ActionModel[];
12
+ /**
13
+ * Actions to be displayed as primary actions with capability to pass MenuList as dropdown
14
+ */
15
+ dropdownActions?: DropdownModel[];
12
16
  /**
13
17
  * array of selected element-ids is used for calculating the number of selected elements - and available for eventhandlers.
14
18
  */
@@ -26,4 +30,4 @@ export interface ActionSheetProps extends CommonProps {
26
30
  * @param {ActionSheetProps} props - The props for the ActionSheet component
27
31
  * @returns {JSX.Element} ActionSheet component
28
32
  */
29
- export declare const ActionSheet: ({ actions, moreActions, selections, resetSelection, className, dataTestId, }: ActionSheetProps) => import("react/jsx-runtime").JSX.Element;
33
+ export declare const ActionSheet: ({ actions, dropdownActions, moreActions, selections, resetSelection, className, dataTestId, }: ActionSheetProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,8 @@
1
1
  export declare const cvaActionSheet: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
2
- export declare const cvaActionContainerAndOverflow: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
3
- export declare const cvaActionSpinnerContainer: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
4
- export declare const cvaActionSpinner: (props?: ({
5
- variant?: "primary" | "primary-danger" | "secondary" | "secondary-danger" | "ghost" | "ghost-neutral" | null | undefined;
2
+ export declare const cvaDivider: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
3
+ export declare const cvaActionContainerAndOverflow: (props?: ({
4
+ isDropdown?: boolean | null | undefined;
5
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
+ export declare const cvaMoreContainer: (props?: ({
7
+ isDropdown?: boolean | null | undefined;
6
8
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
@@ -1,15 +1,10 @@
1
1
  import { ButtonCommonProps } from "@trackunit/react-components";
2
- import { ReactNode } from "react";
3
2
  import { ActionModel } from "./Actions";
4
3
  interface ActionButtonProps extends ButtonCommonProps {
5
4
  /**
6
5
  * The action model defining what the action.
7
6
  */
8
7
  action: ActionModel;
9
- /**
10
- * The children to render inside the button.
11
- */
12
- children: ReactNode;
13
8
  }
14
9
  /**
15
10
  * The button to show in the ActionSheet.
@@ -17,12 +12,11 @@ interface ActionButtonProps extends ButtonCommonProps {
17
12
  *
18
13
  * @param {ActionButtonProps} props - The properties for the action button.
19
14
  * @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
15
  * @param {string} [props.id] - The optional ID for the button.
22
16
  * @param {...any} [props.rest] - Any additional button properties.
23
17
  * @returns {JSX.Element} - The action button component.
24
18
  */
25
- export declare const ActionButton: ({ action, children, id, ...rest }: ActionButtonProps) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const ActionButton: ({ action, id, ...rest }: ActionButtonProps) => import("react/jsx-runtime").JSX.Element;
26
20
  /**
27
21
  * Converts an action model to a MenuItem component.
28
22
  * These should be shown in the more menu.
@@ -42,5 +36,17 @@ export declare const actionDataToMenuItem: (action: ActionModel, dataTestId?: st
42
36
  * @param {string} [dataTestId] - Optional data test ID.
43
37
  * @returns {JSX.Element} - The ActionButton component for the given action.
44
38
  */
45
- export declare const actionDataToActionButton: (action: ActionModel, dataTestId?: string) => import("react/jsx-runtime").JSX.Element;
39
+ export declare const actionDataToActionButton: (action: ActionModel) => import("react/jsx-runtime").JSX.Element;
40
+ interface InnerActionButtonProps {
41
+ action: ActionModel;
42
+ }
43
+ /**
44
+ * Renders the icon for an action button.
45
+ * Should not be used outside the ActionSheet component.
46
+ *
47
+ * @param {InnerActionButtonProps} props - The properties for the action icon.
48
+ * @param {ActionModel} props.action - The action model defining what action to perform.
49
+ * @returns {JSX.Element | null} - The icon for the action button, or null if no icon is defined.
50
+ */
51
+ export declare const ActionIcon: ({ action }: InnerActionButtonProps) => import("react/jsx-runtime").JSX.Element | null;
46
52
  export {};
@@ -1,7 +1,11 @@
1
- import { IconProps, Size } from "@trackunit/react-components";
1
+ import { IconProps } from "@trackunit/react-components";
2
2
  import { IconName } from "@trackunit/ui-icons";
3
+ import { ReactNode } from "react";
3
4
  type IconExposedProp = Omit<IconProps, "color" | "onclick" | "type" | "name">;
4
5
  export type ActionModel = (MethodAction | RouteAction) & CommonAction;
6
+ export type DropdownModel = MethodAction & CommonAction & {
7
+ dropdown: ReactNode;
8
+ };
5
9
  export type MethodAction = {
6
10
  type: "method";
7
11
  method: (e: React.MouseEvent) => void;
@@ -14,8 +18,7 @@ export type RouteAction = {
14
18
  export interface CommonAction extends IconExposedProp {
15
19
  id: string;
16
20
  label: string;
17
- icon: IconName;
18
- size?: Size;
21
+ icon?: IconName;
19
22
  forwardedRef?: React.RefObject<HTMLSpanElement>;
20
23
  style?: Record<string, string>;
21
24
  loading?: boolean;