@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.
- package/dist/_chunks/render-adjustment-type.js +50 -48
- package/dist/_chunks/sidebar-scratchpad.js +714 -326
- package/dist/_chunks/task-detail-panel.js +1638 -1175
- package/dist/_chunks/vendor.js +1154 -1123
- package/dist/dashboard/index.d.ts +20 -0
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +451 -5
- package/dist/dashboard/project-health-card.d.ts +22 -0
- package/dist/dashboard/project-health-card.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/index.d.ts +13 -0
- package/dist/dashboard/scratchpad/index.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-add-input.d.ts +11 -0
- package/dist/dashboard/scratchpad/scratchpad-add-input.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-collapse.d.ts +15 -0
- package/dist/dashboard/scratchpad/scratchpad-collapse.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-context.d.ts +44 -0
- package/dist/dashboard/scratchpad/scratchpad-context.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-empty-state.d.ts +13 -0
- package/dist/dashboard/scratchpad/scratchpad-empty-state.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-filter-toggle.d.ts +7 -0
- package/dist/dashboard/scratchpad/scratchpad-filter-toggle.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-header.d.ts +9 -0
- package/dist/dashboard/scratchpad/scratchpad-header.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-item.d.ts +13 -0
- package/dist/dashboard/scratchpad/scratchpad-item.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-list.d.ts +9 -0
- package/dist/dashboard/scratchpad/scratchpad-list.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-progress-ring.d.ts +11 -0
- package/dist/dashboard/scratchpad/scratchpad-progress-ring.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad-root.d.ts +8 -0
- package/dist/dashboard/scratchpad/scratchpad-root.d.ts.map +1 -0
- package/dist/dashboard/scratchpad/scratchpad.d.ts +29 -0
- package/dist/dashboard/scratchpad/scratchpad.d.ts.map +1 -0
- package/dist/dashboard/scratchpad-widget.d.ts +5 -5
- package/dist/dashboard/scratchpad-widget.d.ts.map +1 -1
- package/dist/dashboard/sidebar-scratchpad.d.ts +8 -1
- package/dist/dashboard/sidebar-scratchpad.d.ts.map +1 -1
- package/dist/dashboard/week-heatmap/index.d.ts +10 -0
- package/dist/dashboard/week-heatmap/index.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-context.d.ts +31 -0
- package/dist/dashboard/week-heatmap/week-heatmap-context.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-day-strip.d.ts +7 -0
- package/dist/dashboard/week-heatmap/week-heatmap-day-strip.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-day.d.ts +15 -0
- package/dist/dashboard/week-heatmap/week-heatmap-day.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-progress-bar.d.ts +7 -0
- package/dist/dashboard/week-heatmap/week-heatmap-progress-bar.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-root.d.ts +8 -0
- package/dist/dashboard/week-heatmap/week-heatmap-root.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-streak.d.ts +7 -0
- package/dist/dashboard/week-heatmap/week-heatmap-streak.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap-summary.d.ts +7 -0
- package/dist/dashboard/week-heatmap/week-heatmap-summary.d.ts.map +1 -0
- package/dist/dashboard/week-heatmap/week-heatmap.d.ts +33 -0
- package/dist/dashboard/week-heatmap/week-heatmap.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -56
- 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 +13 -6
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +766 -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-action-row/index.d.ts +3 -0
- package/dist/tasks/task-action-row/index.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-checkbox.d.ts +8 -0
- package/dist/tasks/task-action-row/task-action-row-checkbox.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-context.d.ts +21 -0
- package/dist/tasks/task-action-row/task-action-row-context.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-due-date.d.ts +5 -0
- package/dist/tasks/task-action-row/task-action-row-due-date.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-labels.d.ts +8 -0
- package/dist/tasks/task-action-row/task-action-row-labels.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-navigate.d.ts +9 -0
- package/dist/tasks/task-action-row/task-action-row-navigate.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-priority.d.ts +5 -0
- package/dist/tasks/task-action-row/task-action-row-priority.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-project-badge.d.ts +8 -0
- package/dist/tasks/task-action-row/task-action-row-project-badge.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-root.d.ts +14 -0
- package/dist/tasks/task-action-row/task-action-row-root.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-status-badge.d.ts +5 -0
- package/dist/tasks/task-action-row/task-action-row-status-badge.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row-title.d.ts +9 -0
- package/dist/tasks/task-action-row/task-action-row-title.d.ts.map +1 -0
- package/dist/tasks/task-action-row/task-action-row.d.ts +48 -0
- package/dist/tasks/task-action-row/task-action-row.d.ts.map +1 -0
- package/dist/tasks/task-detail-panel.d.ts.map +1 -1
- 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/dashboard/project-health-card.md +90 -0
- package/docs/components/dashboard/scratchpad-widget.md +17 -0
- package/docs/components/dashboard/scratchpad.md +151 -0
- package/docs/components/dashboard/sidebar-scratchpad.md +29 -5
- package/docs/components/dashboard/week-heatmap.md +95 -0
- 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-action-row.md +159 -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 +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
|
-
##
|
|
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
|