nexus-shell 0.1.23 → 0.2.1

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.
Files changed (109) hide show
  1. package/README.md +191 -106
  2. package/dist/components/layout/ShellLayout.d.ts +90 -12
  3. package/dist/components/widgets/ActivityBar.d.ts +48 -1
  4. package/dist/components/widgets/AppTitle.d.ts +30 -0
  5. package/dist/components/widgets/ChatPane.d.ts +63 -1
  6. package/dist/components/widgets/CommandPalette.d.ts +55 -7
  7. package/dist/components/widgets/ContextMenu.d.ts +34 -3
  8. package/dist/components/widgets/DataGrid.d.ts +44 -0
  9. package/dist/components/widgets/MenuBar.d.ts +55 -5
  10. package/dist/components/widgets/Modal.d.ts +58 -0
  11. package/dist/components/widgets/QuickSearch.d.ts +66 -0
  12. package/dist/components/widgets/SearchWidget.d.ts +36 -0
  13. package/dist/components/widgets/SettingsPanel.d.ts +33 -0
  14. package/dist/components/widgets/SidebarPane.d.ts +37 -1
  15. package/dist/components/widgets/StatusBar.d.ts +51 -1
  16. package/dist/components/widgets/TerminalPane.d.ts +43 -1
  17. package/dist/components/widgets/ThemeSwitcher.d.ts +35 -5
  18. package/dist/components/widgets/TreeWidget.d.ts +94 -5
  19. package/dist/components/widgets/UserProfile.d.ts +75 -6
  20. package/dist/connected/ConnectedActivityBar.d.ts +10 -0
  21. package/dist/connected/ConnectedChatPane.d.ts +18 -0
  22. package/dist/connected/ConnectedCommandPalette.d.ts +18 -0
  23. package/dist/connected/ConnectedMenuBar.d.ts +12 -0
  24. package/dist/connected/ConnectedModal.d.ts +15 -0
  25. package/dist/connected/ConnectedSidebarPane.d.ts +12 -0
  26. package/dist/connected/ConnectedStatusBar.d.ts +15 -0
  27. package/dist/connected/ConnectedTerminalPane.d.ts +18 -0
  28. package/dist/connected/ConnectedThemeSwitcher.d.ts +11 -0
  29. package/dist/connected/ConnectedUserProfile.d.ts +14 -0
  30. package/dist/connected/index.d.ts +21 -0
  31. package/dist/core/Boot.d.ts +64 -2
  32. package/dist/core/registry/MenuRegistry.d.ts +22 -9
  33. package/dist/core/services/ChatService.d.ts +23 -7
  34. package/dist/core/services/StatusBarService.d.ts +17 -14
  35. package/dist/index.d.ts +53 -33
  36. package/dist/lib/cn.d.ts +12 -0
  37. package/dist/nexus-shell.es.js +2427 -40
  38. package/dist/nexus-shell.umd.js +1 -3707
  39. package/dist/style.css +1 -1
  40. package/package.json +43 -15
  41. package/dist/App.d.ts +0 -2
  42. package/dist/components/layout/NexusWorkspaceShell.d.ts +0 -9
  43. package/dist/components/widgets/AgentManager.d.ts +0 -18
  44. package/dist/components/widgets/ArgumentInspectorWidget.d.ts +0 -5
  45. package/dist/components/widgets/DialogueMapperInspector.d.ts +0 -5
  46. package/dist/components/widgets/DialogueMapperLibrary.d.ts +0 -11
  47. package/dist/components/widgets/DialogueMapperLibraryWidget.d.ts +0 -3
  48. package/dist/components/widgets/DialogueMappingWidget.d.ts +0 -10
  49. package/dist/components/widgets/FilesSidebar.d.ts +0 -1
  50. package/dist/components/widgets/FlowControlToolbar.d.ts +0 -18
  51. package/dist/components/widgets/GlobalModal.d.ts +0 -3
  52. package/dist/components/widgets/MenuBarSearch.d.ts +0 -11
  53. package/dist/components/widgets/MockupReviewWidget.d.ts +0 -3
  54. package/dist/components/widgets/NexusWorkspaceTitle.d.ts +0 -10
  55. package/dist/components/widgets/ProjectPropertiesWidget.d.ts +0 -8
  56. package/dist/components/widgets/WargameMap.d.ts +0 -31
  57. package/dist/components/widgets/WelcomeTab.d.ts +0 -8
  58. package/dist/components/widgets/dialogue-mapper/IbisNode.d.ts +0 -5
  59. package/dist/components/widgets/mockup-reviewer/ExecutionOverlay.d.ts +0 -10
  60. package/dist/components/widgets/mockup-reviewer/HtmlShadowRenderer.d.ts +0 -9
  61. package/dist/components/widgets/mockup-reviewer/ImplementationPlanWorkspace.d.ts +0 -8
  62. package/dist/components/widgets/mockup-reviewer/MockupReviewWorkspace.d.ts +0 -10
  63. package/dist/components/widgets/mockup-reviewer/ReviewSidebar.d.ts +0 -3
  64. package/dist/components/widgets/mockup-reviewer/ReviewToolbar.d.ts +0 -12
  65. package/dist/components/widgets/mockup-reviewer/WorkflowMapper.d.ts +0 -7
  66. package/dist/components/widgets/wiki/AiCoWriterWorkspace.d.ts +0 -3
  67. package/dist/components/widgets/wiki/SemanticLinkMapper.d.ts +0 -3
  68. package/dist/components/widgets/wiki/WikiChatWidget.d.ts +0 -3
  69. package/dist/components/widgets/wiki/WikiEditor.d.ts +0 -3
  70. package/dist/components/widgets/wiki/WikiHistorySidebar.d.ts +0 -3
  71. package/dist/components/widgets/wiki/WikiNavigator.d.ts +0 -3
  72. package/dist/core/services/DialogueMappingService.d.ts +0 -59
  73. package/dist/core/services/FileStoreService.d.ts +0 -11
  74. package/dist/core/services/MockupReviewService.d.ts +0 -58
  75. package/dist/core/services/dialogue-mapper/DialogueLayoutEngine.d.ts +0 -9
  76. package/dist/core/services/dialogue-mapper/DialogueMapRepository.d.ts +0 -15
  77. package/dist/core/services/mockup-reviewer/MockupFixtures.d.ts +0 -11
  78. package/dist/core/services/useWikiStore.d.ts +0 -33
  79. package/dist/index-4EyxMz0x.js +0 -78516
  80. package/dist/main.d.ts +0 -1
  81. package/dist/maplibre-gl-DJOCpYhv.js +0 -24588
  82. package/dist/plugins/WikiPlugin.d.ts +0 -3
  83. package/dist/stories/ActivityBar.stories.d.ts +0 -9
  84. package/dist/stories/AgentManager.stories.d.ts +0 -25
  85. package/dist/stories/ChatPane.stories.d.ts +0 -10
  86. package/dist/stories/CommandPalette.stories.d.ts +0 -9
  87. package/dist/stories/DataGrid.stories.d.ts +0 -12
  88. package/dist/stories/DialogueMapperLibrary.stories.d.ts +0 -10
  89. package/dist/stories/DialogueMappingWidget.stories.d.ts +0 -9
  90. package/dist/stories/FlowControlToolbar.stories.d.ts +0 -14
  91. package/dist/stories/GlobalModal.stories.d.ts +0 -7
  92. package/dist/stories/IbisNode.stories.d.ts +0 -10
  93. package/dist/stories/MenuBar.stories.d.ts +0 -10
  94. package/dist/stories/MenuBarSearch.stories.d.ts +0 -7
  95. package/dist/stories/MockupReviewWidget.stories.d.ts +0 -9
  96. package/dist/stories/MockupReviewerLayout.stories.d.ts +0 -8
  97. package/dist/stories/NexusWorkspaceShell.stories.d.ts +0 -9
  98. package/dist/stories/NexusWorkspaceTitle.stories.d.ts +0 -11
  99. package/dist/stories/SearchWidget.stories.d.ts +0 -9
  100. package/dist/stories/ShellLayout.stories.d.ts +0 -13
  101. package/dist/stories/SidebarPane.stories.d.ts +0 -8
  102. package/dist/stories/StatusBar.stories.d.ts +0 -10
  103. package/dist/stories/TerminalPane.stories.d.ts +0 -9
  104. package/dist/stories/ThemeSwitcher.stories.d.ts +0 -10
  105. package/dist/stories/TreeWidget.stories.d.ts +0 -8
  106. package/dist/stories/UserProfile.stories.d.ts +0 -11
  107. package/dist/stories/WargameMap.stories.d.ts +0 -14
  108. package/dist/stories/wiki/WikiComposition.stories.d.ts +0 -6
  109. package/dist/stories/wiki/WikiWidgets.stories.d.ts +0 -11
package/README.md CHANGED
@@ -1,147 +1,232 @@
1
- # 🚀 Nexus Shell Framework
1
+ # Nexus Shell
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/nexus-shell.svg)](https://www.npmjs.com/package/nexus-shell)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Build & Deploy Storybook](https://github.com/techmuch/nexus-shell/actions/workflows/deploy-storybook.yml/badge.svg)](https://github.com/techmuch/nexus-shell/actions/workflows/deploy-storybook.yml)
6
- [![Live Documentation](https://img.shields.io/badge/docs-live--pages-blueviolet)](https://techmuch.github.io/nexus-shell/?path=/docs/introduction--docs)
3
+ React components for building IDE-style application shells — menu bar, activity
4
+ bar, sidebar, docking layout, terminal, chat pane and status bar.
7
5
 
8
- Nexus Shell is a professional-grade, library-first React 19 / TypeScript frontend framework for building multi-panel **"Workbench"** style applications (resembling VS Code, JupyterLab, or specialized dashboard workstations).
6
+ **[Documentation and live examples →](https://techmuch.github.io/nexus-shell/)** ·
7
+ [Storybook](https://techmuch.github.io/nexus-shell/storybook/)
9
8
 
10
- Instead of building a rigid layout from scratch, Nexus Shell provides a **fully decoupled, registry-driven workspace engine** powered by `flexlayout-react`, allowing tabs, menus, hotkeys, status bars, and custom sidebars to be dynamically declared and contextually composed.
9
+ ```bash
10
+ npm install nexus-shell
11
+ ```
11
12
 
12
- ---
13
+ ```ts
14
+ import 'nexus-shell/style.css';
15
+ ```
13
16
 
14
- ## 📖 Live Interactive Documentation
15
- Explore the live documentation, interactive component playground, prop definitions, and layout compositions at:
16
- 👉 **[Live Storybook Documentation Site](https://techmuch.github.io/nexus-shell/?path=/docs/introduction--docs)**
17
+ React 19 is a peer dependency.
17
18
 
18
- ---
19
+ ## Start with the shell
19
20
 
20
- ## 🎨 Visual Showcase & Capabilities
21
+ An application built on this library starts with `ShellLayout` and grows by
22
+ registering features into it.
21
23
 
22
- ### 1. Tabbed Dialogue Mapping Workbench & Workspace
23
- A flexible workstation that integrates Compendium-style visual argumentation mapping (React Flow canvas) with external node libraries and logic inspectors as drag-and-drop tabs.
24
- ![Dialogue Mapping Workbench (Dark Theme)](docs/images/dialogue-mapper-library-dark.png)
25
- *(Above: Dialogue Mapping workspace in Dark Theme showing interactive nodes, custom icons, and Straight connectors)*
24
+ ```tsx
25
+ // main.tsx — a complete application
26
+ import { createRoot } from 'react-dom/client';
27
+ import { Boxes, Files } from 'lucide-react';
28
+ import {
29
+ AppTitle,
30
+ ShellLayout,
31
+ componentRegistry,
32
+ initializeShell,
33
+ useLayoutStore,
34
+ } from 'nexus-shell';
35
+ import 'nexus-shell/style.css';
36
+
37
+ // Views register by id, so the shell never has to import them.
38
+ componentRegistry.register('editor', Editor);
39
+
40
+ initializeShell({
41
+ panels: [{ id: 'files', label: 'Explorer', icon: Files, component: FileExplorer }],
42
+ commands: [
43
+ { id: 'file.save', label: 'File: Save', keybinding: 'Control+s', execute: save },
44
+ ],
45
+ menus: { File: [{ id: 'save', label: 'Save', commandId: 'file.save' }] },
46
+ statusBar: [{ id: 'branch', label: 'main', alignment: 'left' }],
47
+ });
26
48
 
27
- ### 2. Georgia Tech Theme & Theme-Adaptivity
28
- Fully responsive styling driven by HSL CSS variables, conforming to WCAG contrast standards.
29
- ![Dialogue Mapping Workbench (GT Theme)](docs/images/dialogue-mapper-library-light.png)
30
- *(Above: Light Theme workspace showing responsive menus, active tab headers, and the account widget)*
49
+ useLayoutStore.getState().addTab('editor', 'App.tsx');
31
50
 
32
- ### 3. Workflow Reviews & Mockup Canvas Overlay
33
- Draw overlay annotations directly onto child mockups and generate implementation plans dynamically using AI nodes.
34
- ![Mockup Reviewer Layout](docs/images/mockup-reviewer-layout.png)
35
- *(Above: A complex Mockup Reviewer workstation running canvas drawing tools and terminal consoles side-by-side)*
51
+ createRoot(document.getElementById('root')!).render(
52
+ <ShellLayout title={<AppTitle title="Acme Studio" icon={<Boxes size={16} />} />} />,
53
+ );
54
+ ```
36
55
 
37
- ### 4. Interactive Storybook Workspace
38
- Reorganized story taxonomy allowing you to build, test, and preview widgets in isolation or combined.
39
- ![Storybook Taxonomy](docs/images/media__storybook_layout.png)
56
+ That is a working IDE: dockable tabs, a command palette on `Cmd/Ctrl+Shift+P`, a
57
+ terminal, a chat pane, and a themable frame.
40
58
 
41
- ---
59
+ ## Growing an app
42
60
 
43
- ## 🤔 Why Choose Nexus Shell?
61
+ You add capability by **registering** it. None of this changes the layout, which
62
+ is what lets plugins and distant code contribute to the shell.
44
63
 
45
- | If you are building... | Nexus Shell provides... |
46
- | :--- | :--- |
47
- | **IDE/Workbench Web Apps** | A complete drag-and-drop tab layout engine with splits, resizing, and sidebars (`flexlayout-react` integration). |
48
- | **Modular Dashboard Interfaces** | Inversion of Control registries (`componentRegistry`, `commandRegistry`, `menuRegistry`) so features register themselves dynamically. |
49
- | **Complex Geospatial/Tactical Maps** | High-performance maps (`WargameMap`) combining `react-map-gl`, `deck.gl`, and `h3-js` for hexagonal grid overlays and MIL-STD military icons. |
50
- | **AI Orchestration Workbenches** | State-driven workflow templates, agent nodes, and drawing canvas mockups built with React Flow. |
64
+ | To add | Do this |
65
+ | :-- | :-- |
66
+ | A view or tab | `componentRegistry.register(id, Component)`, then `useLayoutStore().addTab(id, title)` |
67
+ | An action or hotkey | `commandRegistry.registerCommand({ id, label, keybinding, execute })` — appears in the palette automatically |
68
+ | A menu entry | `menuRegistry.registerMenu('File', { id, label, commandId })` |
69
+ | A sidebar panel | Add it to `panels`; it becomes an activity bar icon |
70
+ | A status bar item | `useStatusBarStore.getState().addWidget(...)` |
71
+ | A dialog from anywhere | `await useModalStore.getState().openConfirm('Sure?')` |
72
+ | An unsaved-changes guard | `useLayoutStore.getState().setTabDirty(tabId, true)` |
51
73
 
52
- ---
74
+ ## When you need less than the shell
53
75
 
54
- ## ✨ Key Features
76
+ Every component the shell is assembled from is exported on its own — pure and
77
+ prop-driven, with no global state or registry lookups. This is the escape hatch:
78
+ reach for it when you're embedding one piece into an app you already have, or
79
+ building a frame `ShellLayout` can't express.
55
80
 
56
- - **Advanced Docking Engine**: Full drag-and-drop tab management (dock, split, float, collapse) out-of-the-box.
57
- - **Inversion of Control (IoC) Registries**: Add new menu items, hotkeys, or tab contents programmatically from anywhere in your code without touching the layout container.
58
- - **Zustand State Persistence**: Automatically restores the user's workspace structure, theme preference, and pane configurations across page reloads.
59
- - **Accessibility & Contrast First**: Built to look beautiful and professional under three default themes (`theme-light`, `theme-dark`, and `theme-gt` for Georgia Tech fans) while satisfying AA/AAA color contrast ratios.
60
- - **Pre-Integrated Widgets**: A library of reusable layout widgets including terminal consoles, chat panels, tree file explorers, virtualized grids, and hex maps.
81
+ ```tsx
82
+ import { ActivityBar, SidebarPane, StatusBar, TreeWidget } from 'nexus-shell';
83
+
84
+ const [active, setActive] = useState<string | null>('files');
85
+
86
+ <div className="theme-dark flex h-screen flex-col">
87
+ <div className="flex flex-1">
88
+ <ActivityBar
89
+ items={panels}
90
+ activeId={active}
91
+ onSelect={(id) => setActive(id === active ? null : id)}
92
+ />
93
+ {active && (
94
+ <SidebarPane title="Explorer" onClose={() => setActive(null)}>
95
+ <TreeWidget data={files} onToggle={toggle} onActivate={open} />
96
+ </SidebarPane>
97
+ )}
98
+ <main className="flex-1">{children}</main>
99
+ </div>
100
+ <StatusBar widgets={[{ id: 'branch', label: 'main', alignment: 'left' }]} />
101
+ </div>;
102
+ ```
61
103
 
62
- ---
104
+ These are controlled, so state stays in your app — a real cost the shell was
105
+ absorbing for you.
63
106
 
64
- ## 🚦 Quick Start
107
+ Between the two sit the `Connected*` variants, each binding one component to its
108
+ store. `ShellLayout` is built entirely out of them, so you can rearrange the
109
+ shell's own frame and keep every registration working.
65
110
 
66
- ### 1. Installation
111
+ ## Components
67
112
 
68
- ```bash
69
- npm install nexus-shell
70
- ```
113
+ `ShellLayout` assembles all of these. Each is also exported on its own.
71
114
 
72
- ### 2. Basic Setup
115
+ | Component | What it is |
116
+ | :-- | :-- |
117
+ | `ActivityBar` | Vertical icon rail for switching sidebar panels |
118
+ | `ChatPane` | Docked chat transcript with slash-command autocomplete |
119
+ | `CommandPalette` | Filterable, keyboard-navigable command list |
120
+ | `ContextMenu` | Floating menu positioned at viewport coordinates |
121
+ | `DataGrid` | Sortable, filterable table with optional virtualisation |
122
+ | `MenuBar` | Application menu bar with submenus and content slots |
123
+ | `Modal` | Alert / confirm / prompt dialog |
124
+ | `QuickSearch` | Compact search field with grouped results, for the menu bar |
125
+ | `SearchWidget` | Full-height search panel with autocomplete, for the sidebar |
126
+ | `SettingsPanel` | Theme picker body for the settings sidebar |
127
+ | `SidebarPane` | Titled, closable container for sidebar content |
128
+ | `StatusBar` | Footer with left / center / right item groups |
129
+ | `TerminalPane` | Bottom-docked terminal log and input |
130
+ | `ThemeSwitcher` | Segmented theme control |
131
+ | `TreeWidget` | Virtualised file tree with drag-to-move and a data-driven menu |
132
+ | `UserProfile` | Avatar and identity widget |
73
133
 
74
- In your main entry point (e.g., `main.tsx` or `App.tsx`):
134
+ ## Theming
75
135
 
76
- ```tsx
77
- import React from 'react';
78
- import ReactDOM from 'react-dom/client';
79
- import { ShellLayout, initializeShell } from 'nexus-shell';
80
- import 'nexus-shell/style.css'; // Essential styling properties
81
-
82
- // Initialize core registries and default welcome workspace
83
- initializeShell();
84
-
85
- export default function App() {
86
- return (
87
- <div className="h-screen w-screen bg-background text-foreground">
88
- <ShellLayout
89
- title={<div className="font-bold text-lg">My Custom IDE</div>}
90
- />
91
- </div>
92
- );
93
- }
94
-
95
- ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
96
- ```
136
+ Three themes ship in the stylesheet: `theme-light`, `theme-dark`, `theme-gt`.
137
+ Colors are CSS custom properties scoped to those classes, so switching themes is
138
+ a class on an ancestor — no React context, no provider.
97
139
 
98
- ---
140
+ Add your own by defining a `.theme-yourname` block with the same properties.
99
141
 
100
- ## 🏗 Registry-Driven Customization
142
+ ## Development
101
143
 
102
- Nexus Shell lets you register custom features dynamically:
144
+ ```bash
145
+ npm install
146
+
147
+ npm run site # documentation site at :5173
148
+ npm run storybook # component workbench at :6006
149
+ npm run dev # showcase app at :5173
150
+
151
+ npm run typecheck # library sources
152
+ npm test # vitest — unit and architecture tests
153
+ npm run site:test # renders every site route and demo
154
+ npm run build # library build to dist/
155
+ npm run build-storybook
156
+ npm run site:build # documentation site to website/dist/
157
+ npm run e2e # Playwright against the showcase app
158
+ ```
103
159
 
104
- ### Register a Keyboard Shortcut (Command)
105
- ```typescript
106
- import { commandRegistry } from 'nexus-shell';
160
+ `npm run typecheck` covers `src/` only. To include the examples:
107
161
 
108
- commandRegistry.registerCommand({
109
- id: 'my-app.hello',
110
- label: 'Say Hello',
111
- keybinding: 'Control+L',
112
- execute: () => alert('Hello from Nexus Shell!'),
113
- });
162
+ ```bash
163
+ npx tsc --noEmit -p tsconfig.examples.json
114
164
  ```
115
165
 
116
- ### Register a Tab Component
117
- ```typescript
118
- import { componentRegistry } from 'nexus-shell';
166
+ CI runs all of the above on every push and pull request.
167
+
168
+ ### Layout
119
169
 
120
- componentRegistry.register('my-custom-widget', () => (
121
- <div className="p-4 bg-card text-card-foreground">
122
- <h2>Dynamic Custom Tab</h2>
123
- <p>This tab can be docked anywhere in the workspace!</p>
124
- </div>
125
- ));
170
+ ```
171
+ src/
172
+ components/ Pure, prop-driven components — what the shell is made of
173
+ connected/ Store-bound wrappers used by ShellLayout
174
+ core/ Stores (zustand), registries, and initializeShell
175
+ lib/ Shared utilities
176
+ stories/ MDX documentation pages
177
+ examples/
178
+ showcase/ Demo apps built on the library — not published
179
+ dialogue-mapper/
180
+ mockup-reviewer/
181
+ wiki/
182
+ wargame/
183
+ e2e/ Playwright specs for the showcase app
184
+ basic-app/ Minimal integration example
185
+ website/
186
+ src/demos/ Live examples — the source shown on the site
187
+ src/content/ The component gallery, as data
188
+ scripts/ Generates the props tables from the library's types
126
189
  ```
127
190
 
128
- ---
191
+ ### Documentation site
129
192
 
130
- ## 🧪 Development & Testing
193
+ `website/` is a Vite app that imports the library from `../src`, not from
194
+ `dist`. Every example on the site is rendered by the current source, so a demo
195
+ that no longer compiles against the real API fails the build rather than
196
+ quietly documenting an API that no longer exists.
131
197
 
132
- ```bash
133
- # Start Vite App & local Storybook server
134
- npm run dev:all
198
+ Two generation steps keep it honest:
135
199
 
136
- # Build package artifacts (ESM, UMD, CSS, and Types)
137
- npm run build
200
+ - **Props tables** come from `website/scripts/generate-api.mjs`, which parses
201
+ the component sources for prop names, types, defaults and JSDoc. Nothing is
202
+ hand-written.
203
+ - **Code samples** are extracted from the demo files by `#region` marker, so the
204
+ snippet a visitor copies is provably the code that produced the thing they
205
+ just interacted with.
138
206
 
139
- # Run Playwright E2E and Visual Regression tests
140
- npx playwright test
141
- ```
207
+ Adding a component to the site is one entry in `website/src/content/components.ts`
208
+ plus a demo file. There is no per-component page to keep in sync.
209
+
210
+ The site ships no dependencies of its own — routing, syntax highlighting and the
211
+ copy button are all local, so the docs can't drag the repo's install surface
212
+ around.
213
+
214
+ **Deployment.** `.github/workflows/deploy-pages.yml` builds the site and
215
+ Storybook on every push to `main` and publishes them as one Pages artifact — the
216
+ site at the root, Storybook under `/storybook/`. First-time setup needs your
217
+ credentials: run `./scripts/setup-pages.sh`.
218
+
219
+ The split between `components/` and `connected/` is the load-bearing one. A
220
+ component that reads a global store can't be configured by its caller, rendered
221
+ twice with different data, or documented — its props table is empty because it
222
+ has no props. Everything in `components/` is therefore forbidden from importing
223
+ `core/services`, and the tests in `components/__tests__` exist to keep it that
224
+ way.
142
225
 
143
- ---
226
+ Anything under `examples/` is a consumer of the library, not part of it. It's
227
+ built and documented alongside the components to prove the primitives are
228
+ sufficient, but it ships to nobody.
144
229
 
145
- ## 📄 License
230
+ ## License
146
231
 
147
- MIT © [David/TechMuch]
232
+ MIT
@@ -1,17 +1,95 @@
1
- import { Model } from 'flexlayout-react';
1
+ import { ReactNode } from 'react';
2
+ import { Model, IJsonModel } from 'flexlayout-react';
3
+ import { IMenuItemConfig } from '../../core/registry/MenuRegistry';
4
+ import { ISlashCommandConfig } from '../../core/services/ChatService';
2
5
  import { ISidebarPanel } from '../../core/services/SidebarService';
3
- import { ISlashCommand } from '../../core/services/ChatService';
4
- import { IStatusBarWidget } from '../../core/services/StatusBarService';
5
- import { IMenuItem } from '../../core/registry/MenuRegistry';
6
+ import { IStatusBarWidgetConfig } from '../../core/services/StatusBarService';
6
7
 
7
- interface ShellLayoutProps {
8
+ export interface ShellLayoutProps {
9
+ /**
10
+ * Sidebar panels to register. Each becomes an icon in the activity bar and
11
+ * renders its `component` in the sidebar when selected.
12
+ */
8
13
  panels?: ISidebarPanel[];
9
- slashCommands?: ISlashCommand[];
10
- menuConfig?: Record<string, IMenuItem[]>;
11
- statusBarConfig?: IStatusBarWidget[];
12
- rightMenuBarContent?: React.ReactNode;
13
- title?: React.ReactNode;
14
+ /** Slash commands available in the chat pane. */
15
+ slashCommands?: ISlashCommandConfig[];
16
+ /** Menu structure, keyed by top-level menu name. Items dispatch by `commandId`. */
17
+ menuConfig?: Record<string, IMenuItemConfig[]>;
18
+ /** Items for the status bar, grouped by their `alignment`. */
19
+ statusBarConfig?: IStatusBarWidgetConfig[];
20
+ /** Branding shown at the far left of the menu bar. */
21
+ title?: ReactNode;
22
+ /** Slot at the far right of the menu bar, for actions or a theme switcher. */
23
+ rightMenuBarContent?: ReactNode;
24
+ /** Widget rendered between the menus and the right slot, sized for search. */
25
+ centerMenuBarContent?: ReactNode;
26
+ /**
27
+ * Take control of the docking layout. When provided, the shell renders this
28
+ * model and stops writing changes to `useLayoutStore` — useful for tests and
29
+ * stories. Omit it to use the store's persisted model.
30
+ */
14
31
  layoutModel?: Model;
32
+ /**
33
+ * Starting workspace, as a `flexlayout-react` JSON model. Applied once on
34
+ * mount and only when nothing has been restored from storage, so it seeds a
35
+ * first run without overwriting a layout the user has since arranged.
36
+ *
37
+ * Ignored when `layoutModel` is provided, which takes control outright.
38
+ */
39
+ initialLayoutJson?: IJsonModel;
40
+ /**
41
+ * Stop persisting the layout to `localStorage`. The workspace then resets to
42
+ * `initialLayoutJson` on every load — useful for embedded or multi-tenant
43
+ * shells where a per-browser layout would be wrong. Defaults to `false`.
44
+ */
45
+ disableLocalStorage?: boolean;
46
+ /**
47
+ * Called with the serialised model whenever the user moves, splits, opens or
48
+ * closes a tab. Use it to persist the layout somewhere of your own — a user
49
+ * profile on the server, say — instead of, or alongside, `localStorage`.
50
+ */
51
+ onLayoutChange?: (layout: IJsonModel) => void;
15
52
  }
16
- export declare const ShellLayout: ({ panels, slashCommands, menuConfig, statusBarConfig, rightMenuBarContent, title, layoutModel }: ShellLayoutProps) => import("react/jsx-runtime").JSX.Element;
17
- export {};
53
+ /**
54
+ * The complete application shell: menu bar, activity bar, sidebar, a
55
+ * `flexlayout-react` docking workspace, terminal, chat pane and status bar.
56
+ *
57
+ * **This is where an application starts.** Call {@link initializeShell} once to
58
+ * register your commands, menus and panels, render this component, and add
59
+ * features by registering them rather than by restructuring the layout. Tab
60
+ * contents resolve through the {@link componentRegistry}, so a new view is a
61
+ * registration and a menu entry — the shell never needs to import it.
62
+ *
63
+ * Configuration can arrive either way. Props are convenient for values that
64
+ * change with your app's state; {@link initializeShell} is better for the fixed
65
+ * set, since it runs once and works outside React. Props passed here are
66
+ * written into the same stores on mount, so the two are interchangeable.
67
+ *
68
+ * Internally this composes the `Connected*` component variants, which read from
69
+ * the shell stores. Those components — and the pure ones beneath them — are
70
+ * exported too, for the cases where you need to rearrange the frame itself.
71
+ *
72
+ * Closing a tab marked dirty via `useLayoutStore().setTabDirty` prompts for
73
+ * confirmation before the tab is removed.
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * // main.tsx — a complete application
78
+ * import { initializeShell, ShellLayout, componentRegistry, AppTitle } from 'nexus-shell';
79
+ * import 'nexus-shell/style.css';
80
+ *
81
+ * componentRegistry.register('editor', Editor);
82
+ *
83
+ * initializeShell({
84
+ * panels: [{ id: 'files', label: 'Explorer', icon: Files, component: FileTree }],
85
+ * commands: [{ id: 'file.save', label: 'File: Save', keybinding: 'Control+s', execute: save }],
86
+ * menus: { File: [{ id: 'save', label: 'Save', commandId: 'file.save' }] },
87
+ * statusBar: [{ id: 'branch', label: 'main', alignment: 'left' }],
88
+ * });
89
+ *
90
+ * createRoot(document.getElementById('root')!).render(
91
+ * <ShellLayout title={<AppTitle title="Acme Studio" icon={<Boxes size={16} />} />} />,
92
+ * );
93
+ * ```
94
+ */
95
+ export declare const ShellLayout: ({ panels, slashCommands, menuConfig, statusBarConfig, title, rightMenuBarContent, centerMenuBarContent, layoutModel, initialLayoutJson, disableLocalStorage, onLayoutChange, }: ShellLayoutProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1,48 @@
1
- export declare const ActivityBar: () => import("react/jsx-runtime").JSX.Element;
1
+ import { LucideIcon } from 'lucide-react';
2
+
3
+ /** A single icon button in the {@link ActivityBar}. */
4
+ export interface IActivityBarItem {
5
+ /** Stable identifier reported to `onSelect`. */
6
+ id: string;
7
+ /** Accessible label and tooltip text. */
8
+ label: string;
9
+ /** `lucide-react` icon rendered at 20px. */
10
+ icon: LucideIcon;
11
+ }
12
+ export interface ActivityBarProps {
13
+ /** Items rendered in the main (top) group, in order. */
14
+ items?: IActivityBarItem[];
15
+ /**
16
+ * Items rendered in the bottom group, below the flex spacer. Defaults to a
17
+ * single Settings item. Pass `[]` to render no bottom group.
18
+ */
19
+ bottomItems?: IActivityBarItem[];
20
+ /** Id of the currently active item, or `null` when nothing is selected. */
21
+ activeId?: string | null;
22
+ /**
23
+ * Called with the clicked item's id. Toggling — clicking the active item to
24
+ * deselect it — is the caller's decision, not the component's.
25
+ */
26
+ onSelect?: (id: string) => void;
27
+ /** Extra classes merged onto the root `<aside>`. */
28
+ className?: string;
29
+ /** Accessible label for the landmark. Defaults to `"Activity Bar"`. */
30
+ 'aria-label'?: string;
31
+ }
32
+ /**
33
+ * The narrow vertical icon rail on the left edge of the shell, used to switch
34
+ * which panel the sidebar shows.
35
+ *
36
+ * Controlled — it holds no selection state. For the store-backed variant used
37
+ * by `ShellLayout`, see `ConnectedActivityBar`.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * <ActivityBar
42
+ * items={[{ id: 'files', label: 'Explorer', icon: Files }]}
43
+ * activeId={active}
44
+ * onSelect={(id) => setActive(id === active ? null : id)}
45
+ * />
46
+ * ```
47
+ */
48
+ export declare const ActivityBar: ({ items, bottomItems, activeId, onSelect, className, "aria-label": ariaLabel, }: ActivityBarProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { default as React } from 'react';
2
+
3
+ export interface AppTitleProps {
4
+ /** Primary line. Rendered uppercase in a mono face. */
5
+ title: string;
6
+ /** Secondary line beneath the title. Omit to render a single line. */
7
+ subtitle?: string;
8
+ /**
9
+ * Element shown in the leading badge, typically a 16px `lucide-react` icon.
10
+ * Omit to render no badge at all.
11
+ */
12
+ icon?: React.ReactNode;
13
+ /** Extra classes merged onto the root element. */
14
+ className?: string;
15
+ }
16
+ /**
17
+ * A branding lockup — icon badge, title and subtitle — sized for the
18
+ * {@link MenuBar}'s `title` slot.
19
+ *
20
+ * Purely presentational. Pass whatever branding your app needs; the library
21
+ * supplies no default copy.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * <MenuBar
26
+ * title={<AppTitle title="Acme Studio" subtitle="Design System" icon={<Boxes size={16} />} />}
27
+ * />
28
+ * ```
29
+ */
30
+ export declare const AppTitle: ({ title, subtitle, icon, className }: AppTitleProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1,63 @@
1
- export declare const ChatPane: () => import("react/jsx-runtime").JSX.Element | null;
1
+ import { default as React } from 'react';
2
+
3
+ /** A single message in the {@link ChatPane} transcript. */
4
+ export interface IChatMessage {
5
+ /** Stable identifier. Used as the React key. */
6
+ id: string;
7
+ /** Who sent it. `'user'` right-aligns; anything else left-aligns. */
8
+ role: 'user' | 'assistant';
9
+ /** Message body. Rendered as plain text with newlines preserved. */
10
+ text: string;
11
+ /** Optional display name shown above the bubble. Defaults from `role`. */
12
+ author?: string;
13
+ }
14
+ /** A `/`-prefixed shortcut offered in the composer's autocomplete. */
15
+ export interface ISlashCommand {
16
+ /** Command word without the leading slash, e.g. `"clear"`. */
17
+ command: string;
18
+ /** One-line description shown beside the command in the suggestion list. */
19
+ description: string;
20
+ }
21
+ export interface ChatPaneProps {
22
+ /** Messages to display, oldest first. */
23
+ messages?: IChatMessage[];
24
+ /**
25
+ * Called with the trimmed message text on send. The component clears its
26
+ * composer but does not append to `messages` — that is the caller's job.
27
+ */
28
+ onSend?: (text: string) => void;
29
+ /** Slash commands offered once the composer starts with `/`. */
30
+ slashCommands?: ISlashCommand[];
31
+ /** Called when a slash command is picked from the suggestion list. */
32
+ onSlashCommand?: (command: ISlashCommand) => void;
33
+ /** Called when the close button is pressed. Omit to hide the button. */
34
+ onClose?: () => void;
35
+ /** Title shown in the pane header. Defaults to `"Chat"`. */
36
+ title?: string;
37
+ /** Placeholder for the composer. */
38
+ placeholder?: string;
39
+ /** Shown in place of the transcript when `messages` is empty. */
40
+ emptyState?: React.ReactNode;
41
+ /** Extra classes merged onto the root element. */
42
+ className?: string;
43
+ }
44
+ /**
45
+ * A docked chat panel: a scrolling transcript over a composer with slash-command
46
+ * autocomplete.
47
+ *
48
+ * Fully controlled — it owns only the in-progress input and the suggestion
49
+ * highlight. Messages, sending and visibility belong to the caller, so the same
50
+ * component works against a local array, a websocket, or an LLM endpoint. For
51
+ * the store-backed variant used by `ShellLayout`, see `ConnectedChatPane`.
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * <ChatPane
56
+ * messages={messages}
57
+ * onSend={(text) => send(text)}
58
+ * slashCommands={[{ command: 'clear', description: 'Clear the transcript' }]}
59
+ * onClose={() => setOpen(false)}
60
+ * />
61
+ * ```
62
+ */
63
+ export declare const ChatPane: ({ messages, onSend, slashCommands, onSlashCommand, onClose, title, placeholder, emptyState, className, }: ChatPaneProps) => import("react/jsx-runtime").JSX.Element;