@devalok/shilp-sutra-karm 0.4.0 → 0.6.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/README.md CHANGED
@@ -1,25 +1,32 @@
1
1
  # @devalok/shilp-sutra-karm
2
2
 
3
- Domain components for project management -- board, tasks, chat, dashboard, client portal, and admin.
3
+ Domain-specific UI components for project management applications -- kanban boards, task panels, AI chat, attendance dashboards, client portals, and admin tools.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@devalok/shilp-sutra-karm)](https://www.npmjs.com/package/@devalok/shilp-sutra-karm)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  ---
9
9
 
10
+ ## When to use Karm vs Core
11
+
12
+ | Need | Package |
13
+ |------|---------|
14
+ | Generic UI primitives (Button, Dialog, Table, Badge, etc.) | `@devalok/shilp-sutra` (core) |
15
+ | Project management features (boards, tasks, chat, admin) | `@devalok/shilp-sutra-karm` |
16
+
17
+ Karm builds on top of core. It provides opinionated, domain-specific components that combine multiple core primitives into ready-to-use features for project management and team collaboration apps.
18
+
10
19
  ## Install
11
20
 
12
21
  ```bash
13
22
  pnpm add @devalok/shilp-sutra-karm @devalok/shilp-sutra
14
23
  ```
15
24
 
16
- **Note:** `@devalok/shilp-sutra >=0.3.0` is a required peer dependency.
17
-
18
25
  ## Peer Dependencies
19
26
 
20
27
  | Package | Version | Required |
21
28
  |---------|---------|----------|
22
- | `@devalok/shilp-sutra` | `>=0.3.0` | Yes |
29
+ | `@devalok/shilp-sutra` | `>=0.1.0` | Yes |
23
30
  | `react` | `^18 \|\| ^19` | Yes |
24
31
  | `react-dom` | `^18 \|\| ^19` | Yes |
25
32
 
@@ -32,15 +39,99 @@ import { KanbanBoard } from '@devalok/shilp-sutra-karm/board'
32
39
  import { TaskDetailPanel } from '@devalok/shilp-sutra-karm/tasks'
33
40
  import { ChatPanel } from '@devalok/shilp-sutra-karm/chat'
34
41
  import { AttendanceCTA, DailyBrief } from '@devalok/shilp-sutra-karm/dashboard'
35
- import { ClientHeader, ProjectCard } from '@devalok/shilp-sutra-karm/client'
42
+ import { ClientPortalHeader, ProjectCard } from '@devalok/shilp-sutra-karm/client'
36
43
  import { AdminDashboard, BreakAdmin } from '@devalok/shilp-sutra-karm/admin'
37
44
  ```
38
45
 
46
+ ## Component Inventory
47
+
48
+ ### Board (`@devalok/shilp-sutra-karm/board`)
49
+
50
+ Drag-and-drop kanban board with sortable columns and task cards.
51
+
52
+ | Component | Description |
53
+ |-----------|-------------|
54
+ | `KanbanBoard` | Full kanban board with columns, drag-and-drop, and task management |
55
+ | `BoardColumn` | Single sortable column with task list and add-task action |
56
+ | `TaskCard` | Draggable task card with priority, labels, assignees, and due date |
57
+
58
+ ### Tasks (`@devalok/shilp-sutra-karm/tasks`)
59
+
60
+ Task detail panel with tabbed content (conversation, files, subtasks, reviews, activity).
61
+
62
+ | Component | Description |
63
+ |-----------|-------------|
64
+ | `TaskDetailPanel` | Sheet-based task detail view with all tabs |
65
+ | `TaskProperties` | Editable task metadata (status, priority, assignees, dates) |
66
+ | `ConversationTab` | Threaded comments on a task |
67
+ | `FilesTab` | File attachments with upload and delete |
68
+ | `SubtasksTab` | Nested subtask list with create and status toggle |
69
+ | `ReviewTab` | Review request and approval workflow |
70
+ | `ActivityTab` | Audit log of task changes |
71
+
72
+ ### Chat (`@devalok/shilp-sutra-karm/chat`)
73
+
74
+ AI-powered chat panel with streaming support and conversation history.
75
+
76
+ | Component | Description |
77
+ |-----------|-------------|
78
+ | `ChatPanel` | Full chat interface with conversation list and message area |
79
+ | `ChatInput` | Message input with agent selector and submit |
80
+ | `MessageList` | Scrollable message thread with markdown rendering |
81
+ | `ConversationList` | Sidebar list of past conversations |
82
+ | `StreamingText` | Animated streaming text display for AI responses |
83
+
84
+ ### Dashboard (`@devalok/shilp-sutra-karm/dashboard`)
85
+
86
+ Employee-facing attendance and daily brief widgets.
87
+
88
+ | Component | Description |
89
+ |-----------|-------------|
90
+ | `AttendanceCTA` | Attendance marking card with status display |
91
+ | `DailyBrief` | Daily summary card with tasks, meetings, and announcements |
92
+
93
+ ### Client (`@devalok/shilp-sutra-karm/client`)
94
+
95
+ Client portal components with brand accent theming.
96
+
97
+ | Component | Description |
98
+ |-----------|-------------|
99
+ | `ClientPortalHeader` | Portal header with org branding and user menu |
100
+ | `ProjectCard` | Project summary card for client-facing views |
101
+ | `AccentProvider` | CSS custom property provider for client brand colors |
102
+
103
+ ### Admin (`@devalok/shilp-sutra-karm/admin`)
104
+
105
+ Admin dashboard, break/leave management, attendance tracking, and adjustments.
106
+
107
+ | Component | Description |
108
+ |-----------|-------------|
109
+ | `AdminDashboard` | Compound admin view with attendance overview, calendar, and associate detail |
110
+ | `BreakAdmin` | Compound break management panel (header, balance, breaks list, requests) |
111
+ | `BreakAdminHeader` | Filter bar for break admin |
112
+ | `BreakBalance` | Break balance summary table with edit |
113
+ | `Breaks` | Break list with edit and delete actions |
114
+ | `EditBreak` | Break edit dialog |
115
+ | `DeleteBreak` | Break delete confirmation dialog |
116
+ | `EditBreakBalance` | Balance adjustment dialog |
117
+ | `LeaveRequest` | Individual leave request card with approve/reject |
118
+ | `LeaveRequests` | Pending leave requests list |
119
+ | `AttendanceOverview` | Team attendance summary cards |
120
+ | `AssociateDetail` | Individual associate detail with attendance, tasks, and breaks |
121
+ | `DashboardHeader` | Admin dashboard header with date and user selector |
122
+ | `Calendar` | Monthly attendance calendar with day status |
123
+ | `CorrectionList` | Attendance correction requests list |
124
+ | `RenderDate` | Date display utility component |
125
+ | `ApprovedAdjustments` | Approved break adjustment history table |
126
+ | `BreakAdminSkeleton` | Loading skeleton for BreakAdmin |
127
+ | `DashboardSkeleton` | Loading skeleton for AdminDashboard |
128
+ | `renderAdjustmentType` | Utility to render adjustment type labels |
129
+
39
130
  ## Sub-path Exports
40
131
 
41
132
  | Import path | Contents |
42
133
  |-------------|----------|
43
- | `@devalok/shilp-sutra-karm` | All domain components |
134
+ | `@devalok/shilp-sutra-karm` | All domain components (barrel) |
44
135
  | `@devalok/shilp-sutra-karm/board` | Kanban board with drag-and-drop |
45
136
  | `@devalok/shilp-sutra-karm/tasks` | Task detail panel, properties, tabs |
46
137
  | `@devalok/shilp-sutra-karm/chat` | AI chat panel, message list, streaming |
@@ -138,7 +138,7 @@ const E = p.forwardRef(
138
138
  m,
139
139
  {
140
140
  ref: n,
141
- icon: l,
141
+ icon: /* @__PURE__ */ r(l, {}),
142
142
  title: "No activity yet",
143
143
  description: "Actions on this task will appear here",
144
144
  compact: !0,
@@ -1,13 +1,13 @@
1
1
  "use client";
2
- import { jsxs as a, jsx as t } from "react/jsx-runtime";
2
+ import { jsxs as a, jsx as e } from "react/jsx-runtime";
3
3
  import * as m from "react";
4
4
  import { cn as g } from "@devalok/shilp-sutra/ui";
5
5
  import { Avatar as y, AvatarImage as v, AvatarFallback as w } from "@devalok/shilp-sutra/ui";
6
6
  import { EmptyState as T } from "@devalok/shilp-sutra/composed";
7
7
  import { IconMessageCircle as C, IconSend as A } from "@tabler/icons-react";
8
8
  import { getInitials as I } from "@devalok/shilp-sutra/composed";
9
- function E(e) {
10
- const n = new Date(e), u = (/* @__PURE__ */ new Date()).getTime() - n.getTime(), o = Math.floor(u / 6e4), s = Math.floor(o / 60), l = Math.floor(s / 24);
9
+ function E(t) {
10
+ const n = new Date(t), u = (/* @__PURE__ */ new Date()).getTime() - n.getTime(), o = Math.floor(u / 6e4), s = Math.floor(o / 60), l = Math.floor(s / 24);
11
11
  return o < 1 ? "Just now" : o < 60 ? `${o}m ago` : s < 24 ? `${s}h ago` : l < 7 ? `${l}d ago` : n.toLocaleDateString("en-IN", {
12
12
  month: "short",
13
13
  day: "numeric",
@@ -15,16 +15,16 @@ function E(e) {
15
15
  minute: "2-digit"
16
16
  });
17
17
  }
18
- function k(e) {
19
- return e.authorType === "INTERNAL" && e.internalAuthor ? e.internalAuthor : e.authorType === "CLIENT" && e.clientAuthor ? {
20
- id: e.clientAuthor.id,
21
- name: e.clientAuthor.name,
22
- email: e.clientAuthor.email,
18
+ function k(t) {
19
+ return t.authorType === "INTERNAL" && t.internalAuthor ? t.internalAuthor : t.authorType === "CLIENT" && t.clientAuthor ? {
20
+ id: t.clientAuthor.id,
21
+ name: t.clientAuthor.name,
22
+ email: t.clientAuthor.email,
23
23
  image: null
24
- } : { id: e.authorId, name: "Unknown", image: null };
24
+ } : { id: t.authorId, name: "Unknown", image: null };
25
25
  }
26
- function R(e) {
27
- return e.replace(/<[^>]*>/g, "");
26
+ function R(t) {
27
+ return t.replace(/<[^>]*>/g, "");
28
28
  }
29
29
  const L = m.forwardRef(
30
30
  function({
@@ -43,7 +43,7 @@ const L = m.forwardRef(
43
43
  return m.useEffect(() => {
44
44
  c.current && (c.current.scrollTop = c.current.scrollHeight);
45
45
  }, [n.length]), /* @__PURE__ */ a("div", { ref: b, className: g("flex flex-col", o), children: [
46
- n.length > 0 ? /* @__PURE__ */ t(
46
+ n.length > 0 ? /* @__PURE__ */ e(
47
47
  "div",
48
48
  {
49
49
  ref: c,
@@ -52,8 +52,8 @@ const L = m.forwardRef(
52
52
  const i = k(r), f = r.authorType === "CLIENT";
53
53
  return /* @__PURE__ */ a("div", { className: "flex gap-ds-03", children: [
54
54
  /* @__PURE__ */ a(y, { className: "h-ds-xs-plus w-ds-xs-plus shrink-0 mt-ds-01", children: [
55
- i.image && /* @__PURE__ */ t(v, { src: i.image, alt: i.name }),
56
- /* @__PURE__ */ t(
55
+ i.image && /* @__PURE__ */ e(v, { src: i.image, alt: i.name }),
56
+ /* @__PURE__ */ e(
57
57
  w,
58
58
  {
59
59
  className: g(
@@ -67,34 +67,34 @@ const L = m.forwardRef(
67
67
  ] }),
68
68
  /* @__PURE__ */ a("div", { className: "flex-1 min-w-0", children: [
69
69
  /* @__PURE__ */ a("div", { className: "flex items-baseline gap-ds-03", children: [
70
- /* @__PURE__ */ t("span", { className: "text-ds-md font-medium text-text-primary", children: i.name }),
71
- s ? !f && /* @__PURE__ */ t("span", { className: "rounded bg-layer-03 px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider text-text-on-color", children: "Team" }) : f && /* @__PURE__ */ t("span", { className: "rounded bg-warning-surface px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider text-text-warning", children: "Client" }),
72
- /* @__PURE__ */ t("span", { className: "text-ds-sm text-text-placeholder", children: E(r.createdAt) })
70
+ /* @__PURE__ */ e("span", { className: "text-ds-md font-medium text-text-primary", children: i.name }),
71
+ s ? !f && /* @__PURE__ */ e("span", { className: "rounded bg-layer-03 px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider text-text-on-color", children: "Team" }) : f && /* @__PURE__ */ e("span", { className: "rounded bg-warning-surface px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider text-text-warning", children: "Client" }),
72
+ /* @__PURE__ */ e("span", { className: "text-ds-sm text-text-placeholder", children: E(r.createdAt) })
73
73
  ] }),
74
- /* @__PURE__ */ t("div", { className: "mt-ds-02", children: h ? h({
74
+ /* @__PURE__ */ e("div", { className: "mt-ds-02", children: h ? h({
75
75
  content: r.content,
76
76
  className: "[&_.ProseMirror]:!min-h-0 [&_.ProseMirror]:!p-0"
77
- }) : /* @__PURE__ */ t("p", { className: "text-ds-md text-text-secondary whitespace-pre-wrap", children: R(r.content) }) })
77
+ }) : /* @__PURE__ */ e("p", { className: "text-ds-md text-text-secondary whitespace-pre-wrap", children: R(r.content) }) })
78
78
  ] })
79
79
  ] }, r.id);
80
80
  })
81
81
  }
82
- ) : /* @__PURE__ */ t(
82
+ ) : /* @__PURE__ */ e(
83
83
  T,
84
84
  {
85
- icon: C,
85
+ icon: /* @__PURE__ */ e(C, {}),
86
86
  title: "No comments yet",
87
87
  description: "Start a conversation about this task",
88
88
  compact: !0
89
89
  }
90
90
  ),
91
91
  /* @__PURE__ */ a("div", { className: "mt-ds-05 space-y-ds-03", children: [
92
- x === "EVERYONE" && !s && /* @__PURE__ */ t("p", { className: "text-ds-xs text-text-warning", children: "This task is visible to clients. Comments may be seen by external users." }),
92
+ x === "EVERYONE" && !s && /* @__PURE__ */ e("p", { className: "text-ds-xs text-text-warning", children: "This task is visible to clients. Comments may be seen by external users." }),
93
93
  l ? l({
94
94
  content: d,
95
95
  onChange: p,
96
96
  placeholder: "Write a comment..."
97
- }) : /* @__PURE__ */ t(
97
+ }) : /* @__PURE__ */ e(
98
98
  "textarea",
99
99
  {
100
100
  value: d,
@@ -104,7 +104,7 @@ const L = m.forwardRef(
104
104
  className: "w-full resize-none rounded-ds-md border border-border bg-transparent px-ds-04 py-ds-03 text-ds-md text-text-primary placeholder:text-text-placeholder outline-none focus:border-border-subtle"
105
105
  }
106
106
  ),
107
- /* @__PURE__ */ t("div", { className: "flex justify-end", children: /* @__PURE__ */ a(
107
+ /* @__PURE__ */ e("div", { className: "flex justify-end", children: /* @__PURE__ */ a(
108
108
  "button",
109
109
  {
110
110
  type: "button",
@@ -112,7 +112,7 @@ const L = m.forwardRef(
112
112
  disabled: !d.replace(/<[^>]*>/g, "").trim(),
113
113
  className: "inline-flex items-center gap-ds-02b rounded-ds-lg bg-interactive px-ds-04 py-ds-02b text-ds-sm font-semibold text-text-on-color transition-colors hover:bg-interactive-hover disabled:opacity-[0.38] disabled:cursor-not-allowed",
114
114
  children: [
115
- /* @__PURE__ */ t(A, { className: "h-ico-sm w-ico-sm", stroke: 2 }),
115
+ /* @__PURE__ */ e(A, { className: "h-ico-sm w-ico-sm", stroke: 2 }),
116
116
  "Comment"
117
117
  ]
118
118
  }
@@ -171,7 +171,7 @@ const G = d.forwardRef(
171
171
  }) }) : /* @__PURE__ */ e("div", { className: "mt-ds-03", children: /* @__PURE__ */ e(
172
172
  R,
173
173
  {
174
- icon: B,
174
+ icon: /* @__PURE__ */ e(B, {}),
175
175
  title: "No files attached",
176
176
  description: "Upload files to share with your team",
177
177
  compact: !0
@@ -136,7 +136,7 @@ const G = [
136
136
  }) }) : /* @__PURE__ */ t(
137
137
  S,
138
138
  {
139
- icon: T,
139
+ icon: /* @__PURE__ */ t(T, {}),
140
140
  title: "No reviews yet",
141
141
  description: "Request a review from a team member",
142
142
  compact: !0
@@ -101,7 +101,7 @@ const C = l.forwardRef(
101
101
  }) }) : !m && /* @__PURE__ */ t(
102
102
  j,
103
103
  {
104
- icon: L,
104
+ icon: /* @__PURE__ */ t(L, {}),
105
105
  title: "No subtasks",
106
106
  description: "Break this task into smaller pieces",
107
107
  compact: !0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devalok/shilp-sutra-karm",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Domain components for Karm — board, tasks, chat, dashboard, client, and admin",
5
5
  "license": "MIT",
6
6
  "type": "module",