nexus-shell 0.2.1 → 0.2.3
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 +2 -2
- package/dist/components/widgets/TreeWidget.d.ts +89 -44
- package/dist/index.d.ts +1 -1
- package/dist/nexus-shell.es.js +581 -605
- package/dist/nexus-shell.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ const [active, setActive] = useState<string | null>('files');
|
|
|
92
92
|
/>
|
|
93
93
|
{active && (
|
|
94
94
|
<SidebarPane title="Explorer" onClose={() => setActive(null)}>
|
|
95
|
-
<TreeWidget data={
|
|
95
|
+
<TreeWidget data={nodes} onToggle={toggle} onActivate={open} />
|
|
96
96
|
</SidebarPane>
|
|
97
97
|
)}
|
|
98
98
|
<main className="flex-1">{children}</main>
|
|
@@ -128,7 +128,7 @@ shell's own frame and keep every registration working.
|
|
|
128
128
|
| `StatusBar` | Footer with left / center / right item groups |
|
|
129
129
|
| `TerminalPane` | Bottom-docked terminal log and input |
|
|
130
130
|
| `ThemeSwitcher` | Segmented theme control |
|
|
131
|
-
| `TreeWidget` | Virtualised
|
|
131
|
+
| `TreeWidget` | Virtualised tree for any hierarchy, with drag-to-move and a data-driven menu |
|
|
132
132
|
| `UserProfile` | Avatar and identity widget |
|
|
133
133
|
|
|
134
134
|
## Theming
|
|
@@ -1,31 +1,60 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* A node in the {@link TreeWidget} hierarchy.
|
|
5
|
+
*
|
|
6
|
+
* The model is deliberately domain-neutral: the component knows about branches
|
|
7
|
+
* and leaves, and nothing else. A file explorer, an org chart, a scene graph and
|
|
8
|
+
* a category picker are all the same shape here — what differs is your `kind`
|
|
9
|
+
* and your `icon`.
|
|
10
|
+
*/
|
|
4
11
|
export interface ITreeNode {
|
|
5
12
|
/** Stable identifier, unique across the whole tree. */
|
|
6
13
|
id: string;
|
|
7
14
|
/** Text shown for the node. */
|
|
8
15
|
label: string;
|
|
9
|
-
/**
|
|
10
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Whether this node can contain children — a folder, a department, a group.
|
|
18
|
+
* Branches expand on click and accept drops; leaves do neither.
|
|
19
|
+
*
|
|
20
|
+
* Defaults to `false`. Set it explicitly for a branch whose children haven't
|
|
21
|
+
* been loaded yet, so it still renders as expandable.
|
|
22
|
+
*/
|
|
23
|
+
isBranch?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Your own classification for this node, e.g. `"folder"`, `"department"`,
|
|
26
|
+
* `"question"`. The component never interprets it — it exists so context-menu
|
|
27
|
+
* actions can target node types through {@link ITreeAction.showFor}.
|
|
28
|
+
*/
|
|
29
|
+
kind?: string;
|
|
11
30
|
/** Child nodes. Only rendered while `isOpen` is `true`. */
|
|
12
31
|
children?: ITreeNode[];
|
|
13
|
-
/** Whether a
|
|
32
|
+
/** Whether a branch is expanded. Controlled by you — see `onToggle`. */
|
|
14
33
|
isOpen?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Icon rendered before the label. Any node works — a `lucide-react` icon, an
|
|
36
|
+
* avatar, a coloured dot. Omit it for a label-only row.
|
|
37
|
+
*/
|
|
38
|
+
icon?: React.ReactNode;
|
|
39
|
+
/** Extra classes merged onto this row. */
|
|
40
|
+
className?: string;
|
|
15
41
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Where a context-menu action applies.
|
|
18
|
-
*
|
|
19
|
-
* `nodeId` is `null` when the menu was opened on empty background, which is how
|
|
20
|
-
* you distinguish "new file here" from "new file at the root".
|
|
21
|
-
*/
|
|
42
|
+
/** Where a context-menu action applies. */
|
|
22
43
|
export interface ITreeContext {
|
|
23
44
|
/** The right-clicked node's id, or `null` for the background. */
|
|
24
45
|
nodeId: string | null;
|
|
25
46
|
/** The right-clicked node, or `null` for the background. */
|
|
26
47
|
node: ITreeNode | null;
|
|
27
48
|
}
|
|
28
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Where a context-menu entry is offered.
|
|
51
|
+
*
|
|
52
|
+
* `'branch'` and `'leaf'` match structurally; `'background'` is a right-click on
|
|
53
|
+
* empty space. Any other string is matched against the node's `kind`, so you can
|
|
54
|
+
* scope an action to your own node types.
|
|
55
|
+
*/
|
|
56
|
+
export type TreeActionScope = 'branch' | 'leaf' | 'background' | (string & {});
|
|
57
|
+
/** An entry in the tree's right-click menu. */
|
|
29
58
|
export interface ITreeAction {
|
|
30
59
|
/** Stable identifier. Used as the React key. */
|
|
31
60
|
id: string;
|
|
@@ -38,39 +67,38 @@ export interface ITreeAction {
|
|
|
38
67
|
/** Draw a separator above this entry. */
|
|
39
68
|
divider?: boolean;
|
|
40
69
|
/**
|
|
41
|
-
* Restrict where the entry appears. Defaults to everywhere.
|
|
42
|
-
*
|
|
70
|
+
* Restrict where the entry appears. Defaults to everywhere.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* showFor: ['branch', 'background'] // structural
|
|
75
|
+
* showFor: ['department'] // matches node.kind
|
|
76
|
+
* ```
|
|
43
77
|
*/
|
|
44
|
-
showFor?:
|
|
78
|
+
showFor?: TreeActionScope[];
|
|
45
79
|
}
|
|
46
80
|
export interface TreeWidgetProps {
|
|
47
81
|
/** Root nodes. Expansion state lives on the nodes themselves via `isOpen`. */
|
|
48
82
|
data: ITreeNode[];
|
|
49
83
|
/**
|
|
50
|
-
* Called when a
|
|
84
|
+
* Called when a branch is clicked. Flip that node's `isOpen` in your own
|
|
51
85
|
* state — the tree renders expansion but does not own it.
|
|
52
86
|
*/
|
|
53
87
|
onToggle?: (node: ITreeNode) => void;
|
|
54
|
-
/** Called when a node is double-clicked
|
|
88
|
+
/** Called when a node is double-clicked or Enter is pressed on a leaf. */
|
|
55
89
|
onActivate?: (node: ITreeNode) => void;
|
|
56
|
-
/** Called after a node is dragged onto a folder. */
|
|
57
|
-
onMoveNode?: (draggedId: string, targetFolderId: string) => void;
|
|
58
90
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
91
|
+
* Called after a node is dragged onto a branch. Only branches accept drops.
|
|
92
|
+
* Reparenting is yours to perform — the tree does not mutate `data`.
|
|
93
|
+
*/
|
|
94
|
+
onMoveNode?: (draggedId: string, targetBranchId: string) => void;
|
|
95
|
+
/**
|
|
96
|
+
* Entries for the right-click menu. Empty by default: the component ships no
|
|
97
|
+
* actions of its own, because "New File" means nothing to an org chart.
|
|
61
98
|
*
|
|
62
|
-
*
|
|
63
|
-
* point for app-specific commands, so the tree itself stays generic.
|
|
99
|
+
* With no entries, no menu appears.
|
|
64
100
|
*/
|
|
65
101
|
actions?: ITreeAction[];
|
|
66
|
-
/** Handler for the built-in "New File" action. */
|
|
67
|
-
onNewFile?: (parentId: string | null) => void;
|
|
68
|
-
/** Handler for the built-in "New Folder" action. */
|
|
69
|
-
onNewFolder?: (parentId: string | null) => void;
|
|
70
|
-
/** Handler for the built-in "Rename" action. */
|
|
71
|
-
onRename?: (nodeId: string) => void;
|
|
72
|
-
/** Handler for the built-in "Delete" action. */
|
|
73
|
-
onDelete?: (nodeId: string) => void;
|
|
74
102
|
/** Indentation added per depth level, in px. Defaults to `12`. */
|
|
75
103
|
indent?: number;
|
|
76
104
|
/**
|
|
@@ -79,32 +107,49 @@ export interface TreeWidgetProps {
|
|
|
79
107
|
* search, or a test environment that can't measure layout. Defaults to `true`.
|
|
80
108
|
*/
|
|
81
109
|
virtualized?: boolean;
|
|
110
|
+
/** Accessible label for the tree. Defaults to `"Tree"`. */
|
|
111
|
+
'aria-label'?: string;
|
|
82
112
|
/** Extra classes merged onto the root element. */
|
|
83
113
|
className?: string;
|
|
84
114
|
}
|
|
85
115
|
/**
|
|
86
|
-
* A virtualised
|
|
116
|
+
* A virtualised, domain-neutral tree with drag-to-move and a data-driven
|
|
117
|
+
* right-click menu.
|
|
87
118
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* `
|
|
91
|
-
* a
|
|
119
|
+
* It renders any hierarchy — files, an org chart, a scene graph, nested
|
|
120
|
+
* categories, an argument map. The component's only structural concept is
|
|
121
|
+
* `isBranch`: branches expand and accept drops, leaves do neither. Everything
|
|
122
|
+
* else — what a node *is*, what icon it carries, what actions it offers — is
|
|
123
|
+
* yours to supply.
|
|
92
124
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
125
|
+
* Rows are virtualised via `react-virtuoso`, so large trees stay responsive.
|
|
126
|
+
*
|
|
127
|
+
* Controlled: expansion lives on your nodes as `isOpen` and changes are
|
|
128
|
+
* reported through `onToggle`, so the tree never holds a second copy of your
|
|
129
|
+
* data.
|
|
96
130
|
*
|
|
97
131
|
* @example
|
|
98
132
|
* ```tsx
|
|
133
|
+
* // An org chart — no files in sight.
|
|
99
134
|
* <TreeWidget
|
|
100
|
-
* data={
|
|
101
|
-
*
|
|
102
|
-
*
|
|
135
|
+
* data={[
|
|
136
|
+
* {
|
|
137
|
+
* id: 'eng',
|
|
138
|
+
* label: 'Engineering',
|
|
139
|
+
* isBranch: true,
|
|
140
|
+
* kind: 'department',
|
|
141
|
+
* isOpen: true,
|
|
142
|
+
* icon: <Building2 size={14} />,
|
|
143
|
+
* children: [
|
|
144
|
+
* { id: 'ada', label: 'Ada Lovelace', kind: 'person', icon: <User size={14} /> },
|
|
145
|
+
* ],
|
|
146
|
+
* },
|
|
147
|
+
* ]}
|
|
148
|
+
* onToggle={(node) => setNodes(toggle(nodes, node.id))}
|
|
103
149
|
* actions={[
|
|
104
|
-
* { id: '
|
|
105
|
-
* showFor: ['folder', 'background'], onSelect: (ctx) => createMap(ctx.nodeId) },
|
|
150
|
+
* { id: 'hire', label: 'Add report', showFor: ['department'], onSelect: addReport },
|
|
106
151
|
* ]}
|
|
107
152
|
* />
|
|
108
153
|
* ```
|
|
109
154
|
*/
|
|
110
|
-
export declare const TreeWidget: ({ data, onToggle, onActivate, onMoveNode, actions,
|
|
155
|
+
export declare const TreeWidget: ({ data, onToggle, onActivate, onMoveNode, actions, indent, virtualized, "aria-label": ariaLabel, className, }: TreeWidgetProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* you need a layout the shell cannot express. Most applications should not need
|
|
23
23
|
* to.
|
|
24
24
|
*/
|
|
25
|
-
export { ShellLayout, type ShellLayoutProps } from './components/layout/ShellLayout';
|
|
25
|
+
export { ShellLayout, ShellLayout as NexusWorkspaceShell, type ShellLayoutProps } from './components/layout/ShellLayout';
|
|
26
26
|
export { initializeShell, DEFAULT_COMMAND_IDS, type InitializeShellOptions, } from './core/Boot';
|
|
27
27
|
export { commandRegistry, CommandRegistry, type ICommand } from './core/registry/CommandRegistry';
|
|
28
28
|
export { menuRegistry, MenuRegistry, type IMenuItemConfig } from './core/registry/MenuRegistry';
|