@equinor/fusion-react-layout 0.0.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/CHANGELOG.md +1 -0
- package/README.md +172 -0
- package/dist/components/layout/index.d.ts +14 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/layout/index.js +31 -0
- package/dist/components/page/index.d.ts +15 -0
- package/dist/components/page/index.d.ts.map +1 -0
- package/dist/components/page/index.js +31 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/package.json +70 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @equinor/fusion-react-layout
|
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# @equinor/fusion-react-layout [](https://www.npmjs.com/package/@equinor/fusion-react-layout)
|
|
2
|
+
|
|
3
|
+
Component for handling layout in your application.
|
|
4
|
+
|
|
5
|
+
Use this package to compose app-level layouts with an optional sidebar and page sections for header, main content, and footer.
|
|
6
|
+
|
|
7
|
+
## [Storybook](https://equinor.github.io/fusion-react-components/?path=/docs/ui-layout)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @equinor/fusion-react-layout
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or using pnpm:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
pnpm install @equinor/fusion-react-layout
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Components
|
|
22
|
+
|
|
23
|
+
### `Layout`
|
|
24
|
+
|
|
25
|
+
`Layout` is the top-level container. It renders the application shell and accepts two child components:
|
|
26
|
+
|
|
27
|
+
- `Layout.Sidebar` for sidebar content
|
|
28
|
+
- `Layout.Content` for the main content area
|
|
29
|
+
|
|
30
|
+
If `Layout.Sidebar` is omitted, the layout automatically renders without a sidebar.
|
|
31
|
+
|
|
32
|
+
### `Layout.Sidebar`
|
|
33
|
+
|
|
34
|
+
`Layout.Sidebar` places its children in the layout sidebar slot. Use it for navigation, filters, secondary actions, or supporting information.
|
|
35
|
+
|
|
36
|
+
### `Layout.Content`
|
|
37
|
+
|
|
38
|
+
`Layout.Content` places its children in the main content slot. This is typically where you render pages, dashboards, or other primary content.
|
|
39
|
+
|
|
40
|
+
### `Page`
|
|
41
|
+
|
|
42
|
+
`Page` is a page-level wrapper that can be rendered inside `Layout.Content`. It provides structured slots for common page sections:
|
|
43
|
+
|
|
44
|
+
- `Page.Header`
|
|
45
|
+
- `Page.Main`
|
|
46
|
+
- `Page.Footer`
|
|
47
|
+
|
|
48
|
+
### `Page.Header`
|
|
49
|
+
|
|
50
|
+
Use `Page.Header` for page titles, summaries, breadcrumbs, and top-level actions.
|
|
51
|
+
|
|
52
|
+
### `Page.Main`
|
|
53
|
+
|
|
54
|
+
Use `Page.Main` for the primary page content.
|
|
55
|
+
|
|
56
|
+
### `Page.Footer`
|
|
57
|
+
|
|
58
|
+
Use `Page.Footer` for secondary actions, metadata, or status information shown at the bottom of the page.
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
### Import from the main entry point
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { Layout, Page } from '@equinor/fusion-react-layout';
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Basic layout
|
|
69
|
+
|
|
70
|
+
Use `Layout` with `Layout.Content` when your view does not need a sidebar.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Layout } from '@equinor/fusion-react-layout';
|
|
74
|
+
|
|
75
|
+
export function Example() {
|
|
76
|
+
return (
|
|
77
|
+
<Layout>
|
|
78
|
+
<Layout.Content>
|
|
79
|
+
<h1>Main content</h1>
|
|
80
|
+
<p>This area is used for the primary content of the application.</p>
|
|
81
|
+
</Layout.Content>
|
|
82
|
+
</Layout>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Layout with sidebar
|
|
88
|
+
|
|
89
|
+
Add `Layout.Sidebar` when the page needs navigation or supporting content.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { Layout } from '@equinor/fusion-react-layout';
|
|
93
|
+
|
|
94
|
+
export function Example() {
|
|
95
|
+
return (
|
|
96
|
+
<Layout>
|
|
97
|
+
<Layout.Sidebar>
|
|
98
|
+
<h2>Navigation</h2>
|
|
99
|
+
<p>Sidebar content goes here.</p>
|
|
100
|
+
</Layout.Sidebar>
|
|
101
|
+
<Layout.Content>
|
|
102
|
+
<h1>Main content</h1>
|
|
103
|
+
<p>This is the primary application area.</p>
|
|
104
|
+
</Layout.Content>
|
|
105
|
+
</Layout>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Page structure inside layout content
|
|
111
|
+
|
|
112
|
+
Render `Page` inside `Layout.Content` when you want to split a page into header, main, and footer sections.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { Layout, Page } from '@equinor/fusion-react-layout';
|
|
116
|
+
|
|
117
|
+
export function Example() {
|
|
118
|
+
return (
|
|
119
|
+
<Layout>
|
|
120
|
+
<Layout.Content>
|
|
121
|
+
<Page>
|
|
122
|
+
<Page.Header>
|
|
123
|
+
<h1>Page title</h1>
|
|
124
|
+
<p>Short description of the current page.</p>
|
|
125
|
+
</Page.Header>
|
|
126
|
+
<Page.Main>
|
|
127
|
+
<p>This is the main page content.</p>
|
|
128
|
+
</Page.Main>
|
|
129
|
+
<Page.Footer>
|
|
130
|
+
<p>Last updated just now.</p>
|
|
131
|
+
</Page.Footer>
|
|
132
|
+
</Page>
|
|
133
|
+
</Layout.Content>
|
|
134
|
+
</Layout>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Full example with sidebar and page sections
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { Layout, Page } from '@equinor/fusion-react-layout';
|
|
143
|
+
|
|
144
|
+
export function Example() {
|
|
145
|
+
return (
|
|
146
|
+
<Layout>
|
|
147
|
+
<Layout.Sidebar>
|
|
148
|
+
<h2>Filters</h2>
|
|
149
|
+
<p>Use the sidebar for contextual tools and navigation.</p>
|
|
150
|
+
</Layout.Sidebar>
|
|
151
|
+
<Layout.Content>
|
|
152
|
+
<Page>
|
|
153
|
+
<Page.Header>
|
|
154
|
+
<h1>Projects</h1>
|
|
155
|
+
</Page.Header>
|
|
156
|
+
<Page.Main>
|
|
157
|
+
<p>Project overview content.</p>
|
|
158
|
+
</Page.Main>
|
|
159
|
+
<Page.Footer>
|
|
160
|
+
<p>Showing 24 results.</p>
|
|
161
|
+
</Page.Footer>
|
|
162
|
+
</Page>
|
|
163
|
+
</Layout.Content>
|
|
164
|
+
</Layout>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Notes
|
|
170
|
+
|
|
171
|
+
- `Layout` detects whether `Layout.Sidebar` is present and enables the sidebar slot automatically.
|
|
172
|
+
- `Page` is optional. You can render any content directly inside `Layout.Content`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PropsWithChildren, type ReactNode } from 'react';
|
|
2
|
+
import '@equinor/fusion-wc-layout';
|
|
3
|
+
type LayoutComponent = ((props: PropsWithChildren) => ReactNode) & {
|
|
4
|
+
Sidebar: (props: PropsWithChildren) => ReactNode;
|
|
5
|
+
Content: (props: PropsWithChildren) => ReactNode;
|
|
6
|
+
displayName?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Wraps the Fusion layout web component and exposes compound components for
|
|
10
|
+
* assigning children to the layout content and sidebar slots.
|
|
11
|
+
*/
|
|
12
|
+
export declare const Layout: LayoutComponent;
|
|
13
|
+
export default Layout;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/layout/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAEf,OAAO,2BAA2B,CAAC;AAEnC,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC,GAAG;IACjE,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,eAgBpB,CAAC;AAeF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Children, isValidElement, useEffect, useState, } from 'react';
|
|
3
|
+
import '@equinor/fusion-wc-layout';
|
|
4
|
+
/**
|
|
5
|
+
* Wraps the Fusion layout web component and exposes compound components for
|
|
6
|
+
* assigning children to the layout content and sidebar slots.
|
|
7
|
+
*/
|
|
8
|
+
export const Layout = ({ children }) => {
|
|
9
|
+
const childArray = Children.toArray(children);
|
|
10
|
+
// Keep the web component sidebar state aligned with the compound component tree.
|
|
11
|
+
const hasSidebarChild = childArray.some((child) => {
|
|
12
|
+
return isValidElement(child) && child.type === Layout.Sidebar;
|
|
13
|
+
});
|
|
14
|
+
const [hasSidebar, setHasSidebar] = useState(hasSidebarChild);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
setHasSidebar(hasSidebarChild);
|
|
17
|
+
}, [hasSidebarChild]);
|
|
18
|
+
/* @ts-expect-error fwc-layout is a web component */
|
|
19
|
+
return _jsx("fwc-layout", { sidebar: hasSidebar || undefined, children: children });
|
|
20
|
+
};
|
|
21
|
+
Layout.displayName = 'Layout';
|
|
22
|
+
// Compound components mirror the slots supported by the underlying web component.
|
|
23
|
+
Layout.Sidebar = ({ children }) => {
|
|
24
|
+
// The underlying web component projects this content into its sidebar slot.
|
|
25
|
+
return _jsx("div", { slot: "sidebar", children: children });
|
|
26
|
+
};
|
|
27
|
+
Layout.Content = ({ children }) => {
|
|
28
|
+
// The underlying web component projects this content into its main content slot.
|
|
29
|
+
return _jsx("div", { slot: "content", children: children });
|
|
30
|
+
};
|
|
31
|
+
export default Layout;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PropsWithChildren, ReactNode } from 'react';
|
|
2
|
+
import '@equinor/fusion-wc-page';
|
|
3
|
+
type PageComponent = ((props: PropsWithChildren) => ReactNode) & {
|
|
4
|
+
Header: (props: PropsWithChildren) => ReactNode;
|
|
5
|
+
Main: (props: PropsWithChildren) => ReactNode;
|
|
6
|
+
Footer: (props: PropsWithChildren) => ReactNode;
|
|
7
|
+
displayName?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Wraps the Fusion page web component and exposes compound components for
|
|
11
|
+
* assigning children to the page header, main, and footer slots.
|
|
12
|
+
*/
|
|
13
|
+
export declare const Page: PageComponent;
|
|
14
|
+
export default Page;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/page/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,yBAAyB,CAAC;AAEjC,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC,GAAG;IAC/D,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IAChD,IAAI,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IAC9C,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,aAGlB,CAAC;AA0BF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@equinor/fusion-wc-page';
|
|
3
|
+
/**
|
|
4
|
+
* Wraps the Fusion page web component and exposes compound components for
|
|
5
|
+
* assigning children to the page header, main, and footer slots.
|
|
6
|
+
*/
|
|
7
|
+
export const Page = ({ children }) => {
|
|
8
|
+
/* @ts-expect-error fwc-page is a web component */
|
|
9
|
+
return _jsx("fwc-page", { children: children });
|
|
10
|
+
};
|
|
11
|
+
Page.displayName = 'Page';
|
|
12
|
+
const Header = ({ children }) => {
|
|
13
|
+
// The underlying web component projects this content into its header slot.
|
|
14
|
+
return _jsx("div", { slot: "header", children: children });
|
|
15
|
+
};
|
|
16
|
+
Header.displayName = 'Page.Header';
|
|
17
|
+
const Main = ({ children }) => {
|
|
18
|
+
// The underlying web component projects this content into its main slot.
|
|
19
|
+
return _jsx("div", { slot: "main", children: children });
|
|
20
|
+
};
|
|
21
|
+
Main.displayName = 'Page.Main';
|
|
22
|
+
const Footer = ({ children }) => {
|
|
23
|
+
// The underlying web component projects this content into its footer slot.
|
|
24
|
+
return _jsx("div", { slot: "footer", children: children });
|
|
25
|
+
};
|
|
26
|
+
Footer.displayName = 'Page.Footer';
|
|
27
|
+
// Compound components mirror the slots supported by the underlying web component.
|
|
28
|
+
Page.Header = Header;
|
|
29
|
+
Page.Main = Main;
|
|
30
|
+
Page.Footer = Footer;
|
|
31
|
+
export default Page;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@equinor/fusion-react-layout",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Fusion React Layout Component.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"components",
|
|
8
|
+
"fusion",
|
|
9
|
+
"equinor",
|
|
10
|
+
"layout"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./layout": {
|
|
18
|
+
"import": "./dist/components/layout/index.js",
|
|
19
|
+
"types": "./dist/components/layout/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./page": {
|
|
22
|
+
"import": "./dist/components/page/index.js",
|
|
23
|
+
"types": "./dist/components/page/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./package.json": "./package.json",
|
|
26
|
+
"./README.md": "./README.md",
|
|
27
|
+
"./CHANGELOG.md": "./CHANGELOG.md"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/equinor/fusion-react-components/blob/main/packages/layout#readme",
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"main": "dist/index.js",
|
|
32
|
+
"module": "dist/index.js",
|
|
33
|
+
"types": "dist/index.d.ts",
|
|
34
|
+
"directories": {
|
|
35
|
+
"dist": "dist"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"CHANGELOG.md"
|
|
41
|
+
],
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/equinor/fusion-react-components.git",
|
|
48
|
+
"directory": "packages/layout"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc -b",
|
|
52
|
+
"lint": "biome lint",
|
|
53
|
+
"format": "biome format",
|
|
54
|
+
"prepack": "npm run build"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/equinor/fusion-react-components/issues"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@equinor/fusion-wc-layout": "^0.0.0",
|
|
61
|
+
"@equinor/fusion-wc-page": "^0.0.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@types/react": "^19.2.14",
|
|
65
|
+
"react": "^19.2.5"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"react": "^18 || ^19"
|
|
69
|
+
}
|
|
70
|
+
}
|