From f732d6f272e1961b13e315711a8c23534a6a2f37 Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Wed, 24 Jun 2026 16:49:55 +0000 Subject: [PATCH 1/4] feat(table): add getCopyDeepLinkAction utility and TableAction type Expose a pre-built TableAction descriptor that produces a 'Copy link' row-action menu entry. Callers pass an onCopy callback; the action renders CopyLinkIcon and a 'Copy link' label. Export getCopyDeepLinkAction and the TableAction type from the custom index so Meshery UI and other consumers can use them without reaching into the component internals. Signed-off-by: Lee Calcote --- src/custom/ResponsiveDataTable.tsx | 34 ++++++++++++++++++++++-------- src/custom/index.tsx | 6 +++++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/custom/ResponsiveDataTable.tsx b/src/custom/ResponsiveDataTable.tsx index a2ed0f35e..675ba8ffa 100644 --- a/src/custom/ResponsiveDataTable.tsx +++ b/src/custom/ResponsiveDataTable.tsx @@ -1,7 +1,7 @@ import MUIDataTable, { MUIDataTableColumn } from '@sistent/mui-datatables'; import React, { useCallback } from 'react'; import { Checkbox, Collapse, ListItemIcon, ListItemText, Menu, MenuItem } from '../base'; -import { ShareIcon } from '../icons'; +import { CopyLinkIcon, ShareIcon } from '../icons'; import { EllipsisIcon } from '../icons/Ellipsis'; import { FormattedTime } from '../utils'; import { styled, useTheme } from './../theme'; @@ -123,6 +123,15 @@ export const DataTableEllipsisMenu: React.FC<{ ); }; +export type TableAction = { + title: string; + icon: JSX.Element; + onClick: () => void; + disabled?: boolean; + customComponent?: JSX.Element; + type?: string; +}; + export interface Column { name: string; label: string; @@ -133,17 +142,24 @@ export interface Column { display?: boolean; sortDescFirst?: boolean; customBodyRender?: (value: string | number | boolean | object) => JSX.Element; - actionsList?: { - title: string; - icon: JSX.Element; - onClick: () => void; - disabled?: boolean; - customComponent?: JSX.Element; - type?: string; - }[]; + actionsList?: TableAction[]; }; } +/** + * Returns a pre-built TableAction that copies a deeplink for the given row to + * the clipboard. Drop it into any `actionsList` to give users a one-click + * "Copy link" entry in the row-action menu. + * + * @param onCopy - Called with the row identifier when the user clicks the + * action. The caller is responsible for constructing and writing the URL. + */ +export const getCopyDeepLinkAction = (onCopy: () => void): TableAction => ({ + title: 'Copy link', + icon: , + onClick: onCopy, +}); + export interface ResponsiveDataTableProps { data: string[][]; columns: MUIDataTableColumn[]; diff --git a/src/custom/index.tsx b/src/custom/index.tsx index 489f0e90c..7f9c818e2 100644 --- a/src/custom/index.tsx +++ b/src/custom/index.tsx @@ -40,7 +40,9 @@ import { ModalCard } from './ModalCard'; import PopperListener, { IPopperListener } from './PopperListener'; import ResponsiveDataTable, { DataTableEllipsisMenu, - ResponsiveDataTableProps + getCopyDeepLinkAction, + ResponsiveDataTableProps, + TableAction } from './ResponsiveDataTable'; import SearchBar, { SearchBarProps } from './SearchBar'; import { StyledCardProps } from './StyledCard/StyledCard'; @@ -93,6 +95,7 @@ export { CustomImage, CustomTooltip, DataTableEllipsisMenu, + getCopyDeepLinkAction, EmptyState, EmptyStateCard, ErrorBoundary, @@ -157,6 +160,7 @@ export type { ResponsiveDataTableProps, SearchBarProps, StyledCardProps, + TableAction, TransferListProps, UniversalFilterProps }; From d64abf37ac7e4e21110dded17a65b6c904bc67c8 Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Wed, 24 Jun 2026 16:54:17 +0000 Subject: [PATCH 2/4] feat(table): make getCopyDeepLinkAction title configurable for i18n Signed-off-by: Lee Calcote --- src/custom/ResponsiveDataTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/custom/ResponsiveDataTable.tsx b/src/custom/ResponsiveDataTable.tsx index 675ba8ffa..6f08a9b2a 100644 --- a/src/custom/ResponsiveDataTable.tsx +++ b/src/custom/ResponsiveDataTable.tsx @@ -154,8 +154,8 @@ export interface Column { * @param onCopy - Called with the row identifier when the user clicks the * action. The caller is responsible for constructing and writing the URL. */ -export const getCopyDeepLinkAction = (onCopy: () => void): TableAction => ({ - title: 'Copy link', +export const getCopyDeepLinkAction = (onCopy: () => void, title = 'Copy link'): TableAction => ({ + title, icon: , onClick: onCopy, }); From cb03dd2cafbbd94ddcc6e684c2c70b2d9a22ebe0 Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Wed, 24 Jun 2026 17:09:41 +0000 Subject: [PATCH 3/4] docs: document ResponsiveDataTable custom component usage Expand the custom directory description in CONTRIBUTING.md to cover ResponsiveDataTable: key exports, getCopyDeepLinkAction helper signature and i18n title param, and the steps for adding a new responsive column. Signed-off-by: Lee Calcote --- CONTRIBUTING.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5856c52e6..51ca9ed51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -151,6 +151,42 @@ make lint - Custom directory contains all the custom components using the theme colors. +#### `ResponsiveDataTable` + +`src/custom/ResponsiveDataTable.tsx` wraps `@mui/x-data-grid` (via `@layer5/mui-datatables`) with responsive column visibility and a standardised row action menu. Key exports: + +| Export | Description | +|---|---| +| `ResponsiveDataTable` | The main table component | +| `TableAction` | Type for items in the per-row action menu | +| `getCopyDeepLinkAction` | Helper that builds a "Copy link" `TableAction` | + +**`getCopyDeepLinkAction`** + +Use this to add a deep-link copy button to any row action menu. The `title` argument is optional and defaults to `'Copy link'` — pass a translated string for i18n: + +```tsx +import { getCopyDeepLinkAction, TableAction } from '@sistent/sistent'; + +const rowActions: TableAction[] = [ + getCopyDeepLinkAction(() => copyRowDeepLink(row.id)), + // or, with a custom title: + getCopyDeepLinkAction(() => copyRowDeepLink(row.id), t('Copy link')), +]; +``` + +The helper signature is: + +```ts +getCopyDeepLinkAction(onCopy: () => void, title?: string): TableAction +``` + +**Adding a new column to `ResponsiveDataTable`** + +1. Define the column in the `columns` array passed to `ResponsiveDataTable`. +2. Add a breakpoint entry for the column in the `updateVisibleColumns` / `getResponsiveColumnVisibility` utility so it hides gracefully on narrow viewports. +3. Use `useColumnVisibilityPreference` (from Meshery UI's `utils/hooks`) to merge responsive defaults with user preferences persisted in `localStorage`. + ### icons - Icons directory contains all the icons that are used in the project or can be used in any of other projects. From 8c4f01726097f78b3820fb20f3749fe038b39aeb Mon Sep 17 00:00:00 2001 From: Lee Calcote Date: Wed, 24 Jun 2026 13:03:54 -0500 Subject: [PATCH 4/4] fix(table): keep getCopyDeepLinkAction/TableAction in the published d.ts The helper and its TableAction type were defined inline in ResponsiveDataTable and reached the package entry only through 'export * from ./custom'. rollup-plugin-dts drops such nested re-exports from the bundled declarations, so 'import { getCopyDeepLinkAction, TableAction } from @sistent/sistent' resolved to nothing in consumers despite the runtime export existing. Re-exporting them directly from ResponsiveDataTable is not viable: it imports the untyped @sistent/mui-datatables, which makes the dts build resolve that module and fail (TS7016). Move both into a new leaf module TableActions (free of untyped imports) and re-export it explicitly from src/index.tsx, the same workaround already used for FeedbackButton, so both the value and the type land in the published bundle. Verified: build exits 0 and dist/index.d.ts declares both symbols. Signed-off-by: Lee Calcote --- src/custom/ResponsiveDataTable.tsx | 26 ++------------------ src/custom/TableActions.tsx | 38 ++++++++++++++++++++++++++++++ src/custom/index.tsx | 19 +++++++-------- src/index.tsx | 5 ++++ 4 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 src/custom/TableActions.tsx diff --git a/src/custom/ResponsiveDataTable.tsx b/src/custom/ResponsiveDataTable.tsx index 6f08a9b2a..9cfb6f0f7 100644 --- a/src/custom/ResponsiveDataTable.tsx +++ b/src/custom/ResponsiveDataTable.tsx @@ -1,11 +1,12 @@ import MUIDataTable, { MUIDataTableColumn } from '@sistent/mui-datatables'; import React, { useCallback } from 'react'; import { Checkbox, Collapse, ListItemIcon, ListItemText, Menu, MenuItem } from '../base'; -import { CopyLinkIcon, ShareIcon } from '../icons'; +import { ShareIcon } from '../icons'; import { EllipsisIcon } from '../icons/Ellipsis'; import { FormattedTime } from '../utils'; import { styled, useTheme } from './../theme'; import { ColView } from './Helpers/ResponsiveColumns/responsive-coulmns.tsx'; +import { TableAction } from './TableActions'; import { TooltipIcon } from './TooltipIconButton'; export const IconWrapper = styled('div', { @@ -123,15 +124,6 @@ export const DataTableEllipsisMenu: React.FC<{ ); }; -export type TableAction = { - title: string; - icon: JSX.Element; - onClick: () => void; - disabled?: boolean; - customComponent?: JSX.Element; - type?: string; -}; - export interface Column { name: string; label: string; @@ -146,20 +138,6 @@ export interface Column { }; } -/** - * Returns a pre-built TableAction that copies a deeplink for the given row to - * the clipboard. Drop it into any `actionsList` to give users a one-click - * "Copy link" entry in the row-action menu. - * - * @param onCopy - Called with the row identifier when the user clicks the - * action. The caller is responsible for constructing and writing the URL. - */ -export const getCopyDeepLinkAction = (onCopy: () => void, title = 'Copy link'): TableAction => ({ - title, - icon: , - onClick: onCopy, -}); - export interface ResponsiveDataTableProps { data: string[][]; columns: MUIDataTableColumn[]; diff --git a/src/custom/TableActions.tsx b/src/custom/TableActions.tsx new file mode 100644 index 000000000..2549760f3 --- /dev/null +++ b/src/custom/TableActions.tsx @@ -0,0 +1,38 @@ +import { CopyLinkIcon } from '../icons'; + +/** + * Descriptor for a single entry in a `ResponsiveDataTable` row-action menu + * (`Column.options.actionsList`). + * + * Defined in this leaf module (rather than inline in `ResponsiveDataTable`) so + * the type and the `getCopyDeepLinkAction` helper can be re-exported explicitly + * from the package root. `ResponsiveDataTable` imports `@sistent/mui-datatables`, + * which ships no type declarations; re-exporting directly from it makes + * rollup-plugin-dts resolve that untyped import and drop the whole declaration + * bundle. Keeping these here, free of untyped imports, lets them survive into + * the published `.d.ts` without a consumer-side augmentation. + */ +export type TableAction = { + title: string; + icon: JSX.Element; + onClick: () => void; + disabled?: boolean; + customComponent?: JSX.Element; + type?: string; +}; + +/** + * Returns a pre-built {@link TableAction} that copies a deeplink for the given + * row to the clipboard. Drop it into any `actionsList` to give users a + * one-click "Copy link" entry in the row-action menu. + * + * @param onCopy - Invoked when the user clicks the action. The caller is + * responsible for constructing and writing the URL to the clipboard. + * @param title - Menu label; defaults to `'Copy link'` and is overridable for + * internationalisation. + */ +export const getCopyDeepLinkAction = (onCopy: () => void, title = 'Copy link'): TableAction => ({ + title, + icon: , + onClick: onCopy +}); diff --git a/src/custom/index.tsx b/src/custom/index.tsx index 7f9c818e2..51a104ce5 100644 --- a/src/custom/index.tsx +++ b/src/custom/index.tsx @@ -40,18 +40,17 @@ import { ModalCard } from './ModalCard'; import PopperListener, { IPopperListener } from './PopperListener'; import ResponsiveDataTable, { DataTableEllipsisMenu, - getCopyDeepLinkAction, - ResponsiveDataTableProps, - TableAction + ResponsiveDataTableProps } from './ResponsiveDataTable'; import SearchBar, { SearchBarProps } from './SearchBar'; import { StyledCardProps } from './StyledCard/StyledCard'; +import { getCopyDeepLinkAction, TableAction } from './TableActions'; import { TeamTable, TeamTableConfiguration } from './TeamTable'; import { TooltipIcon } from './TooltipIconButton'; import { TransferList } from './TransferModal/TransferList'; import { TransferListProps } from './TransferModal/TransferList/TransferList'; import UniversalFilter, { UniversalFilterProps } from './UniversalFilter'; -import { UserTableAvatarInfo, UsersTable } from './UsersTable'; +import { UsersTable, UserTableAvatarInfo } from './UsersTable'; import { VisibilityChipMenu } from './VisibilityChipMenu'; export { CatalogCard } from './CatalogCard'; export { CatalogFilterSidebar } from './CatalogFilterSection'; @@ -67,6 +66,7 @@ export { PerformersSection, PerformersSectionButton } from './PerformersSection'; +export { PROMPT_VARIANTS, PromptComponent, type PromptRef } from './Prompt'; export { SetupPreReq } from './SetupPrerequisite'; export { StyledAccordion, StyledAccordionSummary } from './StyledAccordion'; export { StyledCard } from './StyledCard'; @@ -77,7 +77,6 @@ export { Terminal } from './Terminal'; export { TOC } from './TOCChapter'; export { TOCLearning } from './TOCLearning'; export { UserSearchField } from './UserSearchField'; -export { PROMPT_VARIANTS, PromptComponent, type PromptRef } from './Prompt'; export { ActionButton, @@ -95,7 +94,6 @@ export { CustomImage, CustomTooltip, DataTableEllipsisMenu, - getCopyDeepLinkAction, EmptyState, EmptyStateCard, ErrorBoundary, @@ -103,6 +101,7 @@ export { FeedbackButton, FlipCard, FormatId, + getCopyDeepLinkAction, InfoTooltip, LearningCard, ModalCard, @@ -117,12 +116,12 @@ export { TooltipIcon, TransferList, UniversalFilter, - UserTableAvatarInfo, - UsersTable, - VisibilityChipMenu, updateVisibleColumns, useNotificationHandler, + UsersTable, + UserTableAvatarInfo, useWindowDimensions, + VisibilityChipMenu, withErrorBoundary, withSuppressedErrorBoundary }; @@ -169,10 +168,10 @@ export * from './CatalogDesignTable'; export * from './CatalogDetail'; export * from './DashboardWidgets'; export * from './Dialog'; +export * from './LiquidGlass'; export * from './permissions'; export * from './ResourceDetailFormatters'; export * from './RJSFFormWrapper'; export * from './ShareModal'; export * from './UserSearchField'; export * from './Workspaces'; -export * from './LiquidGlass'; diff --git a/src/index.tsx b/src/index.tsx index e5640c595..c5a4561e8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -18,3 +18,8 @@ export * from './utils'; // affects other custom components (see consumers' local d.ts augmentations); // add them here as they are needed. export { FeedbackButton, type FeedbackComponentProps } from './custom/Feedback'; +// `TableAction` and `getCopyDeepLinkAction` live in the leaf `TableActions` +// module (not `ResponsiveDataTable`, which imports the untyped +// `@sistent/mui-datatables` and would crash the dts build) precisely so this +// explicit re-export can force them into the published declaration bundle. +export { getCopyDeepLinkAction, type TableAction } from './custom/TableActions';