@kodffe/ui 0.0.0-stage → 0.10.1

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 (304) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/accordion/accordion.d.ts +44 -0
  3. package/dist/accordion/accordion.js +84 -0
  4. package/dist/accordion/accordion.js.map +1 -0
  5. package/dist/alert/alert.d.ts +17 -0
  6. package/dist/alert/alert.js +59 -0
  7. package/dist/alert/alert.js.map +1 -0
  8. package/dist/app-shell/app-footer.d.ts +29 -0
  9. package/dist/app-shell/app-footer.js +39 -0
  10. package/dist/app-shell/app-footer.js.map +1 -0
  11. package/dist/app-shell/app-shell-context.d.ts +10 -0
  12. package/dist/app-shell/app-shell-context.js +12 -0
  13. package/dist/app-shell/app-shell-context.js.map +1 -0
  14. package/dist/app-shell/app-shell.d.ts +42 -0
  15. package/dist/app-shell/app-shell.js +191 -0
  16. package/dist/app-shell/app-shell.js.map +1 -0
  17. package/dist/app-shell/floating-actions.d.ts +19 -0
  18. package/dist/app-shell/floating-actions.js +59 -0
  19. package/dist/app-shell/floating-actions.js.map +1 -0
  20. package/dist/app-shell/workspace-switcher.d.ts +25 -0
  21. package/dist/app-shell/workspace-switcher.js +82 -0
  22. package/dist/app-shell/workspace-switcher.js.map +1 -0
  23. package/dist/badge/badge.d.ts +19 -0
  24. package/dist/badge/badge.js +59 -0
  25. package/dist/badge/badge.js.map +1 -0
  26. package/dist/banner/banner.d.ts +22 -0
  27. package/dist/banner/banner.js +80 -0
  28. package/dist/banner/banner.js.map +1 -0
  29. package/dist/breadcrumbs/breadcrumbs.d.ts +18 -0
  30. package/dist/breadcrumbs/breadcrumbs.js +45 -0
  31. package/dist/breadcrumbs/breadcrumbs.js.map +1 -0
  32. package/dist/button/button.d.ts +38 -0
  33. package/dist/button/button.js +83 -0
  34. package/dist/button/button.js.map +1 -0
  35. package/dist/card/card.d.ts +159 -0
  36. package/dist/card/card.js +390 -0
  37. package/dist/card/card.js.map +1 -0
  38. package/dist/card/insight-card.d.ts +19 -0
  39. package/dist/card/insight-card.js +51 -0
  40. package/dist/card/insight-card.js.map +1 -0
  41. package/dist/card/integration-card.d.ts +19 -0
  42. package/dist/card/integration-card.js +70 -0
  43. package/dist/card/integration-card.js.map +1 -0
  44. package/dist/charts/charts.d.ts +75 -0
  45. package/dist/charts/charts.js +453 -0
  46. package/dist/charts/charts.js.map +1 -0
  47. package/dist/choice/choice.d.ts +39 -0
  48. package/dist/choice/choice.js +143 -0
  49. package/dist/choice/choice.js.map +1 -0
  50. package/dist/combobox/combobox.d.ts +46 -0
  51. package/dist/combobox/combobox.js +196 -0
  52. package/dist/combobox/combobox.js.map +1 -0
  53. package/dist/command-palette/command-palette.d.ts +35 -0
  54. package/dist/command-palette/command-palette.js +164 -0
  55. package/dist/command-palette/command-palette.js.map +1 -0
  56. package/dist/confirm-dialog/confirm-dialog.d.ts +37 -0
  57. package/dist/confirm-dialog/confirm-dialog.js +106 -0
  58. package/dist/confirm-dialog/confirm-dialog.js.map +1 -0
  59. package/dist/content/assistant.d.ts +86 -0
  60. package/dist/content/assistant.js +213 -0
  61. package/dist/content/assistant.js.map +1 -0
  62. package/dist/content/content.d.ts +45 -0
  63. package/dist/content/content.js +136 -0
  64. package/dist/content/content.js.map +1 -0
  65. package/dist/data-display/avatar-sizes.d.ts +8 -0
  66. package/dist/data-display/avatar-sizes.js +12 -0
  67. package/dist/data-display/avatar-sizes.js.map +1 -0
  68. package/dist/data-display/avatar.d.ts +21 -0
  69. package/dist/data-display/avatar.js +53 -0
  70. package/dist/data-display/avatar.js.map +1 -0
  71. package/dist/data-display/chip.d.ts +20 -0
  72. package/dist/data-display/chip.js +64 -0
  73. package/dist/data-display/chip.js.map +1 -0
  74. package/dist/data-display/code-block.d.ts +14 -0
  75. package/dist/data-display/code-block.js +50 -0
  76. package/dist/data-display/code-block.js.map +1 -0
  77. package/dist/data-display/data-display.d.ts +73 -0
  78. package/dist/data-display/data-display.js +227 -0
  79. package/dist/data-display/data-display.js.map +1 -0
  80. package/dist/data-display/insights.d.ts +120 -0
  81. package/dist/data-display/insights.js +220 -0
  82. package/dist/data-display/insights.js.map +1 -0
  83. package/dist/data-table/cells.d.ts +86 -0
  84. package/dist/data-table/cells.js +163 -0
  85. package/dist/data-table/cells.js.map +1 -0
  86. package/dist/data-table/data-table.d.ts +112 -0
  87. package/dist/data-table/data-table.js +558 -0
  88. package/dist/data-table/data-table.js.map +1 -0
  89. package/dist/date-picker/date-picker.d.ts +61 -0
  90. package/dist/date-picker/date-picker.js +309 -0
  91. package/dist/date-picker/date-picker.js.map +1 -0
  92. package/dist/drawer/drawer.d.ts +32 -0
  93. package/dist/drawer/drawer.js +72 -0
  94. package/dist/drawer/drawer.js.map +1 -0
  95. package/dist/empty-state/empty-state.d.ts +25 -0
  96. package/dist/empty-state/empty-state.js +78 -0
  97. package/dist/empty-state/empty-state.js.map +1 -0
  98. package/dist/error-state/error-state.d.ts +19 -0
  99. package/dist/error-state/error-state.js +56 -0
  100. package/dist/error-state/error-state.js.map +1 -0
  101. package/dist/event-calendar/calendar-logic.test.d.ts +1 -0
  102. package/dist/event-calendar/dates.d.ts +35 -0
  103. package/dist/event-calendar/dates.js +55 -0
  104. package/dist/event-calendar/dates.js.map +1 -0
  105. package/dist/event-calendar/event-calendar.d.ts +125 -0
  106. package/dist/event-calendar/event-calendar.js +795 -0
  107. package/dist/event-calendar/event-calendar.js.map +1 -0
  108. package/dist/event-calendar/event-details.d.ts +50 -0
  109. package/dist/event-calendar/event-details.js +124 -0
  110. package/dist/event-calendar/event-details.js.map +1 -0
  111. package/dist/event-calendar/layout.d.ts +48 -0
  112. package/dist/event-calendar/layout.js +55 -0
  113. package/dist/event-calendar/layout.js.map +1 -0
  114. package/dist/file-upload/file-upload.d.ts +70 -0
  115. package/dist/file-upload/file-upload.js +307 -0
  116. package/dist/file-upload/file-upload.js.map +1 -0
  117. package/dist/filters/filters.d.ts +48 -0
  118. package/dist/filters/filters.js +103 -0
  119. package/dist/filters/filters.js.map +1 -0
  120. package/dist/form-field/form-field.d.ts +39 -0
  121. package/dist/form-field/form-field.js +88 -0
  122. package/dist/form-field/form-field.js.map +1 -0
  123. package/dist/hover-card/hover-card.d.ts +15 -0
  124. package/dist/hover-card/hover-card.js +27 -0
  125. package/dist/hover-card/hover-card.js.map +1 -0
  126. package/dist/hover-card/person-hover-card.d.ts +26 -0
  127. package/dist/hover-card/person-hover-card.js +85 -0
  128. package/dist/hover-card/person-hover-card.js.map +1 -0
  129. package/dist/icon/icon-tile.d.ts +20 -0
  130. package/dist/icon/icon-tile.js +55 -0
  131. package/dist/icon/icon-tile.js.map +1 -0
  132. package/dist/icon/icon.d.ts +14 -0
  133. package/dist/icon/icon.js +28 -0
  134. package/dist/icon/icon.js.map +1 -0
  135. package/dist/icon/icons.generated.d.ts +358 -0
  136. package/dist/icon/icons.generated.js +362 -0
  137. package/dist/icon/icons.generated.js.map +1 -0
  138. package/dist/index.d.ts +90 -0
  139. package/dist/index.js +88 -0
  140. package/dist/input/extra-inputs.d.ts +122 -0
  141. package/dist/input/extra-inputs.js +351 -0
  142. package/dist/input/extra-inputs.js.map +1 -0
  143. package/dist/input/field-styles.d.ts +5 -0
  144. package/dist/input/field-styles.js +14 -0
  145. package/dist/input/field-styles.js.map +1 -0
  146. package/dist/input/input.d.ts +50 -0
  147. package/dist/input/input.js +107 -0
  148. package/dist/input/input.js.map +1 -0
  149. package/dist/layout/layout.d.ts +41 -0
  150. package/dist/layout/layout.js +90 -0
  151. package/dist/layout/layout.js.map +1 -0
  152. package/dist/lib/control-styles.d.ts +9 -0
  153. package/dist/lib/control-styles.js +16 -0
  154. package/dist/lib/control-styles.js.map +1 -0
  155. package/dist/lib/cx.d.ts +2 -0
  156. package/dist/lib/cx.js +8 -0
  157. package/dist/lib/cx.js.map +1 -0
  158. package/dist/lib/glyphs.d.ts +13 -0
  159. package/dist/lib/glyphs.js +67 -0
  160. package/dist/lib/glyphs.js.map +1 -0
  161. package/dist/lib/segmented-styles.d.ts +8 -0
  162. package/dist/lib/segmented-styles.js +12 -0
  163. package/dist/lib/segmented-styles.js.map +1 -0
  164. package/dist/lib/select-on-arrow.d.ts +7 -0
  165. package/dist/lib/select-on-arrow.js +21 -0
  166. package/dist/lib/select-on-arrow.js.map +1 -0
  167. package/dist/lib/skip-link.d.ts +5 -0
  168. package/dist/lib/skip-link.js +13 -0
  169. package/dist/lib/skip-link.js.map +1 -0
  170. package/dist/lib/use-media-query.d.ts +4 -0
  171. package/dist/lib/use-media-query.js +15 -0
  172. package/dist/lib/use-media-query.js.map +1 -0
  173. package/dist/lists/lists.d.ts +76 -0
  174. package/dist/lists/lists.js +133 -0
  175. package/dist/lists/lists.js.map +1 -0
  176. package/dist/locale-switch/locale-switch.d.ts +29 -0
  177. package/dist/locale-switch/locale-switch.js +62 -0
  178. package/dist/locale-switch/locale-switch.js.map +1 -0
  179. package/dist/logo/logo.d.ts +31 -0
  180. package/dist/logo/logo.js +157 -0
  181. package/dist/logo/logo.js.map +1 -0
  182. package/dist/logo/product-logo.d.ts +19 -0
  183. package/dist/logo/product-logo.js +46 -0
  184. package/dist/logo/product-logo.js.map +1 -0
  185. package/dist/marketing/marketing.d.ts +176 -0
  186. package/dist/marketing/marketing.js +451 -0
  187. package/dist/marketing/marketing.js.map +1 -0
  188. package/dist/marketing/newsletter-form.d.ts +21 -0
  189. package/dist/marketing/newsletter-form.js +100 -0
  190. package/dist/marketing/newsletter-form.js.map +1 -0
  191. package/dist/mascot/mascot.d.ts +28 -0
  192. package/dist/mascot/mascot.js +28 -0
  193. package/dist/mascot/mascot.js.map +1 -0
  194. package/dist/mascot/mascots.generated.d.ts +284 -0
  195. package/dist/mascot/mascots.generated.js +287 -0
  196. package/dist/mascot/mascots.generated.js.map +1 -0
  197. package/dist/master-detail/master-detail.d.ts +30 -0
  198. package/dist/master-detail/master-detail.js +71 -0
  199. package/dist/master-detail/master-detail.js.map +1 -0
  200. package/dist/menu/account-menu.d.ts +44 -0
  201. package/dist/menu/account-menu.js +78 -0
  202. package/dist/menu/account-menu.js.map +1 -0
  203. package/dist/menu/context-menu.d.ts +31 -0
  204. package/dist/menu/context-menu.js +111 -0
  205. package/dist/menu/context-menu.js.map +1 -0
  206. package/dist/menu/dropdown-menu.d.ts +49 -0
  207. package/dist/menu/dropdown-menu.js +152 -0
  208. package/dist/menu/dropdown-menu.js.map +1 -0
  209. package/dist/menu/menu-styles.d.ts +8 -0
  210. package/dist/menu/menu-styles.js +6 -0
  211. package/dist/menu/menu-styles.js.map +1 -0
  212. package/dist/menu/menubar.d.ts +31 -0
  213. package/dist/menu/menubar.js +125 -0
  214. package/dist/menu/menubar.js.map +1 -0
  215. package/dist/modal/modal.d.ts +34 -0
  216. package/dist/modal/modal.js +58 -0
  217. package/dist/modal/modal.js.map +1 -0
  218. package/dist/notification-center/notification-center.d.ts +51 -0
  219. package/dist/notification-center/notification-center.js +244 -0
  220. package/dist/notification-center/notification-center.js.map +1 -0
  221. package/dist/otp-input/otp-input.d.ts +23 -0
  222. package/dist/otp-input/otp-input.js +61 -0
  223. package/dist/otp-input/otp-input.js.map +1 -0
  224. package/dist/overlay/overlay.d.ts +53 -0
  225. package/dist/overlay/overlay.js +103 -0
  226. package/dist/overlay/overlay.js.map +1 -0
  227. package/dist/page-header/page-header.d.ts +55 -0
  228. package/dist/page-header/page-header.js +114 -0
  229. package/dist/page-header/page-header.js.map +1 -0
  230. package/dist/page-header/record-headers.d.ts +51 -0
  231. package/dist/page-header/record-headers.js +134 -0
  232. package/dist/page-header/record-headers.js.map +1 -0
  233. package/dist/page-header/section-header.d.ts +21 -0
  234. package/dist/page-header/section-header.js +44 -0
  235. package/dist/page-header/section-header.js.map +1 -0
  236. package/dist/page-navigation/page-navigation.d.ts +59 -0
  237. package/dist/page-navigation/page-navigation.js +136 -0
  238. package/dist/page-navigation/page-navigation.js.map +1 -0
  239. package/dist/pagination/pagination.d.ts +28 -0
  240. package/dist/pagination/pagination.js +102 -0
  241. package/dist/pagination/pagination.js.map +1 -0
  242. package/dist/phone-input/phone-input.d.ts +34 -0
  243. package/dist/phone-input/phone-input.js +171 -0
  244. package/dist/phone-input/phone-input.js.map +1 -0
  245. package/dist/popover/popover.d.ts +23 -0
  246. package/dist/popover/popover.js +40 -0
  247. package/dist/popover/popover.js.map +1 -0
  248. package/dist/progress/progress.d.ts +21 -0
  249. package/dist/progress/progress.js +49 -0
  250. package/dist/progress/progress.js.map +1 -0
  251. package/dist/segmented-control/segmented-control.d.ts +32 -0
  252. package/dist/segmented-control/segmented-control.js +29 -0
  253. package/dist/segmented-control/segmented-control.js.map +1 -0
  254. package/dist/select/select.d.ts +48 -0
  255. package/dist/select/select.js +136 -0
  256. package/dist/select/select.js.map +1 -0
  257. package/dist/settings/permission-matrix.d.ts +29 -0
  258. package/dist/settings/permission-matrix.js +101 -0
  259. package/dist/settings/permission-matrix.js.map +1 -0
  260. package/dist/settings/settings-row.d.ts +32 -0
  261. package/dist/settings/settings-row.js +63 -0
  262. package/dist/settings/settings-row.js.map +1 -0
  263. package/dist/side-nav/side-nav.d.ts +36 -0
  264. package/dist/side-nav/side-nav.js +123 -0
  265. package/dist/side-nav/side-nav.js.map +1 -0
  266. package/dist/site-header/site-header.d.ts +32 -0
  267. package/dist/site-header/site-header.js +99 -0
  268. package/dist/site-header/site-header.js.map +1 -0
  269. package/dist/skeleton/skeleton.d.ts +16 -0
  270. package/dist/skeleton/skeleton.js +19 -0
  271. package/dist/skeleton/skeleton.js.map +1 -0
  272. package/dist/slider/slider.d.ts +15 -0
  273. package/dist/slider/slider.js +48 -0
  274. package/dist/slider/slider.js.map +1 -0
  275. package/dist/spinner/spinner.d.ts +15 -0
  276. package/dist/spinner/spinner.js +42 -0
  277. package/dist/spinner/spinner.js.map +1 -0
  278. package/dist/stepper/step-dots.d.ts +16 -0
  279. package/dist/stepper/step-dots.js +26 -0
  280. package/dist/stepper/step-dots.js.map +1 -0
  281. package/dist/stepper/stepper.d.ts +26 -0
  282. package/dist/stepper/stepper.js +113 -0
  283. package/dist/stepper/stepper.js.map +1 -0
  284. package/dist/tabs/tabs.d.ts +31 -0
  285. package/dist/tabs/tabs.js +66 -0
  286. package/dist/tabs/tabs.js.map +1 -0
  287. package/dist/templates/app-templates.d.ts +126 -0
  288. package/dist/templates/app-templates.js +153 -0
  289. package/dist/templates/app-templates.js.map +1 -0
  290. package/dist/templates/site-templates.d.ts +49 -0
  291. package/dist/templates/site-templates.js +110 -0
  292. package/dist/templates/site-templates.js.map +1 -0
  293. package/dist/toast/toast-store.d.ts +54 -0
  294. package/dist/toast/toast-store.js +49 -0
  295. package/dist/toast/toast-store.js.map +1 -0
  296. package/dist/toast/toaster.d.ts +15 -0
  297. package/dist/toast/toaster.js +124 -0
  298. package/dist/toast/toaster.js.map +1 -0
  299. package/dist/tooltip/tooltip.d.ts +29 -0
  300. package/dist/tooltip/tooltip.js +54 -0
  301. package/dist/tooltip/tooltip.js.map +1 -0
  302. package/package.json +88 -3
  303. package/styles.css +521 -0
  304. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistant.js","names":["RadixPopover","PromptSuggestions","label","cx","className","suggestions","onPick","s","ChatComposer","inner","setInner","useState","text","value","setText","onValueChange","t","send","onSend","labels","IconButton","busy","ChatPanel","logRef","useRef","titleId","useId","draft","setDraft","useEffect","messages","mark","Icon","title","onMinimize","Glyph","m","d","p","pinned","QuickPanel","trigger","floatingSurface","workspace","Avatar","user","stats","actions","a","links","l"],"sources":["../../src/content/assistant.tsx"],"sourcesContent":["'use client';\n\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport { useEffect, useId, useRef, useState, type FormEvent, type ReactElement, type ReactNode } from 'react';\nimport { cx } from '../lib/cx';\nimport { Glyph } from '../lib/glyphs';\nimport { Icon, type IconName } from '../icon/icon';\nimport { Avatar } from '../data-display/avatar';\nimport { IconButton } from '../button/button';\nimport { floatingSurface } from '../popover/popover';\n\n/* ---------------- PromptSuggestions ---------------- */\n\n/** Soft pills with ready-made prompts; picking one sends it (or fills the composer). */\nexport function PromptSuggestions({\n suggestions,\n onPick,\n label = 'Suggestions',\n className,\n}: {\n suggestions: string[];\n onPick: (prompt: string) => void;\n label?: string;\n className?: string;\n}) {\n return (\n <ul aria-label={label} className={cx('m-0 flex list-none flex-wrap gap-2 p-0 font-sans', className)}>\n {suggestions.map((s) => (\n <li key={s}>\n <button\n type=\"button\"\n onClick={() => onPick(s)}\n className=\"cursor-pointer rounded-full border border-accent/40 bg-accent/10 px-3 py-1.5 text-left text-sm font-medium text-fg hover:bg-accent/20 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-focus\"\n >\n {s}\n </button>\n </li>\n ))}\n </ul>\n );\n}\n\n/* ---------------- ChatComposer ---------------- */\n\nexport interface ChatComposerProps {\n onSend: (text: string) => void;\n placeholder?: string;\n /** While the assistant answers: sending is disabled. */\n busy?: boolean;\n /** Controlled text (to fill it from a suggestion). */\n value?: string;\n onValueChange?: (value: string) => void;\n labels?: { message?: string; send?: string };\n className?: string;\n}\n\n/** The message field and send button. Enter sends, Shift+Enter adds a line. */\nexport function ChatComposer({\n onSend,\n placeholder = 'Ask anything…',\n busy,\n value,\n onValueChange,\n labels = {},\n className,\n}: ChatComposerProps) {\n const [inner, setInner] = useState('');\n const text = value ?? inner;\n const setText = (t: string) => (onValueChange ? onValueChange(t) : setInner(t));\n const send = (e?: FormEvent) => {\n e?.preventDefault();\n const t = text.trim();\n if (!t || busy) return;\n onSend(t);\n setText('');\n };\n return (\n <form\n onSubmit={send}\n className={cx(\n 'flex items-end gap-2 rounded-lg border border-border bg-bg p-1.5 pl-3 focus-within:border-primary',\n className,\n )}\n >\n <textarea\n aria-label={labels.message ?? 'Message'}\n rows={1}\n value={text}\n placeholder={placeholder}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n // Not while an IME composes (Japanese, Chinese…): Enter confirms the candidate there.\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n send();\n }\n }}\n className=\"max-h-32 min-h-9 flex-1 resize-none border-0 bg-transparent py-2 font-sans text-base text-fg outline-none [field-sizing:content] placeholder:text-fg-muted/80 sm:text-[15px]\"\n />\n <IconButton\n type=\"submit\"\n icon=\"arrow-right\"\n label={labels.send ?? 'Send'}\n variant=\"primary\"\n disabled={busy || !text.trim()}\n />\n </form>\n );\n}\n\n/* ---------------- ChatPanel ---------------- */\n\nexport interface ChatMessage {\n id: string;\n role: 'user' | 'assistant';\n content: ReactNode;\n}\n\nexport interface ChatPanelProps {\n /** Assistant name in the header (\"Kudi\"). */\n title: string;\n messages: ChatMessage[];\n onSend: (text: string) => void;\n /** Shows the typing indicator and disables sending. */\n busy?: boolean;\n suggestions?: string[];\n /** One highlighted suggestion above the composer (\"Summarize this week\"). */\n pinned?: string;\n onMinimize?: () => void;\n /** The assistant's avatar or mark in the header. */\n mark?: ReactNode;\n labels?: { ai?: string; minimize?: string; typing?: string; log?: string };\n className?: string;\n}\n\n/**\n * The assistant window: brand header with an \"AI\" badge and minimize, the message log, suggestion pills, a pinned\n * suggestion and the composer. Wire `onSend` to your AI endpoint; new messages are announced politely.\n */\nexport function ChatPanel({\n title,\n messages,\n onSend,\n busy,\n suggestions = [],\n pinned,\n onMinimize,\n mark,\n labels = {},\n className,\n}: ChatPanelProps) {\n const logRef = useRef<HTMLDivElement>(null);\n const titleId = useId();\n const [draft, setDraft] = useState('');\n useEffect(() => {\n logRef.current?.scrollTo({ top: logRef.current.scrollHeight });\n }, [messages.length, busy]);\n return (\n <section\n aria-labelledby={titleId}\n className={cx(\n 'flex h-[min(36rem,calc(100dvh-6rem))] w-full max-w-sm flex-col overflow-hidden rounded-xl border border-border bg-surface font-sans shadow-overlay',\n className,\n )}\n >\n <div data-theme=\"dark\" className=\"flex items-center gap-3 bg-primary-strong px-4 py-3 text-fg\">\n {mark ?? (\n <span aria-hidden=\"true\" className=\"grid size-8 place-items-center rounded-full bg-white/12\">\n <Icon name=\"ai\" size={18} />\n </span>\n )}\n <h2 id={titleId} className=\"m-0 flex-1 text-[15px] font-semibold\">\n {title}\n <span className=\"ml-2 rounded-full bg-accent px-1.5 py-0.5 align-middle text-[10px] font-bold text-on-accent\">\n {labels.ai ?? 'AI'}\n </span>\n </h2>\n {onMinimize && (\n <button\n type=\"button\"\n aria-label={labels.minimize ?? 'Minimize'}\n onClick={onMinimize}\n className=\"grid size-8 cursor-pointer place-items-center rounded-full border-0 bg-transparent text-white hover:bg-white/15 focus-visible:outline-3 focus-visible:outline-white\"\n >\n <Glyph name=\"minus\" size={18} />\n </button>\n )}\n </div>\n <div\n ref={logRef}\n role=\"log\"\n aria-label={labels.log ?? 'Conversation'}\n aria-live=\"polite\"\n className=\"grid flex-1 content-start gap-3 overflow-y-auto p-4\"\n >\n {messages.map((m) => (\n <div\n key={m.id}\n className={cx(\n 'max-w-[85%] rounded-2xl px-3.5 py-2.5 text-sm',\n m.role === 'user'\n ? 'justify-self-end rounded-br-sm bg-primary text-on-primary'\n : 'justify-self-start rounded-bl-sm bg-surface-muted text-fg',\n )}\n >\n {m.content}\n </div>\n ))}\n {busy && (\n <div\n className=\"flex w-fit items-center gap-1 rounded-2xl rounded-bl-sm bg-surface-muted px-3.5 py-3\"\n role=\"status\"\n aria-label={labels.typing ?? `${title} is typing`}\n >\n {[0, 1, 2].map((d) => (\n <span\n key={d}\n aria-hidden=\"true\"\n className=\"size-1.5 animate-pulse rounded-full bg-fg-muted motion-reduce:animate-none\"\n style={{ animationDelay: `${d * 150}ms` }}\n />\n ))}\n </div>\n )}\n </div>\n <div className=\"grid gap-3 border-t border-border p-3\">\n {suggestions.length > 0 && messages.length === 0 && (\n <PromptSuggestions suggestions={suggestions} onPick={(p) => !busy && onSend(p)} />\n )}\n {pinned && (\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onSend(pinned)}\n className=\"flex cursor-pointer items-center gap-2 rounded-md border-0 bg-info-surface px-3 py-2 text-left text-sm font-medium text-info-fg hover:bg-info-surface/70 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-focus\"\n >\n <Icon name=\"zap\" size={16} className=\"shrink-0\" />\n {pinned}\n </button>\n )}\n <ChatComposer onSend={onSend} busy={busy} value={draft} onValueChange={setDraft} />\n </div>\n </section>\n );\n}\n\n/* ---------------- QuickPanel ---------------- */\n\nexport interface QuickPanelProps {\n /** The element that opens it, usually a `FloatingActions` secondary button or any button. */\n trigger: ReactElement;\n /** Product mark in the header. */\n mark?: ReactNode;\n workspace: string;\n user: { name: string; avatarSrc?: string };\n stats?: { label: string; value: ReactNode }[];\n actions?: { label: string; icon: IconName; onClick: () => void }[];\n links?: { label: string; href: string }[];\n label?: string;\n}\n\n/**\n * Quick actions in a popover from the floating button: brand header (mark, workspace, avatar), a stats strip,\n * primary actions and footer links.\n */\nexport function QuickPanel({\n trigger,\n mark,\n workspace,\n user,\n stats = [],\n actions = [],\n links = [],\n label = 'Quick actions',\n}: QuickPanelProps) {\n return (\n <RadixPopover.Root>\n <RadixPopover.Trigger asChild>{trigger}</RadixPopover.Trigger>\n <RadixPopover.Portal>\n <RadixPopover.Content\n aria-label={label}\n side=\"top\"\n align=\"end\"\n sideOffset={10}\n collisionPadding={16}\n className={cx('kf-popover w-80 overflow-hidden text-sm', floatingSurface)}\n >\n <div data-theme=\"dark\" className=\"flex items-center gap-3 bg-primary-strong px-4 py-3 text-fg\">\n {mark}\n <span className=\"min-w-0 flex-1 truncate font-semibold\">{workspace}</span>\n <Avatar name={user.name} src={user.avatarSrc} size=\"sm\" />\n </div>\n {stats.length > 0 && (\n <dl className=\"m-0 grid grid-flow-col divide-x divide-border border-b border-border\">\n {stats.map((s) => (\n <div key={s.label} className=\"grid gap-0.5 px-3 py-2.5 text-center\">\n <dt className=\"text-[11px] text-fg-muted\">{s.label}</dt>\n <dd className=\"m-0 font-display text-lg font-bold text-fg tabular-nums\">{s.value}</dd>\n </div>\n ))}\n </dl>\n )}\n {actions.length > 0 && (\n <div className=\"grid grid-cols-2 gap-2 p-3\">\n {actions.map((a) => (\n <button\n key={a.label}\n type=\"button\"\n onClick={a.onClick}\n className=\"grid cursor-pointer justify-items-center gap-1.5 rounded-md border border-border bg-surface px-2 py-3 text-xs font-semibold text-fg hover:border-primary hover:bg-surface-muted focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-focus\"\n >\n <Icon name={a.icon} size={22} className=\"text-primary\" />\n {a.label}\n </button>\n ))}\n </div>\n )}\n {links.length > 0 && (\n <div className=\"flex flex-wrap gap-x-4 gap-y-1 border-t border-border px-4 py-2.5 text-xs\">\n {links.map((l) => (\n <a key={l.href} href={l.href} className=\"text-fg-muted no-underline hover:text-fg hover:underline\">\n {l.label}\n </a>\n ))}\n </div>\n )}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type ElementType, type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type IconName } from '../icon/icon';
3
+ /**
4
+ * Long-form typography for docs, terms and privacy: headings, lists with colored markers, links, quotes and a
5
+ * readable measure (~68 characters). Wrap plain HTML or Markdown output in it.
6
+ */
7
+ export declare function Prose({ as: Tag, className, ...rest }: HTMLAttributes<HTMLElement> & {
8
+ as?: ElementType;
9
+ }): import("react").JSX.Element;
10
+ /** One small line with an icon for disclaimers and formulas, under a section or the page. */
11
+ export declare function Note({ icon, children, className, }: {
12
+ icon?: IconName;
13
+ children: ReactNode;
14
+ className?: string;
15
+ }): import("react").JSX.Element;
16
+ /** A phone, tablet or laptop frame around a screenshot or a live preview (product heroes, docs). */
17
+ export declare function DeviceFrame({ device, children, className, }: {
18
+ device?: 'phone' | 'tablet' | 'laptop';
19
+ children: ReactNode;
20
+ className?: string;
21
+ }): import("react").JSX.Element;
22
+ export interface CarouselStep {
23
+ title: string;
24
+ text: ReactNode;
25
+ /** An illustration or screenshot. */
26
+ media?: ReactNode;
27
+ }
28
+ export interface StepCarouselProps {
29
+ steps: CarouselStep[];
30
+ /** Seconds per step while playing. */
31
+ interval?: number;
32
+ labels?: {
33
+ step?: (n: number, total: number) => string;
34
+ prev?: string;
35
+ next?: string;
36
+ play?: string;
37
+ pause?: string;
38
+ };
39
+ className?: string;
40
+ }
41
+ /**
42
+ * A guided walkthrough: illustration, "Step 1 of 6", title, text, step dots and Previous / Play / Next. Play advances
43
+ * on a timer and never starts on its own; with reduced motion the change is instant.
44
+ */
45
+ export declare function StepCarousel({ steps, interval, labels, className }: StepCarouselProps): import("react").JSX.Element;
@@ -0,0 +1,136 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Icon as t } from "../icon/icon.js";
4
+ import { Button as n } from "../button/button.js";
5
+ import { StepDots as r } from "../stepper/step-dots.js";
6
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
7
+ import { useEffect as o, useState as s } from "react";
8
+ //#region src/content/content.tsx
9
+ function c({ as: t = "div", className: n, ...r }) {
10
+ return /* @__PURE__ */ i(t, {
11
+ className: e("max-w-[68ch] font-sans text-base leading-relaxed text-fg", "[&>*+*]:mt-4 [&_h2]:mt-10 [&_h2]:font-display [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2]:text-balance", "[&_h3]:mt-8 [&_h3]:font-display [&_h3]:text-lg [&_h3]:font-bold [&_h2+*]:mt-3 [&_h3+*]:mt-2", "[&_ul]:list-disc [&_ol]:list-decimal [&_ul,&_ol]:pl-6 [&_li]:mt-1.5 [&_li]:marker:font-semibold [&_li]:marker:text-primary", "[&_a]:font-medium [&_a]:text-link [&_a]:underline [&_a]:underline-offset-2 [&_a:hover]:no-underline", "[&_strong]:font-semibold [&_code]:rounded-xs [&_code]:bg-surface-muted [&_code]:px-1 [&_code]:font-mono [&_code]:text-[0.9em]", "[&_blockquote]:border-l-4 [&_blockquote]:border-accent [&_blockquote]:pl-4 [&_blockquote]:text-fg-muted [&_blockquote]:italic", "[&_hr]:my-8 [&_hr]:border-border", n),
12
+ ...r
13
+ });
14
+ }
15
+ function l({ icon: n = "info", children: r, className: o }) {
16
+ return /* @__PURE__ */ a("p", {
17
+ className: e("m-0 flex items-start gap-1.5 font-sans text-xs text-fg-muted", o),
18
+ children: [/* @__PURE__ */ i(t, {
19
+ name: n,
20
+ size: 14,
21
+ className: "mt-px shrink-0"
22
+ }), /* @__PURE__ */ i("span", { children: r })]
23
+ });
24
+ }
25
+ var u = {
26
+ phone: {
27
+ outer: "w-64 rounded-[2.25rem] p-2.5",
28
+ screen: "aspect-[9/19.5] rounded-[1.75rem]"
29
+ },
30
+ tablet: {
31
+ outer: "w-full max-w-xl rounded-[1.75rem] p-3",
32
+ screen: "aspect-[4/3] rounded-[1.1rem]"
33
+ },
34
+ laptop: {
35
+ outer: "w-[92%] max-w-3xl rounded-t-xl p-2.5 pb-3",
36
+ screen: "aspect-[16/10] rounded-md"
37
+ }
38
+ };
39
+ function d({ device: t = "tablet", children: n, className: r }) {
40
+ let o = u[t];
41
+ return /* @__PURE__ */ a("div", {
42
+ className: e("mx-auto grid justify-items-center", t !== "phone" && "w-full", r),
43
+ children: [/* @__PURE__ */ i("div", {
44
+ className: e("bg-surface-inverse shadow-overlay", o.outer),
45
+ children: /* @__PURE__ */ i("div", {
46
+ className: e("relative w-full overflow-hidden bg-bg [&>img]:size-full [&>img]:object-cover", o.screen),
47
+ children: n
48
+ })
49
+ }), t === "laptop" && /* @__PURE__ */ i("div", {
50
+ "aria-hidden": "true",
51
+ className: "h-3 w-full max-w-[calc(48rem/0.92)] rounded-b-xl bg-surface-inverse/85"
52
+ })]
53
+ });
54
+ }
55
+ function f({ steps: t, interval: c = 5, labels: l = {}, className: u }) {
56
+ let [d, f] = s(0), [p, m] = s(!1), h = t.length - 1;
57
+ o(() => {
58
+ if (!p) return;
59
+ let e = setTimeout(() => d >= h ? m(!1) : f(d + 1), c * 1e3);
60
+ return () => clearTimeout(e);
61
+ }, [
62
+ p,
63
+ d,
64
+ h,
65
+ c
66
+ ]);
67
+ let g = t[d], _ = l.step?.(d + 1, t.length) ?? `Step ${d + 1} of ${t.length}`;
68
+ return /* @__PURE__ */ a("section", {
69
+ "aria-roledescription": "carousel",
70
+ "aria-label": t[0]?.title,
71
+ className: e("grid gap-4 rounded-lg border border-border bg-surface p-card font-sans", u),
72
+ children: [
73
+ g.media && /* @__PURE__ */ i("div", {
74
+ className: "overflow-hidden rounded-md bg-surface-muted [&>img]:w-full",
75
+ children: g.media
76
+ }),
77
+ /* @__PURE__ */ a("div", {
78
+ "aria-live": p ? "off" : "polite",
79
+ className: "grid gap-1.5",
80
+ children: [
81
+ /* @__PURE__ */ i("p", {
82
+ className: "m-0 text-xs font-semibold tracking-wide text-fg-muted uppercase",
83
+ children: _
84
+ }),
85
+ /* @__PURE__ */ i("h3", {
86
+ className: "m-0 font-display text-lg font-bold text-fg",
87
+ children: g.title
88
+ }),
89
+ /* @__PURE__ */ i("div", {
90
+ className: "text-sm text-fg-muted",
91
+ children: g.text
92
+ })
93
+ ]
94
+ }),
95
+ /* @__PURE__ */ a("div", {
96
+ className: "flex flex-wrap items-center justify-between gap-3",
97
+ children: [/* @__PURE__ */ i(r, { steps: t.map((e, t) => ({
98
+ label: e.title,
99
+ state: t < d ? "done" : t === d ? "current" : "upcoming"
100
+ })) }), /* @__PURE__ */ a("div", {
101
+ className: "flex items-center gap-2",
102
+ children: [
103
+ /* @__PURE__ */ i(n, {
104
+ size: "sm",
105
+ variant: "ghost",
106
+ iconStart: "arrow-right",
107
+ className: "[&_svg]:rotate-180",
108
+ disabled: d === 0,
109
+ onClick: () => f(d - 1),
110
+ children: l.prev ?? "Previous"
111
+ }),
112
+ /* @__PURE__ */ i(n, {
113
+ size: "sm",
114
+ variant: "secondary",
115
+ iconStart: "play",
116
+ "aria-pressed": p,
117
+ onClick: () => m((e) => !e),
118
+ children: p ? l.pause ?? "Pause" : l.play ?? "Play"
119
+ }),
120
+ /* @__PURE__ */ i(n, {
121
+ size: "sm",
122
+ iconEnd: "arrow-right",
123
+ disabled: d === h,
124
+ onClick: () => f(d + 1),
125
+ children: l.next ?? "Next"
126
+ })
127
+ ]
128
+ })]
129
+ })
130
+ ]
131
+ });
132
+ }
133
+ //#endregion
134
+ export { d as DeviceFrame, l as Note, c as Prose, f as StepCarousel };
135
+
136
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","names":["Prose","Tag","rest","cx","className","Note","Icon","icon","FRAMES","DeviceFrame","f","device","StepCarousel","i","setI","useState","playing","setPlaying","last","steps","t","interval","step","stepLabel","labels","StepDots","s","n","Button","p"],"sources":["../../src/content/content.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, type ElementType, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../lib/cx';\nimport { Icon, type IconName } from '../icon/icon';\nimport { Button } from '../button/button';\nimport { StepDots } from '../stepper/step-dots';\n\n/* ---------------- Prose ---------------- */\n\n/**\n * Long-form typography for docs, terms and privacy: headings, lists with colored markers, links, quotes and a\n * readable measure (~68 characters). Wrap plain HTML or Markdown output in it.\n */\nexport function Prose({ as: Tag = 'div', className, ...rest }: HTMLAttributes<HTMLElement> & { as?: ElementType }) {\n return (\n <Tag\n className={cx(\n 'max-w-[68ch] font-sans text-base leading-relaxed text-fg',\n '[&>*+*]:mt-4 [&_h2]:mt-10 [&_h2]:font-display [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2]:text-balance',\n '[&_h3]:mt-8 [&_h3]:font-display [&_h3]:text-lg [&_h3]:font-bold [&_h2+*]:mt-3 [&_h3+*]:mt-2',\n '[&_ul]:list-disc [&_ol]:list-decimal [&_ul,&_ol]:pl-6 [&_li]:mt-1.5 [&_li]:marker:font-semibold [&_li]:marker:text-primary',\n '[&_a]:font-medium [&_a]:text-link [&_a]:underline [&_a]:underline-offset-2 [&_a:hover]:no-underline',\n '[&_strong]:font-semibold [&_code]:rounded-xs [&_code]:bg-surface-muted [&_code]:px-1 [&_code]:font-mono [&_code]:text-[0.9em]',\n '[&_blockquote]:border-l-4 [&_blockquote]:border-accent [&_blockquote]:pl-4 [&_blockquote]:text-fg-muted [&_blockquote]:italic',\n '[&_hr]:my-8 [&_hr]:border-border',\n className,\n )}\n {...rest}\n />\n );\n}\n\n/* ---------------- Note ---------------- */\n\n/** One small line with an icon for disclaimers and formulas, under a section or the page. */\nexport function Note({\n icon = 'info',\n children,\n className,\n}: {\n icon?: IconName;\n children: ReactNode;\n className?: string;\n}) {\n return (\n <p className={cx('m-0 flex items-start gap-1.5 font-sans text-xs text-fg-muted', className)}>\n <Icon name={icon} size={14} className=\"mt-px shrink-0\" />\n <span>{children}</span>\n </p>\n );\n}\n\n/* ---------------- DeviceFrame ---------------- */\n\nconst FRAMES = {\n phone: { outer: 'w-64 rounded-[2.25rem] p-2.5', screen: 'aspect-[9/19.5] rounded-[1.75rem]' },\n tablet: { outer: 'w-full max-w-xl rounded-[1.75rem] p-3', screen: 'aspect-[4/3] rounded-[1.1rem]' },\n // The screen is 92% of the base, so the base never overflows its container.\n laptop: { outer: 'w-[92%] max-w-3xl rounded-t-xl p-2.5 pb-3', screen: 'aspect-[16/10] rounded-md' },\n};\n\n/** A phone, tablet or laptop frame around a screenshot or a live preview (product heroes, docs). */\nexport function DeviceFrame({\n device = 'tablet',\n children,\n className,\n}: {\n device?: 'phone' | 'tablet' | 'laptop';\n children: ReactNode;\n className?: string;\n}) {\n const f = FRAMES[device];\n return (\n <div className={cx('mx-auto grid justify-items-center', device !== 'phone' && 'w-full', className)}>\n <div className={cx('bg-surface-inverse shadow-overlay', f.outer)}>\n <div className={cx('relative w-full overflow-hidden bg-bg [&>img]:size-full [&>img]:object-cover', f.screen)}>\n {children}\n </div>\n </div>\n {device === 'laptop' && (\n <div aria-hidden=\"true\" className=\"h-3 w-full max-w-[calc(48rem/0.92)] rounded-b-xl bg-surface-inverse/85\" />\n )}\n </div>\n );\n}\n\n/* ---------------- StepCarousel ---------------- */\n\nexport interface CarouselStep {\n title: string;\n text: ReactNode;\n /** An illustration or screenshot. */\n media?: ReactNode;\n}\n\nexport interface StepCarouselProps {\n steps: CarouselStep[];\n /** Seconds per step while playing. */\n interval?: number;\n labels?: { step?: (n: number, total: number) => string; prev?: string; next?: string; play?: string; pause?: string };\n className?: string;\n}\n\n/**\n * A guided walkthrough: illustration, \"Step 1 of 6\", title, text, step dots and Previous / Play / Next. Play advances\n * on a timer and never starts on its own; with reduced motion the change is instant.\n */\nexport function StepCarousel({ steps, interval = 5, labels = {}, className }: StepCarouselProps) {\n const [i, setI] = useState(0);\n const [playing, setPlaying] = useState(false);\n const last = steps.length - 1;\n useEffect(() => {\n if (!playing) return;\n const t = setTimeout(() => (i >= last ? setPlaying(false) : setI(i + 1)), interval * 1000);\n return () => clearTimeout(t);\n }, [playing, i, last, interval]);\n const step = steps[i]!;\n const stepLabel = labels.step?.(i + 1, steps.length) ?? `Step ${i + 1} of ${steps.length}`;\n return (\n <section\n aria-roledescription=\"carousel\"\n aria-label={steps[0]?.title}\n className={cx('grid gap-4 rounded-lg border border-border bg-surface p-card font-sans', className)}\n >\n {step.media && <div className=\"overflow-hidden rounded-md bg-surface-muted [&>img]:w-full\">{step.media}</div>}\n <div aria-live={playing ? 'off' : 'polite'} className=\"grid gap-1.5\">\n <p className=\"m-0 text-xs font-semibold tracking-wide text-fg-muted uppercase\">{stepLabel}</p>\n <h3 className=\"m-0 font-display text-lg font-bold text-fg\">{step.title}</h3>\n <div className=\"text-sm text-fg-muted\">{step.text}</div>\n </div>\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <StepDots\n steps={steps.map((s, n) => ({ label: s.title, state: n < i ? 'done' : n === i ? 'current' : 'upcoming' }))}\n />\n <div className=\"flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n iconStart=\"arrow-right\"\n className=\"[&_svg]:rotate-180\"\n disabled={i === 0}\n onClick={() => setI(i - 1)}\n >\n {labels.prev ?? 'Previous'}\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n iconStart=\"play\"\n aria-pressed={playing}\n onClick={() => setPlaying((p) => !p)}\n >\n {playing ? (labels.pause ?? 'Pause') : (labels.play ?? 'Play')}\n </Button>\n <Button size=\"sm\" iconEnd=\"arrow-right\" disabled={i === last} onClick={() => setI(i + 1)}>\n {labels.next ?? 'Next'}\n </Button>\n </div>\n </div>\n </section>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Avatar box sizes, shared by the client `Avatar` and the server-safe `AvatarGroup`. */
2
+ export declare const AV_SIZE: {
3
+ xs: string;
4
+ sm: string;
5
+ md: string;
6
+ lg: string;
7
+ xl: string;
8
+ };
@@ -0,0 +1,12 @@
1
+ //#region src/data-display/avatar-sizes.ts
2
+ var e = {
3
+ xs: "size-6 text-[10px]",
4
+ sm: "size-8 text-xs",
5
+ md: "size-10 text-sm",
6
+ lg: "size-14 text-lg",
7
+ xl: "size-20 text-2xl"
8
+ };
9
+ //#endregion
10
+ export { e as AV_SIZE };
11
+
12
+ //# sourceMappingURL=avatar-sizes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar-sizes.js","names":["AV_SIZE"],"sources":["../../src/data-display/avatar-sizes.ts"],"sourcesContent":["/** Avatar box sizes, shared by the client `Avatar` and the server-safe `AvatarGroup`. */\nexport const AV_SIZE = {\n xs: 'size-6 text-[10px]',\n sm: 'size-8 text-xs',\n md: 'size-10 text-sm',\n lg: 'size-14 text-lg',\n xl: 'size-20 text-2xl',\n};\n"],"mappings":";AACA,IAAaA,IAAU;CACrB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN"}
@@ -0,0 +1,21 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
3
+ name: string;
4
+ src?: string;
5
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
+ /** Presence dot. */
7
+ status?: 'online' | 'away' | 'offline';
8
+ /**
9
+ * Custom status dot (e.g. a person's day: Working, Paused, Day done). Any CSS color, usually
10
+ * `var(--kf-category-N)`. Needs `statusLabel`, which is added to the accessible name.
11
+ */
12
+ statusColor?: string;
13
+ statusLabel?: string;
14
+ /**
15
+ * Hidden from screen readers when the name is already text next to it (lists, menus, cards), so it is not read
16
+ * twice and it may sit inside roles that don't allow images (`role="menu"`).
17
+ */
18
+ decorative?: boolean;
19
+ }
20
+ /** Photo, initials, or a person icon when there is no name. */
21
+ export declare function Avatar({ name, src, size, status, statusColor, statusLabel, decorative, className, ...rest }: AvatarProps): import("react").JSX.Element;
@@ -0,0 +1,53 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Icon as t } from "../icon/icon.js";
4
+ import { AV_SIZE as n } from "./avatar-sizes.js";
5
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
6
+ import { useState as a } from "react";
7
+ //#region src/data-display/avatar.tsx
8
+ var o = {
9
+ xs: 14,
10
+ sm: 18,
11
+ md: 22,
12
+ lg: 30,
13
+ xl: 44
14
+ }, s = (e) => e.split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0].toUpperCase()).join("");
15
+ function c({ name: c, src: l, size: u = "md", status: d, statusColor: f, statusLabel: p, decorative: m, className: h, ...g }) {
16
+ let [_, v] = a(!1), y = l && !_;
17
+ return /* @__PURE__ */ i("span", {
18
+ ...m ? { "aria-hidden": !0 } : {
19
+ role: "img",
20
+ "aria-label": p ? `${c}, ${p}` : c
21
+ },
22
+ className: e("relative inline-grid shrink-0 place-items-center rounded-full bg-info-surface font-sans font-bold text-info-fg", n[u], h),
23
+ ...g,
24
+ children: [
25
+ y ? /* @__PURE__ */ r("img", {
26
+ src: l,
27
+ alt: "",
28
+ onError: () => v(!0),
29
+ className: "size-full rounded-full object-cover"
30
+ }) : c ? /* @__PURE__ */ r("span", {
31
+ "aria-hidden": "true",
32
+ children: s(c)
33
+ }) : /* @__PURE__ */ r(t, {
34
+ name: "user",
35
+ size: o[u],
36
+ className: "text-primary"
37
+ }),
38
+ f && /* @__PURE__ */ r("span", {
39
+ "aria-hidden": "true",
40
+ className: "absolute right-0 bottom-0 size-[28%] min-w-2 rounded-full ring-2 ring-bg",
41
+ style: { background: f }
42
+ }),
43
+ d && !f && /* @__PURE__ */ r("span", {
44
+ "aria-hidden": "true",
45
+ className: e("absolute right-0 bottom-0 size-[28%] min-w-2 rounded-full ring-2 ring-bg", d === "online" ? "bg-success-icon" : d === "away" ? "bg-warning-icon" : "bg-fg-muted")
46
+ })
47
+ ]
48
+ });
49
+ }
50
+ //#endregion
51
+ export { c as Avatar };
52
+
53
+ //# sourceMappingURL=avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.js","names":["AV_ICON","initials","name","p","Avatar","rest","failed","setFailed","useState","showImg","src","decorative","statusLabel","cx","AV_SIZE","size","className","Icon","statusColor","status"],"sources":["../../src/data-display/avatar.tsx"],"sourcesContent":["'use client';\n\nimport { useState, type HTMLAttributes } from 'react';\nimport { cx } from '../lib/cx';\nimport { Icon } from '../icon/icon';\nimport { AV_SIZE } from './avatar-sizes';\n\n/* ---------------- Avatar ---------------- */\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n name: string;\n src?: string;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Presence dot. */\n status?: 'online' | 'away' | 'offline';\n /**\n * Custom status dot (e.g. a person's day: Working, Paused, Day done). Any CSS color, usually\n * `var(--kf-category-N)`. Needs `statusLabel`, which is added to the accessible name.\n */\n statusColor?: string;\n statusLabel?: string;\n /**\n * Hidden from screen readers when the name is already text next to it (lists, menus, cards), so it is not read\n * twice and it may sit inside roles that don't allow images (`role=\"menu\"`).\n */\n decorative?: boolean;\n}\n\nconst AV_ICON = { xs: 14, sm: 18, md: 22, lg: 30, xl: 44 };\n\nconst initials = (name: string) =>\n name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((p) => p[0]!.toUpperCase())\n .join('');\n\n/** Photo, initials, or a person icon when there is no name. */\nexport function Avatar({ name, src, size = 'md', status, statusColor, statusLabel, decorative, className, ...rest }: AvatarProps) {\n const [failed, setFailed] = useState(false);\n const showImg = src && !failed;\n return (\n <span\n {...(decorative ? { 'aria-hidden': true } : { role: 'img', 'aria-label': statusLabel ? `${name}, ${statusLabel}` : name })}\n className={cx(\n 'relative inline-grid shrink-0 place-items-center rounded-full bg-info-surface font-sans font-bold text-info-fg',\n AV_SIZE[size],\n className,\n )}\n {...rest}\n >\n {showImg ? (\n <img src={src} alt=\"\" onError={() => setFailed(true)} className=\"size-full rounded-full object-cover\" />\n ) : name ? (\n <span aria-hidden=\"true\">{initials(name)}</span>\n ) : (\n <Icon name=\"user\" size={AV_ICON[size]} className=\"text-primary\" />\n )}\n {statusColor && (\n <span\n aria-hidden=\"true\"\n className=\"absolute right-0 bottom-0 size-[28%] min-w-2 rounded-full ring-2 ring-bg\"\n style={{ background: statusColor }}\n />\n )}\n {status && !statusColor && (\n <span\n aria-hidden=\"true\"\n className={cx(\n 'absolute right-0 bottom-0 size-[28%] min-w-2 rounded-full ring-2 ring-bg',\n status === 'online' ? 'bg-success-icon' : status === 'away' ? 'bg-warning-icon' : 'bg-fg-muted',\n )}\n />\n )}\n </span>\n );\n}\n"],"mappings":";;;;;;;AA4BA,IAAMA,IAAU;CAAE,IAAI;CAAI,IAAI;CAAI,IAAI;CAAI,IAAI;CAAI,IAAI;AAAG,GAEnDC,KAAY,MAChBC,EACG,MAAM,KAAK,CAAC,CACZ,OAAO,OAAO,CAAC,CACf,MAAM,GAAG,CAAC,CAAC,CACX,KAAK,MAAMC,EAAE,EAAE,CAAE,YAAY,CAAC,CAAC,CAC/B,KAAK,EAAE;AAGZ,SAAgBC,EAAO,EAAE,SAAM,QAAK,UAAO,MAAM,WAAQ,gBAAa,gBAAa,eAAY,cAAW,GAAGC,KAAqB;CAChI,IAAM,CAACC,GAAQC,KAAaC,EAAS,EAAK,GACpCC,IAAUC,KAAO,CAACJ;CACxB,OACE,kBAAC,QAAD;EACE,GAAKK,IAAa,EAAE,eAAe,GAAK,IAAI;GAAE,MAAM;GAAO,cAAcC,IAAc,GAAGV,EAAK,IAAIU,MAAgBV;EAAK;EACxH,WAAWW,EACT,kHACAC,EAAQC,IACRC,CACF;EACA,GAAIX;EAPN,UAAA;GASGI,IACC,kBAAC,OAAD;IAAU;IAAK,KAAI;IAAG,eAAeF,EAAU,EAAI;IAAG,WAAU;GAAuC,CAAA,IACrGL,IACF,kBAAC,QAAD;IAAM,eAAY;IAAQ,UAAAD,EAASC,CAAI;GAAQ,CAAA,IAE/C,kBAACe,GAAD;IAAM,MAAK;IAAO,MAAMjB,EAAQe;IAAO,WAAU;GAAgB,CAAA;GAElEG,KACC,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACV,OAAO,EAAE,YAAYA,EAAY;GAClC,CAAA;GAEFC,KAAU,CAACD,KACV,kBAAC,QAAD;IACE,eAAY;IACZ,WAAWL,EACT,4EACAM,MAAW,WAAW,oBAAoBA,MAAW,SAAS,oBAAoB,aACpF;GACD,CAAA;EAEC;;AAEV"}
@@ -0,0 +1,20 @@
1
+ import type { ButtonHTMLAttributes } from 'react';
2
+ import { type IconName } from '../icon/icon';
3
+ export interface ChipProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange'> {
4
+ /** Toggle chip (filters): `aria-pressed`. */
5
+ pressed?: boolean;
6
+ onPressedChange?: (pressed: boolean) => void;
7
+ icon?: IconName;
8
+ /** Count shown at the end. */
9
+ count?: number;
10
+ /** Shows a remove button instead of toggling (applied filters). */
11
+ onRemove?: () => void;
12
+ removeLabel?: string;
13
+ /**
14
+ * Category color for filter toggles (calendar event types, tags): a dot before the label, and the
15
+ * pressed chip is tinted with it. Any CSS color, usually `var(--kf-category-N)`.
16
+ */
17
+ color?: string;
18
+ }
19
+ /** Filter chip. Toggle with `pressed`, or removable with `onRemove`. */
20
+ export declare function Chip({ pressed, onPressedChange, icon, count, onRemove, removeLabel, color, className, children, ...rest }: ChipProps): import("react").JSX.Element;
@@ -0,0 +1,64 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Icon as t } from "../icon/icon.js";
4
+ import { Glyph as n } from "../lib/glyphs.js";
5
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
6
+ //#region src/data-display/chip.tsx
7
+ function a({ pressed: a, onPressedChange: o, icon: s, count: c, onRemove: l, removeLabel: u = "Remove", color: d, className: f, children: p, ...m }) {
8
+ let h = d ? /* @__PURE__ */ r("span", {
9
+ "aria-hidden": "true",
10
+ className: "size-2.5 shrink-0 rounded-full",
11
+ style: { background: d }
12
+ }) : null, g = "inline-flex min-h-8 items-center gap-1.5 rounded-full border font-sans text-sm font-semibold transition-colors pointer-coarse:min-h-10";
13
+ return l ? /* @__PURE__ */ i("span", {
14
+ className: e(g, "border-primary bg-info-surface pr-1 pl-3 text-info-fg", f),
15
+ children: [
16
+ h,
17
+ s && /* @__PURE__ */ r(t, {
18
+ name: s,
19
+ size: 16
20
+ }),
21
+ p,
22
+ /* @__PURE__ */ r("button", {
23
+ type: "button",
24
+ "aria-label": `${u} ${typeof p == "string" ? p : ""}`.trim(),
25
+ onClick: l,
26
+ className: "grid size-6 cursor-pointer place-items-center rounded-full border-0 bg-transparent text-current hover:bg-bg focus-visible:outline-2 focus-visible:outline-focus",
27
+ children: /* @__PURE__ */ r(n, {
28
+ name: "close",
29
+ size: 12
30
+ })
31
+ })
32
+ ]
33
+ }) : /* @__PURE__ */ i("button", {
34
+ type: "button",
35
+ "aria-pressed": a,
36
+ onClick: () => o?.(!a),
37
+ className: e(g, "cursor-pointer px-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-focus", d ? a ? "border-(--kf-chip) bg-[color-mix(in_oklab,var(--kf-chip),transparent_82%)] text-fg" : "border-border bg-surface text-fg hover:border-fg-muted/50" : a ? "border-primary bg-primary text-on-primary" : "border-border bg-surface text-fg hover:border-fg-muted/50", f),
38
+ ...m,
39
+ style: d ? {
40
+ "--kf-chip": d,
41
+ ...m.style
42
+ } : m.style,
43
+ children: [
44
+ a && /* @__PURE__ */ r(n, {
45
+ name: "check",
46
+ size: 14
47
+ }),
48
+ h,
49
+ s && /* @__PURE__ */ r(t, {
50
+ name: s,
51
+ size: 16
52
+ }),
53
+ p,
54
+ c !== void 0 && /* @__PURE__ */ r("span", {
55
+ className: e("tabular-nums", a ? "opacity-80" : "text-fg-muted"),
56
+ children: c
57
+ })
58
+ ]
59
+ });
60
+ }
61
+ //#endregion
62
+ export { a as Chip };
63
+
64
+ //# sourceMappingURL=chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chip.js","names":["Chip","rest","dot","color","base","onRemove","cx","className","icon","Icon","children","removeLabel","Glyph","pressed","onPressedChange","count"],"sources":["../../src/data-display/chip.tsx"],"sourcesContent":["'use client';\n\nimport type { ButtonHTMLAttributes } from 'react';\nimport { cx } from '../lib/cx';\nimport { Glyph } from '../lib/glyphs';\nimport { Icon, type IconName } from '../icon/icon';\n\n/* ---------------- Chip ---------------- */\n\nexport interface ChipProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange'> {\n /** Toggle chip (filters): `aria-pressed`. */\n pressed?: boolean;\n onPressedChange?: (pressed: boolean) => void;\n icon?: IconName;\n /** Count shown at the end. */\n count?: number;\n /** Shows a remove button instead of toggling (applied filters). */\n onRemove?: () => void;\n removeLabel?: string;\n /**\n * Category color for filter toggles (calendar event types, tags): a dot before the label, and the\n * pressed chip is tinted with it. Any CSS color, usually `var(--kf-category-N)`.\n */\n color?: string;\n}\n\n/** Filter chip. Toggle with `pressed`, or removable with `onRemove`. */\nexport function Chip({\n pressed,\n onPressedChange,\n icon,\n count,\n onRemove,\n removeLabel = 'Remove',\n color,\n className,\n children,\n ...rest\n}: ChipProps) {\n const dot = color ? <span aria-hidden=\"true\" className=\"size-2.5 shrink-0 rounded-full\" style={{ background: color }} /> : null;\n const base =\n 'inline-flex min-h-8 items-center gap-1.5 rounded-full border font-sans text-sm font-semibold transition-colors pointer-coarse:min-h-10';\n if (onRemove) {\n return (\n <span className={cx(base, 'border-primary bg-info-surface pr-1 pl-3 text-info-fg', className)}>\n {dot}\n {icon && <Icon name={icon} size={16} />}\n {children}\n <button\n type=\"button\"\n aria-label={`${removeLabel} ${typeof children === 'string' ? children : ''}`.trim()}\n onClick={onRemove}\n className=\"grid size-6 cursor-pointer place-items-center rounded-full border-0 bg-transparent text-current hover:bg-bg focus-visible:outline-2 focus-visible:outline-focus\"\n >\n <Glyph name=\"close\" size={12} />\n </button>\n </span>\n );\n }\n return (\n <button\n type=\"button\"\n aria-pressed={pressed}\n onClick={() => onPressedChange?.(!pressed)}\n className={cx(\n base,\n 'cursor-pointer px-3 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-focus',\n // A colored chip stays readable in both themes: tinted surface and border, regular text color.\n color\n ? pressed\n ? 'border-(--kf-chip) bg-[color-mix(in_oklab,var(--kf-chip),transparent_82%)] text-fg'\n : 'border-border bg-surface text-fg hover:border-fg-muted/50'\n : pressed\n ? 'border-primary bg-primary text-on-primary'\n : 'border-border bg-surface text-fg hover:border-fg-muted/50',\n className,\n )}\n {...rest}\n style={color ? { ['--kf-chip' as string]: color, ...rest.style } : rest.style}\n >\n {pressed && <Glyph name=\"check\" size={14} />}\n {dot}\n {icon && <Icon name={icon} size={16} />}\n {children}\n {count !== undefined && (\n <span className={cx('tabular-nums', pressed ? 'opacity-80' : 'text-fg-muted')}>{count}</span>\n )}\n </button>\n );\n}\n"],"mappings":";;;;;;AA2BA,SAAgBA,EAAK,EACnB,YACA,oBACA,SACA,UACA,aACA,iBAAc,UACd,UACA,cACA,aACA,GAAGC,KACS;CACZ,IAAMC,IAAMC,IAAQ,kBAAC,QAAD;EAAM,eAAY;EAAO,WAAU;EAAiC,OAAO,EAAE,YAAYA,EAAM;CAAI,CAAA,IAAI,MACrHC,IACJ;CAkBF,OAjBIC,IAEA,kBAAC,QAAD;EAAM,WAAWC,EAAGF,GAAM,yDAAyDG,CAAS;EAA5F,UAAA;GACGL;GACAM,KAAQ,kBAACC,GAAD;IAAM,MAAMD;IAAM,MAAM;GAAK,CAAA;GACrCE;GACD,kBAAC,UAAD;IACE,MAAK;IACL,cAAY,GAAGC,EAAY,GAAG,OAAOD,KAAa,WAAWA,IAAW,KAAK,KAAK;IAClF,SAASL;IACT,WAAU;IAEV,UAAA,kBAACO,GAAD;KAAO,MAAK;KAAQ,MAAM;IAAK,CAAA;GACzB,CAAA;EACJ;C,KAIR,kBAAC,UAAD;EACE,MAAK;EACL,gBAAcC;EACd,eAAeC,IAAkB,CAACD,CAAO;EACzC,WAAWP,EACTF,GACA,0GAEAD,IACIU,IACE,uFACA,8DACFA,IACE,8CACA,6DACNN,CACF;EACA,GAAIN;EACJ,OAAOE,IAAQ;GAAG,aAAwBA;GAAO,GAAGF,EAAK;EAAM,IAAIA,EAAK;EAlB1E,UAAA;GAoBGY,KAAW,kBAACD,GAAD;IAAO,MAAK;IAAQ,MAAM;GAAK,CAAA;GAC1CV;GACAM,KAAQ,kBAACC,GAAD;IAAM,MAAMD;IAAM,MAAM;GAAK,CAAA;GACrCE;GACAK,MAAU,KAAA,KACT,kBAAC,QAAD;IAAM,WAAWT,EAAG,gBAAgBO,IAAU,eAAe,eAAe;IAAI,UAAAE;GAAY,CAAA;EAExF;;AAEZ"}
@@ -0,0 +1,14 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export interface CodeBlockProps extends HTMLAttributes<HTMLDivElement> {
3
+ code: string;
4
+ /** Shown in the header (`bash`, `json`, `tsx`). */
5
+ language?: string;
6
+ /** File name or title in the header. */
7
+ title?: string;
8
+ copyLabel?: string;
9
+ copiedLabel?: string;
10
+ /** Show line numbers. */
11
+ lineNumbers?: boolean;
12
+ }
13
+ /** Code sample with copy button. Light, dependency-free: no syntax highlighting by design. */
14
+ export declare function CodeBlock({ code, language, title, copyLabel, copiedLabel, lineNumbers, className, ...rest }: CodeBlockProps): import("react").JSX.Element;
@@ -0,0 +1,50 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Glyph as t } from "../lib/glyphs.js";
4
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ import { useState as i } from "react";
6
+ //#region src/data-display/code-block.tsx
7
+ function a({ code: a, language: o, title: s, copyLabel: c = "Copy", copiedLabel: l = "Copied", lineNumbers: u, className: d, ...f }) {
8
+ let [p, m] = i(!1), h = async () => {
9
+ try {
10
+ await navigator.clipboard.writeText(a), m(!0), setTimeout(() => m(!1), 1800);
11
+ } catch {}
12
+ }, g = a.replace(/\n$/, "").split("\n");
13
+ return /* @__PURE__ */ r("div", {
14
+ className: e("overflow-hidden rounded-md border border-border bg-surface-muted font-sans", d),
15
+ ...f,
16
+ children: [/* @__PURE__ */ r("div", {
17
+ className: "flex items-center justify-between gap-3 border-b border-border px-4 py-1.5",
18
+ children: [/* @__PURE__ */ n("span", {
19
+ className: "font-mono text-xs text-fg-muted",
20
+ children: s ?? o
21
+ }), /* @__PURE__ */ r("button", {
22
+ type: "button",
23
+ onClick: h,
24
+ className: "inline-flex cursor-pointer items-center gap-1.5 rounded-full border-0 bg-transparent px-2.5 py-1 text-xs font-semibold text-fg-muted hover:bg-bg hover:text-fg focus-visible:outline-3 focus-visible:outline-focus",
25
+ children: [/* @__PURE__ */ n(t, {
26
+ name: p ? "check" : "columns",
27
+ size: 14
28
+ }), /* @__PURE__ */ n("span", {
29
+ "aria-live": "polite",
30
+ children: p ? l : c
31
+ })]
32
+ })]
33
+ }), /* @__PURE__ */ n("pre", {
34
+ tabIndex: 0,
35
+ className: "m-0 overflow-x-auto p-4 font-mono text-[13px] leading-relaxed text-fg focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-focus",
36
+ children: /* @__PURE__ */ n("code", { children: u ? g.map((e, t) => /* @__PURE__ */ r("span", {
37
+ className: "block",
38
+ children: [/* @__PURE__ */ n("span", {
39
+ "aria-hidden": "true",
40
+ className: "mr-4 inline-block w-6 text-right text-fg-muted/70 select-none",
41
+ children: t + 1
42
+ }), e]
43
+ }, t)) : a })
44
+ })]
45
+ });
46
+ }
47
+ //#endregion
48
+ export { a as CodeBlock };
49
+
50
+ //# sourceMappingURL=code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block.js","names":["CodeBlock","rest","copied","setCopied","useState","copy","code","lines","cx","className","title","language","Glyph","copiedLabel","copyLabel","lineNumbers","i","l"],"sources":["../../src/data-display/code-block.tsx"],"sourcesContent":["'use client';\n\nimport { useState, type HTMLAttributes } from 'react';\nimport { cx } from '../lib/cx';\nimport { Glyph } from '../lib/glyphs';\n\n/* ---------------- CodeBlock ---------------- */\n\nexport interface CodeBlockProps extends HTMLAttributes<HTMLDivElement> {\n code: string;\n /** Shown in the header (`bash`, `json`, `tsx`). */\n language?: string;\n /** File name or title in the header. */\n title?: string;\n copyLabel?: string;\n copiedLabel?: string;\n /** Show line numbers. */\n lineNumbers?: boolean;\n}\n\n/** Code sample with copy button. Light, dependency-free: no syntax highlighting by design. */\nexport function CodeBlock({\n code,\n language,\n title,\n copyLabel = 'Copy',\n copiedLabel = 'Copied',\n lineNumbers,\n className,\n ...rest\n}: CodeBlockProps) {\n const [copied, setCopied] = useState(false);\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1800);\n } catch {\n /* clipboard blocked: the text stays selectable */\n }\n };\n const lines = code.replace(/\\n$/, '').split('\\n');\n return (\n <div\n className={cx('overflow-hidden rounded-md border border-border bg-surface-muted font-sans', className)}\n {...rest}\n >\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-1.5\">\n <span className=\"font-mono text-xs text-fg-muted\">{title ?? language}</span>\n <button\n type=\"button\"\n onClick={copy}\n className=\"inline-flex cursor-pointer items-center gap-1.5 rounded-full border-0 bg-transparent px-2.5 py-1 text-xs font-semibold text-fg-muted hover:bg-bg hover:text-fg focus-visible:outline-3 focus-visible:outline-focus\"\n >\n <Glyph name={copied ? 'check' : 'columns'} size={14} />\n <span aria-live=\"polite\">{copied ? copiedLabel : copyLabel}</span>\n </button>\n </div>\n <pre\n tabIndex={0}\n className=\"m-0 overflow-x-auto p-4 font-mono text-[13px] leading-relaxed text-fg focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-focus\"\n >\n <code>\n {lineNumbers\n ? lines.map((l, i) => (\n <span key={i} className=\"block\">\n <span aria-hidden=\"true\" className=\"mr-4 inline-block w-6 text-right text-fg-muted/70 select-none\">\n {i + 1}\n </span>\n {l}\n </span>\n ))\n : code}\n </code>\n </pre>\n </div>\n );\n}\n"],"mappings":";;;;;;AAqBA,SAAgBA,EAAU,EACxB,SACA,aACA,UACA,eAAY,QACZ,iBAAc,UACd,gBACA,cACA,GAAGC,KACc;CACjB,IAAM,CAACC,GAAQC,KAAaC,EAAS,EAAK,GACpCC,IAAO,YAAY;EACvB,IAAI;GAGF,AAFA,MAAM,UAAU,UAAU,UAAUC,CAAI,GACxCH,EAAU,EAAI,GACd,iBAAiBA,EAAU,EAAK,GAAG,IAAI;EACzC,QAAQ,CAER;CACF,GACMI,IAAQD,EAAK,QAAQ,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI;CAChD,OACE,kBAAC,OAAD;EACE,WAAWE,EAAG,8EAA8EC,CAAS;EACrG,GAAIR;EAFN,UAAA,CAIE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,QAAD;IAAM,WAAU;IAAmC,UAAAS,KAASC;GAAe,CAAA,GAC3E,kBAAC,UAAD;IACE,MAAK;IACL,SAASN;IACT,WAAU;IAHZ,UAAA,CAKE,kBAACO,GAAD;KAAO,MAAMV,IAAS,UAAU;KAAW,MAAM;IAAK,CAAA,GACtD,kBAAC,QAAD;KAAM,aAAU;KAAU,UAAAA,IAASW,IAAcC;IAAgB,CAAA,CAC3D;GACL,CAAA,CAAA;EACL,CAAA,GAAA,kBAAC,OAAD;GACE,UAAU;GACV,WAAU;GAEV,UAAA,kBAAC,QAAD,EAAA,UACGC,IACGR,EAAM,KAAK,GAAG,MACZ,kBAAC,QAAD;IAAc,WAAU;IAAxB,UAAA,CACE,kBAAC,QAAD;KAAM,eAAY;KAAO,WAAU;KAChC,UAAAS,IAAI;IACD,CAAA,GACLC,CACG;GALK,GAAAD,CAKL,CACP,IACDV,EACA,CAAA;EACH,CAAA,CACF;;AAET"}
@@ -0,0 +1,73 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type IconName } from '../icon/icon';
3
+ import { type AvatarProps } from './avatar';
4
+ export interface SparklineProps extends Omit<HTMLAttributes<SVGSVGElement>, 'children'> {
5
+ data: number[];
6
+ /** Accessible summary, e.g. "Runs per day, last 14 days: rising from 120 to 310". */
7
+ label: string;
8
+ height?: number;
9
+ tone?: 'primary' | 'accent' | 'success' | 'danger';
10
+ /** Fill the area under the line. */
11
+ area?: boolean;
12
+ }
13
+ /** Dependency-free trend line for KPI tiles. For full charts use LineChart, AreaChart, BarChart, DonutChart. */
14
+ export declare function Sparkline({ data, label, height, tone, area, className, ...rest }: SparklineProps): import("react").JSX.Element | null;
15
+ export interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {
16
+ people: {
17
+ name: string;
18
+ src?: string;
19
+ }[];
20
+ max?: number;
21
+ size?: AvatarProps['size'];
22
+ /** Accessible summary, e.g. "5 members". Defaults to the names. */
23
+ label?: string;
24
+ }
25
+ export declare function AvatarGroup({ people, max, size, label, className, ...rest }: AvatarGroupProps): import("react").JSX.Element;
26
+ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
27
+ /** Neutral metadata label (technology, category). For status use `Badge`. */
28
+ children: ReactNode;
29
+ icon?: IconName;
30
+ }
31
+ export declare function Tag({ icon, className, children, ...rest }: TagProps): import("react").JSX.Element;
32
+ export interface TimelineItem {
33
+ title: ReactNode;
34
+ description?: ReactNode;
35
+ /** Label at the start (year, time). */
36
+ time?: ReactNode;
37
+ icon?: IconName;
38
+ tone?: 'default' | 'success' | 'warning' | 'danger' | 'info';
39
+ }
40
+ /** Vertical sequence of events: company history (years), run logs, activity. */
41
+ export declare function Timeline({ items, className }: {
42
+ items: TimelineItem[];
43
+ className?: string;
44
+ }): import("react").JSX.Element;
45
+ export interface DescriptionListProps extends HTMLAttributes<HTMLDListElement> {
46
+ items: {
47
+ term: ReactNode;
48
+ description: ReactNode;
49
+ }[];
50
+ /** `stacked` (term above), `inline` (term | value columns from sm), `grid` (2–3 columns of pairs). */
51
+ layout?: 'stacked' | 'inline' | 'grid';
52
+ }
53
+ /** Key/value details for record pages (workflow settings, invoice data). */
54
+ export declare function DescriptionList({ items, layout, className, ...rest }: DescriptionListProps): import("react").JSX.Element;
55
+ export interface FlowStep {
56
+ id: string;
57
+ label: ReactNode;
58
+ /** App or system ("Gmail", "AI", "QuickBooks"). */
59
+ meta?: ReactNode;
60
+ icon?: IconName;
61
+ kind?: 'trigger' | 'action' | 'ai' | 'output';
62
+ }
63
+ /**
64
+ * Static automation flow for case studies and the Blueprint tool. `responsive` (default): left to
65
+ * right from 960px, top to bottom below. Use `vertical` in narrow containers. The interactive
66
+ * editor (React Flow) needs its own ADR.
67
+ */
68
+ export declare function FlowDiagram({ steps, label, orientation, className, }: {
69
+ steps: FlowStep[];
70
+ label: string;
71
+ orientation?: 'responsive' | 'vertical' | 'horizontal';
72
+ className?: string;
73
+ }): import("react").JSX.Element;