@devalok/shilp-sutra-karm 0.18.1 → 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.
- package/dist/_chunks/task-detail-panel.js +1339 -1144
- package/dist/tasks/activity-tab.d.ts +2 -11
- package/dist/tasks/activity-tab.d.ts.map +1 -1
- package/dist/tasks/conversation-tab.d.ts +2 -21
- package/dist/tasks/conversation-tab.d.ts.map +1 -1
- package/dist/tasks/files-tab.d.ts +2 -18
- package/dist/tasks/files-tab.d.ts.map +1 -1
- package/dist/tasks/index.d.ts +12 -6
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +765 -8
- package/dist/tasks/pickers/index.d.ts +16 -0
- package/dist/tasks/pickers/index.d.ts.map +1 -0
- package/dist/tasks/pickers/task-assignee-picker.d.ts +14 -0
- package/dist/tasks/pickers/task-assignee-picker.d.ts.map +1 -0
- package/dist/tasks/pickers/task-column-picker.d.ts +13 -0
- package/dist/tasks/pickers/task-column-picker.d.ts.map +1 -0
- package/dist/tasks/pickers/task-date-picker.d.ts +12 -0
- package/dist/tasks/pickers/task-date-picker.d.ts.map +1 -0
- package/dist/tasks/pickers/task-label-editor.d.ts +13 -0
- package/dist/tasks/pickers/task-label-editor.d.ts.map +1 -0
- package/dist/tasks/pickers/task-member-picker.d.ts +14 -0
- package/dist/tasks/pickers/task-member-picker.d.ts.map +1 -0
- package/dist/tasks/pickers/task-priority-picker.d.ts +12 -0
- package/dist/tasks/pickers/task-priority-picker.d.ts.map +1 -0
- package/dist/tasks/pickers/task-visibility-picker.d.ts +13 -0
- package/dist/tasks/pickers/task-visibility-picker.d.ts.map +1 -0
- package/dist/tasks/review-tab.d.ts +4 -20
- package/dist/tasks/review-tab.d.ts.map +1 -1
- package/dist/tasks/subtasks-tab.d.ts +2 -18
- package/dist/tasks/subtasks-tab.d.ts.map +1 -1
- package/dist/tasks/tabs/activity-entry.d.ts +9 -0
- package/dist/tasks/tabs/activity-entry.d.ts.map +1 -0
- package/dist/tasks/tabs/activity-timeline.d.ts +8 -0
- package/dist/tasks/tabs/activity-timeline.d.ts.map +1 -0
- package/dist/tasks/tabs/file-drop-zone.d.ts +10 -0
- package/dist/tasks/tabs/file-drop-zone.d.ts.map +1 -0
- package/dist/tasks/tabs/file-item.d.ts +11 -0
- package/dist/tasks/tabs/file-item.d.ts.map +1 -0
- package/dist/tasks/tabs/file-list.d.ts +8 -0
- package/dist/tasks/tabs/file-list.d.ts.map +1 -0
- package/dist/tasks/tabs/index.d.ts +34 -0
- package/dist/tasks/tabs/index.d.ts.map +1 -0
- package/dist/tasks/tabs/message-bubble.d.ts +14 -0
- package/dist/tasks/tabs/message-bubble.d.ts.map +1 -0
- package/dist/tasks/tabs/message-input.d.ts +16 -0
- package/dist/tasks/tabs/message-input.d.ts.map +1 -0
- package/dist/tasks/tabs/message-list.d.ts +9 -0
- package/dist/tasks/tabs/message-list.d.ts.map +1 -0
- package/dist/tasks/tabs/review-card.d.ts +10 -0
- package/dist/tasks/tabs/review-card.d.ts.map +1 -0
- package/dist/tasks/tabs/review-request-button.d.ts +10 -0
- package/dist/tasks/tabs/review-request-button.d.ts.map +1 -0
- package/dist/tasks/tabs/review-response-form.d.ts +11 -0
- package/dist/tasks/tabs/review-response-form.d.ts.map +1 -0
- package/dist/tasks/tabs/subtask-add-form.d.ts +9 -0
- package/dist/tasks/tabs/subtask-add-form.d.ts.map +1 -0
- package/dist/tasks/tabs/subtask-item.d.ts +12 -0
- package/dist/tasks/tabs/subtask-item.d.ts.map +1 -0
- package/dist/tasks/tabs/subtask-list.d.ts +8 -0
- package/dist/tasks/tabs/subtask-list.d.ts.map +1 -0
- package/dist/tasks/tabs/subtask-progress.d.ts +9 -0
- package/dist/tasks/tabs/subtask-progress.d.ts.map +1 -0
- package/dist/tasks/tabs/visibility-warning.d.ts +7 -0
- package/dist/tasks/tabs/visibility-warning.d.ts.map +1 -0
- package/dist/tasks/task-panel.d.ts +104 -0
- package/dist/tasks/task-panel.d.ts.map +1 -0
- package/dist/tasks/task-properties.d.ts +2 -12
- package/dist/tasks/task-properties.d.ts.map +1 -1
- package/dist/tasks/task-types.d.ts +104 -0
- package/dist/tasks/task-types.d.ts.map +1 -0
- package/docs/components/admin/admin-dashboard.md +6 -6
- package/docs/components/admin/admin-utils.md +2 -2
- package/docs/components/admin/break-admin.md +14 -14
- package/docs/components/board/board-provider.md +16 -0
- package/docs/components/board/column-empty.md +1 -1
- package/docs/components/board/task-card.md +4 -0
- package/docs/components/chat/streaming-text.md +1 -1
- package/docs/components/client/client-portal-header.md +2 -2
- package/docs/components/dashboard/attendance-cta.md +3 -3
- package/docs/components/dashboard/daily-brief.md +1 -1
- package/docs/components/tasks/activity-tab.md +4 -0
- package/docs/components/tasks/conversation-tab.md +4 -0
- package/docs/components/tasks/files-tab.md +4 -0
- package/docs/components/tasks/review-tab.md +5 -1
- package/docs/components/tasks/subtasks-tab.md +5 -0
- package/docs/components/tasks/task-assignee-picker.md +36 -0
- package/docs/components/tasks/task-column-picker.md +37 -0
- package/docs/components/tasks/task-date-picker.md +49 -0
- package/docs/components/tasks/task-detail-panel.md +256 -84
- package/docs/components/tasks/task-label-editor.md +42 -0
- package/docs/components/tasks/task-member-picker.md +35 -0
- package/docs/components/tasks/task-panel.md +89 -0
- package/docs/components/tasks/task-priority-picker.md +37 -0
- package/docs/components/tasks/task-properties.md +5 -0
- package/docs/components/tasks/task-visibility-picker.md +38 -0
- package/llms.txt +40 -13
- package/package.json +82 -82
|
@@ -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
|
-
##
|
|
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
|
|
16
|
-
clientMode: boolean (default: false)
|
|
243
|
+
enrichedComments: Comment[] | null
|
|
244
|
+
clientMode: boolean (default: false)
|
|
17
245
|
clientEditableFields: string[] (default: ['priority', 'dueDate'])
|
|
18
|
-
headerSlot: ReactNode
|
|
19
|
-
extraTabs: ExtraTab[]
|
|
20
|
-
onTitleUpdate
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
- Title
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
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
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# TaskPriorityPicker
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra-karm/tasks
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: tasks
|
|
6
|
+
|
|
7
|
+
Popover-based picker for task priority. Each priority level has a distinct icon and color.
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
value: Priority (REQUIRED — 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT')
|
|
11
|
+
onChange: (priority: Priority) => void (REQUIRED)
|
|
12
|
+
readOnly?: boolean (default: false — renders as non-interactive indicator)
|
|
13
|
+
className?: string
|
|
14
|
+
|
|
15
|
+
## Priority Icons
|
|
16
|
+
URGENT: IconAlertTriangleFilled (text-error-9)
|
|
17
|
+
HIGH: IconArrowUp (text-warning-9)
|
|
18
|
+
MEDIUM: IconMinus (text-surface-fg-muted)
|
|
19
|
+
LOW: IconArrowDown (text-surface-fg-subtle)
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
```jsx
|
|
23
|
+
<TaskPriorityPicker
|
|
24
|
+
value={task.priority}
|
|
25
|
+
onChange={(priority) => updateTask({ priority })}
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gotchas
|
|
30
|
+
- Icon-per-level design: each priority has a unique icon and semantic color, not just a label.
|
|
31
|
+
- Priority labels are sourced from the shared `PRIORITY_LABELS` constant in `task-constants`.
|
|
32
|
+
- The selected priority row has a highlighted background and check icon.
|
|
33
|
+
- Forwards ref to the trigger button.
|
|
34
|
+
|
|
35
|
+
## Changes
|
|
36
|
+
### v0.19.0
|
|
37
|
+
- **Added** Initial release
|
|
@@ -72,8 +72,13 @@
|
|
|
72
72
|
- onUpdate field values: 'columnId', 'ownerId', 'priority', 'dueDate', 'labels', 'visibility'.
|
|
73
73
|
- Uses MemberPicker from core composed library for owner/assignee selection.
|
|
74
74
|
- onConfirmVisibilityChange is a guard hook: when provided and user switches to EVERYONE, it is called instead of onUpdate, allowing a confirmation dialog.
|
|
75
|
+
- Priority and Due Date rows are always rendered as interactive popovers regardless of readOnly. Enforcement of readOnly for these fields is done at the callback level. If using TaskProperties standalone in readOnly mode, supply a no-op onUpdate to prevent unintended changes.
|
|
75
76
|
- Forwards ref to outer div.
|
|
76
77
|
|
|
77
78
|
## Changes
|
|
79
|
+
### v0.19.0
|
|
80
|
+
- **Added** Property logic extracted into 7 standalone pickers: `TaskColumnPicker`, `TaskPriorityPicker`, `TaskMemberPicker`, `TaskAssigneePicker`, `TaskDatePicker`, `TaskLabelEditor`, `TaskVisibilityPicker`
|
|
81
|
+
- TaskProperties remains as a pre-assembled default; use individual pickers with `TaskPanel.Property` for custom layouts
|
|
82
|
+
|
|
78
83
|
### v0.18.0
|
|
79
84
|
- **Added** Initial release
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# TaskVisibilityPicker
|
|
2
|
+
|
|
3
|
+
- Import: @devalok/shilp-sutra-karm/tasks
|
|
4
|
+
- Server-safe: No
|
|
5
|
+
- Category: tasks
|
|
6
|
+
|
|
7
|
+
Popover-based picker for task visibility with an optional confirmation dialog when switching to public ("Everyone") visibility.
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
value: Visibility (REQUIRED — 'INTERNAL' | 'EVERYONE')
|
|
11
|
+
onChange: (visibility: Visibility) => void (REQUIRED)
|
|
12
|
+
confirmOnPublic?: boolean (default: false — when true, shows a confirmation dialog before switching to EVERYONE)
|
|
13
|
+
readOnly?: boolean (default: false — renders as non-interactive display)
|
|
14
|
+
className?: string
|
|
15
|
+
|
|
16
|
+
## Visibility Options
|
|
17
|
+
INTERNAL: IconLock — "Internal" — "Only team members"
|
|
18
|
+
EVERYONE: IconWorld — "Everyone" — "Visible to clients"
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
```jsx
|
|
22
|
+
<TaskVisibilityPicker
|
|
23
|
+
value={task.visibility}
|
|
24
|
+
onChange={(visibility) => updateTask({ visibility })}
|
|
25
|
+
confirmOnPublic
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gotchas
|
|
30
|
+
- When `confirmOnPublic` is true and the user selects "Everyone", a confirmation Dialog appears warning that the task will become visible to clients. The change only applies after the user clicks "Confirm".
|
|
31
|
+
- Switching to "Internal" never requires confirmation.
|
|
32
|
+
- Selecting the already-active option closes the popover without calling onChange.
|
|
33
|
+
- Each option row shows an icon, label, and description. The selected option has a highlighted background and check icon.
|
|
34
|
+
- Forwards ref to the trigger button.
|
|
35
|
+
|
|
36
|
+
## Changes
|
|
37
|
+
### v0.19.0
|
|
38
|
+
- **Added** Initial release
|