@canonical/maas-react-components 2.3.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.
@@ -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,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 {};
@@ -0,0 +1,2 @@
1
+ export { SidePanel } from './SidePanel';
2
+ export { SidePanelContextProvider, useSidePanel } from './SidePanelContextProvider/SidePanelContextProvider';
@@ -1,5 +1,6 @@
1
- export * from './Navigation';
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 './ContentSection';
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.3.0",
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": "^2.2.0",
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
  }