@canonical/maas-react-components 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@canonical/maas-react-components.es.js +1802 -1627
- package/dist/@canonical/maas-react-components.umd.js +17 -17
- package/dist/maas-react-components.css +1 -1
- package/dist/src/lib/components/GenericTable/GenericTable.d.ts +10 -3
- package/dist/src/lib/components/GenericTable/components/TableCheckbox/TableCheckbox.d.ts +3 -3
- package/dist/src/lib/components/GenericTable/types.d.ts +5 -1
- package/dist/src/lib/components/GenericTable/utils/processColumnDefs.d.ts +1 -2
- package/dist/src/lib/components/GenericTable/utils/renderLoadingRows.d.ts +4 -2
- package/dist/src/lib/sections/Navigation/Link/Link.stories.d.ts +19 -0
- package/dist/src/lib/sections/SidePanel/SidePanel.d.ts +37 -0
- package/dist/src/lib/sections/SidePanel/SidePanel.stories.d.ts +10 -0
- package/dist/src/lib/sections/SidePanel/SidePanel.test.d.ts +1 -0
- package/dist/src/lib/sections/SidePanel/SidePanelContextProvider/SidePanelContextProvider.d.ts +95 -0
- package/dist/src/lib/sections/SidePanel/index.d.ts +2 -0
- package/dist/src/lib/sections/index.d.ts +4 -3
- package/package.json +3 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DetailedHTMLProps, Dispatch, HTMLAttributes, ReactElement, ReactNode, RefObject, SetStateAction } from 'react';
|
|
2
2
|
import { Column, ColumnDef, ColumnSort, Header, Row, SortingState } from '@tanstack/react-table';
|
|
3
3
|
import { PaginationBarProps } from './components/PaginationBar';
|
|
4
|
-
import { SelectionProps, GenericTableData } from './types';
|
|
4
|
+
import { SelectionProps, GenericTableData, ColumnVisibilityProps } from './types';
|
|
5
5
|
type GenericTableProps<T extends GenericTableData> = {
|
|
6
6
|
"aria-label"?: string;
|
|
7
7
|
className?: string;
|
|
@@ -15,17 +15,20 @@ type GenericTableProps<T extends GenericTableData> = {
|
|
|
15
15
|
isLoading: boolean;
|
|
16
16
|
loadingVariant?: "spinner" | "skeleton";
|
|
17
17
|
skeletonRowCount?: number;
|
|
18
|
+
skeletonGroupCount?: number;
|
|
18
19
|
noData?: ReactNode;
|
|
19
20
|
pagination?: PaginationBarProps;
|
|
20
21
|
pinGroup?: {
|
|
21
22
|
value: string;
|
|
22
23
|
isTop: boolean;
|
|
23
24
|
}[];
|
|
25
|
+
columnVisibility?: ColumnVisibilityProps;
|
|
24
26
|
sorting?: ColumnSort[];
|
|
25
27
|
selection?: SelectionProps<T>;
|
|
26
28
|
setSorting?: Dispatch<SetStateAction<SortingState>>;
|
|
27
29
|
showChevron?: boolean;
|
|
28
30
|
variant?: "full-height" | "regular";
|
|
31
|
+
debug?: boolean;
|
|
29
32
|
} & DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
|
30
33
|
/**
|
|
31
34
|
* GenericTable - A flexible and feature-rich table component for React applications
|
|
@@ -39,6 +42,8 @@ type GenericTableProps<T extends GenericTableData> = {
|
|
|
39
42
|
* @param {Object} props - Component props
|
|
40
43
|
* @param {string} [props.className] - Additional CSS class for the table wrapper
|
|
41
44
|
* @param {ColumnDef<T, Partial<T>>[]} props.columns - Column definitions
|
|
45
|
+
* @param {ColumnVisibilityProps} [props.columnVisibility] - Controlled column visibility state and setter; when omitted, visibility is managed internally. See {@link ColumnVisibilityProps} for all sub-options
|
|
46
|
+
* (columnVisibility, setColumnVisibility).
|
|
42
47
|
* @param {RefObject<HTMLElement | null>} [props.containerRef] - Reference to container for size calculations
|
|
43
48
|
* @param {T[]} props.data - Table data array
|
|
44
49
|
* @param {(row: Row<T>, column: Column<T>) => boolean} [props.filterCells] - Function to filter which cells should be displayed
|
|
@@ -47,7 +52,8 @@ type GenericTableProps<T extends GenericTableData> = {
|
|
|
47
52
|
* @param {string[]} [props.groupBy] - Column IDs to group rows by
|
|
48
53
|
* @param {boolean} props.isLoading - Loading state to display placeholder content
|
|
49
54
|
* @param {"spinner" | "skeleton"} [props.loadingVariant="spinner"] - Loading display style; "spinner" shows a single spinner row, "skeleton" renders skeletonRowCount pulsing skeleton rows using meta.skeleton per column when defined, falling back to a default Placeholder block
|
|
50
|
-
* @param {number} [props.skeletonRowCount=10] - Number of skeleton rows to render when loadingVariant="skeleton"
|
|
55
|
+
* @param {number} [props.skeletonRowCount=10] - Number of skeleton rows to render per group (or total when ungrouped) when loadingVariant="skeleton"
|
|
56
|
+
* @param {number} [props.skeletonGroupCount=2] - Number of skeleton group rows to render when loadingVariant="skeleton" and groupBy is set
|
|
51
57
|
* @param {ReactNode} [props.noData] - Content to display when no data is available
|
|
52
58
|
* @param {PaginationBarProps} [props.pagination] - Pagination configuration
|
|
53
59
|
* @param {{ value: string; isTop: boolean }[]} [props.pinGroup] - Group pinning configuration
|
|
@@ -57,6 +63,7 @@ type GenericTableProps<T extends GenericTableData> = {
|
|
|
57
63
|
* (filterSelectable, disabledSelectionTooltip, rowSelection, rowSelectionLabelKey, setRowSelection).
|
|
58
64
|
* @param {boolean} [props.showChevron=false] - Show group row expansion state chevrons
|
|
59
65
|
* @param {"full-height" | "regular"} [props.variant="full-height"] - Table layout variant
|
|
66
|
+
* @param {boolean} [props.debug] - React Table debug output
|
|
60
67
|
*
|
|
61
68
|
* @returns {ReactElement} - The rendered table component
|
|
62
69
|
*
|
|
@@ -80,5 +87,5 @@ type GenericTableProps<T extends GenericTableData> = {
|
|
|
80
87
|
* }}
|
|
81
88
|
* />
|
|
82
89
|
*/
|
|
83
|
-
export declare const GenericTable: <T extends GenericTableData>({ "aria-label": tableAriaLabel, className, columns: initialColumns, containerRef, data: initialData, filterCells, filterHeaders, getSubRows, groupBy, isLoading, loadingVariant, skeletonRowCount, noData, pagination, pinGroup, sorting: externalSorting, selection, setSorting: setExternalSorting, showChevron, variant, ...divProps }: GenericTableProps<T>) => ReactElement;
|
|
90
|
+
export declare const GenericTable: <T extends GenericTableData>({ "aria-label": tableAriaLabel, className, columns: initialColumns, columnVisibility: externalColumnVisibility, containerRef, data: initialData, filterCells, filterHeaders, getSubRows, groupBy, isLoading, loadingVariant, skeletonRowCount, skeletonGroupCount, noData, pagination, pinGroup, sorting: externalSorting, selection, setSorting: setExternalSorting, showChevron, variant, debug, ...divProps }: GenericTableProps<T>) => ReactElement;
|
|
84
91
|
export {};
|
|
@@ -6,10 +6,10 @@ type TableCheckboxProps<T> = Partial<DetailedHTMLProps<InputHTMLAttributes<HTMLI
|
|
|
6
6
|
};
|
|
7
7
|
declare const TableCheckbox: {
|
|
8
8
|
<T>({ row, disabledTooltip, isNested, ...props }: TableCheckboxProps<T> & {
|
|
9
|
-
disabledTooltip
|
|
10
|
-
isNested
|
|
9
|
+
disabledTooltip?: string | ((row: Row<T>) => string);
|
|
10
|
+
isNested?: boolean;
|
|
11
11
|
}): ReactElement | null;
|
|
12
12
|
All: <T>({ table, ...props }: TableCheckboxProps<T>) => import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
-
Group: <T>({ row, ...props }: TableCheckboxProps<T>) => import("react/jsx-runtime").JSX.Element
|
|
13
|
+
Group: <T>({ row, ...props }: TableCheckboxProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
14
14
|
};
|
|
15
15
|
export default TableCheckbox;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
2
|
-
import { Row, RowData, RowSelectionState } from '@tanstack/react-table';
|
|
2
|
+
import { Row, RowData, RowSelectionState, VisibilityState } from '@tanstack/react-table';
|
|
3
3
|
declare module "@tanstack/react-table" {
|
|
4
4
|
interface ColumnMeta<TData extends RowData, TValue = unknown> {
|
|
5
5
|
/** Custom loading skeleton renderer. Overrides the default shimmer for this column. */
|
|
@@ -25,3 +25,7 @@ export type SelectionProps<T extends GenericTableData> = {
|
|
|
25
25
|
rowSelection?: RowSelectionState;
|
|
26
26
|
setRowSelection?: Dispatch<SetStateAction<RowSelectionState>>;
|
|
27
27
|
};
|
|
28
|
+
export type ColumnVisibilityProps = {
|
|
29
|
+
columnVisibility: VisibilityState;
|
|
30
|
+
setColumnVisibility: Dispatch<SetStateAction<VisibilityState>>;
|
|
31
|
+
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { ColumnDef } from '@tanstack/react-table';
|
|
2
2
|
import { SelectionProps, GenericTableData } from '../types';
|
|
3
|
-
export declare const processColumnDefs: <T extends GenericTableData>({ canSelect, initialColumns,
|
|
3
|
+
export declare const processColumnDefs: <T extends GenericTableData>({ canSelect, initialColumns, groupBy, getSubRows, selection, showChevron, }: {
|
|
4
4
|
canSelect: boolean;
|
|
5
5
|
initialColumns: ColumnDef<T, Partial<T>>[];
|
|
6
|
-
isLoading: boolean;
|
|
7
6
|
groupBy: string[] | undefined;
|
|
8
7
|
getSubRows?: (originalRow: T, index: number) => T[] | undefined;
|
|
9
8
|
selection?: SelectionProps<T>;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { ColumnDef, Header, Table } from '@tanstack/react-table';
|
|
1
|
+
import { Column, ColumnDef, Header, Row, Table } from '@tanstack/react-table';
|
|
2
2
|
import { GenericTableData } from '../types';
|
|
3
|
-
export declare const renderLoadingRows: <T extends GenericTableData>({ table, columns, filterHeaders, loadingVariant, skeletonRowCount, }: {
|
|
3
|
+
export declare const renderLoadingRows: <T extends GenericTableData>({ table, columns, filterHeaders, filterCells, loadingVariant, skeletonRowCount, skeletonGroupCount, }: {
|
|
4
4
|
table: Table<T>;
|
|
5
5
|
columns: ColumnDef<T, Partial<T>>[];
|
|
6
6
|
filterHeaders: (header: Header<T, unknown>) => boolean;
|
|
7
|
+
filterCells: (row: Row<T>, column: Column<T>) => boolean;
|
|
7
8
|
loadingVariant?: "skeleton" | "spinner";
|
|
8
9
|
skeletonRowCount: number;
|
|
10
|
+
skeletonGroupCount: number;
|
|
9
11
|
}) => import("react/jsx-runtime").JSX.Element | import("react/jsx-runtime").JSX.Element[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import { Navigation } from '../Navigation';
|
|
3
|
+
declare const meta: Meta<typeof Navigation.Link>;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const Example: {
|
|
6
|
+
args: {
|
|
7
|
+
as: string;
|
|
8
|
+
href: string;
|
|
9
|
+
"aria-current": string;
|
|
10
|
+
children: import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export declare const ButtonExample: {
|
|
14
|
+
args: {
|
|
15
|
+
as: <P>({ appearance, children, className, dense, disabled, element: Component, hasIcon, inline, onClick, small, ...buttonProps }: import('@canonical/react-components').ButtonProps<P>) => React.JSX.Element;
|
|
16
|
+
appearance: string;
|
|
17
|
+
children: import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Slide-in aside panel rendered at the edge of the page.
|
|
4
|
+
*
|
|
5
|
+
* Reads all state from the nearest `SidePanelContextProvider` via `useSidePanel`.
|
|
6
|
+
* The panel has no props of its own — open it by calling `openSidePanel` from the hook.
|
|
7
|
+
*
|
|
8
|
+
* Behaviour:
|
|
9
|
+
* - Collapses automatically when the current route changes
|
|
10
|
+
* - Closes when the Escape key is pressed
|
|
11
|
+
* - Resets its size to `"regular"` on unmount
|
|
12
|
+
*
|
|
13
|
+
* Size variants (set via `openSidePanel` or `setSidePanelSize`):
|
|
14
|
+
* - `"narrow"` — adds the `is-narrow` CSS modifier
|
|
15
|
+
* - `"regular"` — default, no modifier class
|
|
16
|
+
* - `"wide"` — adds the `is-wide` CSS modifier
|
|
17
|
+
* - `"large"` — adds the `is-large` CSS modifier
|
|
18
|
+
*
|
|
19
|
+
* @requires SidePanelContextProvider — must be present higher in the tree
|
|
20
|
+
* @requires A React Router context — must be rendered inside a Router
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* // In your app root:
|
|
25
|
+
* <SidePanelContextProvider>
|
|
26
|
+
* <Router>
|
|
27
|
+
* <main>…</main>
|
|
28
|
+
* <SidePanel />
|
|
29
|
+
* </Router>
|
|
30
|
+
* </SidePanelContextProvider>
|
|
31
|
+
*
|
|
32
|
+
* // Anywhere in the tree:
|
|
33
|
+
* const { openSidePanel } = useSidePanel();
|
|
34
|
+
* openSidePanel({ component: EditForm, title: "Edit item", size: "wide" });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare const SidePanel: () => ReactElement;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { SidePanel } from './SidePanel';
|
|
3
|
+
declare const meta: Meta<typeof SidePanel>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof SidePanel>;
|
|
6
|
+
export declare const Interactive: Story;
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
export declare const NarrowSize: Story;
|
|
9
|
+
export declare const WideSize: Story;
|
|
10
|
+
export declare const LargeSize: Story;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/src/lib/sections/SidePanel/SidePanelContextProvider/SidePanelContextProvider.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ComponentType, PropsWithChildren, ReactElement } from 'react';
|
|
2
|
+
type SidePanelSize = "large" | "narrow" | "regular" | "wide";
|
|
3
|
+
interface SidePanelState<TProps = Record<string, unknown>> {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
title: string;
|
|
6
|
+
size: SidePanelSize;
|
|
7
|
+
component: ComponentType<TProps> | null;
|
|
8
|
+
props: TProps;
|
|
9
|
+
}
|
|
10
|
+
export interface SidePanelActions {
|
|
11
|
+
openSidePanel: <TProps extends Record<string, unknown> = Record<string, unknown>>(params: {
|
|
12
|
+
component: ComponentType<TProps>;
|
|
13
|
+
title: string;
|
|
14
|
+
props?: TProps;
|
|
15
|
+
size?: SidePanelSize;
|
|
16
|
+
}) => void;
|
|
17
|
+
closeSidePanel: () => void;
|
|
18
|
+
setSidePanelSize: (size: SidePanelSize) => void;
|
|
19
|
+
}
|
|
20
|
+
type SidePanelContextValue = SidePanelActions & SidePanelState;
|
|
21
|
+
/**
|
|
22
|
+
* Hook for managing side panel state and actions.
|
|
23
|
+
*
|
|
24
|
+
* Provides methods to open/close side panels with React components and manages
|
|
25
|
+
* panel size and visibility state.
|
|
26
|
+
*
|
|
27
|
+
* @returns Object containing:
|
|
28
|
+
* - `isOpen`: Boolean indicating if the side panel is currently open
|
|
29
|
+
* - `title`: Current panel title string
|
|
30
|
+
* - `size`: Current panel size ('narrow' | 'regular' | 'wide' | 'large')
|
|
31
|
+
* - `component`: Currently rendered component
|
|
32
|
+
* - `props`: Props passed to the current component
|
|
33
|
+
* - `openSidePanel({component, title, props?, size?})`: Opens panel with given component
|
|
34
|
+
* - `closeSidePanel()`: Closes the panel and resets state
|
|
35
|
+
* - `setSidePanelSize(size)`: Changes the panel width
|
|
36
|
+
*
|
|
37
|
+
* @throws Error when used outside SidePanelProvider
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* const { open, close, isOpen } = useSidePanel();
|
|
42
|
+
*
|
|
43
|
+
* // Open a panel with a form component
|
|
44
|
+
* const handleEdit = (userId: number) => {
|
|
45
|
+
* open(EditUserForm, 'Edit User', { userId }, 'wide');
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* // Close the panel
|
|
49
|
+
* const handleCancel = () => {
|
|
50
|
+
* close();
|
|
51
|
+
* };
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare const useSidePanel: () => SidePanelContextValue;
|
|
55
|
+
/**
|
|
56
|
+
* Provider component for managing side panel state and actions.
|
|
57
|
+
*
|
|
58
|
+
* Wraps your application or subtree to provide side panel context to all child
|
|
59
|
+
* components. Child components can use the `useSidePanel` hook to access and
|
|
60
|
+
* control the side panel.
|
|
61
|
+
*
|
|
62
|
+
* @param children - React elements to render within the provider
|
|
63
|
+
*
|
|
64
|
+
* @returns A React element wrapping children with SidePanelContext
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* function App() {
|
|
69
|
+
* return (
|
|
70
|
+
* <SidePanelContextProvider>
|
|
71
|
+
* <MainLayout />
|
|
72
|
+
* </SidePanelContextProvider>
|
|
73
|
+
* );
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* function MainLayout() {
|
|
77
|
+
* const { openSidePanel, closeSidePanel, isOpen } = useSidePanel();
|
|
78
|
+
*
|
|
79
|
+
* return (
|
|
80
|
+
* <>
|
|
81
|
+
* <button onClick={() => openSidePanel({
|
|
82
|
+
* component: UserForm,
|
|
83
|
+
* title: 'Create User',
|
|
84
|
+
* size: 'wide'
|
|
85
|
+
* })}>
|
|
86
|
+
* New User
|
|
87
|
+
* </button>
|
|
88
|
+
* {isOpen && <SidePanel />}
|
|
89
|
+
* </>
|
|
90
|
+
* );
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare const SidePanelContextProvider: ({ children, }: PropsWithChildren) => ReactElement;
|
|
95
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './InputGroup';
|
|
1
|
+
export * from './ContentSection';
|
|
3
2
|
export * from './FormSection';
|
|
3
|
+
export * from './InputGroup';
|
|
4
4
|
export * from './MainToolbar';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './Navigation';
|
|
6
|
+
export * from './SidePanel';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonical/maas-react-components",
|
|
3
3
|
"description": "React components for use in MAAS UI projects.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/canonical/maas-react-components.git"
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"vitest": "^3.0.8"
|
|
94
94
|
},
|
|
95
95
|
"peerDependencies": {
|
|
96
|
-
"@canonical/react-components": "^
|
|
96
|
+
"@canonical/react-components": "^4.5.0",
|
|
97
97
|
"@tanstack/react-table": "^8.15.3",
|
|
98
98
|
"@types/react": "^19.1.2",
|
|
99
99
|
"@types/react-dom": "^19.1.3",
|
|
@@ -101,6 +101,7 @@
|
|
|
101
101
|
"react": "19.1.0",
|
|
102
102
|
"react-dom": "19.1.0",
|
|
103
103
|
"react-dropzone": "14.3.8",
|
|
104
|
+
"react-router": "^6.0.0",
|
|
104
105
|
"react-router-dom": "^6.0.0",
|
|
105
106
|
"vanilla-framework": "^4.10.0"
|
|
106
107
|
}
|