@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
@@ -70,6 +70,24 @@
70
70
  "description": "Convenience mirror of each prop's defaultValue for props with defaults (from the doc's Defaults section).",
71
71
  "additionalProperties": { "type": ["string", "number", "boolean"] }
72
72
  },
73
+ "subComponents": {
74
+ "type": "object",
75
+ "description": "Props owned by compound subcomponents, parsed from `### Subpart` headings inside the doc's Props section. Keeps a child's props OFF the root entry: a `numeric` prop belonging to TableCell must not read as a prop of <Table>, or an agent writes `<Table numeric>` and hits TS2322 (#132). Keyed by subcomponent display name.",
76
+ "patternProperties": {
77
+ "^[A-Za-z][A-Za-z0-9.]*$": {
78
+ "type": "object",
79
+ "additionalProperties": false,
80
+ "properties": {
81
+ "note": { "type": "string", "description": "Parenthetical from the subpart heading — e.g. a separate import path for a subcomponent shipped under its own subpath export." },
82
+ "props": {
83
+ "type": "object",
84
+ "additionalProperties": { "$ref": "#/$defs/prop" }
85
+ }
86
+ }
87
+ }
88
+ },
89
+ "additionalProperties": false
90
+ },
73
91
  "examples": {
74
92
  "type": "array",
75
93
  "items": { "type": "string" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devalok/shilp-sutra",
3
- "version": "0.47.0",
3
+ "version": "0.49.0",
4
4
  "description": "Devalok Design System — accessible React components, OKLCH design tokens, and Tailwind 4 CSS-first setup. Ships with AI-agent setup recipes.",
5
5
  "license": "MIT",
6
6
  "author": "Devalok Design & Strategy Studios <shilp-sutra@devalok.in>",
@@ -52,8 +52,10 @@
52
52
  "provenance": true
53
53
  },
54
54
  "dependencies": {
55
+ "@emoji-mart/data": "^1.2.1",
55
56
  "class-variance-authority": "^0.7.1",
56
57
  "clsx": "^2.1.1",
58
+ "frimousse": "^0.3.0",
57
59
  "tw-animate-css": "^1.4.0",
58
60
  "use-sync-external-store": "^1.5.0"
59
61
  },
@@ -202,6 +204,11 @@
202
204
  "import": "./dist/ui/devalok-grain.js",
203
205
  "default": "./dist/ui/devalok-grain.js"
204
206
  },
207
+ "./ui/dot": {
208
+ "types": "./dist/ui/dot.d.ts",
209
+ "import": "./dist/ui/dot.js",
210
+ "default": "./dist/ui/dot.js"
211
+ },
205
212
  "./ui/dropdown-menu": {
206
213
  "types": "./dist/ui/dropdown-menu.d.ts",
207
214
  "import": "./dist/ui/dropdown-menu.js",
@@ -367,11 +374,6 @@
367
374
  "import": "./dist/ui/stat-card.js",
368
375
  "default": "./dist/ui/stat-card.js"
369
376
  },
370
- "./ui/status-dot": {
371
- "types": "./dist/ui/status-dot.d.ts",
372
- "import": "./dist/ui/status-dot.js",
373
- "default": "./dist/ui/status-dot.js"
374
- },
375
377
  "./ui/stepper": {
376
378
  "types": "./dist/ui/stepper.d.ts",
377
379
  "import": "./dist/ui/stepper.js",
@@ -637,6 +639,11 @@
637
639
  "import": "./dist/composed/priority-indicator.js",
638
640
  "default": "./dist/composed/priority-indicator.js"
639
641
  },
642
+ "./composed/responsive-modal": {
643
+ "types": "./dist/composed/responsive-modal.d.ts",
644
+ "import": "./dist/composed/responsive-modal.js",
645
+ "default": "./dist/composed/responsive-modal.js"
646
+ },
640
647
  "./composed/rich-text-editor": {
641
648
  "types": "./dist/composed/rich-text-editor.d.ts",
642
649
  "import": "./dist/composed/rich-text-editor.js",
@@ -839,8 +846,6 @@
839
846
  ]
840
847
  },
841
848
  "peerDependencies": {
842
- "@emoji-mart/data": "^1.0.0",
843
- "@emoji-mart/react": "^1.0.0",
844
849
  "@tabler/icons-react": "^3.0.0",
845
850
  "@tanstack/react-table": "^8.0.0",
846
851
  "@tanstack/react-virtual": "^3.0.0",
@@ -873,12 +878,6 @@
873
878
  "@tanstack/react-virtual": {
874
879
  "optional": true
875
880
  },
876
- "@emoji-mart/data": {
877
- "optional": true
878
- },
879
- "@emoji-mart/react": {
880
- "optional": true
881
- },
882
881
  "d3-array": {
883
882
  "optional": true
884
883
  },
@@ -985,6 +984,9 @@
985
984
  "build:tokens": "node scripts/copy-tokens.mjs",
986
985
  "build:docs": "node scripts/build-component-docs.mjs",
987
986
  "build:docs:check": "node scripts/build-component-docs.mjs --check",
987
+ "peers:check": "node scripts/derive-peer-map.mjs --check",
988
+ "smoke:cold": "node scripts/cold-install-smoke.mjs",
989
+ "smoke:cold:next": "node scripts/cold-install-smoke.mjs --framework next-app-router",
988
990
  "typecheck": "tsc --noEmit",
989
991
  "lint": "eslint src/",
990
992
  "test": "vitest run",
package/skill/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: shilp-sutra
3
3
  description: Add, configure, and use components from Devalok's shilp-sutra design system (@devalok/shilp-sutra) — a Tailwind 4 + React 19 + CVA library with 110+ accessible components, OKLCH design tokens, framer-motion animations, and per-component RSC-safe entry points. Use this skill whenever the user mentions shilp-sutra, Devalok, the @devalok npm scope, or asks to install/add/style/theme UI in any React project that already depends on the package — even if they don't name it explicitly. Use it instead of generic shadcn/ui, MUI, or Chakra knowledge when shilp-sutra is in the project. Covers Next.js (App + Pages), Vite, Astro, Remix, TanStack Start setup playbooks; component API and variant reference; brand token customization; Server Component import patterns; and a troubleshoot tree for the thirteen most common breakages.
4
4
  license: MIT
5
5
  metadata:
6
- version: "0.47.0"
6
+ version: "0.49.0"
7
7
  author: Devalok Design & Strategy Studios
8
8
  homepage: https://github.com/devalok-design/shilp-sutra
9
9
  npm: https://www.npmjs.com/package/@devalok/shilp-sutra
@@ -2,13 +2,13 @@
2
2
 
3
3
  # @devalok/shilp-sutra
4
4
 
5
- > Radix UI + Tailwind 4 (CSS-first) + CVA design system for Devalok apps, v0.47.0.
5
+ > Radix UI + Tailwind 4 (CSS-first) + CVA design system for Devalok apps, v0.49.0.
6
6
  > Built on the same primitives as shadcn/ui but with DIFFERENT prop APIs — never guess from shadcn knowledge; verify every prop.
7
7
  > This file is a ROUTER: it tells you what exists and where to get details. Do not look for prop tables here — fetch them per component (MCP tool or per-component doc file below).
8
8
 
9
9
  ## How to get component details (in priority order)
10
10
 
11
- 1. **shilp-sutra MCP** (if connected): `get_component(name)` — version-exact props/variants/examples/composition as JSON. Also: `find_component(query)`, `get_tokens(category)`, `get_setup(framework)`, `upgrade(from, to)`, `search_docs(query)`. Pass your installed version (`node_modules/@devalok/shilp-sutra/package.json`) as `version` on every call.
11
+ 1. **shilp-sutra MCP** (if connected): `get_component(name)` — version-exact props/variants/examples/composition as JSON. Also: `find_component(query)`, `get_tokens(category)`, `get_setup(framework)`, `upgrade(from, to)`, `search_docs(query)`. **Setting up in a project?** `detect_framework(packageJson)` → `get_setup(framework)` → `preflight(framework, imports)` (peer installs) → `validate_snippet(code)` before writing → `verify_setup(...)`. Pass your installed version (`node_modules/@devalok/shilp-sutra/package.json`) as `version` on every call.
12
12
  Connect: `claude mcp add --transport http shilp-sutra https://shilp-sutra.devalok.in/mcp`
13
13
  2. **No MCP?** Read the single per-component file linked in the index below (`node_modules/@devalok/shilp-sutra/docs/components/...`, ~3K tokens each). Read only the components you need — never bulk-read the directory.
14
14
  3. **Machine-readable everything**: `mcp-manifest.json` at the package root (all props/tokens/composition as JSON, react-docgen shape). Prefer targeted reads of it over any prose.
@@ -67,6 +67,7 @@ Format: `[name](doc path): summary`. Import paths follow `@devalok/shilp-sutra/<
67
67
  - [data-table-toolbar](docs/components/ui/data-table-toolbar.md)
68
68
  - [devalok-grain](docs/components/ui/devalok-grain.md)
69
69
  - [dialog](docs/components/ui/dialog.md)
70
+ - [dot](docs/components/ui/dot.md): A small semantic status/indicator dot — the low-level primitive behind status pills, presence indicators, legend swatches, and `StatusDot`
70
71
  - [dropdown-menu](docs/components/ui/dropdown-menu.md)
71
72
  - [file-upload](docs/components/ui/file-upload.md)
72
73
  - [form](docs/components/ui/form.md)
@@ -85,7 +86,7 @@ Format: `[name](doc path): summary`. Import paths follow `@devalok/shilp-sutra/<
85
86
  - [oauth-button](docs/components/ui/oauth-button.md)
86
87
  - [pagination](docs/components/ui/pagination.md)
87
88
  - [popover](docs/components/ui/popover.md)
88
- - [progress](docs/components/ui/progress.md)
89
+ - [progress](docs/components/ui/progress.md): A linear progress bar
89
90
  - [progress-ring](docs/components/ui/progress-ring.md)
90
91
  - [radio](docs/components/ui/radio.md)
91
92
  - [search-input](docs/components/ui/search-input.md)
@@ -100,7 +101,6 @@ Format: `[name](doc path): summary`. Import paths follow `@devalok/shilp-sutra/<
100
101
  - [stack](docs/components/ui/stack.md)
101
102
  - [stat-card](docs/components/ui/stat-card.md)
102
103
  - [stat-flash](docs/components/ui/stat-flash.md)
103
- - [status-dot](docs/components/ui/status-dot.md)
104
104
  - [stepper](docs/components/ui/stepper.md)
105
105
  - [surface](docs/components/ui/surface.md): The low-level elevated container primitive
106
106
  - [switch](docs/components/ui/switch.md)
@@ -143,6 +143,7 @@ Format: `[name](doc path): summary`. Import paths follow `@devalok/shilp-sutra/<
143
143
  - [page-header](docs/components/composed/page-header.md)
144
144
  - [page-skeletons](docs/components/composed/page-skeletons.md): Exports: DashboardSkeleton, ProjectListSkeleton, TaskDetailSkeleton
145
145
  - [priority-indicator](docs/components/composed/priority-indicator.md)
146
+ - [responsive-modal](docs/components/composed/responsive-modal.md)
146
147
  - [rich-chat-input](docs/components/composed/rich-chat-input.md): Compact rich text chat input for unified human+AI workspaces
147
148
  - [rich-text-editor](docs/components/composed/rich-text-editor.md): Exports: RichTextEditor, RichTextViewer
148
149
  - [schedule-view](docs/components/composed/schedule-view.md)
@@ -159,6 +160,13 @@ Format: `[name](doc path): summary`. Import paths follow `@devalok/shilp-sutra/<
159
160
  - [sidebar](docs/components/shell/sidebar.md)
160
161
  - [top-bar](docs/components/shell/top-bar.md)
161
162
 
163
+ ### ai
164
+ - [ai-command-provider](docs/components/ai/ai-command-provider.md): Context provider for the AI command system
165
+ - [block-renderer](docs/components/ai/block-renderer.md): Renders an ordered list of typed AI "blocks" — the structured chunks an assistant/ server emits instead of plain text
166
+ - [command-bar](docs/components/ai/command-bar.md): A unified AI command input with three layout variants
167
+ - [conversation](docs/components/ai/conversation.md): 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
168
+ - [devadoot-icon](docs/components/ai/devadoot-icon.md): The animated Devalok chakra glyph — the visual identity for the AI command system
169
+
162
170
  ## Tokens
163
171
 
164
172
  Categories: color, spacing (`ds-01`…), typography (`text-ds-*`), radius (`rounded-ds-*`), shadow (`shadow-raised`/`shadow-overlay`/…), motion, z-layers. Full reference: `get_tokens(category)` via MCP, or the `tokens` object in `mcp-manifest.json`.
@@ -33,18 +33,21 @@ pnpm add sonner
33
33
 
34
34
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
35
35
 
36
- Some components ship hard peers as optional. **Install BEFORE first import** or Astro's Vite build will fail with `Failed to resolve import`. Skip if you only use core components.
37
-
38
- | When you import… | Install |
39
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
40
- | `@devalok/shilp-sutra/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
41
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
42
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
43
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
44
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
45
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
46
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
47
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
36
+ Some components ship hard peers as optional. **Install BEFORE first import.** On Vite / Rolldown a missing peer may **not** fail the build — the bundler can silently replace the import with a stub that throws `Could not resolve "…"` in the browser at runtime, while the build still exits 0. A green build is therefore **not** proof the app works. Confirm coverage with the MCP `verify_setup` / `preflight` tools or the table below. Skip only if you use core components.
37
+
38
+ | When you import… | Install |
39
+ |---|---|
40
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
41
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
42
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
43
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
44
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
45
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
46
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
47
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
48
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
49
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
50
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
48
51
 
49
52
  ## 3. Wire Tailwind 4 in `astro.config`
50
53
 
@@ -48,16 +48,19 @@ pnpm add sonner
48
48
 
49
49
  Some components depend on third-party libraries that ship as optional peers. **Install BEFORE first import** of the matching component, or `next build` will exit with `Module not found`. Skip entirely if you only use core components (`Button`, `Text`, `Stack`, `Dialog`, `Toast`, `Form*`, `Input`, `Card`, etc.).
50
50
 
51
- | When you import… | Install |
52
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
53
- | `@devalok/shilp-sutra/ui/charts/*` (BarChart, LineChart, …)| `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
54
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
55
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
56
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
57
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
58
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
59
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
60
- | Any `Icon` / `IconButton` use with Tabler icons | `pnpm add @tabler/icons-react` |
51
+ | When you import… | Install |
52
+ |---|---|
53
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
54
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
55
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
56
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
57
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
58
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
59
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
60
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
61
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
62
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
63
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
61
64
 
62
65
  > These aren't in core deps so consumers who never render a chart, OTP input, or rich-text editor don't pay the install / bundle cost. One-time decision at install.
63
66
 
@@ -166,9 +169,14 @@ export function Providers({ children }: { children: ReactNode }) {
166
169
  }
167
170
  ```
168
171
 
169
- `next-themes` is already in the install list from § 2 no extra install step needed here. If `<Toaster />` is not used:
172
+ > **This default `Providers` renders `<Toaster />`, which imports `sonner`.** Install it now or `next build` fails with `Module not found: Can't resolve 'sonner'`:
173
+ > ```bash
174
+ > pnpm add sonner
175
+ > ```
170
176
 
171
- - Drop the `Toaster` import and its JSX usage
177
+ `next-themes` is already in the install list from § 2 — no extra install step needed here. If you do **not** want toasts:
178
+
179
+ - Drop the `Toaster` import and its JSX usage from `Providers`
172
180
  - Skip installing `sonner`
173
181
 
174
182
  Mount `<Providers>` from `app/layout.tsx` (or `src/app/layout.tsx`). **Replace the scaffold's layout** with the version below — the scaffold imports `next/font/google` (Geist) and applies font-variable classes to `<html>`, which you don't need when shilp-sutra ships its own fonts:
@@ -18,7 +18,7 @@ If both `app/` and `pages/` exist, prefer [install-next-app-router.md](./install
18
18
 
19
19
  Same dependencies as the App Router recipe — see [install-next-app-router.md § 2](./install-next-app-router.md#2-install-dependencies). Replace `next-themes`'s `attribute="class"` setup with the same on Pages Router (it works identically).
20
20
 
21
- **Optional peer dependencies** — if you'll render `<DataTable>`, any chart, `<DatePicker>`, `<RichTextEditor>`, `<InputOTP>`, `<FilePreview>`, `<MarkdownViewer>`, or use Tabler icons, install the matching peers BEFORE first import. Full table at [install-next-app-router.md § 2a](./install-next-app-router.md#2a-optional-peer-dependencies-install-only-when-importing-the-matching-subpath) — identical for Pages Router.
21
+ **Optional peer dependencies** — if you'll render `<DataTable>`, any chart, `<DatePicker>`, `<ScheduleView>`, `<InputOTP>`, `<FilePreview>`, `<MarkdownViewer>`, or `<Toaster>`, install the matching peers BEFORE first import. (The emoji picker and rich-text editors bundle their deps — no install needed; `@tabler/icons-react` auto-installs as a required peer.) Full table at [install-next-app-router.md § 2a](./install-next-app-router.md#2a-optional-peer-dependencies-install-only-when-importing-the-matching-subpath) — identical for Pages Router.
22
22
 
23
23
  ## 3. PostCSS
24
24
 
@@ -69,6 +69,8 @@ export default function App({ Component, pageProps }: AppProps) {
69
69
  }
70
70
  ```
71
71
 
72
+ > ⚠ **This renders `<Toaster />`, which imports `sonner`.** Install it or `next build` fails with `Module not found: Can't resolve 'sonner'`: `pnpm add sonner`. If you don't want toasts, drop the `Toaster` import + usage and skip `sonner`.
73
+
72
74
  For `next-themes` to avoid hydration warnings, add a `_document.tsx` with `suppressHydrationWarning` on the `<html>`:
73
75
 
74
76
  ```tsx
@@ -12,7 +12,7 @@ You are in this recipe if:
12
12
  - `vite.config.{ts,js}` exists with the `vitePlugin` from `@remix-run/dev`
13
13
  - `app/root.tsx` exists with `<Outlet />` inside `<Document>` shell
14
14
 
15
- For React Router v7 (the spiritual successor to Remix), use the [install-vite.md](./install-vite.md) recipeit works the same way.
15
+ > **New projects scaffold as React Router v7, not Remix.** `create-remix` is deprecated and redirects to `create-react-router`; Remix v2 was upstreamed into React Router (maintenance mode). If you ran `create-react-router`, you have an RR7 **framework-mode** app (`@react-router/dev` + `react-router build` + `app/root.tsx` + `ssr: true`) — verified cold with shilp-sutra (SSR render, HTTP 200). Its wiring is the same shape as this recipe: `@tailwindcss/vite` plugin, `@import "@devalok/shilp-sutra/css"` in `app/app.css`, and **no `transpilePackages`** (Vite resolves our ESM). Ignore the SPA-only steps in [install-vite.md](./install-vite.md) (`index.html` bootstrap, `main.tsx` `createRoot`) RR7 framework mode has its own `root.tsx` shell, like this recipe.
16
16
 
17
17
  ## 2. Install
18
18
 
@@ -29,18 +29,21 @@ pnpm add sonner # only if rendering <Toaster />
29
29
 
30
30
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
31
31
 
32
- Some components ship hard peers as optional. **Install BEFORE first import** or Remix's Vite build will fail with `Failed to resolve import`. Skip if you only use core components.
33
-
34
- | When you import… | Install |
35
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
36
- | `@devalok/shilp-sutra/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
37
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
38
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
39
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
40
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
41
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
42
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
43
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
32
+ Some components ship hard peers as optional. **Install BEFORE first import.** On Vite 8 / Rolldown a missing peer does **not** fail the build — Rolldown silently replaces the import with a stub that throws `Could not resolve "…"` in the browser at runtime, while the build still exits 0. A green build is therefore **not** proof the app works. Confirm coverage with the MCP `verify_setup` / `preflight` tools or the table below. Skip only if you use core components.
33
+
34
+ | When you import… | Install |
35
+ |---|---|
36
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
37
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
38
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
39
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
40
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
41
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
42
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
43
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
44
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
45
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
46
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
44
47
 
45
48
  ## 3. Wire Tailwind 4 in `vite.config.ts`
46
49
 
@@ -16,6 +16,8 @@ You are in this recipe if:
16
16
 
17
17
  If instead you see `app.config.ts` + `@tanstack/start`, that is the legacy Vinxi setup — this recipe does not apply until you migrate.
18
18
 
19
+ > **Scaffolded with `create-start` and got a Router SPA?** As of `@tanstack/create-start` 0.59, the default template is a TanStack **Router** SPA — Vite + `@tanstack/react-router` + an `index.html` + `src/main.tsx` (client `createRoot`), with **no** `@tanstack/react-start` and no SSR server entry. That is NOT the Start SSR setup this recipe covers — use [install-vite.md](./install-vite.md) instead (it is router-agnostic and covers TanStack Router SPAs cleanly). This recipe applies only when `@tanstack/react-start` is a dependency.
20
+
19
21
  ## 2. Install
20
22
 
21
23
  ```bash
@@ -36,18 +38,21 @@ pnpm add sonner # only if rendering <Toaster />
36
38
 
37
39
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
38
40
 
39
- Some components ship hard peers as optional. **Install BEFORE first import** or the TanStack Start dev/build will fail with `Failed to resolve import`. Skip if you only use core components.
40
-
41
- | When you import… | Install |
42
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
43
- | `@devalok/shilp-sutra/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
44
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
45
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
46
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
47
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
48
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
49
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
50
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
41
+ Some components ship hard peers as optional. **Install BEFORE first import.** On Vite 8 / Rolldown a missing peer does **not** fail the build — Rolldown silently replaces the import with a stub that throws `Could not resolve "…"` in the browser at runtime, while the build still exits 0. A green build is therefore **not** proof the app works. Confirm coverage with the MCP `verify_setup` / `preflight` tools or the table below. Skip only if you use core components.
42
+
43
+ | When you import… | Install |
44
+ |---|---|
45
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
46
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
47
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
48
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
49
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
50
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
51
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
52
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
53
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
54
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
55
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
51
56
 
52
57
  ## 3. Wire Tailwind 4 in `vite.config.ts`
53
58
 
@@ -117,6 +122,8 @@ function RootComponent() {
117
122
  }
118
123
  ```
119
124
 
125
+ > **Newer scaffolds use `shellComponent`.** As of `@tanstack/create-start` 0.59 the generated `__root.tsx` uses `shellComponent: RootDocument` (which receives `{ children }`) instead of `component: RootComponent` with `<Outlet />`. Both wire up the same way for shilp-sutra — put the `{ rel: "stylesheet", href: appCss }` link in `head()` and keep `<HeadContent />` + `<Scripts />`. If your `__root.tsx` already has a `shellComponent`, add the stylesheet link to its existing `head()` rather than replacing the component. (Verified cold: shilp-sutra components — Button, Text, MarkdownViewer, EmojiPickerPopover — SSR-render cleanly under TanStack Start, HTTP 200.)
126
+
120
127
  ## 5. Theme toggle
121
128
 
122
129
  Add a pre-hydration bootstrap so there is no flash of the wrong theme. The cleanest place is a `scripts` entry on the root route (runs before hydration); a static `public/theme-bootstrap.js` referenced from `<head>` also works and is CSP-friendly.
@@ -44,18 +44,21 @@ pnpm add sonner
44
44
 
45
45
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
46
46
 
47
- Some components ship hard peers as optional. **Install BEFORE first import** or `vite dev` / `vite build` will fail with `Failed to resolve import`. Skip if you only use core components.
48
-
49
- | When you import… | Install |
50
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
51
- | `@devalok/shilp-sutra/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
52
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
53
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
54
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
55
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
56
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
57
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
58
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
47
+ Some components ship hard peers as optional. **Install BEFORE first import.** ⚠ On Vite 8 / Rolldown a missing peer does **not** fail the build — Rolldown silently replaces the import with a stub that throws `Could not resolve "…"` in the browser at runtime, while `vite build` still exits 0. A green build is therefore **not** proof the app works. Confirm coverage with the MCP `verify_setup` / `preflight` tools or the table below. Skip only if you use core components.
48
+
49
+ | When you import… | Install |
50
+ |---|---|
51
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
52
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
53
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
54
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
55
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
56
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
57
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
58
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
59
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
60
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
61
+ | Any `Icon` / `IconButton` with Tabler icons (near-universal — most components use icons internally, so it is a base-install peer) | `pnpm add @tabler/icons-react` |
59
62
 
60
63
  ## 3. Wire Tailwind 4 in `vite.config.ts`
61
64
 
@@ -138,7 +141,7 @@ If you installed `sonner`, mount the Toaster once near the app root:
138
141
  import { StrictMode } from "react";
139
142
  import { createRoot } from "react-dom/client";
140
143
  import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
141
- import { App } from "./App";
144
+ import App from "./App";
142
145
  import "./index.css";
143
146
 
144
147
  createRoot(document.getElementById("root")!).render(
@@ -151,14 +154,14 @@ createRoot(document.getElementById("root")!).render(
151
154
 
152
155
  ## 7. Verify
153
156
 
154
- Replace `src/App.tsx`:
157
+ Replace `src/App.tsx` (keep the **default export** — the `create-vite` template's `main.tsx` imports it as `import App from "./App"`, so a named export would break the build with `TS2613: Module has no default export`):
155
158
 
156
159
  ```tsx
157
160
  import { Button } from "@devalok/shilp-sutra/ui/button";
158
161
  import { Stack } from "@devalok/shilp-sutra/ui/stack";
159
162
  import { Text } from "@devalok/shilp-sutra/ui/text";
160
163
 
161
- export function App() {
164
+ export default function App() {
162
165
  return (
163
166
  <Stack className="p-ds-08" gap="ds-04">
164
167
  <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
@@ -97,26 +97,25 @@ Add:
97
97
  transpilePackages: ["@devalok/shilp-sutra"],
98
98
  ```
99
99
 
100
- ## Symptom: Build error `Cannot find module 'sonner' / 'input-otp' / 'date-fns' / '@tiptap/react' / 'react-pdf' / 'react-markdown' / '@emoji-mart/react'`
100
+ ## Symptom: Build error `Cannot find module 'sonner' / 'input-otp' / 'date-fns' / 'react-pdf' / 'react-markdown'` OR (on Vite 8) a runtime `Could not resolve "…"` from a green build
101
101
 
102
- **Diagnosis:** an optional peer dependency is missing. Each component below has a peer it pulls only when imported. Install the matching peer (always BEFORE the first import):
102
+ **Diagnosis:** an optional peer dependency is missing. Each component below has a peer it pulls only when imported. Install the matching peer (always BEFORE the first import). On Vite 8 / Rolldown this does **not** fail the build — it throws at runtime — so run the MCP `verify_setup` tool to catch it early.
103
103
 
104
104
  | You imported (per-component subpath) | Install |
105
105
  |--------------------------------------|-----------------------------------------------------------------------------------------------|
106
106
  | `…/ui/toaster` or `…/ui/toast` | `pnpm add sonner` |
107
107
  | `…/ui/input-otp` | `pnpm add input-otp` |
108
- | `…/composed/date-picker` | `pnpm add date-fns` |
109
- | `…/composed/emoji-picker` | `pnpm add @emoji-mart/data @emoji-mart/react` |
110
- | `…/composed/extensions/emoji-node` or `…/extensions/emoji-suggestion` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
111
- | `…/composed/rich-text-editor` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
112
- | `…/composed/rich-chat-input` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
108
+ | `…/composed/date-picker` or `…/composed/schedule-view` | `pnpm add date-fns` |
109
+ | `…/ui/data-table` or `…/ui/data-table-toolbar` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
113
110
  | `…/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
114
111
  | `…/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
115
112
  | `…/ai/block-renderer`, `…/ai/blocks/text`, `…/ai/blocks/error` | `pnpm add react-markdown remark-gfm` |
116
- | Any `…/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
113
+ | Any `…/ui/charts/*` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
117
114
 
118
115
  These ship as **optional** peers so consumers who never render the matching component don't pay the install cost. Once you import the component, the peer becomes required. Each affected component's JSDoc carries the same install hint — hover the import in your editor to see it inline.
119
116
 
117
+ **No longer peers (bundled since the frimousse migration):** the emoji picker (`…/composed/emoji-picker`) and the rich-text editors (`…/composed/rich-text-editor`, `…/composed/rich-chat-input`) bundle their dependencies (frimousse, `@emoji-mart/data`, TipTap) into a lazy chunk — you do **not** install anything for them. `@tabler/icons-react` is a required peer that most package managers auto-install.
118
+
120
119
  **Catch this at edit time, not build time:** install `@devalok/eslint-plugin-shilp-sutra` (`pnpm add -D @devalok/eslint-plugin-shilp-sutra`, then `shilpSutra.configs['flat/recommended']`). Its `prefer-per-component-import` rule flags peer-cliff symbols imported from a barrel and autofixes the path — surfacing the cliff in your editor before the bundler ever fails.
121
120
 
122
121
  For the full table in your framework's install recipe, see `install-<framework>.md → §2a. Optional peer dependencies`.
@@ -1,45 +0,0 @@
1
- "use client";
2
- import { emojiDataLoaders as e } from "../composed/emoji-picker.js";
3
- //#region src/composed/extensions/emoji-data.ts
4
- var t = (e) => `https://cdn.jsdelivr.net/npm/emoji-datasource-${e}@15.0.1/img/${e}/sheets-256/64.png`, n = null, r = null;
5
- async function i(t) {
6
- if (n === t && r) return r;
7
- let i = await (e[t] ?? e.native)();
8
- return r = i.default ?? i, n = t, r;
9
- }
10
- function a(e, t) {
11
- let n = e.emojis[t];
12
- if (!n) return null;
13
- let r = n.skins[0];
14
- return r ? {
15
- id: n.id,
16
- name: n.name,
17
- native: r.native,
18
- x: r.x ?? 0,
19
- y: r.y ?? 0
20
- } : null;
21
- }
22
- function o(e, t, n = 8) {
23
- let r = Object.values(e.emojis);
24
- if (!t) return r.slice(0, n).map((e) => ({
25
- id: e.id,
26
- name: e.name,
27
- native: e.skins[0]?.native ?? "",
28
- x: e.skins[0]?.x ?? 0,
29
- y: e.skins[0]?.y ?? 0
30
- }));
31
- let i = t.toLowerCase(), a = [];
32
- for (let e of r) {
33
- if (a.length >= n) break;
34
- (e.id.includes(i) || e.name.toLowerCase().includes(i) || e.keywords?.some((e) => e.includes(i))) && a.push({
35
- id: e.id,
36
- name: e.name,
37
- native: e.skins[0]?.native ?? "",
38
- x: e.skins[0]?.x ?? 0,
39
- y: e.skins[0]?.y ?? 0
40
- });
41
- }
42
- return a;
43
- }
44
- //#endregion
45
- export { o as i, i as n, a as r, t };
@@ -1 +0,0 @@
1
- {"version":3,"file":"emoji-data.js","names":[],"sources":["../../src/composed/extensions/emoji-data.ts"],"sourcesContent":["import { emojiDataLoaders } from '../emoji-picker'\n\n// Spritesheet constants — must match emoji-mart's rendering (emoji-datasource v15.0.1)\nexport const SPRITESHEET_URL = (set: string) =>\n `https://cdn.jsdelivr.net/npm/emoji-datasource-${set}@15.0.1/img/${set}/sheets-256/64.png`\nexport const SHEET_COLS = 61\nexport const SHEET_ROWS = 61\n\ninterface EmojiSkin {\n unified: string\n native: string\n x?: number\n y?: number\n}\n\ninterface EmojiEntry {\n id: string\n name: string\n keywords?: string[]\n skins: EmojiSkin[]\n}\n\nexport interface EmojiDataset {\n emojis: Record<string, EmojiEntry>\n sheet?: { cols: number; rows: number }\n}\n\nexport interface ResolvedEmoji {\n id: string\n name: string\n native: string\n x: number\n y: number\n}\n\nlet cachedSet: string | null = null\nlet cachedData: EmojiDataset | null = null\n\nexport async function loadEmojiData(set: string): Promise<EmojiDataset> {\n if (cachedSet === set && cachedData) return cachedData\n const loader = emojiDataLoaders[set] ?? emojiDataLoaders.native\n const mod = await loader()\n cachedData = (mod.default ?? mod) as EmojiDataset\n cachedSet = set\n return cachedData\n}\n\nexport function lookupEmoji(data: EmojiDataset, id: string): ResolvedEmoji | null {\n const entry = data.emojis[id]\n if (!entry) return null\n const skin = entry.skins[0]\n if (!skin) return null\n return {\n id: entry.id,\n name: entry.name,\n native: skin.native,\n x: skin.x ?? 0,\n y: skin.y ?? 0,\n }\n}\n\nexport function searchEmoji(data: EmojiDataset, query: string, limit = 8): ResolvedEmoji[] {\n const entries = Object.values(data.emojis)\n if (!query) {\n return entries.slice(0, limit).map((e) => ({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n }))\n }\n const q = query.toLowerCase()\n const results: ResolvedEmoji[] = []\n for (const e of entries) {\n if (results.length >= limit) break\n if (\n e.id.includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.keywords?.some((k) => k.includes(q))\n ) {\n results.push({\n id: e.id,\n name: e.name,\n native: e.skins[0]?.native ?? '',\n x: e.skins[0]?.x ?? 0,\n y: e.skins[0]?.y ?? 0,\n })\n }\n }\n return results\n}\n"],"mappings":";;AAGA,IAAa,KAAmB,MAC9B,iDAAiD,EAAI,cAAc,EAAI,qBA+BrE,IAA2B,MAC3B,IAAkC;AAEtC,eAAsB,EAAc,GAAoC;AACtE,KAAI,MAAc,KAAO,EAAY,QAAO;CAE5C,IAAM,IAAM,OADG,EAAiB,MAAQ,EAAiB,SAC/B;AAG1B,QAFA,IAAc,EAAI,WAAW,GAC7B,IAAY,GACL;;AAGT,SAAgB,EAAY,GAAoB,GAAkC;CAChF,IAAM,IAAQ,EAAK,OAAO;AAC1B,KAAI,CAAC,EAAO,QAAO;CACnB,IAAM,IAAO,EAAM,MAAM;AAEzB,QADK,IACE;EACL,IAAI,EAAM;EACV,MAAM,EAAM;EACZ,QAAQ,EAAK;EACb,GAAG,EAAK,KAAK;EACb,GAAG,EAAK,KAAK;EACd,GAPiB;;AAUpB,SAAgB,EAAY,GAAoB,GAAe,IAAQ,GAAoB;CACzF,IAAM,IAAU,OAAO,OAAO,EAAK,OAAO;AAC1C,KAAI,CAAC,EACH,QAAO,EAAQ,MAAM,GAAG,EAAM,CAAC,KAAK,OAAO;EACzC,IAAI,EAAE;EACN,MAAM,EAAE;EACR,QAAQ,EAAE,MAAM,IAAI,UAAU;EAC9B,GAAG,EAAE,MAAM,IAAI,KAAK;EACpB,GAAG,EAAE,MAAM,IAAI,KAAK;EACrB,EAAE;CAEL,IAAM,IAAI,EAAM,aAAa,EACvB,IAA2B,EAAE;AACnC,MAAK,IAAM,KAAK,GAAS;AACvB,MAAI,EAAQ,UAAU,EAAO;AAC7B,GACE,EAAE,GAAG,SAAS,EAAE,IAChB,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,UAAU,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,KAEtC,EAAQ,KAAK;GACX,IAAI,EAAE;GACN,MAAM,EAAE;GACR,QAAQ,EAAE,MAAM,IAAI,UAAU;GAC9B,GAAG,EAAE,MAAM,IAAI,KAAK;GACpB,GAAG,EAAE,MAAM,IAAI,KAAK;GACrB,CAAC;;AAGN,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"emoji-suggestion.js","names":[],"sources":["../../../src/composed/extensions/emoji-suggestion.tsx"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport Suggestion, { type SuggestionKeyDownProps,type SuggestionProps } from '@tiptap/suggestion'\nimport { PluginKey } from 'prosemirror-state'\nimport * as React from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\n\nimport { cn } from '../../ui/lib/utils'\nimport { loadEmojiData, type ResolvedEmoji, searchEmoji, SHEET_COLS, SHEET_ROWS,SPRITESHEET_URL } from './emoji-data'\n\n// Re-export for external consumers\nexport type { ResolvedEmoji as EmojiSuggestionItem }\n\nfunction EmojiImage({ emoji, set, size = '1.2em' }: { emoji: ResolvedEmoji; set: string; size?: string }) {\n if (set === 'native') {\n return <span style={{ fontSize: size }}>{emoji.native}</span>\n }\n return (\n <span\n role=\"img\"\n aria-label={emoji.native}\n className=\"inline-block\"\n style={{\n width: size,\n height: size,\n backgroundImage: `url(${SPRITESHEET_URL(set)})`,\n backgroundSize: `${100 * SHEET_COLS}% ${100 * SHEET_ROWS}%`,\n backgroundPosition: `${(100 / (SHEET_COLS - 1)) * emoji.x}% ${(100 / (SHEET_ROWS - 1)) * emoji.y}%`,\n }}\n />\n )\n}\n\ninterface EmojiListRef {\n onKeyDown: (props: SuggestionKeyDownProps) => boolean\n}\n\ninterface EmojiListProps {\n items: ResolvedEmoji[]\n set: string\n command: (item: ResolvedEmoji) => void\n}\n\nconst EmojiList = React.forwardRef<EmojiListRef, EmojiListProps>(\n ({ items, set, command }, ref) => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n\n React.useEffect(() => setSelectedIndex(0), [items])\n\n React.useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: SuggestionKeyDownProps) => {\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length)\n return true\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length)\n return true\n }\n if (event.key === 'Enter') {\n if (items[selectedIndex]) command(items[selectedIndex])\n return true\n }\n return false\n },\n }))\n\n if (!items.length) return null\n\n return (\n <div role=\"listbox\" aria-label=\"Emoji suggestions\" className=\"z-popover max-h-[200px] overflow-x-hidden overflow-y-auto rounded-control bg-surface-overlay shadow-raised-hover\">\n {items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={index === selectedIndex}\n onClick={() => command(item)}\n className={cn(\n 'flex w-full items-center gap-ds-03 px-ds-04 py-ds-02b text-left text-ds-sm',\n index === selectedIndex ? 'bg-surface-raised text-surface-fg' : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n <EmojiImage emoji={item} set={set} size=\"1.25em\" />\n <span className=\"truncate\">:{item.id}:</span>\n </button>\n ))}\n </div>\n )\n },\n)\nEmojiList.displayName = 'EmojiList'\n\nfunction createEmojiSuggestionRenderer(set: string) {\n return () => {\n let root: Root | null = null\n let container: HTMLDivElement | null = null\n let componentRef: EmojiListRef | null = null\n\n return {\n onStart: (props: SuggestionProps<ResolvedEmoji>) => {\n container = document.createElement('div')\n container.style.position = 'absolute'\n container.style.zIndex = '1400'\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n document.body.appendChild(container)\n root = createRoot(container)\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onUpdate: (props: SuggestionProps<ResolvedEmoji>) => {\n if (!root || !container) return\n const rect = props.clientRect?.()\n if (rect) {\n container.style.left = `${rect.left}px`\n container.style.top = `${rect.bottom + 4}px`\n }\n root.render(\n <EmojiList\n ref={(r) => { componentRef = r }}\n items={props.items as ResolvedEmoji[]}\n set={set}\n command={(item) => props.command(item)}\n />,\n )\n },\n\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (props.event.key === 'Escape') {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n return true\n }\n return componentRef?.onKeyDown(props) ?? false\n },\n\n onExit: () => {\n if (container) {\n root?.unmount()\n container.remove()\n container = null\n root = null\n }\n },\n }\n }\n}\n\n/** Factory: call with the emoji set to get a configured extension. */\nexport function createEmojiSuggestion(set = 'native') {\n return Extension.create({\n name: 'emojiSuggestion',\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n pluginKey: new PluginKey('emojiSuggestion'),\n editor: this.editor,\n char: ':',\n items: async ({ query }) => {\n const data = await loadEmojiData(set)\n return searchEmoji(data, query, 8)\n },\n command: ({ editor, range, props: item }) => {\n const emoji = item as ResolvedEmoji\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({\n type: 'emojiNode',\n attrs: { id: emoji.id, native: emoji.native, set, x: emoji.x, y: emoji.y },\n })\n .run()\n },\n render: createEmojiSuggestionRenderer(set),\n }),\n ]\n },\n })\n}\n"],"mappings":"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"}