@petrarca/sonnet-shell 0.2.0 → 0.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/README.md +241 -6
- package/dist/index.d.ts +277 -32
- package/dist/index.js +797 -287
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,13 +4,28 @@ Application shell, layout, and navigation for the Petrarca Sonnet component libr
|
|
|
4
4
|
|
|
5
5
|
## What's included
|
|
6
6
|
|
|
7
|
-
**AppShell**
|
|
7
|
+
**RootLayout / AppShell** — Full application shell: TopBar, navigation
|
|
8
|
+
(icon-rail or sidebar), SidePane, content area, overlays, command menu.
|
|
8
9
|
|
|
9
|
-
**
|
|
10
|
+
**Navigation layouts** — Two built-in layouts driven by the same module metadata:
|
|
11
|
+
- `ShellRail` — narrow icon strip + contextual sub-nav panel (default)
|
|
12
|
+
- `ShellSidebar` — single-column sidebar with icons, labels, and collapsible sections
|
|
10
13
|
|
|
11
|
-
**
|
|
14
|
+
**Navigation primitives** — Compose custom layouts from `IconRail`, `RailIcon`,
|
|
15
|
+
`RailSeparator`, `Sidebar`, `SidebarGroup`, `SidebarItem`, `SubNavPanel`.
|
|
12
16
|
|
|
13
|
-
**
|
|
17
|
+
**Shell chrome** — `TopBar`, `ShellFooter`, `ShellVersion` for header/footer slots.
|
|
18
|
+
|
|
19
|
+
**Imperative API** — Shell capabilities as simple function calls from any module:
|
|
20
|
+
`notification`, `dialog`, `navigation`, `panel`, `sidePane`, `fullscreen`, `events`.
|
|
21
|
+
|
|
22
|
+
**Module system** — Register app modules (`ShellModule`) with routes, navigation,
|
|
23
|
+
Cmd+K commands, and side pane config. `createModuleRegistry()` aggregates them.
|
|
24
|
+
|
|
25
|
+
**Auth components** (`@petrarca/sonnet-shell/auth`) — `Login`, `ProtectedRoute`,
|
|
26
|
+
`TenantSelection`. Prop-driven — no auth logic baked in.
|
|
27
|
+
|
|
28
|
+
---
|
|
14
29
|
|
|
15
30
|
## Install
|
|
16
31
|
|
|
@@ -18,8 +33,228 @@ Application shell, layout, and navigation for the Petrarca Sonnet component libr
|
|
|
18
33
|
pnpm add @petrarca/sonnet-shell @petrarca/sonnet-ui @petrarca/sonnet-core
|
|
19
34
|
```
|
|
20
35
|
|
|
21
|
-
Peer dependencies: `react`, `react-dom`, `react-router-dom`, `tailwindcss`.
|
|
36
|
+
Peer dependencies: `react >=19`, `react-dom >=19`, `react-router-dom`, `tailwindcss`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Setup
|
|
41
|
+
|
|
42
|
+
### 1. Define modules
|
|
43
|
+
|
|
44
|
+
Each feature area is a `ShellModule`:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// src/modules/home/index.ts
|
|
48
|
+
import { Home } from "lucide-react";
|
|
49
|
+
import type { ShellModule } from "@petrarca/sonnet-shell";
|
|
50
|
+
import { routes } from "./routes";
|
|
51
|
+
|
|
52
|
+
const homeModule: ShellModule = {
|
|
53
|
+
id: "home",
|
|
54
|
+
label: "Home",
|
|
55
|
+
icon: Home,
|
|
56
|
+
basePath: "/home",
|
|
57
|
+
navigation: [
|
|
58
|
+
{
|
|
59
|
+
id: "main",
|
|
60
|
+
links: [
|
|
61
|
+
{ id: "home.overview", label: "Overview", path: "/home" },
|
|
62
|
+
{ id: "home.settings", label: "Settings", path: "/home/settings" },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
// Optional: fixed top-zone links in sidebar mode (no heading, separator below)
|
|
67
|
+
topNav: [
|
|
68
|
+
{ id: "home.overview", label: "Overview", path: "/home" },
|
|
69
|
+
],
|
|
70
|
+
routes,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default homeModule;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. Create the registry
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// src/modules/registry.ts
|
|
80
|
+
import { createModuleRegistry } from "@petrarca/sonnet-shell";
|
|
81
|
+
import home from "./home";
|
|
82
|
+
import settings from "./settings";
|
|
83
|
+
|
|
84
|
+
const registry = createModuleRegistry([home, settings]);
|
|
85
|
+
|
|
86
|
+
export const { allRoutes } = registry;
|
|
87
|
+
export default registry;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Wire the shell
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// src/routes/AppRouter.tsx
|
|
94
|
+
import { createBrowserRouter, RouterProvider, Navigate } from "react-router-dom";
|
|
95
|
+
import {
|
|
96
|
+
RootLayout,
|
|
97
|
+
SearchTrigger,
|
|
98
|
+
UserMenu,
|
|
99
|
+
ShellVersion,
|
|
100
|
+
type ShellConfig,
|
|
101
|
+
} from "@petrarca/sonnet-shell";
|
|
102
|
+
import pkg from "../../package.json";
|
|
103
|
+
import registry from "@/modules/registry";
|
|
104
|
+
|
|
105
|
+
function TopBarContent() {
|
|
106
|
+
return (
|
|
107
|
+
<>
|
|
108
|
+
<div className="flex items-center gap-3">
|
|
109
|
+
<span className="text-sm font-semibold">MY APP</span>
|
|
110
|
+
</div>
|
|
111
|
+
<div className="flex items-center gap-2">
|
|
112
|
+
<SearchTrigger />
|
|
113
|
+
<UserMenu user={...} onSignOut={...} />
|
|
114
|
+
</div>
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const shellConfig: ShellConfig = {
|
|
120
|
+
topBar: <TopBarContent />,
|
|
121
|
+
footer: <ShellVersion name="My App" version={pkg.version} />,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const router = createBrowserRouter([
|
|
125
|
+
{
|
|
126
|
+
element: <RootLayout config={shellConfig} registry={registry} />,
|
|
127
|
+
children: [
|
|
128
|
+
{ index: true, element: <Navigate to="/home" replace /> },
|
|
129
|
+
...registry.allRoutes,
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
export function AppRouter() {
|
|
135
|
+
return <RouterProvider router={router} />;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 4. CSS and Tailwind
|
|
140
|
+
|
|
141
|
+
```css
|
|
142
|
+
/* index.css */
|
|
143
|
+
@import "@petrarca/sonnet-ui/styles.css";
|
|
144
|
+
|
|
145
|
+
/* Shell layout — app-level, not provided by the library */
|
|
146
|
+
html, body, #root { height: 100%; }
|
|
147
|
+
#root { display: flex; flex-direction: column; overflow: hidden; }
|
|
148
|
+
body { min-height: 100vh; overflow: hidden; }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
// tailwind.config.js
|
|
153
|
+
module.exports = {
|
|
154
|
+
presets: [require("@petrarca/sonnet-ui/tailwind-preset")],
|
|
155
|
+
content: [
|
|
156
|
+
"./src/**/*.{ts,tsx}",
|
|
157
|
+
"./node_modules/@petrarca/sonnet-*/dist/**/*.js",
|
|
158
|
+
],
|
|
159
|
+
plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
|
|
160
|
+
};
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Sidebar layout
|
|
166
|
+
|
|
167
|
+
Pass a `sidebar` prop to `RootLayout` to replace the default icon-rail with a
|
|
168
|
+
single-column sidebar:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { ShellSidebar } from "@petrarca/sonnet-shell";
|
|
172
|
+
|
|
173
|
+
// Auto-wired from registry metadata:
|
|
174
|
+
<RootLayout config={shellConfig} registry={registry} sidebar={<ShellSidebar />} />
|
|
175
|
+
|
|
176
|
+
// Or fully custom:
|
|
177
|
+
import { Sidebar, SidebarGroup, SidebarItem } from "@petrarca/sonnet-shell";
|
|
178
|
+
|
|
179
|
+
<RootLayout
|
|
180
|
+
config={shellConfig}
|
|
181
|
+
registry={registry}
|
|
182
|
+
sidebar={
|
|
183
|
+
<Sidebar>
|
|
184
|
+
<SidebarGroup separator>
|
|
185
|
+
<SidebarItem icon={Home} label="Overview" path="/home" />
|
|
186
|
+
</SidebarGroup>
|
|
187
|
+
<SidebarGroup heading="PROJECTS" collapsible>
|
|
188
|
+
<SidebarItem icon={Folder} label="Alpha" path="/projects/alpha" />
|
|
189
|
+
</SidebarGroup>
|
|
190
|
+
</Sidebar>
|
|
191
|
+
}
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`topNav` on a `ShellModule` populates the top separator zone automatically
|
|
196
|
+
when using `ShellSidebar`.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Imperative API
|
|
201
|
+
|
|
202
|
+
Any module can call the shell API without prop drilling:
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
import { notification, dialog, navigation, panel, sidePane } from "@petrarca/sonnet-shell";
|
|
206
|
+
|
|
207
|
+
notification.success("Saved.");
|
|
208
|
+
notification.error("Failed to save.");
|
|
209
|
+
|
|
210
|
+
const confirmed = await dialog.confirm({
|
|
211
|
+
title: "Delete item?",
|
|
212
|
+
confirmLabel: "Delete",
|
|
213
|
+
variant: "destructive",
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
navigation.goTo("/home");
|
|
217
|
+
navigation.goToFeature("home.settings"); // stable id, path-independent
|
|
218
|
+
|
|
219
|
+
panel.open({
|
|
220
|
+
title: "Details",
|
|
221
|
+
content: <MyPanel />,
|
|
222
|
+
width: "default",
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
sidePane.toggle({ moduleId: "my-module", content: <MySidePane /> });
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## ShellModule reference
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
interface ShellModule {
|
|
234
|
+
id: string; // unique, e.g. "terminology"
|
|
235
|
+
label: string; // shown in rail tooltip, sub-nav header
|
|
236
|
+
description?: string; // shown in Cmd+K
|
|
237
|
+
icon: LucideIcon;
|
|
238
|
+
|
|
239
|
+
basePath: string; // URL prefix, e.g. "/terminology"
|
|
240
|
+
routes: RouteObject[]; // React Router routes
|
|
241
|
+
|
|
242
|
+
topNav?: NavLink[]; // fixed top-zone links (sidebar only)
|
|
243
|
+
navigation: NavGroup[]; // grouped nav links (rail + sidebar)
|
|
244
|
+
|
|
245
|
+
pinBottom?: boolean; // pin to bottom of rail / sidebar tools group
|
|
246
|
+
hidden?: boolean; // hide from navigation entirely
|
|
247
|
+
|
|
248
|
+
contributions?: Contribution[]; // inject links into other modules' nav
|
|
249
|
+
commands?: ModuleCommand[]; // Cmd+K actions
|
|
250
|
+
|
|
251
|
+
sidePane?: { ... }; // inline resizable panel config
|
|
252
|
+
layout?: "default" | "full"; // "full" removes scroll wrapper and padding
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
22
257
|
|
|
23
258
|
## License
|
|
24
259
|
|
|
25
|
-
|
|
260
|
+
See [LICENSE.md](../../LICENSE.md).
|