@devalok/shilp-sutra-karm 0.18.1 → 0.20.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 (185) hide show
  1. package/dist/_chunks/render-adjustment-type.js +50 -48
  2. package/dist/_chunks/sidebar-scratchpad.js +714 -326
  3. package/dist/_chunks/task-detail-panel.js +1638 -1175
  4. package/dist/_chunks/vendor.js +1154 -1123
  5. package/dist/dashboard/index.d.ts +20 -0
  6. package/dist/dashboard/index.d.ts.map +1 -1
  7. package/dist/dashboard/index.js +451 -5
  8. package/dist/dashboard/project-health-card.d.ts +22 -0
  9. package/dist/dashboard/project-health-card.d.ts.map +1 -0
  10. package/dist/dashboard/scratchpad/index.d.ts +13 -0
  11. package/dist/dashboard/scratchpad/index.d.ts.map +1 -0
  12. package/dist/dashboard/scratchpad/scratchpad-add-input.d.ts +11 -0
  13. package/dist/dashboard/scratchpad/scratchpad-add-input.d.ts.map +1 -0
  14. package/dist/dashboard/scratchpad/scratchpad-collapse.d.ts +15 -0
  15. package/dist/dashboard/scratchpad/scratchpad-collapse.d.ts.map +1 -0
  16. package/dist/dashboard/scratchpad/scratchpad-context.d.ts +44 -0
  17. package/dist/dashboard/scratchpad/scratchpad-context.d.ts.map +1 -0
  18. package/dist/dashboard/scratchpad/scratchpad-empty-state.d.ts +13 -0
  19. package/dist/dashboard/scratchpad/scratchpad-empty-state.d.ts.map +1 -0
  20. package/dist/dashboard/scratchpad/scratchpad-filter-toggle.d.ts +7 -0
  21. package/dist/dashboard/scratchpad/scratchpad-filter-toggle.d.ts.map +1 -0
  22. package/dist/dashboard/scratchpad/scratchpad-header.d.ts +9 -0
  23. package/dist/dashboard/scratchpad/scratchpad-header.d.ts.map +1 -0
  24. package/dist/dashboard/scratchpad/scratchpad-item.d.ts +13 -0
  25. package/dist/dashboard/scratchpad/scratchpad-item.d.ts.map +1 -0
  26. package/dist/dashboard/scratchpad/scratchpad-list.d.ts +9 -0
  27. package/dist/dashboard/scratchpad/scratchpad-list.d.ts.map +1 -0
  28. package/dist/dashboard/scratchpad/scratchpad-progress-ring.d.ts +11 -0
  29. package/dist/dashboard/scratchpad/scratchpad-progress-ring.d.ts.map +1 -0
  30. package/dist/dashboard/scratchpad/scratchpad-root.d.ts +8 -0
  31. package/dist/dashboard/scratchpad/scratchpad-root.d.ts.map +1 -0
  32. package/dist/dashboard/scratchpad/scratchpad.d.ts +29 -0
  33. package/dist/dashboard/scratchpad/scratchpad.d.ts.map +1 -0
  34. package/dist/dashboard/scratchpad-widget.d.ts +5 -5
  35. package/dist/dashboard/scratchpad-widget.d.ts.map +1 -1
  36. package/dist/dashboard/sidebar-scratchpad.d.ts +8 -1
  37. package/dist/dashboard/sidebar-scratchpad.d.ts.map +1 -1
  38. package/dist/dashboard/week-heatmap/index.d.ts +10 -0
  39. package/dist/dashboard/week-heatmap/index.d.ts.map +1 -0
  40. package/dist/dashboard/week-heatmap/week-heatmap-context.d.ts +31 -0
  41. package/dist/dashboard/week-heatmap/week-heatmap-context.d.ts.map +1 -0
  42. package/dist/dashboard/week-heatmap/week-heatmap-day-strip.d.ts +7 -0
  43. package/dist/dashboard/week-heatmap/week-heatmap-day-strip.d.ts.map +1 -0
  44. package/dist/dashboard/week-heatmap/week-heatmap-day.d.ts +15 -0
  45. package/dist/dashboard/week-heatmap/week-heatmap-day.d.ts.map +1 -0
  46. package/dist/dashboard/week-heatmap/week-heatmap-progress-bar.d.ts +7 -0
  47. package/dist/dashboard/week-heatmap/week-heatmap-progress-bar.d.ts.map +1 -0
  48. package/dist/dashboard/week-heatmap/week-heatmap-root.d.ts +8 -0
  49. package/dist/dashboard/week-heatmap/week-heatmap-root.d.ts.map +1 -0
  50. package/dist/dashboard/week-heatmap/week-heatmap-streak.d.ts +7 -0
  51. package/dist/dashboard/week-heatmap/week-heatmap-streak.d.ts.map +1 -0
  52. package/dist/dashboard/week-heatmap/week-heatmap-summary.d.ts +7 -0
  53. package/dist/dashboard/week-heatmap/week-heatmap-summary.d.ts.map +1 -0
  54. package/dist/dashboard/week-heatmap/week-heatmap.d.ts +33 -0
  55. package/dist/dashboard/week-heatmap/week-heatmap.d.ts.map +1 -0
  56. package/dist/index.d.ts +1 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +57 -56
  59. package/dist/tasks/activity-tab.d.ts +2 -11
  60. package/dist/tasks/activity-tab.d.ts.map +1 -1
  61. package/dist/tasks/conversation-tab.d.ts +2 -21
  62. package/dist/tasks/conversation-tab.d.ts.map +1 -1
  63. package/dist/tasks/files-tab.d.ts +2 -18
  64. package/dist/tasks/files-tab.d.ts.map +1 -1
  65. package/dist/tasks/index.d.ts +13 -6
  66. package/dist/tasks/index.d.ts.map +1 -1
  67. package/dist/tasks/index.js +766 -8
  68. package/dist/tasks/pickers/index.d.ts +16 -0
  69. package/dist/tasks/pickers/index.d.ts.map +1 -0
  70. package/dist/tasks/pickers/task-assignee-picker.d.ts +14 -0
  71. package/dist/tasks/pickers/task-assignee-picker.d.ts.map +1 -0
  72. package/dist/tasks/pickers/task-column-picker.d.ts +13 -0
  73. package/dist/tasks/pickers/task-column-picker.d.ts.map +1 -0
  74. package/dist/tasks/pickers/task-date-picker.d.ts +12 -0
  75. package/dist/tasks/pickers/task-date-picker.d.ts.map +1 -0
  76. package/dist/tasks/pickers/task-label-editor.d.ts +13 -0
  77. package/dist/tasks/pickers/task-label-editor.d.ts.map +1 -0
  78. package/dist/tasks/pickers/task-member-picker.d.ts +14 -0
  79. package/dist/tasks/pickers/task-member-picker.d.ts.map +1 -0
  80. package/dist/tasks/pickers/task-priority-picker.d.ts +12 -0
  81. package/dist/tasks/pickers/task-priority-picker.d.ts.map +1 -0
  82. package/dist/tasks/pickers/task-visibility-picker.d.ts +13 -0
  83. package/dist/tasks/pickers/task-visibility-picker.d.ts.map +1 -0
  84. package/dist/tasks/review-tab.d.ts +4 -20
  85. package/dist/tasks/review-tab.d.ts.map +1 -1
  86. package/dist/tasks/subtasks-tab.d.ts +2 -18
  87. package/dist/tasks/subtasks-tab.d.ts.map +1 -1
  88. package/dist/tasks/tabs/activity-entry.d.ts +9 -0
  89. package/dist/tasks/tabs/activity-entry.d.ts.map +1 -0
  90. package/dist/tasks/tabs/activity-timeline.d.ts +8 -0
  91. package/dist/tasks/tabs/activity-timeline.d.ts.map +1 -0
  92. package/dist/tasks/tabs/file-drop-zone.d.ts +10 -0
  93. package/dist/tasks/tabs/file-drop-zone.d.ts.map +1 -0
  94. package/dist/tasks/tabs/file-item.d.ts +11 -0
  95. package/dist/tasks/tabs/file-item.d.ts.map +1 -0
  96. package/dist/tasks/tabs/file-list.d.ts +8 -0
  97. package/dist/tasks/tabs/file-list.d.ts.map +1 -0
  98. package/dist/tasks/tabs/index.d.ts +34 -0
  99. package/dist/tasks/tabs/index.d.ts.map +1 -0
  100. package/dist/tasks/tabs/message-bubble.d.ts +14 -0
  101. package/dist/tasks/tabs/message-bubble.d.ts.map +1 -0
  102. package/dist/tasks/tabs/message-input.d.ts +16 -0
  103. package/dist/tasks/tabs/message-input.d.ts.map +1 -0
  104. package/dist/tasks/tabs/message-list.d.ts +9 -0
  105. package/dist/tasks/tabs/message-list.d.ts.map +1 -0
  106. package/dist/tasks/tabs/review-card.d.ts +10 -0
  107. package/dist/tasks/tabs/review-card.d.ts.map +1 -0
  108. package/dist/tasks/tabs/review-request-button.d.ts +10 -0
  109. package/dist/tasks/tabs/review-request-button.d.ts.map +1 -0
  110. package/dist/tasks/tabs/review-response-form.d.ts +11 -0
  111. package/dist/tasks/tabs/review-response-form.d.ts.map +1 -0
  112. package/dist/tasks/tabs/subtask-add-form.d.ts +9 -0
  113. package/dist/tasks/tabs/subtask-add-form.d.ts.map +1 -0
  114. package/dist/tasks/tabs/subtask-item.d.ts +12 -0
  115. package/dist/tasks/tabs/subtask-item.d.ts.map +1 -0
  116. package/dist/tasks/tabs/subtask-list.d.ts +8 -0
  117. package/dist/tasks/tabs/subtask-list.d.ts.map +1 -0
  118. package/dist/tasks/tabs/subtask-progress.d.ts +9 -0
  119. package/dist/tasks/tabs/subtask-progress.d.ts.map +1 -0
  120. package/dist/tasks/tabs/visibility-warning.d.ts +7 -0
  121. package/dist/tasks/tabs/visibility-warning.d.ts.map +1 -0
  122. package/dist/tasks/task-action-row/index.d.ts +3 -0
  123. package/dist/tasks/task-action-row/index.d.ts.map +1 -0
  124. package/dist/tasks/task-action-row/task-action-row-checkbox.d.ts +8 -0
  125. package/dist/tasks/task-action-row/task-action-row-checkbox.d.ts.map +1 -0
  126. package/dist/tasks/task-action-row/task-action-row-context.d.ts +21 -0
  127. package/dist/tasks/task-action-row/task-action-row-context.d.ts.map +1 -0
  128. package/dist/tasks/task-action-row/task-action-row-due-date.d.ts +5 -0
  129. package/dist/tasks/task-action-row/task-action-row-due-date.d.ts.map +1 -0
  130. package/dist/tasks/task-action-row/task-action-row-labels.d.ts +8 -0
  131. package/dist/tasks/task-action-row/task-action-row-labels.d.ts.map +1 -0
  132. package/dist/tasks/task-action-row/task-action-row-navigate.d.ts +9 -0
  133. package/dist/tasks/task-action-row/task-action-row-navigate.d.ts.map +1 -0
  134. package/dist/tasks/task-action-row/task-action-row-priority.d.ts +5 -0
  135. package/dist/tasks/task-action-row/task-action-row-priority.d.ts.map +1 -0
  136. package/dist/tasks/task-action-row/task-action-row-project-badge.d.ts +8 -0
  137. package/dist/tasks/task-action-row/task-action-row-project-badge.d.ts.map +1 -0
  138. package/dist/tasks/task-action-row/task-action-row-root.d.ts +14 -0
  139. package/dist/tasks/task-action-row/task-action-row-root.d.ts.map +1 -0
  140. package/dist/tasks/task-action-row/task-action-row-status-badge.d.ts +5 -0
  141. package/dist/tasks/task-action-row/task-action-row-status-badge.d.ts.map +1 -0
  142. package/dist/tasks/task-action-row/task-action-row-title.d.ts +9 -0
  143. package/dist/tasks/task-action-row/task-action-row-title.d.ts.map +1 -0
  144. package/dist/tasks/task-action-row/task-action-row.d.ts +48 -0
  145. package/dist/tasks/task-action-row/task-action-row.d.ts.map +1 -0
  146. package/dist/tasks/task-detail-panel.d.ts.map +1 -1
  147. package/dist/tasks/task-panel.d.ts +104 -0
  148. package/dist/tasks/task-panel.d.ts.map +1 -0
  149. package/dist/tasks/task-properties.d.ts +2 -12
  150. package/dist/tasks/task-properties.d.ts.map +1 -1
  151. package/dist/tasks/task-types.d.ts +104 -0
  152. package/dist/tasks/task-types.d.ts.map +1 -0
  153. package/docs/components/admin/admin-dashboard.md +6 -6
  154. package/docs/components/admin/admin-utils.md +2 -2
  155. package/docs/components/admin/break-admin.md +14 -14
  156. package/docs/components/board/board-provider.md +16 -0
  157. package/docs/components/board/column-empty.md +1 -1
  158. package/docs/components/board/task-card.md +4 -0
  159. package/docs/components/chat/streaming-text.md +1 -1
  160. package/docs/components/client/client-portal-header.md +2 -2
  161. package/docs/components/dashboard/attendance-cta.md +3 -3
  162. package/docs/components/dashboard/daily-brief.md +1 -1
  163. package/docs/components/dashboard/project-health-card.md +90 -0
  164. package/docs/components/dashboard/scratchpad-widget.md +17 -0
  165. package/docs/components/dashboard/scratchpad.md +151 -0
  166. package/docs/components/dashboard/sidebar-scratchpad.md +29 -5
  167. package/docs/components/dashboard/week-heatmap.md +95 -0
  168. package/docs/components/tasks/activity-tab.md +4 -0
  169. package/docs/components/tasks/conversation-tab.md +4 -0
  170. package/docs/components/tasks/files-tab.md +4 -0
  171. package/docs/components/tasks/review-tab.md +5 -1
  172. package/docs/components/tasks/subtasks-tab.md +5 -0
  173. package/docs/components/tasks/task-action-row.md +159 -0
  174. package/docs/components/tasks/task-assignee-picker.md +36 -0
  175. package/docs/components/tasks/task-column-picker.md +37 -0
  176. package/docs/components/tasks/task-date-picker.md +49 -0
  177. package/docs/components/tasks/task-detail-panel.md +256 -84
  178. package/docs/components/tasks/task-label-editor.md +42 -0
  179. package/docs/components/tasks/task-member-picker.md +35 -0
  180. package/docs/components/tasks/task-panel.md +89 -0
  181. package/docs/components/tasks/task-priority-picker.md +37 -0
  182. package/docs/components/tasks/task-properties.md +5 -0
  183. package/docs/components/tasks/task-visibility-picker.md +38 -0
  184. package/llms.txt +40 -13
  185. package/package.json +1 -1
@@ -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
@@ -1,10 +1,238 @@
1
- # TaskDetailPanel
1
+ # TaskDetailPanel (deprecated) / TaskPanel (v2)
2
2
 
3
3
  - Import: @devalok/shilp-sutra-karm/tasks
4
4
  - Server-safe: No
5
5
  - Category: tasks
6
6
 
7
- ## Props
7
+ ## TaskPanel — Composition API (v0.19.0)
8
+
9
+ TaskPanel is a headless compound component for building task detail panels.
10
+ It provides the **shell** (layout slots); you fill it with pickers, tab pieces,
11
+ or pre-assembled tabs as needed.
12
+
13
+ ### Shell Subcomponents
14
+
15
+ | Subcomponent | Props | Description |
16
+ |---|---|---|
17
+ | `TaskPanel` (root) | `children`, `className` | Flex column container, `h-full` |
18
+ | `TaskPanel.Header` | `children`, `className` | Top section with bottom border |
19
+ | `TaskPanel.Title` | `value`, `editable?`, `onUpdate?`, `subtask?`, `className` | Inline-editable heading. Click to edit (staff), Enter to commit, Escape to cancel |
20
+ | `TaskPanel.Properties` | `children`, `className` | Property rows container with bottom border |
21
+ | `TaskPanel.Property` | `icon`, `label`, `children`, `className` | Single property row: 120 px icon+label, flex-1 value |
22
+ | `TaskPanel.Tabs` | `defaultTab`, `onTabChange?`, `children`, `className` | Tab system. Children must be `TaskPanel.Tab` |
23
+ | `TaskPanel.Tab` | `id`, `label`, `icon?`, `children` | Declarative tab definition (does not render on its own) |
24
+ | `TaskPanel.Loading` | `className` | Skeleton placeholder (title + 6 property rows + 5 tab triggers + 3 content lines) |
25
+
26
+ ### Pickers (7)
27
+
28
+ All pickers support `readOnly?: boolean` and `className?: string`. Forwards ref.
29
+
30
+ | Picker | Key Props | Description |
31
+ |---|---|---|
32
+ | `TaskColumnPicker` | `columns: Column[]`, `value: string`, `onChange: (id) => void` | Popover column selector |
33
+ | `TaskPriorityPicker` | `value: Priority`, `onChange: (p) => void` | Popover with colored icons per priority |
34
+ | `TaskMemberPicker` | `members: Member[]`, `value: string \| null`, `onChange: (id \| null) => void`, `placeholder?` | Single-member picker (owner). Uses core MemberPicker |
35
+ | `TaskAssigneePicker` | `members: Member[]`, `value: Member[]`, `onAssign: (id) => void`, `onUnassign: (id) => void` | Multi-select assignee chips with add/remove. Uses core MemberPicker |
36
+ | `TaskDatePicker` | `value: Date \| string \| null`, `onChange: (date \| null) => void`, `presets?: boolean` | Date popover with quick-select presets (Today, Tomorrow, Next Monday, +7d, +14d, Clear) |
37
+ | `TaskLabelEditor` | `value: string[]`, `onChange: (labels) => void`, `availableLabels?: LabelOption[]` | Label chips with inline add input + autocomplete from availableLabels |
38
+ | `TaskVisibilityPicker` | `value: Visibility`, `onChange: (v) => void`, `confirmOnPublic?: boolean` | Internal/Everyone popover. When `confirmOnPublic=true`, shows a confirmation dialog before switching to EVERYONE |
39
+
40
+ ### Tab Pieces (16)
41
+
42
+ Grouped by the pre-assembled tab they belong to.
43
+
44
+ **Subtasks (4)**
45
+
46
+ | Piece | Key Props |
47
+ |---|---|
48
+ | `SubtaskProgress` | `completed: number`, `total: number` — progress bar |
49
+ | `SubtaskList` | `children` — wrapper div |
50
+ | `SubtaskItem` | `subtask: Subtask`, `isComplete: boolean`, `onToggle?`, `onClick?` |
51
+ | `SubtaskAddForm` | `onCreate: (title) => void`, `placeholder?` |
52
+
53
+ **Conversation (4)**
54
+
55
+ | Piece | Key Props |
56
+ |---|---|
57
+ | `MessageList` | `children`, `autoScroll?: boolean` — auto-scrolls to bottom on new children |
58
+ | `MessageBubble` | `comment: Comment`, `clientMode?`, `renderViewer?` |
59
+ | `MessageInput` | `onSubmit: (content, authorType) => void`, `renderEditor?`, `placeholder?`, `clientMode?` |
60
+ | `VisibilityWarning` | (no custom props) — renders "Comments may be seen by external users" |
61
+
62
+ **Files (3)**
63
+
64
+ | Piece | Key Props |
65
+ |---|---|
66
+ | `FileDropZone` | `onUpload: (file, title?) => void`, `isUploading?`, `accept?` |
67
+ | `FileList` | `children` — wrapper div |
68
+ | `FileItem` | `file: TaskFile`, `onDelete?`, `readOnly?` |
69
+
70
+ **Review (3)**
71
+
72
+ | Piece | Key Props |
73
+ |---|---|
74
+ | `ReviewCard` | `review: ReviewRequest`, `onUpdateStatus?` |
75
+ | `ReviewResponseForm` | `reviewId: string`, `onSubmit: (id, status, feedback?) => void` |
76
+ | `ReviewRequestButton` | `members: Member[]`, `onRequest: (reviewerId) => void` |
77
+
78
+ **Activity (2)**
79
+
80
+ | Piece | Key Props |
81
+ |---|---|
82
+ | `ActivityTimeline` | `children` — vertical timeline wrapper |
83
+ | `ActivityEntry` | `entry: AuditLogEntry` — single entry with icon, dot, timestamp, description |
84
+
85
+ ### Pre-Assembled Tab Defaults
86
+
87
+ These are the v0.18.0 tab components, still exported and usable inside `TaskPanel.Tab`:
88
+
89
+ | Tab | Import |
90
+ |---|---|
91
+ | `SubtasksTab` | `@devalok/shilp-sutra-karm/tasks` |
92
+ | `ConversationTab` | `@devalok/shilp-sutra-karm/tasks` |
93
+ | `FilesTab` | `@devalok/shilp-sutra-karm/tasks` |
94
+ | `ReviewTab` | `@devalok/shilp-sutra-karm/tasks` |
95
+ | `ActivityTab` | `@devalok/shilp-sutra-karm/tasks` |
96
+
97
+ Their props are unchanged from v0.18.0 (see individual docs).
98
+
99
+ ### Shared Types
100
+
101
+ All shared types are exported from `@devalok/shilp-sutra-karm/tasks`:
102
+
103
+ Priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT'
104
+ Visibility: 'INTERNAL' | 'EVERYONE'
105
+ CommentAuthorType: 'INTERNAL' | 'CLIENT'
106
+ LabelOption: { name: string; color?: string }
107
+ Member: { id: string; name: string; email?: string; image?: string | null }
108
+ Column: { id: string; name: string; isDefault?: boolean; isTerminal?: boolean }
109
+ Subtask, ReviewRequest, Comment, TaskFile, AuditLogEntry — see task-types.ts
110
+
111
+ ## Usage: Quick Drop-In (Pre-Assembled Tabs)
112
+
113
+ ```jsx
114
+ import {
115
+ TaskPanel,
116
+ SubtasksTab,
117
+ ConversationTab,
118
+ FilesTab,
119
+ ReviewTab,
120
+ ActivityTab,
121
+ TaskColumnPicker,
122
+ TaskPriorityPicker,
123
+ TaskMemberPicker,
124
+ TaskAssigneePicker,
125
+ TaskDatePicker,
126
+ TaskLabelEditor,
127
+ TaskVisibilityPicker,
128
+ } from '@devalok/shilp-sutra-karm/tasks'
129
+
130
+ function MyTaskPanel({ task, columns, members, activities }) {
131
+ if (!task) return <TaskPanel><TaskPanel.Loading /></TaskPanel>
132
+
133
+ return (
134
+ <TaskPanel>
135
+ <TaskPanel.Header>
136
+ <TaskPanel.Title
137
+ value={task.title}
138
+ editable
139
+ onUpdate={(title) => updateTitle(task.id, title)}
140
+ subtask={!!task.parentTaskId}
141
+ />
142
+ </TaskPanel.Header>
143
+
144
+ <TaskPanel.Properties>
145
+ <TaskPanel.Property icon={<ColumnsIcon />} label="Column">
146
+ <TaskColumnPicker columns={columns} value={task.columnId} onChange={(id) => update('columnId', id)} />
147
+ </TaskPanel.Property>
148
+ <TaskPanel.Property icon={<UserIcon />} label="Priority">
149
+ <TaskPriorityPicker value={task.priority} onChange={(p) => update('priority', p)} />
150
+ </TaskPanel.Property>
151
+ {/* ...more properties */}
152
+ </TaskPanel.Properties>
153
+
154
+ <TaskPanel.Tabs defaultTab="subtasks">
155
+ <TaskPanel.Tab id="subtasks" label="Subtasks">
156
+ <SubtasksTab
157
+ subtasks={task.subtasks}
158
+ projectId={task.projectId}
159
+ parentTaskId={task.id}
160
+ defaultColumnId={columns[0]?.id ?? ''}
161
+ onCreateSubtask={(title) => createSubtask(title)}
162
+ onToggleSubtask={(id, done) => toggleSubtask(id, done)}
163
+ />
164
+ </TaskPanel.Tab>
165
+ <TaskPanel.Tab id="conversation" label="Conversation">
166
+ <ConversationTab
167
+ comments={task.comments ?? []}
168
+ taskVisibility={task.visibility}
169
+ onPostComment={(content, type) => postComment(content, type)}
170
+ />
171
+ </TaskPanel.Tab>
172
+ {/* ...more tabs */}
173
+ </TaskPanel.Tabs>
174
+ </TaskPanel>
175
+ )
176
+ }
177
+ ```
178
+
179
+ ## Usage: Custom Composition (Individual Pieces)
180
+
181
+ ```jsx
182
+ import {
183
+ TaskPanel,
184
+ SubtaskProgress,
185
+ SubtaskList,
186
+ SubtaskItem,
187
+ SubtaskAddForm,
188
+ MessageList,
189
+ MessageBubble,
190
+ MessageInput,
191
+ } from '@devalok/shilp-sutra-karm/tasks'
192
+
193
+ function CustomSubtasksContent({ task }) {
194
+ const terminalId = columns.find(c => c.isTerminal)?.id
195
+
196
+ return (
197
+ <>
198
+ <SubtaskProgress completed={doneCount} total={task.subtasks.length} />
199
+ <SubtaskList>
200
+ {task.subtasks.map(st => (
201
+ <SubtaskItem
202
+ key={st.id}
203
+ subtask={st}
204
+ isComplete={st.column?.isTerminal || st.columnId === terminalId}
205
+ onToggle={(id, done) => toggleSubtask(id, done)}
206
+ onClick={(id) => navigateToTask(id)}
207
+ />
208
+ ))}
209
+ </SubtaskList>
210
+ <SubtaskAddForm onCreate={(title) => createSubtask(title)} />
211
+ </>
212
+ )
213
+ }
214
+ ```
215
+
216
+ ## TaskDetailPanel (deprecated)
217
+
218
+ `TaskDetailPanel` is the v0.18.0 monolithic component. It is still exported
219
+ and functional but is **deprecated** in favour of the TaskPanel composition API.
220
+
221
+ ### Migration Guide
222
+
223
+ | Old (TaskDetailPanel) | New (TaskPanel) |
224
+ |---|---|
225
+ | Single component with 30+ props | Compose shell + pickers + tab pieces |
226
+ | `task`, `columns`, `members` passed once | Pass data directly to each picker/tab |
227
+ | `clientMode` hides tabs/fields automatically | You control which tabs/properties to render |
228
+ | `headerSlot` render prop | Put any content inside `TaskPanel.Header` |
229
+ | `extraTabs` array | Add more `TaskPanel.Tab` children |
230
+ | `renderEditor`/`renderViewer` | Pass to `MessageBubble`/`MessageInput` or `ConversationTab` |
231
+ | `renderPriorityIndicator` | Use `TaskPriorityPicker` directly |
232
+ | `renderDatePicker` | Use `TaskDatePicker` directly |
233
+
234
+ ### Old Props (for reference)
235
+
8
236
  task: FullTask | null (REQUIRED)
9
237
  loading: boolean (default: false)
10
238
  open: boolean (REQUIRED)
@@ -12,92 +240,36 @@
12
240
  columns: Column[] (REQUIRED)
13
241
  members: Member[] (REQUIRED)
14
242
  activities: AuditLogEntry[] (default: [])
15
- enrichedComments: Comment[] | null (override comments from separate API)
16
- clientMode: boolean (default: false) — hides staff-only tabs/fields
243
+ enrichedComments: Comment[] | null
244
+ clientMode: boolean (default: false)
17
245
  clientEditableFields: string[] (default: ['priority', 'dueDate'])
18
- headerSlot: ReactNode (content between title and properties)
19
- extraTabs: ExtraTab[] (default: []) — additional tab panels alongside built-in tabs
20
- onTitleUpdate: (title: string) => void
21
- onPropertyUpdate: (field: string, value: unknown) => void
22
- onAssign: (userId: string) => void
23
- onUnassign: (userId: string) => void
24
- onCreateSubtask: (title: string) => void
25
- onToggleSubtask: (taskId: string, isComplete: boolean) => void
26
- onRequestReview: (reviewerId: string) => void
27
- onUpdateReviewStatus: (reviewId: string, status: string, feedback?: string) => void
28
- onPostComment: (content: string, authorType: 'INTERNAL' | 'CLIENT') => void
29
- onUploadFile: (file: File, title?: string) => void
30
- onUploadDeliverable: (file: File, deliverableId?: string) => void
31
- onDeleteFile: (fileId: string) => void
32
- onTabChange: (tab: string) => void
33
- renderEditor: (props: { content: string; onChange: (content: string) => void; placeholder: string }) => ReactNode
34
- renderViewer: (props: { content: string; className?: string }) => ReactNode
35
- renderPriorityIndicator: (props: { priority: string }) => ReactNode
36
- renderDatePicker: (props: { value: Date | null; onChange: (date: Date | null) => void; placeholder: string; className?: string }) => ReactNode
246
+ headerSlot: ReactNode
247
+ extraTabs: ExtraTab[]
248
+ onTitleUpdate, onPropertyUpdate, onAssign, onUnassign,
249
+ onCreateSubtask, onToggleSubtask, onRequestReview,
250
+ onUpdateReviewStatus, onPostComment, onUploadFile,
251
+ onUploadDeliverable, onDeleteFile, onTabChange
252
+ renderEditor, renderViewer, renderPriorityIndicator, renderDatePicker
37
253
  isUploading: boolean (default: false)
38
254
 
39
- ## FullTask Shape
40
- id: string
41
- title: string
42
- description: string | null
43
- projectId: string
44
- columnId: string
45
- column: { id: string; name: string }
46
- ownerId: string | null
47
- owner: Member | null
48
- priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT'
49
- dueDate: string | null
50
- labels: string[]
51
- visibility: 'INTERNAL' | 'EVERYONE'
52
- parentTaskId: string | null
53
- depth: number
54
- order: number
55
- isBlocked: boolean
56
- assignees: { user: Member }[]
57
- subtasks: Subtask[]
58
- reviewRequests: ReviewRequest[]
59
- comments: Comment[] (optional)
60
- files: TaskFile[]
61
- createdAt: string
62
- updatedAt: string
63
- metadata: Record<string, unknown> (optional)
64
-
65
- ## ExtraTab Shape
66
- id: string
67
- label: string
68
- icon: ReactNode (optional)
69
- content: ReactNode
70
- position: 'before' | 'after' (default: 'after')
71
-
72
- ## Built-in Tabs
73
- subtasks, review, conversation, files, activity
74
-
75
- ## Defaults
76
- loading=false, clientMode=false, clientEditableFields=['priority','dueDate'], activities=[], extraTabs=[], isUploading=false
77
-
78
- ## Example
79
- ```jsx
80
- <TaskDetailPanel
81
- task={selectedTask}
82
- open={isPanelOpen}
83
- onOpenChange={setIsPanelOpen}
84
- columns={projectColumns}
85
- members={teamMembers}
86
- activities={auditLog}
87
- onPropertyUpdate={(field, value) => updateTask(field, value)}
88
- onPostComment={(content, type) => postComment(content, type)}
89
- />
90
- ```
91
-
92
255
  ## Gotchas
93
- - Renders as a Sheet (side panel) on the right, 40% width (min 380px).
94
- - In clientMode, only the Conversation tab is shown. Staff-only tabs (subtasks, review, files, activity) are hidden.
95
- - In clientMode, title editing is disabled and properties respect clientEditableFields.
96
- - Title is editable by clicking on it (staff mode only).
97
- - enrichedComments takes priority over task.comments when both are provided.
98
- - extraTabs with position="before" render before built-in tabs; default "after" appends them.
99
- - Forwards ref to SheetContent.
256
+ - TaskPanel is a **layout shell** only — it does not render inside a Sheet. Wrap it in a Sheet yourself if you need a side panel.
257
+ - TaskDetailPanel (deprecated) still renders as a Sheet (right side panel, 40% width, min 380 px).
258
+ - TaskPanel.Tab renders nothing on its own; TaskPanel.Tabs extracts props from Tab children.
259
+ - TaskPanel.Title auto-selects text on edit activation for quick replacement.
260
+ - All pickers fall back to a read-only display when `readOnly=true`.
261
+ - TaskVisibilityPicker with `confirmOnPublic` shows a Dialog before switching to EVERYONE.
262
+ - TaskDatePicker accepts both `Date` and ISO string for the `value` prop.
263
+ - TaskLabelEditor supports both free-text entry and autocomplete from `availableLabels`.
100
264
 
101
265
  ## Changes
266
+ ### v0.19.0
267
+ - **Added** TaskPanel composition API (shell: Root, Header, Title, Properties, Property, Tabs, Tab, Loading)
268
+ - **Added** 7 standalone pickers: TaskColumnPicker, TaskPriorityPicker, TaskMemberPicker, TaskAssigneePicker, TaskDatePicker, TaskLabelEditor, TaskVisibilityPicker
269
+ - **Added** 16 tab pieces: SubtaskProgress, SubtaskList, SubtaskItem, SubtaskAddForm, MessageList, MessageBubble, MessageInput, VisibilityWarning, FileDropZone, FileList, FileItem, ReviewCard, ReviewResponseForm, ReviewRequestButton, ActivityTimeline, ActivityEntry
270
+ - **Added** Shared domain types exported from task-types.ts
271
+ - **Deprecated** TaskDetailPanel — use TaskPanel composition API instead
272
+ - **Breaking** Import path unchanged (`@devalok/shilp-sutra-karm/tasks`), but consumers using TaskDetailPanel should migrate to TaskPanel for new features
273
+
102
274
  ### v0.18.0
103
- - **Added** Initial release
275
+ - **Added** Initial release (monolithic TaskDetailPanel)
@@ -0,0 +1,42 @@
1
+ # TaskLabelEditor
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Inline label editor with autocomplete suggestions and color dot support. Displays labels as removable chips and provides a "+" button to add new labels by typing.
8
+
9
+ ## Props
10
+ value: string[] (REQUIRED — currently applied label names)
11
+ onChange: (labels: string[]) => void (REQUIRED — full updated label array)
12
+ availableLabels?: LabelOption[] (default: [] — autocomplete options, each { name, color? })
13
+ readOnly?: boolean (default: false — hides remove buttons and add input)
14
+ className?: string
15
+
16
+ ## Example
17
+ ```jsx
18
+ <TaskLabelEditor
19
+ value={task.labels}
20
+ onChange={(labels) => updateTask({ labels })}
21
+ availableLabels={[
22
+ { name: 'Bug', color: '#ef4444' },
23
+ { name: 'Feature', color: '#3b82f6' },
24
+ { name: 'Design', color: '#8b5cf6' },
25
+ ]}
26
+ />
27
+ ```
28
+
29
+ ## Gotchas
30
+ - Supports both selecting from `availableLabels` and creating new labels by typing a name not in the list.
31
+ - Autocomplete popover appears as you type, filtered to labels matching the input that are not already applied.
32
+ - Enter key: selects the first matching suggestion if available, otherwise creates a new label from the typed text.
33
+ - Escape key closes the input without adding.
34
+ - On blur, the typed value is committed as a label (if non-empty).
35
+ - Color dots appear on chips and in autocomplete suggestions when a label has a `color` value.
36
+ - Duplicate labels are prevented — adding an already-applied label is a no-op.
37
+ - In readOnly mode with no labels, displays "None".
38
+ - Forwards ref to the outer `<div>`.
39
+
40
+ ## Changes
41
+ ### v0.19.0
42
+ - **Added** Initial release
@@ -0,0 +1,35 @@
1
+ # TaskMemberPicker
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Single-select member picker for assigning a task owner. Wraps the core MemberPicker composed component with task-specific styling.
8
+
9
+ ## Props
10
+ members: Member[] (REQUIRED — array of { id, name, email?, image? })
11
+ value: string | null (REQUIRED — selected member id, or null for none)
12
+ onChange: (memberId: string | null) => void (REQUIRED — returns null when deselecting)
13
+ placeholder?: string (default: 'No owner')
14
+ readOnly?: boolean (default: false — renders as non-interactive display)
15
+ className?: string
16
+
17
+ ## Example
18
+ ```jsx
19
+ <TaskMemberPicker
20
+ members={projectMembers}
21
+ value={task.ownerId}
22
+ onChange={(memberId) => updateTask({ ownerId: memberId })}
23
+ placeholder="Assign owner"
24
+ />
25
+ ```
26
+
27
+ ## Gotchas
28
+ - Selecting the already-selected member deselects them (toggles to null).
29
+ - Uses core Avatar with initials fallback via `getInitials()`.
30
+ - In readOnly mode with no selection, shows the placeholder text in muted style.
31
+ - Forwards ref to the trigger button.
32
+
33
+ ## Changes
34
+ ### v0.19.0
35
+ - **Added** Initial release
@@ -0,0 +1,89 @@
1
+ # TaskPanel
2
+
3
+ - Import: @devalok/shilp-sutra-karm/tasks
4
+ - Server-safe: No
5
+ - Category: tasks
6
+
7
+ Compound component shell for the task detail panel. Container-agnostic — works in sidebars, modals, or full-page layouts. Compose the sub-components to build a complete task view.
8
+
9
+ ## Sub-components
10
+
11
+ ### TaskPanel (root)
12
+ children: ReactNode (REQUIRED)
13
+ className?: string
14
+
15
+ ### TaskPanel.Header
16
+ children: ReactNode (REQUIRED)
17
+ className?: string
18
+
19
+ ### TaskPanel.Title
20
+ value: string (REQUIRED — current title text)
21
+ editable?: boolean (default: false — enables inline editing)
22
+ onUpdate?: (title: string) => void (called when user commits a title change)
23
+ subtask?: boolean (default: false — shows a "Subtask" label above the title)
24
+ className?: string
25
+
26
+ ### TaskPanel.Properties
27
+ children: ReactNode (REQUIRED — should contain TaskPanel.Property rows)
28
+ className?: string
29
+
30
+ ### TaskPanel.Property
31
+ icon: ReactNode (REQUIRED — icon element for the label area)
32
+ label: string (REQUIRED — human-readable property name)
33
+ children: ReactNode (REQUIRED — property value or control)
34
+ className?: string
35
+
36
+ ### TaskPanel.Tabs
37
+ defaultTab: string (REQUIRED — id of the initially active tab)
38
+ onTabChange?: (tab: string) => void
39
+ children: ReactNode (REQUIRED — must contain TaskPanel.Tab children)
40
+ className?: string
41
+
42
+ ### TaskPanel.Tab
43
+ id: string (REQUIRED — unique tab identifier)
44
+ icon?: ReactNode (optional icon in the tab trigger)
45
+ label: string (REQUIRED — tab trigger label)
46
+ children: ReactNode (REQUIRED — tab panel content)
47
+
48
+ ### TaskPanel.Loading
49
+ className?: string
50
+
51
+ ## Example
52
+ ```jsx
53
+ <TaskPanel>
54
+ <TaskPanel.Header>
55
+ <TaskPanel.Title value={task.title} editable onUpdate={handleTitleUpdate} />
56
+ </TaskPanel.Header>
57
+
58
+ <TaskPanel.Properties>
59
+ <TaskPanel.Property icon={<IconColumns />} label="Status">
60
+ <TaskColumnPicker columns={columns} value={task.columnId} onChange={handleColumnChange} />
61
+ </TaskPanel.Property>
62
+ <TaskPanel.Property icon={<IconFlag />} label="Priority">
63
+ <TaskPriorityPicker value={task.priority} onChange={handlePriorityChange} />
64
+ </TaskPanel.Property>
65
+ </TaskPanel.Properties>
66
+
67
+ <TaskPanel.Tabs defaultTab="comments">
68
+ <TaskPanel.Tab id="comments" label="Comments" icon={<IconMessage />}>
69
+ {/* comments content */}
70
+ </TaskPanel.Tab>
71
+ <TaskPanel.Tab id="subtasks" label="Subtasks" icon={<IconSubtask />}>
72
+ {/* subtasks content */}
73
+ </TaskPanel.Tab>
74
+ </TaskPanel.Tabs>
75
+ </TaskPanel>
76
+ ```
77
+
78
+ ## Gotchas
79
+ - TaskPanel is container-agnostic. It renders as a flex column with `overflow-hidden h-full` — the parent must provide height constraints.
80
+ - TaskPanel.Tab does not render anything on its own. TaskPanel.Tabs extracts props from Tab children declaratively.
81
+ - TaskPanel.Title in editable mode: Enter commits, Escape cancels, blur commits. Empty titles revert to the previous value.
82
+ - TaskPanel.Title with `subtask` shows a small uppercase "Subtask" label above the heading.
83
+ - TaskPanel.Tabs uses a sticky tab bar. The content area scrolls independently.
84
+ - TaskPanel.Loading renders a skeleton placeholder with 6 property rows and 5 tab stubs.
85
+ - The label area in TaskPanel.Property has a fixed 120px width.
86
+
87
+ ## Changes
88
+ ### v0.19.0
89
+ - **Added** Initial release