@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
@@ -4,38 +4,76 @@
4
4
  - Server-safe: No
5
5
  - Category: ui
6
6
 
7
+ A linear progress bar. Use the smart all-in-one `<Progress value={70} />` for the
8
+ common cases, or the compound parts (`Progress.Root` / `Track` / `Indicator` /
9
+ `Segment` / `Label` / `Value`) for full layout control and multi-segment bars.
10
+
7
11
  ## Props
8
- value: number (0-100) — omit for indeterminate
12
+ value: number | null (0–max) — omit or null for an indeterminate bar
13
+ max: number (scale maximum, default 100)
9
14
  size: "sm" | "md" | "lg" (track height)
10
- color: "default" | "success" | "warning" | "error" (indicator color)
11
- autoColor: boolean (auto-shifts color by value: 0-59=default, 60-84=warning, 85-100=success, >100=error)
12
- showLabel: boolean (shows percentage text)
13
- indicatorClassName: string
15
+ color: "accent" | "success" | "warning" | "error" (indicator color)
16
+ autoColor: boolean (auto-shift color by value: 0-59=accent, 60-84=warning, 85-100=success, >100=error)
17
+ label: ReactNode (descriptive label rendered before the bar; names the bar for a11y)
18
+ showValue: boolean (shows the "{n}%" readout after the bar)
19
+ segments: { value: number; color?: "accent" | "success" | "warning" | "error" }[] (multi-segment bar; overrides the single indicator)
20
+ trackClassName: string (class for the Track element)
21
+ indicatorClassName: string (class for the single Indicator; ignored when segments set)
22
+
23
+ ## Compound Components
24
+ Progress (smart all-in-one — value/size/color/label/showValue/autoColor/segments)
25
+ Progress.Root (layout container + context; owns value/max/size)
26
+ Progress.Label (descriptive label; give it id + point Track's aria-labelledby at it)
27
+ Progress.Track (the aria progressbar + track visual; holds Indicator or Segments)
28
+ Progress.Indicator (single fill; color, or auto-color by value)
29
+ Progress.Segment (one slice of a multi-segment bar — value + color)
30
+ Progress.Value (the "{n}%" readout; custom via children or a `format` fn)
14
31
 
15
32
  ## Defaults
16
33
  size: "md"
17
- color: "default"
34
+ color: "accent"
35
+ max: 100
18
36
 
19
37
  ## Example
20
38
  ```jsx
21
- <Progress value={75} color="success" showLabel />
22
- <Progress size="sm" /> {/* indeterminate */}
39
+ // Simple:
40
+ <Progress value={75} color="success" showValue />
41
+ <Progress size="sm" /> {/* indeterminate */}
42
+ <Progress value={80} autoColor showValue /> {/* color follows value */}
43
+
44
+ // Multi-segment (Mantine-style):
45
+ <Progress segments={[{ value: 40, color: 'success' }, { value: 30, color: 'warning' }]} />
46
+
47
+ // Compound — full control:
48
+ <Progress.Root value={62} size="lg">
49
+ <Progress.Label id="storage-lbl">Storage</Progress.Label>
50
+ <Progress.Track aria-labelledby="storage-lbl">
51
+ <Progress.Indicator color="warning" />
52
+ </Progress.Track>
53
+ <Progress.Value format={(pct) => `${pct}% of 50 GB`} />
54
+ </Progress.Root>
23
55
  ```
24
56
 
25
57
  ## Composability
26
- - **Radix Progress** underneath `value` (determinate) or absent (indeterminate). Standard ARIA: role=progressbar, aria-valuenow/min/max.
27
- - **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.
28
- - **Indeterminate:** Omit `value` to get a continuous animated indeterminate bar. Use for unknown-duration loads.
29
- - **Progress vs ProgressRing:** Progress is a linear bar (horizontal). ProgressRing is circular. ProgressRing offers multi-ring stacked variants; Progress doesn't.
30
- - **Inside Card/StatCard:** StatCard has a `progress` prop that renders a thin inline version use that inside StatCards instead of a separate Progress.
58
+ - **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.
59
+ - **`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.
60
+ - **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.
61
+ - **Segments** render side-by-side, each `value` as a % of `max`; the Track's aria value still reflects `Root`'s `value`.
62
+ - **Indeterminate:** omit `value` (or pass `null`) for the continuous sweep. Motion-reduced users get a static bar.
63
+ - **Progress vs ProgressRing:** Progress is linear; `ProgressRing` is circular (with multi-ring stacked variants).
31
64
 
32
65
  ## Gotchas
33
- - Omit value (or pass undefined) for indeterminate animation
34
- - `autoColor` overrides `color` when `value` is set — do not pass both unless you want autoColor to win
66
+ - Omit `value` (or pass `null`) for indeterminate.
67
+ - Pass an explicit `color` to override `autoColor`.
68
+ - 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).
69
+ - `Progress.Indicator` / `Segment` / `Value` throw if rendered outside `Progress.Root`.
35
70
 
36
71
  ## Changes
72
+ ### v0.49.0
73
+ - **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).
74
+
37
75
  ### v0.29.0
38
- - **Added** `autoColor` prop — automatically shifts indicator color based on value thresholds (0-59 default, 60-84 warning, 85-100 success, >100 error)
76
+ - **Added** `autoColor` prop — automatically shifts indicator color based on value thresholds
39
77
 
40
78
  ### v0.1.0
41
79
  - **Added** Initial release with `size`, `color`, `indeterminate` variants and optional label slot
@@ -12,6 +12,7 @@
12
12
  disabled: boolean (propagates to all items)
13
13
  orientation: "horizontal" | "vertical"
14
14
  name: string (form name for all items)
15
+ state: "default" | "error" | "warning" | "success" (validation; sets aria-invalid on the group + tints item borders. Inherited from FormField when omitted)
15
16
 
16
17
  ### RadioGroupItem
17
18
  value: string (REQUIRED — what's selected when this item is checked)
@@ -44,14 +45,17 @@
44
45
  - **RadioGroup propagates** `disabled` to every RadioGroupItem; items can opt back in with `disabled={false}` for granular control (rare).
45
46
  - **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.
46
47
  - **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.
47
- - **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.
48
+ - **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.
48
49
 
49
50
  ## Gotchas
50
51
  - Each RadioGroupItem needs a unique `value` prop
51
52
  - Pair each item with a Label for accessibility
52
- - RadioGroup does NOT auto-inherit FormField error state handle error styling at the group level
53
+ - RadioGroup inherits FormField state; pass `state` explicitly to override
53
54
 
54
55
  ## Changes
56
+ ### v0.49.0
57
+ - **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.
58
+
55
59
  ### v0.4.2
56
60
  - **Added** `RadioGroupProps`, `RadioGroupItemProps` type exports
57
61
 
@@ -7,12 +7,12 @@
7
7
  ## Props
8
8
  ### SelectTrigger
9
9
  variant: "default" | "outline" | "ghost"
10
- color: "default" | "error" | "success" | "warning" (sets aria-invalid when error)
10
+ state: "default" | "error" | "warning" | "success" (validation; sets aria-invalid when error. Inherited from FormField when omitted)
11
11
  size: "xs" | "sm" | "md" | "lg"
12
12
 
13
13
  ## Compound Components
14
14
  Select (root — value, onValueChange, defaultValue)
15
- SelectTrigger (variant/color/size go HERE, not on Select root)
15
+ SelectTrigger (variant/state/size go HERE, not on Select root)
16
16
  SelectValue (placeholder)
17
17
  SelectContent
18
18
  SelectGroup (optional grouping)
@@ -21,7 +21,7 @@
21
21
  SelectSeparator
22
22
 
23
23
  ## Defaults
24
- SelectTrigger variant="default", color="default", size="md"
24
+ SelectTrigger variant="default", state="default", size="md"
25
25
 
26
26
  ## Example
27
27
  ```jsx
@@ -38,10 +38,10 @@
38
38
 
39
39
  ## Composability
40
40
  - **Radix Select** underneath — `value`/`onValueChange`/`defaultValue`/`open`/`onOpenChange` standard state.
41
- - **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.
41
+ - **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.
42
42
  - **SelectItem requires `value`** — unique within the Select. Labels are the children of SelectItem.
43
43
  - **SelectGroup + SelectLabel:** Organize options into sections with a non-interactive section heading.
44
- - **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).
44
+ - **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.
45
45
  - **Portal + z-popover (1400):** content portals to body, stacks above Dialog/Sheet/other overlays.
46
46
  - **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.
47
47
 
@@ -50,6 +50,10 @@
50
50
  - `<Select size="lg">` is silently ignored (no TypeScript error)
51
51
 
52
52
  ## Changes
53
+ ### v0.49.0
54
+ - **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">`.
55
+ - **Added** SelectTrigger now inherits validation state from `FormField` context (was manual-only before).
56
+
53
57
  ### v0.31.0
54
58
  - **Added** `variant` prop on SelectTrigger: `default | outline | ghost`
55
59
  - **Added** `color` prop on SelectTrigger: `default | error | success | warning`. Sets `aria-invalid` when error.
@@ -7,7 +7,7 @@
7
7
  ## Props
8
8
  checked: boolean
9
9
  onCheckedChange: (checked: boolean) => void
10
- error: boolean (shows red border/bg)
10
+ state: "default" | "error" | "warning" | "success" (validation border/checked-track tint; error sets aria-invalid. Inherited from FormField when omitted. Distinct from `color`, the ON-track tint)
11
11
  disabled: boolean
12
12
  size: "sm" | "md" | "lg"
13
13
  color: "accent" | "success" | "warning"
@@ -35,6 +35,9 @@
35
35
  - Switch does NOT auto-consume FormField — pass `error` explicitly inside a FormField
36
36
 
37
37
  ## Changes
38
+ ### v0.49.0
39
+ - **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.)
40
+
38
41
  ### v0.29.0
39
42
  - **Added** `size` prop: `"sm"` (18px track) | `"md"` (24px, default) | `"lg"` (28px track)
40
43
  - **Added** `color` prop: `"accent"` (default) | `"success"` | `"warning"` for checked-state color
@@ -18,7 +18,7 @@
18
18
  <TableCell><Badge color="success">Active</Badge></TableCell>
19
19
  <TableCell>
20
20
  <TableRowActions>
21
- <IconButton className="relative z-[1]" size="xs" variant="ghost" aria-label={`Actions for ${name}`} icon={<IconDots />} />
21
+ <IconButton className="relative z-[1]" size="sm" variant="ghost" aria-label={`Actions for ${name}`} icon={<IconDots />} />
22
22
  </TableRowActions>
23
23
  </TableCell>
24
24
  </TableRow>
@@ -16,7 +16,8 @@
16
16
  Reveal is opacity-based: buttons stay in the tab order permanently, appear on row hover AND :focus-within, and are always visible on touch (pointer-coarse). Give the column a visually-hidden header.
17
17
 
18
18
  ### TableRowLink (separate import: ui/table-row-link — client component)
19
- href: string (required); stretch: boolean (default true)
19
+ href: string (required)
20
+ stretch: boolean (default: true)
20
21
  A real anchor placed in the row's primary cell (`<TableCell className="relative">`), stretched across the row via a pseudo-element — cmd/ctrl+click, middle-click, and context menu work, unlike onClick-on-row. Keyboard focus draws a row-level ring. Other interactive elements in the row need `className="relative z-[1]"`. `stretch={false}` = title-only link (keeps row text selectable).
21
22
 
22
23
  ## Compound Components
@@ -21,7 +21,7 @@ Pick the recipe that matches your framework. Detection criteria are listed at th
21
21
  | Vite + React | [install-vite.md](./install-vite.md) | `vite.config.*` exists; SPA or MPA |
22
22
  | Astro | [install-astro.md](./install-astro.md) | `astro.config.*` exists |
23
23
  | Remix | [install-remix.md](./install-remix.md) | `remix.config.*` or Remix v2 with Vite |
24
- | TanStack Start | [install-tanstack-start.md](./install-tanstack-start.md) | `app.config.*` with `@tanstack/start` |
24
+ | TanStack Start | [install-tanstack-start.md](./install-tanstack-start.md) | `@tanstack/react-start` + `vite.config.*` (the current Vite-plugin setup; the retired Vinxi `app.config.*` + `@tanstack/start` must migrate first) |
25
25
 
26
26
  If the framework is not listed, start with [install-vite.md](./install-vite.md) and adapt — most React+Tailwind setups follow the same shape.
27
27
 
@@ -31,18 +31,21 @@ pnpm add sonner
31
31
 
32
32
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
33
33
 
34
- 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.
35
-
36
- | When you import… | Install |
37
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
38
- | `@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` |
39
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
40
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
41
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
42
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
43
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
44
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
45
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
34
+ 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.
35
+
36
+ | When you import… | Install |
37
+ |---|---|
38
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
39
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
40
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
41
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
42
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
43
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
44
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
45
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
46
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
47
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
48
+ | 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` |
46
49
 
47
50
  ## 3. Wire Tailwind 4 in `astro.config`
48
51
 
@@ -46,16 +46,19 @@ pnpm add sonner
46
46
 
47
47
  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.).
48
48
 
49
- | When you import… | Install |
50
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
51
- | `@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` |
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` use with Tabler icons | `pnpm add @tabler/icons-react` |
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
  > 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.
61
64
 
@@ -164,9 +167,14 @@ export function Providers({ children }: { children: ReactNode }) {
164
167
  }
165
168
  ```
166
169
 
167
- `next-themes` is already in the install list from § 2 no extra install step needed here. If `<Toaster />` is not used:
170
+ > **This default `Providers` renders `<Toaster />`, which imports `sonner`.** Install it now or `next build` fails with `Module not found: Can't resolve 'sonner'`:
171
+ > ```bash
172
+ > pnpm add sonner
173
+ > ```
168
174
 
169
- - Drop the `Toaster` import and its JSX usage
175
+ `next-themes` is already in the install list from § 2 — no extra install step needed here. If you do **not** want toasts:
176
+
177
+ - Drop the `Toaster` import and its JSX usage from `Providers`
170
178
  - Skip installing `sonner`
171
179
 
172
180
  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:
@@ -16,7 +16,7 @@ If both `app/` and `pages/` exist, prefer [install-next-app-router.md](./install
16
16
 
17
17
  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).
18
18
 
19
- **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.
19
+ **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.
20
20
 
21
21
  ## 3. PostCSS
22
22
 
@@ -67,6 +67,8 @@ export default function App({ Component, pageProps }: AppProps) {
67
67
  }
68
68
  ```
69
69
 
70
+ > ⚠ **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`.
71
+
70
72
  For `next-themes` to avoid hydration warnings, add a `_document.tsx` with `suppressHydrationWarning` on the `<html>`:
71
73
 
72
74
  ```tsx
@@ -10,7 +10,7 @@ You are in this recipe if:
10
10
  - `vite.config.{ts,js}` exists with the `vitePlugin` from `@remix-run/dev`
11
11
  - `app/root.tsx` exists with `<Outlet />` inside `<Document>` shell
12
12
 
13
- For React Router v7 (the spiritual successor to Remix), use the [install-vite.md](./install-vite.md) recipeit works the same way.
13
+ > **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.
14
14
 
15
15
  ## 2. Install
16
16
 
@@ -27,18 +27,21 @@ pnpm add sonner # only if rendering <Toaster />
27
27
 
28
28
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
29
29
 
30
- 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.
31
-
32
- | When you import… | Install |
33
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
34
- | `@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` |
35
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
36
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
37
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
38
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
39
- | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
40
- | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter` |
41
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
30
+ 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.
31
+
32
+ | When you import… | Install |
33
+ |---|---|
34
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
35
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
36
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
37
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
38
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
39
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
40
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
41
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
42
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
43
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
44
+ | 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` |
42
45
 
43
46
  ## 3. Wire Tailwind 4 in `vite.config.ts`
44
47
 
@@ -14,6 +14,8 @@ You are in this recipe if:
14
14
 
15
15
  If instead you see `app.config.ts` + `@tanstack/start`, that is the legacy Vinxi setup — this recipe does not apply until you migrate.
16
16
 
17
+ > **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.
18
+
17
19
  ## 2. Install
18
20
 
19
21
  ```bash
@@ -34,18 +36,21 @@ pnpm add sonner # only if rendering <Toaster />
34
36
 
35
37
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
36
38
 
37
- 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.
38
-
39
- | When you import… | Install |
40
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
41
- | `@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` |
42
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
43
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
44
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
45
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
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` |
48
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
39
+ 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.
40
+
41
+ | When you import… | Install |
42
+ |---|---|
43
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
44
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
45
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
46
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
47
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
48
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
49
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
50
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
51
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
52
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
53
+ | 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` |
49
54
 
50
55
  ## 3. Wire Tailwind 4 in `vite.config.ts`
51
56
 
@@ -115,6 +120,8 @@ function RootComponent() {
115
120
  }
116
121
  ```
117
122
 
123
+ > **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.)
124
+
118
125
  ## 5. Theme toggle
119
126
 
120
127
  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.
@@ -42,18 +42,21 @@ pnpm add sonner
42
42
 
43
43
  ### 2a. Optional peer dependencies (install ONLY when importing the matching subpath)
44
44
 
45
- 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.
46
-
47
- | When you import… | Install |
48
- |-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
49
- | `@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` |
50
- | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
51
- | `@devalok/shilp-sutra/composed/date-picker` (+ DateRange, DateTime, Calendar) | `pnpm add date-fns` |
52
- | `@devalok/shilp-sutra/composed/rich-text-editor` (+ RichChatInput, RichTextViewer) | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
53
- | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
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` |
56
- | Any `Icon` / `IconButton` with Tabler icons | `pnpm add @tabler/icons-react` |
45
+ 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.
46
+
47
+ | When you import… | Install |
48
+ |---|---|
49
+ | `@devalok/shilp-sutra/composed/date-picker` | `pnpm add date-fns` |
50
+ | `@devalok/shilp-sutra/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
51
+ | `@devalok/shilp-sutra/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
52
+ | `@devalok/shilp-sutra/composed/schedule-view` | `pnpm add date-fns` |
53
+ | `@devalok/shilp-sutra/ui/charts` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
54
+ | `@devalok/shilp-sutra/ui/data-table` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
55
+ | `@devalok/shilp-sutra/ui/data-table-toolbar` | `pnpm add @tanstack/react-table` |
56
+ | `@devalok/shilp-sutra/ui/input-otp` | `pnpm add input-otp` |
57
+ | `@devalok/shilp-sutra/ui/toast` | `pnpm add sonner` |
58
+ | `@devalok/shilp-sutra/ui/toaster` | `pnpm add sonner` |
59
+ | 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` |
57
60
 
58
61
  ## 3. Wire Tailwind 4 in `vite.config.ts`
59
62
 
@@ -136,7 +139,7 @@ If you installed `sonner`, mount the Toaster once near the app root:
136
139
  import { StrictMode } from "react";
137
140
  import { createRoot } from "react-dom/client";
138
141
  import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
139
- import { App } from "./App";
142
+ import App from "./App";
140
143
  import "./index.css";
141
144
 
142
145
  createRoot(document.getElementById("root")!).render(
@@ -149,14 +152,14 @@ createRoot(document.getElementById("root")!).render(
149
152
 
150
153
  ## 7. Verify
151
154
 
152
- Replace `src/App.tsx`:
155
+ 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`):
153
156
 
154
157
  ```tsx
155
158
  import { Button } from "@devalok/shilp-sutra/ui/button";
156
159
  import { Stack } from "@devalok/shilp-sutra/ui/stack";
157
160
  import { Text } from "@devalok/shilp-sutra/ui/text";
158
161
 
159
- export function App() {
162
+ export default function App() {
160
163
  return (
161
164
  <Stack className="p-ds-08" gap="ds-04">
162
165
  <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
@@ -95,26 +95,25 @@ Add:
95
95
  transpilePackages: ["@devalok/shilp-sutra"],
96
96
  ```
97
97
 
98
- ## Symptom: Build error `Cannot find module 'sonner' / 'input-otp' / 'date-fns' / '@tiptap/react' / 'react-pdf' / 'react-markdown' / '@emoji-mart/react'`
98
+ ## 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
99
99
 
100
- **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):
100
+ **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.
101
101
 
102
102
  | You imported (per-component subpath) | Install |
103
103
  |--------------------------------------|-----------------------------------------------------------------------------------------------|
104
104
  | `…/ui/toaster` or `…/ui/toast` | `pnpm add sonner` |
105
105
  | `…/ui/input-otp` | `pnpm add input-otp` |
106
- | `…/composed/date-picker` | `pnpm add date-fns` |
107
- | `…/composed/emoji-picker` | `pnpm add @emoji-mart/data @emoji-mart/react` |
108
- | `…/composed/extensions/emoji-node` or `…/extensions/emoji-suggestion` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
109
- | `…/composed/rich-text-editor` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
110
- | `…/composed/rich-chat-input` | `pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-placeholder` |
106
+ | `…/composed/date-picker` or `…/composed/schedule-view` | `pnpm add date-fns` |
107
+ | `…/ui/data-table` or `…/ui/data-table-toolbar` | `pnpm add @tanstack/react-table @tanstack/react-virtual` |
111
108
  | `…/composed/file-preview` | `pnpm add react-pdf react-zoom-pan-pinch` |
112
109
  | `…/composed/markdown-viewer` | `pnpm add react-markdown react-syntax-highlighter remark-gfm` |
113
110
  | `…/ai/block-renderer`, `…/ai/blocks/text`, `…/ai/blocks/error` | `pnpm add react-markdown remark-gfm` |
114
- | Any `…/ui/charts/*` | `pnpm add d3-array d3-axis d3-format d3-interpolate d3-scale d3-selection d3-shape d3-time-format d3-transition` |
111
+ | Any `…/ui/charts/*` | `pnpm add d3-axis d3-scale d3-selection d3-shape` |
115
112
 
116
113
  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.
117
114
 
115
+ **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.
116
+
118
117
  **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.
119
118
 
120
119
  For the full table in your framework's install recipe, see `install-<framework>.md → §2a. Optional peer dependencies`.