@devalok/shilp-sutra-karm 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/_chunks/task-detail-panel.js +1339 -1144
  2. package/dist/tasks/activity-tab.d.ts +2 -11
  3. package/dist/tasks/activity-tab.d.ts.map +1 -1
  4. package/dist/tasks/conversation-tab.d.ts +2 -21
  5. package/dist/tasks/conversation-tab.d.ts.map +1 -1
  6. package/dist/tasks/files-tab.d.ts +2 -18
  7. package/dist/tasks/files-tab.d.ts.map +1 -1
  8. package/dist/tasks/index.d.ts +12 -6
  9. package/dist/tasks/index.d.ts.map +1 -1
  10. package/dist/tasks/index.js +765 -8
  11. package/dist/tasks/pickers/index.d.ts +16 -0
  12. package/dist/tasks/pickers/index.d.ts.map +1 -0
  13. package/dist/tasks/pickers/task-assignee-picker.d.ts +14 -0
  14. package/dist/tasks/pickers/task-assignee-picker.d.ts.map +1 -0
  15. package/dist/tasks/pickers/task-column-picker.d.ts +13 -0
  16. package/dist/tasks/pickers/task-column-picker.d.ts.map +1 -0
  17. package/dist/tasks/pickers/task-date-picker.d.ts +12 -0
  18. package/dist/tasks/pickers/task-date-picker.d.ts.map +1 -0
  19. package/dist/tasks/pickers/task-label-editor.d.ts +13 -0
  20. package/dist/tasks/pickers/task-label-editor.d.ts.map +1 -0
  21. package/dist/tasks/pickers/task-member-picker.d.ts +14 -0
  22. package/dist/tasks/pickers/task-member-picker.d.ts.map +1 -0
  23. package/dist/tasks/pickers/task-priority-picker.d.ts +12 -0
  24. package/dist/tasks/pickers/task-priority-picker.d.ts.map +1 -0
  25. package/dist/tasks/pickers/task-visibility-picker.d.ts +13 -0
  26. package/dist/tasks/pickers/task-visibility-picker.d.ts.map +1 -0
  27. package/dist/tasks/review-tab.d.ts +4 -20
  28. package/dist/tasks/review-tab.d.ts.map +1 -1
  29. package/dist/tasks/subtasks-tab.d.ts +2 -18
  30. package/dist/tasks/subtasks-tab.d.ts.map +1 -1
  31. package/dist/tasks/tabs/activity-entry.d.ts +9 -0
  32. package/dist/tasks/tabs/activity-entry.d.ts.map +1 -0
  33. package/dist/tasks/tabs/activity-timeline.d.ts +8 -0
  34. package/dist/tasks/tabs/activity-timeline.d.ts.map +1 -0
  35. package/dist/tasks/tabs/file-drop-zone.d.ts +10 -0
  36. package/dist/tasks/tabs/file-drop-zone.d.ts.map +1 -0
  37. package/dist/tasks/tabs/file-item.d.ts +11 -0
  38. package/dist/tasks/tabs/file-item.d.ts.map +1 -0
  39. package/dist/tasks/tabs/file-list.d.ts +8 -0
  40. package/dist/tasks/tabs/file-list.d.ts.map +1 -0
  41. package/dist/tasks/tabs/index.d.ts +34 -0
  42. package/dist/tasks/tabs/index.d.ts.map +1 -0
  43. package/dist/tasks/tabs/message-bubble.d.ts +14 -0
  44. package/dist/tasks/tabs/message-bubble.d.ts.map +1 -0
  45. package/dist/tasks/tabs/message-input.d.ts +16 -0
  46. package/dist/tasks/tabs/message-input.d.ts.map +1 -0
  47. package/dist/tasks/tabs/message-list.d.ts +9 -0
  48. package/dist/tasks/tabs/message-list.d.ts.map +1 -0
  49. package/dist/tasks/tabs/review-card.d.ts +10 -0
  50. package/dist/tasks/tabs/review-card.d.ts.map +1 -0
  51. package/dist/tasks/tabs/review-request-button.d.ts +10 -0
  52. package/dist/tasks/tabs/review-request-button.d.ts.map +1 -0
  53. package/dist/tasks/tabs/review-response-form.d.ts +11 -0
  54. package/dist/tasks/tabs/review-response-form.d.ts.map +1 -0
  55. package/dist/tasks/tabs/subtask-add-form.d.ts +9 -0
  56. package/dist/tasks/tabs/subtask-add-form.d.ts.map +1 -0
  57. package/dist/tasks/tabs/subtask-item.d.ts +12 -0
  58. package/dist/tasks/tabs/subtask-item.d.ts.map +1 -0
  59. package/dist/tasks/tabs/subtask-list.d.ts +8 -0
  60. package/dist/tasks/tabs/subtask-list.d.ts.map +1 -0
  61. package/dist/tasks/tabs/subtask-progress.d.ts +9 -0
  62. package/dist/tasks/tabs/subtask-progress.d.ts.map +1 -0
  63. package/dist/tasks/tabs/visibility-warning.d.ts +7 -0
  64. package/dist/tasks/tabs/visibility-warning.d.ts.map +1 -0
  65. package/dist/tasks/task-panel.d.ts +104 -0
  66. package/dist/tasks/task-panel.d.ts.map +1 -0
  67. package/dist/tasks/task-properties.d.ts +2 -12
  68. package/dist/tasks/task-properties.d.ts.map +1 -1
  69. package/dist/tasks/task-types.d.ts +104 -0
  70. package/dist/tasks/task-types.d.ts.map +1 -0
  71. package/docs/components/admin/admin-dashboard.md +215 -0
  72. package/docs/components/admin/admin-types.md +167 -0
  73. package/docs/components/admin/admin-utils.md +165 -0
  74. package/docs/components/admin/break-admin.md +167 -0
  75. package/docs/components/board/board-column.md +35 -0
  76. package/docs/components/board/board-provider.md +89 -0
  77. package/docs/components/board/board-toolbar.md +36 -0
  78. package/docs/components/board/board-types.md +62 -0
  79. package/docs/components/board/bulk-action-bar.md +38 -0
  80. package/docs/components/board/column-empty.md +33 -0
  81. package/docs/components/board/column-header.md +36 -0
  82. package/docs/components/board/kanban-board.md +53 -0
  83. package/docs/components/board/task-card.md +62 -0
  84. package/docs/components/board/task-context-menu.md +36 -0
  85. package/docs/components/chat/chat-input.md +37 -0
  86. package/docs/components/chat/chat-panel.md +58 -0
  87. package/docs/components/chat/conversation-list.md +47 -0
  88. package/docs/components/chat/message-list.md +44 -0
  89. package/docs/components/chat/streaming-text.md +29 -0
  90. package/docs/components/client/accent-provider.md +29 -0
  91. package/docs/components/client/client-portal-header.md +40 -0
  92. package/docs/components/client/project-card.md +39 -0
  93. package/docs/components/dashboard/attendance-cta.md +47 -0
  94. package/docs/components/dashboard/daily-brief.md +45 -0
  95. package/docs/components/dashboard/scratchpad-widget.md +52 -0
  96. package/docs/components/dashboard/sidebar-scratchpad.md +39 -0
  97. package/docs/components/other/karm-command-registry.md +61 -0
  98. package/docs/components/other/page-skeletons.md +52 -0
  99. package/docs/components/tasks/activity-tab.md +45 -0
  100. package/docs/components/tasks/conversation-tab.md +56 -0
  101. package/docs/components/tasks/files-tab.md +55 -0
  102. package/docs/components/tasks/review-tab.md +53 -0
  103. package/docs/components/tasks/subtasks-tab.md +61 -0
  104. package/docs/components/tasks/task-assignee-picker.md +36 -0
  105. package/docs/components/tasks/task-column-picker.md +37 -0
  106. package/docs/components/tasks/task-date-picker.md +49 -0
  107. package/docs/components/tasks/task-detail-panel.md +275 -0
  108. package/docs/components/tasks/task-label-editor.md +42 -0
  109. package/docs/components/tasks/task-member-picker.md +35 -0
  110. package/docs/components/tasks/task-panel.md +89 -0
  111. package/docs/components/tasks/task-priority-picker.md +37 -0
  112. package/docs/components/tasks/task-properties.md +84 -0
  113. package/docs/components/tasks/task-visibility-picker.md +38 -0
  114. package/llms.txt +40 -13
  115. package/package.json +82 -80
@@ -0,0 +1,61 @@
1
+ # karmCommandRegistry
2
+
3
+ - Import: @devalok/shilp-sutra-karm (top-level export)
4
+ - Server-safe: No
5
+ - Category: shell
6
+
7
+ Pre-configured command registry for the Karm app's AppCommandPalette. Contains all page routes and admin routes.
8
+
9
+ Exports: karmCommandRegistry
10
+
11
+ ## Type
12
+ ```ts
13
+ const karmCommandRegistry: CommandRegistry
14
+ ```
15
+
16
+ Where `CommandRegistry` is `{ pages: CommandPageItem[], adminPages: CommandPageItem[] }` from `@devalok/shilp-sutra/shell/command-registry`.
17
+
18
+ ## Pages
19
+ | id | label | path | keywords |
20
+ |----|-------|------|----------|
21
+ | nav-dashboard | Dashboard | / | home |
22
+ | nav-attendance | Attendance | /attendance | clock, time |
23
+ | nav-breaks | Breaks | /breaks | leave, vacation |
24
+ | nav-projects | Projects | /projects | board, kanban |
25
+ | nav-my-tasks | My Tasks | /my-tasks | todo |
26
+ | nav-devsabha | Devsabha | /devsabha | standup, meeting |
27
+ | nav-adjustments | Adjustments | /adjustments | corrections |
28
+ | nav-profile | Profile | /profile | account, settings |
29
+
30
+ ## Admin Pages
31
+ | id | label | path | keywords |
32
+ |----|-------|------|----------|
33
+ | nav-admin-dashboard | Admin Dashboard | /admin | admin, overview |
34
+ | nav-admin-breaks | Manage Breaks | /admin/breaks | admin, leave |
35
+ | nav-admin-attendance | Manage Attendance | /admin/attendance | admin, time |
36
+ | nav-admin-lokwasi | Lokwasi | /admin/lokwasi | admin, onboarding |
37
+ | nav-admin-onboarding | Onboarding | /admin/onboarding | admin, new hire |
38
+ | nav-admin-config | System Config | /admin/system-config | admin, settings, configuration |
39
+
40
+ ## Example
41
+ ```jsx
42
+ import { CommandRegistryProvider } from '@devalok/shilp-sutra/shell/command-registry'
43
+ import { karmCommandRegistry } from '@devalok/shilp-sutra-karm'
44
+
45
+ <CommandRegistryProvider registry={karmCommandRegistry}>
46
+ <AppCommandPalette
47
+ user={user}
48
+ onNavigate={(path) => router.push(path)}
49
+ />
50
+ </CommandRegistryProvider>
51
+ ```
52
+
53
+ ## Gotchas
54
+ - Each entry includes a Tabler icon (e.g. `IconLayoutDashboard`, `IconUmbrella`) — these are bundled, not tree-shaken
55
+ - The registry is a plain object, not a React component — pass it to `CommandRegistryProvider`
56
+ - Admin pages are only shown in the command palette when the user has admin role (handled by AppCommandPalette)
57
+ - To add new routes, extend the registry object in your app rather than modifying this export
58
+
59
+ ## Changes
60
+ ### v0.9.0
61
+ - **Added** Initial release with 8 pages and 6 admin pages
@@ -0,0 +1,52 @@
1
+ # Page Skeletons (Karm)
2
+
3
+ - Import: @devalok/shilp-sutra-karm
4
+ - Server-safe: No
5
+ - Category: other
6
+
7
+ Domain-specific loading skeleton components for Karm pages.
8
+
9
+ Exports: DevsabhaSkeleton, BandwidthSkeleton
10
+
11
+ ## Props
12
+
13
+ ### DevsabhaSkeleton
14
+ ...HTMLDivElement attributes (className, etc.)
15
+
16
+ Renders a 5-section skeleton grid mimicking the Devsabha (standup) page layout:
17
+ 1. Main large card (lg:col-span-2) with 4 rows
18
+ 2. Side card with 3 avatar rows
19
+ 3. Full-width card (lg:col-span-3) with 3 sub-cards
20
+ 4. Stats row (lg:col-span-2) with 4 stat blocks
21
+ 5. Timeline card with 3 entries
22
+
23
+ ### BandwidthSkeleton
24
+ ...HTMLDivElement attributes (className, etc.)
25
+
26
+ Renders a skeleton mimicking the Bandwidth page layout:
27
+ 1. 3 summary cards (sm:grid-cols-3) with progress bars
28
+ 2. Table with 5-column header and 6 rows with avatar + name
29
+
30
+ ## Defaults
31
+ None
32
+
33
+ ## Example
34
+ ```jsx
35
+ import { DevsabhaSkeleton, BandwidthSkeleton } from '@devalok/shilp-sutra-karm'
36
+
37
+ // Use while data loads
38
+ if (isLoading) return <DevsabhaSkeleton />
39
+
40
+ // Bandwidth page loading
41
+ if (isLoading) return <BandwidthSkeleton className="p-6" />
42
+ ```
43
+
44
+ ## Gotchas
45
+ - These are top-level exports from the karm package, not from the admin sub-path
46
+ - Both use the core `Skeleton` component internally
47
+ - Layout uses `gap-ds-06` spacing and `rounded-ds-xl` border radius
48
+ - Pass `className` to customize outer container styles
49
+
50
+ ## Changes
51
+ ### v0.9.0
52
+ - **Added** Initial release
@@ -0,0 +1,45 @@
1
+ # ActivityTab
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ ## Props
8
+ activities: AuditLogEntry[] (REQUIRED)
9
+ ...HTMLAttributes<HTMLDivElement>
10
+
11
+ ## AuditLogEntry Shape
12
+ id: string
13
+ timestamp: string
14
+ actorType: 'USER' | 'CLIENT' | 'SYSTEM' | 'AGENT'
15
+ actorId: string | null
16
+ action: string
17
+ entityType: string
18
+ entityId: string
19
+ projectId: string | null
20
+ metadata: Record<string, unknown> | null
21
+
22
+ ## Supported Actions
23
+ task.created, task.updated, task.moved, task.assigned, task.unassigned,
24
+ task.commented, task.file_uploaded, task.review_requested, task.review_completed,
25
+ task.visibility_changed, task.priority_changed, task.labels_changed, task.due_date_changed
26
+
27
+ ## Example
28
+ ```jsx
29
+ <ActivityTab activities={auditLogEntries} />
30
+ ```
31
+
32
+ ## Gotchas
33
+ - Renders a vertical timeline with colored dots and icons per action type.
34
+ - Unknown actions fall back to a generic icon and use entry.action as the description.
35
+ - Actor name is derived from metadata.actorName, falling back to "System", "AI Agent", or "Someone".
36
+ - Empty state uses EmptyState component: "No activity yet".
37
+ - Forwards ref to outer div.
38
+
39
+ ## Changes
40
+ ### v0.19.0
41
+ - **Added** Decomposed into composable pieces: `ActivityTimeline`, `ActivityEntry` — importable from `@devalok/shilp-sutra-karm/tasks`
42
+ - ActivityTab remains as a pre-assembled default; use the pieces for custom layouts
43
+
44
+ ### v0.18.0
45
+ - **Added** Initial release
@@ -0,0 +1,56 @@
1
+ # ConversationTab
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ ## Props
8
+ comments: Comment[] (REQUIRED)
9
+ taskVisibility: 'INTERNAL' | 'EVERYONE' (REQUIRED)
10
+ onPostComment: (content: string, authorType: 'INTERNAL' | 'CLIENT') => void (REQUIRED)
11
+ clientMode: boolean (default: false)
12
+ richText: boolean (default: true) — enable built-in RichTextEditor/Viewer
13
+ renderEditor: (props: { content: string; onChange: (content: string) => void; placeholder: string }) => ReactNode
14
+ renderViewer: (props: { content: string; className?: string }) => ReactNode
15
+ ...HTMLAttributes<HTMLDivElement>
16
+
17
+ ## Comment Shape
18
+ id: string
19
+ taskId: string
20
+ authorType: 'INTERNAL' | 'CLIENT'
21
+ authorId: string
22
+ content: string
23
+ createdAt: string
24
+ updatedAt: string
25
+ internalAuthor: { id: string; name: string; email?: string; image?: string | null } | null (optional)
26
+ clientAuthor: { id: string; name: string; email: string } | null (optional)
27
+
28
+ ## Defaults
29
+ clientMode=false, richText=true
30
+
31
+ ## Example
32
+ ```jsx
33
+ <ConversationTab
34
+ comments={task.comments}
35
+ taskVisibility={task.visibility}
36
+ onPostComment={(content, type) => postComment(content, type)}
37
+ />
38
+ ```
39
+
40
+ ## Gotchas
41
+ - In clientMode, comments are posted with authorType='CLIENT'. In staff mode, authorType='INTERNAL'.
42
+ - When taskVisibility='EVERYONE' and not clientMode, a warning is shown: "Comments may be seen by external users."
43
+ - In clientMode, staff comments show a "Team" badge. In staff mode, client comments show a "Client" badge.
44
+ - Editor resolution priority: renderEditor prop > built-in RichTextEditor (when richText=true) > plain textarea fallback.
45
+ - Viewer resolution priority: renderViewer prop > built-in RichTextViewer (when richText=true) > plain text with HTML stripped.
46
+ - Auto-scrolls to bottom when new comments arrive.
47
+ - Empty state: "No comments yet".
48
+ - Forwards ref to outer div.
49
+
50
+ ## Changes
51
+ ### v0.19.0
52
+ - **Added** Decomposed into composable pieces: `MessageList`, `MessageBubble`, `MessageInput`, `VisibilityWarning` — importable from `@devalok/shilp-sutra-karm/tasks`
53
+ - ConversationTab remains as a pre-assembled default; use the pieces for custom layouts
54
+
55
+ ### v0.18.0
56
+ - **Added** Initial release
@@ -0,0 +1,55 @@
1
+ # FilesTab
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ ## Props
8
+ files: TaskFile[] (REQUIRED)
9
+ onUpload: (file: File, title?: string) => void (REQUIRED)
10
+ onDelete: (fileId: string) => void (REQUIRED)
11
+ isUploading: boolean (default: false)
12
+ readOnly: boolean (default: false) — hides upload/delete controls
13
+ ...HTMLAttributes<HTMLDivElement>
14
+
15
+ ## TaskFile Shape
16
+ id: string
17
+ taskId: string
18
+ title: string
19
+ fileUrl: string
20
+ downloadUrl: string (optional)
21
+ fileType: string | null
22
+ uploadedBy: { id: string; name: string; image: string | null }
23
+ createdAt: string
24
+ externalUrl: string (optional, e.g. Google Drive link)
25
+ externalLabel: string (optional, tooltip for external link, default: "Open externally")
26
+
27
+ ## Defaults
28
+ isUploading=false, readOnly=false
29
+
30
+ ## Example
31
+ ```jsx
32
+ <FilesTab
33
+ files={task.files}
34
+ onUpload={(file) => uploadFile(file)}
35
+ onDelete={(fileId) => deleteFile(fileId)}
36
+ isUploading={uploading}
37
+ />
38
+ ```
39
+
40
+ ## Gotchas
41
+ - Supports drag-and-drop upload zone and click-to-upload.
42
+ - File icons are auto-detected from fileType: images, documents, code, spreadsheets, archives.
43
+ - Delete triggers a confirmation Dialog before calling onDelete.
44
+ - In readOnly mode, upload zone and delete buttons are hidden; download/external links remain.
45
+ - externalUrl is validated to start with https?:// before rendering as a link.
46
+ - Empty state: "No files attached".
47
+ - Forwards ref to outer div.
48
+
49
+ ## Changes
50
+ ### v0.19.0
51
+ - **Added** Decomposed into composable pieces: `FileDropZone`, `FileList`, `FileItem` — importable from `@devalok/shilp-sutra-karm/tasks`
52
+ - FilesTab remains as a pre-assembled default; use the pieces for custom layouts
53
+
54
+ ### v0.18.0
55
+ - **Added** Initial release
@@ -0,0 +1,53 @@
1
+ # ReviewTab
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ ## Props
8
+ reviews: ReviewRequest[] (REQUIRED)
9
+ members: Member[] (REQUIRED)
10
+ onRequestReview: (reviewerId: string) => void (REQUIRED)
11
+ onUpdateStatus: (reviewId: string, status: ReviewRequest['status'], feedback?: string) => void (REQUIRED)
12
+ ...HTMLAttributes<HTMLDivElement>
13
+
14
+ ## ReviewRequest Shape
15
+ id: string
16
+ taskId: string
17
+ status: 'PENDING' | 'APPROVED' | 'CHANGES_REQUESTED' | 'REJECTED'
18
+ feedback: string | null
19
+ requestedBy: { id: string; name: string; image: string | null }
20
+ reviewer: { id: string; name: string; image: string | null }
21
+ createdAt: string
22
+ updatedAt: string
23
+
24
+ ## Member Shape
25
+ id: string
26
+ name: string
27
+ image?: string | null
28
+
29
+ ## Example
30
+ ```jsx
31
+ <ReviewTab
32
+ reviews={task.reviewRequests}
33
+ members={teamMembers}
34
+ onRequestReview={(reviewerId) => requestReview(reviewerId)}
35
+ onUpdateStatus={(id, status, feedback) => updateReview(id, status, feedback)}
36
+ />
37
+ ```
38
+
39
+ ## Gotchas
40
+ - Each review card shows reviewer avatar, name, requested-by name, and status badge.
41
+ - PENDING reviews have a "Respond" button that expands to show feedback textarea and three response buttons: Approve (success), Request Changes (warning), Reject (error).
42
+ - "Request Review" button at the bottom uses MemberPicker from core.
43
+ - Status badge colors are defined in task-constants.ts via REVIEW_STATUS_MAP.
44
+ - Empty state: "No reviews yet".
45
+ - Forwards ref to outer div.
46
+
47
+ ## Changes
48
+ ### v0.19.0
49
+ - **Added** Decomposed into composable pieces: `ReviewCard`, `ReviewResponseForm`, `ReviewRequestButton` — importable from `@devalok/shilp-sutra-karm/tasks`
50
+ - ReviewTab remains as a pre-assembled default; use the pieces for custom layouts
51
+
52
+ ### v0.18.0
53
+ - **Added** Initial release
@@ -0,0 +1,61 @@
1
+ # SubtasksTab
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ ## Props
8
+ subtasks: Subtask[] (REQUIRED)
9
+ terminalColumnId: string (optional — column ID that marks tasks as complete)
10
+ projectId: string (REQUIRED)
11
+ parentTaskId: string (REQUIRED)
12
+ defaultColumnId: string (REQUIRED)
13
+ onCreateSubtask: (title: string) => void (REQUIRED)
14
+ onToggleSubtask: (taskId: string, isComplete: boolean) => void (REQUIRED)
15
+ onClickSubtask: (taskId: string) => void
16
+ readOnly: boolean (default: false) — hides create/toggle controls
17
+ ...HTMLAttributes<HTMLDivElement>
18
+
19
+ ## Subtask Shape
20
+ id: string
21
+ title: string
22
+ priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT'
23
+ columnId: string
24
+ column: { id: string; name: string; isTerminal?: boolean } (optional)
25
+ assignees: { user: { id: string; name: string; image?: string | null } }[]
26
+
27
+ ## Defaults
28
+ readOnly=false
29
+
30
+ ## Example
31
+ ```jsx
32
+ <SubtasksTab
33
+ subtasks={task.subtasks}
34
+ terminalColumnId="done-col"
35
+ projectId={task.projectId}
36
+ parentTaskId={task.id}
37
+ defaultColumnId="todo-col"
38
+ onCreateSubtask={(title) => createSubtask(title)}
39
+ onToggleSubtask={(id, complete) => toggleSubtask(id, complete)}
40
+ onClickSubtask={(id) => navigateToTask(id)}
41
+ />
42
+ ```
43
+
44
+ ## Gotchas
45
+ - A subtask is considered "complete" when column.isTerminal is true OR columnId matches terminalColumnId.
46
+ - Progress bar shows completed/total count at the top.
47
+ - Each subtask row shows: checkbox, priority dot, title (strikethrough when complete), first assignee avatar.
48
+ - Clicking a subtask row triggers onClickSubtask (if provided).
49
+ - In readOnly mode, checkboxes are non-interactive and the "Add subtask" button is hidden.
50
+ - "Add subtask" inline form with Enter to submit, Escape to cancel.
51
+ - projectId, parentTaskId, and defaultColumnId are defined in the interface and required by the type but are not currently used in the component's rendering logic. They are reserved for future navigation/creation features.
52
+ - Empty state: "No subtasks".
53
+ - Forwards ref to outer div.
54
+
55
+ ## Changes
56
+ ### v0.19.0
57
+ - **Added** Decomposed into composable pieces: `SubtaskProgress`, `SubtaskList`, `SubtaskItem`, `SubtaskAddForm` — importable from `@devalok/shilp-sutra-karm/tasks`
58
+ - SubtasksTab remains as a pre-assembled default; use the pieces for custom layouts
59
+
60
+ ### v0.18.0
61
+ - **Added** Initial release
@@ -0,0 +1,36 @@
1
+ # TaskAssigneePicker
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Multi-select assignee picker. Displays assigned members as removable chips with avatars and provides a "+" button to add more via the core MemberPicker.
8
+
9
+ ## Props
10
+ members: Member[] (REQUIRED — full list of available members)
11
+ value: Member[] (REQUIRED — currently assigned members)
12
+ onAssign: (userId: string) => void (REQUIRED — called when a member is added)
13
+ onUnassign: (userId: string) => void (REQUIRED — called when a member is removed)
14
+ readOnly?: boolean (default: false — hides remove buttons and add button)
15
+ className?: string
16
+
17
+ ## Example
18
+ ```jsx
19
+ <TaskAssigneePicker
20
+ members={projectMembers}
21
+ value={task.assignees}
22
+ onAssign={(userId) => assignUser(task.id, userId)}
23
+ onUnassign={(userId) => unassignUser(task.id, userId)}
24
+ />
25
+ ```
26
+
27
+ ## Gotchas
28
+ - Unlike TaskMemberPicker (single-select), this is multi-select with separate onAssign/onUnassign callbacks.
29
+ - Each assignee chip shows first name only (splits on space).
30
+ - The "+" button opens a MemberPicker with `multiple` mode. Toggling an already-assigned member calls onUnassign.
31
+ - In readOnly mode with no assignees, displays "None".
32
+ - Forwards ref to the outer `<div>`, not a button.
33
+
34
+ ## Changes
35
+ ### v0.19.0
36
+ - **Added** Initial release
@@ -0,0 +1,37 @@
1
+ # TaskColumnPicker
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Popover-based picker for selecting a board column (status). Displays the current column name and opens a dropdown with all available columns.
8
+
9
+ ## Props
10
+ columns: Column[] (REQUIRED — array of { id, name, isDefault?, isTerminal? })
11
+ value: string (REQUIRED — currently selected column id)
12
+ onChange: (columnId: string) => void (REQUIRED)
13
+ readOnly?: boolean (default: false — renders as plain text)
14
+ className?: string
15
+
16
+ ## Example
17
+ ```jsx
18
+ <TaskColumnPicker
19
+ columns={[
20
+ { id: 'todo', name: 'To Do' },
21
+ { id: 'in-progress', name: 'In Progress' },
22
+ { id: 'done', name: 'Done', isTerminal: true },
23
+ ]}
24
+ value={task.columnId}
25
+ onChange={(columnId) => updateTask({ columnId })}
26
+ />
27
+ ```
28
+
29
+ ## Gotchas
30
+ - If `value` does not match any column id, the trigger displays "Select column".
31
+ - The selected column is highlighted with `text-accent-11` and shows a check icon.
32
+ - Forwards ref to the trigger button.
33
+ - In readOnly mode, renders a plain `<span>` instead of a button.
34
+
35
+ ## Changes
36
+ ### v0.19.0
37
+ - **Added** Initial release
@@ -0,0 +1,49 @@
1
+ # TaskDatePicker
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Date picker with optional quick-select presets. Uses a native `<input type="date">` inside a popover, with preset buttons for common due dates.
8
+
9
+ ## Props
10
+ value: Date | string | null (REQUIRED — current date value)
11
+ onChange: (date: Date | null) => void (REQUIRED — null means cleared)
12
+ presets?: boolean (default: true — show quick-select preset buttons)
13
+ readOnly?: boolean (default: false — renders as plain text)
14
+ className?: string
15
+
16
+ ## Presets
17
+ When `presets` is true, the popover includes a "Quick select" section with:
18
+ - Today
19
+ - Tomorrow
20
+ - Next Monday
21
+ - +7 days
22
+ - +14 days
23
+ - Clear
24
+
25
+ ## Example
26
+ ```jsx
27
+ <TaskDatePicker
28
+ value={task.dueDate}
29
+ onChange={(date) => updateTask({ dueDate: date })}
30
+ />
31
+
32
+ {/* Without presets */}
33
+ <TaskDatePicker
34
+ value={task.startDate}
35
+ onChange={(date) => updateTask({ startDate: date })}
36
+ presets={false}
37
+ />
38
+ ```
39
+
40
+ ## Gotchas
41
+ - Accepts both `Date` objects and ISO date strings as `value`. Internally normalizes to `Date`.
42
+ - An inline clear button (X icon) appears next to the trigger when a date is set.
43
+ - The popover contains a native date input as the primary selector, with presets below it.
44
+ - Date display format: "Mar 14, 2026" (en-US, short month).
45
+ - Forwards ref to the trigger button.
46
+
47
+ ## Changes
48
+ ### v0.19.0
49
+ - **Added** Initial release