@devalok/shilp-sutra 0.18.1 → 0.18.2
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/docs/components/_header.md +83 -0
- package/docs/components/composed/activity-feed.md +43 -0
- package/docs/components/composed/avatar-group.md +32 -0
- package/docs/components/composed/command-palette.md +40 -0
- package/docs/components/composed/confirm-dialog.md +46 -0
- package/docs/components/composed/content-card.md +36 -0
- package/docs/components/composed/date-picker.md +130 -0
- package/docs/components/composed/empty-state.md +53 -0
- package/docs/components/composed/error-boundary.md +29 -0
- package/docs/components/composed/global-loading.md +27 -0
- package/docs/components/composed/loading-skeleton.md +51 -0
- package/docs/components/composed/member-picker.md +35 -0
- package/docs/components/composed/page-header.md +41 -0
- package/docs/components/composed/page-skeletons.md +32 -0
- package/docs/components/composed/priority-indicator.md +32 -0
- package/docs/components/composed/rich-text-editor.md +71 -0
- package/docs/components/composed/schedule-view.md +39 -0
- package/docs/components/composed/simple-tooltip.md +33 -0
- package/docs/components/composed/status-badge.md +41 -0
- package/docs/components/shell/app-command-palette.md +44 -0
- package/docs/components/shell/bottom-navbar.md +48 -0
- package/docs/components/shell/command-registry.md +48 -0
- package/docs/components/shell/link-context.md +41 -0
- package/docs/components/shell/notification-center.md +63 -0
- package/docs/components/shell/notification-preferences.md +42 -0
- package/docs/components/shell/sidebar.md +88 -0
- package/docs/components/shell/top-bar.md +63 -0
- package/docs/components/ui/accordion.md +48 -0
- package/docs/components/ui/alert-dialog.md +58 -0
- package/docs/components/ui/alert.md +43 -0
- package/docs/components/ui/aspect-ratio.md +25 -0
- package/docs/components/ui/autocomplete.md +48 -0
- package/docs/components/ui/avatar.md +34 -0
- package/docs/components/ui/badge.md +48 -0
- package/docs/components/ui/banner.md +35 -0
- package/docs/components/ui/breadcrumb.md +37 -0
- package/docs/components/ui/button-group.md +32 -0
- package/docs/components/ui/button.md +55 -0
- package/docs/components/ui/card.md +48 -0
- package/docs/components/ui/charts.md +43 -0
- package/docs/components/ui/checkbox.md +31 -0
- package/docs/components/ui/chip.md +43 -0
- package/docs/components/ui/code.md +28 -0
- package/docs/components/ui/collapsible.md +40 -0
- package/docs/components/ui/color-input.md +37 -0
- package/docs/components/ui/combobox.md +54 -0
- package/docs/components/ui/container.md +26 -0
- package/docs/components/ui/context-menu.md +43 -0
- package/docs/components/ui/data-table-toolbar.md +44 -0
- package/docs/components/ui/data-table.md +91 -0
- package/docs/components/ui/dialog.md +51 -0
- package/docs/components/ui/dropdown-menu.md +45 -0
- package/docs/components/ui/file-upload.md +41 -0
- package/docs/components/ui/form.md +51 -0
- package/docs/components/ui/hover-card.md +32 -0
- package/docs/components/ui/icon-button.md +33 -0
- package/docs/components/ui/input-otp.md +44 -0
- package/docs/components/ui/input.md +48 -0
- package/docs/components/ui/label.md +25 -0
- package/docs/components/ui/link.md +29 -0
- package/docs/components/ui/menubar.md +44 -0
- package/docs/components/ui/navigation-menu.md +46 -0
- package/docs/components/ui/number-input.md +44 -0
- package/docs/components/ui/pagination.md +48 -0
- package/docs/components/ui/popover.md +30 -0
- package/docs/components/ui/progress.md +29 -0
- package/docs/components/ui/radio.md +34 -0
- package/docs/components/ui/search-input.md +43 -0
- package/docs/components/ui/segmented-control.md +50 -0
- package/docs/components/ui/select.md +49 -0
- package/docs/components/ui/separator.md +29 -0
- package/docs/components/ui/sheet.md +47 -0
- package/docs/components/ui/sidebar.md +72 -0
- package/docs/components/ui/skeleton.md +77 -0
- package/docs/components/ui/slider.md +29 -0
- package/docs/components/ui/spinner.md +50 -0
- package/docs/components/ui/stack.md +39 -0
- package/docs/components/ui/stat-card.md +61 -0
- package/docs/components/ui/stepper.md +49 -0
- package/docs/components/ui/switch.md +34 -0
- package/docs/components/ui/table.md +47 -0
- package/docs/components/ui/tabs.md +56 -0
- package/docs/components/ui/text.md +37 -0
- package/docs/components/ui/textarea.md +39 -0
- package/docs/components/ui/toast.md +65 -0
- package/docs/components/ui/toaster.md +47 -0
- package/docs/components/ui/toggle-group.md +43 -0
- package/docs/components/ui/toggle.md +37 -0
- package/docs/components/ui/tooltip.md +33 -0
- package/docs/components/ui/tree-view.md +65 -0
- package/docs/components/ui/visually-hidden.md +21 -0
- package/llms-full.txt +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# PriorityIndicator
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/composed/priority-indicator
|
|
4
|
+
- Server-safe: Yes
|
|
5
|
+
- Category: composed
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
priority: Priority
|
|
9
|
+
display: "compact" | "full" (default: "full")
|
|
10
|
+
|
|
11
|
+
Priority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' | 'low' | 'medium' | 'high' | 'urgent'
|
|
12
|
+
|
|
13
|
+
## Defaults
|
|
14
|
+
display="full"
|
|
15
|
+
|
|
16
|
+
## Example
|
|
17
|
+
```jsx
|
|
18
|
+
<PriorityIndicator priority="HIGH" />
|
|
19
|
+
<PriorityIndicator priority="low" display="compact" />
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Gotchas
|
|
23
|
+
- Case-insensitive — "low" and "LOW" both work
|
|
24
|
+
- Server-safe: can be imported directly in Next.js Server Components
|
|
25
|
+
- `compact` display shows only the icon; `full` shows icon + text label
|
|
26
|
+
|
|
27
|
+
## Changes
|
|
28
|
+
### v0.2.0
|
|
29
|
+
- **Added** Identified as server-safe component
|
|
30
|
+
|
|
31
|
+
### v0.1.0
|
|
32
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# RichTextEditor
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/composed/rich-text-editor
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: composed
|
|
6
|
+
|
|
7
|
+
Exports: RichTextEditor, RichTextViewer
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### RichTextEditor
|
|
12
|
+
content: string (HTML string)
|
|
13
|
+
placeholder: string (default: "Start writing...")
|
|
14
|
+
onChange: (html: string) => void
|
|
15
|
+
className: string
|
|
16
|
+
editable: boolean (default: true)
|
|
17
|
+
onImageUpload?: (file: File) => Promise<string> — return URL. If omitted, images paste as base64
|
|
18
|
+
onFileUpload?: (file: File) => Promise<{ url: string; name: string; size: number }> — enables file attachments
|
|
19
|
+
mentions?: MentionItem[] — static list for @mention autocomplete
|
|
20
|
+
onMentionSearch?: (query: string) => Promise<MentionItem[]> — async search, takes precedence over static mentions
|
|
21
|
+
onMentionSelect?: (item: MentionItem) => void — called when a mention is selected
|
|
22
|
+
|
|
23
|
+
MentionItem: { id: string; label: string; avatar?: string }
|
|
24
|
+
|
|
25
|
+
### RichTextViewer
|
|
26
|
+
content: string (REQUIRED, HTML string)
|
|
27
|
+
className: string
|
|
28
|
+
|
|
29
|
+
## Defaults
|
|
30
|
+
RichTextEditor: placeholder="Start writing...", editable=true
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
```jsx
|
|
34
|
+
<RichTextEditor content={html} onChange={setHtml} placeholder="Write your message..." />
|
|
35
|
+
|
|
36
|
+
<RichTextEditor
|
|
37
|
+
content={html}
|
|
38
|
+
onChange={setHtml}
|
|
39
|
+
mentions={[{ id: '1', label: 'Aarav' }]}
|
|
40
|
+
onImageUpload={async (file) => uploadAndReturnUrl(file)}
|
|
41
|
+
onFileUpload={async (file) => ({ url: uploadUrl, name: file.name, size: file.size })}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<RichTextViewer content={savedHtml} />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Gotchas
|
|
48
|
+
- Tiptap is bundled — no need to install `@tiptap/*` packages separately
|
|
49
|
+
- Emoji picker requires `@emoji-mart/react` + `@emoji-mart/data` peers
|
|
50
|
+
- Images without `onImageUpload` are stored as base64 in HTML — large images bloat content
|
|
51
|
+
- Mention rendering in viewer always works (no mention props needed, just the HTML)
|
|
52
|
+
- Features: bold, italic, underline, strikethrough, highlight, headings, blockquote, lists, task lists, code, links, images, file attachments, mentions, emoji, text alignment, horizontal rule
|
|
53
|
+
|
|
54
|
+
## Changes
|
|
55
|
+
### v0.18.0
|
|
56
|
+
- **Fixed** Use ref to track internal changes, prevent update loop
|
|
57
|
+
|
|
58
|
+
### v0.9.0
|
|
59
|
+
- **Changed** All `@tiptap/*` packages moved from peerDependencies to bundled build-time dependencies — consumers no longer need to install tiptap separately
|
|
60
|
+
|
|
61
|
+
### v0.8.0
|
|
62
|
+
- **Fixed** Emoji picker now renders above the editor (not clipped by overflow)
|
|
63
|
+
- **Fixed** Link/image URL injection prevented via protocol validation
|
|
64
|
+
- **Fixed** Escape key in emoji picker no longer closes parent dialogs
|
|
65
|
+
- **Fixed** Tiptap peer deps tightened to `>=2.27.2 <3.0.0`
|
|
66
|
+
|
|
67
|
+
### v0.7.0
|
|
68
|
+
- **Added** Initial release — full-featured tiptap-based rich text editing with toolbar, mentions, emoji, image, alignment
|
|
69
|
+
|
|
70
|
+
### v0.1.1
|
|
71
|
+
- **Fixed** Added content sync effect so editor updates when `content` prop changes externally
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# ScheduleView
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/composed/schedule-view
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: composed
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
view: "day" | "week" (REQUIRED)
|
|
9
|
+
date: Date (REQUIRED — current day or any date in target week)
|
|
10
|
+
events: ScheduleEvent[] (REQUIRED) — { id, title, start: Date, end: Date, color? }
|
|
11
|
+
onEventClick: (event: ScheduleEvent) => void
|
|
12
|
+
onSlotClick: (start: Date, end: Date) => void
|
|
13
|
+
startHour: number (default: 8)
|
|
14
|
+
endHour: number (default: 18, exclusive)
|
|
15
|
+
slotDuration: number (minutes, default: 30)
|
|
16
|
+
|
|
17
|
+
Event colors: "primary" | "success" | "warning" | "error" | "info" | "neutral"
|
|
18
|
+
|
|
19
|
+
## Defaults
|
|
20
|
+
startHour=8, endHour=18, slotDuration=30
|
|
21
|
+
|
|
22
|
+
## Example
|
|
23
|
+
```jsx
|
|
24
|
+
<ScheduleView
|
|
25
|
+
view="week"
|
|
26
|
+
date={new Date()}
|
|
27
|
+
events={calendarEvents}
|
|
28
|
+
onEventClick={(e) => openEvent(e.id)}
|
|
29
|
+
/>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Gotchas
|
|
33
|
+
- `endHour` is exclusive — `endHour=18` means the last visible slot starts at 17:30 (with default 30min slots)
|
|
34
|
+
- `onSlotClick` fires when clicking an empty time slot — useful for creating new events
|
|
35
|
+
- Events that span outside `startHour`/`endHour` may be clipped
|
|
36
|
+
|
|
37
|
+
## Changes
|
|
38
|
+
### v0.1.0
|
|
39
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# SimpleTooltip
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/composed/simple-tooltip
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: composed
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
content: ReactNode (REQUIRED — tooltip content)
|
|
9
|
+
side: "top" | "right" | "bottom" | "left" (default: "top")
|
|
10
|
+
align: "start" | "center" | "end" (default: "center")
|
|
11
|
+
delayDuration: number (ms, default: 300)
|
|
12
|
+
children: ReactNode (trigger element)
|
|
13
|
+
|
|
14
|
+
## Defaults
|
|
15
|
+
side="top", align="center", delayDuration=300
|
|
16
|
+
|
|
17
|
+
## Example
|
|
18
|
+
```jsx
|
|
19
|
+
<SimpleTooltip content="Edit this item">
|
|
20
|
+
<IconButton icon={<IconEdit />} aria-label="Edit" />
|
|
21
|
+
</SimpleTooltip>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Gotchas
|
|
25
|
+
- Wraps the full Tooltip compound (Provider + Tooltip + Trigger + Content) into one component — no need for TooltipProvider
|
|
26
|
+
- Unlike the low-level Tooltip, SimpleTooltip does not require wrapping in a TooltipProvider
|
|
27
|
+
|
|
28
|
+
## Changes
|
|
29
|
+
### v0.18.0
|
|
30
|
+
- **Fixed** Type definition corrected
|
|
31
|
+
|
|
32
|
+
### v0.1.0
|
|
33
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# StatusBadge
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/composed/status-badge
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: composed
|
|
6
|
+
|
|
7
|
+
Note: StatusBadge was server-safe prior to v0.18.0 but is NO LONGER server-safe due to Framer Motion dependency.
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
status: "active" | "pending" | "approved" | "rejected" | "completed" | "blocked" | "cancelled" | "draft"
|
|
11
|
+
color: "success" | "warning" | "error" | "info" | "neutral" (overrides status styling when set)
|
|
12
|
+
size: "sm" | "md"
|
|
13
|
+
label: string (auto-derived from status/color if omitted)
|
|
14
|
+
hideDot: boolean (default: false)
|
|
15
|
+
|
|
16
|
+
## Defaults
|
|
17
|
+
size="md", hideDot=false
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
```jsx
|
|
21
|
+
<StatusBadge status="active" />
|
|
22
|
+
<StatusBadge color="warning" label="In Review" size="sm" />
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Gotchas
|
|
26
|
+
- When `color` is set, it takes priority over `status` for styling
|
|
27
|
+
- Props use a discriminated union — pass either `status` or `color`, not both
|
|
28
|
+
- As of v0.18.0, StatusBadge is NOT server-safe (Framer Motion dependency)
|
|
29
|
+
|
|
30
|
+
## Changes
|
|
31
|
+
### v0.18.0
|
|
32
|
+
- **Changed** No longer server-safe due to Framer Motion dependency
|
|
33
|
+
|
|
34
|
+
### v0.8.0
|
|
35
|
+
- **Changed** Props now use discriminated union — pass either `status` or `color`, not both
|
|
36
|
+
|
|
37
|
+
### v0.2.0
|
|
38
|
+
- **Added** Identified as server-safe component (later reverted in v0.18.0)
|
|
39
|
+
|
|
40
|
+
### v0.1.0
|
|
41
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# AppCommandPalette
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/app-command-palette
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
user?: AppCommandPaletteUser | null — { name, role? } (optional)
|
|
9
|
+
isAdmin?: boolean (shows admin command groups regardless of user.role; takes precedence over role-based detection)
|
|
10
|
+
extraGroups?: CommandGroup[]
|
|
11
|
+
onNavigate?: (path: string) => void
|
|
12
|
+
onSearch?: (query: string) => void
|
|
13
|
+
searchResults?: SearchResult[]
|
|
14
|
+
isSearching?: boolean (shows loading state while search is in progress)
|
|
15
|
+
onSearchResultSelect?: (result: SearchResult) => void
|
|
16
|
+
|
|
17
|
+
SearchResult: { id: string, title: string, snippet?: string, entityType: string, projectId?: string | null, metadata?: Record<string, unknown> }
|
|
18
|
+
AppCommandPaletteUser: { name: string, role?: string }
|
|
19
|
+
|
|
20
|
+
## Defaults
|
|
21
|
+
None
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
```jsx
|
|
25
|
+
<AppCommandPalette
|
|
26
|
+
user={{ name: 'John', role: 'admin' }}
|
|
27
|
+
isAdmin={true}
|
|
28
|
+
onNavigate={(path) => router.push(path)}
|
|
29
|
+
searchResults={results}
|
|
30
|
+
onSearchResultSelect={(r) => router.push(`/${r.entityType}/${r.id}`)}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Gotchas
|
|
35
|
+
- Uses CommandRegistry context for page navigation items (see CommandRegistryProvider)
|
|
36
|
+
- `isAdmin` takes precedence over `user.role` for showing admin command groups
|
|
37
|
+
- Should be placed at the app root level, typically alongside TopBar
|
|
38
|
+
|
|
39
|
+
## Changes
|
|
40
|
+
### v0.3.0
|
|
41
|
+
- **Fixed** Added missing `'use client'` directive
|
|
42
|
+
|
|
43
|
+
### v0.1.0
|
|
44
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# BottomNavbar
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/bottom-navbar
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
currentPath?: string (optional)
|
|
9
|
+
user?: BottomNavbarUser | null (optional)
|
|
10
|
+
primaryItems?: BottomNavItem[] (max 4 recommended, optional)
|
|
11
|
+
moreItems?: BottomNavItem[] (overflow items in "More" menu, optional)
|
|
12
|
+
className?: string
|
|
13
|
+
|
|
14
|
+
BottomNavItem: { title: string, href: string, icon: ReactNode, exact?: boolean, badge?: number }
|
|
15
|
+
BottomNavbarUser: { name: string, role?: string }
|
|
16
|
+
|
|
17
|
+
## Defaults
|
|
18
|
+
None
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
```jsx
|
|
22
|
+
<BottomNavbar
|
|
23
|
+
currentPath="/dashboard"
|
|
24
|
+
primaryItems={[
|
|
25
|
+
{ title: 'Home', href: '/', icon: <IconHome /> },
|
|
26
|
+
{ title: 'Tasks', href: '/tasks', icon: <IconChecklist /> },
|
|
27
|
+
]}
|
|
28
|
+
/>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Gotchas
|
|
32
|
+
- Designed for mobile viewports — fixed to bottom of screen
|
|
33
|
+
- Max 4 `primaryItems` recommended; overflow goes in `moreItems` shown in a "More" sheet
|
|
34
|
+
- Use with `useIsMobile()` hook to conditionally render instead of AppSidebar
|
|
35
|
+
- Requires LinkProvider for framework-specific link components (e.g., Next.js Link)
|
|
36
|
+
|
|
37
|
+
## Changes
|
|
38
|
+
### v0.18.0
|
|
39
|
+
- **Fixed** Removed incorrect `role="button"` and `tabIndex` from overlay
|
|
40
|
+
|
|
41
|
+
### v0.16.0
|
|
42
|
+
- **Added** `badge?: number` on `BottomNavItem` — notification count badge (red dot, 99+ cap)
|
|
43
|
+
|
|
44
|
+
### v0.1.1
|
|
45
|
+
- **Changed** Decoupled from Next.js via LinkProvider
|
|
46
|
+
|
|
47
|
+
### v0.1.0
|
|
48
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# CommandRegistry
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/command-registry
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
Exports: CommandRegistryProvider, useCommandRegistry
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### CommandRegistryProvider
|
|
12
|
+
children: ReactNode
|
|
13
|
+
registry: CommandRegistry (REQUIRED)
|
|
14
|
+
|
|
15
|
+
CommandRegistry: { pages: CommandPageItem[], adminPages: CommandPageItem[] }
|
|
16
|
+
CommandPageItem: { id: string, label: string, icon: ReactNode, path: string, keywords?: string[] }
|
|
17
|
+
|
|
18
|
+
### useCommandRegistry hook
|
|
19
|
+
Returns: CommandRegistry | null
|
|
20
|
+
|
|
21
|
+
## Defaults
|
|
22
|
+
None
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
```jsx
|
|
26
|
+
<CommandRegistryProvider
|
|
27
|
+
registry={{
|
|
28
|
+
pages: [
|
|
29
|
+
{ id: 'dashboard', label: 'Dashboard', icon: <IconHome />, path: '/dashboard' },
|
|
30
|
+
{ id: 'projects', label: 'Projects', icon: <IconFolder />, path: '/projects' },
|
|
31
|
+
],
|
|
32
|
+
adminPages: [
|
|
33
|
+
{ id: 'users', label: 'Manage Users', icon: <IconUsers />, path: '/admin/users' },
|
|
34
|
+
],
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<App />
|
|
38
|
+
</CommandRegistryProvider>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Gotchas
|
|
42
|
+
- Provides the command registry context consumed by AppCommandPalette
|
|
43
|
+
- Place at app root, wrapping both AppCommandPalette and the rest of the app
|
|
44
|
+
- `useCommandRegistry()` returns `null` if no provider is found — handle this case
|
|
45
|
+
|
|
46
|
+
## Changes
|
|
47
|
+
### v0.1.0
|
|
48
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# LinkProvider
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/link-context
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
Exports: LinkProvider, useLink
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### LinkProvider
|
|
12
|
+
component: ForwardRefComponent (e.g. Next.js Link, Remix Link)
|
|
13
|
+
children: ReactNode
|
|
14
|
+
|
|
15
|
+
### useLink hook
|
|
16
|
+
Returns: LinkComponent
|
|
17
|
+
|
|
18
|
+
## Defaults
|
|
19
|
+
Without LinkProvider, shell components render plain `<a>` tags
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
```jsx
|
|
23
|
+
import Link from 'next/link'
|
|
24
|
+
|
|
25
|
+
<LinkProvider component={Link}>
|
|
26
|
+
<AppSidebar ... />
|
|
27
|
+
<BottomNavbar ... />
|
|
28
|
+
</LinkProvider>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Gotchas
|
|
32
|
+
- Without LinkProvider, shell components render plain `<a>` tags (full page reloads)
|
|
33
|
+
- Place at app root, wrapping all shell components that render navigation links
|
|
34
|
+
- The `component` prop must be a forwardRef component (Next.js Link, Remix Link, etc.)
|
|
35
|
+
|
|
36
|
+
## Changes
|
|
37
|
+
### v0.1.1
|
|
38
|
+
- **Added** Shell components decoupled from Next.js — replaced hard `next/link` import with polymorphic `LinkProvider`/`useLink` context
|
|
39
|
+
|
|
40
|
+
### v0.1.0
|
|
41
|
+
- **Added** Initial release (with hardcoded Next.js Link dependency)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# NotificationCenter
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/notification-center
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
notifications?: Notification[]
|
|
9
|
+
unreadCount: number (derived from notifications if not provided)
|
|
10
|
+
open: boolean (controlled mode)
|
|
11
|
+
onOpenChange: (open: boolean) => void
|
|
12
|
+
isLoading: boolean
|
|
13
|
+
hasMore: boolean
|
|
14
|
+
onFetchMore: () => void
|
|
15
|
+
onMarkRead: (id: string) => void
|
|
16
|
+
onMarkAllRead: () => void
|
|
17
|
+
onNavigate: (path: string) => void — called when a notification with a route is clicked
|
|
18
|
+
getNotificationRoute: (notification: Notification) => string | null — returns route for a notification; defaults to () => null
|
|
19
|
+
footerSlot: ReactNode — content rendered in a sticky footer below the scroll area
|
|
20
|
+
emptyState: ReactNode — replaces default empty state UI
|
|
21
|
+
headerActions: ReactNode — extra action buttons after "Mark all read"
|
|
22
|
+
popoverClassName: string — override default popover dimensions
|
|
23
|
+
onDismiss: (id: string) => void — when provided, each notification shows a dismiss button
|
|
24
|
+
|
|
25
|
+
Notification: { id: string, title: string, body?: string | null, tier: 'INFO' | 'IMPORTANT' | 'CRITICAL', isRead: boolean, createdAt: string, entityType?: string | null, entityId?: string | null, projectId?: string | null, project?: { title: string } | null, actions?: NotificationAction[] }
|
|
26
|
+
NotificationAction: { label: string, variant?: 'primary' | 'default' | 'danger', onClick: (id: string) => void }
|
|
27
|
+
|
|
28
|
+
## Defaults
|
|
29
|
+
getNotificationRoute defaults to () => null (no hardcoded routes)
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
```jsx
|
|
33
|
+
<NotificationCenter
|
|
34
|
+
notifications={notifications}
|
|
35
|
+
onMarkRead={markAsRead}
|
|
36
|
+
onMarkAllRead={markAllAsRead}
|
|
37
|
+
onNavigate={(path) => router.push(path)}
|
|
38
|
+
getNotificationRoute={(n) => n.entityType === 'task' ? `/tasks/${n.entityId}` : null}
|
|
39
|
+
onDismiss={(id) => dismissNotification(id)}
|
|
40
|
+
footerSlot={<Link href="/notifications">View all notifications</Link>}
|
|
41
|
+
emptyState={<p>You're all caught up!</p>}
|
|
42
|
+
headerActions={<Button variant="ghost" size="sm">Settings</Button>}
|
|
43
|
+
popoverClassName="w-[480px]"
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Gotchas
|
|
48
|
+
- Typically rendered inside TopBar's `notificationSlot` prop
|
|
49
|
+
- `getNotificationRoute` must be provided for clickable notifications — no hardcoded routes
|
|
50
|
+
- Tier dot doubles as read/unread marker (opacity-based)
|
|
51
|
+
- `onDismiss` enables per-notification dismiss buttons when provided
|
|
52
|
+
|
|
53
|
+
## Changes
|
|
54
|
+
### v0.13.0
|
|
55
|
+
- **Added** `NotificationAction` type and `actions` prop on `Notification` — inline action buttons per notification row
|
|
56
|
+
- **Fixed** Tier dot now doubles as read/unread marker (opacity-based) — removed separate unread indicator dot
|
|
57
|
+
|
|
58
|
+
### v0.1.1
|
|
59
|
+
- **Changed** Decoupled from Next.js via LinkProvider
|
|
60
|
+
- **Fixed** Added `aria-label` to bell button
|
|
61
|
+
|
|
62
|
+
### v0.1.0
|
|
63
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# NotificationPreferences
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/notification-preferences
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
preferences?: NotificationPreference[]
|
|
9
|
+
projects?: NotificationProject[]
|
|
10
|
+
isLoading?: boolean
|
|
11
|
+
onSave?: (preference: { projectId, channel, minTier, muted }) => void | Promise<void>
|
|
12
|
+
onToggleMute?: (preference: NotificationPreference) => void | Promise<void>
|
|
13
|
+
onUpdateTier?: (preference: NotificationPreference, newTier: string) => void | Promise<void>
|
|
14
|
+
onDelete?: (preferenceId: string) => void | Promise<void>
|
|
15
|
+
className?: string
|
|
16
|
+
|
|
17
|
+
NotificationPreference: { id: string, userId?: string, projectId: string | null, channel: string, minTier: string, muted: boolean }
|
|
18
|
+
NotificationProject: { id: string, title: string }
|
|
19
|
+
|
|
20
|
+
## Defaults
|
|
21
|
+
None
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
```jsx
|
|
25
|
+
<NotificationPreferences
|
|
26
|
+
preferences={prefs}
|
|
27
|
+
projects={projectList}
|
|
28
|
+
onSave={handleSavePref}
|
|
29
|
+
onToggleMute={handleToggleMute}
|
|
30
|
+
onUpdateTier={handleUpdateTier}
|
|
31
|
+
onDelete={handleDeletePref}
|
|
32
|
+
/>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Gotchas
|
|
36
|
+
- Manages per-project notification preferences (channel, tier, mute)
|
|
37
|
+
- All callback props support async (Promise<void>) for server-side operations
|
|
38
|
+
- Typically rendered on a settings/preferences page
|
|
39
|
+
|
|
40
|
+
## Changes
|
|
41
|
+
### v0.1.0
|
|
42
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# AppSidebar
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/sidebar
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
currentPath?: string (highlights active nav item)
|
|
9
|
+
user?: SidebarUser | null — { name, email?, image?, designation?, role? }
|
|
10
|
+
navGroups?: NavGroup[] — { label: string, items: NavItem[], action?: ReactNode }
|
|
11
|
+
logo?: ReactNode
|
|
12
|
+
footerLinks?: Array<{ label: string, href: string }> (DEPRECATED — use footer.links)
|
|
13
|
+
footer?: SidebarFooterConfig — structured footer (takes precedence over footerLinks)
|
|
14
|
+
headerSlot?: ReactNode — content between user info and navigation
|
|
15
|
+
preFooterSlot?: ReactNode — content between navigation and footer
|
|
16
|
+
preFooterClassName?: string — className on preFooterSlot wrapper div
|
|
17
|
+
renderItem?: (item: NavItem, defaultRender: () => ReactNode) => ReactNode | null — custom item rendering
|
|
18
|
+
className?: string
|
|
19
|
+
|
|
20
|
+
NavItem: { title: string, href: string, icon: ReactNode, exact?: boolean, badge?: string | number, children?: NavSubItem[], defaultOpen?: boolean }
|
|
21
|
+
NavSubItem: { title: string, href: string, icon?: ReactNode, exact?: boolean }
|
|
22
|
+
NavGroup: { label: string, items: NavItem[], action?: ReactNode }
|
|
23
|
+
SidebarUser: { name: string, email?: string, image?: string | null, designation?: string, role?: string }
|
|
24
|
+
SidebarFooterConfig: { links: Array<{ label: string, href: string }>, version: string | { label: string, href: string }, slot: ReactNode, promo: SidebarPromo }
|
|
25
|
+
SidebarPromo: { text: string, icon?: ReactNode, action?: { label: string, href?: string, onClick?: () => void }, onDismiss?: () => void }
|
|
26
|
+
|
|
27
|
+
## Defaults
|
|
28
|
+
None
|
|
29
|
+
|
|
30
|
+
## Example
|
|
31
|
+
```jsx
|
|
32
|
+
<AppSidebar
|
|
33
|
+
currentPath="/dashboard"
|
|
34
|
+
user={{ name: 'Jane', email: 'jane@example.com' }}
|
|
35
|
+
navGroups={[{
|
|
36
|
+
label: 'Main',
|
|
37
|
+
items: [
|
|
38
|
+
{ title: 'Dashboard', href: '/dashboard', icon: <IconHome /> },
|
|
39
|
+
{ title: 'Projects', href: '/projects', icon: <IconFolder />, children: [
|
|
40
|
+
{ title: 'Karm V2', href: '/projects/abc/board' },
|
|
41
|
+
]},
|
|
42
|
+
],
|
|
43
|
+
}]}
|
|
44
|
+
footer={{
|
|
45
|
+
links: [{ label: 'Terms', href: '/terms' }],
|
|
46
|
+
version: { label: 'v2.4.1', href: '/changelog' },
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Gotchas
|
|
52
|
+
- Must be wrapped in SidebarProvider (from ui/sidebar)
|
|
53
|
+
- Requires LinkProvider for framework-specific link components
|
|
54
|
+
- `footerLinks` is deprecated — use `footer.links` instead
|
|
55
|
+
- `renderItem` returning `null` falls back to default rendering
|
|
56
|
+
- Collapsible nav items auto-open when a child is active (matching `currentPath`)
|
|
57
|
+
- Badge numbers > 99 display as "99+"
|
|
58
|
+
|
|
59
|
+
## Changes
|
|
60
|
+
### v0.18.0
|
|
61
|
+
- **Fixed** `bg-interactive-subtle` changed to `bg-accent-2` (OKLCH migration)
|
|
62
|
+
|
|
63
|
+
### v0.16.0
|
|
64
|
+
- **Added** `preFooterClassName?: string` — custom className on preFooterSlot wrapper
|
|
65
|
+
|
|
66
|
+
### v0.14.0
|
|
67
|
+
- **Changed** `footer.version` now accepts `string | { label: string; href: string }` — version can link to changelog
|
|
68
|
+
|
|
69
|
+
### v0.13.0
|
|
70
|
+
- **Added** `SidebarPromo` type and `footer.promo` prop — dismissable promo/upsell banner
|
|
71
|
+
- **Changed** Footer links and version now render on a single line separated by dividers
|
|
72
|
+
- **Fixed** Collapsible chevron wrapped in fixed-height container to prevent drift
|
|
73
|
+
- **Fixed** Collapsible chevron no longer drifts into child elements when sub-list expands
|
|
74
|
+
|
|
75
|
+
### v0.10.0
|
|
76
|
+
- **Added** Collapsible nav items with `children` array and `NavSubItem` type
|
|
77
|
+
- **Added** Nav item `badge` prop for counts/labels, caps at 99+
|
|
78
|
+
- **Added** Nav group `action` prop for buttons next to group labels
|
|
79
|
+
- **Added** Structured `footer` prop with `SidebarFooterConfig` — links, version, slot
|
|
80
|
+
- **Added** `headerSlot` and `preFooterSlot` content slots
|
|
81
|
+
- **Added** `renderItem` escape hatch for custom item rendering
|
|
82
|
+
- **Deprecated** `footerLinks` prop — use `footer.links` instead
|
|
83
|
+
|
|
84
|
+
### v0.1.1
|
|
85
|
+
- **Changed** Decoupled from Next.js via LinkProvider
|
|
86
|
+
|
|
87
|
+
### v0.1.0
|
|
88
|
+
- **Added** Initial release
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# TopBar
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra/shell/top-bar
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: shell
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
pageTitle?: string (default: "")
|
|
9
|
+
user?: TopBarUser | null — { name, email?, image? }
|
|
10
|
+
onNavigate?: (path: string) => void
|
|
11
|
+
onLogout?: () => void
|
|
12
|
+
onSearchClick?: () => void
|
|
13
|
+
onAiChatClick?: () => void
|
|
14
|
+
mobileLogo?: ReactNode
|
|
15
|
+
notificationSlot?: ReactNode (render NotificationCenter here)
|
|
16
|
+
userMenuItems?: UserMenuItem[] — custom items between Profile and Dark/Light Mode toggle
|
|
17
|
+
className?: string
|
|
18
|
+
|
|
19
|
+
TopBarUser: { name: string, email?: string, image?: string | null }
|
|
20
|
+
UserMenuItem: { label: string, icon?: ReactNode, href?: string, onClick?: () => void, separator?: boolean, color?: string, badge?: string | boolean, disabled?: boolean }
|
|
21
|
+
|
|
22
|
+
UserMenuItem fields:
|
|
23
|
+
- href — navigates via onNavigate callback
|
|
24
|
+
- onClick — custom action (takes precedence over href)
|
|
25
|
+
- separator — renders a DropdownMenuSeparator before this item
|
|
26
|
+
- color — semantic text color (e.g. "error" for text-error)
|
|
27
|
+
- badge — string for count badge, true for dot indicator
|
|
28
|
+
- disabled — greys out the item
|
|
29
|
+
|
|
30
|
+
## Defaults
|
|
31
|
+
None
|
|
32
|
+
|
|
33
|
+
## Example
|
|
34
|
+
```jsx
|
|
35
|
+
<TopBar
|
|
36
|
+
pageTitle="Dashboard"
|
|
37
|
+
user={{ name: 'John', email: 'john@example.com' }}
|
|
38
|
+
onNavigate={(p) => router.push(p)}
|
|
39
|
+
onLogout={handleLogout}
|
|
40
|
+
notificationSlot={<NotificationCenter notifications={notifications} />}
|
|
41
|
+
userMenuItems={[
|
|
42
|
+
{ label: 'Changelog', icon: <IconNews />, href: '/changelog', badge: '3' },
|
|
43
|
+
{ label: 'Shortcuts', icon: <IconKeyboard />, onClick: () => openModal() },
|
|
44
|
+
]}
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Gotchas
|
|
49
|
+
- `notificationSlot` is where NotificationCenter should be rendered
|
|
50
|
+
- `userMenuItems` are inserted between the Profile link and the Dark/Light Mode toggle in the user dropdown
|
|
51
|
+
- Requires LinkProvider for framework-specific navigation
|
|
52
|
+
|
|
53
|
+
## Changes
|
|
54
|
+
### v0.7.0
|
|
55
|
+
- **Added** `userMenuItems` prop for custom dropdown items
|
|
56
|
+
|
|
57
|
+
### v0.1.1
|
|
58
|
+
- **Changed** Decoupled from Next.js via LinkProvider
|
|
59
|
+
- **Fixed** Added `aria-label` to search/AI buttons
|
|
60
|
+
- **Fixed** Added `type="button"` to search/AI/avatar buttons to prevent form submission
|
|
61
|
+
|
|
62
|
+
### v0.1.0
|
|
63
|
+
- **Added** Initial release
|