@qontinui/navigation 0.1.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.
@@ -0,0 +1,417 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * Navigation Types
5
+ *
6
+ * Shared type definitions for navigation structures across Qontinui applications.
7
+ */
8
+ /**
9
+ * Icon names that map to lucide-react icons.
10
+ * Each app imports the actual icon component from lucide-react.
11
+ */
12
+ type IconName = "Video" | "Play" | "Activity" | "History" | "Bot" | "Settings" | "HelpCircle" | "ChevronDown" | "ChevronRight" | "ScrollText" | "LayoutDashboard" | "ClipboardCheck" | "Zap" | "Radio" | "Radar" | "Image" | "ClipboardList" | "FileText" | "FileSearch" | "TestTube" | "BarChart3" | "Database" | "Cloud" | "Accessibility" | "AlertCircle" | "Bug" | "BookOpen" | "BookText" | "CheckCircle2" | "Sparkles" | "MousePointer2" | "Layers" | "FlaskConical" | "Camera" | "GitBranch" | "Network" | "Globe" | "Code" | "Puzzle" | "ShieldCheck" | "ShieldAlert" | "Wifi" | "Terminal" | "ListChecks" | "FolderOpen" | "Tag" | "Plug" | "Calendar" | "User" | "HardDrive" | "Wrench" | "Download" | "Archive" | "Monitor" | "Palette" | "Bell" | "Key" | "CreditCard" | "Brain" | "Eye" | "Webhook" | "RotateCcw" | "Cpu" | "Repeat" | "Target" | "MessageSquare" | "Server" | "Workflow" | "Package";
13
+ /**
14
+ * A single navigation item in the sidebar.
15
+ */
16
+ interface NavigationItem {
17
+ /** Unique identifier for this item */
18
+ id: string;
19
+ /** Display label */
20
+ label: string;
21
+ /** Icon name (maps to lucide-react icon) */
22
+ icon: IconName;
23
+ /** Optional description shown in tooltips or secondary text */
24
+ description?: string;
25
+ /** Whether this item should be visually indented (for sub-items in flat lists) */
26
+ indent?: boolean;
27
+ /** If set, this item is a child of another item */
28
+ parentId?: string;
29
+ /** If true, this item has children and can be expanded/collapsed */
30
+ hasChildren?: boolean;
31
+ /** If true, clicking this item selects its first child instead of itself */
32
+ selectsFirstChild?: boolean;
33
+ /** Platform availability - if not set, available on all platforms */
34
+ platforms?: Platform[];
35
+ /** Badge count or status to show on this item */
36
+ badge?: NavigationBadge;
37
+ /** Whether this item is disabled */
38
+ disabled?: boolean;
39
+ /** Keyboard shortcut hint (e.g., "Ctrl+N") */
40
+ shortcut?: string;
41
+ /** Hide from navigation in production (visible in dev mode with a badge) */
42
+ hiddenInProd?: boolean;
43
+ /** Product mode visibility - "ai", "visual", or "both" (default: shown in all modes) */
44
+ productMode?: "ai" | "visual" | "both";
45
+ /** URL path for web routing (e.g., "/build/workflows") */
46
+ route?: string;
47
+ /** Accent color CSS value (e.g., "#9333EA" or "var(--brand-secondary)") */
48
+ color?: string;
49
+ /** Requires superuser access (web-only concept) */
50
+ adminOnly?: boolean;
51
+ }
52
+ /**
53
+ * Badge configuration for navigation items.
54
+ */
55
+ interface NavigationBadge {
56
+ /** Type of badge */
57
+ type: "count" | "dot" | "text";
58
+ /** Value for count or text badges */
59
+ value?: number | string;
60
+ /** Color variant */
61
+ variant?: "default" | "primary" | "success" | "warning" | "error";
62
+ }
63
+ /**
64
+ * A group of navigation items (e.g., RUN, OBSERVE, BUILD).
65
+ */
66
+ interface NavigationGroup {
67
+ /** Unique identifier for this group */
68
+ id: string;
69
+ /** Display label (usually uppercase) */
70
+ label: string;
71
+ /** Items in this group */
72
+ items: NavigationItem[];
73
+ /** Whether this group should be expanded by default */
74
+ defaultExpanded?: boolean;
75
+ /** Icon for the group header (optional) */
76
+ icon?: IconName;
77
+ /** Platform availability - if not set, available on all platforms */
78
+ platforms?: Platform[];
79
+ }
80
+ /**
81
+ * Platform identifiers for conditional navigation items.
82
+ */
83
+ type Platform = "web" | "runner";
84
+ /**
85
+ * State for the secondary sidebar.
86
+ */
87
+ interface SecondarySidebarState {
88
+ /** Whether the secondary sidebar is open */
89
+ isOpen: boolean;
90
+ /** The parent item that triggered the secondary sidebar */
91
+ parentId: string | null;
92
+ /** Items to display in the secondary sidebar */
93
+ items: NavigationItem[];
94
+ }
95
+ /**
96
+ * Complete navigation state.
97
+ */
98
+ interface NavigationState {
99
+ /** Currently active item ID */
100
+ activeItemId: string | null;
101
+ /** Expanded group IDs */
102
+ expandedGroups: Set<string>;
103
+ /** Expanded parent item IDs (for items with children) */
104
+ expandedItems: Set<string>;
105
+ /** Secondary sidebar state */
106
+ secondarySidebar: SecondarySidebarState;
107
+ /** Whether the main sidebar is collapsed */
108
+ isCollapsed: boolean;
109
+ }
110
+ /**
111
+ * Navigation actions for state management.
112
+ */
113
+ type NavigationAction = {
114
+ type: "SET_ACTIVE";
115
+ itemId: string;
116
+ } | {
117
+ type: "TOGGLE_GROUP";
118
+ groupId: string;
119
+ } | {
120
+ type: "TOGGLE_ITEM";
121
+ itemId: string;
122
+ } | {
123
+ type: "EXPAND_GROUP";
124
+ groupId: string;
125
+ } | {
126
+ type: "COLLAPSE_GROUP";
127
+ groupId: string;
128
+ } | {
129
+ type: "OPEN_SECONDARY";
130
+ parentId: string;
131
+ items: NavigationItem[];
132
+ } | {
133
+ type: "CLOSE_SECONDARY";
134
+ } | {
135
+ type: "TOGGLE_SIDEBAR_COLLAPSE";
136
+ } | {
137
+ type: "SET_SIDEBAR_COLLAPSED";
138
+ collapsed: boolean;
139
+ };
140
+
141
+ /**
142
+ * Navigation Groups
143
+ *
144
+ * Shared navigation group definitions for Qontinui applications.
145
+ * These define the structure and hierarchy of the sidebar navigation.
146
+ *
147
+ * Each item can have three orthogonal visibility dimensions:
148
+ * - platform: "runner" | "web" | both (default) — which app shows the item
149
+ * - productMode: "ai" | "visual" | "both" | undefined (default=both) — which product mode
150
+ * - hiddenInProd: true — dev-only items hidden in production
151
+ */
152
+
153
+ declare const RUN_ITEMS: NavigationItem[];
154
+ declare const RUN_GROUP: NavigationGroup;
155
+ declare const SESSION_ITEMS: NavigationItem[];
156
+ declare const RUNS_ITEMS: NavigationItem[];
157
+ declare const OBSERVE_ITEMS: NavigationItem[];
158
+ declare const OBSERVE_GROUP: NavigationGroup;
159
+ declare const LEARN_ITEMS: NavigationItem[];
160
+ declare const LEARN_GROUP: NavigationGroup;
161
+ declare const BUILD_ITEMS: NavigationItem[];
162
+ declare const BUILD_GROUP: NavigationGroup;
163
+ declare const WRAPPERS_ITEMS: NavigationItem[];
164
+ declare const WRAPPERS_GROUP: NavigationGroup;
165
+ declare const CONFIGURE_ITEMS: NavigationItem[];
166
+ declare const CONFIGURE_GROUP: NavigationGroup;
167
+ declare const SCHEDULE_ITEMS: NavigationItem[];
168
+ declare const SCHEDULE_GROUP: NavigationGroup;
169
+ declare const DEV_ITEMS: NavigationItem[];
170
+ declare const DEV_GROUP: NavigationGroup;
171
+ declare const SETTINGS_ITEMS: NavigationItem[];
172
+ declare const SYSTEM_ITEMS: NavigationItem[];
173
+ declare const SYSTEM_GROUP: NavigationGroup;
174
+ /**
175
+ * All navigation groups in order.
176
+ */
177
+ declare const NAVIGATION_GROUPS: NavigationGroup[];
178
+ /**
179
+ * Map of parent IDs to their children for secondary sidebar.
180
+ */
181
+ declare const CHILDREN_MAP: Record<string, NavigationItem[]>;
182
+ /**
183
+ * Get children items for a parent item.
184
+ */
185
+ declare function getChildrenItems(parentId: string): NavigationItem[];
186
+ /**
187
+ * Get all navigation items flattened.
188
+ */
189
+ declare function getAllItems(): NavigationItem[];
190
+ /**
191
+ * Find an item by ID across all groups and children.
192
+ */
193
+ declare function findItemById(id: string): NavigationItem | undefined;
194
+ /**
195
+ * Get the parent group for an item.
196
+ */
197
+ declare function getItemGroup(itemId: string): NavigationGroup | undefined;
198
+
199
+ /**
200
+ * Icon Utilities
201
+ *
202
+ * Runtime validation helpers for icon names.
203
+ */
204
+
205
+ /**
206
+ * All available icon names as an array.
207
+ */
208
+ declare const ICON_NAMES: IconName[];
209
+ /**
210
+ * Check if a string is a valid icon name.
211
+ */
212
+ declare function isValidIconName(name: string): name is IconName;
213
+
214
+ /**
215
+ * Platform Utilities
216
+ *
217
+ * Functions for filtering navigation based on platform.
218
+ */
219
+
220
+ /**
221
+ * Set whether the app is running in development mode.
222
+ * Call this at app startup to enable showing dev-only navigation items.
223
+ */
224
+ declare function setDevelopmentMode(isDev: boolean): void;
225
+ /**
226
+ * Check if running in development mode.
227
+ */
228
+ declare function isDevelopmentMode(): boolean;
229
+ type ProductMode = "ai" | "visual" | null;
230
+ /**
231
+ * Set the active product mode for navigation filtering.
232
+ * Pass null to show all items regardless of product mode.
233
+ */
234
+ declare function setProductMode(mode: ProductMode): void;
235
+ /**
236
+ * Get the current product mode filter.
237
+ */
238
+ declare function getProductMode(): ProductMode;
239
+ /**
240
+ * Filter a navigation item based on platform.
241
+ * Returns true if the item should be shown on the given platform.
242
+ */
243
+ declare function isItemAvailable(item: NavigationItem, platform: Platform): boolean;
244
+ /**
245
+ * Filter navigation items for a specific platform.
246
+ */
247
+ declare function filterItemsForPlatform(items: NavigationItem[], platform: Platform): NavigationItem[];
248
+ /**
249
+ * Filter a navigation group for a specific platform.
250
+ */
251
+ declare function filterGroupForPlatform(group: NavigationGroup, platform: Platform): NavigationGroup;
252
+ /**
253
+ * Filter all navigation groups for a specific platform.
254
+ */
255
+ declare function filterGroupsForPlatform(groups: NavigationGroup[], platform: Platform): NavigationGroup[];
256
+ /**
257
+ * Get navigation groups filtered for a specific platform.
258
+ */
259
+ declare function getNavigationGroups(platform: Platform): NavigationGroup[];
260
+ /**
261
+ * Get children items for a parent, filtered by platform.
262
+ */
263
+ declare function getChildrenForPlatform(parentId: string, platform: Platform): NavigationItem[];
264
+ /**
265
+ * Pre-built navigation config for the runner application.
266
+ */
267
+ declare function getRunnerNavigation(): NavigationGroup[];
268
+ /**
269
+ * Pre-built navigation config for the web application.
270
+ */
271
+ declare function getWebNavigation(): NavigationGroup[];
272
+
273
+ /**
274
+ * Navigation State Management
275
+ *
276
+ * Reducer and utilities for managing navigation state.
277
+ */
278
+
279
+ /**
280
+ * Create the initial navigation state.
281
+ */
282
+ declare function createInitialState(options?: Partial<{
283
+ activeItemId: string | null;
284
+ expandedGroups: string[];
285
+ expandedItems: string[];
286
+ isCollapsed: boolean;
287
+ }>): NavigationState;
288
+ /**
289
+ * Navigation state reducer.
290
+ */
291
+ declare function navigationReducer(state: NavigationState, action: NavigationAction): NavigationState;
292
+ /**
293
+ * Action creators for navigation state.
294
+ */
295
+ declare const navigationActions: {
296
+ setActive: (itemId: string) => NavigationAction;
297
+ toggleGroup: (groupId: string) => NavigationAction;
298
+ toggleItem: (itemId: string) => NavigationAction;
299
+ expandGroup: (groupId: string) => NavigationAction;
300
+ collapseGroup: (groupId: string) => NavigationAction;
301
+ openSecondary: (parentId: string, items: NavigationItem[]) => NavigationAction;
302
+ closeSecondary: () => NavigationAction;
303
+ toggleSidebarCollapse: () => NavigationAction;
304
+ setSidebarCollapsed: (collapsed: boolean) => NavigationAction;
305
+ };
306
+ /**
307
+ * Check if a group is expanded.
308
+ */
309
+ declare function isGroupExpanded(state: NavigationState, groupId: string): boolean;
310
+ /**
311
+ * Check if an item is expanded (for items with children).
312
+ *
313
+ * Currently unused by consumers. Available for future use.
314
+ */
315
+ declare function isItemExpanded(state: NavigationState, itemId: string): boolean;
316
+ /**
317
+ * Check if an item is active.
318
+ *
319
+ * Currently unused by consumers. Available for future use.
320
+ */
321
+ declare function isItemActive(state: NavigationState, itemId: string): boolean;
322
+ /**
323
+ * Check if the secondary sidebar is open for a specific parent.
324
+ *
325
+ * Currently unused by consumers. The runner manages flyout state
326
+ * independently via local React state rather than through the
327
+ * shared navigation reducer.
328
+ */
329
+ declare function isSecondaryOpenFor(state: NavigationState, parentId: string): boolean;
330
+ /**
331
+ * Serialize navigation state for localStorage.
332
+ */
333
+ declare function serializeState(state: NavigationState): string;
334
+ /**
335
+ * Deserialize navigation state from localStorage.
336
+ */
337
+ declare function deserializeState(json: string): Partial<NavigationState> | null;
338
+ /**
339
+ * Storage keys for navigation persistence.
340
+ */
341
+ declare const STORAGE_KEYS: {
342
+ readonly state: "qontinui-navigation-state";
343
+ readonly collapsed: "qontinui-sidebar-collapsed";
344
+ readonly expandedGroups: "qontinui-sidebar-groups";
345
+ readonly activeTab: "qontinui-active-tab";
346
+ };
347
+
348
+ /**
349
+ * React Integration for qontinui-navigation
350
+ *
351
+ * Exposes a lightweight hook and a thin shell component so every navigation
352
+ * item rendered by a consumer automatically registers itself with the UI
353
+ * Bridge as a first-class element. That makes sidebar / secondary-nav
354
+ * entries discoverable via `/control/snapshot` and actionable via
355
+ * `/control/action`, using a stable, predictable id scheme:
356
+ *
357
+ * nav:<item.id> (e.g. "nav:settings-discovery", "nav:build")
358
+ *
359
+ * The hook resolves `useUIElement` from `@qontinui/ui-bridge` lazily so this
360
+ * package remains usable in environments where the UI Bridge isn't
361
+ * installed (tests, Storybook, CLI tooling) — the hook degrades to a no-op
362
+ * rather than crashing.
363
+ */
364
+
365
+ /**
366
+ * Minimal subset of `NavigationItem` the hook needs. Accepting this wider
367
+ * type lets consumer apps that have their own richer nav-item shape (e.g.
368
+ * qontinui-web's `NavItem` with `icon: React.ReactNode`) hand us an object
369
+ * directly without a mapping step — as long as `id` and `label` exist.
370
+ */
371
+ interface NavigationItemLike {
372
+ id: string;
373
+ label: string;
374
+ description?: string;
375
+ }
376
+ /**
377
+ * Register a navigation item with the UI Bridge.
378
+ *
379
+ * - Always assigns `id: nav:<item.id>` (stable, predictable for test scripts
380
+ * and agent-driven workflows).
381
+ * - Exposes a single `click` custom action that invokes the caller-supplied
382
+ * `onActivate`, which matches what a real user click does.
383
+ * - Hints the element's semantic role as `"navigation-item"` via the
384
+ * `variant` field so content-element discovery can group nav entries
385
+ * together.
386
+ * - Tags the element type as `menuitem` (closest DOM semantic, honoured by
387
+ * the existing registry's type filters).
388
+ *
389
+ * If `useUIElement` isn't available at runtime (package not installed, no
390
+ * UIBridgeProvider in the tree, etc.) the hook is a no-op. It never throws.
391
+ *
392
+ * Consumers typically call this hook inside the component that renders the
393
+ * nav item's `<button>`. See `NavigationItemShell` for a zero-boilerplate
394
+ * wrapper.
395
+ */
396
+ declare function useNavigationItem(item: NavigationItemLike, onActivate: () => void): void;
397
+ interface NavigationItemShellProps {
398
+ item: NavigationItemLike;
399
+ onActivate: () => void;
400
+ children: React.ReactNode;
401
+ }
402
+ /**
403
+ * Thin render-prop-free wrapper that invokes `useNavigationItem` for the
404
+ * given `item` + `onActivate` and renders `children` unchanged.
405
+ *
406
+ * Use this when you want auto-registration without refactoring an existing
407
+ * nav button into its own component. Example:
408
+ *
409
+ * ```tsx
410
+ * <NavigationItemShell item={item} onActivate={() => onTabChange(item.id)}>
411
+ * <button onClick={() => onTabChange(item.id)}>{item.label}</button>
412
+ * </NavigationItemShell>
413
+ * ```
414
+ */
415
+ declare function NavigationItemShell({ item, onActivate, children, }: NavigationItemShellProps): React.ReactElement;
416
+
417
+ export { BUILD_GROUP, BUILD_ITEMS, CHILDREN_MAP, CONFIGURE_GROUP, CONFIGURE_ITEMS, DEV_GROUP, DEV_ITEMS, ICON_NAMES, type IconName, LEARN_GROUP, LEARN_ITEMS, NAVIGATION_GROUPS, type NavigationAction, type NavigationBadge, type NavigationGroup, type NavigationItem, type NavigationItemLike, NavigationItemShell, type NavigationItemShellProps, type NavigationState, OBSERVE_GROUP, OBSERVE_ITEMS, type Platform, RUNS_ITEMS, RUN_GROUP, RUN_ITEMS, SCHEDULE_GROUP, SCHEDULE_ITEMS, SESSION_ITEMS, SETTINGS_ITEMS, STORAGE_KEYS, SYSTEM_GROUP, SYSTEM_ITEMS, type SecondarySidebarState, WRAPPERS_GROUP, WRAPPERS_ITEMS, createInitialState, deserializeState, filterGroupForPlatform, filterGroupsForPlatform, filterItemsForPlatform, findItemById, getAllItems, getChildrenForPlatform, getChildrenItems, getItemGroup, getNavigationGroups, getProductMode, getRunnerNavigation, getWebNavigation, isDevelopmentMode, isGroupExpanded, isItemActive, isItemAvailable, isItemExpanded, isSecondaryOpenFor, isValidIconName, navigationActions, navigationReducer, serializeState, setDevelopmentMode, setProductMode, useNavigationItem };