@devalok/shilp-sutra 0.47.0 → 0.49.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 (228) hide show
  1. package/AGENTS.md +36 -12
  2. package/BREAKING.json +78 -0
  3. package/MIGRATION.md +891 -846
  4. package/dist/_chunks/badge-group.js +50 -63
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chat.js +1 -1
  7. package/dist/_chunks/chat.js.map +1 -1
  8. package/dist/_chunks/emoji-suggestion.js +124 -0
  9. package/dist/_chunks/emoji-suggestion.js.map +1 -0
  10. package/dist/_chunks/emoji.js +1115 -0
  11. package/dist/_chunks/emoji.js.map +1 -0
  12. package/dist/_chunks/field-state.js +8 -0
  13. package/dist/_chunks/field-state.js.map +1 -0
  14. package/dist/_chunks/popover.js +50 -47
  15. package/dist/_chunks/popover.js.map +1 -1
  16. package/dist/_chunks/primitives.js +155 -155
  17. package/dist/_chunks/primitives.js.map +1 -1
  18. package/dist/_chunks/shared.js +4 -4
  19. package/dist/_chunks/tiptap.js +10 -10
  20. package/dist/_chunks/tiptap.js.map +1 -1
  21. package/dist/_chunks/use-calendar.js +1 -1
  22. package/dist/_chunks/use-calendar.js.map +1 -1
  23. package/dist/_chunks/use-controllable-open.js +15 -0
  24. package/dist/_chunks/use-controllable-open.js.map +1 -0
  25. package/dist/composed/command-palette.js +3 -3
  26. package/dist/composed/command-palette.js.map +1 -1
  27. package/dist/composed/confirm-dialog.js +3 -3
  28. package/dist/composed/confirm-dialog.js.map +1 -1
  29. package/dist/composed/date-picker/index.js +3 -3
  30. package/dist/composed/date-picker/index.js.map +1 -1
  31. package/dist/composed/emoji-picker.d.ts +19 -9
  32. package/dist/composed/emoji-picker.d.ts.map +1 -1
  33. package/dist/composed/emoji-picker.js +87 -68
  34. package/dist/composed/emoji-picker.js.map +1 -1
  35. package/dist/composed/error-boundary.js +1 -1
  36. package/dist/composed/error-boundary.js.map +1 -1
  37. package/dist/composed/extensions/emoji-data.d.ts +1 -14
  38. package/dist/composed/extensions/emoji-data.d.ts.map +1 -1
  39. package/dist/composed/extensions/emoji-node.d.ts +0 -3
  40. package/dist/composed/extensions/emoji-node.d.ts.map +1 -1
  41. package/dist/composed/extensions/emoji-node.js +9 -34
  42. package/dist/composed/extensions/emoji-node.js.map +1 -1
  43. package/dist/composed/extensions/emoji-suggestion.d.ts +2 -2
  44. package/dist/composed/extensions/emoji-suggestion.d.ts.map +1 -1
  45. package/dist/composed/extensions/emoji-suggestion.js +2 -116
  46. package/dist/composed/index.d.ts +3 -1
  47. package/dist/composed/index.d.ts.map +1 -1
  48. package/dist/composed/index.js +4 -3
  49. package/dist/composed/loading-skeleton.js +15 -15
  50. package/dist/composed/loading-skeleton.js.map +1 -1
  51. package/dist/composed/page-header.d.ts.map +1 -1
  52. package/dist/composed/page-header.js +32 -45
  53. package/dist/composed/page-header.js.map +1 -1
  54. package/dist/composed/page-skeletons.js +19 -19
  55. package/dist/composed/page-skeletons.js.map +1 -1
  56. package/dist/composed/responsive-modal.d.ts +39 -0
  57. package/dist/composed/responsive-modal.d.ts.map +1 -0
  58. package/dist/composed/responsive-modal.js +212 -0
  59. package/dist/composed/responsive-modal.js.map +1 -0
  60. package/dist/composed/rich-chat-input.d.ts.map +1 -1
  61. package/dist/composed/rich-chat-input.js +558 -579
  62. package/dist/composed/rich-chat-input.js.map +1 -1
  63. package/dist/composed/rich-text-editor.d.ts.map +1 -1
  64. package/dist/composed/rich-text-editor.js +167 -190
  65. package/dist/composed/rich-text-editor.js.map +1 -1
  66. package/dist/composed/schedule-view.d.ts +1 -1
  67. package/dist/composed/schedule-view.d.ts.map +1 -1
  68. package/dist/composed/schedule-view.js +48 -54
  69. package/dist/composed/schedule-view.js.map +1 -1
  70. package/dist/composed/status-badge.d.ts +13 -11
  71. package/dist/composed/status-badge.d.ts.map +1 -1
  72. package/dist/composed/status-badge.js +54 -130
  73. package/dist/composed/status-badge.js.map +1 -1
  74. package/dist/shell/bottom-navbar.js +1 -1
  75. package/dist/shell/bottom-navbar.js.map +1 -1
  76. package/dist/shell/top-bar.js +1 -1
  77. package/dist/shell/top-bar.js.map +1 -1
  78. package/dist/tokens/semantic.css +8 -1
  79. package/dist/ui/accordion.js +9 -9
  80. package/dist/ui/alert-dialog.js +26 -26
  81. package/dist/ui/aspect-ratio.js +1 -1
  82. package/dist/ui/autocomplete.js +7 -7
  83. package/dist/ui/avatar.d.ts.map +1 -1
  84. package/dist/ui/avatar.js +87 -82
  85. package/dist/ui/avatar.js.map +1 -1
  86. package/dist/ui/badge.d.ts.map +1 -1
  87. package/dist/ui/breadcrumb.d.ts +0 -1
  88. package/dist/ui/breadcrumb.d.ts.map +1 -1
  89. package/dist/ui/breadcrumb.js +58 -35
  90. package/dist/ui/breadcrumb.js.map +1 -1
  91. package/dist/ui/button.js +3 -3
  92. package/dist/ui/checkbox.d.ts +4 -2
  93. package/dist/ui/checkbox.d.ts.map +1 -1
  94. package/dist/ui/checkbox.js +33 -28
  95. package/dist/ui/checkbox.js.map +1 -1
  96. package/dist/ui/collapsible.js +4 -4
  97. package/dist/ui/combobox.d.ts +3 -0
  98. package/dist/ui/combobox.d.ts.map +1 -1
  99. package/dist/ui/combobox.js +137 -132
  100. package/dist/ui/combobox.js.map +1 -1
  101. package/dist/ui/context-menu.js +46 -46
  102. package/dist/ui/dialog.d.ts.map +1 -1
  103. package/dist/ui/dialog.js +53 -50
  104. package/dist/ui/dialog.js.map +1 -1
  105. package/dist/ui/dot.d.ts +38 -0
  106. package/dist/ui/dot.d.ts.map +1 -0
  107. package/dist/ui/dot.js +92 -0
  108. package/dist/ui/dot.js.map +1 -0
  109. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  110. package/dist/ui/dropdown-menu.js +70 -65
  111. package/dist/ui/dropdown-menu.js.map +1 -1
  112. package/dist/ui/hover-card.js +11 -11
  113. package/dist/ui/index.d.ts +3 -2
  114. package/dist/ui/index.d.ts.map +1 -1
  115. package/dist/ui/index.js +67 -67
  116. package/dist/ui/index.js.map +1 -1
  117. package/dist/ui/input-otp.js +1 -1
  118. package/dist/ui/input-otp.js.map +1 -1
  119. package/dist/ui/input.d.ts +4 -2
  120. package/dist/ui/input.d.ts.map +1 -1
  121. package/dist/ui/input.js +38 -37
  122. package/dist/ui/input.js.map +1 -1
  123. package/dist/ui/label.js +1 -1
  124. package/dist/ui/lib/field-state.d.ts +21 -0
  125. package/dist/ui/lib/field-state.d.ts.map +1 -0
  126. package/dist/ui/lib/use-controllable-open.d.ts +32 -0
  127. package/dist/ui/lib/use-controllable-open.d.ts.map +1 -0
  128. package/dist/ui/link.js +1 -1
  129. package/dist/ui/number-input.d.ts +4 -2
  130. package/dist/ui/number-input.d.ts.map +1 -1
  131. package/dist/ui/number-input.js +51 -50
  132. package/dist/ui/number-input.js.map +1 -1
  133. package/dist/ui/pagination.js +1 -1
  134. package/dist/ui/popover.d.ts.map +1 -1
  135. package/dist/ui/progress.d.ts +66 -42
  136. package/dist/ui/progress.d.ts.map +1 -1
  137. package/dist/ui/progress.js +144 -40
  138. package/dist/ui/progress.js.map +1 -1
  139. package/dist/ui/radio.d.ts +6 -2
  140. package/dist/ui/radio.d.ts.map +1 -1
  141. package/dist/ui/radio.js +44 -33
  142. package/dist/ui/radio.js.map +1 -1
  143. package/dist/ui/select.d.ts +1 -1
  144. package/dist/ui/select.d.ts.map +1 -1
  145. package/dist/ui/select.js +58 -57
  146. package/dist/ui/select.js.map +1 -1
  147. package/dist/ui/separator.js +2 -2
  148. package/dist/ui/separator.js.map +1 -1
  149. package/dist/ui/sheet.d.ts.map +1 -1
  150. package/dist/ui/sheet.js +59 -56
  151. package/dist/ui/sheet.js.map +1 -1
  152. package/dist/ui/sidebar.js +5 -5
  153. package/dist/ui/sidebar.js.map +1 -1
  154. package/dist/ui/slider.js +6 -6
  155. package/dist/ui/slider.js.map +1 -1
  156. package/dist/ui/stat-card.d.ts.map +1 -1
  157. package/dist/ui/stat-card.js +122 -125
  158. package/dist/ui/stat-card.js.map +1 -1
  159. package/dist/ui/surface.js +1 -1
  160. package/dist/ui/switch.d.ts +3 -1
  161. package/dist/ui/switch.d.ts.map +1 -1
  162. package/dist/ui/switch.js +32 -27
  163. package/dist/ui/switch.js.map +1 -1
  164. package/dist/ui/textarea.d.ts +3 -3
  165. package/dist/ui/textarea.d.ts.map +1 -1
  166. package/dist/ui/textarea.js +18 -17
  167. package/dist/ui/textarea.js.map +1 -1
  168. package/dist/ui/toast.js +2 -2
  169. package/dist/ui/toast.js.map +1 -1
  170. package/dist/ui/toggle-group.js +1 -1
  171. package/dist/ui/toggle.js +1 -1
  172. package/dist/ui/tooltip.d.ts.map +1 -1
  173. package/dist/ui/tooltip.js +36 -33
  174. package/dist/ui/tooltip.js.map +1 -1
  175. package/docs/components/ai/ai-command-provider.md +46 -0
  176. package/docs/components/ai/block-renderer.md +59 -0
  177. package/docs/components/ai/command-bar.md +78 -0
  178. package/docs/components/ai/conversation.md +59 -0
  179. package/docs/components/ai/devadoot-icon.md +41 -0
  180. package/docs/components/composed/emoji-picker.md +19 -17
  181. package/docs/components/composed/page-header.md +1 -1
  182. package/docs/components/composed/responsive-modal.md +66 -0
  183. package/docs/components/composed/rich-text-editor.md +1 -1
  184. package/docs/components/composed/schedule-view.md +6 -2
  185. package/docs/components/ui/breadcrumb.md +1 -1
  186. package/docs/components/ui/checkbox.md +4 -1
  187. package/docs/components/ui/combobox.md +4 -0
  188. package/docs/components/ui/dot.md +61 -0
  189. package/docs/components/ui/progress.md +54 -16
  190. package/docs/components/ui/radio.md +6 -2
  191. package/docs/components/ui/select.md +9 -5
  192. package/docs/components/ui/switch.md +4 -1
  193. package/docs/components/ui/table-row-link.md +1 -1
  194. package/docs/components/ui/table.md +2 -1
  195. package/docs/recipes/index.md +1 -1
  196. package/docs/recipes/install-astro.md +15 -12
  197. package/docs/recipes/install-next-app-router.md +20 -12
  198. package/docs/recipes/install-next-pages.md +3 -1
  199. package/docs/recipes/install-remix.md +16 -13
  200. package/docs/recipes/install-tanstack-start.md +19 -12
  201. package/docs/recipes/install-vite.md +18 -15
  202. package/docs/recipes/troubleshoot.md +7 -8
  203. package/llms.txt +12 -4
  204. package/make-kit/components/form.md +2 -2
  205. package/make-kit/components/icon.md +2 -2
  206. package/make-kit/components/overview.md +2 -2
  207. package/make-kit/components/select.md +1 -1
  208. package/make-kit/components/table.md +1 -1
  209. package/mcp-manifest.json +2696 -1145
  210. package/mcp-manifest.schema.json +18 -0
  211. package/package.json +16 -14
  212. package/skill/SKILL.md +1 -1
  213. package/skill/references/components.md +12 -4
  214. package/skill/references/setup-astro.md +15 -12
  215. package/skill/references/setup-next-app-router.md +20 -12
  216. package/skill/references/setup-next-pages.md +3 -1
  217. package/skill/references/setup-remix.md +16 -13
  218. package/skill/references/setup-tanstack-start.md +19 -12
  219. package/skill/references/setup-vite.md +18 -15
  220. package/skill/references/troubleshoot.md +7 -8
  221. package/dist/_chunks/emoji-data.js +0 -45
  222. package/dist/_chunks/emoji-data.js.map +0 -1
  223. package/dist/composed/extensions/emoji-suggestion.js.map +0 -1
  224. package/dist/ui/status-dot.d.ts +0 -27
  225. package/dist/ui/status-dot.d.ts.map +0 -1
  226. package/dist/ui/status-dot.js +0 -68
  227. package/dist/ui/status-dot.js.map +0 -1
  228. package/docs/components/ui/status-dot.md +0 -35
package/mcp-manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./mcp-manifest.schema.json",
3
- "manifestVersion": "1.1.0",
3
+ "manifestVersion": "1.2.0",
4
4
  "package": "@devalok/shilp-sutra",
5
- "packageVersion": "0.47.0",
5
+ "packageVersion": "0.49.0",
6
6
  "components": {
7
7
  "accordion": {
8
8
  "displayName": "Accordion",
@@ -1106,7 +1106,7 @@
1106
1106
  "displayName": "Breadcrumb",
1107
1107
  "tier": "ui",
1108
1108
  "import": "@devalok/shilp-sutra/ui/breadcrumb",
1109
- "serverSafe": false,
1109
+ "serverSafe": true,
1110
1110
  "description": "",
1111
1111
  "props": {},
1112
1112
  "composition": {
@@ -1617,28 +1617,6 @@
1617
1617
  },
1618
1618
  "required": false,
1619
1619
  "description": "enables hover shadow lift + pointer cursor"
1620
- },
1621
- "placement": {
1622
- "type": {
1623
- "name": "union",
1624
- "raw": "\"top-right\" (default) | \"top-left\" | \"bottom-right\" | \"bottom-left\""
1625
- },
1626
- "required": false
1627
- },
1628
- "tuck": {
1629
- "type": {
1630
- "name": "boolean"
1631
- },
1632
- "required": false,
1633
- "description": "pull a step toward the corner so an icon button's glyph aligns to the content edge"
1634
- },
1635
- "side": {
1636
- "type": {
1637
- "name": "union",
1638
- "raw": "\"x\" (default) | \"top\" | \"bottom\" | \"y\" | \"all\""
1639
- },
1640
- "required": false,
1641
- "description": "which card padding to negate; top/bottom/y for direct children — inherit the card radius; x/all for content inside a slot"
1642
1620
  }
1643
1621
  },
1644
1622
  "composition": {
@@ -1702,6 +1680,38 @@
1702
1680
  "size": "md",
1703
1681
  "orientation": "vertical"
1704
1682
  },
1683
+ "subComponents": {
1684
+ "CardAction": {
1685
+ "props": {
1686
+ "placement": {
1687
+ "type": {
1688
+ "name": "union",
1689
+ "raw": "\"top-right\" (default) | \"top-left\" | \"bottom-right\" | \"bottom-left\""
1690
+ },
1691
+ "required": false
1692
+ },
1693
+ "tuck": {
1694
+ "type": {
1695
+ "name": "boolean"
1696
+ },
1697
+ "required": false,
1698
+ "description": "pull a step toward the corner so an icon button's glyph aligns to the content edge"
1699
+ }
1700
+ }
1701
+ },
1702
+ "CardBleed": {
1703
+ "props": {
1704
+ "side": {
1705
+ "type": {
1706
+ "name": "union",
1707
+ "raw": "\"x\" (default) | \"top\" | \"bottom\" | \"y\" | \"all\""
1708
+ },
1709
+ "required": false,
1710
+ "description": "which card padding to negate; top/bottom/y for direct children — inherit the card radius; x/all for content inside a slot"
1711
+ }
1712
+ }
1713
+ }
1714
+ },
1705
1715
  "examples": [
1706
1716
  "<Card variant=\"elevated\" interactive onClick={() => navigate(url)}>\n <CardHeader>\n <CardTitle>Project</CardTitle>\n <CardDescription>Last updated 2h ago</CardDescription>\n </CardHeader>\n <CardContent><p>Content here</p></CardContent>\n</Card>"
1707
1717
  ],
@@ -1782,15 +1792,10 @@
1782
1792
  }
1783
1793
  ],
1784
1794
  "peers": [
1785
- "d3-array",
1786
1795
  "d3-axis",
1787
- "d3-format",
1788
- "d3-interpolate",
1789
1796
  "d3-scale",
1790
1797
  "d3-selection",
1791
- "d3-shape",
1792
- "d3-time-format",
1793
- "d3-transition"
1798
+ "d3-shape"
1794
1799
  ]
1795
1800
  },
1796
1801
  "chat": {
@@ -1862,12 +1867,18 @@
1862
1867
  "required": false,
1863
1868
  "defaultValue": "md"
1864
1869
  },
1865
- "error": {
1870
+ "state": {
1866
1871
  "type": {
1867
- "name": "boolean"
1872
+ "name": "enum",
1873
+ "value": [
1874
+ "default",
1875
+ "error",
1876
+ "warning",
1877
+ "success"
1878
+ ]
1868
1879
  },
1869
1880
  "required": false,
1870
- "description": "shows red border"
1881
+ "description": "validation border/bg tint; error sets aria-invalid. Inherited from FormField when omitted"
1871
1882
  },
1872
1883
  "indeterminate": {
1873
1884
  "type": {
@@ -1903,6 +1914,10 @@
1903
1914
  "WCAG 2.5.8 minimum target size met at md (24px); sm (20px) may fail if not paired with enough label hit area"
1904
1915
  ],
1905
1916
  "changes": [
1917
+ {
1918
+ "version": "0.49.0",
1919
+ "summary": "**BREAKING** Removed the `error: boolean` prop; use `state` (`FieldState = \"default\" | \"error\" | \"warning\" | \"success\"`). Migrate `<Checkbox error />` → `<Checkbox state=\"error\" />`. Gains `warning`/`success` tints and now inherits state from `FormField`."
1920
+ },
1906
1921
  {
1907
1922
  "version": "0.22.0",
1908
1923
  "summary": "**Changed** Check indicator animation from scale-bounce to path-draw (stroke draws progressively). Indeterminate dash also draws in."
@@ -2278,6 +2293,19 @@
2278
2293
  "description": "trigger height",
2279
2294
  "defaultValue": "md"
2280
2295
  },
2296
+ "state": {
2297
+ "type": {
2298
+ "name": "enum",
2299
+ "value": [
2300
+ "default",
2301
+ "error",
2302
+ "warning",
2303
+ "success"
2304
+ ]
2305
+ },
2306
+ "required": false,
2307
+ "description": "validation border tint; error sets aria-invalid. Inherited from FormField when omitted"
2308
+ },
2281
2309
  "Multiple": {
2282
2310
  "type": {
2283
2311
  "name": "function",
@@ -2377,6 +2405,10 @@
2377
2405
  "Dropdown content is portalled to document.body — parent styles like `overflow: hidden` don't clip it, and container-scoped test queries won't find it"
2378
2406
  ],
2379
2407
  "changes": [
2408
+ {
2409
+ "version": "0.49.0",
2410
+ "summary": "**Added** `state` prop (`FieldState = \"default\" | \"error\" | \"warning\" | \"success\"`) — unified field-state API. Renders a validation border tint + sets `aria-invalid`; inherits from `FormField` when omitted. (Additive — Combobox had no prior validation prop.)"
2411
+ },
2380
2412
  {
2381
2413
  "version": "0.18.0",
2382
2414
  "summary": "**Added** `accessibleLabel` prop — custom aria-label for trigger, falls back to placeholder"
@@ -3018,8 +3050,7 @@
3018
3050
  }
3019
3051
  ],
3020
3052
  "peers": [
3021
- "@tanstack/react-table",
3022
- "@tanstack/react-virtual"
3053
+ "@tanstack/react-table"
3023
3054
  ]
3024
3055
  },
3025
3056
  "devalok-grain": {
@@ -3177,6 +3208,130 @@
3177
3208
  }
3178
3209
  ]
3179
3210
  },
3211
+ "dot": {
3212
+ "displayName": "Dot",
3213
+ "tier": "ui",
3214
+ "import": "@devalok/shilp-sutra/ui/dot",
3215
+ "serverSafe": false,
3216
+ "description": "A small semantic status/indicator dot — the low-level primitive behind status pills, presence indicators, legend swatches, and `StatusDot`. Intent-coloured, sized, optionally pulsing, filled or ring.",
3217
+ "props": {
3218
+ "color": {
3219
+ "type": {
3220
+ "name": "enum",
3221
+ "value": [
3222
+ "accent",
3223
+ "success",
3224
+ "warning",
3225
+ "error",
3226
+ "info",
3227
+ "neutral",
3228
+ "current"
3229
+ ]
3230
+ },
3231
+ "required": false,
3232
+ "description": "intent colour; `current` inherits text colour"
3233
+ },
3234
+ "size": {
3235
+ "type": {
3236
+ "name": "enum",
3237
+ "value": [
3238
+ "xs",
3239
+ "sm",
3240
+ "md",
3241
+ "lg"
3242
+ ]
3243
+ },
3244
+ "required": false
3245
+ },
3246
+ "variant": {
3247
+ "type": {
3248
+ "name": "enum",
3249
+ "value": [
3250
+ "filled",
3251
+ "ring",
3252
+ "off"
3253
+ ]
3254
+ },
3255
+ "required": false,
3256
+ "description": "`off` = faint fill + light border, i.e. inactive"
3257
+ },
3258
+ "withBorder": {
3259
+ "type": {
3260
+ "name": "boolean"
3261
+ },
3262
+ "required": false,
3263
+ "description": "contrast ring so the dot stays visible on busy/coloured backgrounds"
3264
+ },
3265
+ "pulse": {
3266
+ "type": {
3267
+ "name": "boolean"
3268
+ },
3269
+ "required": false,
3270
+ "description": "animate a pulsing ripple; ignored for `off`"
3271
+ },
3272
+ "pulseSpeed": {
3273
+ "type": {
3274
+ "name": "enum",
3275
+ "value": [
3276
+ "slow",
3277
+ "normal",
3278
+ "fast"
3279
+ ]
3280
+ },
3281
+ "required": false,
3282
+ "description": "pulse tempo"
3283
+ },
3284
+ "label": {
3285
+ "type": {
3286
+ "name": "ReactNode"
3287
+ },
3288
+ "required": false,
3289
+ "description": "inline text; makes the dot an announced status"
3290
+ },
3291
+ "labelPosition": {
3292
+ "type": {
3293
+ "name": "enum",
3294
+ "value": [
3295
+ "start",
3296
+ "end"
3297
+ ]
3298
+ },
3299
+ "required": false,
3300
+ "description": "which side the label sits on"
3301
+ },
3302
+ "labelClassName": {
3303
+ "type": {
3304
+ "name": "string"
3305
+ },
3306
+ "required": false
3307
+ }
3308
+ },
3309
+ "composition": {
3310
+ "notes": [
3311
+ "**Decorative vs announced.** A bare `<Dot>` is `aria-hidden` (the surrounding element carries meaning — e.g. a Badge's text). Pass a `label` (or `aria-label`) to make it a `role=\"status\"` announced indicator.",
3312
+ "**Intent colour, shared vocabulary.** `color` uses the same intent names as the rest of the system (`accent/success/warning/error/info/neutral`), so a Dot next to a Badge/Button of the same intent matches.",
3313
+ "**`pulse` = \"live\".** Off by default (static status). Turn it on for active/attention states (recording, live, connecting) — a pulsing dot reads as \"happening now\", so leave it off for settled statuses.",
3314
+ "**Powers the higher-level pieces.** `StatusBadge` composes `<Badge>` + `<Dot>`; use `Dot` directly anywhere you need a coloured indicator without a pill.",
3315
+ "**Three treatments:** `filled` (active), `ring` (hollow outline), `off` (faint same-tone fill + light border — present but inactive/disabled).",
3316
+ "**`withBorder`** adds a contrast ring (`ring-2 ring-surface-raised`) so the dot reads on avatars, images, or coloured fills — the pattern Avatar's status dot uses.",
3317
+ "**`pulseSpeed`** (slow/normal/fast) tunes the pulse tempo — fast for urgent (recording), slow for ambient (syncing)."
3318
+ ]
3319
+ },
3320
+ "docPath": "docs/components/ui/dot.md",
3321
+ "examples": [
3322
+ "<Dot color=\"success\" /> {/* bare, decorative */}\n<Dot color=\"error\" pulse pulseSpeed=\"fast\" label=\"Recording\" /> {/* pulsing + announced */}\n<Dot color=\"neutral\" variant=\"off\" label=\"Offline\" /> {/* inactive: faint fill + light border */}\n<Dot color=\"success\" withBorder /> {/* contrast ring for busy backgrounds */}\n<Dot color=\"accent\" label=\"3 online\" labelPosition=\"start\" /> {/* label before the dot */}\n<Dot color=\"neutral\" variant=\"ring\" size=\"lg\" /> {/* hollow ring */}\n\n// As leading content in a pill:\n<Badge variant=\"soft\" color=\"warning\" startIcon={<Dot color=\"warning\" size=\"sm\" />}>\n Pending\n</Badge>"
3323
+ ],
3324
+ "gotchas": [
3325
+ "A bare dot is decorative by design — if a dot is the *only* signal (no adjacent text), give it a `label` or `aria-label` so it's announced.",
3326
+ "`pulse` respects `prefers-reduced-motion` (the ripple is disabled)."
3327
+ ],
3328
+ "changes": [
3329
+ {
3330
+ "version": "0.49.0",
3331
+ "summary": "**Added** Initial release. Extracted as the shared primitive behind `StatusDot`, `StatusBadge`, and `Badge`'s dot. Colours `accent/success/warning/error/info/neutral/current`; sizes `xs–lg`; variants `filled/ring/off`; `withBorder` contrast ring; `pulse` + `pulseSpeed`; `label` + `labelPosition`."
3332
+ }
3333
+ ]
3334
+ },
3180
3335
  "dropdown-menu": {
3181
3336
  "displayName": "DropdownMenu",
3182
3337
  "tier": "ui",
@@ -3378,7 +3533,7 @@
3378
3533
  ]
3379
3534
  },
3380
3535
  "required": false,
3381
- "description": "inherits from FormField context"
3536
+ "defaultValue": "helper"
3382
3537
  },
3383
3538
  "helperTextId": {
3384
3539
  "type": {
@@ -3402,6 +3557,25 @@
3402
3557
  ]
3403
3558
  },
3404
3559
  "docPath": "docs/components/ui/form.md",
3560
+ "subComponents": {
3561
+ "FormHelperText": {
3562
+ "props": {
3563
+ "state": {
3564
+ "type": {
3565
+ "name": "enum",
3566
+ "value": [
3567
+ "helper",
3568
+ "error",
3569
+ "warning",
3570
+ "success"
3571
+ ]
3572
+ },
3573
+ "required": false,
3574
+ "description": "inherits from FormField context"
3575
+ }
3576
+ }
3577
+ }
3578
+ },
3405
3579
  "examples": [
3406
3580
  "<FormField state=\"error\">\n <Label htmlFor=\"email\">Email</Label>\n <Input id=\"email\" state=\"error\" />\n <FormHelperText>Please enter a valid email.</FormHelperText>\n</FormField>"
3407
3581
  ],
@@ -3997,13 +4171,6 @@
3997
4171
  },
3998
4172
  "required": false,
3999
4173
  "description": "on the outer group container — separate from inner input's className"
4000
- },
4001
- "index": {
4002
- "type": {
4003
- "name": "object",
4004
- "raw": "number (REQUIRED, 0-based) — which position this slot renders"
4005
- },
4006
- "required": false
4007
4174
  }
4008
4175
  },
4009
4176
  "composition": {
@@ -4036,6 +4203,19 @@
4036
4203
  "size": "md",
4037
4204
  "state": "default"
4038
4205
  },
4206
+ "subComponents": {
4207
+ "InputOTPSlot": {
4208
+ "props": {
4209
+ "index": {
4210
+ "type": {
4211
+ "name": "object",
4212
+ "raw": "number (REQUIRED, 0-based) — which position this slot renders"
4213
+ },
4214
+ "required": false
4215
+ }
4216
+ }
4217
+ }
4218
+ },
4039
4219
  "examples": [
4040
4220
  "<InputOTP maxLength={6} onComplete={verifyCode}>\n <InputOTPGroup>\n <InputOTPSlot index={0} />\n <InputOTPSlot index={1} />\n <InputOTPSlot index={2} />\n </InputOTPGroup>\n <InputOTPSeparator />\n <InputOTPGroup>\n <InputOTPSlot index={3} />\n <InputOTPSlot index={4} />\n <InputOTPSlot index={5} />\n </InputOTPGroup>\n</InputOTP>"
4041
4221
  ],
@@ -4561,15 +4741,22 @@
4561
4741
  "tier": "ui",
4562
4742
  "import": "@devalok/shilp-sutra/ui/progress",
4563
4743
  "serverSafe": false,
4564
- "description": "",
4744
+ "description": "A linear progress bar. Use the smart all-in-one `<Progress value={70} />` for the common cases, or the compound parts (`Progress.Root` / `Track` / `Indicator` / `Segment` / `Label` / `Value`) for full layout control and multi-segment bars.",
4565
4745
  "props": {
4566
4746
  "value": {
4567
4747
  "type": {
4568
- "name": "object",
4569
- "raw": "number (0-100) — omit for indeterminate"
4748
+ "name": "union",
4749
+ "raw": "number | null (0–max) — omit or null for an indeterminate bar"
4570
4750
  },
4571
4751
  "required": false
4572
4752
  },
4753
+ "max": {
4754
+ "type": {
4755
+ "name": "number"
4756
+ },
4757
+ "required": false,
4758
+ "description": "scale maximum, default 100"
4759
+ },
4573
4760
  "size": {
4574
4761
  "type": {
4575
4762
  "name": "enum",
@@ -4586,7 +4773,7 @@
4586
4773
  "type": {
4587
4774
  "name": "enum",
4588
4775
  "value": [
4589
- "default",
4776
+ "accent",
4590
4777
  "success",
4591
4778
  "warning",
4592
4779
  "error"
@@ -4600,43 +4787,103 @@
4600
4787
  "name": "boolean"
4601
4788
  },
4602
4789
  "required": false,
4603
- "description": "auto-shifts color by value: 0-59=default, 60-84=warning, 85-100=success, >100=error"
4790
+ "description": "auto-shift color by value: 0-59=accent, 60-84=warning, 85-100=success, >100=error"
4791
+ },
4792
+ "label": {
4793
+ "type": {
4794
+ "name": "ReactNode"
4795
+ },
4796
+ "required": false,
4797
+ "description": "descriptive label rendered before the bar; names the bar for a11y"
4604
4798
  },
4605
- "showLabel": {
4799
+ "showValue": {
4606
4800
  "type": {
4607
4801
  "name": "boolean"
4608
4802
  },
4609
4803
  "required": false,
4610
- "description": "shows percentage text"
4804
+ "description": "shows the \"{n}%\" readout after the bar"
4805
+ },
4806
+ "segments": {
4807
+ "type": {
4808
+ "name": "union",
4809
+ "raw": "{ value: number; color?: \"accent\" | \"success\" | \"warning\" | \"error\" }[]"
4810
+ },
4811
+ "required": false,
4812
+ "description": "multi-segment bar; overrides the single indicator"
4813
+ },
4814
+ "trackClassName": {
4815
+ "type": {
4816
+ "name": "string"
4817
+ },
4818
+ "required": false,
4819
+ "description": "class for the Track element"
4611
4820
  },
4612
4821
  "indicatorClassName": {
4613
4822
  "type": {
4614
4823
  "name": "string"
4615
4824
  },
4616
- "required": false
4825
+ "required": false,
4826
+ "description": "class for the single Indicator; ignored when segments set"
4617
4827
  }
4618
4828
  },
4619
4829
  "composition": {
4620
4830
  "notes": [
4621
- "**Radix Progress** underneath `value` (determinate) or absent (indeterminate). Standard ARIA: role=progressbar, aria-valuenow/min/max.",
4622
- "**autoColor semantic signal:** Maps value thresholds to color so consumers don't have to manually compute: 0–59=default, 60–84=warning, 85–100=success, >100=error. Useful for storage meters, budget trackers, goal progress.",
4623
- "**Indeterminate:** Omit `value` to get a continuous animated indeterminate bar. Use for unknown-duration loads.",
4624
- "**Progress vs ProgressRing:** Progress is a linear bar (horizontal). ProgressRing is circular. ProgressRing offers multi-ring stacked variants; Progress doesn't.",
4625
- "**Inside Card/StatCard:** StatCard has a `progress` prop that renders a thin inline version use that inside StatCards instead of a separate Progress."
4831
+ "**Two APIs, one component.** The smart `<Progress>` composes the parts for you; reach for the compound parts when you need a custom layout (label above the bar, value inside, multiple bars) or multi-segment fills. Structure follows Ark UI / Chakra; `Progress.Segment` follows Mantine.",
4832
+ "**`Progress.Track` is the accessible progressbar** (role=progressbar, aria-valuenow/min/max from `Root`'s value). Give it a name via `aria-label`, or a `Progress.Label` + matching `aria-labelledby`. The smart form wires this from the `label` prop / a passed `aria-label` automatically.",
4833
+ "**autoColor semantic signal:** maps value thresholds to color (0–59 accent · 60–84 warning · 85–100 success · >100 error) — storage meters, budget trackers, goal progress. Pass an explicit `color` to opt out.",
4834
+ "**Segments** render side-by-side, each `value` as a % of `max`; the Track's aria value still reflects `Root`'s `value`.",
4835
+ "**Indeterminate:** omit `value` (or pass `null`) for the continuous sweep. Motion-reduced users get a static bar.",
4836
+ "**Progress vs ProgressRing:** Progress is linear; `ProgressRing` is circular (with multi-ring stacked variants)."
4837
+ ],
4838
+ "parts": [
4839
+ {
4840
+ "name": "Progress",
4841
+ "description": "smart all-in-one — value/size/color/label/showValue/autoColor/segments"
4842
+ },
4843
+ {
4844
+ "name": "Progress.Root",
4845
+ "description": "layout container + context; owns value/max/size"
4846
+ },
4847
+ {
4848
+ "name": "Progress.Label",
4849
+ "description": "descriptive label; give it id + point Track's aria-labelledby at it"
4850
+ },
4851
+ {
4852
+ "name": "Progress.Track",
4853
+ "description": "the aria progressbar + track visual; holds Indicator or Segments"
4854
+ },
4855
+ {
4856
+ "name": "Progress.Indicator",
4857
+ "description": "single fill; color, or auto-color by value"
4858
+ },
4859
+ {
4860
+ "name": "Progress.Segment",
4861
+ "description": "one slice of a multi-segment bar — value + color"
4862
+ },
4863
+ {
4864
+ "name": "Progress.Value",
4865
+ "description": "the \"{n}%\" readout; custom via children or a `format` fn"
4866
+ }
4626
4867
  ]
4627
4868
  },
4628
4869
  "docPath": "docs/components/ui/progress.md",
4629
4870
  "examples": [
4630
- "<Progress value={75} color=\"success\" showLabel />\n<Progress size=\"sm\" /> {/* indeterminate */}"
4871
+ "// Simple:\n<Progress value={75} color=\"success\" showValue />\n<Progress size=\"sm\" /> {/* indeterminate */}\n<Progress value={80} autoColor showValue /> {/* color follows value */}\n\n// Multi-segment (Mantine-style):\n<Progress segments={[{ value: 40, color: 'success' }, { value: 30, color: 'warning' }]} />\n\n// Compound — full control:\n<Progress.Root value={62} size=\"lg\">\n <Progress.Label id=\"storage-lbl\">Storage</Progress.Label>\n <Progress.Track aria-labelledby=\"storage-lbl\">\n <Progress.Indicator color=\"warning\" />\n </Progress.Track>\n <Progress.Value format={(pct) => `${pct}% of 50 GB`} />\n</Progress.Root>"
4631
4872
  ],
4632
4873
  "gotchas": [
4633
- "Omit value (or pass undefined) for indeterminate animation",
4634
- "`autoColor` overrides `color` when `value` is set — do not pass both unless you want autoColor to win"
4874
+ "Omit `value` (or pass `null`) for indeterminate.",
4875
+ "Pass an explicit `color` to override `autoColor`.",
4876
+ "Compound `Progress.Track` needs a name — an `aria-label`, or a `Progress.Label` whose `id` the Track's `aria-labelledby` points to. A Track with neither is an unnamed progressbar (axe will flag it).",
4877
+ "`Progress.Indicator` / `Segment` / `Value` throw if rendered outside `Progress.Root`."
4635
4878
  ],
4636
4879
  "changes": [
4880
+ {
4881
+ "version": "0.49.0",
4882
+ "summary": "**BREAKING** Progress redesigned as a compound component. Renamed `showLabel` → `showValue`. The `color` neutral value `\"default\"` → `\"accent\"` (the type is now `\"accent\" | \"success\" | \"warning\" | \"error\"`). Added compound parts (`Progress.Root/Track/Indicator/Segment/Label/Value`), a `label` prop, a `max` prop, a `segments` prop (multi-segment bars), and `trackClassName`. Migrate `showLabel` → `showValue` and `color=\"default\"` → `color=\"accent\"` (or drop it — accent is the default)."
4883
+ },
4637
4884
  {
4638
4885
  "version": "0.29.0",
4639
- "summary": "**Added** `autoColor` prop — automatically shifts indicator color based on value thresholds (0-59 default, 60-84 warning, 85-100 success, >100 error)"
4886
+ "summary": "**Added** `autoColor` prop — automatically shifts indicator color based on value thresholds"
4640
4887
  },
4641
4888
  {
4642
4889
  "version": "0.1.0",
@@ -4706,13 +4953,6 @@
4706
4953
  },
4707
4954
  "required": false,
4708
4955
  "description": "accessible label — falls back to \"{n}% progress\""
4709
- },
4710
- "rings": {
4711
- "type": {
4712
- "name": "union",
4713
- "raw": "Array<{ value: number; max?: number; color?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\"; label?: string }>"
4714
- },
4715
- "required": false
4716
4956
  }
4717
4957
  },
4718
4958
  "composition": {
@@ -4731,6 +4971,30 @@
4731
4971
  "color": "default",
4732
4972
  "showValue": "{false}"
4733
4973
  },
4974
+ "subComponents": {
4975
+ "MultiProgressRing": {
4976
+ "props": {
4977
+ "rings": {
4978
+ "type": {
4979
+ "name": "union",
4980
+ "raw": "Array<{ value: number; max?: number; color?: \"default\" | \"success\" | \"warning\" | \"error\" | \"info\"; label?: string }>"
4981
+ },
4982
+ "required": false
4983
+ },
4984
+ "size": {
4985
+ "type": {
4986
+ "name": "enum",
4987
+ "value": [
4988
+ "sm",
4989
+ "md",
4990
+ "lg"
4991
+ ]
4992
+ },
4993
+ "required": false
4994
+ }
4995
+ }
4996
+ }
4997
+ },
4734
4998
  "examples": [
4735
4999
  "<ProgressRing value={75} />\n<ProgressRing value={3} max={12} size=\"lg\" color=\"warning\" showValue />\n\n<MultiProgressRing\n rings={[\n { value: 80, color: 'error', label: 'Move' },\n { value: 60, color: 'success', label: 'Exercise' },\n ]}\n size=\"lg\"\n/>"
4736
5000
  ],
@@ -4752,7 +5016,7 @@
4752
5016
  "name": "string"
4753
5017
  },
4754
5018
  "required": false,
4755
- "description": "REQUIRED — what's selected when this item is checked"
5019
+ "description": "controlled"
4756
5020
  },
4757
5021
  "onValueChange": {
4758
5022
  "type": {
@@ -4772,7 +5036,7 @@
4772
5036
  "name": "boolean"
4773
5037
  },
4774
5038
  "required": false,
4775
- "description": "item-level override"
5039
+ "description": "propagates to all items"
4776
5040
  },
4777
5041
  "orientation": {
4778
5042
  "type": {
@@ -4791,17 +5055,18 @@
4791
5055
  "required": false,
4792
5056
  "description": "form name for all items"
4793
5057
  },
4794
- "size": {
5058
+ "state": {
4795
5059
  "type": {
4796
5060
  "name": "enum",
4797
5061
  "value": [
4798
- "sm",
4799
- "md",
4800
- "lg"
5062
+ "default",
5063
+ "error",
5064
+ "warning",
5065
+ "success"
4801
5066
  ]
4802
5067
  },
4803
5068
  "required": false,
4804
- "defaultValue": "md"
5069
+ "description": "validation; sets aria-invalid on the group + tints item borders. Inherited from FormField when omitted"
4805
5070
  }
4806
5071
  },
4807
5072
  "composition": {
@@ -4810,7 +5075,7 @@
4810
5075
  "**RadioGroup propagates** `disabled` to every RadioGroupItem; items can opt back in with `disabled={false}` for granular control (rare).",
4811
5076
  "**Labels:** RadioGroupItem has no intrinsic label — pair each with `<Label htmlFor=\"x\" />` + `<RadioGroupItem id=\"x\" value=\"...\" />`. Screen readers announce the group label (from FormField or aria-labelledby on RadioGroup) plus each item's label.",
4812
5077
  "**Form libraries:** RadioGroup works with react-hook-form via Controller (onValueChange maps to field.onChange). The `name` prop puts a hidden form input per item for native form serialization.",
4813
- "**FormField integration:** RadioGroup does NOT auto-consume FormField error state. For error visuals, style the RadioGroup surround (e.g. via aria-invalid on a wrapping fieldset) individual radios don't show red borders the way Inputs do."
5078
+ "**FormField integration:** RadioGroup now consumes FormField state (or set `state` explicitly). It sets `aria-invalid` on the group and tints each item's border to matchunified with the other form controls via the shared `FieldState` type. An explicit `state` prop wins over FormField context."
4814
5079
  ],
4815
5080
  "parts": [
4816
5081
  {
@@ -4827,15 +5092,50 @@
4827
5092
  "defaults": {
4828
5093
  "size": "md"
4829
5094
  },
5095
+ "subComponents": {
5096
+ "RadioGroupItem": {
5097
+ "props": {
5098
+ "value": {
5099
+ "type": {
5100
+ "name": "string"
5101
+ },
5102
+ "required": false,
5103
+ "description": "REQUIRED — what's selected when this item is checked"
5104
+ },
5105
+ "size": {
5106
+ "type": {
5107
+ "name": "enum",
5108
+ "value": [
5109
+ "sm",
5110
+ "md",
5111
+ "lg"
5112
+ ]
5113
+ },
5114
+ "required": false
5115
+ },
5116
+ "disabled": {
5117
+ "type": {
5118
+ "name": "boolean"
5119
+ },
5120
+ "required": false,
5121
+ "description": "item-level override"
5122
+ }
5123
+ }
5124
+ }
5125
+ },
4830
5126
  "examples": [
4831
5127
  "<RadioGroup defaultValue=\"option-1\" onValueChange={setValue}>\n <div className=\"flex items-center gap-2\">\n <RadioGroupItem value=\"option-1\" id=\"r1\" />\n <Label htmlFor=\"r1\">Option 1</Label>\n </div>\n <div className=\"flex items-center gap-2\">\n <RadioGroupItem value=\"option-2\" id=\"r2\" />\n <Label htmlFor=\"r2\">Option 2</Label>\n </div>\n</RadioGroup>"
4832
5128
  ],
4833
5129
  "gotchas": [
4834
5130
  "Each RadioGroupItem needs a unique `value` prop",
4835
5131
  "Pair each item with a Label for accessibility",
4836
- "RadioGroup does NOT auto-inherit FormField error state handle error styling at the group level"
5132
+ "RadioGroup inherits FormField state; pass `state` explicitly to override"
4837
5133
  ],
4838
5134
  "changes": [
5135
+ {
5136
+ "version": "0.49.0",
5137
+ "summary": "**Added** `state` prop on RadioGroup (`FieldState = \"default\" | \"error\" | \"warning\" | \"success\"`) — unified field-state API. Sets `aria-invalid` + tints item borders, and now inherits from `FormField` context."
5138
+ },
4839
5139
  {
4840
5140
  "version": "0.4.2",
4841
5141
  "summary": "**Added** `RadioGroupProps`, `RadioGroupItemProps` type exports"
@@ -5030,65 +5330,25 @@
5030
5330
  "import": "@devalok/shilp-sutra/ui/select",
5031
5331
  "serverSafe": false,
5032
5332
  "description": "",
5033
- "props": {
5034
- "variant": {
5035
- "type": {
5036
- "name": "enum",
5037
- "value": [
5038
- "default",
5039
- "outline",
5040
- "ghost"
5041
- ]
5042
- },
5043
- "required": false,
5044
- "defaultValue": "default"
5045
- },
5046
- "color": {
5047
- "type": {
5048
- "name": "enum",
5049
- "value": [
5050
- "default",
5051
- "error",
5052
- "success",
5053
- "warning"
5054
- ]
5055
- },
5056
- "required": false,
5057
- "description": "sets aria-invalid when error",
5058
- "defaultValue": "default"
5059
- },
5060
- "size": {
5061
- "type": {
5062
- "name": "enum",
5063
- "value": [
5064
- "xs",
5065
- "sm",
5066
- "md",
5067
- "lg"
5068
- ]
5069
- },
5070
- "required": false,
5071
- "defaultValue": "md"
5072
- }
5073
- },
5074
- "composition": {
5075
- "notes": [
5076
- "**Radix Select** underneath — `value`/`onValueChange`/`defaultValue`/`open`/`onOpenChange` standard state.",
5077
- "**Styling props live on SelectTrigger, not Select root.** The Select root owns value/state; the Trigger owns appearance (variant/color/size). Setting `<Select size=\"lg\">` silently does nothing — TypeScript won't catch it.",
5078
- "**SelectItem requires `value`** — unique within the Select. Labels are the children of SelectItem.",
5079
- "**SelectGroup + SelectLabel:** Organize options into sections with a non-interactive section heading.",
5080
- "**FormField integration:** Set `color=\"error\"` on SelectTrigger for error visuals. Not auto-consumed from FormField (same as Checkbox/Radio — form-library convention for select controls).",
5081
- "**Portal + z-popover (1400):** content portals to body, stacks above Dialog/Sheet/other overlays.",
5082
- "**Select vs Combobox vs Autocomplete:** Select = short fixed list, click-to-open, no typeahead. Combobox = searchable, forced selection. Autocomplete = searchable, free text. Pick by list size and search need."
5083
- ],
5084
- "parts": [
5085
- {
5086
- "name": "Select",
5087
- "description": "root — value, onValueChange, defaultValue"
5333
+ "props": {},
5334
+ "composition": {
5335
+ "notes": [
5336
+ "**Radix Select** underneath — `value`/`onValueChange`/`defaultValue`/`open`/`onOpenChange` standard state.",
5337
+ "**Styling props live on SelectTrigger, not Select root.** The Select root owns value/state; the Trigger owns appearance (variant/state/size). Setting `<Select size=\"lg\">` silently does nothing — TypeScript won't catch it.",
5338
+ "**SelectItem requires `value`** — unique within the Select. Labels are the children of SelectItem.",
5339
+ "**SelectGroup + SelectLabel:** Organize options into sections with a non-interactive section heading.",
5340
+ "**FormField integration:** Set `state=\"error\"` on SelectTrigger for error visuals, or omit it inside a `<FormField state=\"error\">` — SelectTrigger now inherits the field state from context (explicit `state` prop wins). Unified with Input/Textarea/Checkbox/Radio/Switch/Combobox via the shared `FieldState` type.",
5341
+ "**Portal + z-popover (1400):** content portals to body, stacks above Dialog/Sheet/other overlays.",
5342
+ "**Select vs Combobox vs Autocomplete:** Select = short fixed list, click-to-open, no typeahead. Combobox = searchable, forced selection. Autocomplete = searchable, free text. Pick by list size and search need."
5343
+ ],
5344
+ "parts": [
5345
+ {
5346
+ "name": "Select",
5347
+ "description": "root — value, onValueChange, defaultValue"
5088
5348
  },
5089
5349
  {
5090
5350
  "name": "SelectTrigger",
5091
- "description": "variant/color/size go HERE, not on Select root"
5351
+ "description": "variant/state/size go HERE, not on Select root"
5092
5352
  },
5093
5353
  {
5094
5354
  "name": "SelectValue",
@@ -5117,9 +5377,51 @@
5117
5377
  "docPath": "docs/components/ui/select.md",
5118
5378
  "defaults": {
5119
5379
  "variant": "default",
5120
- "color": "default",
5380
+ "state": "default",
5121
5381
  "size": "md"
5122
5382
  },
5383
+ "subComponents": {
5384
+ "SelectTrigger": {
5385
+ "props": {
5386
+ "variant": {
5387
+ "type": {
5388
+ "name": "enum",
5389
+ "value": [
5390
+ "default",
5391
+ "outline",
5392
+ "ghost"
5393
+ ]
5394
+ },
5395
+ "required": false
5396
+ },
5397
+ "state": {
5398
+ "type": {
5399
+ "name": "enum",
5400
+ "value": [
5401
+ "default",
5402
+ "error",
5403
+ "warning",
5404
+ "success"
5405
+ ]
5406
+ },
5407
+ "required": false,
5408
+ "description": "validation; sets aria-invalid when error. Inherited from FormField when omitted"
5409
+ },
5410
+ "size": {
5411
+ "type": {
5412
+ "name": "enum",
5413
+ "value": [
5414
+ "xs",
5415
+ "sm",
5416
+ "md",
5417
+ "lg"
5418
+ ]
5419
+ },
5420
+ "required": false
5421
+ }
5422
+ }
5423
+ }
5424
+ },
5123
5425
  "examples": [
5124
5426
  "<Select onValueChange={setValue}>\n <SelectTrigger size=\"lg\">\n <SelectValue placeholder=\"Choose...\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"a\">Option A</SelectItem>\n <SelectItem value=\"b\">Option B</SelectItem>\n </SelectContent>\n</Select>"
5125
5427
  ],
@@ -5128,6 +5430,10 @@
5128
5430
  "`<Select size=\"lg\">` is silently ignored (no TypeScript error)"
5129
5431
  ],
5130
5432
  "changes": [
5433
+ {
5434
+ "version": "0.49.0",
5435
+ "summary": "**BREAKING** Renamed the SelectTrigger `color` prop → `state` (unified field-state API across all form controls; type `FieldState = \"default\" | \"error\" | \"warning\" | \"success\"`). Migrate `<SelectTrigger color=\"error\">` → `<SelectTrigger state=\"error\">`."
5436
+ },
5131
5437
  {
5132
5438
  "version": "0.31.0",
5133
5439
  "summary": "**Added** `variant` prop on SelectTrigger: `default | outline | ghost`"
@@ -5210,21 +5516,7 @@
5210
5516
  "import": "@devalok/shilp-sutra/ui/sheet",
5211
5517
  "serverSafe": false,
5212
5518
  "description": "",
5213
- "props": {
5214
- "side": {
5215
- "type": {
5216
- "name": "enum",
5217
- "value": [
5218
- "top",
5219
- "bottom",
5220
- "left",
5221
- "right"
5222
- ]
5223
- },
5224
- "required": false,
5225
- "defaultValue": "right"
5226
- }
5227
- },
5519
+ "props": {},
5228
5520
  "composition": {
5229
5521
  "notes": [
5230
5522
  "Same primitives as Dialog — open/onOpenChange/defaultOpen, trigger asChild, portal rendering, focus trap.",
@@ -5265,6 +5557,24 @@
5265
5557
  "defaults": {
5266
5558
  "side": "right"
5267
5559
  },
5560
+ "subComponents": {
5561
+ "SheetContent": {
5562
+ "props": {
5563
+ "side": {
5564
+ "type": {
5565
+ "name": "enum",
5566
+ "value": [
5567
+ "top",
5568
+ "bottom",
5569
+ "left",
5570
+ "right"
5571
+ ]
5572
+ },
5573
+ "required": false
5574
+ }
5575
+ }
5576
+ }
5577
+ },
5268
5578
  "examples": [
5269
5579
  "<Sheet>\n <SheetTrigger asChild><Button>Open</Button></SheetTrigger>\n <SheetContent side=\"right\">\n <SheetHeader>\n <SheetTitle>Settings</SheetTitle>\n </SheetHeader>\n <div>Content</div>\n </SheetContent>\n</Sheet>"
5270
5580
  ],
@@ -5457,77 +5767,6 @@
5457
5767
  },
5458
5768
  "required": false,
5459
5769
  "defaultValue": "pulse"
5460
- },
5461
- "size": {
5462
- "type": {
5463
- "name": "enum",
5464
- "value": [
5465
- "sm",
5466
- "md",
5467
- "lg"
5468
- ]
5469
- },
5470
- "required": false,
5471
- "defaultValue": "md"
5472
- },
5473
- "lines": {
5474
- "type": {
5475
- "name": "number"
5476
- },
5477
- "required": false,
5478
- "defaultValue": 3
5479
- },
5480
- "lastLineWidth": {
5481
- "type": {
5482
- "name": "enum",
5483
- "value": [
5484
- "full",
5485
- "three-quarter",
5486
- "half"
5487
- ]
5488
- },
5489
- "required": false,
5490
- "defaultValue": "three-quarter"
5491
- },
5492
- "spacing": {
5493
- "type": {
5494
- "name": "enum",
5495
- "value": [
5496
- "sm",
5497
- "md"
5498
- ]
5499
- },
5500
- "required": false,
5501
- "defaultValue": "md"
5502
- },
5503
- "width": {
5504
- "type": {
5505
- "name": "string"
5506
- },
5507
- "required": false,
5508
- "defaultValue": "w-full"
5509
- },
5510
- "bars": {
5511
- "type": {
5512
- "name": "number"
5513
- },
5514
- "required": false,
5515
- "defaultValue": 7
5516
- },
5517
- "height": {
5518
- "type": {
5519
- "name": "string"
5520
- },
5521
- "required": false,
5522
- "defaultValue": "h-40"
5523
- },
5524
- "label": {
5525
- "type": {
5526
- "name": "object",
5527
- "raw": "string (default: \"Loading\") — accessible label for the loading state"
5528
- },
5529
- "required": false,
5530
- "defaultValue": "Loading"
5531
5770
  }
5532
5771
  },
5533
5772
  "composition": {
@@ -5552,6 +5791,212 @@
5552
5791
  "height": "h-40",
5553
5792
  "label": "Loading"
5554
5793
  },
5794
+ "subComponents": {
5795
+ "SkeletonAvatar": {
5796
+ "props": {
5797
+ "size": {
5798
+ "type": {
5799
+ "name": "enum",
5800
+ "value": [
5801
+ "sm",
5802
+ "md",
5803
+ "lg",
5804
+ "xl"
5805
+ ]
5806
+ },
5807
+ "required": false
5808
+ },
5809
+ "animation": {
5810
+ "type": {
5811
+ "name": "enum",
5812
+ "value": [
5813
+ "pulse",
5814
+ "shimmer",
5815
+ "none"
5816
+ ]
5817
+ },
5818
+ "required": false
5819
+ }
5820
+ }
5821
+ },
5822
+ "SkeletonText": {
5823
+ "props": {
5824
+ "lines": {
5825
+ "type": {
5826
+ "name": "number"
5827
+ },
5828
+ "required": false,
5829
+ "defaultValue": 3
5830
+ },
5831
+ "lastLineWidth": {
5832
+ "type": {
5833
+ "name": "enum",
5834
+ "value": [
5835
+ "full",
5836
+ "three-quarter",
5837
+ "half"
5838
+ ]
5839
+ },
5840
+ "required": false,
5841
+ "defaultValue": "three-quarter"
5842
+ },
5843
+ "spacing": {
5844
+ "type": {
5845
+ "name": "enum",
5846
+ "value": [
5847
+ "sm",
5848
+ "md"
5849
+ ]
5850
+ },
5851
+ "required": false,
5852
+ "defaultValue": "md"
5853
+ },
5854
+ "animation": {
5855
+ "type": {
5856
+ "name": "enum",
5857
+ "value": [
5858
+ "pulse",
5859
+ "shimmer",
5860
+ "none"
5861
+ ]
5862
+ },
5863
+ "required": false
5864
+ }
5865
+ }
5866
+ },
5867
+ "SkeletonButton": {
5868
+ "props": {
5869
+ "size": {
5870
+ "type": {
5871
+ "name": "enum",
5872
+ "value": [
5873
+ "sm",
5874
+ "md",
5875
+ "lg"
5876
+ ]
5877
+ },
5878
+ "required": false
5879
+ },
5880
+ "width": {
5881
+ "type": {
5882
+ "name": "enum",
5883
+ "value": [
5884
+ "auto",
5885
+ "full",
5886
+ "icon"
5887
+ ]
5888
+ },
5889
+ "required": false
5890
+ },
5891
+ "animation": {
5892
+ "type": {
5893
+ "name": "enum",
5894
+ "value": [
5895
+ "pulse",
5896
+ "shimmer",
5897
+ "none"
5898
+ ]
5899
+ },
5900
+ "required": false
5901
+ }
5902
+ }
5903
+ },
5904
+ "SkeletonInput": {
5905
+ "props": {
5906
+ "size": {
5907
+ "type": {
5908
+ "name": "enum",
5909
+ "value": [
5910
+ "sm",
5911
+ "md",
5912
+ "lg"
5913
+ ]
5914
+ },
5915
+ "required": false
5916
+ },
5917
+ "animation": {
5918
+ "type": {
5919
+ "name": "enum",
5920
+ "value": [
5921
+ "pulse",
5922
+ "shimmer",
5923
+ "none"
5924
+ ]
5925
+ },
5926
+ "required": false
5927
+ }
5928
+ }
5929
+ },
5930
+ "SkeletonChart": {
5931
+ "props": {
5932
+ "bars": {
5933
+ "type": {
5934
+ "name": "number"
5935
+ },
5936
+ "required": false,
5937
+ "defaultValue": 7
5938
+ },
5939
+ "height": {
5940
+ "type": {
5941
+ "name": "string"
5942
+ },
5943
+ "required": false,
5944
+ "defaultValue": "h-40"
5945
+ },
5946
+ "animation": {
5947
+ "type": {
5948
+ "name": "enum",
5949
+ "value": [
5950
+ "pulse",
5951
+ "shimmer",
5952
+ "none"
5953
+ ]
5954
+ },
5955
+ "required": false
5956
+ }
5957
+ }
5958
+ },
5959
+ "SkeletonImage": {
5960
+ "props": {
5961
+ "width": {
5962
+ "type": {
5963
+ "name": "string"
5964
+ },
5965
+ "required": false,
5966
+ "defaultValue": "w-full"
5967
+ },
5968
+ "height": {
5969
+ "type": {
5970
+ "name": "string"
5971
+ },
5972
+ "required": false,
5973
+ "defaultValue": "h-40"
5974
+ },
5975
+ "animation": {
5976
+ "type": {
5977
+ "name": "enum",
5978
+ "value": [
5979
+ "pulse",
5980
+ "shimmer",
5981
+ "none"
5982
+ ]
5983
+ },
5984
+ "required": false
5985
+ }
5986
+ }
5987
+ },
5988
+ "SkeletonGroup": {
5989
+ "props": {
5990
+ "label": {
5991
+ "type": {
5992
+ "name": "object",
5993
+ "raw": "string (default: \"Loading\") — accessible label for the loading state"
5994
+ },
5995
+ "required": false
5996
+ }
5997
+ }
5998
+ }
5999
+ },
5555
6000
  "examples": [
5556
6001
  "<Skeleton variant=\"text\" className=\"w-3/4\" />\n<Skeleton variant=\"circle\" className=\"h-12 w-12\" />\n<Skeleton variant=\"rectangle\" animation=\"shimmer\" className=\"h-48 w-full\" />\n\n<SkeletonGroup label=\"Loading user profile\">\n <SkeletonAvatar size=\"lg\" />\n <SkeletonText lines={2} />\n <SkeletonButton />\n</SkeletonGroup>\n\n<SkeletonChart bars={5} height=\"h-32\" />\n<SkeletonImage height=\"h-64\" />"
5557
6002
  ],
@@ -6223,82 +6668,6 @@
6223
6668
  }
6224
6669
  ]
6225
6670
  },
6226
- "status-dot": {
6227
- "displayName": "StatusDot",
6228
- "tier": "ui",
6229
- "import": "@devalok/shilp-sutra/ui/status-dot",
6230
- "serverSafe": true,
6231
- "description": "",
6232
- "props": {
6233
- "status": {
6234
- "type": {
6235
- "name": "enum",
6236
- "value": [
6237
- "healthy",
6238
- "warning",
6239
- "critical",
6240
- "neutral",
6241
- "inactive"
6242
- ]
6243
- },
6244
- "required": false
6245
- },
6246
- "size": {
6247
- "type": {
6248
- "name": "enum",
6249
- "value": [
6250
- "sm",
6251
- "md",
6252
- "lg"
6253
- ]
6254
- },
6255
- "required": false,
6256
- "defaultValue": "md"
6257
- },
6258
- "pulse": {
6259
- "type": {
6260
- "name": "boolean"
6261
- },
6262
- "required": false,
6263
- "description": "ping animation; defaults to true for \"healthy\", false for others",
6264
- "defaultValue": "{status ==="
6265
- },
6266
- "label": {
6267
- "type": {
6268
- "name": "string"
6269
- },
6270
- "required": false,
6271
- "description": "inline text rendered after the dot"
6272
- },
6273
- "labelClassName": {
6274
- "type": {
6275
- "name": "string"
6276
- },
6277
- "required": false,
6278
- "description": "extra classes on the label span"
6279
- }
6280
- },
6281
- "composition": {
6282
- "notes": [
6283
- "**Server-safe presentational dot** — simple status indicator, pairs with inline text.",
6284
- "**Status semantics map to color:** healthy=success, warning=warning, critical=error, neutral=muted surface, inactive=dimmed. The pulse animation calls attention to \"healthy\" by default (active presence); you can flip it for other statuses by setting pulse explicitly.",
6285
- "**StatusDot vs BadgeIndicator vs StatusBadge:** - StatusDot = tiny presence/status indicator with optional inline label (e.g. \"Service online\") - BadgeIndicator = overlay on another element (notification dot on a bell icon) - StatusBadge (composed) = full pill-style badge with colored bg and label text (e.g. ticket status)",
6286
- "**Label composability:** If you pass `label`, it renders inline after the dot. Use `labelClassName` for custom typography (e.g. font-mono for status codes)."
6287
- ]
6288
- },
6289
- "docPath": "docs/components/ui/status-dot.md",
6290
- "defaults": {
6291
- "size": "md",
6292
- "pulse": "{status ==="
6293
- },
6294
- "examples": [
6295
- "<StatusDot status=\"healthy\" />\n<StatusDot status=\"critical\" label=\"Service down\" pulse />\n<StatusDot status=\"warning\" size=\"lg\" label=\"Elevated load\" />"
6296
- ],
6297
- "gotchas": [
6298
- "The `pulse` prop auto-enables for \"healthy\" status — pass `pulse={false}` to suppress",
6299
- "Status type is exported as `StatusDotStatus` if you need it in consumer code"
6300
- ]
6301
- },
6302
6671
  "stepper": {
6303
6672
  "displayName": "Stepper / Step",
6304
6673
  "tier": "ui",
@@ -6329,25 +6698,6 @@
6329
6698
  "raw": "<Step> elements"
6330
6699
  },
6331
6700
  "required": false
6332
- },
6333
- "label": {
6334
- "type": {
6335
- "name": "string"
6336
- },
6337
- "required": true
6338
- },
6339
- "description": {
6340
- "type": {
6341
- "name": "string"
6342
- },
6343
- "required": false
6344
- },
6345
- "icon": {
6346
- "type": {
6347
- "name": "ReactNode"
6348
- },
6349
- "required": false,
6350
- "description": "overrides default number/checkmark"
6351
6701
  }
6352
6702
  },
6353
6703
  "composition": {
@@ -6374,6 +6724,31 @@
6374
6724
  ]
6375
6725
  },
6376
6726
  "docPath": "docs/components/ui/stepper.md",
6727
+ "subComponents": {
6728
+ "Step": {
6729
+ "props": {
6730
+ "label": {
6731
+ "type": {
6732
+ "name": "string"
6733
+ },
6734
+ "required": true
6735
+ },
6736
+ "description": {
6737
+ "type": {
6738
+ "name": "string"
6739
+ },
6740
+ "required": false
6741
+ },
6742
+ "icon": {
6743
+ "type": {
6744
+ "name": "ReactNode"
6745
+ },
6746
+ "required": false,
6747
+ "description": "overrides default number/checkmark"
6748
+ }
6749
+ }
6750
+ }
6751
+ },
6377
6752
  "examples": [
6378
6753
  "<Stepper activeStep={1}>\n <Step label=\"Account\" description=\"Create credentials\" />\n <Step label=\"Profile\" description=\"Add details\" />\n <Step label=\"Review\" />\n</Stepper>"
6379
6754
  ],
@@ -6501,12 +6876,18 @@
6501
6876
  },
6502
6877
  "required": false
6503
6878
  },
6504
- "error": {
6879
+ "state": {
6505
6880
  "type": {
6506
- "name": "boolean"
6881
+ "name": "enum",
6882
+ "value": [
6883
+ "default",
6884
+ "error",
6885
+ "warning",
6886
+ "success"
6887
+ ]
6507
6888
  },
6508
6889
  "required": false,
6509
- "description": "shows red border/bg"
6890
+ "description": "validation border/checked-track tint; error sets aria-invalid. Inherited from FormField when omitted. Distinct from `color`, the ON-track tint"
6510
6891
  },
6511
6892
  "disabled": {
6512
6893
  "type": {
@@ -6569,6 +6950,10 @@
6569
6950
  "Switch does NOT auto-consume FormField — pass `error` explicitly inside a FormField"
6570
6951
  ],
6571
6952
  "changes": [
6953
+ {
6954
+ "version": "0.49.0",
6955
+ "summary": "**BREAKING** Removed the `error: boolean` prop; use `state` (`FieldState = \"default\" | \"error\" | \"warning\" | \"success\"`). Migrate `<Switch error />` → `<Switch state=\"error\" />`. Gains `warning`/`success` and inherits from `FormField`. (`color` is unchanged — it's the ON-track tint, not validation.)"
6956
+ },
6572
6957
  {
6573
6958
  "version": "0.29.0",
6574
6959
  "summary": "**Added** `size` prop: `\"sm\"` (18px track) | `\"md\"` (24px, default) | `\"lg\"` (28px track)"
@@ -6611,28 +6996,6 @@
6611
6996
  },
6612
6997
  "required": false,
6613
6998
  "description": "opt-in zebra — even body rows get the faintest surface step; hairline separators remain the default row cue"
6614
- },
6615
- "numeric": {
6616
- "type": {
6617
- "name": "boolean"
6618
- },
6619
- "required": false,
6620
- "description": "right-align + tabular figures; header follows the column. Identifier-numbers — dates, phones, IDs — stay left"
6621
- },
6622
- "persist": {
6623
- "type": {
6624
- "name": "boolean"
6625
- },
6626
- "required": false,
6627
- "description": "always show instead of hover/focus reveal"
6628
- },
6629
- "href": {
6630
- "type": {
6631
- "name": "object",
6632
- "raw": "string (required); stretch: boolean"
6633
- },
6634
- "required": false,
6635
- "description": "default true"
6636
6999
  }
6637
7000
  },
6638
7001
  "composition": {
@@ -6683,6 +7046,59 @@
6683
7046
  ]
6684
7047
  },
6685
7048
  "docPath": "docs/components/ui/table.md",
7049
+ "subComponents": {
7050
+ "TableCell": {
7051
+ "props": {
7052
+ "numeric": {
7053
+ "type": {
7054
+ "name": "boolean"
7055
+ },
7056
+ "required": false,
7057
+ "description": "right-align + tabular figures; header follows the column. Identifier-numbers — dates, phones, IDs — stay left"
7058
+ }
7059
+ }
7060
+ },
7061
+ "TableHead": {
7062
+ "props": {
7063
+ "numeric": {
7064
+ "type": {
7065
+ "name": "boolean"
7066
+ },
7067
+ "required": false,
7068
+ "description": "right-align + tabular figures; header follows the column. Identifier-numbers — dates, phones, IDs — stay left"
7069
+ }
7070
+ }
7071
+ },
7072
+ "TableRowActions": {
7073
+ "props": {
7074
+ "persist": {
7075
+ "type": {
7076
+ "name": "boolean"
7077
+ },
7078
+ "required": false,
7079
+ "description": "always show instead of hover/focus reveal"
7080
+ }
7081
+ }
7082
+ },
7083
+ "TableRowLink": {
7084
+ "props": {
7085
+ "href": {
7086
+ "type": {
7087
+ "name": "string"
7088
+ },
7089
+ "required": true
7090
+ },
7091
+ "stretch": {
7092
+ "type": {
7093
+ "name": "boolean"
7094
+ },
7095
+ "required": false,
7096
+ "defaultValue": true
7097
+ }
7098
+ },
7099
+ "note": "separate import: ui/table-row-link — client component"
7100
+ }
7101
+ },
6686
7102
  "examples": [
6687
7103
  "<Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Status</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <TableRow>\n <TableCell>Project Alpha</TableCell>\n <TableCell><Badge color=\"success\">Active</Badge></TableCell>\n </TableRow>\n </TableBody>\n</Table>"
6688
7104
  ],
@@ -6745,7 +7161,7 @@
6745
7161
  },
6746
7162
  "docPath": "docs/components/ui/table-row-link.md",
6747
7163
  "examples": [
6748
- "<TableRow>\n <TableCell className=\"relative\">\n <TableRowLink href={`/projects/${id}`}>{name}</TableRowLink>\n </TableCell>\n <TableCell><Badge color=\"success\">Active</Badge></TableCell>\n <TableCell>\n <TableRowActions>\n <IconButton className=\"relative z-[1]\" size=\"xs\" variant=\"ghost\" aria-label={`Actions for ${name}`} icon={<IconDots />} />\n </TableRowActions>\n </TableCell>\n</TableRow>"
7164
+ "<TableRow>\n <TableCell className=\"relative\">\n <TableRowLink href={`/projects/${id}`}>{name}</TableRowLink>\n </TableCell>\n <TableCell><Badge color=\"success\">Active</Badge></TableCell>\n <TableCell>\n <TableRowActions>\n <IconButton className=\"relative z-[1]\" size=\"sm\" variant=\"ghost\" aria-label={`Actions for ${name}`} icon={<IconDots />} />\n </TableRowActions>\n </TableCell>\n</TableRow>"
6749
7165
  ],
6750
7166
  "gotchas": [
6751
7167
  "The stretched overlay blocks text selection inside the row — use `stretch={false}` (GitHub-style title link) when row text must stay selectable",
@@ -6776,7 +7192,7 @@
6776
7192
  "type": {
6777
7193
  "name": "string"
6778
7194
  },
6779
- "required": true
7195
+ "required": false
6780
7196
  },
6781
7197
  "onValueChange": {
6782
7198
  "type": {
@@ -6784,37 +7200,6 @@
6784
7200
  "raw": "(value: string) => void"
6785
7201
  },
6786
7202
  "required": false
6787
- },
6788
- "variant": {
6789
- "type": {
6790
- "name": "object",
6791
- "raw": "(inherits from TabsList)"
6792
- },
6793
- "required": false,
6794
- "defaultValue": "line"
6795
- },
6796
- "size": {
6797
- "type": {
6798
- "name": "enum",
6799
- "value": [
6800
- "sm",
6801
- "md",
6802
- "lg"
6803
- ]
6804
- },
6805
- "required": false,
6806
- "defaultValue": "md"
6807
- },
6808
- "orientation": {
6809
- "type": {
6810
- "name": "enum",
6811
- "value": [
6812
- "horizontal",
6813
- "vertical"
6814
- ]
6815
- },
6816
- "required": false,
6817
- "defaultValue": "horizontal"
6818
7203
  }
6819
7204
  },
6820
7205
  "composition": {
@@ -6849,6 +7234,70 @@
6849
7234
  "size": "md",
6850
7235
  "orientation": "horizontal"
6851
7236
  },
7237
+ "subComponents": {
7238
+ "TabsList": {
7239
+ "props": {
7240
+ "variant": {
7241
+ "type": {
7242
+ "name": "enum",
7243
+ "value": [
7244
+ "line",
7245
+ "contained"
7246
+ ]
7247
+ },
7248
+ "required": false
7249
+ },
7250
+ "size": {
7251
+ "type": {
7252
+ "name": "enum",
7253
+ "value": [
7254
+ "sm",
7255
+ "md",
7256
+ "lg"
7257
+ ]
7258
+ },
7259
+ "required": false
7260
+ },
7261
+ "orientation": {
7262
+ "type": {
7263
+ "name": "enum",
7264
+ "value": [
7265
+ "horizontal",
7266
+ "vertical"
7267
+ ]
7268
+ },
7269
+ "required": false
7270
+ }
7271
+ }
7272
+ },
7273
+ "TabsTrigger": {
7274
+ "props": {
7275
+ "value": {
7276
+ "type": {
7277
+ "name": "string"
7278
+ },
7279
+ "required": true
7280
+ },
7281
+ "variant": {
7282
+ "type": {
7283
+ "name": "object",
7284
+ "raw": "(inherits from TabsList)"
7285
+ },
7286
+ "required": false
7287
+ }
7288
+ }
7289
+ },
7290
+ "TabsContent": {
7291
+ "props": {
7292
+ "value": {
7293
+ "type": {
7294
+ "name": "string"
7295
+ },
7296
+ "required": true
7297
+ }
7298
+ }
7299
+ }
7300
+ },
6852
7301
  "examples": [
6853
7302
  "<Tabs defaultValue=\"overview\">\n <TabsList variant=\"contained\">\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"activity\">Activity</TabsTrigger>\n </TabsList>\n <TabsContent value=\"overview\">Overview content</TabsContent>\n <TabsContent value=\"activity\">Activity content</TabsContent>\n</Tabs>"
6854
7303
  ],
@@ -7069,6 +7518,9 @@
7069
7518
  "version": "0.1.0",
7070
7519
  "summary": "**Added** Initial release"
7071
7520
  }
7521
+ ],
7522
+ "peers": [
7523
+ "sonner"
7072
7524
  ]
7073
7525
  },
7074
7526
  "toaster": {
@@ -7146,6 +7598,9 @@
7146
7598
  "version": "0.1.0",
7147
7599
  "summary": "**Added** Initial release"
7148
7600
  }
7601
+ ],
7602
+ "peers": [
7603
+ "sonner"
7149
7604
  ]
7150
7605
  },
7151
7606
  "toggle": {
@@ -7293,7 +7748,8 @@
7293
7748
  },
7294
7749
  "value": {
7295
7750
  "type": {
7296
- "name": "string"
7751
+ "name": "union",
7752
+ "raw": "string | string[]"
7297
7753
  },
7298
7754
  "required": false
7299
7755
  },
@@ -7327,6 +7783,18 @@
7327
7783
  "variant": "default",
7328
7784
  "size": "md"
7329
7785
  },
7786
+ "subComponents": {
7787
+ "ToggleGroupItem": {
7788
+ "props": {
7789
+ "value": {
7790
+ "type": {
7791
+ "name": "string"
7792
+ },
7793
+ "required": false
7794
+ }
7795
+ }
7796
+ }
7797
+ },
7330
7798
  "examples": [
7331
7799
  "<ToggleGroup type=\"single\" variant=\"outline\" size=\"sm\" value={alignment} onValueChange={setAlignment}>\n <ToggleGroupItem value=\"left\"><IconAlignLeft /></ToggleGroupItem>\n <ToggleGroupItem value=\"center\"><IconAlignCenter /></ToggleGroupItem>\n <ToggleGroupItem value=\"right\"><IconAlignRight /></ToggleGroupItem>\n</ToggleGroup>"
7332
7800
  ],
@@ -7466,49 +7934,7 @@
7466
7934
  "name": "ReactNode"
7467
7935
  },
7468
7936
  "required": false,
7469
- "description": "nested TreeItems"
7470
- },
7471
- "itemId": {
7472
- "type": {
7473
- "name": "string"
7474
- },
7475
- "required": true
7476
- },
7477
- "label": {
7478
- "type": {
7479
- "name": "ReactNode"
7480
- },
7481
- "required": false
7482
- },
7483
- "secondaryLabel": {
7484
- "type": {
7485
- "name": "ReactNode"
7486
- },
7487
- "required": false
7488
- },
7489
- "icon": {
7490
- "type": {
7491
- "name": "ReactNode"
7492
- },
7493
- "required": false
7494
- },
7495
- "actions": {
7496
- "type": {
7497
- "name": "ReactNode"
7498
- },
7499
- "required": false
7500
- },
7501
- "disabled": {
7502
- "type": {
7503
- "name": "boolean"
7504
- },
7505
- "required": false
7506
- },
7507
- "depth": {
7508
- "type": {
7509
- "name": "number"
7510
- },
7511
- "required": false
7937
+ "description": "declarative mode"
7512
7938
  }
7513
7939
  },
7514
7940
  "composition": {
@@ -7521,6 +7947,61 @@
7521
7947
  ]
7522
7948
  },
7523
7949
  "docPath": "docs/components/ui/tree-view.md",
7950
+ "subComponents": {
7951
+ "TreeItem": {
7952
+ "props": {
7953
+ "itemId": {
7954
+ "type": {
7955
+ "name": "string"
7956
+ },
7957
+ "required": true
7958
+ },
7959
+ "label": {
7960
+ "type": {
7961
+ "name": "ReactNode"
7962
+ },
7963
+ "required": false
7964
+ },
7965
+ "secondaryLabel": {
7966
+ "type": {
7967
+ "name": "ReactNode"
7968
+ },
7969
+ "required": false
7970
+ },
7971
+ "icon": {
7972
+ "type": {
7973
+ "name": "ReactNode"
7974
+ },
7975
+ "required": false
7976
+ },
7977
+ "actions": {
7978
+ "type": {
7979
+ "name": "ReactNode"
7980
+ },
7981
+ "required": false
7982
+ },
7983
+ "disabled": {
7984
+ "type": {
7985
+ "name": "boolean"
7986
+ },
7987
+ "required": false
7988
+ },
7989
+ "depth": {
7990
+ "type": {
7991
+ "name": "number"
7992
+ },
7993
+ "required": false
7994
+ },
7995
+ "children": {
7996
+ "type": {
7997
+ "name": "ReactNode"
7998
+ },
7999
+ "required": false,
8000
+ "description": "nested TreeItems"
8001
+ }
8002
+ }
8003
+ }
8004
+ },
7524
8005
  "gotchas": [
7525
8006
  "Supports both data-driven (items prop) and declarative (children) modes",
7526
8007
  "Don't mix data-driven and declarative in the same TreeView — pick one",
@@ -7971,43 +8452,6 @@
7971
8452
  "name": "string"
7972
8453
  },
7973
8454
  "required": false
7974
- },
7975
- "label": {
7976
- "type": {
7977
- "name": "string"
7978
- },
7979
- "required": false
7980
- },
7981
- "icon": {
7982
- "type": {
7983
- "name": "object",
7984
- "raw": "ComponentType<{ className?: string }>"
7985
- },
7986
- "required": false,
7987
- "description": "optional icon component"
7988
- },
7989
- "onClick": {
7990
- "type": {
7991
- "name": "function",
7992
- "raw": "() => void"
7993
- },
7994
- "required": false
7995
- },
7996
- "color": {
7997
- "type": {
7998
- "name": "enum",
7999
- "value": [
8000
- "default",
8001
- "error"
8002
- ]
8003
- },
8004
- "required": false
8005
- },
8006
- "disabled": {
8007
- "type": {
8008
- "name": "boolean"
8009
- },
8010
- "required": false
8011
8455
  }
8012
8456
  },
8013
8457
  "composition": {
@@ -8019,6 +8463,49 @@
8019
8463
  ]
8020
8464
  },
8021
8465
  "docPath": "docs/components/composed/bulk-action-bar.md",
8466
+ "subComponents": {
8467
+ "BulkActionBarAction": {
8468
+ "props": {
8469
+ "label": {
8470
+ "type": {
8471
+ "name": "string"
8472
+ },
8473
+ "required": false
8474
+ },
8475
+ "icon": {
8476
+ "type": {
8477
+ "name": "object",
8478
+ "raw": "ComponentType<{ className?: string }>"
8479
+ },
8480
+ "required": false,
8481
+ "description": "optional icon component"
8482
+ },
8483
+ "onClick": {
8484
+ "type": {
8485
+ "name": "function",
8486
+ "raw": "() => void"
8487
+ },
8488
+ "required": false
8489
+ },
8490
+ "color": {
8491
+ "type": {
8492
+ "name": "enum",
8493
+ "value": [
8494
+ "default",
8495
+ "error"
8496
+ ]
8497
+ },
8498
+ "required": false
8499
+ },
8500
+ "disabled": {
8501
+ "type": {
8502
+ "name": "boolean"
8503
+ },
8504
+ "required": false
8505
+ }
8506
+ }
8507
+ }
8508
+ },
8022
8509
  "examples": [
8023
8510
  "<BulkActionBar\n show={selected.length > 0}\n count={selected.length}\n onClearSelection={() => setSelected([])}\n actions={[\n { label: 'Archive', icon: IconArchive, onClick: archiveSelected },\n { label: 'Delete', icon: IconTrash, onClick: deleteSelected, color: 'error' },\n ]}\n/>"
8024
8511
  ],
@@ -8321,13 +8808,12 @@
8321
8808
  "name": "union",
8322
8809
  "raw": "Date | null"
8323
8810
  },
8324
- "required": false,
8325
- "description": "time stored as a Date object"
8811
+ "required": false
8326
8812
  },
8327
8813
  "onChange": {
8328
8814
  "type": {
8329
8815
  "name": "function",
8330
- "raw": "(date: Date) => void"
8816
+ "raw": "(date: Date | null) => void"
8331
8817
  },
8332
8818
  "required": false
8333
8819
  },
@@ -8336,7 +8822,7 @@
8336
8822
  "name": "string"
8337
8823
  },
8338
8824
  "required": false,
8339
- "defaultValue": "Pick a time"
8825
+ "defaultValue": "Pick a date"
8340
8826
  },
8341
8827
  "formatStr": {
8342
8828
  "type": {
@@ -8371,292 +8857,524 @@
8371
8857
  "name": "string"
8372
8858
  },
8373
8859
  "required": false
8860
+ }
8861
+ },
8862
+ "composition": {
8863
+ "notes": [
8864
+ "**7 sub-components in one kit:** DatePicker, DateRangePicker, DateTimePicker, TimePicker, CalendarGrid, MonthPicker, YearPicker, Presets. Built on Popover (trigger + calendar content) + date-fns.",
8865
+ "**Layered abstractions:** - High-level: DatePicker / DateRangePicker / DateTimePicker / TimePicker (use these 95% of the time — Popover-wrapped, single-field pickers with formatted value display). - Low-level: CalendarGrid / MonthPicker / YearPicker (use for custom picker layouts, inline calendars, dashboards with embedded date selection).",
8866
+ "**useCalendar hook** manages month navigation state — use it when building custom picker UI (e.g. inline calendar with custom header).",
8867
+ "**Presets component** is standalone — drop it next to a DateRangePicker's calendar for quick-select sidebars (Today / Last 7 days / This month / etc.).",
8868
+ "**Events on calendar:** CalendarGrid accepts `events: { date, color, label }[]` — renders up to 3 colored dots per day cell. Useful for availability / booked-days highlights.",
8869
+ "**min/max/disabledDates** are shared contract across the whole family — pass the same bounds config to any date picker variant."
8870
+ ]
8871
+ },
8872
+ "docPath": "docs/components/composed/date-picker.md",
8873
+ "defaults": {
8874
+ "placeholder": "Pick a date range",
8875
+ "formatStr": "MMM d",
8876
+ "numberOfMonths": 1,
8877
+ "format": "12h",
8878
+ "minuteStep": 1,
8879
+ "secondStep": 1,
8880
+ "showSeconds": false
8881
+ },
8882
+ "subComponents": {
8883
+ "DateRangePicker": {
8884
+ "props": {
8885
+ "startDate": {
8886
+ "type": {
8887
+ "name": "union",
8888
+ "raw": "Date | null"
8889
+ },
8890
+ "required": false
8891
+ },
8892
+ "endDate": {
8893
+ "type": {
8894
+ "name": "union",
8895
+ "raw": "Date | null"
8896
+ },
8897
+ "required": false
8898
+ },
8899
+ "onChange": {
8900
+ "type": {
8901
+ "name": "function",
8902
+ "raw": "(range: { start: Date | null, end: Date | null }) => void"
8903
+ },
8904
+ "required": false
8905
+ },
8906
+ "placeholder": {
8907
+ "type": {
8908
+ "name": "string"
8909
+ },
8910
+ "required": false,
8911
+ "defaultValue": "Pick a date range"
8912
+ },
8913
+ "formatStr": {
8914
+ "type": {
8915
+ "name": "string"
8916
+ },
8917
+ "required": false,
8918
+ "defaultValue": "MMM d, yyyy"
8919
+ },
8920
+ "minDate": {
8921
+ "type": {
8922
+ "name": "object",
8923
+ "raw": "Date"
8924
+ },
8925
+ "required": false
8926
+ },
8927
+ "maxDate": {
8928
+ "type": {
8929
+ "name": "object",
8930
+ "raw": "Date"
8931
+ },
8932
+ "required": false
8933
+ },
8934
+ "disabledDates": {
8935
+ "type": {
8936
+ "name": "function",
8937
+ "raw": "(date: Date) => boolean"
8938
+ },
8939
+ "required": false
8940
+ },
8941
+ "presets": {
8942
+ "type": {
8943
+ "name": "object",
8944
+ "raw": "PresetKey[]"
8945
+ },
8946
+ "required": false,
8947
+ "description": "shows quick-select sidebar"
8948
+ },
8949
+ "numberOfMonths": {
8950
+ "type": {
8951
+ "name": "number"
8952
+ },
8953
+ "required": false,
8954
+ "defaultValue": 1
8955
+ }
8956
+ }
8374
8957
  },
8375
- "startDate": {
8376
- "type": {
8377
- "name": "union",
8378
- "raw": "Date | null"
8379
- },
8380
- "required": false
8958
+ "DateTimePicker": {
8959
+ "props": {
8960
+ "value": {
8961
+ "type": {
8962
+ "name": "union",
8963
+ "raw": "Date | null"
8964
+ },
8965
+ "required": false
8966
+ },
8967
+ "onChange": {
8968
+ "type": {
8969
+ "name": "function",
8970
+ "raw": "(date: Date | null) => void"
8971
+ },
8972
+ "required": false
8973
+ },
8974
+ "minDate": {
8975
+ "type": {
8976
+ "name": "object",
8977
+ "raw": "Date"
8978
+ },
8979
+ "required": false
8980
+ },
8981
+ "maxDate": {
8982
+ "type": {
8983
+ "name": "object",
8984
+ "raw": "Date"
8985
+ },
8986
+ "required": false
8987
+ },
8988
+ "disabledDates": {
8989
+ "type": {
8990
+ "name": "function",
8991
+ "raw": "(date: Date) => boolean"
8992
+ },
8993
+ "required": false
8994
+ },
8995
+ "timeFormat": {
8996
+ "type": {
8997
+ "name": "enum",
8998
+ "value": [
8999
+ "12h",
9000
+ "24h"
9001
+ ]
9002
+ },
9003
+ "required": false
9004
+ },
9005
+ "minuteStep": {
9006
+ "type": {
9007
+ "name": "number"
9008
+ },
9009
+ "required": false
9010
+ },
9011
+ "placeholder": {
9012
+ "type": {
9013
+ "name": "string"
9014
+ },
9015
+ "required": false
9016
+ },
9017
+ "className": {
9018
+ "type": {
9019
+ "name": "string"
9020
+ },
9021
+ "required": false
9022
+ }
9023
+ }
8381
9024
  },
8382
- "endDate": {
8383
- "type": {
8384
- "name": "union",
8385
- "raw": "Date | null"
8386
- },
8387
- "required": false
9025
+ "TimePicker": {
9026
+ "props": {
9027
+ "value": {
9028
+ "type": {
9029
+ "name": "union",
9030
+ "raw": "Date | null"
9031
+ },
9032
+ "required": false,
9033
+ "description": "time stored as a Date object"
9034
+ },
9035
+ "onChange": {
9036
+ "type": {
9037
+ "name": "function",
9038
+ "raw": "(date: Date) => void"
9039
+ },
9040
+ "required": false
9041
+ },
9042
+ "format": {
9043
+ "type": {
9044
+ "name": "enum",
9045
+ "value": [
9046
+ "12h",
9047
+ "24h"
9048
+ ]
9049
+ },
9050
+ "required": false,
9051
+ "defaultValue": "12h"
9052
+ },
9053
+ "minuteStep": {
9054
+ "type": {
9055
+ "name": "number"
9056
+ },
9057
+ "required": false,
9058
+ "defaultValue": 1
9059
+ },
9060
+ "secondStep": {
9061
+ "type": {
9062
+ "name": "number"
9063
+ },
9064
+ "required": false,
9065
+ "defaultValue": 1
9066
+ },
9067
+ "showSeconds": {
9068
+ "type": {
9069
+ "name": "boolean"
9070
+ },
9071
+ "required": false,
9072
+ "defaultValue": false
9073
+ },
9074
+ "placeholder": {
9075
+ "type": {
9076
+ "name": "string"
9077
+ },
9078
+ "required": false,
9079
+ "defaultValue": "Pick a time"
9080
+ },
9081
+ "disabled": {
9082
+ "type": {
9083
+ "name": "boolean"
9084
+ },
9085
+ "required": false,
9086
+ "defaultValue": false
9087
+ },
9088
+ "className": {
9089
+ "type": {
9090
+ "name": "string"
9091
+ },
9092
+ "required": false
9093
+ }
9094
+ }
8388
9095
  },
8389
- "presets": {
8390
- "type": {
8391
- "name": "object",
8392
- "raw": "PresetKey[]"
8393
- },
8394
- "required": true
9096
+ "CalendarGrid": {
9097
+ "props": {
9098
+ "currentMonth": {
9099
+ "type": {
9100
+ "name": "object",
9101
+ "raw": "Date"
9102
+ },
9103
+ "required": true
9104
+ },
9105
+ "selected": {
9106
+ "type": {
9107
+ "name": "union",
9108
+ "raw": "Date | null"
9109
+ },
9110
+ "required": false
9111
+ },
9112
+ "rangeStart": {
9113
+ "type": {
9114
+ "name": "union",
9115
+ "raw": "Date | null"
9116
+ },
9117
+ "required": false
9118
+ },
9119
+ "rangeEnd": {
9120
+ "type": {
9121
+ "name": "union",
9122
+ "raw": "Date | null"
9123
+ },
9124
+ "required": false
9125
+ },
9126
+ "hoverDate": {
9127
+ "type": {
9128
+ "name": "union",
9129
+ "raw": "Date | null"
9130
+ },
9131
+ "required": false
9132
+ },
9133
+ "onSelect": {
9134
+ "type": {
9135
+ "name": "function",
9136
+ "raw": "(date: Date) => void (REQUIRED)"
9137
+ },
9138
+ "required": false
9139
+ },
9140
+ "onHover": {
9141
+ "type": {
9142
+ "name": "function",
9143
+ "raw": "(date: Date | null) => void"
9144
+ },
9145
+ "required": false
9146
+ },
9147
+ "onMonthChange": {
9148
+ "type": {
9149
+ "name": "function",
9150
+ "raw": "(date: Date) => void (REQUIRED)"
9151
+ },
9152
+ "required": false
9153
+ },
9154
+ "onHeaderClick": {
9155
+ "type": {
9156
+ "name": "function",
9157
+ "raw": "() => void"
9158
+ },
9159
+ "required": false
9160
+ },
9161
+ "disabledDates": {
9162
+ "type": {
9163
+ "name": "function",
9164
+ "raw": "(date: Date) => boolean"
9165
+ },
9166
+ "required": false
9167
+ },
9168
+ "minDate": {
9169
+ "type": {
9170
+ "name": "object",
9171
+ "raw": "Date"
9172
+ },
9173
+ "required": false
9174
+ },
9175
+ "maxDate": {
9176
+ "type": {
9177
+ "name": "object",
9178
+ "raw": "Date"
9179
+ },
9180
+ "required": false
9181
+ },
9182
+ "hidePrevNav": {
9183
+ "type": {
9184
+ "name": "boolean"
9185
+ },
9186
+ "required": false
9187
+ },
9188
+ "hideNextNav": {
9189
+ "type": {
9190
+ "name": "boolean"
9191
+ },
9192
+ "required": false
9193
+ },
9194
+ "events": {
9195
+ "type": {
9196
+ "name": "object",
9197
+ "raw": "CalendarEvent[] — { date: Date, color?: string, label?: string }"
9198
+ },
9199
+ "required": false
9200
+ }
9201
+ }
9202
+ },
9203
+ "YearPicker": {
9204
+ "props": {
9205
+ "currentYear": {
9206
+ "type": {
9207
+ "name": "number"
9208
+ },
9209
+ "required": true
9210
+ },
9211
+ "selectedYear": {
9212
+ "type": {
9213
+ "name": "number"
9214
+ },
9215
+ "required": false
9216
+ },
9217
+ "onYearSelect": {
9218
+ "type": {
9219
+ "name": "function",
9220
+ "raw": "(year: number) => void (REQUIRED)"
9221
+ },
9222
+ "required": false
9223
+ },
9224
+ "minDate": {
9225
+ "type": {
9226
+ "name": "object",
9227
+ "raw": "Date"
9228
+ },
9229
+ "required": false
9230
+ },
9231
+ "maxDate": {
9232
+ "type": {
9233
+ "name": "object",
9234
+ "raw": "Date"
9235
+ },
9236
+ "required": false
9237
+ }
9238
+ }
9239
+ },
9240
+ "MonthPicker": {
9241
+ "props": {
9242
+ "currentYear": {
9243
+ "type": {
9244
+ "name": "number"
9245
+ },
9246
+ "required": true
9247
+ },
9248
+ "selectedMonth": {
9249
+ "type": {
9250
+ "name": "number"
9251
+ },
9252
+ "required": false,
9253
+ "description": "0-11"
9254
+ },
9255
+ "onMonthSelect": {
9256
+ "type": {
9257
+ "name": "function",
9258
+ "raw": "(month: number) => void (REQUIRED)"
9259
+ },
9260
+ "required": false
9261
+ },
9262
+ "minDate": {
9263
+ "type": {
9264
+ "name": "object",
9265
+ "raw": "Date"
9266
+ },
9267
+ "required": false
9268
+ },
9269
+ "maxDate": {
9270
+ "type": {
9271
+ "name": "object",
9272
+ "raw": "Date"
9273
+ },
9274
+ "required": false
9275
+ }
9276
+ }
9277
+ },
9278
+ "Presets": {
9279
+ "props": {
9280
+ "presets": {
9281
+ "type": {
9282
+ "name": "object",
9283
+ "raw": "PresetKey[]"
9284
+ },
9285
+ "required": true
9286
+ },
9287
+ "onSelect": {
9288
+ "type": {
9289
+ "name": "function",
9290
+ "raw": "(start: Date, end: Date) => void (REQUIRED)"
9291
+ },
9292
+ "required": false
9293
+ },
9294
+ "className": {
9295
+ "type": {
9296
+ "name": "string"
9297
+ },
9298
+ "required": false
9299
+ }
9300
+ }
9301
+ },
9302
+ "useCalendar hook": {
9303
+ "props": {}
9304
+ }
9305
+ },
9306
+ "examples": [
9307
+ "<DatePicker value={date} onChange={setDate} placeholder=\"Select date\" />\n\n<DateRangePicker\n startDate={start}\n endDate={end}\n onChange={({ start, end }) => { setStart(start); setEnd(end); }}\n/>\n\n<DateTimePicker value={dateTime} onChange={setDateTime} timeFormat=\"12h\" minuteStep={15} />\n\n<TimePicker value={time} onChange={setTime} format=\"24h\" minuteStep={15} />"
9308
+ ],
9309
+ "gotchas": [
9310
+ "TimePicker stores time inside a Date object — only hours/minutes/seconds are meaningful",
9311
+ "CalendarGrid is a low-level building block — prefer DatePicker/DateRangePicker for most use cases",
9312
+ "MonthPicker month values are 0-indexed (Jan=0, Dec=11) — same as JavaScript `Date.getMonth()`",
9313
+ "YearPicker displays a 12-year grid based on the decade of `currentYear`",
9314
+ "CalendarGrid supports up to 3 event dots per day cell",
9315
+ "useCalendar is a convenience hook for managing calendar month state"
9316
+ ],
9317
+ "changes": [
9318
+ {
9319
+ "version": "0.18.0",
9320
+ "summary": "**Fixed** Added `aria-label` to DatePicker/DateRangePicker trigger buttons"
9321
+ },
9322
+ {
9323
+ "version": "0.4.2",
9324
+ "summary": "**Changed** DateRangePicker default `formatStr` from `'MMM d'` to `'MMM d, yyyy'`"
8395
9325
  },
8396
- "numberOfMonths": {
9326
+ {
9327
+ "version": "0.1.0",
9328
+ "summary": "**Added** Initial release"
9329
+ }
9330
+ ],
9331
+ "peers": [
9332
+ "date-fns"
9333
+ ]
9334
+ },
9335
+ "deadline-indicator": {
9336
+ "displayName": "DeadlineIndicator",
9337
+ "tier": "composed",
9338
+ "import": "@devalok/shilp-sutra/composed/deadline-indicator",
9339
+ "serverSafe": true,
9340
+ "description": "",
9341
+ "props": {
9342
+ "deadline": {
8397
9343
  "type": {
8398
- "name": "number"
9344
+ "name": "union",
9345
+ "raw": "Date | string"
8399
9346
  },
8400
9347
  "required": false,
8401
- "defaultValue": 1
9348
+ "description": "deadline timestamp"
8402
9349
  },
8403
- "timeFormat": {
9350
+ "warningThreshold": {
8404
9351
  "type": {
8405
- "name": "enum",
8406
- "value": [
8407
- "12h",
8408
- "24h"
8409
- ]
9352
+ "name": "number"
8410
9353
  },
8411
- "required": false
9354
+ "required": false,
9355
+ "description": "minutes before deadline to show warning color",
9356
+ "defaultValue": "{1440} (24h)"
8412
9357
  },
8413
- "minuteStep": {
9358
+ "criticalThreshold": {
8414
9359
  "type": {
8415
9360
  "name": "number"
8416
9361
  },
8417
9362
  "required": false,
8418
- "defaultValue": 1
9363
+ "description": "minutes before deadline to show critical/error color",
9364
+ "defaultValue": "{240} (4h)"
8419
9365
  },
8420
9366
  "format": {
8421
9367
  "type": {
8422
9368
  "name": "enum",
8423
9369
  "value": [
8424
- "12h",
8425
- "24h"
9370
+ "relative",
9371
+ "absolute"
8426
9372
  ]
8427
9373
  },
8428
9374
  "required": false,
8429
- "defaultValue": "12h"
8430
- },
8431
- "secondStep": {
8432
- "type": {
8433
- "name": "number"
8434
- },
8435
- "required": false,
8436
- "defaultValue": 1
8437
- },
8438
- "showSeconds": {
8439
- "type": {
8440
- "name": "boolean"
8441
- },
8442
- "required": false,
8443
- "defaultValue": false
9375
+ "defaultValue": "relative"
8444
9376
  },
8445
- "disabled": {
8446
- "type": {
8447
- "name": "boolean"
8448
- },
8449
- "required": false,
8450
- "defaultValue": false
8451
- },
8452
- "currentMonth": {
8453
- "type": {
8454
- "name": "object",
8455
- "raw": "Date"
8456
- },
8457
- "required": true
8458
- },
8459
- "selected": {
8460
- "type": {
8461
- "name": "union",
8462
- "raw": "Date | null"
8463
- },
8464
- "required": false
8465
- },
8466
- "rangeStart": {
8467
- "type": {
8468
- "name": "union",
8469
- "raw": "Date | null"
8470
- },
8471
- "required": false
8472
- },
8473
- "rangeEnd": {
8474
- "type": {
8475
- "name": "union",
8476
- "raw": "Date | null"
8477
- },
8478
- "required": false
8479
- },
8480
- "hoverDate": {
8481
- "type": {
8482
- "name": "union",
8483
- "raw": "Date | null"
8484
- },
8485
- "required": false
8486
- },
8487
- "onSelect": {
8488
- "type": {
8489
- "name": "function",
8490
- "raw": "(start: Date, end: Date) => void (REQUIRED)"
8491
- },
8492
- "required": false
8493
- },
8494
- "onHover": {
8495
- "type": {
8496
- "name": "function",
8497
- "raw": "(date: Date | null) => void"
8498
- },
8499
- "required": false
8500
- },
8501
- "onMonthChange": {
8502
- "type": {
8503
- "name": "function",
8504
- "raw": "(date: Date) => void (REQUIRED)"
8505
- },
8506
- "required": false
8507
- },
8508
- "onHeaderClick": {
8509
- "type": {
8510
- "name": "function",
8511
- "raw": "() => void"
8512
- },
8513
- "required": false
8514
- },
8515
- "hidePrevNav": {
8516
- "type": {
8517
- "name": "boolean"
8518
- },
8519
- "required": false
8520
- },
8521
- "hideNextNav": {
8522
- "type": {
8523
- "name": "boolean"
8524
- },
8525
- "required": false
8526
- },
8527
- "events": {
8528
- "type": {
8529
- "name": "object",
8530
- "raw": "CalendarEvent[] — { date: Date, color?: string, label?: string }"
8531
- },
8532
- "required": false
8533
- },
8534
- "currentYear": {
8535
- "type": {
8536
- "name": "number"
8537
- },
8538
- "required": true
8539
- },
8540
- "selectedYear": {
8541
- "type": {
8542
- "name": "number"
8543
- },
8544
- "required": false
8545
- },
8546
- "onYearSelect": {
8547
- "type": {
8548
- "name": "function",
8549
- "raw": "(year: number) => void (REQUIRED)"
8550
- },
8551
- "required": false
8552
- },
8553
- "selectedMonth": {
8554
- "type": {
8555
- "name": "number"
8556
- },
8557
- "required": false,
8558
- "description": "0-11"
8559
- },
8560
- "onMonthSelect": {
8561
- "type": {
8562
- "name": "function",
8563
- "raw": "(month: number) => void (REQUIRED)"
8564
- },
8565
- "required": false
8566
- }
8567
- },
8568
- "composition": {
8569
- "notes": [
8570
- "**7 sub-components in one kit:** DatePicker, DateRangePicker, DateTimePicker, TimePicker, CalendarGrid, MonthPicker, YearPicker, Presets. Built on Popover (trigger + calendar content) + date-fns.",
8571
- "**Layered abstractions:** - High-level: DatePicker / DateRangePicker / DateTimePicker / TimePicker (use these 95% of the time — Popover-wrapped, single-field pickers with formatted value display). - Low-level: CalendarGrid / MonthPicker / YearPicker (use for custom picker layouts, inline calendars, dashboards with embedded date selection).",
8572
- "**useCalendar hook** manages month navigation state — use it when building custom picker UI (e.g. inline calendar with custom header).",
8573
- "**Presets component** is standalone — drop it next to a DateRangePicker's calendar for quick-select sidebars (Today / Last 7 days / This month / etc.).",
8574
- "**Events on calendar:** CalendarGrid accepts `events: { date, color, label }[]` — renders up to 3 colored dots per day cell. Useful for availability / booked-days highlights.",
8575
- "**min/max/disabledDates** are shared contract across the whole family — pass the same bounds config to any date picker variant."
8576
- ]
8577
- },
8578
- "docPath": "docs/components/composed/date-picker.md",
8579
- "defaults": {
8580
- "placeholder": "Pick a date range",
8581
- "formatStr": "MMM d",
8582
- "numberOfMonths": 1,
8583
- "format": "12h",
8584
- "minuteStep": 1,
8585
- "secondStep": 1,
8586
- "showSeconds": false
8587
- },
8588
- "examples": [
8589
- "<DatePicker value={date} onChange={setDate} placeholder=\"Select date\" />\n\n<DateRangePicker\n startDate={start}\n endDate={end}\n onChange={({ start, end }) => { setStart(start); setEnd(end); }}\n/>\n\n<DateTimePicker value={dateTime} onChange={setDateTime} timeFormat=\"12h\" minuteStep={15} />\n\n<TimePicker value={time} onChange={setTime} format=\"24h\" minuteStep={15} />"
8590
- ],
8591
- "gotchas": [
8592
- "TimePicker stores time inside a Date object — only hours/minutes/seconds are meaningful",
8593
- "CalendarGrid is a low-level building block — prefer DatePicker/DateRangePicker for most use cases",
8594
- "MonthPicker month values are 0-indexed (Jan=0, Dec=11) — same as JavaScript `Date.getMonth()`",
8595
- "YearPicker displays a 12-year grid based on the decade of `currentYear`",
8596
- "CalendarGrid supports up to 3 event dots per day cell",
8597
- "useCalendar is a convenience hook for managing calendar month state"
8598
- ],
8599
- "changes": [
8600
- {
8601
- "version": "0.18.0",
8602
- "summary": "**Fixed** Added `aria-label` to DatePicker/DateRangePicker trigger buttons"
8603
- },
8604
- {
8605
- "version": "0.4.2",
8606
- "summary": "**Changed** DateRangePicker default `formatStr` from `'MMM d'` to `'MMM d, yyyy'`"
8607
- },
8608
- {
8609
- "version": "0.1.0",
8610
- "summary": "**Added** Initial release"
8611
- }
8612
- ],
8613
- "peers": [
8614
- "date-fns"
8615
- ]
8616
- },
8617
- "deadline-indicator": {
8618
- "displayName": "DeadlineIndicator",
8619
- "tier": "composed",
8620
- "import": "@devalok/shilp-sutra/composed/deadline-indicator",
8621
- "serverSafe": true,
8622
- "description": "",
8623
- "props": {
8624
- "deadline": {
8625
- "type": {
8626
- "name": "union",
8627
- "raw": "Date | string"
8628
- },
8629
- "required": false,
8630
- "description": "deadline timestamp"
8631
- },
8632
- "warningThreshold": {
8633
- "type": {
8634
- "name": "number"
8635
- },
8636
- "required": false,
8637
- "description": "minutes before deadline to show warning color",
8638
- "defaultValue": "{1440} (24h)"
8639
- },
8640
- "criticalThreshold": {
8641
- "type": {
8642
- "name": "number"
8643
- },
8644
- "required": false,
8645
- "description": "minutes before deadline to show critical/error color",
8646
- "defaultValue": "{240} (4h)"
8647
- },
8648
- "format": {
8649
- "type": {
8650
- "name": "enum",
8651
- "value": [
8652
- "relative",
8653
- "absolute"
8654
- ]
8655
- },
8656
- "required": false,
8657
- "defaultValue": "relative"
8658
- },
8659
- "showIcon": {
9377
+ "showIcon": {
8660
9378
  "type": {
8661
9379
  "name": "boolean"
8662
9380
  },
@@ -8704,81 +9422,14 @@
8704
9422
  },
8705
9423
  "required": false
8706
9424
  },
8707
- "theme": {
8708
- "type": {
8709
- "name": "enum",
8710
- "value": [
8711
- "auto",
8712
- "light",
8713
- "dark"
8714
- ]
8715
- },
8716
- "required": false,
8717
- "defaultValue": "auto"
8718
- },
8719
- "previewPosition": {
8720
- "type": {
8721
- "name": "enum",
8722
- "value": [
8723
- "top",
8724
- "bottom",
8725
- "none"
8726
- ]
8727
- },
8728
- "required": false,
8729
- "defaultValue": "none"
8730
- },
8731
- "skinTonePosition": {
8732
- "type": {
8733
- "name": "enum",
8734
- "value": [
8735
- "search",
8736
- "preview",
8737
- "none"
8738
- ]
8739
- },
8740
- "required": false,
8741
- "defaultValue": "search"
8742
- },
8743
- "className": {
8744
- "type": {
8745
- "name": "string"
8746
- },
8747
- "required": false
8748
- },
8749
- "children": {
8750
- "type": {
8751
- "name": "ReactNode"
8752
- },
8753
- "required": false,
8754
- "description": "trigger element"
8755
- },
8756
- "align": {
8757
- "type": {
8758
- "name": "enum",
8759
- "value": [
8760
- "start",
8761
- "center",
8762
- "end"
8763
- ]
8764
- },
8765
- "required": false,
8766
- "defaultValue": "start"
8767
- },
8768
- "id": {
8769
- "type": {
8770
- "name": "string"
8771
- },
8772
- "required": false
8773
- },
8774
- "native": {
9425
+ "emojibaseUrl": {
8775
9426
  "type": {
8776
9427
  "name": "string"
8777
9428
  },
8778
9429
  "required": false,
8779
- "description": "the emoji character"
9430
+ "description": "base URL for the emoji dataset; default = frimousse's jsdelivr CDN"
8780
9431
  },
8781
- "shortcodes": {
9432
+ "className": {
8782
9433
  "type": {
8783
9434
  "name": "string"
8784
9435
  },
@@ -8788,32 +9439,78 @@
8788
9439
  "composition": {
8789
9440
  "notes": [
8790
9441
  "**Two exports:** `EmojiPicker` (inline grid, no trigger) and `EmojiPickerPopover` (trigger + popover wrapper). Use EmojiPickerPopover 95% of the time — trigger-on-click is the standard UX.",
8791
- "**Wraps @emoji-mart/react**, lazy-loaded with a Skeleton placeholder while the ~200KB bundle fetches. Don't pre-import unless you need it eagerly.",
9442
+ "**Built on frimousse**, bundled and lazy-loaded (own `emoji` chunk, incl. the dataset). Needs no consumer peer install and no React-19 peer workaround. Don't pre-import unless you need it eagerly.",
9443
+ "**Native emoji only.** Each platform renders its own glyphs. Theme follows the surrounding `.dark` class via DS tokens automatically — no theme prop.",
9444
+ "**Built-in footer:** a live preview of the hovered/active emoji (frimousse `ActiveEmoji`) plus a skin-tone selector (`SkinToneSelector`) — no props needed.",
9445
+ "**Dataset source / CSP:** frimousse fetches the emoji dataset from jsdelivr at runtime. To remove the CDN dependency (strict CSP, offline, air-gapped), copy `node_modules/emojibase-data` into your app's `public/emojibase` and pass `emojibaseUrl=\"/emojibase\"`.",
8792
9446
  "**Trigger composition:** EmojiPickerPopover's `children` is the trigger — wrap any Button/IconButton. Typical pairing is an icon-only IconButton with a 😀 label.",
8793
- "**TipTap integration:** Use `createEmojiSuggestion(set?)` factory to create a TipTap suggestion plugin that opens the picker on typing `:emoji`. Works with RichChatInput and RichTextEditor.",
8794
- "**Theme matching:** `theme=\"auto\"` reads the `.dark` class on `<html>` — matches the DS dark mode toggle automatically. Override with explicit light/dark.",
8795
- "**Emoji sets:** Pass `set=\"apple\" | \"google\" | ...` for consistent cross-platform emoji art (defaults to native OS glyphs)."
9447
+ "**TipTap integration:** Use `createEmojiSuggestion()` (from `./extensions/emoji-suggestion`) to open a `:shortcode:` suggestion list. Works with RichChatInput and RichTextEditor."
8796
9448
  ]
8797
9449
  },
8798
9450
  "docPath": "docs/components/composed/emoji-picker.md",
8799
9451
  "defaults": {
8800
- "theme": "auto",
8801
- "previewPosition": "none",
8802
- "skinTonePosition": "search",
8803
9452
  "align": "start"
8804
9453
  },
9454
+ "subComponents": {
9455
+ "EmojiPickerPopover": {
9456
+ "props": {
9457
+ "children": {
9458
+ "type": {
9459
+ "name": "ReactNode"
9460
+ },
9461
+ "required": false,
9462
+ "description": "trigger element"
9463
+ },
9464
+ "align": {
9465
+ "type": {
9466
+ "name": "enum",
9467
+ "value": [
9468
+ "start",
9469
+ "center",
9470
+ "end"
9471
+ ]
9472
+ },
9473
+ "required": false
9474
+ }
9475
+ },
9476
+ "note": "extends EmojiPicker props"
9477
+ },
9478
+ "EmojiData": {
9479
+ "props": {
9480
+ "id": {
9481
+ "type": {
9482
+ "name": "string"
9483
+ },
9484
+ "required": false
9485
+ },
9486
+ "native": {
9487
+ "type": {
9488
+ "name": "string"
9489
+ },
9490
+ "required": false,
9491
+ "description": "the emoji character"
9492
+ },
9493
+ "shortcodes": {
9494
+ "type": {
9495
+ "name": "string"
9496
+ },
9497
+ "required": false
9498
+ }
9499
+ }
9500
+ }
9501
+ },
8805
9502
  "examples": [
8806
- "<EmojiPickerPopover onSelect={(emoji) => insertEmoji(emoji.native)}>\n <Button variant=\"ghost\" size=\"icon-sm\">😀</Button>\n</EmojiPickerPopover>\n\n<EmojiPicker onSelect={handleEmoji} theme=\"dark\" />"
9503
+ "<EmojiPickerPopover onSelect={(emoji) => insertEmoji(emoji.native)}>\n <Button variant=\"ghost\" size=\"icon-sm\">😀</Button>\n</EmojiPickerPopover>\n\n<EmojiPicker onSelect={handleEmoji} />"
8807
9504
  ],
8808
9505
  "gotchas": [
8809
- "Wraps `@emoji-mart/react` which is lazy-loaded shows a Skeleton placeholder while loading",
8810
- "`theme=\"auto\"` reads the `.dark` class on `<html>` to pick light/dark",
8811
- "EmojiPickerPopover auto-closes after selection"
9506
+ "Client-only (fetches its emoji dataset on first open) not server-safe.",
9507
+ "EmojiPickerPopover auto-closes after selection.",
9508
+ "The `set` / `theme` / `previewPosition` / `skinTonePosition` props are deprecated no-ops kept for source compatibility; the picker is native-only."
8812
9509
  ],
8813
9510
  "changes": [
8814
9511
  {
8815
9512
  "version": "0.33.0",
8816
- "summary": "**Added** `set` prop on EmojiPicker and EmojiPickerPopover — `EmojiSet` type: 'native' | 'apple' | 'google' | 'twitter' | 'facebook'"
9513
+ "summary": "**Added** `EmojiNode` TipTap extension and `createEmojiSuggestion()` factory."
8817
9514
  }
8818
9515
  ]
8819
9516
  },
@@ -9121,41 +9818,6 @@
9121
9818
  },
9122
9819
  "required": false,
9123
9820
  "description": "FilterSelect / FilterMultiSelect controls"
9124
- },
9125
- "label": {
9126
- "type": {
9127
- "name": "string"
9128
- },
9129
- "required": false
9130
- },
9131
- "value": {
9132
- "type": {
9133
- "name": "object",
9134
- "raw": "string[]"
9135
- },
9136
- "required": false
9137
- },
9138
- "onValueChange": {
9139
- "type": {
9140
- "name": "function",
9141
- "raw": "(values: string[]) => void"
9142
- },
9143
- "required": false
9144
- },
9145
- "options": {
9146
- "type": {
9147
- "name": "object",
9148
- "raw": "{ value: string; label: string }[]"
9149
- },
9150
- "required": false
9151
- },
9152
- "allLabel": {
9153
- "type": {
9154
- "name": "string"
9155
- },
9156
- "required": false,
9157
- "description": "label for the \"all\" option",
9158
- "defaultValue": "All"
9159
9821
  }
9160
9822
  },
9161
9823
  "composition": {
@@ -9174,6 +9836,76 @@
9174
9836
  "searchPlaceholder": "Search...",
9175
9837
  "allLabel": "All"
9176
9838
  },
9839
+ "subComponents": {
9840
+ "FilterSelect": {
9841
+ "props": {
9842
+ "label": {
9843
+ "type": {
9844
+ "name": "string"
9845
+ },
9846
+ "required": false
9847
+ },
9848
+ "value": {
9849
+ "type": {
9850
+ "name": "string"
9851
+ },
9852
+ "required": false
9853
+ },
9854
+ "onValueChange": {
9855
+ "type": {
9856
+ "name": "function",
9857
+ "raw": "(value: string) => void"
9858
+ },
9859
+ "required": false
9860
+ },
9861
+ "options": {
9862
+ "type": {
9863
+ "name": "object",
9864
+ "raw": "{ value: string; label: string }[]"
9865
+ },
9866
+ "required": false
9867
+ },
9868
+ "allLabel": {
9869
+ "type": {
9870
+ "name": "string"
9871
+ },
9872
+ "required": false,
9873
+ "description": "label for the \"all\" option"
9874
+ }
9875
+ }
9876
+ },
9877
+ "FilterMultiSelect": {
9878
+ "props": {
9879
+ "label": {
9880
+ "type": {
9881
+ "name": "string"
9882
+ },
9883
+ "required": false
9884
+ },
9885
+ "value": {
9886
+ "type": {
9887
+ "name": "object",
9888
+ "raw": "string[]"
9889
+ },
9890
+ "required": false
9891
+ },
9892
+ "onValueChange": {
9893
+ "type": {
9894
+ "name": "function",
9895
+ "raw": "(values: string[]) => void"
9896
+ },
9897
+ "required": false
9898
+ },
9899
+ "options": {
9900
+ "type": {
9901
+ "name": "object",
9902
+ "raw": "{ value: string; label: string }[]"
9903
+ },
9904
+ "required": false
9905
+ }
9906
+ }
9907
+ }
9908
+ },
9177
9909
  "examples": [
9178
9910
  "<FilterBar searchValue={search} onSearchChange={setSearch} onClearAll={clearFilters}>\n <FilterSelect\n label=\"Status\"\n value={status}\n onValueChange={setStatus}\n options={[{ value: 'active', label: 'Active' }, { value: 'done', label: 'Done' }]}\n />\n <FilterMultiSelect\n label=\"Assignees\"\n value={assignees}\n onValueChange={setAssignees}\n options={memberOptions}\n />\n</FilterBar>"
9179
9911
  ],
@@ -9382,42 +10114,7 @@
9382
10114
  "import": "@devalok/shilp-sutra/composed/loading-skeleton",
9383
10115
  "serverSafe": true,
9384
10116
  "description": "Exports: CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton",
9385
- "props": {
9386
- "className": {
9387
- "type": {
9388
- "name": "string"
9389
- },
9390
- "required": false
9391
- },
9392
- "rows": {
9393
- "type": {
9394
- "name": "number"
9395
- },
9396
- "required": false,
9397
- "defaultValue": 6
9398
- },
9399
- "columns": {
9400
- "type": {
9401
- "name": "number"
9402
- },
9403
- "required": false,
9404
- "defaultValue": 4
9405
- },
9406
- "cardsPerColumn": {
9407
- "type": {
9408
- "name": "number"
9409
- },
9410
- "required": false,
9411
- "defaultValue": 3
9412
- },
9413
- "showAvatar": {
9414
- "type": {
9415
- "name": "boolean"
9416
- },
9417
- "required": false,
9418
- "defaultValue": true
9419
- }
9420
- },
10117
+ "props": {},
9421
10118
  "composition": {
9422
10119
  "notes": [
9423
10120
  "**Pre-composed skeleton layouts** — CardSkeleton, TableSkeleton, BoardSkeleton, ListSkeleton. Each mimics the shape of a common DS layout so users see meaningful loading placeholders.",
@@ -9434,6 +10131,90 @@
9434
10131
  "cardsPerColumn": 3,
9435
10132
  "showAvatar": true
9436
10133
  },
10134
+ "subComponents": {
10135
+ "CardSkeleton": {
10136
+ "props": {
10137
+ "className": {
10138
+ "type": {
10139
+ "name": "string"
10140
+ },
10141
+ "required": false
10142
+ }
10143
+ }
10144
+ },
10145
+ "TableSkeleton": {
10146
+ "props": {
10147
+ "rows": {
10148
+ "type": {
10149
+ "name": "number"
10150
+ },
10151
+ "required": false,
10152
+ "defaultValue": 5
10153
+ },
10154
+ "columns": {
10155
+ "type": {
10156
+ "name": "number"
10157
+ },
10158
+ "required": false,
10159
+ "defaultValue": 4
10160
+ },
10161
+ "className": {
10162
+ "type": {
10163
+ "name": "string"
10164
+ },
10165
+ "required": false
10166
+ }
10167
+ }
10168
+ },
10169
+ "BoardSkeleton": {
10170
+ "props": {
10171
+ "columns": {
10172
+ "type": {
10173
+ "name": "number"
10174
+ },
10175
+ "required": false,
10176
+ "defaultValue": 4
10177
+ },
10178
+ "cardsPerColumn": {
10179
+ "type": {
10180
+ "name": "number"
10181
+ },
10182
+ "required": false,
10183
+ "defaultValue": 3
10184
+ },
10185
+ "className": {
10186
+ "type": {
10187
+ "name": "string"
10188
+ },
10189
+ "required": false
10190
+ }
10191
+ }
10192
+ },
10193
+ "ListSkeleton": {
10194
+ "props": {
10195
+ "rows": {
10196
+ "type": {
10197
+ "name": "number"
10198
+ },
10199
+ "required": false,
10200
+ "defaultValue": 6
10201
+ },
10202
+ "showAvatar": {
10203
+ "type": {
10204
+ "name": "boolean"
10205
+ },
10206
+ "required": false,
10207
+ "defaultValue": true
10208
+ },
10209
+ "className": {
10210
+ "type": {
10211
+ "name": "string"
10212
+ },
10213
+ "required": false
10214
+ }
10215
+ }
10216
+ }
10217
+ },
9437
10218
  "examples": [
9438
10219
  "<CardSkeleton />\n<TableSkeleton rows={8} columns={5} />\n<BoardSkeleton columns={3} cardsPerColumn={4} />\n<ListSkeleton rows={10} showAvatar={false} />"
9439
10220
  ],
@@ -9519,7 +10300,8 @@
9519
10300
  ],
9520
10301
  "peers": [
9521
10302
  "react-markdown",
9522
- "react-syntax-highlighter"
10303
+ "react-syntax-highlighter",
10304
+ "remark-gfm"
9523
10305
  ]
9524
10306
  },
9525
10307
  "master-detail": {
@@ -9565,13 +10347,6 @@
9565
10347
  "required": false,
9566
10348
  "description": "below this, stacked mobile mode activates",
9567
10349
  "defaultValue": "md"
9568
- },
9569
- "active": {
9570
- "type": {
9571
- "name": "boolean"
9572
- },
9573
- "required": false,
9574
- "description": "highlights the item"
9575
10350
  }
9576
10351
  },
9577
10352
  "composition": {
@@ -9589,6 +10364,19 @@
9589
10364
  "masterWidth": "280px",
9590
10365
  "breakpoint": "md"
9591
10366
  },
10367
+ "subComponents": {
10368
+ "MasterDetail.ListItem": {
10369
+ "props": {
10370
+ "active": {
10371
+ "type": {
10372
+ "name": "boolean"
10373
+ },
10374
+ "required": false,
10375
+ "description": "highlights the item"
10376
+ }
10377
+ }
10378
+ }
10379
+ },
9592
10380
  "examples": [
9593
10381
  "<MasterDetail selected={selectedId} onBack={() => setSelectedId(null)}>\n <MasterDetail.List>\n {items.map((item) => (\n <MasterDetail.ListItem\n key={item.id}\n active={item.id === selectedId}\n onClick={() => setSelectedId(item.id)}\n >\n {item.name}\n </MasterDetail.ListItem>\n ))}\n </MasterDetail.List>\n <MasterDetail.Detail>\n {selectedId ? <ItemDetail id={selectedId} /> : <EmptyState />}\n </MasterDetail.Detail>\n</MasterDetail>"
9594
10382
  ],
@@ -9693,7 +10481,8 @@
9693
10481
  "name": "object",
9694
10482
  "raw": "MultiSelectItem[]"
9695
10483
  },
9696
- "required": false
10484
+ "required": false,
10485
+ "description": "flat list — use `groups` for grouped rendering"
9697
10486
  },
9698
10487
  "groups": {
9699
10488
  "type": {
@@ -9789,36 +10578,6 @@
9789
10578
  },
9790
10579
  "required": false,
9791
10580
  "description": "trigger element"
9792
- },
9793
- "id": {
9794
- "type": {
9795
- "name": "string"
9796
- },
9797
- "required": false
9798
- },
9799
- "label": {
9800
- "type": {
9801
- "name": "string"
9802
- },
9803
- "required": false
9804
- },
9805
- "image": {
9806
- "type": {
9807
- "name": "string"
9808
- },
9809
- "required": false
9810
- },
9811
- "description": {
9812
- "type": {
9813
- "name": "string"
9814
- },
9815
- "required": false
9816
- },
9817
- "disabled": {
9818
- "type": {
9819
- "name": "boolean"
9820
- },
9821
- "required": false
9822
10581
  }
9823
10582
  },
9824
10583
  "composition": {
@@ -9839,6 +10598,59 @@
9839
10598
  "align": "start",
9840
10599
  "width": "{240}"
9841
10600
  },
10601
+ "subComponents": {
10602
+ "MultiSelectItem": {
10603
+ "props": {
10604
+ "id": {
10605
+ "type": {
10606
+ "name": "string"
10607
+ },
10608
+ "required": false
10609
+ },
10610
+ "label": {
10611
+ "type": {
10612
+ "name": "string"
10613
+ },
10614
+ "required": false
10615
+ },
10616
+ "image": {
10617
+ "type": {
10618
+ "name": "string"
10619
+ },
10620
+ "required": false
10621
+ },
10622
+ "description": {
10623
+ "type": {
10624
+ "name": "string"
10625
+ },
10626
+ "required": false
10627
+ },
10628
+ "disabled": {
10629
+ "type": {
10630
+ "name": "boolean"
10631
+ },
10632
+ "required": false
10633
+ }
10634
+ }
10635
+ },
10636
+ "MultiSelectGroup": {
10637
+ "props": {
10638
+ "label": {
10639
+ "type": {
10640
+ "name": "string"
10641
+ },
10642
+ "required": false
10643
+ },
10644
+ "items": {
10645
+ "type": {
10646
+ "name": "object",
10647
+ "raw": "MultiSelectItem[]"
10648
+ },
10649
+ "required": false
10650
+ }
10651
+ }
10652
+ }
10653
+ },
9842
10654
  "examples": [
9843
10655
  "<MultiSelectPopover\n items={[\n { id: '1', label: 'Alice', image: '/alice.jpg' },\n { id: '2', label: 'Bob' },\n ]}\n value={selected}\n onValueChange={setSelected}\n>\n <Button>Assign members</Button>\n</MultiSelectPopover>"
9844
10656
  ],
@@ -9905,7 +10717,7 @@
9905
10717
  "**Server-safe page-top header** with title + subtitle + breadcrumbs + actions slot. Renders Breadcrumb internally from the `breadcrumbs` array.",
9906
10718
  "**Auto-derived title:** If `title` is omitted, the last breadcrumb's `label` becomes the h1. Saves duplication when the page title matches the breadcrumb leaf.",
9907
10719
  "**Breadcrumb contract:** Last item should NOT have an `href` (it's the current page — renders as BreadcrumbPage, not a link). Items with `href` render as BreadcrumbLink.",
9908
- "**actions slot:** Typically one to three buttons (Save, Cancel, More). For larger action groups, use ButtonGroup or a toolbar.",
10720
+ "**actions slot:** Typically one to three buttons (Save, Cancel, More). The slot wraps onto its own line under the title on narrow viewports instead of forcing horizontal overflow, so multiple/wide buttons are mobile-safe. For larger action groups, use ButtonGroup or a toolbar.",
9909
10721
  "**Not for tabs / sub-navigation** — pair with Tabs rendered below PageHeader for that."
9910
10722
  ]
9911
10723
  },
@@ -10031,180 +10843,331 @@
10031
10843
  }
10032
10844
  ]
10033
10845
  },
10034
- "rich-chat-input": {
10035
- "displayName": "RichChatInput",
10846
+ "responsive-modal": {
10847
+ "displayName": "ResponsiveModal",
10036
10848
  "tier": "composed",
10037
- "import": "@devalok/shilp-sutra/composed/rich-chat-input",
10849
+ "import": "@devalok/shilp-sutra/composed/responsive-modal",
10038
10850
  "serverSafe": false,
10039
- "description": "Compact rich text chat input for unified human+AI workspaces. Built on TipTap.",
10851
+ "description": "",
10040
10852
  "props": {
10041
- "onSubmit": {
10042
- "type": {
10043
- "name": "function",
10044
- "raw": "(html: string, plainText: string) => void (REQUIRED)"
10045
- },
10046
- "required": false
10047
- },
10048
- "placeholder": {
10049
- "type": {
10050
- "name": "string"
10051
- },
10052
- "required": false,
10053
- "defaultValue": "Type a message..."
10054
- },
10055
- "disabled": {
10853
+ "open": {
10056
10854
  "type": {
10057
10855
  "name": "boolean"
10058
10856
  },
10059
10857
  "required": false,
10060
- "defaultValue": false
10061
- },
10062
- "variant": {
10063
- "type": {
10064
- "name": "enum",
10065
- "value": [
10066
- "compact",
10067
- "expanded",
10068
- "minimal"
10069
- ]
10070
- },
10071
- "required": false,
10072
- "defaultValue": "compact"
10073
- },
10074
- "maxRows": {
10075
- "type": {
10076
- "name": "number"
10077
- },
10078
- "required": false
10858
+ "description": "controlled open state"
10079
10859
  },
10080
- "enterBehavior": {
10860
+ "defaultOpen": {
10081
10861
  "type": {
10082
- "name": "enum",
10083
- "value": [
10084
- "send",
10085
- "newline"
10086
- ]
10862
+ "name": "boolean"
10087
10863
  },
10088
10864
  "required": false,
10089
- "defaultValue": "send"
10090
- },
10091
- "maxLength": {
10092
- "type": {
10093
- "name": "object",
10094
- "raw": "number — enables character counter"
10095
- },
10096
- "required": false
10097
- },
10098
- "mentions": {
10099
- "type": {
10100
- "name": "object",
10101
- "raw": "MentionItem[] — static list for @mention autocomplete"
10102
- },
10103
- "required": false
10104
- },
10105
- "onMentionSearch": {
10106
- "type": {
10107
- "name": "function",
10108
- "raw": "(query: string) => Promise<MentionItem[]> — async search"
10109
- },
10110
- "required": false
10865
+ "description": "uncontrolled initial state"
10111
10866
  },
10112
- "onMentionSelect": {
10867
+ "onOpenChange": {
10113
10868
  "type": {
10114
10869
  "name": "function",
10115
- "raw": "(item: MentionItem) => void"
10870
+ "raw": "(open: boolean) => void"
10116
10871
  },
10117
10872
  "required": false
10118
10873
  },
10119
- "onFileUpload": {
10874
+ "dismissable": {
10120
10875
  "type": {
10121
- "name": "function",
10122
- "raw": "(file: File) => Promise<{ url: string; name: string; size: number }>"
10876
+ "name": "boolean"
10123
10877
  },
10124
- "required": false
10125
- },
10126
- "onImageUpload": {
10127
- "type": {
10128
- "name": "function",
10129
- "raw": "(file: File) => Promise<string>"
10878
+ "required": false,
10879
+ "defaultValue": "true — when false, Escape / outside-click / drag cannot close; only an explicit Close or onOpenChange does"
10880
+ }
10881
+ },
10882
+ "composition": {
10883
+ "parts": [
10884
+ {
10885
+ "name": "ResponsiveModal",
10886
+ "required": true,
10887
+ "description": "root; owns open/close state and the desktop/mobile switch"
10130
10888
  },
10131
- "required": false
10132
- },
10133
- "slashCommands": {
10134
- "type": {
10135
- "name": "object",
10136
- "raw": "SlashCommandGroup[] — enables / command palette"
10889
+ {
10890
+ "name": "ResponsiveModalTrigger",
10891
+ "description": "opens the modal; use `asChild` to wrap your own button"
10137
10892
  },
10138
- "required": false
10139
- },
10140
- "onTyping": {
10141
- "type": {
10142
- "name": "function",
10143
- "raw": "(isTyping: boolean) => void — typing indicator callback"
10893
+ {
10894
+ "name": "ResponsiveModalContent",
10895
+ "description": "the switching panel: centered Dialog at md+, bottom sheet below"
10144
10896
  },
10145
- "required": false
10146
- },
10147
- "onEmpty": {
10148
- "type": {
10149
- "name": "function",
10150
- "raw": "(isEmpty: boolean) => void"
10897
+ {
10898
+ "name": "ResponsiveModalBackground",
10899
+ "slot": "behind",
10900
+ "description": "optional full-bleed layer painted at `-z-10`, clipped to the panel radius"
10151
10901
  },
10152
- "required": false
10153
- },
10154
- "isStreaming": {
10155
- "type": {
10156
- "name": "object",
10157
- "raw": "boolean (default: false) — shows stop button instead of send"
10902
+ {
10903
+ "name": "ResponsiveModalHeader",
10904
+ "slot": "top",
10905
+ "description": "pinned; stays put while the body scrolls"
10158
10906
  },
10159
- "required": false
10160
- },
10161
- "onCancel": {
10162
- "type": {
10163
- "name": "function",
10164
- "raw": "() => void — called when stop button is clicked"
10907
+ {
10908
+ "name": "ResponsiveModalTitle",
10909
+ "required": true,
10910
+ "description": "labels the dialog for accessibility"
10165
10911
  },
10166
- "required": false
10167
- },
10168
- "leadingSlot": {
10169
- "type": {
10170
- "name": "ReactNode"
10912
+ {
10913
+ "name": "ResponsiveModalDescription",
10914
+ "description": "optional subtitle"
10171
10915
  },
10172
- "required": false
10173
- },
10174
- "trailingSlot": {
10175
- "type": {
10176
- "name": "ReactNode"
10916
+ {
10917
+ "name": "ResponsiveModalBody",
10918
+ "description": "internal scroll region (min-h-0 flex-1 overflow-y-auto), capped 85dvh desktop / 90dvh mobile"
10177
10919
  },
10178
- "required": false
10179
- },
10180
- "disclaimer": {
10181
- "type": {
10182
- "name": "object",
10183
- "raw": "string — small text below the input"
10920
+ {
10921
+ "name": "ResponsiveModalFooter",
10922
+ "slot": "bottom",
10923
+ "description": "pinned action row; stacks on mobile, right-aligned inline on desktop"
10184
10924
  },
10185
- "required": false
10186
- },
10187
- "toolbar": {
10188
- "type": {
10189
- "name": "union",
10190
- "raw": "boolean | ChatToolbarItem[]"
10925
+ {
10926
+ "name": "ResponsiveModalClose",
10927
+ "description": "manual close (Content already renders a built-in close button when dismissable)"
10928
+ }
10929
+ ],
10930
+ "composesWith": [
10931
+ {
10932
+ "component": "dialog",
10933
+ "relation": "alternative-to",
10934
+ "description": "use Dialog directly when you always want a centered modal"
10191
10935
  },
10192
- "required": false,
10193
- "defaultValue": true
10194
- }
10195
- },
10196
- "composition": {
10197
- "notes": [
10198
- "**Chat-specific TipTap editor** — purpose-built for AI + human messaging. Built on RichTextEditor primitives but pre-configured for the chat UX (auto-resize, Enter-to-send, inline toolbar).",
10199
- "**Variant drives the UX envelope:** - `compact` — 2-3 line inline (chat bubble composer) - `expanded` — 5+ lines with always-visible toolbar (AI prompt input) - `minimal` — single line, toolbar on focus (reply composer, quick comment)",
10200
- "**Toolbar is opt-in per feature:** Icons only appear when their corresponding handler/prop is set. `onFileUpload` → attach button appears. `slashCommands` → slash button appears. `mentions` or `onMentionSearch` → @ button appears.",
10201
- "**Composes with Message from ui/chat:** RichChatInput is the composer; Message is the read-only render of the message after send. Use them together for a complete chat UX (RichChatInput at the bottom, MessageList above).",
10202
- "**TipTap is bundled** — no need to install `@tiptap/*` directly.",
10203
- "**For general rich text editing** (not chat — long-form docs, notes), use RichTextEditor instead.",
10204
- "**isStreaming + onCancel** — when the receiving side is streaming a response, show a stop button in place of send. Standard AI chat pattern."
10936
+ {
10937
+ "component": "sheet",
10938
+ "relation": "alternative-to",
10939
+ "description": "use Sheet directly when you always want an edge panel"
10940
+ }
10941
+ ],
10942
+ "contexts": [
10943
+ {
10944
+ "name": "ResponsiveModal",
10945
+ "effect": "provides open / isMobile / dismissable / onClose to its parts via context"
10946
+ }
10205
10947
  ]
10206
10948
  },
10207
- "docPath": "docs/components/composed/rich-chat-input.md",
10949
+ "docPath": "docs/components/composed/responsive-modal.md",
10950
+ "defaults": {
10951
+ "dismissable": true
10952
+ },
10953
+ "subComponents": {
10954
+ "ResponsiveModalContent": {
10955
+ "props": {
10956
+ "snapPoints": {
10957
+ "type": {
10958
+ "name": "object",
10959
+ "raw": "number[]"
10960
+ },
10961
+ "required": false,
10962
+ "description": "mobile only; ascending viewport-height fractions like [0.4, 0.9] the sheet rests at. Omit for a content-height sheet. Ignored on desktop"
10963
+ },
10964
+ "defaultSnapPoint": {
10965
+ "type": {
10966
+ "name": "number"
10967
+ },
10968
+ "required": false,
10969
+ "description": "mobile only; index into snapPoints the sheet opens at. Defaults to the last/tallest"
10970
+ }
10971
+ }
10972
+ }
10973
+ },
10974
+ "examples": [
10975
+ "<ResponsiveModal>\n <ResponsiveModalTrigger asChild><Button>Edit profile</Button></ResponsiveModalTrigger>\n <ResponsiveModalContent snapPoints={[0.5, 0.9]}>\n <ResponsiveModalBackground className=\"bg-linear-to-br from-accent-3 to-accent-6 opacity-40\" />\n <ResponsiveModalHeader>\n <ResponsiveModalTitle>Edit profile</ResponsiveModalTitle>\n <ResponsiveModalDescription>Changes save when you apply.</ResponsiveModalDescription>\n </ResponsiveModalHeader>\n <ResponsiveModalBody>{/* form fields — scrolls internally */}</ResponsiveModalBody>\n <ResponsiveModalFooter>\n <ResponsiveModalClose asChild><Button variant=\"soft\">Cancel</Button></ResponsiveModalClose>\n <Button>Apply</Button>\n </ResponsiveModalFooter>\n </ResponsiveModalContent>\n</ResponsiveModal>"
10976
+ ],
10977
+ "gotchas": [
10978
+ "Built on the same dialog primitive as Dialog and Sheet — focus trap, Escape, scroll lock, and portal are handled. Not server-safe (uses hooks); import in a client component.",
10979
+ "Put a `ResponsiveModalTitle` inside every modal — it sets the ARIA label. Omitting it triggers an accessibility warning.",
10980
+ "The built-in close button sits at `z-10` above `ResponsiveModalBackground` (`-z-10`); keep Header/Body/Footer in normal flow (no `relative z-*` wrapper) or a positioned wrapper will paint over the close button and eat the tap.",
10981
+ "`snapPoints` and `defaultSnapPoint` are mobile-only — they are ignored at md+ (always a centered Dialog).",
10982
+ "Height caps live on the panel (85dvh desktop / 90dvh mobile); do not add your own `max-h` to `ResponsiveModalBody` — it already scrolls.",
10983
+ "Prefer this over `DialogContent responsive` when the mobile form should be a partial bottom sheet; `responsive` collapses to a full-screen takeover that leaves dead space under short content."
10984
+ ],
10985
+ "changes": [
10986
+ {
10987
+ "version": "0.49.0",
10988
+ "summary": "Added — new component. Dialog (md+) / bottom-sheet (mobile) responsive modal with pinned header/footer, internal scroll body, optional full-bleed background slot, drag-to-dismiss, and optional mobile snap points."
10989
+ }
10990
+ ]
10991
+ },
10992
+ "rich-chat-input": {
10993
+ "displayName": "RichChatInput",
10994
+ "tier": "composed",
10995
+ "import": "@devalok/shilp-sutra/composed/rich-chat-input",
10996
+ "serverSafe": false,
10997
+ "description": "Compact rich text chat input for unified human+AI workspaces. Built on TipTap.",
10998
+ "props": {},
10999
+ "composition": {
11000
+ "notes": [
11001
+ "**Chat-specific TipTap editor** — purpose-built for AI + human messaging. Built on RichTextEditor primitives but pre-configured for the chat UX (auto-resize, Enter-to-send, inline toolbar).",
11002
+ "**Variant drives the UX envelope:** - `compact` — 2-3 line inline (chat bubble composer) - `expanded` — 5+ lines with always-visible toolbar (AI prompt input) - `minimal` — single line, toolbar on focus (reply composer, quick comment)",
11003
+ "**Toolbar is opt-in per feature:** Icons only appear when their corresponding handler/prop is set. `onFileUpload` → attach button appears. `slashCommands` → slash button appears. `mentions` or `onMentionSearch` → @ button appears.",
11004
+ "**Composes with Message from ui/chat:** RichChatInput is the composer; Message is the read-only render of the message after send. Use them together for a complete chat UX (RichChatInput at the bottom, MessageList above).",
11005
+ "**TipTap is bundled** — no need to install `@tiptap/*` directly.",
11006
+ "**For general rich text editing** (not chat — long-form docs, notes), use RichTextEditor instead.",
11007
+ "**isStreaming + onCancel** — when the receiving side is streaming a response, show a stop button in place of send. Standard AI chat pattern."
11008
+ ]
11009
+ },
11010
+ "docPath": "docs/components/composed/rich-chat-input.md",
11011
+ "subComponents": {
11012
+ "RichChatInputProps": {
11013
+ "props": {
11014
+ "onSubmit": {
11015
+ "type": {
11016
+ "name": "function",
11017
+ "raw": "(html: string, plainText: string) => void (REQUIRED)"
11018
+ },
11019
+ "required": false
11020
+ },
11021
+ "placeholder": {
11022
+ "type": {
11023
+ "name": "string"
11024
+ },
11025
+ "required": false,
11026
+ "defaultValue": "Type a message..."
11027
+ },
11028
+ "disabled": {
11029
+ "type": {
11030
+ "name": "boolean"
11031
+ },
11032
+ "required": false,
11033
+ "defaultValue": false
11034
+ },
11035
+ "variant": {
11036
+ "type": {
11037
+ "name": "enum",
11038
+ "value": [
11039
+ "compact",
11040
+ "expanded",
11041
+ "minimal"
11042
+ ]
11043
+ },
11044
+ "required": false,
11045
+ "defaultValue": "compact"
11046
+ },
11047
+ "maxRows": {
11048
+ "type": {
11049
+ "name": "number"
11050
+ },
11051
+ "required": false
11052
+ },
11053
+ "enterBehavior": {
11054
+ "type": {
11055
+ "name": "enum",
11056
+ "value": [
11057
+ "send",
11058
+ "newline"
11059
+ ]
11060
+ },
11061
+ "required": false,
11062
+ "defaultValue": "send"
11063
+ },
11064
+ "maxLength": {
11065
+ "type": {
11066
+ "name": "object",
11067
+ "raw": "number — enables character counter"
11068
+ },
11069
+ "required": false
11070
+ },
11071
+ "mentions": {
11072
+ "type": {
11073
+ "name": "object",
11074
+ "raw": "MentionItem[] — static list for @mention autocomplete"
11075
+ },
11076
+ "required": false
11077
+ },
11078
+ "onMentionSearch": {
11079
+ "type": {
11080
+ "name": "function",
11081
+ "raw": "(query: string) => Promise<MentionItem[]> — async search"
11082
+ },
11083
+ "required": false
11084
+ },
11085
+ "onMentionSelect": {
11086
+ "type": {
11087
+ "name": "function",
11088
+ "raw": "(item: MentionItem) => void"
11089
+ },
11090
+ "required": false
11091
+ },
11092
+ "onFileUpload": {
11093
+ "type": {
11094
+ "name": "function",
11095
+ "raw": "(file: File) => Promise<{ url: string; name: string; size: number }>"
11096
+ },
11097
+ "required": false
11098
+ },
11099
+ "onImageUpload": {
11100
+ "type": {
11101
+ "name": "function",
11102
+ "raw": "(file: File) => Promise<string>"
11103
+ },
11104
+ "required": false
11105
+ },
11106
+ "slashCommands": {
11107
+ "type": {
11108
+ "name": "object",
11109
+ "raw": "SlashCommandGroup[] — enables / command palette"
11110
+ },
11111
+ "required": false
11112
+ },
11113
+ "onTyping": {
11114
+ "type": {
11115
+ "name": "function",
11116
+ "raw": "(isTyping: boolean) => void — typing indicator callback"
11117
+ },
11118
+ "required": false
11119
+ },
11120
+ "onEmpty": {
11121
+ "type": {
11122
+ "name": "function",
11123
+ "raw": "(isEmpty: boolean) => void"
11124
+ },
11125
+ "required": false
11126
+ },
11127
+ "isStreaming": {
11128
+ "type": {
11129
+ "name": "object",
11130
+ "raw": "boolean (default: false) — shows stop button instead of send"
11131
+ },
11132
+ "required": false
11133
+ },
11134
+ "onCancel": {
11135
+ "type": {
11136
+ "name": "function",
11137
+ "raw": "() => void — called when stop button is clicked"
11138
+ },
11139
+ "required": false
11140
+ },
11141
+ "leadingSlot": {
11142
+ "type": {
11143
+ "name": "ReactNode"
11144
+ },
11145
+ "required": false
11146
+ },
11147
+ "trailingSlot": {
11148
+ "type": {
11149
+ "name": "ReactNode"
11150
+ },
11151
+ "required": false
11152
+ },
11153
+ "disclaimer": {
11154
+ "type": {
11155
+ "name": "object",
11156
+ "raw": "string — small text below the input"
11157
+ },
11158
+ "required": false
11159
+ },
11160
+ "toolbar": {
11161
+ "type": {
11162
+ "name": "union",
11163
+ "raw": "boolean | ChatToolbarItem[]"
11164
+ },
11165
+ "required": false,
11166
+ "defaultValue": true
11167
+ }
11168
+ }
11169
+ }
11170
+ },
10208
11171
  "examples": [
10209
11172
  "<RichChatInput\n onSubmit={(html, text) => sendMessage(html)}\n mentions={teamMembers}\n onFileUpload={uploadFile}\n slashCommands={[{ label: 'Actions', commands: [...] }]}\n/>\n\n<RichChatInput\n variant=\"expanded\"\n onSubmit={handleSubmit}\n maxLength={2000}\n disclaimer=\"AI-generated content may be inaccurate.\"\n/>\n\n<RichChatInput\n variant=\"minimal\"\n enterBehavior=\"newline\"\n onSubmit={handleReply}\n/>"
10210
11173
  ],
@@ -10225,11 +11188,6 @@
10225
11188
  "version": "0.32.0",
10226
11189
  "summary": "Initial release"
10227
11190
  }
10228
- ],
10229
- "peers": [
10230
- "@tiptap/react",
10231
- "@tiptap/starter-kit",
10232
- "@tiptap/extension-placeholder"
10233
11191
  ]
10234
11192
  },
10235
11193
  "rich-text-editor": {
@@ -10244,7 +11202,7 @@
10244
11202
  "name": "string"
10245
11203
  },
10246
11204
  "required": false,
10247
- "description": "REQUIRED, HTML string"
11205
+ "description": "HTML string"
10248
11206
  },
10249
11207
  "placeholder": {
10250
11208
  "type": {
@@ -10332,12 +11290,31 @@
10332
11290
  "placeholder": "Start writing...",
10333
11291
  "editable": true
10334
11292
  },
11293
+ "subComponents": {
11294
+ "RichTextViewer": {
11295
+ "props": {
11296
+ "content": {
11297
+ "type": {
11298
+ "name": "string"
11299
+ },
11300
+ "required": false,
11301
+ "description": "REQUIRED, HTML string"
11302
+ },
11303
+ "className": {
11304
+ "type": {
11305
+ "name": "string"
11306
+ },
11307
+ "required": false
11308
+ }
11309
+ }
11310
+ }
11311
+ },
10335
11312
  "examples": [
10336
11313
  "<RichTextEditor content={html} onChange={setHtml} placeholder=\"Write your message...\" />\n\n<RichTextEditor\n content={html}\n onChange={setHtml}\n mentions={[{ id: '1', label: 'Aarav' }]}\n onImageUpload={async (file) => uploadAndReturnUrl(file)}\n onFileUpload={async (file) => ({ url: uploadUrl, name: file.name, size: file.size })}\n/>\n\n<RichTextViewer content={savedHtml} />"
10337
11314
  ],
10338
11315
  "gotchas": [
10339
11316
  "Tiptap is bundled — no need to install `@tiptap/*` packages separately",
10340
- "Emoji picker requires `@emoji-mart/react` + `@emoji-mart/data` peers",
11317
+ "Emoji picker (frimousse) + its dataset are bundled too — no emoji peers to install (native-only since the frimousse migration)",
10341
11318
  "Images without `onImageUpload` are stored as base64 in HTML — large images bloat content",
10342
11319
  "Mention rendering in viewer always works (no mention props needed, just the HTML)",
10343
11320
  "Features: bold, italic, underline, strikethrough, highlight, headings, blockquote, lists, task lists, code, links, images, file attachments, mentions, emoji, text alignment, horizontal rule"
@@ -10371,11 +11348,6 @@
10371
11348
  "version": "0.1.1",
10372
11349
  "summary": "**Fixed** Added content sync effect so editor updates when `content` prop changes externally"
10373
11350
  }
10374
- ],
10375
- "peers": [
10376
- "@tiptap/react",
10377
- "@tiptap/starter-kit",
10378
- "@tiptap/extension-placeholder"
10379
11351
  ]
10380
11352
  },
10381
11353
  "schedule-view": {
@@ -10452,7 +11424,7 @@
10452
11424
  "**Day / Week calendar view** for time-block display (meetings, shifts, availability). Not a full calendar app — no month view, no drag-to-create.",
10453
11425
  "**Event data is consumer-owned:** You pass `events` as an array; ScheduleView doesn't fetch, doesn't cache, doesn't expand recurring events. All scheduling logic lives in your app.",
10454
11426
  "**Event click + slot click** — `onEventClick` for existing events; `onSlotClick` for creating new events (fires with start/end of the empty slot).",
10455
- "**Color vocabulary matches the DS** — `primary/success/warning/error/info/neutral`. Map your event types to these at the data layer.",
11427
+ "**Color vocabulary matches the DS** — `accent/success/warning/error/info/neutral`. Map your event types to these at the data layer.",
10456
11428
  "**endHour is exclusive:** `endHour=18` means the last visible slot starts at 17:30 (with 30min slots). Match your UX expectation: 9-5 typically means `startHour=9, endHour=18`.",
10457
11429
  "**Pairs with date-picker/composed** — use DatePicker or DateRangePicker to choose which date to show; pass that as ScheduleView's `date`."
10458
11430
  ]
@@ -10472,10 +11444,17 @@
10472
11444
  "Events that span outside `startHour`/`endHour` may be clipped"
10473
11445
  ],
10474
11446
  "changes": [
11447
+ {
11448
+ "version": "0.49.0",
11449
+ "summary": "**BREAKING** `ScheduleEvent.color` value `\"primary\"` renamed `\"accent\"` (DS colour vocabulary). It was the default, so untyped events are unaffected."
11450
+ },
10475
11451
  {
10476
11452
  "version": "0.1.0",
10477
11453
  "summary": "**Added** Initial release"
10478
11454
  }
11455
+ ],
11456
+ "peers": [
11457
+ "date-fns"
10479
11458
  ]
10480
11459
  },
10481
11460
  "simple-tooltip": {
@@ -10883,28 +11862,7 @@
10883
11862
  "import": "@devalok/shilp-sutra/shell/command-registry",
10884
11863
  "serverSafe": false,
10885
11864
  "description": "Exports: CommandRegistryProvider, useCommandRegistry",
10886
- "props": {
10887
- "children": {
10888
- "type": {
10889
- "name": "ReactNode"
10890
- },
10891
- "required": false
10892
- },
10893
- "registry": {
10894
- "type": {
10895
- "name": "object",
10896
- "raw": "CommandRegistry"
10897
- },
10898
- "required": true
10899
- },
10900
- "Returns": {
10901
- "type": {
10902
- "name": "union",
10903
- "raw": "CommandRegistry | null"
10904
- },
10905
- "required": false
10906
- }
10907
- },
11865
+ "props": {},
10908
11866
  "composition": {
10909
11867
  "notes": [
10910
11868
  "**Context provider for AppCommandPalette.** Registers page-level navigation items that the command palette surfaces as commands.",
@@ -10915,6 +11873,36 @@
10915
11873
  ]
10916
11874
  },
10917
11875
  "docPath": "docs/components/shell/command-registry.md",
11876
+ "subComponents": {
11877
+ "CommandRegistryProvider": {
11878
+ "props": {
11879
+ "children": {
11880
+ "type": {
11881
+ "name": "ReactNode"
11882
+ },
11883
+ "required": false
11884
+ },
11885
+ "registry": {
11886
+ "type": {
11887
+ "name": "object",
11888
+ "raw": "CommandRegistry"
11889
+ },
11890
+ "required": true
11891
+ }
11892
+ }
11893
+ },
11894
+ "useCommandRegistry hook": {
11895
+ "props": {
11896
+ "Returns": {
11897
+ "type": {
11898
+ "name": "union",
11899
+ "raw": "CommandRegistry | null"
11900
+ },
11901
+ "required": false
11902
+ }
11903
+ }
11904
+ }
11905
+ },
10918
11906
  "examples": [
10919
11907
  "<CommandRegistryProvider\n registry={{\n pages: [\n { id: 'dashboard', label: 'Dashboard', icon: <IconHome />, path: '/dashboard' },\n { id: 'projects', label: 'Projects', icon: <IconFolder />, path: '/projects' },\n ],\n adminPages: [\n { id: 'users', label: 'Manage Users', icon: <IconUsers />, path: '/admin/users' },\n ],\n }}\n>\n <App />\n</CommandRegistryProvider>"
10920
11908
  ],
@@ -10950,13 +11938,6 @@
10950
11938
  "name": "ReactNode"
10951
11939
  },
10952
11940
  "required": false
10953
- },
10954
- "Returns": {
10955
- "type": {
10956
- "name": "object",
10957
- "raw": "LinkComponent"
10958
- },
10959
- "required": false
10960
11941
  }
10961
11942
  },
10962
11943
  "composition": {
@@ -10970,6 +11951,19 @@
10970
11951
  ]
10971
11952
  },
10972
11953
  "docPath": "docs/components/shell/link-context.md",
11954
+ "subComponents": {
11955
+ "useLink hook": {
11956
+ "props": {
11957
+ "Returns": {
11958
+ "type": {
11959
+ "name": "object",
11960
+ "raw": "LinkComponent"
11961
+ },
11962
+ "required": false
11963
+ }
11964
+ }
11965
+ }
11966
+ },
10973
11967
  "examples": [
10974
11968
  "import Link from 'next/link'\n\n<LinkProvider component={Link}>\n <AppSidebar ... />\n <BottomNavbar ... />\n</LinkProvider>"
10975
11969
  ],
@@ -11246,102 +12240,655 @@
11246
12240
  "name": "string"
11247
12241
  },
11248
12242
  "required": false
12243
+ }
12244
+ },
12245
+ "composition": {
12246
+ "notes": [
12247
+ "**Composition-based, NOT data-driven.** Use dot-notation subcomponents (`TopBar.Left`, `TopBar.Center`, `TopBar.Right`, `TopBar.Section`, `TopBar.IconButton`, `TopBar.Title`, `TopBar.UserMenu`) to assemble. No \"props config\" — explicit JSX.",
12248
+ "**Two-zone vs three-zone layout** — adding `TopBar.Center` flips the root from `flex` to CSS grid (`1fr auto 1fr`) for true centering. Standard apps are two-zone (Left + Right); dashboards with prominent search are three-zone.",
12249
+ "**Required providers:** - `SidebarProvider` — for SidebarTrigger inside `TopBar.Left` to work - `LinkProvider` — for TopBar.UserMenu's menu items that use `href`",
12250
+ "**NotificationCenter lives inside TopBar.Right** — it's a complete bell+popover component. Drop it in a TopBar.Section next to other icon buttons.",
12251
+ "**UserMenu is composable:** `userMenuItems` inserts custom items between the built-in Profile and the color-mode toggle. Each item can navigate (href), run an action (onClick), or show a separator/badge/color decoration.",
12252
+ "**Responsive hiding:** Actions that shouldn't appear on mobile use `className=\"hidden md:flex\"` on the IconButton — the component doesn't enforce mobile hiding; that's layout responsibility.",
12253
+ "**Pairs with AppSidebar** — desktop app shell is typically `<TopBar>` + `<AppSidebar>` + main content region."
12254
+ ]
12255
+ },
12256
+ "docPath": "docs/components/shell/top-bar.md",
12257
+ "subComponents": {
12258
+ "TopBar.Left": {
12259
+ "props": {
12260
+ "children": {
12261
+ "type": {
12262
+ "name": "ReactNode"
12263
+ },
12264
+ "required": false
12265
+ },
12266
+ "className": {
12267
+ "type": {
12268
+ "name": "string"
12269
+ },
12270
+ "required": false
12271
+ }
12272
+ }
11249
12273
  },
11250
- "gap": {
12274
+ "TopBar.Center": {
12275
+ "props": {
12276
+ "children": {
12277
+ "type": {
12278
+ "name": "ReactNode"
12279
+ },
12280
+ "required": false
12281
+ },
12282
+ "className": {
12283
+ "type": {
12284
+ "name": "string"
12285
+ },
12286
+ "required": false
12287
+ }
12288
+ }
12289
+ },
12290
+ "TopBar.Right": {
12291
+ "props": {
12292
+ "children": {
12293
+ "type": {
12294
+ "name": "ReactNode"
12295
+ },
12296
+ "required": false
12297
+ },
12298
+ "className": {
12299
+ "type": {
12300
+ "name": "string"
12301
+ },
12302
+ "required": false
12303
+ }
12304
+ }
12305
+ },
12306
+ "TopBar.Section": {
12307
+ "props": {
12308
+ "gap": {
12309
+ "type": {
12310
+ "name": "enum",
12311
+ "value": [
12312
+ "tight",
12313
+ "default",
12314
+ "loose"
12315
+ ]
12316
+ },
12317
+ "required": false,
12318
+ "defaultValue": "default"
12319
+ },
12320
+ "children": {
12321
+ "type": {
12322
+ "name": "ReactNode"
12323
+ },
12324
+ "required": false
12325
+ },
12326
+ "className": {
12327
+ "type": {
12328
+ "name": "string"
12329
+ },
12330
+ "required": false
12331
+ }
12332
+ }
12333
+ },
12334
+ "TopBar.IconButton": {
12335
+ "props": {
12336
+ "icon": {
12337
+ "type": {
12338
+ "name": "ReactNode"
12339
+ },
12340
+ "required": false
12341
+ },
12342
+ "tooltip": {
12343
+ "type": {
12344
+ "name": "string"
12345
+ },
12346
+ "required": false
12347
+ }
12348
+ }
12349
+ },
12350
+ "TopBar.Title": {
12351
+ "props": {
12352
+ "children": {
12353
+ "type": {
12354
+ "name": "ReactNode"
12355
+ },
12356
+ "required": false
12357
+ },
12358
+ "className": {
12359
+ "type": {
12360
+ "name": "string"
12361
+ },
12362
+ "required": false
12363
+ }
12364
+ }
12365
+ },
12366
+ "TopBar.UserMenu": {
12367
+ "props": {
12368
+ "user": {
12369
+ "type": {
12370
+ "name": "object",
12371
+ "raw": "TopBarUser — { name, email?, image? }"
12372
+ },
12373
+ "required": false
12374
+ },
12375
+ "onNavigate": {
12376
+ "type": {
12377
+ "name": "function",
12378
+ "raw": "(path: string) => void"
12379
+ },
12380
+ "required": false
12381
+ },
12382
+ "onLogout": {
12383
+ "type": {
12384
+ "name": "function",
12385
+ "raw": "() => void"
12386
+ },
12387
+ "required": false
12388
+ },
12389
+ "userMenuItems": {
12390
+ "type": {
12391
+ "name": "object",
12392
+ "raw": "UserMenuItem[]"
12393
+ },
12394
+ "required": false
12395
+ },
12396
+ "className": {
12397
+ "type": {
12398
+ "name": "string"
12399
+ },
12400
+ "required": false
12401
+ }
12402
+ }
12403
+ }
12404
+ },
12405
+ "examples": [
12406
+ "<TopBar>\n <TopBar.Left>\n <SidebarTrigger />\n <TopBar.Title>Dashboard</TopBar.Title>\n </TopBar.Left>\n <TopBar.Right>\n <TopBar.Section gap=\"tight\">\n <TopBar.IconButton icon={<IconSearch />} tooltip=\"Search (Ctrl+K)\" onClick={openSearch} />\n <NotificationCenter notifications={notifications} />\n <TopBar.IconButton icon={<IconSparkles />} tooltip=\"AI Chat\" onClick={openAI} />\n </TopBar.Section>\n <TopBar.UserMenu\n user={{ name: 'John', email: 'john@example.com' }}\n onNavigate={(p) => router.push(p)}\n onLogout={handleLogout}\n userMenuItems={[\n { label: 'Changelog', icon: <IconNews />, href: '/changelog', badge: '3' },\n ]}\n />\n </TopBar.Right>\n</TopBar>",
12407
+ "<TopBar>\n <TopBar.Left>\n <SidebarTrigger />\n <TopBar.Title>Dashboard</TopBar.Title>\n </TopBar.Left>\n <TopBar.Center>\n <SearchBarTrigger />\n </TopBar.Center>\n <TopBar.Right>\n <TopBar.Section gap=\"tight\">\n <TopBar.IconButton icon={<IconBell />} tooltip=\"Notifications\" onClick={fn} />\n </TopBar.Section>\n <TopBar.UserMenu user={user} onLogout={logout} />\n </TopBar.Right>\n</TopBar>"
12408
+ ],
12409
+ "gotchas": [
12410
+ "Without `TopBar.Center`, layout is flex (two-zone). With it, layout switches to CSS grid `1fr auto 1fr` for true centering.",
12411
+ "`TopBar.IconButton` renders any number of action buttons — no artificial limit. Use responsive hiding (`className=\"hidden md:flex\"`) for mobile.",
12412
+ "`TopBar.UserMenu` includes Profile link, color mode toggle, and logout automatically. `userMenuItems` are inserted between Profile and the toggle.",
12413
+ "Requires SidebarProvider wrapper for SidebarTrigger to work."
12414
+ ],
12415
+ "changes": [
12416
+ {
12417
+ "version": "0.19.0",
12418
+ "summary": "**BREAKING** Rewritten as composition API. Old props-based API removed (`pageTitle`, `onSearchClick`, `onAiChatClick`, `notificationSlot`, `mobileLogo` props)."
12419
+ },
12420
+ {
12421
+ "version": "0.27.2",
12422
+ "summary": "**Fixed** UserMenu email truncation — long emails now truncate instead of overflowing the dropdown"
12423
+ },
12424
+ {
12425
+ "version": "0.7.0",
12426
+ "summary": "**Added** `userMenuItems` prop for custom dropdown items"
12427
+ },
12428
+ {
12429
+ "version": "0.1.1",
12430
+ "summary": "**Changed** Decoupled from Next.js via LinkProvider"
12431
+ },
12432
+ {
12433
+ "version": "0.1.0",
12434
+ "summary": "**Added** Initial release"
12435
+ }
12436
+ ]
12437
+ },
12438
+ "ai-command-provider": {
12439
+ "displayName": "AICommandProvider",
12440
+ "tier": "ai",
12441
+ "import": "@devalok/shilp-sutra/ai/ai-command-provider",
12442
+ "serverSafe": false,
12443
+ "description": "Context provider for the AI command system. Supplies custom block renderers, the action handler, and the agent identity to `AIConversation` / `BlockRenderer` below it, so you configure them once instead of threading props through every message. Ships a `useAICommand()` hook to read the context.",
12444
+ "props": {
12445
+ "children": {
11251
12446
  "type": {
11252
- "name": "enum",
11253
- "value": [
11254
- "tight",
11255
- "default",
11256
- "loose"
11257
- ]
12447
+ "name": "ReactNode"
11258
12448
  },
11259
- "required": false,
11260
- "defaultValue": "default"
12449
+ "required": true
11261
12450
  },
11262
- "icon": {
12451
+ "customBlocks": {
11263
12452
  "type": {
11264
- "name": "ReactNode"
12453
+ "name": "object",
12454
+ "raw": "Record<string, ComponentType<BlockComponentProps>> — custom block-type renderers available to all descendants"
11265
12455
  },
11266
12456
  "required": false
11267
12457
  },
11268
- "tooltip": {
12458
+ "onAction": {
11269
12459
  "type": {
11270
- "name": "string"
12460
+ "name": "function",
12461
+ "raw": "(actionId: string, type: \"confirm\" | \"cancel\" | \"undo\") => void — default action handler for descendant blocks"
11271
12462
  },
11272
12463
  "required": false
11273
12464
  },
11274
- "user": {
12465
+ "agent": {
11275
12466
  "type": {
11276
12467
  "name": "object",
11277
- "raw": "TopBarUser — { name, email?, image? }"
12468
+ "raw": "{ name: string, icon?: IconInput } — default agent identity for assistant messages"
12469
+ },
12470
+ "required": false
12471
+ }
12472
+ },
12473
+ "composition": {
12474
+ "notes": [
12475
+ "**Configure once** — set `customBlocks`, `onAction`, and `agent` here; `AIConversation` and `BlockRenderer` read them via context. Per-component props still win over the context (prop overrides provider).",
12476
+ "**`useAICommand()`** — returns the context (`{ customBlocks, onAction, agent }`) or `null` when no provider is mounted. Custom blocks can use it to reach the shared action handler.",
12477
+ "**Optional** — `AIConversation`/`BlockRenderer` work without a provider if you pass their props directly; the provider is a convenience for app-wide config."
12478
+ ]
12479
+ },
12480
+ "docPath": "docs/components/ai/ai-command-provider.md",
12481
+ "examples": [
12482
+ "<AICommandProvider\n agent={{ name: 'Devadoot', icon: <IconSparkles /> }}\n customBlocks={{ chart: ChartBlock }}\n onAction={(id, type) => handleAction(id, type)}\n>\n <AIConversation messages={messages} />\n</AICommandProvider>\n\n// Read the context in a descendant:\nfunction MyBlock() {\n const ctx = useAICommand() // { customBlocks, onAction, agent } | null\n // ...\n}"
12483
+ ],
12484
+ "gotchas": [
12485
+ "Client component — mount inside a client boundary.",
12486
+ "`useAICommand()` returns `null` (not a throw) when there's no provider — guard for it in custom blocks."
12487
+ ],
12488
+ "changes": [
12489
+ {
12490
+ "version": "0.49.0",
12491
+ "summary": "**Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP)."
12492
+ }
12493
+ ]
12494
+ },
12495
+ "block-renderer": {
12496
+ "displayName": "BlockRenderer",
12497
+ "tier": "ai",
12498
+ "import": "@devalok/shilp-sutra/ai/block-renderer",
12499
+ "serverSafe": false,
12500
+ "description": "Renders an ordered list of typed AI \"blocks\" — the structured chunks an assistant/ server emits instead of plain text. A registry maps each block's `type` to a React component; consumers can register their own types. This doc also covers the block system and how to author a custom block.",
12501
+ "props": {
12502
+ "blocks": {
12503
+ "type": {
12504
+ "name": "object",
12505
+ "raw": "Block[] (required) — ordered blocks to render"
11278
12506
  },
11279
12507
  "required": false
11280
12508
  },
11281
- "onNavigate": {
12509
+ "onAction": {
11282
12510
  "type": {
11283
12511
  "name": "function",
11284
- "raw": "(path: string) => void"
12512
+ "raw": "(actionId: string, type: \"confirm\" | \"cancel\" | \"undo\") => void — fired by interactive blocks (e.g. confirm)"
11285
12513
  },
11286
12514
  "required": false
11287
12515
  },
11288
- "onLogout": {
12516
+ "customBlocks": {
12517
+ "type": {
12518
+ "name": "object",
12519
+ "raw": "Record<string, ComponentType<BlockComponentProps>> — extra type→component renderers, merged OVER the built-ins"
12520
+ },
12521
+ "required": false,
12522
+ "description": "prop wins over context"
12523
+ },
12524
+ "staggerDelay": {
12525
+ "type": {
12526
+ "name": "object",
12527
+ "raw": "number — ms between each block's entrance animation"
12528
+ },
12529
+ "required": false,
12530
+ "description": "default 50"
12531
+ },
12532
+ "className": {
12533
+ "type": {
12534
+ "name": "string"
12535
+ },
12536
+ "required": false
12537
+ }
12538
+ },
12539
+ "composition": {
12540
+ "notes": [
12541
+ "**The block system** — the AI conversation renders assistant output as a `Block[]`. Each block has a `type` (string) and a `data` payload. `BlockRenderer` looks up the type in its registry and renders the matching component; an unknown type falls back to an `Alert` showing the raw JSON (so a new server-emitted type degrades gracefully instead of crashing).",
12542
+ "**Built-in block types** (9): `text` (Markdown prose), `table` (tabular data), `confirm` (action confirmation — confirm/cancel buttons + a \"Why this action?\" rationale drawer), `success` / `error` / `info` (status messages), `loading` (pending indicator), `divider` (separator), `stat_row` (a row of metric cards, composes `StatCard`).",
12543
+ "**Confidence** — every block may carry `confidence: \"high\" | \"medium\" | \"low\"`. Low-confidence blocks get a faint warning wash + a \"Low confidence\" chip (owned by the shared `BlockShell` wrapper, so the treatment is consistent across all block types). This is an AI-native affordance: the UI signals how sure the model is.",
12544
+ "**Writing a custom block** — a block component receives `BlockComponentProps<T>` (`data`, `confidence`, `onAction`, `blockId`). Wrap your content in `BlockShell` to inherit the confidence treatment. Register it via `customBlocks` (on `BlockRenderer` or `AICommandProvider`) keyed by the `type` string your server emits.",
12545
+ "**Two public block subpaths** — `text` and `error` import `react-markdown` + `remark-gfm` (a Markdown peer dependency). They were split out of the `ai/blocks` barrel in 0.40.0 so consumers don't pull those peers unless they render Markdown. Import them directly when needed: `@devalok/shilp-sutra/ai/blocks/text`, `@devalok/shilp-sutra/ai/blocks/error`.",
12546
+ "**Provider merge** — `customBlocks` from `AICommandProvider` (context) are merged with the `customBlocks` prop; the prop wins on key collision. Same for `onAction`."
12547
+ ]
12548
+ },
12549
+ "docPath": "docs/components/ai/block-renderer.md",
12550
+ "examples": [
12551
+ "// Render server-emitted blocks:\n<BlockRenderer\n blocks={message.blocks}\n onAction={(id, type) => handleAction(id, type)}\n/>\n\n// Register a custom block type:\nfunction ChartBlock({ data }) {\n return <MyChart series={data.series} />\n}\n<BlockRenderer\n blocks={message.blocks}\n customBlocks={{ chart: ChartBlock }}\n/>"
12552
+ ],
12553
+ "gotchas": [
12554
+ "Client component — mount inside a client boundary.",
12555
+ "Requires a mounted `MotionProvider` (block entrances respect reduced-motion).",
12556
+ "Rendering `text`/`error` blocks requires the `react-markdown` + `remark-gfm` peer dependencies — install them if your blocks include Markdown.",
12557
+ "The `ai/blocks/*` components are an implementation detail of the registry; consume blocks via `BlockRenderer`/`AIConversation`, not by importing each block (except the two documented Markdown subpaths)."
12558
+ ],
12559
+ "changes": [
12560
+ {
12561
+ "version": "0.49.0",
12562
+ "summary": "**Added** Component + block-system documentation (the AI layer is now covered by the docs gate + hosted MCP)."
12563
+ }
12564
+ ]
12565
+ },
12566
+ "command-bar": {
12567
+ "displayName": "CommandBar",
12568
+ "tier": "ai",
12569
+ "import": "@devalok/shilp-sutra/ai/command-bar",
12570
+ "serverSafe": false,
12571
+ "description": "A unified AI command input with three layout variants. Supports natural-language submission (`onSubmit`) and, optionally, command-palette filtering (`groups`) in the same bar. Shows an animated brand-gradient border while processing.",
12572
+ "props": {
12573
+ "onSubmit": {
11289
12574
  "type": {
11290
12575
  "name": "function",
11291
- "raw": "() => void"
12576
+ "raw": "(query: string) => void — called on Enter (natural-language submission)"
12577
+ },
12578
+ "required": false
12579
+ },
12580
+ "state": {
12581
+ "type": {
12582
+ "name": "union",
12583
+ "raw": "\"idle\" | \"typing\" | \"processing\" | \"responded\" — drives visual feedback"
12584
+ },
12585
+ "required": false,
12586
+ "description": "gradient border, placeholder"
12587
+ },
12588
+ "groups": {
12589
+ "type": {
12590
+ "name": "object",
12591
+ "raw": "CommandGroup[] — when provided, enables command-palette filtering alongside AI submission"
12592
+ },
12593
+ "required": false
12594
+ },
12595
+ "onSearch": {
12596
+ "type": {
12597
+ "name": "function",
12598
+ "raw": "(query: string) => void — fired as the query changes (palette mode)"
11292
12599
  },
11293
12600
  "required": false
11294
12601
  },
11295
- "userMenuItems": {
12602
+ "emptyMessage": {
11296
12603
  "type": {
11297
12604
  "name": "object",
11298
- "raw": "UserMenuItem[]"
12605
+ "raw": "string — text when a palette search yields nothing"
12606
+ },
12607
+ "required": false
12608
+ },
12609
+ "emptyState": {
12610
+ "type": {
12611
+ "name": "ReactNode"
12612
+ },
12613
+ "required": false
12614
+ },
12615
+ "variant": {
12616
+ "type": {
12617
+ "name": "union",
12618
+ "raw": "\"hero\" | \"inline\" | \"floating\" — layout"
12619
+ },
12620
+ "required": false,
12621
+ "description": "default \"hero\""
12622
+ },
12623
+ "placeholder": {
12624
+ "type": {
12625
+ "name": "union",
12626
+ "raw": "string | string[] — static text, or an array that rotates on an interval"
12627
+ },
12628
+ "required": false
12629
+ },
12630
+ "placeholderInterval": {
12631
+ "type": {
12632
+ "name": "object",
12633
+ "raw": "number — rotation interval in ms when placeholder is an array"
12634
+ },
12635
+ "required": false,
12636
+ "description": "default 4000"
12637
+ },
12638
+ "greeting": {
12639
+ "type": {
12640
+ "name": "object",
12641
+ "raw": "string — text above the input"
12642
+ },
12643
+ "required": false,
12644
+ "description": "hero variant"
12645
+ },
12646
+ "hints": {
12647
+ "type": {
12648
+ "name": "object",
12649
+ "raw": "string[] — hint strings below the input"
12650
+ },
12651
+ "required": false,
12652
+ "description": "hero variant"
12653
+ },
12654
+ "agentName": {
12655
+ "type": {
12656
+ "name": "string"
12657
+ },
12658
+ "required": false
12659
+ },
12660
+ "agentIcon": {
12661
+ "type": {
12662
+ "name": "ReactNode"
12663
+ },
12664
+ "required": false
12665
+ },
12666
+ "open": {
12667
+ "type": {
12668
+ "name": "object",
12669
+ "raw": "boolean — controlled open state"
12670
+ },
12671
+ "required": false,
12672
+ "description": "floating variant"
12673
+ },
12674
+ "defaultOpen": {
12675
+ "type": {
12676
+ "name": "object",
12677
+ "raw": "boolean — uncontrolled initial open"
12678
+ },
12679
+ "required": false,
12680
+ "description": "floating variant"
12681
+ },
12682
+ "onOpenChange": {
12683
+ "type": {
12684
+ "name": "function",
12685
+ "raw": "(open: boolean) => void — floating variant"
12686
+ },
12687
+ "required": false
12688
+ },
12689
+ "keybinding": {
12690
+ "type": {
12691
+ "name": "union",
12692
+ "raw": "string | string[] | false — global toggle for the floating bar"
12693
+ },
12694
+ "required": false,
12695
+ "description": "default \"mod+j\""
12696
+ },
12697
+ "disabled": {
12698
+ "type": {
12699
+ "name": "boolean"
12700
+ },
12701
+ "required": false
12702
+ },
12703
+ "maxHeight": {
12704
+ "type": {
12705
+ "name": "union",
12706
+ "raw": "string | number — cap on the results/scroll region"
12707
+ },
12708
+ "required": false,
12709
+ "description": "default \"320px\""
12710
+ },
12711
+ "children": {
12712
+ "type": {
12713
+ "name": "ReactNode"
11299
12714
  },
11300
12715
  "required": false
11301
12716
  }
11302
12717
  },
11303
12718
  "composition": {
11304
12719
  "notes": [
11305
- "**Composition-based, NOT data-driven.** Use dot-notation subcomponents (`TopBar.Left`, `TopBar.Center`, `TopBar.Right`, `TopBar.Section`, `TopBar.IconButton`, `TopBar.Title`, `TopBar.UserMenu`) to assemble. No \"props config\" explicit JSX.",
11306
- "**Two-zone vs three-zone layout** — adding `TopBar.Center` flips the root from `flex` to CSS grid (`1fr auto 1fr`) for true centering. Standard apps are two-zone (Left + Right); dashboards with prominent search are three-zone.",
11307
- "**Required providers:** - `SidebarProvider` for SidebarTrigger inside `TopBar.Left` to work - `LinkProvider` for TopBar.UserMenu's menu items that use `href`",
11308
- "**NotificationCenter lives inside TopBar.Right** — it's a complete bell+popover component. Drop it in a TopBar.Section next to other icon buttons.",
11309
- "**UserMenu is composable:** `userMenuItems` inserts custom items between the built-in Profile and the color-mode toggle. Each item can navigate (href), run an action (onClick), or show a separator/badge/color decoration.",
11310
- "**Responsive hiding:** Actions that shouldn't appear on mobile use `className=\"hidden md:flex\"` on the IconButton — the component doesn't enforce mobile hiding; that's layout responsibility.",
11311
- "**Pairs with AppSidebar** — desktop app shell is typically `<TopBar>` + `<AppSidebar>` + main content region."
12720
+ "**Two modes in one bar** pass `onSubmit` for natural-language AI; add `groups` to also get command-palette filtering (arrow-key navigation, grouped items). Reuses `CommandGroup`/`CommandItem` from composed/command-palette.",
12721
+ "**`floating` reuses the Dialog primitive** (`DialogContentRaw`) with a global keybinding same overlay pattern as CommandPalette, so focus-trap/Escape/scroll-lock come for free.",
12722
+ "**State-driven feedback** set `state=\"processing\"` to show the animated brand-gradient border; `\"responded\"` to settle it. Wire `state` to your agent's lifecycle.",
12723
+ "**Placeholder rotation** — pass an array to `placeholder` for the rotating-prompt effect (paused while typing; respects reduced-motion).",
12724
+ "**Pairs with `AIConversation`** CommandBar is the input; AIConversation renders the response thread."
11312
12725
  ]
11313
12726
  },
11314
- "docPath": "docs/components/shell/top-bar.md",
12727
+ "docPath": "docs/components/ai/command-bar.md",
11315
12728
  "examples": [
11316
- "<TopBar>\n <TopBar.Left>\n <SidebarTrigger />\n <TopBar.Title>Dashboard</TopBar.Title>\n </TopBar.Left>\n <TopBar.Right>\n <TopBar.Section gap=\"tight\">\n <TopBar.IconButton icon={<IconSearch />} tooltip=\"Search (Ctrl+K)\" onClick={openSearch} />\n <NotificationCenter notifications={notifications} />\n <TopBar.IconButton icon={<IconSparkles />} tooltip=\"AI Chat\" onClick={openAI} />\n </TopBar.Section>\n <TopBar.UserMenu\n user={{ name: 'John', email: 'john@example.com' }}\n onNavigate={(p) => router.push(p)}\n onLogout={handleLogout}\n userMenuItems={[\n { label: 'Changelog', icon: <IconNews />, href: '/changelog', badge: '3' },\n ]}\n />\n </TopBar.Right>\n</TopBar>",
11317
- "<TopBar>\n <TopBar.Left>\n <SidebarTrigger />\n <TopBar.Title>Dashboard</TopBar.Title>\n </TopBar.Left>\n <TopBar.Center>\n <SearchBarTrigger />\n </TopBar.Center>\n <TopBar.Right>\n <TopBar.Section gap=\"tight\">\n <TopBar.IconButton icon={<IconBell />} tooltip=\"Notifications\" onClick={fn} />\n </TopBar.Section>\n <TopBar.UserMenu user={user} onLogout={logout} />\n </TopBar.Right>\n</TopBar>"
12729
+ "// Hero variant — the primary AI entry point on a dashboard:\n<CommandBar\n variant=\"hero\"\n greeting=\"What can I help with?\"\n placeholder={['Summarize this project…', 'Draft a status update…', 'Find overdue tasks…']}\n hints={['⌘J to open anywhere', 'Ask in plain English']}\n state={aiState}\n onSubmit={(q) => runAgent(q)}\n/>\n\n// Floating variant global ⌘J overlay, palette + AI in one:\n<CommandBar\n variant=\"floating\"\n keybinding=\"mod+j\"\n groups={commandGroups}\n onSearch={setQuery}\n onSubmit={(q) => runAgent(q)}\n/>"
11318
12730
  ],
11319
12731
  "gotchas": [
11320
- "Without `TopBar.Center`, layout is flex (two-zone). With it, layout switches to CSS grid `1fr auto 1fr` for true centering.",
11321
- "`TopBar.IconButton` renders any number of action buttons — no artificial limit. Use responsive hiding (`className=\"hidden md:flex\"`) for mobile.",
11322
- "`TopBar.UserMenu` includes Profile link, color mode toggle, and logout automatically. `userMenuItems` are inserted between Profile and the toggle.",
11323
- "Requires SidebarProvider wrapper for SidebarTrigger to work."
12732
+ "Client component mount inside a client boundary.",
12733
+ "Requires a mounted `MotionProvider`.",
12734
+ "`keybinding` only applies to the `floating` variant; pass `false` to disable the global shortcut.",
12735
+ "Largest component in the AI layer (3 variants share one implementation) — prefer `inline`/`hero` for embedded bars, `floating` for the app-wide launcher."
11324
12736
  ],
11325
12737
  "changes": [
11326
12738
  {
11327
- "version": "0.19.0",
11328
- "summary": "**BREAKING** Rewritten as composition API. Old props-based API removed (`pageTitle`, `onSearchClick`, `onAiChatClick`, `notificationSlot`, `mobileLogo` props)."
12739
+ "version": "0.49.0",
12740
+ "summary": "**Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP)."
12741
+ }
12742
+ ]
12743
+ },
12744
+ "conversation": {
12745
+ "displayName": "AIConversation",
12746
+ "tier": "ai",
12747
+ "import": "@devalok/shilp-sutra/ai/conversation",
12748
+ "serverSafe": false,
12749
+ "description": "A scrollable AI conversation thread: user + assistant turns, streaming processing steps, an agent header, and structured content blocks (rendered via BlockRenderer) with confirm/cancel/undo action support.",
12750
+ "props": {
12751
+ "messages": {
12752
+ "type": {
12753
+ "name": "object",
12754
+ "raw": "ConversationMessage[] (required) — ordered user + assistant turns"
12755
+ },
12756
+ "required": false
11329
12757
  },
11330
- {
11331
- "version": "0.27.2",
11332
- "summary": "**Fixed** UserMenu email truncation — long emails now truncate instead of overflowing the dropdown"
12758
+ "isProcessing": {
12759
+ "type": {
12760
+ "name": "object",
12761
+ "raw": "boolean — shows a live processing indicator below the last message"
12762
+ },
12763
+ "required": false
11333
12764
  },
11334
- {
11335
- "version": "0.7.0",
11336
- "summary": "**Added** `userMenuItems` prop for custom dropdown items"
12765
+ "processingSteps": {
12766
+ "type": {
12767
+ "name": "object",
12768
+ "raw": "ProcessingStep[] — granular steps shown during processing"
12769
+ },
12770
+ "required": false,
12771
+ "description": "status: pending | active | done | error"
11337
12772
  },
12773
+ "agent": {
12774
+ "type": {
12775
+ "name": "object",
12776
+ "raw": "{ name: string, icon?: IconInput } — agent identity shown as a header on assistant messages"
12777
+ },
12778
+ "required": false
12779
+ },
12780
+ "onAction": {
12781
+ "type": {
12782
+ "name": "function",
12783
+ "raw": "(actionId: string, type: \"confirm\" | \"cancel\" | \"undo\") => void — fired by action blocks"
12784
+ },
12785
+ "required": false
12786
+ },
12787
+ "customBlocks": {
12788
+ "type": {
12789
+ "name": "object",
12790
+ "raw": "Record<string, ComponentType<BlockComponentProps>> — extra block-type renderers merged over the built-ins"
12791
+ },
12792
+ "required": false
12793
+ },
12794
+ "maxHeight": {
12795
+ "type": {
12796
+ "name": "union",
12797
+ "raw": "string | number — max height of the container"
12798
+ },
12799
+ "required": false,
12800
+ "description": "enables scrolling"
12801
+ },
12802
+ "autoScroll": {
12803
+ "type": {
12804
+ "name": "object",
12805
+ "raw": "boolean — auto-scroll to bottom on new messages"
12806
+ },
12807
+ "required": false,
12808
+ "description": "default true"
12809
+ },
12810
+ "className": {
12811
+ "type": {
12812
+ "name": "string"
12813
+ },
12814
+ "required": false
12815
+ }
12816
+ },
12817
+ "composition": {
12818
+ "notes": [
12819
+ "**Renders blocks, not raw text** — each assistant turn is a list of typed `Block`s rendered by `BlockRenderer`. See the block-renderer doc for the block system and how to register custom block types.",
12820
+ "**Pairs with `AICommandProvider`** — the provider supplies `customBlocks`, `onAction`, and `agent` via context so you don't thread them through every message. Props on `AIConversation` win over context.",
12821
+ "**Pairs with `CommandBar`** — CommandBar is the input surface (natural-language submission); AIConversation is the output thread. Common layout: CommandBar on top/bottom, AIConversation as the scroll region.",
12822
+ "**Streaming** — set `isProcessing` + feed `processingSteps` to show step-by-step progress (Reading → Drafting → …) while the model works.",
12823
+ "**Actions** — action blocks (e.g. `confirm`) call `onAction(actionId, type)`; wire it to your confirm/cancel/undo handlers."
12824
+ ]
12825
+ },
12826
+ "docPath": "docs/components/ai/conversation.md",
12827
+ "examples": [
12828
+ "<AICommandProvider agent={{ name: 'Devadoot' }} onAction={handleAction}>\n <AIConversation\n messages={messages}\n isProcessing={isThinking}\n processingSteps={[\n { label: 'Reading project', status: 'done' },\n { label: 'Drafting reply', status: 'active' },\n ]}\n agent={{ name: 'Devadoot', icon: <IconSparkles /> }}\n onAction={(id, type) => handleAction(id, type)}\n maxHeight=\"60vh\"\n />\n</AICommandProvider>"
12829
+ ],
12830
+ "gotchas": [
12831
+ "Client component — mount inside a client boundary.",
12832
+ "Requires a mounted `MotionProvider` (respects reduced-motion for the step spinner and block entrances).",
12833
+ "`agent` set here labels assistant messages; `AICommandProvider`'s `agent` is the fallback when not passed per-conversation."
12834
+ ],
12835
+ "changes": [
11338
12836
  {
11339
- "version": "0.1.1",
11340
- "summary": "**Changed** Decoupled from Next.js via LinkProvider"
12837
+ "version": "0.49.0",
12838
+ "summary": "**Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP)."
12839
+ }
12840
+ ]
12841
+ },
12842
+ "devadoot-icon": {
12843
+ "displayName": "DevadootIcon",
12844
+ "tier": "ai",
12845
+ "import": "@devalok/shilp-sutra/ai",
12846
+ "serverSafe": false,
12847
+ "description": "The animated Devalok chakra glyph — the visual identity for the AI command system. Uses fill-first animation (the gradient color *is* the animation, Gemini-style), with a distinct state for idle, processing, responded, and error.",
12848
+ "props": {
12849
+ "state": {
12850
+ "type": {
12851
+ "name": "union",
12852
+ "raw": "\"idle\" | \"processing\" | \"responded\" | \"error\" — animation mode"
12853
+ },
12854
+ "required": false,
12855
+ "description": "default \"idle\""
11341
12856
  },
12857
+ "size": {
12858
+ "type": {
12859
+ "name": "object",
12860
+ "raw": "number — pixel size"
12861
+ },
12862
+ "required": false,
12863
+ "description": "default 20"
12864
+ },
12865
+ "className": {
12866
+ "type": {
12867
+ "name": "string"
12868
+ },
12869
+ "required": false
12870
+ }
12871
+ },
12872
+ "composition": {
12873
+ "notes": [
12874
+ "**State-as-identity** — `idle` breathes pink↔rose slowly; `processing` sweeps a pink→purple→magenta gradient + glow; `responded` flashes bright then settles + a scale pop; `error` turns red with a glow pulse. Wire `state` to your agent's status.",
12875
+ "**Pairs with `CommandBar` / `AIConversation`** — commonly placed in the CommandBar (hero/floating) or as the agent header avatar in the conversation.",
12876
+ "**Exported from the `ai` barrel** — `import { DevadootIcon } from '@devalok/shilp-sutra/ai'` (no dedicated subpath)."
12877
+ ]
12878
+ },
12879
+ "docPath": "docs/components/ai/devadoot-icon.md",
12880
+ "examples": [
12881
+ "// Drive the icon from the agent lifecycle:\n<DevadootIcon state={isThinking ? 'processing' : hasReplied ? 'responded' : 'idle'} size={24} />\n\n// Error state:\n<DevadootIcon state=\"error\" />"
12882
+ ],
12883
+ "gotchas": [
12884
+ "Client component — mount inside a client boundary.",
12885
+ "Requires a mounted `MotionProvider`; renders a static chakra when reduced-motion is set.",
12886
+ "Brand-locked colors (Devalok pink↔purple palette) — it's a brand asset, not a generic spinner. Use `Spinner` for neutral loading."
12887
+ ],
12888
+ "changes": [
11342
12889
  {
11343
- "version": "0.1.0",
11344
- "summary": "**Added** Initial release"
12890
+ "version": "0.49.0",
12891
+ "summary": "**Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP)."
11345
12892
  }
11346
12893
  ]
11347
12894
  }
@@ -11540,6 +13087,10 @@
11540
13087
  "name": "--color-surface-raised-active",
11541
13088
  "value": "Canvas"
11542
13089
  },
13090
+ {
13091
+ "name": "--color-surface-chrome",
13092
+ "value": "Canvas"
13093
+ },
11543
13094
  {
11544
13095
  "name": "--color-surface-inverted",
11545
13096
  "value": "CanvasText"