From 1c1a4ed4bf02e3a71960c5097784b5aeca0fe6f7 Mon Sep 17 00:00:00 2001 From: Austin Pinkerton Date: Mon, 14 Jul 2025 17:26:33 -0400 Subject: [PATCH 1/2] feat: add drag and drop column component --- packages/module/src/Column/Column.test.tsx | 101 +++++++++++ packages/module/src/Column/Column.tsx | 195 +++++++++++++++++++++ packages/module/src/Column/index.ts | 2 + packages/module/src/index.ts | 3 + 4 files changed, 301 insertions(+) create mode 100644 packages/module/src/Column/Column.test.tsx create mode 100644 packages/module/src/Column/Column.tsx create mode 100644 packages/module/src/Column/index.ts diff --git a/packages/module/src/Column/Column.test.tsx b/packages/module/src/Column/Column.test.tsx new file mode 100644 index 00000000..7c30eaca --- /dev/null +++ b/packages/module/src/Column/Column.test.tsx @@ -0,0 +1,101 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import '@testing-library/jest-dom'; +import Column from '../Column'; + +const mockColumns = [ + { key: 'name', title: 'Name', isShownByDefault: true }, + { key: 'status', title: 'Status', isShownByDefault: true }, + { key: 'version', title: 'Version', isShownByDefault: false }, +]; + +describe('Column', () => { + it('renders with initial columns', () => { + render(); + expect(screen.getByLabelText('Name')).toBeChecked(); + expect(screen.getByLabelText('Status')).toBeChecked(); + expect(screen.getByLabelText('Version')).not.toBeChecked(); + }); + + it('renders title and description', () => { + render(); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + }); + + it('renders a cancel button', () => { + const onCancel = jest.fn(); + render(); + const cancelButton = screen.getByText('Cancel'); + expect(cancelButton).toBeInTheDocument(); + userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalled(); + }); + + it('toggles a column', async () => { + const onSelect = jest.fn(); + render(); + const nameCheckbox = screen.getByLabelText('Name'); + await userEvent.click(nameCheckbox); + expect(nameCheckbox).not.toBeChecked(); + expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ key: 'name', isShown: false })); + }); + + it('selects all columns', async () => { + render(); + const menuToggle = screen.getByLabelText('Select all').closest('button'); + if (menuToggle) { + await userEvent.click(menuToggle); + } + const selectAllButton = screen.getByText('Select all'); + await userEvent.click(selectAllButton); + expect(screen.getByLabelText('Name')).toBeChecked(); + expect(screen.getByLabelText('Status')).toBeChecked(); + expect(screen.getByLabelText('Version')).toBeChecked(); + }); + + it('selects no columns', async () => { + render(); + const menuToggle = screen.getByLabelText('Select all').closest('button'); + if (menuToggle) { + await userEvent.click(menuToggle); + } + const selectNoneButton = screen.getByText('Select none'); + await userEvent.click(selectNoneButton); + expect(screen.getByLabelText('Name')).not.toBeChecked(); + expect(screen.getByLabelText('Status')).not.toBeChecked(); + expect(screen.getByLabelText('Version')).not.toBeChecked(); + }); + + it('saves changes', async () => { + const onSave = jest.fn(); + render(); + const saveButton = screen.getByText('Save'); + await userEvent.click(saveButton); + expect(onSave).toHaveBeenCalledWith(expect.any(Array)); + }); + + it('reorders columns with drag and drop', () => { + const onOrderChange = jest.fn(); + const { container } = render(); + const firstItem = screen.getByText('Name').closest('li'); + const secondItem = screen.getByText('Status').closest('li'); + + if (firstItem && secondItem) { + fireEvent.dragStart(firstItem); + fireEvent.dragEnter(secondItem); + fireEvent.dragOver(secondItem); + fireEvent.drop(secondItem); + fireEvent.dragEnd(firstItem); + + const listItems = container.querySelectorAll('li'); + expect(listItems[0].textContent).toContain('Status'); + expect(listItems[1].textContent).toContain('Name'); + expect(onOrderChange).toHaveBeenCalledWith([ + expect.objectContaining({ key: 'status' }), + expect.objectContaining({ key: 'name' }), + expect.objectContaining({ key: 'version' }), + ]); + } + }); +}); diff --git a/packages/module/src/Column/Column.tsx b/packages/module/src/Column/Column.tsx new file mode 100644 index 00000000..09b41890 --- /dev/null +++ b/packages/module/src/Column/Column.tsx @@ -0,0 +1,195 @@ +import type { FunctionComponent } from 'react'; +import { useState, useEffect } from 'react'; +import { + DataListItem, + DataList, + DataListItemRow, + DataListCheck, + DataListCell, + DataListItemCells, + DataListControl, + DataListDragButton, + Button, + ButtonVariant, + Title, + Checkbox, + Dropdown, + DropdownItem, + MenuToggle +} from '@patternfly/react-core'; +import { + DragDrop, + Droppable, + Draggable +} from '@patternfly/react-core/deprecated'; + +export interface ColumnColumn { + /** Internal identifier of a column by which table displayed columns are filtered. */ + key: string; + /** The actual display name of the column possibly with a tooltip or icon. */ + title: React.ReactNode; + /** If user changes checkboxes, the component will send back column array with this property altered. */ + isShown?: boolean; + /** Set to false if the column should be hidden initially */ + isShownByDefault: boolean; + /** The checkbox will be disabled, this is applicable to columns which should not be toggleable by user */ + isUntoggleable?: boolean; +} + +export interface ColumnProps { + /** Current column state */ + columns: ColumnColumn[]; + /* Column description text */ + description?: string; + /* Column title text */ + title?: string; + /** Custom OUIA ID */ + ouiaId?: string | number; + /** Callback when a column is selected or deselected */ + onSelect?: (column: ColumnColumn) => void; + /** Callback when the column order changes */ + onOrderChange?: (columns: ColumnColumn[]) => void; + /** Callback to save the column state */ + onSave?: (columns: ColumnColumn[]) => void; + /** Callback to close the modal */ + onCancel?: () => void; +} + +const Column: FunctionComponent = ( + { columns, + description, + title, + ouiaId = 'Column', + onSelect, + onOrderChange, + onSave, + onCancel }: ColumnProps) => { + + const [ isDropdownOpen, setIsDropdownOpen ] = useState(false); + const [ currentColumns, setCurrentColumns ] = useState( + () => columns.map(column => ({ ...column, isShown: column.isShown ?? column.isShownByDefault, id: column.key })) + ); + + useEffect(() => { + setCurrentColumns(columns.map(column => ({ ...column, isShown: column.isShown ?? column.isShownByDefault, id: column.key }))); + }, [ columns ]); + + const handleChange = index => { + const newColumns = [ ...currentColumns ]; + const changedColumn = { ...newColumns[index] }; + + changedColumn.isShown = !changedColumn.isShown; + newColumns[index] = changedColumn; + + setCurrentColumns(newColumns); + onSelect?.(changedColumn); + }; + + const onDrag = (source, dest) => { + if (dest) { + const newColumns = [ ...currentColumns ]; + const [ removed ] = newColumns.splice(source.index, 1); + newColumns.splice(dest.index, 0, removed); + setCurrentColumns(newColumns); + onOrderChange?.(newColumns); + return true; + } + return false; + }; + + const handleSave = () => { + onSave?.(currentColumns); + onCancel?.(); + } + + const onSelectAll = (select = true) => { + const newColumns = currentColumns.map(c => ({ ...c, isShown: c.isUntoggleable ? c.isShown : select })); + setCurrentColumns(newColumns); + onOrderChange?.(newColumns); + } + + const isAllSelected = () => currentColumns.every(c => c.isShown || c.isUntoggleable); + const isSomeSelected = () => currentColumns.some(c => c.isShown); + + const dropdownItems = [ + onSelectAll(true)}>Select all, + onSelectAll(false)}>Select none + ]; + + const content = ( + <> + {title} + {description &&

{description}

} +
+ setIsDropdownOpen(false)} + toggle={(toggleRef) => ( + setIsDropdownOpen(!isDropdownOpen)} + isExpanded={isDropdownOpen} + > + + + )} + isOpen={isDropdownOpen} + > + {dropdownItems} + +
+ + + + {currentColumns.map((column, index) => + + + + + + + handleChange(index)} + isDisabled={column.isUntoggleable} + aria-labelledby={`${ouiaId}-column-${index}-label`} + ouiaId={`${ouiaId}-column-${index}-checkbox`} + id={`${ouiaId}-column-${index}-checkbox`} + /> + + + + ]} + /> + + + + )} + + + +
+ + +
+ + ); + + return content; +} + +export default Column; diff --git a/packages/module/src/Column/index.ts b/packages/module/src/Column/index.ts new file mode 100644 index 00000000..8f5de7e6 --- /dev/null +++ b/packages/module/src/Column/index.ts @@ -0,0 +1,2 @@ +export { default } from './Column'; +export * from './Column'; diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 640a3cee..3ac16b0c 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -72,6 +72,9 @@ export * from './ErrorBoundary'; export { default as ColumnManagementModal } from './ColumnManagementModal'; export * from './ColumnManagementModal'; +export { default as Column } from './Column'; +export * from './Column'; + export { default as CloseButton } from './CloseButton'; export * from './CloseButton'; From ab3fc5aa5014bc1450c1a302b5c1305c0852516a Mon Sep 17 00:00:00 2001 From: Austin Pinkerton Date: Wed, 16 Jul 2025 16:01:32 -0400 Subject: [PATCH 2/2] feat: refactor Column into ColumnManagement and add patternfly-docs/examples --- .../ColumnManagement/ColumnManagement.md | 28 +++++ .../ColumnManagementExample.tsx | 57 ++++++++++ packages/module/src/Column/Column.test.tsx | 101 ------------------ packages/module/src/Column/index.ts | 2 - .../ColumnManagement.test.tsx | 77 +++++++++++++ .../ColumnManagement.tsx} | 33 +++--- packages/module/src/ColumnManagement/index.ts | 2 + packages/module/src/index.ts | 4 +- 8 files changed, 183 insertions(+), 121 deletions(-) create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagement.md create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagementExample.tsx delete mode 100644 packages/module/src/Column/Column.test.tsx delete mode 100644 packages/module/src/Column/index.ts create mode 100644 packages/module/src/ColumnManagement/ColumnManagement.test.tsx rename packages/module/src/{Column/Column.tsx => ColumnManagement/ColumnManagement.tsx} (87%) create mode 100644 packages/module/src/ColumnManagement/index.ts diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagement.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagement.md new file mode 100644 index 00000000..40de02c8 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagement.md @@ -0,0 +1,28 @@ +--- +# Sidenav top-level section +# should be the same for all markdown files +section: Component groups +subsection: Helpers +# Sidenav secondary level section +# should be the same for all markdown files +id: Column management +# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility) +source: react +# If you use typescript, the name of the interface to display props for +# These are found through the sourceProps function provided in patternfly-docs.source.js +propComponents: ['ColumnManagement'] +sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagement.md +--- + +import ColumnManagement from '@patternfly/react-component-groups/dist/dynamic/ColumnManagement'; +import { FunctionComponent, useState } from 'react'; + +The **column management** component can be used to implement customizable table columns. Columns can be configured to be enabled or disabled by default or be unhidable. + +## Examples + +### Basic column list + +The order of the columns can be changed by dragging and dropping the columns themselves. This list can be used within a page or within a modal. Always make sure to set `isShownByDefault` and `isShown` to the same boolean value in the initial state. + +```js file="./ColumnManagementExample.tsx" diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagementExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagementExample.tsx new file mode 100644 index 00000000..16e02420 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/ColumnManagement/ColumnManagementExample.tsx @@ -0,0 +1,57 @@ +import { FunctionComponent, useState } from 'react'; +import { Column, ColumnManagement } from '@patternfly/react-component-groups'; + +const DEFAULT_COLUMNS: Column[] = [ + { + title: 'ID', + key: 'id', + isShownByDefault: true, + isShown: true, + isUntoggleable: true + }, + { + title: 'Publish date', + key: 'publishDate', + isShownByDefault: true, + isShown: true + }, + { + title: 'Impact', + key: 'impact', + isShownByDefault: true, + isShown: true + }, + { + title: 'Score', + key: 'score', + isShownByDefault: false, + isShown: false + } +]; + +export const ColumnExample: FunctionComponent = () => { + const [ columns, setColumns ] = useState(DEFAULT_COLUMNS); + + return ( + { + const newColumns = [...columns]; + const changedColumn = newColumns.find(c => c.key === col.key); + if (changedColumn) { + changedColumn.isShown = col.isShown; + } + setColumns(newColumns); + }} + onSelectAll={(newColumns) => setColumns(newColumns)} + onSave={(newColumns) => { + setColumns(newColumns); + alert('Changes saved!'); + }} + onCancel={() => alert('Changes cancelled!')} + /> + ); +}; diff --git a/packages/module/src/Column/Column.test.tsx b/packages/module/src/Column/Column.test.tsx deleted file mode 100644 index 7c30eaca..00000000 --- a/packages/module/src/Column/Column.test.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { render, screen, fireEvent } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import '@testing-library/jest-dom'; -import Column from '../Column'; - -const mockColumns = [ - { key: 'name', title: 'Name', isShownByDefault: true }, - { key: 'status', title: 'Status', isShownByDefault: true }, - { key: 'version', title: 'Version', isShownByDefault: false }, -]; - -describe('Column', () => { - it('renders with initial columns', () => { - render(); - expect(screen.getByLabelText('Name')).toBeChecked(); - expect(screen.getByLabelText('Status')).toBeChecked(); - expect(screen.getByLabelText('Version')).not.toBeChecked(); - }); - - it('renders title and description', () => { - render(); - expect(screen.getByText('Test Title')).toBeInTheDocument(); - expect(screen.getByText('Test Description')).toBeInTheDocument(); - }); - - it('renders a cancel button', () => { - const onCancel = jest.fn(); - render(); - const cancelButton = screen.getByText('Cancel'); - expect(cancelButton).toBeInTheDocument(); - userEvent.click(cancelButton); - expect(onCancel).toHaveBeenCalled(); - }); - - it('toggles a column', async () => { - const onSelect = jest.fn(); - render(); - const nameCheckbox = screen.getByLabelText('Name'); - await userEvent.click(nameCheckbox); - expect(nameCheckbox).not.toBeChecked(); - expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ key: 'name', isShown: false })); - }); - - it('selects all columns', async () => { - render(); - const menuToggle = screen.getByLabelText('Select all').closest('button'); - if (menuToggle) { - await userEvent.click(menuToggle); - } - const selectAllButton = screen.getByText('Select all'); - await userEvent.click(selectAllButton); - expect(screen.getByLabelText('Name')).toBeChecked(); - expect(screen.getByLabelText('Status')).toBeChecked(); - expect(screen.getByLabelText('Version')).toBeChecked(); - }); - - it('selects no columns', async () => { - render(); - const menuToggle = screen.getByLabelText('Select all').closest('button'); - if (menuToggle) { - await userEvent.click(menuToggle); - } - const selectNoneButton = screen.getByText('Select none'); - await userEvent.click(selectNoneButton); - expect(screen.getByLabelText('Name')).not.toBeChecked(); - expect(screen.getByLabelText('Status')).not.toBeChecked(); - expect(screen.getByLabelText('Version')).not.toBeChecked(); - }); - - it('saves changes', async () => { - const onSave = jest.fn(); - render(); - const saveButton = screen.getByText('Save'); - await userEvent.click(saveButton); - expect(onSave).toHaveBeenCalledWith(expect.any(Array)); - }); - - it('reorders columns with drag and drop', () => { - const onOrderChange = jest.fn(); - const { container } = render(); - const firstItem = screen.getByText('Name').closest('li'); - const secondItem = screen.getByText('Status').closest('li'); - - if (firstItem && secondItem) { - fireEvent.dragStart(firstItem); - fireEvent.dragEnter(secondItem); - fireEvent.dragOver(secondItem); - fireEvent.drop(secondItem); - fireEvent.dragEnd(firstItem); - - const listItems = container.querySelectorAll('li'); - expect(listItems[0].textContent).toContain('Status'); - expect(listItems[1].textContent).toContain('Name'); - expect(onOrderChange).toHaveBeenCalledWith([ - expect.objectContaining({ key: 'status' }), - expect.objectContaining({ key: 'name' }), - expect.objectContaining({ key: 'version' }), - ]); - } - }); -}); diff --git a/packages/module/src/Column/index.ts b/packages/module/src/Column/index.ts deleted file mode 100644 index 8f5de7e6..00000000 --- a/packages/module/src/Column/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Column'; -export * from './Column'; diff --git a/packages/module/src/ColumnManagement/ColumnManagement.test.tsx b/packages/module/src/ColumnManagement/ColumnManagement.test.tsx new file mode 100644 index 00000000..dadf3bb4 --- /dev/null +++ b/packages/module/src/ColumnManagement/ColumnManagement.test.tsx @@ -0,0 +1,77 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import '@testing-library/jest-dom'; +import ColumnManagement from './ColumnManagement'; + +const mockColumns = [ + { key: 'name', title: 'Name', isShown: true, isShownByDefault: true }, + { key: 'status', title: 'Status', isShown: true, isShownByDefault: true }, + { key: 'version', title: 'Version', isShown: false, isShownByDefault: false }, +]; + +describe('Column', () => { + it('renders with initial columns', () => { + render(); + expect(screen.getByTestId('column-check-name')).toBeChecked(); + expect(screen.getByTestId('column-check-status')).toBeChecked(); + expect(screen.getByTestId('column-check-version')).not.toBeChecked(); + }); + + it('renders title and description', () => { + render(); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + }); + + it('renders a cancel button', async () => { + const onCancel = jest.fn(); + render(); + const cancelButton = screen.getByText('Cancel'); + expect(cancelButton).toBeInTheDocument(); + await userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalled(); + }); + + it('toggles a column', async () => { + const onSelect = jest.fn(); + render(); + const nameCheckbox = screen.getByTestId('column-check-name'); + await userEvent.click(nameCheckbox); + expect(nameCheckbox).not.toBeChecked(); + expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ key: 'name', isShown: false })); + }); + + it('selects all columns', async () => { + render(); + const menuToggle = screen.getByLabelText('Select all').closest('button'); + if (menuToggle) { + await userEvent.click(menuToggle); + } + const selectAllButton = screen.getByText('Select all'); + await userEvent.click(selectAllButton); + expect(screen.getByTestId('column-check-name')).toBeChecked(); + expect(screen.getByTestId('column-check-status')).toBeChecked(); + expect(screen.getByTestId('column-check-version')).toBeChecked(); + }); + + it('selects no columns', async () => { + render(); + const menuToggle = screen.getByLabelText('Select all').closest('button'); + if (menuToggle) { + await userEvent.click(menuToggle); + } + const selectNoneButton = screen.getByText('Select none'); + await userEvent.click(selectNoneButton); + expect(screen.getByTestId('column-check-name')).not.toBeChecked(); + expect(screen.getByTestId('column-check-status')).not.toBeChecked(); + expect(screen.getByTestId('column-check-version')).not.toBeChecked(); + }); + + it('saves changes', async () => { + const onSave = jest.fn(); + render(); + const saveButton = screen.getByText('Save'); + await userEvent.click(saveButton); + expect(onSave).toHaveBeenCalledWith(expect.any(Array)); + }); +}); diff --git a/packages/module/src/Column/Column.tsx b/packages/module/src/ColumnManagement/ColumnManagement.tsx similarity index 87% rename from packages/module/src/Column/Column.tsx rename to packages/module/src/ColumnManagement/ColumnManagement.tsx index 09b41890..680d486e 100644 --- a/packages/module/src/Column/Column.tsx +++ b/packages/module/src/ColumnManagement/ColumnManagement.tsx @@ -23,7 +23,7 @@ import { Draggable } from '@patternfly/react-core/deprecated'; -export interface ColumnColumn { +export interface Column { /** Internal identifier of a column by which table displayed columns are filtered. */ key: string; /** The actual display name of the column possibly with a tooltip or icon. */ @@ -38,7 +38,7 @@ export interface ColumnColumn { export interface ColumnProps { /** Current column state */ - columns: ColumnColumn[]; + columns: Column[]; /* Column description text */ description?: string; /* Column title text */ @@ -46,21 +46,24 @@ export interface ColumnProps { /** Custom OUIA ID */ ouiaId?: string | number; /** Callback when a column is selected or deselected */ - onSelect?: (column: ColumnColumn) => void; + onSelect?: (column: Column) => void; + /** Callback when all columns are selected or deselected */ + onSelectAll?: (columns: Column[]) => void; /** Callback when the column order changes */ - onOrderChange?: (columns: ColumnColumn[]) => void; + onOrderChange?: (columns: Column[]) => void; /** Callback to save the column state */ - onSave?: (columns: ColumnColumn[]) => void; + onSave?: (columns: Column[]) => void; /** Callback to close the modal */ onCancel?: () => void; } -const Column: FunctionComponent = ( +const ColumnManagement: FunctionComponent = ( { columns, description, title, ouiaId = 'Column', onSelect, + onSelectAll, onOrderChange, onSave, onCancel }: ColumnProps) => { @@ -99,24 +102,23 @@ const Column: FunctionComponent = ( const handleSave = () => { onSave?.(currentColumns); - onCancel?.(); } - const onSelectAll = (select = true) => { + const handleSelectAll = (select = true) => { const newColumns = currentColumns.map(c => ({ ...c, isShown: c.isUntoggleable ? c.isShown : select })); setCurrentColumns(newColumns); - onOrderChange?.(newColumns); + onSelectAll?.(newColumns); } const isAllSelected = () => currentColumns.every(c => c.isShown || c.isUntoggleable); const isSomeSelected = () => currentColumns.some(c => c.isShown); const dropdownItems = [ - onSelectAll(true)}>Select all, - onSelectAll(false)}>Select none + handleSelectAll(true)}>Select all, + handleSelectAll(false)}>Select none ]; - const content = ( + return ( <> {title} {description &&

{description}

} @@ -146,7 +148,7 @@ const Column: FunctionComponent = ( {currentColumns.map((column, index) => - + = ( /> handleChange(index)} isDisabled={column.isUntoggleable} @@ -188,8 +191,6 @@ const Column: FunctionComponent = ( ); - - return content; } -export default Column; +export default ColumnManagement; diff --git a/packages/module/src/ColumnManagement/index.ts b/packages/module/src/ColumnManagement/index.ts new file mode 100644 index 00000000..283ecbe7 --- /dev/null +++ b/packages/module/src/ColumnManagement/index.ts @@ -0,0 +1,2 @@ +export { default } from './ColumnManagement'; +export * from './ColumnManagement'; diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 3ac16b0c..54683748 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -72,8 +72,8 @@ export * from './ErrorBoundary'; export { default as ColumnManagementModal } from './ColumnManagementModal'; export * from './ColumnManagementModal'; -export { default as Column } from './Column'; -export * from './Column'; +export { default as ColumnManagement } from './ColumnManagement'; +export * from './ColumnManagement'; export { default as CloseButton } from './CloseButton'; export * from './CloseButton';