@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 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** -- Full application shell with icon rail, top bar, side pane, sub-navigation, command menu, and confirm dialogs.
7
+ **RootLayout / AppShell** Full application shell: TopBar, navigation
8
+ (icon-rail or sidebar), SidePane, content area, overlays, command menu.
8
9
 
9
- **Imperative API** -- Shell capabilities exposed as simple function calls: `notification.success()`, `panel.open()`, `navigation.go()`, `dialog.confirm()`, `fullscreen.enter()`.
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
- **Module registry** -- Register application modules with navigation, routes, and search providers. The shell renders the navigation and routes automatically.
14
+ **Navigation primitives** Compose custom layouts from `IconRail`, `RailIcon`,
15
+ `RailSeparator`, `Sidebar`, `SidebarGroup`, `SidebarItem`, `SubNavPanel`.
12
16
 
13
- **Auth components** (subpath: `@petrarca/sonnet-shell/auth`) -- Login, ProtectedRoute, and TenantSelection components with prop-driven auth configuration. No auth logic baked in -- the host app provides the auth state.
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
- Apache 2.0
260
+ See [LICENSE.md](../../LICENSE.md).