@devalok/shilp-sutra 0.28.0 → 0.29.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 (242) hide show
  1. package/dist/_chunks/badge-group.js +299 -0
  2. package/dist/_chunks/framer.js +1915 -1980
  3. package/dist/_chunks/keybinding.js +4 -5
  4. package/dist/_chunks/primitives.js +3198 -3272
  5. package/dist/_chunks/sonner.js +29 -31
  6. package/dist/_chunks/stat-row.js +110 -131
  7. package/dist/_chunks/tiptap.js +42 -78
  8. package/dist/_chunks/tree-view.js +138 -149
  9. package/dist/_chunks/typing-indicator.js +565 -0
  10. package/dist/_chunks/use-calendar.js +416 -439
  11. package/dist/_chunks/vendor-client.js +5 -5
  12. package/dist/_chunks/vendor-utils.js +5 -5
  13. package/dist/ai/block-renderer.js +22 -22
  14. package/dist/ai/blocks/loading.d.ts.map +1 -1
  15. package/dist/ai/command-bar.d.ts.map +1 -1
  16. package/dist/ai/command-bar.js +241 -263
  17. package/dist/ai/conversation.d.ts.map +1 -1
  18. package/dist/ai/conversation.js +87 -107
  19. package/dist/composed/activity-feed.d.ts +2 -0
  20. package/dist/composed/activity-feed.d.ts.map +1 -1
  21. package/dist/composed/activity-feed.js +118 -90
  22. package/dist/composed/avatar-group.d.ts +1 -0
  23. package/dist/composed/avatar-group.d.ts.map +1 -1
  24. package/dist/composed/avatar-group.js +91 -67
  25. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  26. package/dist/composed/bulk-action-bar.js +29 -28
  27. package/dist/composed/command-palette.d.ts.map +1 -1
  28. package/dist/composed/command-palette.js +99 -113
  29. package/dist/composed/content-card.js +1 -1
  30. package/dist/composed/date-picker/calendar-grid.d.ts.map +1 -1
  31. package/dist/composed/date-picker/date-picker.d.ts.map +1 -1
  32. package/dist/composed/date-picker/date-range-picker.d.ts.map +1 -1
  33. package/dist/composed/date-picker/date-time-picker.d.ts.map +1 -1
  34. package/dist/composed/date-picker/time-picker.d.ts.map +1 -1
  35. package/dist/composed/deadline-indicator.d.ts.map +1 -1
  36. package/dist/composed/deadline-indicator.js +29 -28
  37. package/dist/composed/error-boundary.d.ts.map +1 -1
  38. package/dist/composed/error-boundary.js +30 -27
  39. package/dist/composed/extensions/file-attachment.d.ts.map +1 -1
  40. package/dist/composed/file-preview.d.ts.map +1 -1
  41. package/dist/composed/file-preview.js +261 -271
  42. package/dist/composed/filter-bar.d.ts.map +1 -1
  43. package/dist/composed/filter-bar.js +49 -48
  44. package/dist/composed/form-section.d.ts.map +1 -1
  45. package/dist/composed/form-section.js +12 -11
  46. package/dist/composed/global-loading.js +1 -1
  47. package/dist/composed/index.js +63 -63
  48. package/dist/composed/inline-edit.d.ts.map +1 -1
  49. package/dist/composed/inline-edit.js +55 -54
  50. package/dist/composed/markdown-viewer.d.ts.map +1 -1
  51. package/dist/composed/markdown-viewer.js +44 -43
  52. package/dist/composed/master-detail.d.ts.map +1 -1
  53. package/dist/composed/master-detail.js +35 -34
  54. package/dist/composed/multi-select-popover.d.ts.map +1 -1
  55. package/dist/composed/multi-select-popover.js +73 -73
  56. package/dist/composed/page-header.d.ts.map +1 -1
  57. package/dist/composed/page-header.js +31 -37
  58. package/dist/composed/priority-indicator.d.ts.map +1 -1
  59. package/dist/composed/priority-indicator.js +37 -36
  60. package/dist/composed/rich-text-editor.d.ts.map +1 -1
  61. package/dist/composed/rich-text-editor.js +287 -306
  62. package/dist/composed/schedule-view.js +62 -62
  63. package/dist/composed/status-badge.d.ts +4 -2
  64. package/dist/composed/status-badge.d.ts.map +1 -1
  65. package/dist/composed/status-badge.js +58 -45
  66. package/dist/shell/app-command-palette.d.ts.map +1 -1
  67. package/dist/shell/app-command-palette.js +93 -93
  68. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  69. package/dist/shell/bottom-navbar.js +21 -20
  70. package/dist/shell/index.js +18 -18
  71. package/dist/shell/notification-center.d.ts.map +1 -1
  72. package/dist/shell/notification-center.js +96 -95
  73. package/dist/shell/notification-preferences.d.ts.map +1 -1
  74. package/dist/shell/notification-preferences.js +82 -85
  75. package/dist/shell/sidebar.js +59 -60
  76. package/dist/shell/top-bar.d.ts.map +1 -1
  77. package/dist/shell/top-bar.js +103 -103
  78. package/dist/tailwind/index.cjs +37 -4
  79. package/dist/tailwind/preset.d.ts.map +1 -1
  80. package/dist/tailwind/preset.js +38 -5
  81. package/dist/tokens/primitives.css +10 -0
  82. package/dist/tokens/semantic.css +70 -7
  83. package/dist/ui/accordion.d.ts +5 -2
  84. package/dist/ui/accordion.d.ts.map +1 -1
  85. package/dist/ui/accordion.js +44 -39
  86. package/dist/ui/alert-dialog.js +57 -57
  87. package/dist/ui/alert.d.ts +1 -1
  88. package/dist/ui/alert.d.ts.map +1 -1
  89. package/dist/ui/alert.js +30 -29
  90. package/dist/ui/aspect-ratio.js +4 -4
  91. package/dist/ui/autocomplete.js +56 -56
  92. package/dist/ui/avatar.js +2 -2
  93. package/dist/ui/badge-group.d.ts +22 -0
  94. package/dist/ui/badge-group.d.ts.map +1 -0
  95. package/dist/ui/badge-group.js +8 -0
  96. package/dist/ui/badge-indicator.d.ts +32 -0
  97. package/dist/ui/badge-indicator.d.ts.map +1 -0
  98. package/dist/ui/badge-indicator.js +54 -0
  99. package/dist/ui/badge.d.ts +27 -24
  100. package/dist/ui/badge.d.ts.map +1 -1
  101. package/dist/ui/badge.js +13 -129
  102. package/dist/ui/banner.d.ts +1 -1
  103. package/dist/ui/banner.d.ts.map +1 -1
  104. package/dist/ui/banner.js +27 -26
  105. package/dist/ui/breadcrumb.d.ts.map +1 -1
  106. package/dist/ui/breadcrumb.js +37 -36
  107. package/dist/ui/button-group.d.ts +12 -6
  108. package/dist/ui/button-group.d.ts.map +1 -1
  109. package/dist/ui/button-group.js +18 -18
  110. package/dist/ui/button-processing.d.ts +15 -0
  111. package/dist/ui/button-processing.d.ts.map +1 -0
  112. package/dist/ui/button-processing.js +77 -0
  113. package/dist/ui/button.d.ts +50 -25
  114. package/dist/ui/button.d.ts.map +1 -1
  115. package/dist/ui/button.js +243 -127
  116. package/dist/ui/card.js +20 -21
  117. package/dist/ui/charts/index.js +499 -508
  118. package/dist/ui/chat/date-separator.d.ts +12 -0
  119. package/dist/ui/chat/date-separator.d.ts.map +1 -0
  120. package/dist/ui/chat/index.d.ts +9 -0
  121. package/dist/ui/chat/index.d.ts.map +1 -0
  122. package/dist/ui/chat/index.js +12 -0
  123. package/dist/ui/chat/message-input.d.ts +16 -0
  124. package/dist/ui/chat/message-input.d.ts.map +1 -0
  125. package/dist/ui/chat/message-list.d.ts +24 -0
  126. package/dist/ui/chat/message-list.d.ts.map +1 -0
  127. package/dist/ui/chat/message.d.ts +108 -0
  128. package/dist/ui/chat/message.d.ts.map +1 -0
  129. package/dist/ui/chat/system-message.d.ts +11 -0
  130. package/dist/ui/chat/system-message.d.ts.map +1 -0
  131. package/dist/ui/chat/typing-indicator.d.ts +14 -0
  132. package/dist/ui/chat/typing-indicator.d.ts.map +1 -0
  133. package/dist/ui/chat/unread-separator.d.ts +12 -0
  134. package/dist/ui/chat/unread-separator.d.ts.map +1 -0
  135. package/dist/ui/checkbox.js +18 -18
  136. package/dist/ui/chip.d.ts +13 -62
  137. package/dist/ui/chip.d.ts.map +1 -1
  138. package/dist/ui/chip.js +10 -109
  139. package/dist/ui/collapsible.js +4 -4
  140. package/dist/ui/color-input.js +134 -134
  141. package/dist/ui/color-swatch.js +11 -11
  142. package/dist/ui/combobox.d.ts.map +1 -1
  143. package/dist/ui/combobox.js +74 -80
  144. package/dist/ui/context-menu.d.ts.map +1 -1
  145. package/dist/ui/context-menu.js +86 -85
  146. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  147. package/dist/ui/data-table-toolbar.js +51 -57
  148. package/dist/ui/data-table.d.ts.map +1 -1
  149. package/dist/ui/data-table.js +268 -296
  150. package/dist/ui/devalok-grain.d.ts +81 -0
  151. package/dist/ui/devalok-grain.d.ts.map +1 -0
  152. package/dist/ui/devalok-grain.js +69 -0
  153. package/dist/ui/dialog.d.ts.map +1 -1
  154. package/dist/ui/dialog.js +73 -72
  155. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  156. package/dist/ui/dropdown-menu.js +93 -92
  157. package/dist/ui/file-upload.d.ts.map +1 -1
  158. package/dist/ui/file-upload.js +82 -82
  159. package/dist/ui/hover-card.js +29 -29
  160. package/dist/ui/icon-button.d.ts +7 -7
  161. package/dist/ui/icon-button.d.ts.map +1 -1
  162. package/dist/ui/icon-context.d.ts +15 -0
  163. package/dist/ui/icon-context.d.ts.map +1 -0
  164. package/dist/ui/icon-context.js +20 -0
  165. package/dist/ui/icon-group.d.ts +22 -0
  166. package/dist/ui/icon-group.d.ts.map +1 -0
  167. package/dist/ui/icon-group.js +32 -0
  168. package/dist/ui/icon.d.ts +57 -0
  169. package/dist/ui/icon.d.ts.map +1 -0
  170. package/dist/ui/icon.js +122 -0
  171. package/dist/ui/index.d.ts +8 -1
  172. package/dist/ui/index.d.ts.map +1 -1
  173. package/dist/ui/index.js +351 -329
  174. package/dist/ui/input-otp.d.ts.map +1 -1
  175. package/dist/ui/input-otp.js +21 -20
  176. package/dist/ui/input.d.ts +32 -11
  177. package/dist/ui/input.d.ts.map +1 -1
  178. package/dist/ui/input.js +149 -44
  179. package/dist/ui/lib/motion.d.ts +2 -0
  180. package/dist/ui/lib/motion.d.ts.map +1 -1
  181. package/dist/ui/lib/motion.js +13 -11
  182. package/dist/ui/lib/utils.js +1 -1
  183. package/dist/ui/menubar.d.ts.map +1 -1
  184. package/dist/ui/menubar.js +87 -86
  185. package/dist/ui/navigation-menu.d.ts.map +1 -1
  186. package/dist/ui/navigation-menu.js +23 -28
  187. package/dist/ui/number-input.d.ts.map +1 -1
  188. package/dist/ui/number-input.js +54 -53
  189. package/dist/ui/pagination.d.ts.map +1 -1
  190. package/dist/ui/pagination.js +45 -44
  191. package/dist/ui/popover.js +28 -28
  192. package/dist/ui/progress.d.ts +3 -1
  193. package/dist/ui/progress.d.ts.map +1 -1
  194. package/dist/ui/progress.js +43 -39
  195. package/dist/ui/search-input.d.ts.map +1 -1
  196. package/dist/ui/search-input.js +47 -60
  197. package/dist/ui/segmented-control.js +1 -1
  198. package/dist/ui/select.d.ts.map +1 -1
  199. package/dist/ui/select.js +54 -53
  200. package/dist/ui/sheet.d.ts.map +1 -1
  201. package/dist/ui/sheet.js +46 -45
  202. package/dist/ui/sidebar.d.ts.map +1 -1
  203. package/dist/ui/sidebar.js +196 -193
  204. package/dist/ui/skeleton.js +1 -1
  205. package/dist/ui/spinner.js +74 -74
  206. package/dist/ui/stat-card.d.ts.map +1 -1
  207. package/dist/ui/stat-card.js +85 -86
  208. package/dist/ui/switch.d.ts +3 -0
  209. package/dist/ui/switch.d.ts.map +1 -1
  210. package/dist/ui/switch.js +41 -27
  211. package/dist/ui/tabs.js +43 -43
  212. package/dist/ui/text.js +1 -1
  213. package/dist/ui/textarea.js +10 -10
  214. package/dist/ui/toast.d.ts.map +1 -1
  215. package/dist/ui/toast.js +169 -169
  216. package/dist/ui/toggle.js +4 -4
  217. package/dist/ui/tooltip.js +40 -40
  218. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  219. package/docs/components/_header.md +4 -4
  220. package/docs/components/composed/activity-feed.md +7 -0
  221. package/docs/components/composed/avatar-group.md +8 -5
  222. package/docs/components/composed/status-badge.md +14 -1
  223. package/docs/components/ui/accordion.md +5 -2
  224. package/docs/components/ui/badge-group.md +38 -0
  225. package/docs/components/ui/badge-indicator.md +40 -0
  226. package/docs/components/ui/badge.md +36 -5
  227. package/docs/components/ui/button-processing.md +15 -0
  228. package/docs/components/ui/button.md +40 -11
  229. package/docs/components/ui/chat.md +214 -0
  230. package/docs/components/ui/data-table.md +3 -0
  231. package/docs/components/ui/devalok-grain.md +55 -0
  232. package/docs/components/ui/icon-button.md +12 -5
  233. package/docs/components/ui/icon-context.md +38 -0
  234. package/docs/components/ui/icon-group.md +36 -0
  235. package/docs/components/ui/icon.md +47 -0
  236. package/docs/components/ui/input.md +32 -6
  237. package/docs/components/ui/progress.md +5 -0
  238. package/docs/components/ui/spinner.md +3 -0
  239. package/docs/components/ui/switch.md +13 -0
  240. package/llms-full.txt +666 -40
  241. package/llms.txt +37 -18
  242. package/package.json +7 -2
@@ -0,0 +1,214 @@
1
+ # Chat
2
+
3
+ - Import: @devalok/shilp-sutra/ui/chat
4
+ - Server-safe: No (MessageList, Message, MessageInput, TypingIndicator use Framer Motion); DateSeparator and UnreadSeparator are server-safe
5
+ - Category: ui
6
+
7
+ Seven primitives for building chat interfaces: MessageList, Message (compound), SystemMessage, MessageInput, DateSeparator, UnreadSeparator, TypingIndicator.
8
+
9
+ ---
10
+
11
+ ## MessageList
12
+
13
+ Scrollable container with auto-scroll, load-more, empty state, and "N new" floating pill.
14
+
15
+ ### Props
16
+ autoScroll: boolean — auto-scroll to bottom on new content (default: true)
17
+ newMessageCount: number — count shown in floating pill (default: 0)
18
+ onScrollToBottom: () => void — called when user clicks the "N new" pill
19
+ onLoadMore: () => void — called when user scrolls near top
20
+ isLoadingMore: boolean — shows spinner at top (default: false)
21
+ emptySlot: ReactNode — content when there are no children
22
+ headerSlot: ReactNode — content above the scroll container (e.g. channel name)
23
+ scrollToBottomSlot: ReactNode — reserved slot for custom scroll-to-bottom button
24
+ children: ReactNode (REQUIRED)
25
+
26
+ ### Example
27
+ ```jsx
28
+ <MessageList autoScroll onLoadMore={loadMore} isLoadingMore={loading} newMessageCount={3} onScrollToBottom={markRead}>
29
+ {messages.map(m => <Message key={m.id}>...</Message>)}
30
+ </MessageList>
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Message (Compound)
36
+
37
+ Compound component: `Message`, `Message.Avatar`, `Message.Content`, `Message.Author`, `Message.Body`, `Message.EditableBody`, `Message.Reactions`, `Message.Actions`, `Message.Action`.
38
+
39
+ ### Message (root) Props
40
+ variant: "flat" | "bubble" (default: "flat")
41
+ placement: "start" | "end" (default: "start")
42
+ highlight: "mention" | "internal"
43
+ grouped: boolean — hides avatar/author for consecutive messages (default: false)
44
+ deleted: boolean — renders deleted placeholder (default: false)
45
+ deletedText: string (default: "This message was deleted")
46
+
47
+ ### Message.Avatar Props
48
+ src: string | null — avatar image URL
49
+ fallback: string — initials text
50
+ icon: ReactNode — custom icon instead of avatar
51
+ size: "sm" | "md" (default: "md")
52
+ children: ReactNode — fully custom avatar slot
53
+
54
+ ### Message.Author Props
55
+ name: string (REQUIRED)
56
+ badge: ReactNode
57
+ timestamp: Date
58
+ formattedTimestamp: string — pre-formatted timestamp (overrides timestamp)
59
+ timestampFormat: (date: Date) => string — custom formatter
60
+
61
+ ### Message.Body Props
62
+ children: ReactNode (REQUIRED)
63
+
64
+ ### Message.EditableBody Props
65
+ content: string (REQUIRED)
66
+ onSave: (newContent: string) => void (REQUIRED)
67
+ onCancel: () => void
68
+ canEdit: boolean (default: false)
69
+ renderContent: (content: string) => ReactNode — custom render for display mode
70
+
71
+ ### Message.Reactions Props
72
+ reactions: { emoji: string; count: number; reacted: boolean }[] (REQUIRED)
73
+ onReact: (emoji: string) => void (REQUIRED)
74
+
75
+ ### Message.Content Props
76
+ children: ReactNode (REQUIRED)
77
+ className: string
78
+
79
+ ### Message.Actions Props
80
+ children: ReactNode (REQUIRED)
81
+ delay: number — hover reveal delay in ms (default: 100)
82
+
83
+ ### Message.Action Props
84
+ icon: IconProps["icon"] (REQUIRED) — pass the Tabler component reference, e.g. `IconReply` (not `<IconReply />`)
85
+ label: string (REQUIRED)
86
+ onClick: () => void (REQUIRED)
87
+ variant: "default" | "danger" (default: "default")
88
+
89
+ ### Example
90
+ ```jsx
91
+ <Message variant="flat" highlight="mention">
92
+ <Message.Avatar src={user.photo} fallback="JD" />
93
+ <Message.Content>
94
+ <Message.Author name="Jane Doe" timestamp={new Date()} badge={<Badge>Admin</Badge>} />
95
+ <Message.Body>Hello, world!</Message.Body>
96
+ <Message.Reactions reactions={reactions} onReact={handleReact} />
97
+ <Message.Actions>
98
+ <Message.Action icon={IconReply} label="Reply" onClick={handleReply} />
99
+ <Message.Action icon={IconTrash} label="Delete" onClick={handleDelete} variant="danger" />
100
+ </Message.Actions>
101
+ </Message.Content>
102
+ </Message>
103
+ ```
104
+
105
+ ---
106
+
107
+ ## SystemMessage
108
+
109
+ Inline system event or alert message (e.g. "Alice joined the channel").
110
+
111
+ ### Props
112
+ icon: ReactNode — custom icon
113
+ timestamp: string — ISO timestamp string
114
+ variant: "event" | "alert" (default: "event")
115
+ children: ReactNode (REQUIRED)
116
+
117
+ ### Example
118
+ ```jsx
119
+ <SystemMessage>Alice joined the channel</SystemMessage>
120
+ <SystemMessage variant="alert" timestamp="2026-03-26T10:00:00Z">Connection lost</SystemMessage>
121
+ ```
122
+
123
+ ---
124
+
125
+ ## MessageInput
126
+
127
+ Auto-resizing textarea with send/stop buttons, streaming support, and slot-based extensibility.
128
+
129
+ ### Props
130
+ onSubmit: (text: string) => void (REQUIRED)
131
+ placeholder: string (default: "Type a message...")
132
+ disabled: boolean (default: false)
133
+ isStreaming: boolean — shows stop button instead of send (default: false)
134
+ onCancel: () => void — called when stop button is clicked
135
+ leadingSlot: ReactNode — content before the textarea (e.g. attachment button)
136
+ trailingSlot: ReactNode — content after the send button
137
+ disclaimer: string — centered text below the input (e.g. "AI can make mistakes")
138
+ sendIcon: ReactNode — custom send icon
139
+
140
+ ### Example
141
+ ```jsx
142
+ <MessageInput
143
+ onSubmit={handleSend}
144
+ isStreaming={streaming}
145
+ onCancel={handleStop}
146
+ disclaimer="AI can make mistakes"
147
+ />
148
+ ```
149
+
150
+ ---
151
+
152
+ ## DateSeparator
153
+
154
+ Horizontal rule with a formatted date label.
155
+
156
+ ### Props
157
+ date: Date | string (REQUIRED)
158
+ format: (date: Date) => string — custom date formatter
159
+ className: string
160
+
161
+ ### Example
162
+ ```jsx
163
+ <DateSeparator date={new Date()} />
164
+ <DateSeparator date="2026-03-25" format={(d) => d.toLocaleDateString()} />
165
+ ```
166
+
167
+ ---
168
+
169
+ ## UnreadSeparator
170
+
171
+ Accent-colored horizontal rule marking the unread boundary.
172
+
173
+ ### Props
174
+ label: string (default: "NEW")
175
+ count: number — prepended to label (e.g. "5 NEW")
176
+ className: string
177
+
178
+ ### Example
179
+ ```jsx
180
+ <UnreadSeparator />
181
+ <UnreadSeparator count={5} />
182
+ ```
183
+
184
+ ---
185
+
186
+ ## TypingIndicator
187
+
188
+ Animated bouncing dots with a text description of who is typing.
189
+
190
+ ### Props
191
+ users: { name: string; image?: string }[] (REQUIRED)
192
+ className: string
193
+
194
+ ### Example
195
+ ```jsx
196
+ <TypingIndicator users={[{ name: 'Alice' }]} />
197
+ <TypingIndicator users={[{ name: 'Alice' }, { name: 'Bob' }]} />
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Gotchas
203
+ - MessageList uses `role="log"` with `aria-live="polite"` — screen readers announce new messages
204
+ - Message entrance animations use Framer Motion springs — AnimatePresence wraps children in MessageList
205
+ - `grouped` hides avatar and author — use for consecutive messages from the same user
206
+ - MessageInput sends on Enter (Shift+Enter for newline) — textarea auto-resizes up to 160px
207
+ - TypingIndicator renders nothing when `users` is empty
208
+ - Message.Actions toolbar is hidden by default (opacity-0) — it reveals on hover of the parent Message root via `group-hover/message`. Only works when Actions is inside a Message root.
209
+ - Message.Content is the flex column wrapper for Author + Body — required for proper layout in flat variant
210
+ - DateSeparator's default formatter shows "Today", "Yesterday", or "Mon DD" / "Mon DD, YYYY"
211
+
212
+ ## Changes
213
+ ### v0.29.0
214
+ - **Added** Initial release — 7 chat primitives (MessageList, Message, SystemMessage, MessageInput, DateSeparator, UnreadSeparator, TypingIndicator)
@@ -65,6 +65,9 @@ import { DataTable } from '@devalok/shilp-sutra/ui/data-table'
65
65
  - Use defaultDensity="compact" for Karm-style h-9 rows
66
66
 
67
67
  ## Changes
68
+ ### v0.29.0
69
+ - **Fixed** Controlled selection infinite re-render loop — inline `getRowId` callback caused `onSelectionChange` effect to fire every render, creating a setState cycle with `selectedIds`. Now uses a stable ref for `getRowId`.
70
+
68
71
  ### v0.16.1
69
72
  - **Fixed** `serverPagination` object reference in `useCallback` dependency caused stale closure — now uses stable ref for `onPageChange`
70
73
  - **Fixed** `onSelectionChange` effect fired every render due to `table` in dependency array — now derives selected rows directly
@@ -0,0 +1,55 @@
1
+ # DevalokGrain
2
+
3
+ - Import: @devalok/shilp-sutra/ui/devalok-grain
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ ## Props
8
+ intensity: "subtle" | "medium" | "heavy" — grain intensity level
9
+ surface: "solid" | "soft" — affects noise opacity ('solid' for filled backgrounds, 'soft' for tinted/muted)
10
+ sheen: boolean — inner highlight (top-lit emboss) for premium 3D feel
11
+ animated: boolean — fade-in entrance animation on mount
12
+ hoverIntensify: boolean — increase grain visibility on parent hover (requires parent `group` class)
13
+ tint: string — CSS color for the directional gradient (e.g. "oklch(0.55 0.19 360)", "var(--color-accent-9)")
14
+
15
+ ## Defaults
16
+ intensity: "subtle"
17
+ surface: "solid"
18
+ sheen: false
19
+ animated: false
20
+ hoverIntensify: false
21
+ tint: undefined (no gradient, noise texture only)
22
+
23
+ ## Example
24
+ ```jsx
25
+ {/* Inside a Button (Button already has relative/overflow-hidden/isolate): */}
26
+ <Button>
27
+ <DevalokGrain />
28
+ Save changes
29
+ </Button>
30
+
31
+ {/* Inside a Card: */}
32
+ <Card className="relative overflow-hidden isolate">
33
+ <DevalokGrain surface="soft" />
34
+ Card content
35
+ </Card>
36
+
37
+ {/* Heavy grain with tint on a hero section: */}
38
+ <div className="relative overflow-hidden isolate rounded-ds-lg bg-accent-9 p-8">
39
+ <DevalokGrain intensity="heavy" tint="oklch(0.55 0.19 360)" />
40
+ <h1 className="relative z-[2]">Hero</h1>
41
+ </div>
42
+ ```
43
+
44
+ ## Gotchas
45
+ - Parent element MUST have `relative overflow-hidden isolate` for the grain to render correctly
46
+ - The grain layers are absolute-positioned at `z-[1]` — content that should appear above must use `z-[2]` or higher
47
+ - Uses `rounded-[inherit]` to match parent border-radius automatically
48
+ - Renders `aria-hidden="true"` — purely decorative
49
+ - Without `tint`, only the noise texture renders (no directional gradient)
50
+ - `hoverIntensify` requires the parent to have a `group` class for `group-hover:` to work
51
+ - Respects `prefers-reduced-motion` — entrance animation disabled when user prefers reduced motion
52
+
53
+ ## Changes
54
+ ### v0.29.0
55
+ - **Added** Initial release — brand noise texture with directional gradient, sheen, animation, and hover intensification
@@ -5,12 +5,12 @@
5
5
  - Category: ui
6
6
 
7
7
  ## Props
8
- icon: ReactNode (REQUIRED)
8
+ icon: ReactElement (REQUIRED — use <Icon icon={...} />)
9
9
  aria-label: string (REQUIRED — WCAG AA mandatory)
10
10
  shape: "square" | "circle"
11
11
  size: "sm" | "md" | "lg"
12
- variant: same as Button (solid, outline, ghost, link)
13
- color: same as Button (default, error)
12
+ variant: same as Button (solid, soft, outline, ghost, link)
13
+ color: same as Button (accent, error, success, warning, neutral)
14
14
  loading: boolean
15
15
  disabled: boolean
16
16
 
@@ -20,14 +20,21 @@
20
20
 
21
21
  ## Example
22
22
  ```jsx
23
- <IconButton icon={<IconEdit />} variant="ghost" aria-label="Edit item" />
24
- <IconButton icon={<IconX />} shape="circle" variant="ghost" size="sm" aria-label="Close" />
23
+ <IconButton icon={<Icon icon={IconEdit} />} variant="ghost" aria-label="Edit item" />
24
+ <IconButton icon={<Icon icon={IconX} />} shape="circle" variant="ghost" size="sm" aria-label="Close" />
25
+ <IconButton icon={<Icon icon={IconTrash} />} variant="solid" color="error" aria-label="Delete" />
25
26
  ```
26
27
 
27
28
  ## Gotchas
28
29
  - aria-label is enforced by TypeScript — you MUST provide it
29
30
  - Prefer IconButton over Button with size="icon-*" for icon-only buttons
31
+ - `icon` prop should use `<Icon icon={...} />` wrapper (auto-sized via Button's IconProvider)
30
32
 
31
33
  ## Changes
34
+ ### v0.29.0
35
+ - **Changed** `icon` prop now expects `<Icon icon={...} />` wrapper (auto-sized via Button's IconProvider context)
36
+ - **Changed** Inherits all new Button v2 colors: `accent`, `error`, `success`, `warning`, `neutral` (was `default`/`error` only)
37
+ - **Changed** Inherits Button v2 variants including new `soft` variant
38
+
32
39
  ### v0.1.0
33
40
  - **Added** Initial release
@@ -0,0 +1,38 @@
1
+ # IconContext
2
+
3
+ - Import: @devalok/shilp-sutra/ui (barrel export)
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ ## Exports
8
+ IconContext — React.Context<IconContextValue>
9
+ IconProvider — Provider component (props: size?, stroke?, children)
10
+ useIconContext() — Hook returning { size?, stroke? }
11
+ IconSize — Type: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
12
+ IconStroke — Type: "light" | "regular" | "bold"
13
+
14
+ ## IconProvider Props
15
+ size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
16
+ stroke: "light" | "regular" | "bold"
17
+ children: ReactNode (REQUIRED)
18
+
19
+ ## Example
20
+ ```jsx
21
+ import { IconProvider, useIconContext } from '@devalok/shilp-sutra/ui'
22
+
23
+ <IconProvider size="sm" stroke="bold">
24
+ <MyCustomIconComponent />
25
+ </IconProvider>
26
+
27
+ // Inside MyCustomIconComponent:
28
+ const { size, stroke } = useIconContext()
29
+ ```
30
+
31
+ ## Gotchas
32
+ - Used internally by IconGroup and Button to propagate icon sizing to children
33
+ - If no provider is present, `useIconContext()` returns `{}` (empty object) — consumers should fall back to defaults
34
+ - Value is memoized — safe for frequent re-renders
35
+
36
+ ## Changes
37
+ ### v0.29.0
38
+ - **Added** Initial release — React context for propagating icon size and stroke weight
@@ -0,0 +1,36 @@
1
+ # IconGroup
2
+
3
+ - Import: @devalok/shilp-sutra/ui (barrel export)
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ ## Props
8
+ size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" — propagated to children via IconContext
9
+ stroke: "light" | "regular" | "bold" — propagated to children via IconContext
10
+ gap: "tight" | "default" | "loose" — flex gap between icons
11
+ label: string — accessible label (used as aria-label when role="toolbar")
12
+ role: "toolbar" — optional, set for toolbar patterns
13
+ className: string
14
+ children: ReactNode (REQUIRED)
15
+
16
+ ## Defaults
17
+ gap: "default"
18
+ role: undefined (no ARIA role)
19
+
20
+ ## Example
21
+ ```jsx
22
+ <IconGroup size="sm" gap="tight" role="toolbar" label="Formatting">
23
+ <Icon icon={IconBold} label="Bold" />
24
+ <Icon icon={IconItalic} label="Italic" />
25
+ <Icon icon={IconUnderline} label="Underline" />
26
+ </IconGroup>
27
+ ```
28
+
29
+ ## Gotchas
30
+ - Wraps children in an IconProvider — all child Icons inherit size/stroke from the group
31
+ - `label` is only applied as `aria-label` when `role="toolbar"` is set
32
+ - Gap values: tight=2px, default=4px, loose=8px
33
+
34
+ ## Changes
35
+ ### v0.29.0
36
+ - **Added** Initial release — icon grouping with shared context, toolbar ARIA support
@@ -0,0 +1,47 @@
1
+ # Icon
2
+
3
+ - Import: @devalok/shilp-sutra/ui (barrel export)
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ ## Props
8
+ icon: ForwardRefExoticComponent (REQUIRED — Tabler icon or any ForwardRef SVG icon component)
9
+ size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" — reads from IconContext if not set
10
+ stroke: "light" | "regular" | "bold" — reads from IconContext if not set
11
+ label: string — accessible label (renders <title> + sets aria-label; without it, icon is aria-hidden)
12
+ animate: "spin" | "pulse" | "bounce" | "draw" | "none" | { rotate?: number; scale?: number }
13
+ state: "idle" | "loading" | "success" | "error" — delegates to Spinner (bare variant)
14
+ className: string
15
+
16
+ ## Defaults
17
+ size: "md" (from context or fallback)
18
+ stroke: "regular" (from context or fallback)
19
+ state: undefined (no state machine)
20
+ animate: undefined (static render)
21
+
22
+ ## Example
23
+ ```jsx
24
+ <Icon icon={IconPlus} />
25
+ <Icon icon={IconPlus} size="xs" stroke="light" />
26
+ <Icon icon={IconPlus} label="Add item" />
27
+ <Icon icon={IconPlus} animate="spin" />
28
+ <Icon icon={IconCheck} animate="draw" />
29
+ <Icon icon={IconPlus} state="loading" />
30
+ <Icon icon={IconPlus} state="success" />
31
+ ```
32
+
33
+ ## Gotchas
34
+ - Without `label`, the icon renders `aria-hidden="true"` (decorative)
35
+ - With `label`, the icon renders `role="img"` with `aria-label` and a `<title>` element
36
+ - **Priority rule:** If both `state` and `animate` are set, `state` wins
37
+ - `state="loading"` renders a bare Spinner; `state="success"` / `state="error"` render animated checkmark/cross
38
+ - Size tiers map to pixel values: xs=14, sm=16, md=18, lg=20, xl=24, 2xl=32
39
+ - Stroke weight varies by size tier (lighter strokes on smaller icons)
40
+ - Reads size/stroke from IconContext (provided by Button, IconGroup, etc.); explicit props override context
41
+ - `animate="draw"` works with IconCheck, IconX, and CircleCheck only — other icons fall back to static render
42
+ - Respects `prefers-reduced-motion` — animations disabled when user prefers reduced motion
43
+
44
+ ## Changes
45
+ ### v0.29.0
46
+ - **Added** Initial release — context-aware Icon wrapper with size tiers, stroke weights, accessibility, animations, state machine
47
+ - **Added** `animate="draw"` — SVG path-draw animation using `pathLength`. Draws check/X strokes progressively (0.35s easeOut). Respects `prefers-reduced-motion`.
@@ -5,10 +5,17 @@
5
5
  - Category: ui
6
6
 
7
7
  ## Props
8
- size: "sm" | "md" | "lg"
8
+ size: "xs" | "sm" | "md" | "lg"
9
9
  state: InputState
10
- startIcon: ReactNode
11
- endIcon: ReactNode
10
+ startSection: ReactNode (icon or content in the leading slot)
11
+ endSection: ReactNode (icon or content in the trailing slot)
12
+ startSectionClickable: boolean (enables pointer events on start section)
13
+ endSectionClickable: boolean (enables pointer events on end section)
14
+ startSectionType: 'icon' | 'label' (section display type — auto-inferred from content)
15
+ endSectionType: 'icon' | 'label' (section display type — auto-inferred from content)
16
+ wrapperClassName: string (classes for the wrapper div — border, bg, ring)
17
+ startIcon: ReactNode (@deprecated — use startSection)
18
+ endIcon: ReactNode (@deprecated — use endSection)
12
19
  (plus all standard HTML input attributes except native "size")
13
20
 
14
21
  ## Types
@@ -19,17 +26,36 @@
19
26
 
20
27
  ## Example
21
28
  ```jsx
22
- <Input type="email" placeholder="you@example.com" state="error" startIcon={<IconMail />} />
29
+ <Input type="email" placeholder="you@example.com" state="error" startSection={<Icon icon={IconMail} />} />
30
+ <Input size="xs" placeholder="Quick search" startSection={<Icon icon={IconSearch} />} />
31
+ <Input startSection="https://" startSectionType="label" placeholder="example.com" />
32
+ <Input endSection=".00" endSectionType="label" startSection={<Icon icon={IconCurrencyDollar} />} placeholder="0" />
23
33
  ```
24
34
 
25
35
  ## Gotchas
26
36
  - HTML native "size" attribute is excluded — use CSS width instead
27
37
  - state="error" sets aria-invalid automatically
28
38
  - Inside FormField: auto-inherits state, aria-describedby, aria-required from context (explicit props override)
29
- - Resting border is border-subtle (soft); focus ring is `ring-1 ring-accent-7` (v0.12.0)
30
- - All sizes (sm, md, lg) use text-ds-md (14px) font size only affects height and padding (v0.15.0)
39
+ - `className` targets the `<input>` element; use `wrapperClassName` for border/bg/ring overrides
40
+ - Focus ring is on the wrapper container (focus-within), not the input itself
41
+ - Icons in startSection/endSection are auto-sized via IconProvider per input size
42
+ - Sections are `pointer-events-none` by default — set `startSectionClickable`/`endSectionClickable` for interactive sections
43
+ - Section type is auto-inferred: strings default to `'label'` (tinted bg + border), React elements default to `'icon'` (fixed-width centered). Override with `startSectionType`/`endSectionType`.
31
44
 
32
45
  ## Changes
46
+ ### v0.29.0
47
+ - **Changed** v2 rewrite: container-first architecture with wrapper div holding focus ring
48
+ - **Added** `xs` size (28px height)
49
+ - **Added** `startSection` / `endSection` props replacing `startIcon` / `endIcon` (deprecated but still work)
50
+ - **Added** `startSectionClickable` / `endSectionClickable` props for interactive sections
51
+ - **Added** `wrapperClassName` prop for styling the wrapper div (border, bg, ring)
52
+ - **Changed** Focus ring now on wrapper via `focus-within` (container-level ring, not input-level)
53
+ - **Changed** Icons auto-sized via `IconProvider` context per input size
54
+ - **Deprecated** `startIcon` / `endIcon` — use `startSection` / `endSection`
55
+ - **Added** `startSectionType` / `endSectionType` props — `'icon'` (fixed-width centered cell) or `'label'` (tinted background with border separator). Auto-inferred from content type (strings → label, React elements → icon).
56
+ - **Changed** Sections use flexbox layout for consistent alignment
57
+ - **Deprecated** `inputVariants` export — use `inputWrapperVariants` (semantics changed to target wrapper)
58
+
33
59
  ### v0.15.0
34
60
  - **Changed** `lg` size font changed from `text-ds-lg` (18px) to `text-ds-md` (14px) — all input sizes now use 14px for consistency
35
61
  - **Changed** `md` size font standardized to `text-ds-md` (14px) from mixed values
@@ -8,6 +8,7 @@
8
8
  value: number (0-100) — omit for indeterminate
9
9
  size: "sm" | "md" | "lg" (track height)
10
10
  color: "default" | "success" | "warning" | "error" (indicator color)
11
+ autoColor: boolean (auto-shifts color by value: 0-59=default, 60-84=warning, 85-100=success, >100=error)
11
12
  showLabel: boolean (shows percentage text)
12
13
  indicatorClassName: string
13
14
 
@@ -23,7 +24,11 @@
23
24
 
24
25
  ## Gotchas
25
26
  - Omit value (or pass undefined) for indeterminate animation
27
+ - `autoColor` overrides `color` when `value` is set — do not pass both unless you want autoColor to win
26
28
 
27
29
  ## Changes
30
+ ### v0.29.0
31
+ - **Added** `autoColor` prop — automatically shifts indicator color based on value thresholds (0-59 default, 60-84 warning, 85-100 success, >100 error)
32
+
28
33
  ### v0.1.0
29
34
  - **Added** Initial release with `size`, `color`, `indeterminate` variants and optional label slot
@@ -32,6 +32,9 @@
32
32
  - No longer server-safe as of v0.18.0 (uses Framer Motion)
33
33
 
34
34
  ## Changes
35
+ ### v0.29.0
36
+ - **Changed** `bare` variant spinning state now uses `currentColor` instead of `var(--color-accent-9)` — inherits text color from parent for seamless embedding in buttons/toolbars
37
+
35
38
  ### v0.18.0
36
39
  - **Changed** (BREAKING) Complete rewrite with Framer Motion arc animation and state transitions
37
40
  - **Added** `state` prop: 'spinning' | 'success' | 'error'
@@ -9,16 +9,29 @@
9
9
  onCheckedChange: (checked: boolean) => void
10
10
  error: boolean (shows red border/bg)
11
11
  disabled: boolean
12
+ size: "sm" | "md" | "lg"
13
+ color: "accent" | "success" | "warning"
14
+ thumbIcon: ReactNode (icon rendered inside the thumb)
15
+
16
+ ## Defaults
17
+ size="md", color="accent"
12
18
 
13
19
  ## Example
14
20
  ```jsx
15
21
  <Switch checked={enabled} onCheckedChange={setEnabled} />
22
+ <Switch size="lg" color="success" thumbIcon={<IconCheck size={14} />} />
16
23
  ```
17
24
 
18
25
  ## Gotchas
19
26
  - Use error prop for validation states (matches Checkbox API)
27
+ - `error` overrides `color` — when error is true, checked state always uses error-9
20
28
 
21
29
  ## Changes
30
+ ### v0.29.0
31
+ - **Added** `size` prop: `"sm"` (18px track) | `"md"` (24px, default) | `"lg"` (28px track)
32
+ - **Added** `color` prop: `"accent"` (default) | `"success"` | `"warning"` for checked-state color
33
+ - **Added** `thumbIcon` prop — renders any ReactNode inside the thumb circle (e.g., check icon)
34
+
22
35
  ### v0.18.0
23
36
  - **Changed** Migrated to Framer Motion spring thumb animation
24
37
  - **Fixed** Added visible border on unchecked state (`border-surface-border-strong`) — was borderless, making unchecked state hard to see