@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
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/ui/tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@primitives/react-tooltip'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Auto-provider: wraps with TooltipPrimitive.Provider if none exists ──\n\nconst TooltipProviderContext = React.createContext(false)\n\nconst TooltipProvider: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>> = ({\n children,\n ...props\n}) => (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider {...props}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n)\n\nfunction AutoProvider({ children }: { children: React.ReactNode }) {\n const hasProvider = React.useContext(TooltipProviderContext)\n if (hasProvider) return <>{children}</>\n return (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider delayDuration={300}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n )\n}\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype TooltipContextValue = { open: boolean }\nconst TooltipContext = React.createContext<TooltipContextValue>({ open: false })\n\nconst Tooltip: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const isControlled = openProp !== undefined\n const open = isControlled ? openProp : internalOpen\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) setInternalOpen(nextOpen)\n onOpenChange?.(nextOpen)\n },\n [isControlled, onOpenChange],\n )\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AutoProvider>\n <TooltipContext.Provider value={contextValue}>\n <TooltipPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />\n </TooltipContext.Provider>\n </AutoProvider>\n )\n}\nTooltip.displayName = 'Tooltip'\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\n// ── Side-based slide offsets ──\n\nconst sideOffset: Record<string, { x?: number; y?: number }> = {\n top: { y: 4 },\n bottom: { y: -4 },\n left: { x: 4 },\n right: { x: -4 },\n}\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset: sideOffsetProp = 4, side = 'top', children, ...props }, ref) => {\n const { open } = React.useContext(TooltipContext)\n const slideInit = sideOffset[side] ?? {}\n\n return (\n <AnimatePresence>\n {open && (\n <TooltipPrimitive.Portal forceMount>\n <TooltipPrimitive.Content\n ref={ref}\n forceMount\n sideOffset={sideOffsetProp}\n side={side}\n {...props}\n asChild\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95, ...slideInit }}\n animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, ...slideInit }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-ds-sm text-surface-inverted-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )}\n </AnimatePresence>\n )\n})\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n\nexport { Tooltip, TooltipContent, TooltipProvider,TooltipTrigger }\n"],"mappings":";;;;;;;;AAWA,IAAM,IAAyB,EAAM,cAAc,GAAM,EAEnD,KAA+F,EACnG,aACA,GAAG,QAEH,kBAAC,EAAuB,UAAxB;CAAiC,OAAO;WACtC,kBAAC,GAAD;EAA2B,GAAI;EAC5B;EACyB,CAAA;CACI,CAAA;AAGpC,SAAS,EAAa,EAAE,eAA2C;AAGjE,QAFoB,EAAM,WAAW,EAAuB,GACpC,kBAAA,GAAA,EAAG,aAAY,CAAA,GAErC,kBAAC,EAAuB,UAAxB;EAAiC,OAAO;YACtC,kBAAC,GAAD;GAA2B,eAAe;GACvC;GACyB,CAAA;EACI,CAAA;;AAOtC,IAAM,IAAiB,EAAM,cAAmC,EAAE,MAAM,IAAO,CAAC,EAE1E,KAAmF,EACvF,MAAM,GACN,gBACA,iBACA,GAAG,QACC;CACJ,IAAM,CAAC,GAAc,KAAmB,EAAM,SAAS,KAAe,GAAM,EACtE,IAAe,MAAa,KAAA,GAC5B,IAAO,IAAe,IAAW,GAEjC,IAAmB,EAAM,aAC5B,MAAsB;AAErB,EADK,KAAc,EAAgB,EAAS,EAC5C,IAAe,EAAS;IAE1B,CAAC,GAAc,EAAa,CAC7B,EAEK,IAAe,EAAM,eAAe,EAAE,SAAM,GAAG,CAAC,EAAK,CAAC;AAE5D,QACE,kBAAC,GAAD,EAAA,UACE,kBAAC,EAAe,UAAhB;EAAyB,OAAO;YAC9B,kBAAC,GAAD;GAA6B;GAAM,cAAc;GAAkB,GAAI;GAAS,CAAA;EACxD,CAAA,EACb,CAAA;;AAGnB,EAAQ,cAAc;AAEtB,IAAM,IAAiB,GAIjB,IAAyD;CAC7D,KAAK,EAAE,GAAG,GAAG;CACb,QAAQ,EAAE,GAAG,IAAI;CACjB,MAAM,EAAE,GAAG,GAAG;CACd,OAAO,EAAE,GAAG,IAAI;CACjB,EAEK,IAAiB,EAAM,YAG1B,EAAE,cAAW,YAAY,IAAiB,GAAG,UAAO,OAAO,aAAU,GAAG,KAAS,MAAQ;CAC1F,IAAM,EAAE,YAAS,EAAM,WAAW,EAAe,EAC3C,IAAY,EAAW,MAAS,EAAE;AAExC,QACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EAAyB,YAAA;YACvB,kBAAC,GAAD;GACO;GACL,YAAA;GACA,YAAY;GACN;GACN,GAAI;GACJ,SAAA;aAEA,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;KAAW;IAClD,SAAS;KAAE,SAAS;KAAG,OAAO;KAAG,GAAG;KAAG,GAAG;KAAG;IAC7C,MAAM;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;KAAW;IAC/C,YAAY;KAAE,GAAG,EAAQ;KAAQ,SAAS,EAAO;KAAM;IACvD,WAAW,EACT,2IACA,EACD;IAEA;IACU,CAAA;GACY,CAAA;EACH,CAAA,EAEZ,CAAA;EAEpB;AACF,EAAe,cAAA,EAAuC"}
1
+ {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/ui/tooltip.tsx"],"sourcesContent":["'use client'\n\nimport * as TooltipPrimitive from '@primitives/react-tooltip'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs, tweens } from './lib/motion'\nimport { useControllableOpen } from './lib/use-controllable-open'\nimport { cn } from './lib/utils'\n\n// ── Auto-provider: wraps with TooltipPrimitive.Provider if none exists ──\n\nconst TooltipProviderContext = React.createContext(false)\n\nconst TooltipProvider: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>> = ({\n children,\n ...props\n}) => (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider {...props}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n)\n\nfunction AutoProvider({ children }: { children: React.ReactNode }) {\n const hasProvider = React.useContext(TooltipProviderContext)\n if (hasProvider) return <>{children}</>\n return (\n <TooltipProviderContext.Provider value={true}>\n <TooltipPrimitive.Provider delayDuration={300}>\n {children}\n </TooltipPrimitive.Provider>\n </TooltipProviderContext.Provider>\n )\n}\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype TooltipContextValue = { open: boolean }\nconst TooltipContext = React.createContext<TooltipContextValue>({ open: false })\n\nconst Tooltip: React.FC<React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const { open, setOpen } = useControllableOpen({ open: openProp, defaultOpen, onOpenChange })\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AutoProvider>\n <TooltipContext.Provider value={contextValue}>\n <TooltipPrimitive.Root open={open} onOpenChange={setOpen} {...props} />\n </TooltipContext.Provider>\n </AutoProvider>\n )\n}\nTooltip.displayName = 'Tooltip'\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\n// ── Side-based slide offsets ──\n\nconst sideOffset: Record<string, { x?: number; y?: number }> = {\n top: { y: 4 },\n bottom: { y: -4 },\n left: { x: 4 },\n right: { x: -4 },\n}\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset: sideOffsetProp = 4, side = 'top', children, ...props }, ref) => {\n const { open } = React.useContext(TooltipContext)\n const slideInit = sideOffset[side] ?? {}\n\n return (\n <AnimatePresence>\n {open && (\n <TooltipPrimitive.Portal forceMount>\n <TooltipPrimitive.Content\n ref={ref}\n forceMount\n sideOffset={sideOffsetProp}\n side={side}\n {...props}\n asChild\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95, ...slideInit }}\n animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, ...slideInit }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-tooltip overflow-hidden rounded-overlay-sm bg-surface-inverted px-ds-04 py-ds-02b text-ds-sm text-surface-inverted-fg shadow-floating',\n className,\n )}\n >\n {children}\n </motion.div>\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )}\n </AnimatePresence>\n )\n})\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n\nexport { Tooltip, TooltipContent, TooltipProvider,TooltipTrigger }\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAyB,EAAM,cAAc,GAAM,EAEnD,KAA+F,EACnG,aACA,GAAG,QAEH,kBAAC,EAAuB,UAAxB;CAAiC,OAAO;WACtC,kBAAC,GAAD;EAA2B,GAAI;EAC5B;EACyB,CAAA;CACI,CAAA;AAGpC,SAAS,EAAa,EAAE,eAA2C;AAGjE,QAFoB,EAAM,WAAW,EAAuB,GACpC,kBAAA,GAAA,EAAG,aAAY,CAAA,GAErC,kBAAC,EAAuB,UAAxB;EAAiC,OAAO;YACtC,kBAAC,GAAD;GAA2B,eAAe;GACvC;GACyB,CAAA;EACI,CAAA;;AAOtC,IAAM,IAAiB,EAAM,cAAmC,EAAE,MAAM,IAAO,CAAC,EAE1E,KAAmF,EACvF,MAAM,GACN,gBACA,iBACA,GAAG,QACC;CACJ,IAAM,EAAE,SAAM,eAAY,EAAoB;EAAE,MAAM;EAAU;EAAa;EAAc,CAAC,EAEtF,IAAe,EAAM,eAAe,EAAE,SAAM,GAAG,CAAC,EAAK,CAAC;AAE5D,QACE,kBAAC,GAAD,EAAA,UACE,kBAAC,EAAe,UAAhB;EAAyB,OAAO;YAC9B,kBAAC,GAAD;GAA6B;GAAM,cAAc;GAAS,GAAI;GAAS,CAAA;EAC/C,CAAA,EACb,CAAA;;AAGnB,EAAQ,cAAc;AAEtB,IAAM,IAAiB,GAIjB,IAAyD;CAC7D,KAAK,EAAE,GAAG,GAAG;CACb,QAAQ,EAAE,GAAG,IAAI;CACjB,MAAM,EAAE,GAAG,GAAG;CACd,OAAO,EAAE,GAAG,IAAI;CACjB,EAEK,IAAiB,EAAM,YAG1B,EAAE,cAAW,YAAY,IAAiB,GAAG,UAAO,OAAO,aAAU,GAAG,KAAS,MAAQ;CAC1F,IAAM,EAAE,YAAS,EAAM,WAAW,EAAe,EAC3C,IAAY,EAAW,MAAS,EAAE;AAExC,QACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EAAyB,YAAA;YACvB,kBAAC,GAAD;GACO;GACL,YAAA;GACA,YAAY;GACN;GACN,GAAI;GACJ,SAAA;aAEA,kBAAC,EAAO,KAAR;IACE,SAAS;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;KAAW;IAClD,SAAS;KAAE,SAAS;KAAG,OAAO;KAAG,GAAG;KAAG,GAAG;KAAG;IAC7C,MAAM;KAAE,SAAS;KAAG,OAAO;KAAM,GAAG;KAAW;IAC/C,YAAY;KAAE,GAAG,EAAQ;KAAQ,SAAS,EAAO;KAAM;IACvD,WAAW,EACT,2IACA,EACD;IAEA;IACU,CAAA;GACY,CAAA;EACH,CAAA,EAEZ,CAAA;EAEpB;AACF,EAAe,cAAA,EAAuC"}
@@ -0,0 +1,46 @@
1
+ # AICommandProvider
2
+
3
+ - Import: @devalok/shilp-sutra/ai/ai-command-provider
4
+ - Server-safe: No
5
+ - Category: ai
6
+
7
+ Context provider for the AI command system. Supplies custom block renderers, the
8
+ action handler, and the agent identity to `AIConversation` / `BlockRenderer` below
9
+ it, so you configure them once instead of threading props through every message.
10
+ Ships a `useAICommand()` hook to read the context.
11
+
12
+ ## Props
13
+ children: ReactNode (required)
14
+ customBlocks: Record<string, ComponentType<BlockComponentProps>> — custom block-type renderers available to all descendants
15
+ onAction: (actionId: string, type: "confirm" | "cancel" | "undo") => void — default action handler for descendant blocks
16
+ agent: { name: string, icon?: IconInput } — default agent identity for assistant messages
17
+
18
+ ## Example
19
+ ```jsx
20
+ <AICommandProvider
21
+ agent={{ name: 'Devadoot', icon: <IconSparkles /> }}
22
+ customBlocks={{ chart: ChartBlock }}
23
+ onAction={(id, type) => handleAction(id, type)}
24
+ >
25
+ <AIConversation messages={messages} />
26
+ </AICommandProvider>
27
+
28
+ // Read the context in a descendant:
29
+ function MyBlock() {
30
+ const ctx = useAICommand() // { customBlocks, onAction, agent } | null
31
+ // ...
32
+ }
33
+ ```
34
+
35
+ ## Composability
36
+ - **Configure once** — set `customBlocks`, `onAction`, and `agent` here; `AIConversation` and `BlockRenderer` read them via context. Per-component props still win over the context (prop overrides provider).
37
+ - **`useAICommand()`** — returns the context (`{ customBlocks, onAction, agent }`) or `null` when no provider is mounted. Custom blocks can use it to reach the shared action handler.
38
+ - **Optional** — `AIConversation`/`BlockRenderer` work without a provider if you pass their props directly; the provider is a convenience for app-wide config.
39
+
40
+ ## Gotchas
41
+ - Client component — mount inside a client boundary.
42
+ - `useAICommand()` returns `null` (not a throw) when there's no provider — guard for it in custom blocks.
43
+
44
+ ## Changes
45
+ ### v0.49.0
46
+ - **Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP).
@@ -0,0 +1,59 @@
1
+ # BlockRenderer
2
+
3
+ - Import: @devalok/shilp-sutra/ai/block-renderer
4
+ - Server-safe: No
5
+ - Category: ai
6
+
7
+ Renders an ordered list of typed AI "blocks" — the structured chunks an assistant/
8
+ server emits instead of plain text. A registry maps each block's `type` to a React
9
+ component; consumers can register their own types. This doc also covers the block
10
+ system and how to author a custom block.
11
+
12
+ ## Props
13
+ blocks: Block[] (required) — ordered blocks to render
14
+ onAction: (actionId: string, type: "confirm" | "cancel" | "undo") => void — fired by interactive blocks (e.g. confirm)
15
+ customBlocks: Record<string, ComponentType<BlockComponentProps>> — extra type→component renderers, merged OVER the built-ins (prop wins over context)
16
+ staggerDelay: number — ms between each block's entrance animation (default 50)
17
+ className: string
18
+
19
+ Block: { id?: string, type: string, data: Record<string, unknown>, confidence?: "high" | "medium" | "low" } (see ai/types)
20
+ BlockComponentProps<T>: { data: T, blockId?: string, confidence?: "high" | "medium" | "low", onAction?: (actionId, type) => void }
21
+
22
+ ## Defaults
23
+ staggerDelay defaults to 50
24
+
25
+ ## Example
26
+ ```jsx
27
+ // Render server-emitted blocks:
28
+ <BlockRenderer
29
+ blocks={message.blocks}
30
+ onAction={(id, type) => handleAction(id, type)}
31
+ />
32
+
33
+ // Register a custom block type:
34
+ function ChartBlock({ data }) {
35
+ return <MyChart series={data.series} />
36
+ }
37
+ <BlockRenderer
38
+ blocks={message.blocks}
39
+ customBlocks={{ chart: ChartBlock }}
40
+ />
41
+ ```
42
+
43
+ ## Composability
44
+ - **The block system** — the AI conversation renders assistant output as a `Block[]`. Each block has a `type` (string) and a `data` payload. `BlockRenderer` looks up the type in its registry and renders the matching component; an unknown type falls back to an `Alert` showing the raw JSON (so a new server-emitted type degrades gracefully instead of crashing).
45
+ - **Built-in block types** (9): `text` (Markdown prose), `table` (tabular data), `confirm` (action confirmation — confirm/cancel buttons + a "Why this action?" rationale drawer), `success` / `error` / `info` (status messages), `loading` (pending indicator), `divider` (separator), `stat_row` (a row of metric cards, composes `StatCard`).
46
+ - **Confidence** — every block may carry `confidence: "high" | "medium" | "low"`. Low-confidence blocks get a faint warning wash + a "Low confidence" chip (owned by the shared `BlockShell` wrapper, so the treatment is consistent across all block types). This is an AI-native affordance: the UI signals how sure the model is.
47
+ - **Writing a custom block** — a block component receives `BlockComponentProps<T>` (`data`, `confidence`, `onAction`, `blockId`). Wrap your content in `BlockShell` to inherit the confidence treatment. Register it via `customBlocks` (on `BlockRenderer` or `AICommandProvider`) keyed by the `type` string your server emits.
48
+ - **Two public block subpaths** — `text` and `error` import `react-markdown` + `remark-gfm` (a Markdown peer dependency). They were split out of the `ai/blocks` barrel in 0.40.0 so consumers don't pull those peers unless they render Markdown. Import them directly when needed: `@devalok/shilp-sutra/ai/blocks/text`, `@devalok/shilp-sutra/ai/blocks/error`.
49
+ - **Provider merge** — `customBlocks` from `AICommandProvider` (context) are merged with the `customBlocks` prop; the prop wins on key collision. Same for `onAction`.
50
+
51
+ ## Gotchas
52
+ - Client component — mount inside a client boundary.
53
+ - Requires a mounted `MotionProvider` (block entrances respect reduced-motion).
54
+ - Rendering `text`/`error` blocks requires the `react-markdown` + `remark-gfm` peer dependencies — install them if your blocks include Markdown.
55
+ - The `ai/blocks/*` components are an implementation detail of the registry; consume blocks via `BlockRenderer`/`AIConversation`, not by importing each block (except the two documented Markdown subpaths).
56
+
57
+ ## Changes
58
+ ### v0.49.0
59
+ - **Added** Component + block-system documentation (the AI layer is now covered by the docs gate + hosted MCP).
@@ -0,0 +1,78 @@
1
+ # CommandBar
2
+
3
+ - Import: @devalok/shilp-sutra/ai/command-bar
4
+ - Server-safe: No
5
+ - Category: ai
6
+
7
+ A unified AI command input with three layout variants. Supports natural-language
8
+ submission (`onSubmit`) and, optionally, command-palette filtering (`groups`) in the
9
+ same bar. Shows an animated brand-gradient border while processing.
10
+
11
+ ## Props
12
+ onSubmit: (query: string) => void — called on Enter (natural-language submission)
13
+ state: "idle" | "typing" | "processing" | "responded" — drives visual feedback (gradient border, placeholder)
14
+ groups: CommandGroup[] — when provided, enables command-palette filtering alongside AI submission
15
+ onSearch: (query: string) => void — fired as the query changes (palette mode)
16
+ emptyMessage: string — text when a palette search yields nothing
17
+ emptyState: ReactNode — replaces the default empty UI
18
+ variant: "hero" | "inline" | "floating" — layout (default "hero")
19
+ placeholder: string | string[] — static text, or an array that rotates on an interval
20
+ placeholderInterval: number — rotation interval in ms when placeholder is an array (default 4000)
21
+ greeting: string — text above the input (hero variant)
22
+ hints: string[] — hint strings below the input (hero variant)
23
+ agentName: string
24
+ agentIcon: ReactNode
25
+ open: boolean — controlled open state (floating variant)
26
+ defaultOpen: boolean — uncontrolled initial open (floating variant)
27
+ onOpenChange: (open: boolean) => void — floating variant
28
+ keybinding: string | string[] | false — global toggle for the floating bar (default "mod+j")
29
+ disabled: boolean
30
+ maxHeight: string | number — cap on the results/scroll region (default "320px")
31
+ children: ReactNode
32
+
33
+ CommandGroup / CommandItem: shared with composed/command-palette (see that doc)
34
+
35
+ ## Defaults
36
+ variant defaults to "hero"
37
+ placeholderInterval defaults to 4000
38
+ keybinding defaults to "mod+j"
39
+ maxHeight defaults to "320px"
40
+
41
+ ## Example
42
+ ```jsx
43
+ // Hero variant — the primary AI entry point on a dashboard:
44
+ <CommandBar
45
+ variant="hero"
46
+ greeting="What can I help with?"
47
+ placeholder={['Summarize this project…', 'Draft a status update…', 'Find overdue tasks…']}
48
+ hints={['⌘J to open anywhere', 'Ask in plain English']}
49
+ state={aiState}
50
+ onSubmit={(q) => runAgent(q)}
51
+ />
52
+
53
+ // Floating variant — global ⌘J overlay, palette + AI in one:
54
+ <CommandBar
55
+ variant="floating"
56
+ keybinding="mod+j"
57
+ groups={commandGroups}
58
+ onSearch={setQuery}
59
+ onSubmit={(q) => runAgent(q)}
60
+ />
61
+ ```
62
+
63
+ ## Composability
64
+ - **Two modes in one bar** — pass `onSubmit` for natural-language AI; add `groups` to also get command-palette filtering (arrow-key navigation, grouped items). Reuses `CommandGroup`/`CommandItem` from composed/command-palette.
65
+ - **`floating` reuses the Dialog primitive** (`DialogContentRaw`) with a global keybinding — same overlay pattern as CommandPalette, so focus-trap/Escape/scroll-lock come for free.
66
+ - **State-driven feedback** — set `state="processing"` to show the animated brand-gradient border; `"responded"` to settle it. Wire `state` to your agent's lifecycle.
67
+ - **Placeholder rotation** — pass an array to `placeholder` for the rotating-prompt effect (paused while typing; respects reduced-motion).
68
+ - **Pairs with `AIConversation`** — CommandBar is the input; AIConversation renders the response thread.
69
+
70
+ ## Gotchas
71
+ - Client component — mount inside a client boundary.
72
+ - Requires a mounted `MotionProvider`.
73
+ - `keybinding` only applies to the `floating` variant; pass `false` to disable the global shortcut.
74
+ - Largest component in the AI layer (3 variants share one implementation) — prefer `inline`/`hero` for embedded bars, `floating` for the app-wide launcher.
75
+
76
+ ## Changes
77
+ ### v0.49.0
78
+ - **Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP).
@@ -0,0 +1,59 @@
1
+ # AIConversation
2
+
3
+ - Import: @devalok/shilp-sutra/ai/conversation
4
+ - Server-safe: No
5
+ - Category: ai
6
+
7
+ A scrollable AI conversation thread: user + assistant turns, streaming processing
8
+ steps, an agent header, and structured content blocks (rendered via BlockRenderer)
9
+ with confirm/cancel/undo action support.
10
+
11
+ ## Props
12
+ messages: ConversationMessage[] (required) — ordered user + assistant turns
13
+ isProcessing: boolean — shows a live processing indicator below the last message
14
+ processingSteps: ProcessingStep[] — granular steps shown during processing (status: pending | active | done | error)
15
+ agent: { name: string, icon?: IconInput } — agent identity shown as a header on assistant messages
16
+ onAction: (actionId: string, type: "confirm" | "cancel" | "undo") => void — fired by action blocks
17
+ customBlocks: Record<string, ComponentType<BlockComponentProps>> — extra block-type renderers merged over the built-ins
18
+ maxHeight: string | number — max height of the container (enables scrolling)
19
+ autoScroll: boolean — auto-scroll to bottom on new messages (default true)
20
+ className: string
21
+
22
+ ConversationMessage: { id: string, role: "user" | "assistant", blocks: Block[], ... } (see ai/types)
23
+ ProcessingStep: { label: string, status: "pending" | "active" | "done" | "error" }
24
+
25
+ ## Defaults
26
+ autoScroll defaults to true
27
+
28
+ ## Example
29
+ ```jsx
30
+ <AICommandProvider agent={{ name: 'Devadoot' }} onAction={handleAction}>
31
+ <AIConversation
32
+ messages={messages}
33
+ isProcessing={isThinking}
34
+ processingSteps={[
35
+ { label: 'Reading project', status: 'done' },
36
+ { label: 'Drafting reply', status: 'active' },
37
+ ]}
38
+ agent={{ name: 'Devadoot', icon: <IconSparkles /> }}
39
+ onAction={(id, type) => handleAction(id, type)}
40
+ maxHeight="60vh"
41
+ />
42
+ </AICommandProvider>
43
+ ```
44
+
45
+ ## Composability
46
+ - **Renders blocks, not raw text** — each assistant turn is a list of typed `Block`s rendered by `BlockRenderer`. See the block-renderer doc for the block system and how to register custom block types.
47
+ - **Pairs with `AICommandProvider`** — the provider supplies `customBlocks`, `onAction`, and `agent` via context so you don't thread them through every message. Props on `AIConversation` win over context.
48
+ - **Pairs with `CommandBar`** — CommandBar is the input surface (natural-language submission); AIConversation is the output thread. Common layout: CommandBar on top/bottom, AIConversation as the scroll region.
49
+ - **Streaming** — set `isProcessing` + feed `processingSteps` to show step-by-step progress (Reading → Drafting → …) while the model works.
50
+ - **Actions** — action blocks (e.g. `confirm`) call `onAction(actionId, type)`; wire it to your confirm/cancel/undo handlers.
51
+
52
+ ## Gotchas
53
+ - Client component — mount inside a client boundary.
54
+ - Requires a mounted `MotionProvider` (respects reduced-motion for the step spinner and block entrances).
55
+ - `agent` set here labels assistant messages; `AICommandProvider`'s `agent` is the fallback when not passed per-conversation.
56
+
57
+ ## Changes
58
+ ### v0.49.0
59
+ - **Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP).
@@ -0,0 +1,41 @@
1
+ # DevadootIcon
2
+
3
+ - Import: @devalok/shilp-sutra/ai
4
+ - Server-safe: No
5
+ - Category: ai
6
+
7
+ The animated Devalok chakra glyph — the visual identity for the AI command system.
8
+ Uses fill-first animation (the gradient color *is* the animation, Gemini-style),
9
+ with a distinct state for idle, processing, responded, and error.
10
+
11
+ ## Props
12
+ state: "idle" | "processing" | "responded" | "error" — animation mode (default "idle")
13
+ size: number — pixel size (default 20)
14
+ className: string
15
+
16
+ ## Defaults
17
+ state defaults to "idle"
18
+ size defaults to 20
19
+
20
+ ## Example
21
+ ```jsx
22
+ // Drive the icon from the agent lifecycle:
23
+ <DevadootIcon state={isThinking ? 'processing' : hasReplied ? 'responded' : 'idle'} size={24} />
24
+
25
+ // Error state:
26
+ <DevadootIcon state="error" />
27
+ ```
28
+
29
+ ## Composability
30
+ - **State-as-identity** — `idle` breathes pink↔rose slowly; `processing` sweeps a pink→purple→magenta gradient + glow; `responded` flashes bright then settles + a scale pop; `error` turns red with a glow pulse. Wire `state` to your agent's status.
31
+ - **Pairs with `CommandBar` / `AIConversation`** — commonly placed in the CommandBar (hero/floating) or as the agent header avatar in the conversation.
32
+ - **Exported from the `ai` barrel** — `import { DevadootIcon } from '@devalok/shilp-sutra/ai'` (no dedicated subpath).
33
+
34
+ ## Gotchas
35
+ - Client component — mount inside a client boundary.
36
+ - Requires a mounted `MotionProvider`; renders a static chakra when reduced-motion is set.
37
+ - Brand-locked colors (Devalok pink↔purple palette) — it's a brand asset, not a generic spinner. Use `Spinner` for neutral loading.
38
+
39
+ ## Changes
40
+ ### v0.49.0
41
+ - **Added** Component documentation (the AI layer is now covered by the docs gate + hosted MCP).
@@ -11,9 +11,7 @@ EmojiPicker, EmojiPickerPopover
11
11
 
12
12
  ### EmojiPicker
13
13
  onSelect: (emoji: EmojiData) => void
14
- theme: "auto" | "light" | "dark"
15
- previewPosition: "top" | "bottom" | "none"
16
- skinTonePosition: "search" | "preview" | "none"
14
+ emojibaseUrl: string (base URL for the emoji dataset; default = frimousse's jsdelivr CDN)
17
15
  className: string
18
16
 
19
17
  ### EmojiPickerPopover (extends EmojiPicker props)
@@ -26,7 +24,7 @@ EmojiPicker, EmojiPickerPopover
26
24
  shortcodes: string
27
25
 
28
26
  ## Defaults
29
- theme="auto", previewPosition="none", skinTonePosition="search", align="start"
27
+ align="start"
30
28
 
31
29
  ## Example
32
30
  ```jsx
@@ -34,27 +32,31 @@ EmojiPicker, EmojiPickerPopover
34
32
  <Button variant="ghost" size="icon-sm">😀</Button>
35
33
  </EmojiPickerPopover>
36
34
 
37
- <EmojiPicker onSelect={handleEmoji} theme="dark" />
35
+ <EmojiPicker onSelect={handleEmoji} />
38
36
  ```
39
37
 
40
38
  ## Composability
41
39
  - **Two exports:** `EmojiPicker` (inline grid, no trigger) and `EmojiPickerPopover` (trigger + popover wrapper). Use EmojiPickerPopover 95% of the time — trigger-on-click is the standard UX.
42
- - **Wraps @emoji-mart/react**, lazy-loaded with a Skeleton placeholder while the ~200KB bundle fetches. Don't pre-import unless you need it eagerly.
40
+ - **Built on frimousse**, bundled and lazy-loaded (own `emoji` chunk, incl. the dataset). Needs no consumer peer install and no React-19 peer workaround. Don't pre-import unless you need it eagerly.
41
+ - **Native emoji only.** Each platform renders its own glyphs. Theme follows the surrounding `.dark` class via DS tokens automatically — no theme prop.
42
+ - **Built-in footer:** a live preview of the hovered/active emoji (frimousse `ActiveEmoji`) plus a skin-tone selector (`SkinToneSelector`) — no props needed.
43
+ - **Dataset source / CSP:** frimousse fetches the emoji dataset from jsdelivr at runtime. To remove the CDN dependency (strict CSP, offline, air-gapped), copy `node_modules/emojibase-data` into your app's `public/emojibase` and pass `emojibaseUrl="/emojibase"`.
43
44
  - **Trigger composition:** EmojiPickerPopover's `children` is the trigger — wrap any Button/IconButton. Typical pairing is an icon-only IconButton with a 😀 label.
44
- - **TipTap integration:** Use `createEmojiSuggestion(set?)` factory to create a TipTap suggestion plugin that opens the picker on typing `:emoji`. Works with RichChatInput and RichTextEditor.
45
- - **Theme matching:** `theme="auto"` reads the `.dark` class on `<html>` — matches the DS dark mode toggle automatically. Override with explicit light/dark.
46
- - **Emoji sets:** Pass `set="apple" | "google" | ...` for consistent cross-platform emoji art (defaults to native OS glyphs).
45
+ - **TipTap integration:** Use `createEmojiSuggestion()` (from `./extensions/emoji-suggestion`) to open a `:shortcode:` suggestion list. Works with RichChatInput and RichTextEditor.
47
46
 
48
47
  ## Gotchas
49
- - Wraps `@emoji-mart/react` which is lazy-loaded shows a Skeleton placeholder while loading
50
- - `theme="auto"` reads the `.dark` class on `<html>` to pick light/dark
51
- - EmojiPickerPopover auto-closes after selection
48
+ - Client-only (fetches its emoji dataset on first open) not server-safe.
49
+ - EmojiPickerPopover auto-closes after selection.
50
+ - The `set` / `theme` / `previewPosition` / `skinTonePosition` props are deprecated no-ops kept for source compatibility; the picker is native-only.
52
51
 
53
52
  ## Changes
54
53
 
54
+ ### v-next
55
+ - **Breaking** picker migrated from `@emoji-mart/react` to `frimousse` — native emoji only. Art-style sets (apple/google/twitter/facebook) removed; `set`/`theme`/`previewPosition`/`skinTonePosition` are now no-ops.
56
+ - **Breaking** `emojiDataLoaders` export removed; `EmojiNodeAttrs` narrowed to `{ id, native }`; `createEmojiSuggestion()` takes no argument; `EmojiSuggestionItem` no longer has `x`/`y`.
57
+ - **Changed** frimousse + `@emoji-mart/data` are now bundled (lazy `emoji` chunk) — the emoji feature needs zero consumer peer installs.
58
+ - **Added** built-in footer: active-emoji preview + skin-tone selector. New `emojibaseUrl` prop to self-host the dataset (remove the runtime CDN dependency).
59
+
55
60
  ### v0.33.0
56
- - **Added** `set` prop on EmojiPicker and EmojiPickerPopover — `EmojiSet` type: 'native' | 'apple' | 'google' | 'twitter' | 'facebook'
57
- - **Added** `EmojiNode` TipTap extensioninline atom node with spritesheet rendering for consistent emoji art styles
58
- - **Added** `createEmojiSuggestion(set?)` factory — replaces `EmojiSuggestion` named export
59
- - **Added** `EmojiSet` type exported from barrel
60
- - **Breaking** `EmojiSuggestion` named export removed — use `createEmojiSuggestion()` factory
61
+ - **Added** `EmojiNode` TipTap extension and `createEmojiSuggestion()` factory.
62
+ - **Breaking** `EmojiSuggestion` named export removed use `createEmojiSuggestion()` factory.
@@ -32,7 +32,7 @@
32
32
  - **Server-safe page-top header** with title + subtitle + breadcrumbs + actions slot. Renders Breadcrumb internally from the `breadcrumbs` array.
33
33
  - **Auto-derived title:** If `title` is omitted, the last breadcrumb's `label` becomes the h1. Saves duplication when the page title matches the breadcrumb leaf.
34
34
  - **Breadcrumb contract:** Last item should NOT have an `href` (it's the current page — renders as BreadcrumbPage, not a link). Items with `href` render as BreadcrumbLink.
35
- - **actions slot:** Typically one to three buttons (Save, Cancel, More). For larger action groups, use ButtonGroup or a toolbar.
35
+ - **actions slot:** Typically one to three buttons (Save, Cancel, More). The slot wraps onto its own line under the title on narrow viewports instead of forcing horizontal overflow, so multiple/wide buttons are mobile-safe. For larger action groups, use ButtonGroup or a toolbar.
36
36
  - **Not for tabs / sub-navigation** — pair with Tabs rendered below PageHeader for that.
37
37
 
38
38
  ## Gotchas
@@ -0,0 +1,66 @@
1
+ # ResponsiveModal
2
+
3
+ - Import: @devalok/shilp-sutra/composed/responsive-modal
4
+ - Server-safe: No
5
+ - Category: composed
6
+
7
+ ## Props
8
+
9
+ ### ResponsiveModal (root)
10
+ open: boolean (controlled open state)
11
+ defaultOpen: boolean (uncontrolled initial state)
12
+ onOpenChange: (open: boolean) => void
13
+ dismissable: boolean (default: true — when false, Escape / outside-click / drag cannot close; only an explicit Close or onOpenChange does)
14
+
15
+ ### ResponsiveModalContent
16
+ snapPoints: number[] (mobile only; ascending viewport-height fractions like [0.4, 0.9] the sheet rests at. Omit for a content-height sheet. Ignored on desktop)
17
+ defaultSnapPoint: number (mobile only; index into snapPoints the sheet opens at. Defaults to the last/tallest)
18
+
19
+ ## Defaults
20
+ dismissable=true
21
+
22
+ ## Example
23
+ ```jsx
24
+ <ResponsiveModal>
25
+ <ResponsiveModalTrigger asChild><Button>Edit profile</Button></ResponsiveModalTrigger>
26
+ <ResponsiveModalContent snapPoints={[0.5, 0.9]}>
27
+ <ResponsiveModalBackground className="bg-linear-to-br from-accent-3 to-accent-6 opacity-40" />
28
+ <ResponsiveModalHeader>
29
+ <ResponsiveModalTitle>Edit profile</ResponsiveModalTitle>
30
+ <ResponsiveModalDescription>Changes save when you apply.</ResponsiveModalDescription>
31
+ </ResponsiveModalHeader>
32
+ <ResponsiveModalBody>{/* form fields — scrolls internally */}</ResponsiveModalBody>
33
+ <ResponsiveModalFooter>
34
+ <ResponsiveModalClose asChild><Button variant="soft">Cancel</Button></ResponsiveModalClose>
35
+ <Button>Apply</Button>
36
+ </ResponsiveModalFooter>
37
+ </ResponsiveModalContent>
38
+ </ResponsiveModal>
39
+ ```
40
+
41
+ ## Composability
42
+ - **Part:** ResponsiveModal (required) — root; owns open/close state and the desktop/mobile switch
43
+ - **Part:** ResponsiveModalTrigger — opens the modal; use `asChild` to wrap your own button
44
+ - **Part:** ResponsiveModalContent — the switching panel: centered Dialog at md+, bottom sheet below
45
+ - **Part:** ResponsiveModalBackground (slot: behind) — optional full-bleed layer painted at `-z-10`, clipped to the panel radius
46
+ - **Part:** ResponsiveModalHeader (slot: top) — pinned; stays put while the body scrolls
47
+ - **Part:** ResponsiveModalTitle (required) — labels the dialog for accessibility
48
+ - **Part:** ResponsiveModalDescription — optional subtitle
49
+ - **Part:** ResponsiveModalBody — internal scroll region (min-h-0 flex-1 overflow-y-auto), capped 85dvh desktop / 90dvh mobile
50
+ - **Part:** ResponsiveModalFooter (slot: bottom) — pinned action row; stacks on mobile, right-aligned inline on desktop
51
+ - **Part:** ResponsiveModalClose — manual close (Content already renders a built-in close button when dismissable)
52
+ - **Composes:** dialog (alternative-to) — use Dialog directly when you always want a centered modal
53
+ - **Composes:** sheet (alternative-to) — use Sheet directly when you always want an edge panel
54
+ - **Context:** ResponsiveModal — provides open / isMobile / dismissable / onClose to its parts via context
55
+
56
+ ## Gotchas
57
+ - Built on the same dialog primitive as Dialog and Sheet — focus trap, Escape, scroll lock, and portal are handled. Not server-safe (uses hooks); import in a client component.
58
+ - Put a `ResponsiveModalTitle` inside every modal — it sets the ARIA label. Omitting it triggers an accessibility warning.
59
+ - The built-in close button sits at `z-10` above `ResponsiveModalBackground` (`-z-10`); keep Header/Body/Footer in normal flow (no `relative z-*` wrapper) or a positioned wrapper will paint over the close button and eat the tap.
60
+ - `snapPoints` and `defaultSnapPoint` are mobile-only — they are ignored at md+ (always a centered Dialog).
61
+ - Height caps live on the panel (85dvh desktop / 90dvh mobile); do not add your own `max-h` to `ResponsiveModalBody` — it already scrolls.
62
+ - Prefer this over `DialogContent responsive` when the mobile form should be a partial bottom sheet; `responsive` collapses to a full-screen takeover that leaves dead space under short content.
63
+
64
+ ## Changes
65
+ ### v0.49.0
66
+ - Added — new component. Dialog (md+) / bottom-sheet (mobile) responsive modal with pinned header/footer, internal scroll body, optional full-bleed background slot, drag-to-dismiss, and optional mobile snap points.
@@ -58,7 +58,7 @@ MentionItem: { id: string; label: string; avatar?: string }
58
58
 
59
59
  ## Gotchas
60
60
  - Tiptap is bundled — no need to install `@tiptap/*` packages separately
61
- - Emoji picker requires `@emoji-mart/react` + `@emoji-mart/data` peers
61
+ - Emoji picker (frimousse) + its dataset are bundled too — no emoji peers to install (native-only since the frimousse migration)
62
62
  - Images without `onImageUpload` are stored as base64 in HTML — large images bloat content
63
63
  - Mention rendering in viewer always works (no mention props needed, just the HTML)
64
64
  - Features: bold, italic, underline, strikethrough, highlight, headings, blockquote, lists, task lists, code, links, images, file attachments, mentions, emoji, text alignment, horizontal rule
@@ -14,7 +14,7 @@
14
14
  endHour: number (default: 18, exclusive)
15
15
  slotDuration: number (minutes, default: 30)
16
16
 
17
- Event colors: "primary" | "success" | "warning" | "error" | "info" | "neutral"
17
+ Event colors: "accent" | "success" | "warning" | "error" | "info" | "neutral"
18
18
 
19
19
  ## Defaults
20
20
  startHour=8, endHour=18, slotDuration=30
@@ -33,7 +33,7 @@ Event colors: "primary" | "success" | "warning" | "error" | "info" | "neutral"
33
33
  - **Day / Week calendar view** for time-block display (meetings, shifts, availability). Not a full calendar app — no month view, no drag-to-create.
34
34
  - **Event data is consumer-owned:** You pass `events` as an array; ScheduleView doesn't fetch, doesn't cache, doesn't expand recurring events. All scheduling logic lives in your app.
35
35
  - **Event click + slot click** — `onEventClick` for existing events; `onSlotClick` for creating new events (fires with start/end of the empty slot).
36
- - **Color vocabulary matches the DS** — `primary/success/warning/error/info/neutral`. Map your event types to these at the data layer.
36
+ - **Color vocabulary matches the DS** — `accent/success/warning/error/info/neutral`. Map your event types to these at the data layer.
37
37
  - **endHour is exclusive:** `endHour=18` means the last visible slot starts at 17:30 (with 30min slots). Match your UX expectation: 9-5 typically means `startHour=9, endHour=18`.
38
38
  - **Pairs with date-picker/composed** — use DatePicker or DateRangePicker to choose which date to show; pass that as ScheduleView's `date`.
39
39
 
@@ -43,5 +43,9 @@ Event colors: "primary" | "success" | "warning" | "error" | "info" | "neutral"
43
43
  - Events that span outside `startHour`/`endHour` may be clipped
44
44
 
45
45
  ## Changes
46
+ ### v0.49.0
47
+ - **BREAKING** `ScheduleEvent.color` value `"primary"` renamed `"accent"` (DS colour vocabulary). It was the default, so untyped events are unaffected.
48
+ - **Added** keyboard focus rings on slot cells + event blocks; current-time indicator uses the shared `<Dot>`.
49
+
46
50
  ### v0.1.0
47
51
  - **Added** Initial release
@@ -1,7 +1,7 @@
1
1
  # Breadcrumb
2
2
 
3
3
  - Import: @devalok/shilp-sutra/ui/breadcrumb
4
- - Server-safe: No
4
+ - Server-safe: Yes
5
5
  - Category: ui
6
6
 
7
7
  ## Compound Components
@@ -8,7 +8,7 @@
8
8
  checked: boolean | "indeterminate"
9
9
  onCheckedChange: (checked: boolean | "indeterminate") => void
10
10
  size: "sm" | "md" | "lg"
11
- error: boolean (shows red border)
11
+ state: "default" | "error" | "warning" | "success" (validation border/bg tint; error sets aria-invalid. Inherited from FormField when omitted)
12
12
  indeterminate: boolean (overrides checked, shows dash icon)
13
13
  disabled: boolean
14
14
 
@@ -37,6 +37,9 @@
37
37
  - WCAG 2.5.8 minimum target size met at md (24px); sm (20px) may fail if not paired with enough label hit area
38
38
 
39
39
  ## Changes
40
+ ### v0.49.0
41
+ - **BREAKING** Removed the `error: boolean` prop; use `state` (`FieldState = "default" | "error" | "warning" | "success"`). Migrate `<Checkbox error />` → `<Checkbox state="error" />`. Gains `warning`/`success` tints and now inherits state from `FormField`.
42
+
40
43
  ### v0.22.0
41
44
  - **Changed** Check indicator animation from scale-bounce to path-draw (stroke draws progressively). Indeterminate dash also draws in.
42
45
  - **Fixed** Uncontrolled checkbox never showed checkmark — `checked` from props was `undefined`, so `isActive` was always `false`. Now tracks internal state.
@@ -7,6 +7,7 @@
7
7
  ## Props
8
8
  options: ComboboxOption[] (REQUIRED) — { value: string, label: string, description?: string, icon?: ReactNode, disabled?: boolean }
9
9
  size: "xs" | "sm" | "md" | "lg" (trigger height)
10
+ state: "default" | "error" | "warning" | "success" (validation border tint; error sets aria-invalid. Inherited from FormField when omitted)
10
11
  DISCRIMINATED UNION — type depends on `multiple` flag:
11
12
  Single (default): multiple?: false, value?: string, onValueChange: (value: string) => void
12
13
  Multiple: multiple: true, value?: string[], onValueChange: (value: string[]) => void
@@ -50,6 +51,9 @@
50
51
  - Dropdown content is portalled to document.body — parent styles like `overflow: hidden` don't clip it, and container-scoped test queries won't find it
51
52
 
52
53
  ## Changes
54
+ ### v0.49.0
55
+ - **Added** `state` prop (`FieldState = "default" | "error" | "warning" | "success"`) — unified field-state API. Renders a validation border tint + sets `aria-invalid`; inherits from `FormField` when omitted. (Additive — Combobox had no prior validation prop.)
56
+
53
57
  ### v0.18.0
54
58
  - **Added** `accessibleLabel` prop — custom aria-label for trigger, falls back to placeholder
55
59
 
@@ -0,0 +1,61 @@
1
+ # Dot
2
+
3
+ - Import: @devalok/shilp-sutra/ui/dot
4
+ - Server-safe: No
5
+ - Category: ui
6
+
7
+ A small semantic status/indicator dot — the low-level primitive behind status
8
+ pills, presence indicators, legend swatches, and `StatusDot`. Intent-coloured,
9
+ sized, optionally pulsing, filled or ring.
10
+
11
+ ## Props
12
+ color: "accent" | "success" | "warning" | "error" | "info" | "neutral" | "current" (intent colour; `current` inherits text colour)
13
+ size: "xs" | "sm" | "md" | "lg"
14
+ variant: "filled" | "ring" | "off" (`off` = faint fill + light border, i.e. inactive)
15
+ withBorder: boolean (contrast ring so the dot stays visible on busy/coloured backgrounds)
16
+ pulse: boolean (animate a pulsing ripple; ignored for `off`)
17
+ pulseSpeed: "slow" | "normal" | "fast" (pulse tempo)
18
+ label: ReactNode (inline text; makes the dot an announced status)
19
+ labelPosition: "start" | "end" (which side the label sits on)
20
+ labelClassName: string
21
+
22
+ ## Defaults
23
+ color: "neutral"
24
+ size: "md"
25
+ variant: "filled"
26
+ withBorder: false
27
+ pulse: false
28
+ pulseSpeed: "normal"
29
+ labelPosition: "end"
30
+
31
+ ## Example
32
+ ```jsx
33
+ <Dot color="success" /> {/* bare, decorative */}
34
+ <Dot color="error" pulse pulseSpeed="fast" label="Recording" /> {/* pulsing + announced */}
35
+ <Dot color="neutral" variant="off" label="Offline" /> {/* inactive: faint fill + light border */}
36
+ <Dot color="success" withBorder /> {/* contrast ring for busy backgrounds */}
37
+ <Dot color="accent" label="3 online" labelPosition="start" /> {/* label before the dot */}
38
+ <Dot color="neutral" variant="ring" size="lg" /> {/* hollow ring */}
39
+
40
+ // As leading content in a pill:
41
+ <Badge variant="soft" color="warning" startIcon={<Dot color="warning" size="sm" />}>
42
+ Pending
43
+ </Badge>
44
+ ```
45
+
46
+ ## Composability
47
+ - **Decorative vs announced.** A bare `<Dot>` is `aria-hidden` (the surrounding element carries meaning — e.g. a Badge's text). Pass a `label` (or `aria-label`) to make it a `role="status"` announced indicator.
48
+ - **Intent colour, shared vocabulary.** `color` uses the same intent names as the rest of the system (`accent/success/warning/error/info/neutral`), so a Dot next to a Badge/Button of the same intent matches.
49
+ - **`pulse` = "live".** Off by default (static status). Turn it on for active/attention states (recording, live, connecting) — a pulsing dot reads as "happening now", so leave it off for settled statuses.
50
+ - **Powers the higher-level pieces.** `StatusBadge` composes `<Badge>` + `<Dot>`; use `Dot` directly anywhere you need a coloured indicator without a pill.
51
+ - **Three treatments:** `filled` (active), `ring` (hollow outline), `off` (faint same-tone fill + light border — present but inactive/disabled).
52
+ - **`withBorder`** adds a contrast ring (`ring-2 ring-surface-raised`) so the dot reads on avatars, images, or coloured fills — the pattern Avatar's status dot uses.
53
+ - **`pulseSpeed`** (slow/normal/fast) tunes the pulse tempo — fast for urgent (recording), slow for ambient (syncing).
54
+
55
+ ## Gotchas
56
+ - A bare dot is decorative by design — if a dot is the *only* signal (no adjacent text), give it a `label` or `aria-label` so it's announced.
57
+ - `pulse` respects `prefers-reduced-motion` (the ripple is disabled).
58
+
59
+ ## Changes
60
+ ### v0.49.0
61
+ - **Added** Initial release. Extracted as the shared primitive behind `StatusDot`, `StatusBadge`, and `Badge`'s dot. Colours `accent/success/warning/error/info/neutral/current`; sizes `xs–lg`; variants `filled/ring/off`; `withBorder` contrast ring; `pulse` + `pulseSpeed`; `label` + `labelPosition`.