prime-ui-kit 0.13.1 → 0.15.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 (609) hide show
  1. package/README.md +20 -20
  2. package/dist/chunks/{chunk-XNOJEX55.js → chunk-2IKH55MI.js} +1 -1
  3. package/dist/chunks/{chunk-JV2KB5JZ.js → chunk-THFZIHKU.js} +3761 -3041
  4. package/dist/chunks/{chunk-PK2GC77E.js → chunk-XJAVS6FH.js} +213 -188
  5. package/dist/color-picker.js +2 -2
  6. package/dist/components/banner/Banner.d.ts +5 -2
  7. package/dist/components/chart-frame/ChartFrame.d.ts +19 -6
  8. package/dist/components/chat/Chat.d.ts +2 -2
  9. package/dist/components/chat/ChatPinned.d.ts +2 -2
  10. package/dist/components/chat/MessageList.d.ts +1 -1
  11. package/dist/components/chat/chatContext.d.ts +1 -1
  12. package/dist/components/dnd/Dnd.d.ts +1 -1
  13. package/dist/components/field-list/FieldList.d.ts +90 -0
  14. package/dist/components/index.d.ts +3 -1
  15. package/dist/components/input/Input.d.ts +2 -2
  16. package/dist/components/kanban/Kanban.d.ts +6 -3
  17. package/dist/components/login-form/LoginForm.d.ts +5 -1
  18. package/dist/components/page-content/PageContent.d.ts +55 -4
  19. package/dist/components/sparkline/Sparkline.d.ts +64 -15
  20. package/dist/components/sparkline/geometry.d.ts +26 -0
  21. package/dist/components/tooltip/Tooltip.d.ts +5 -2
  22. package/dist/hooks/usePosition.d.ts +15 -4
  23. package/dist/index.css +1 -1
  24. package/dist/index.js +4 -2
  25. package/dist/internal/ChartTooltip.d.ts +26 -0
  26. package/dist/internal/FieldAction.d.ts +6 -7
  27. package/dist/internal/fieldCell.d.ts +21 -0
  28. package/dist/internal/messageList.d.ts +2 -2
  29. package/dist/internal/palette.d.ts +7 -0
  30. package/dist/internal/swatch.d.ts +6 -2
  31. package/dist/layout/app-header/AppHeader.d.ts +9 -28
  32. package/dist/layout/index.d.ts +1 -1
  33. package/dist/skill/SKILL.md +32 -20
  34. package/dist/skill/anti-slop.md +77 -4
  35. package/dist/skill/api-contract.md +2 -2
  36. package/dist/skill/cheatsheet.md +33 -7
  37. package/dist/skill/checklist.md +28 -6
  38. package/dist/skill/choosing.md +17 -14
  39. package/dist/skill/components.md +9 -15
  40. package/dist/skill/composition.md +301 -61
  41. package/dist/skill/foundations.md +9 -7
  42. package/dist/skill/layouts.md +70 -37
  43. package/dist/skill/reference/components/avatar/COMPONENT.md +4 -4
  44. package/dist/skill/reference/components/avatar/examples/presence.tsx +1 -1
  45. package/dist/skill/reference/components/avatar/examples/states.tsx +5 -5
  46. package/dist/skill/reference/components/badge/examples/applied-filters.tsx +13 -19
  47. package/dist/skill/reference/components/badge/examples/examples.module.css +1 -8
  48. package/dist/skill/reference/components/badge/examples/server-tags.tsx +2 -6
  49. package/dist/skill/reference/components/banner/COMPONENT.md +6 -6
  50. package/dist/skill/reference/components/banner/examples/dismissible.tsx +22 -11
  51. package/dist/skill/reference/components/banner/examples/examples.module.css +4 -8
  52. package/dist/skill/reference/components/banner/examples/narrow.tsx +1 -1
  53. package/dist/skill/reference/components/banner/examples/page-strip.tsx +16 -22
  54. package/dist/skill/reference/components/breadcrumb/COMPONENT.md +5 -4
  55. package/dist/skill/reference/components/breadcrumb/examples/ellipsis.tsx +2 -2
  56. package/dist/skill/reference/components/breadcrumb/examples/overflow.tsx +1 -1
  57. package/dist/skill/reference/components/button-group/COMPONENT.md +2 -2
  58. package/dist/skill/reference/components/button-group/examples/in-form.tsx +22 -2
  59. package/dist/skill/reference/components/button-group/examples/states.tsx +10 -1
  60. package/dist/skill/reference/components/card/COMPONENT.md +7 -5
  61. package/dist/skill/reference/components/card/examples/examples.module.css +0 -28
  62. package/dist/skill/reference/components/card/examples/kpi-media.tsx +13 -11
  63. package/dist/skill/reference/components/card/examples/narrow.tsx +1 -1
  64. package/dist/skill/reference/components/card/examples/panel-chart.tsx +45 -22
  65. package/dist/skill/reference/components/card/examples/screen.module.css +14 -0
  66. package/dist/skill/reference/components/card/examples/screen.tsx +362 -0
  67. package/dist/skill/reference/components/card/examples/variants.tsx +15 -1
  68. package/dist/skill/reference/components/chart-frame/COMPONENT.md +12 -8
  69. package/dist/skill/reference/components/chart-frame/examples/fill-height.tsx +119 -0
  70. package/dist/skill/reference/components/chart-frame/examples/states.tsx +3 -1
  71. package/dist/skill/reference/components/chart-frame/examples/tooltip.tsx +20 -24
  72. package/dist/skill/reference/components/chat/COMPONENT.md +6 -4
  73. package/dist/skill/reference/components/chat/examples/group-chat.tsx +15 -2
  74. package/dist/skill/reference/components/chat/examples/reactions.tsx +121 -0
  75. package/dist/skill/reference/components/chat/examples/screen.module.css +9 -0
  76. package/dist/skill/{patterns/chat.tsx → reference/components/chat/examples/screen.tsx} +187 -350
  77. package/dist/skill/reference/components/chat/examples/search.tsx +1 -1
  78. package/dist/skill/reference/components/chat-list/COMPONENT.md +2 -1
  79. package/dist/skill/reference/components/chat-list/examples/links.tsx +72 -0
  80. package/dist/skill/reference/components/checkbox/COMPONENT.md +1 -1
  81. package/dist/skill/reference/components/checkbox/examples/examples.module.css +5 -1
  82. package/dist/skill/reference/components/checkbox/examples/indicator.tsx +37 -9
  83. package/dist/skill/reference/components/checkbox/examples/states.tsx +6 -1
  84. package/dist/skill/reference/components/color-field/COMPONENT.md +1 -1
  85. package/dist/skill/reference/components/color-picker/COMPONENT.md +6 -5
  86. package/dist/skill/reference/components/color-picker/examples/controlled-open.tsx +37 -0
  87. package/dist/skill/reference/components/color-picker/examples/presets.tsx +2 -2
  88. package/dist/skill/reference/components/color-picker/examples/states.tsx +23 -14
  89. package/dist/skill/reference/components/color-swatches/COMPONENT.md +1 -0
  90. package/dist/skill/reference/components/composer/COMPONENT.md +2 -1
  91. package/dist/skill/reference/components/composer/examples/attach-menu.tsx +78 -0
  92. package/dist/skill/reference/components/composer/examples/attachments.tsx +2 -2
  93. package/dist/skill/reference/components/crossfade/COMPONENT.md +1 -0
  94. package/dist/skill/{patterns/screen-states.module.css → reference/components/crossfade/examples/screen.module.css} +3 -17
  95. package/dist/skill/reference/components/crossfade/examples/screen.tsx +197 -0
  96. package/dist/skill/reference/components/data-table/COMPONENT.md +3 -2
  97. package/dist/skill/reference/components/data-table/examples/detail-panel.tsx +36 -37
  98. package/dist/skill/reference/components/data-table/examples/examples.module.css +0 -12
  99. package/dist/skill/reference/components/data-table/examples/numeric.tsx +36 -4
  100. package/dist/skill/reference/components/data-table/examples/overview.tsx +1 -0
  101. package/dist/skill/reference/components/data-table/examples/row-open.tsx +7 -36
  102. package/dist/skill/{patterns/list-page.module.css → reference/components/data-table/examples/screen.module.css} +1 -7
  103. package/dist/skill/{patterns/list-page.tsx → reference/components/data-table/examples/screen.tsx} +84 -64
  104. package/dist/skill/reference/components/datepicker/COMPONENT.md +6 -4
  105. package/dist/skill/reference/components/datepicker/examples/examples.module.css +2 -6
  106. package/dist/skill/reference/components/datepicker/examples/in-form.tsx +47 -55
  107. package/dist/skill/reference/components/datepicker/examples/locale.tsx +35 -0
  108. package/dist/skill/reference/components/datepicker/examples/range-presets.tsx +11 -2
  109. package/dist/skill/reference/components/datepicker/examples/states.tsx +9 -1
  110. package/dist/skill/reference/components/description-list/COMPONENT.md +1 -0
  111. package/dist/skill/{patterns/detail-page.module.css → reference/components/description-list/examples/screen.module.css} +2 -12
  112. package/dist/skill/reference/components/description-list/examples/screen.tsx +214 -0
  113. package/dist/skill/reference/components/description-list/examples/structure.tsx +1 -1
  114. package/dist/skill/reference/components/digit-input/COMPONENT.md +3 -1
  115. package/dist/skill/reference/components/digit-input/examples/states.tsx +3 -1
  116. package/dist/skill/reference/components/digit-input/examples/without-focus-ring.tsx +13 -0
  117. package/dist/skill/reference/components/divider/examples/with-icon.tsx +2 -2
  118. package/dist/skill/reference/components/dnd/COMPONENT.md +7 -5
  119. package/dist/skill/reference/components/dnd/examples/drop-zones.tsx +82 -49
  120. package/dist/skill/reference/components/dnd/examples/examples.module.css +50 -0
  121. package/dist/skill/reference/components/dnd/examples/states.tsx +54 -0
  122. package/dist/skill/reference/components/dnd/examples/table.tsx +113 -0
  123. package/dist/skill/reference/components/drawer/COMPONENT.md +1 -0
  124. package/dist/skill/reference/components/drawer/examples/dismiss.tsx +5 -3
  125. package/dist/skill/reference/components/drawer/examples/examples.module.css +0 -13
  126. package/dist/skill/reference/components/drawer/examples/header-actions.tsx +5 -9
  127. package/dist/skill/reference/components/drawer/examples/overview.tsx +6 -18
  128. package/dist/skill/reference/components/drawer/examples/screen.tsx +298 -0
  129. package/dist/skill/reference/components/dropdown/examples/examples.module.css +1 -5
  130. package/dist/skill/reference/components/empty-page/COMPONENT.md +1 -1
  131. package/dist/skill/reference/components/empty-page/examples/region-error.tsx +8 -2
  132. package/dist/skill/reference/components/example-frame/COMPONENT.md +3 -2
  133. package/dist/skill/reference/components/example-frame/examples/initial-view.tsx +44 -0
  134. package/dist/skill/reference/components/field-list/COMPONENT.md +165 -0
  135. package/dist/skill/reference/components/field-list/examples/base-row.tsx +76 -0
  136. package/dist/skill/reference/components/field-list/examples/controlled.tsx +72 -0
  137. package/dist/skill/reference/components/field-list/examples/errors.tsx +88 -0
  138. package/dist/skill/reference/components/field-list/examples/examples.module.css +34 -0
  139. package/dist/skill/reference/components/field-list/examples/limits.tsx +55 -0
  140. package/dist/skill/reference/components/field-list/examples/locked.tsx +139 -0
  141. package/dist/skill/reference/components/field-list/examples/narrow.tsx +68 -0
  142. package/dist/skill/reference/components/field-list/examples/overview.tsx +66 -0
  143. package/dist/skill/reference/components/field-list/examples/reorder.tsx +42 -0
  144. package/dist/skill/reference/components/field-list/examples/screen.module.css +18 -0
  145. package/dist/skill/reference/components/field-list/examples/screen.tsx +316 -0
  146. package/dist/skill/reference/components/field-list/examples/sizes.tsx +42 -0
  147. package/dist/skill/reference/components/field-list/examples/states.tsx +51 -0
  148. package/dist/skill/reference/components/file-upload/COMPONENT.md +7 -6
  149. package/dist/skill/reference/components/file-upload/examples/custom-body.tsx +2 -1
  150. package/dist/skill/reference/components/file-upload/examples/examples.module.css +1 -7
  151. package/dist/skill/reference/components/file-upload/examples/file-cards.tsx +10 -1
  152. package/dist/skill/reference/components/file-upload/examples/gallery.tsx +2 -2
  153. package/dist/skill/reference/components/file-upload/examples/in-form.tsx +4 -9
  154. package/dist/skill/reference/components/file-upload/examples/overview.tsx +5 -1
  155. package/dist/skill/reference/components/file-upload/examples/row-parts.tsx +24 -1
  156. package/dist/skill/{patterns/media-library.module.css → reference/components/file-upload/examples/screen.module.css} +2 -23
  157. package/dist/skill/reference/components/file-upload/examples/screen.tsx +646 -0
  158. package/dist/skill/reference/components/file-upload/examples/states.tsx +6 -2
  159. package/dist/skill/reference/components/file-upload/examples/validation.tsx +11 -2
  160. package/dist/skill/reference/components/file-upload/examples/variants.tsx +3 -20
  161. package/dist/skill/reference/components/gantt/COMPONENT.md +2 -1
  162. package/dist/skill/reference/components/gantt/examples/screen.module.css +14 -0
  163. package/dist/skill/{patterns/schedule.tsx → reference/components/gantt/examples/screen.tsx} +174 -170
  164. package/dist/skill/reference/components/gantt/examples/states.tsx +6 -2
  165. package/dist/skill/reference/components/input/COMPONENT.md +2 -2
  166. package/dist/skill/reference/components/input/examples/examples.module.css +2 -13
  167. package/dist/skill/reference/components/input/examples/in-form.tsx +1 -9
  168. package/dist/skill/reference/components/input/examples/password-strength.tsx +34 -8
  169. package/dist/skill/reference/components/input/examples/states.tsx +6 -1
  170. package/dist/skill/reference/components/kanban/COMPONENT.md +16 -11
  171. package/dist/skill/reference/components/kanban/examples/columns.tsx +8 -5
  172. package/dist/skill/reference/components/kanban/examples/limits.tsx +2 -1
  173. package/dist/skill/reference/components/kanban/examples/screen.module.css +17 -0
  174. package/dist/skill/{patterns/kanban-board.tsx → reference/components/kanban/examples/screen.tsx} +132 -172
  175. package/dist/skill/reference/components/kanban/examples/states.tsx +17 -6
  176. package/dist/skill/reference/components/kanban/examples/variants.tsx +16 -8
  177. package/dist/skill/reference/components/list/COMPONENT.md +1 -1
  178. package/dist/skill/reference/components/login-form/COMPONENT.md +6 -5
  179. package/dist/skill/reference/components/login-form/examples/examples.module.css +2 -21
  180. package/dist/skill/reference/components/login-form/examples/forgot-password.tsx +28 -32
  181. package/dist/skill/reference/components/login-form/examples/narrow.tsx +1 -1
  182. package/dist/skill/reference/components/login-form/examples/overview.tsx +45 -47
  183. package/dist/skill/reference/components/login-form/examples/register.tsx +64 -68
  184. package/dist/skill/reference/components/login-form/examples/reset-password.tsx +50 -47
  185. package/dist/skill/reference/components/login-form/examples/sizes.tsx +4 -6
  186. package/dist/skill/reference/components/login-form/examples/states.tsx +53 -57
  187. package/dist/skill/reference/components/login-form/examples/structure.tsx +18 -22
  188. package/dist/skill/reference/components/login-form/examples/verification-code.tsx +41 -45
  189. package/dist/skill/reference/components/media-viewer/COMPONENT.md +3 -3
  190. package/dist/skill/reference/components/media-viewer/examples/dismiss.tsx +5 -1
  191. package/dist/skill/reference/components/message/COMPONENT.md +6 -5
  192. package/dist/skill/reference/components/message/examples/file.tsx +5 -1
  193. package/dist/skill/reference/components/message/examples/media-open.tsx +48 -0
  194. package/dist/skill/reference/components/message/examples/status.tsx +21 -3
  195. package/dist/skill/reference/components/message/examples/text-formatting.tsx +7 -1
  196. package/dist/skill/reference/components/modal/COMPONENT.md +2 -1
  197. package/dist/skill/reference/components/modal/examples/custom-container.tsx +20 -20
  198. package/dist/skill/reference/components/modal/examples/dismiss.tsx +5 -3
  199. package/dist/skill/reference/components/modal/examples/enter-key.tsx +116 -0
  200. package/dist/skill/reference/components/modal/examples/examples.module.css +7 -13
  201. package/dist/skill/reference/components/modal/examples/structure.tsx +5 -2
  202. package/dist/skill/reference/components/native-select/COMPONENT.md +1 -1
  203. package/dist/skill/reference/components/native-select/examples/states.tsx +5 -1
  204. package/dist/skill/reference/components/notification/COMPONENT.md +2 -1
  205. package/dist/skill/reference/components/notification/examples/dismiss.tsx +2 -2
  206. package/dist/skill/reference/components/page-content/COMPONENT.md +71 -14
  207. package/dist/skill/reference/components/page-content/examples/grid.tsx +107 -0
  208. package/dist/skill/reference/components/page-content/examples/list-detail.tsx +0 -3
  209. package/dist/skill/reference/components/page-content/examples/overview.tsx +2 -2
  210. package/dist/skill/{patterns/settings-page.module.css → reference/components/page-content/examples/screen.module.css} +1 -21
  211. package/dist/skill/{patterns/settings-page.tsx → reference/components/page-content/examples/screen.tsx} +61 -82
  212. package/dist/skill/reference/components/page-content/examples/sections.tsx +81 -0
  213. package/dist/skill/reference/components/page-content/examples/variants.tsx +4 -11
  214. package/dist/skill/reference/components/page-toolbar/COMPONENT.md +18 -16
  215. package/dist/skill/reference/components/page-toolbar/examples/narrow.tsx +6 -3
  216. package/dist/skill/reference/components/pagination/examples/controlled.tsx +29 -29
  217. package/dist/skill/reference/components/pagination/examples/examples.module.css +0 -2
  218. package/dist/skill/reference/components/progress-bar/COMPONENT.md +1 -1
  219. package/dist/skill/reference/components/progress-bar/examples/segments.tsx +2 -2
  220. package/dist/skill/reference/components/progress-circle/COMPONENT.md +1 -1
  221. package/dist/skill/reference/components/progress-circle/examples/segments.tsx +8 -3
  222. package/dist/skill/reference/components/radio/COMPONENT.md +1 -0
  223. package/dist/skill/reference/components/radio/examples/examples.module.css +14 -0
  224. package/dist/skill/reference/components/radio/examples/in-form.tsx +45 -0
  225. package/dist/skill/reference/components/scroll-container/COMPONENT.md +1 -0
  226. package/dist/skill/reference/components/scroll-container/examples/auto-scroll.tsx +3 -3
  227. package/dist/skill/reference/components/scroll-container/examples/chat.tsx +3 -3
  228. package/dist/skill/reference/components/scroll-container/examples/edges.tsx +6 -3
  229. package/dist/skill/reference/components/scroll-container/examples/examples.module.css +4 -17
  230. package/dist/skill/reference/components/scroll-container/examples/load-more.tsx +51 -0
  231. package/dist/skill/reference/components/scroll-container/examples/lock.tsx +3 -5
  232. package/dist/skill/reference/components/scroll-container/examples/overscroll.tsx +3 -3
  233. package/dist/skill/reference/components/scroll-container/examples/overview.tsx +3 -3
  234. package/dist/skill/reference/components/scroll-container/examples/scrollbar.tsx +13 -7
  235. package/dist/skill/reference/components/scroll-container/examples/variants.tsx +13 -7
  236. package/dist/skill/reference/components/segmented-control/COMPONENT.md +3 -2
  237. package/dist/skill/reference/components/segmented-control/examples/in-form.tsx +5 -1
  238. package/dist/skill/reference/components/segmented-control/examples/states.tsx +10 -1
  239. package/dist/skill/reference/components/select/COMPONENT.md +5 -3
  240. package/dist/skill/reference/components/select/examples/examples.module.css +2 -7
  241. package/dist/skill/reference/components/select/examples/icon-only.tsx +38 -0
  242. package/dist/skill/reference/components/select/examples/states.tsx +13 -1
  243. package/dist/skill/reference/components/sheet/COMPONENT.md +2 -0
  244. package/dist/skill/reference/components/sheet/examples/guard.tsx +72 -0
  245. package/dist/skill/reference/components/sheet/examples/header-actions.tsx +56 -0
  246. package/dist/skill/reference/components/slider/COMPONENT.md +2 -1
  247. package/dist/skill/reference/components/slider/examples/examples.module.css +8 -0
  248. package/dist/skill/reference/components/slider/examples/in-form.tsx +47 -0
  249. package/dist/skill/reference/components/slider/examples/states.tsx +4 -1
  250. package/dist/skill/reference/components/smart-filter/COMPONENT.md +1 -1
  251. package/dist/skill/reference/components/smart-filter/examples/controlled.tsx +3 -3
  252. package/dist/skill/reference/components/smart-filter/examples/ranges.tsx +44 -10
  253. package/dist/skill/reference/components/sparkline/COMPONENT.md +83 -30
  254. package/dist/skill/reference/components/sparkline/examples/compact.tsx +1 -1
  255. package/dist/skill/reference/components/sparkline/examples/curve.tsx +28 -0
  256. package/dist/skill/reference/components/sparkline/examples/gaps.tsx +33 -0
  257. package/dist/skill/reference/components/sparkline/examples/overview.tsx +11 -2
  258. package/dist/skill/reference/components/sparkline/examples/period.tsx +7 -2
  259. package/dist/skill/reference/components/sparkline/examples/reference.tsx +38 -0
  260. package/dist/skill/reference/components/sparkline/examples/variants.tsx +2 -2
  261. package/dist/skill/reference/components/tabs/COMPONENT.md +1 -1
  262. package/dist/skill/reference/components/tabs/examples/examples.module.css +0 -6
  263. package/dist/skill/reference/components/tabs/examples/in-drawer.tsx +11 -13
  264. package/dist/skill/reference/components/tabs/examples/sizes.tsx +1 -1
  265. package/dist/skill/reference/components/tag-select/COMPONENT.md +1 -1
  266. package/dist/skill/reference/components/tag-select/examples/states.tsx +8 -1
  267. package/dist/skill/reference/components/textarea/COMPONENT.md +1 -1
  268. package/dist/skill/reference/components/textarea/examples/examples.module.css +0 -6
  269. package/dist/skill/reference/components/textarea/examples/in-form.tsx +1 -9
  270. package/dist/skill/reference/components/textarea/examples/states.tsx +2 -1
  271. package/dist/skill/reference/components/thumbnail/COMPONENT.md +2 -1
  272. package/dist/skill/reference/components/thumbnail/examples/examples.module.css +1 -1
  273. package/dist/skill/reference/components/thumbnail/examples/fit.tsx +24 -0
  274. package/dist/skill/reference/components/thumbnail/examples/video.tsx +20 -1
  275. package/dist/skill/reference/components/timeline/COMPONENT.md +1 -1
  276. package/dist/skill/reference/components/timeline/examples/examples.module.css +0 -8
  277. package/dist/skill/reference/components/timeline/examples/links.tsx +55 -14
  278. package/dist/skill/reference/components/timeline/examples/narrow.tsx +2 -2
  279. package/dist/skill/reference/components/timeline/examples/sizes.tsx +3 -3
  280. package/dist/skill/reference/components/timeline/examples/variants.tsx +4 -4
  281. package/dist/skill/reference/components/tooltip/COMPONENT.md +7 -5
  282. package/dist/skill/reference/components/tooltip/examples/placement.tsx +2 -1
  283. package/dist/skill/reference/components/tooltip/examples/toolbar.tsx +2 -2
  284. package/dist/skill/reference/components/typography/examples/weights.tsx +3 -0
  285. package/dist/skill/reference/components/video-note/COMPONENT.md +3 -3
  286. package/dist/skill/reference/components/video-note/examples/controlled.tsx +19 -2
  287. package/dist/skill/reference/components/video-note/examples/in-message.tsx +5 -2
  288. package/dist/skill/reference/components/visually-hidden/COMPONENT.md +2 -1
  289. package/dist/skill/reference/components/visually-hidden/examples/assertive.tsx +39 -0
  290. package/dist/skill/reference/components/voice-player/COMPONENT.md +3 -3
  291. package/dist/skill/reference/components/voice-player/examples/call-recording.tsx +19 -9
  292. package/dist/skill/reference/components/voice-player/examples/controlled.tsx +20 -3
  293. package/dist/skill/reference/layout/app-header/COMPONENT.md +46 -63
  294. package/dist/skill/reference/layout/app-header/examples/breadcrumbs.tsx +10 -9
  295. package/dist/skill/reference/layout/app-header/examples/examples.module.css +1 -1
  296. package/dist/skill/reference/layout/app-header/examples/in-app-shell.tsx +2 -3
  297. package/dist/skill/reference/layout/app-header/examples/narrow.tsx +4 -5
  298. package/dist/skill/reference/layout/app-header/examples/overview.tsx +8 -10
  299. package/dist/skill/reference/layout/app-header/examples/page-title.tsx +3 -10
  300. package/dist/skill/reference/layout/app-shell/COMPONENT.md +5 -4
  301. package/dist/skill/reference/layout/app-shell/examples/footer.tsx +2 -2
  302. package/dist/skill/reference/layout/app-shell/examples/overview.tsx +17 -32
  303. package/dist/skill/{patterns/app-shell.module.css → reference/layout/app-shell/examples/screen.module.css} +1 -8
  304. package/dist/skill/reference/layout/app-shell/examples/screen.tsx +262 -0
  305. package/dist/skill/reference/layout/app-shell/examples/template.tsx +31 -11
  306. package/dist/skill/reference/layout/bottom-nav/examples/floating-action.tsx +2 -2
  307. package/dist/skill/reference/layout/bottom-nav/examples/floating.tsx +2 -2
  308. package/dist/skill/reference/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
  309. package/dist/skill/reference/layout/sidebar/COMPONENT.md +7 -4
  310. package/dist/skill/reference/layout/sidebar/examples/account.tsx +2 -2
  311. package/dist/skill/reference/layout/sidebar/examples/collapsible-groups.tsx +12 -4
  312. package/dist/skill/reference/layout/sidebar/examples/custom-part.tsx +53 -0
  313. package/dist/skill/reference/layout/sidebar/examples/examples.module.css +5 -0
  314. package/dist/skill/reference/layout/sidebar/examples/narrow.tsx +53 -0
  315. package/dist/skill/reference/layout/sidebar/examples/persist.tsx +57 -0
  316. package/dist/skill/reference/layout/sidebar/examples/router.tsx +14 -2
  317. package/dist/skill/reference/layout/sidebar/examples/structure.tsx +7 -2
  318. package/dist/skill/responsive.md +7 -5
  319. package/dist/skill/ux.md +145 -0
  320. package/dist/tokens/semantic.d.ts +2 -0
  321. package/package.json +1 -1
  322. package/src/components/avatar/COMPONENT.md +4 -4
  323. package/src/components/avatar/examples/presence.tsx +1 -1
  324. package/src/components/avatar/examples/states.tsx +5 -5
  325. package/src/components/badge/examples/applied-filters.tsx +13 -19
  326. package/src/components/badge/examples/examples.module.css +1 -8
  327. package/src/components/badge/examples/server-tags.tsx +2 -6
  328. package/src/components/banner/COMPONENT.md +6 -6
  329. package/src/components/banner/examples/dismissible.tsx +22 -11
  330. package/src/components/banner/examples/examples.module.css +4 -8
  331. package/src/components/banner/examples/narrow.tsx +1 -1
  332. package/src/components/banner/examples/page-strip.tsx +16 -22
  333. package/src/components/breadcrumb/COMPONENT.md +5 -4
  334. package/src/components/breadcrumb/examples/ellipsis.tsx +2 -2
  335. package/src/components/breadcrumb/examples/overflow.tsx +1 -1
  336. package/src/components/button-group/COMPONENT.md +2 -2
  337. package/src/components/button-group/examples/in-form.tsx +22 -2
  338. package/src/components/button-group/examples/states.tsx +10 -1
  339. package/src/components/card/COMPONENT.md +7 -5
  340. package/src/components/card/examples/examples.module.css +0 -28
  341. package/src/components/card/examples/kpi-media.tsx +13 -11
  342. package/src/components/card/examples/narrow.tsx +1 -1
  343. package/src/components/card/examples/panel-chart.tsx +45 -22
  344. package/src/components/card/examples/screen.module.css +14 -0
  345. package/src/components/card/examples/screen.tsx +362 -0
  346. package/src/components/card/examples/variants.tsx +15 -1
  347. package/src/components/chart-frame/COMPONENT.md +12 -8
  348. package/src/components/chart-frame/examples/fill-height.tsx +119 -0
  349. package/src/components/chart-frame/examples/states.tsx +3 -1
  350. package/src/components/chart-frame/examples/tooltip.tsx +20 -24
  351. package/src/components/chat/COMPONENT.md +6 -4
  352. package/src/components/chat/examples/group-chat.tsx +15 -2
  353. package/src/components/chat/examples/reactions.tsx +121 -0
  354. package/src/components/chat/examples/screen.module.css +9 -0
  355. package/src/components/chat/examples/screen.tsx +718 -0
  356. package/src/components/chat/examples/search.tsx +1 -1
  357. package/src/components/chat-list/COMPONENT.md +2 -1
  358. package/src/components/chat-list/examples/links.tsx +72 -0
  359. package/src/components/checkbox/COMPONENT.md +1 -1
  360. package/src/components/checkbox/examples/examples.module.css +5 -1
  361. package/src/components/checkbox/examples/indicator.tsx +37 -9
  362. package/src/components/checkbox/examples/states.tsx +6 -1
  363. package/src/components/color-field/COMPONENT.md +1 -1
  364. package/src/components/color-picker/COMPONENT.md +6 -5
  365. package/src/components/color-picker/examples/controlled-open.tsx +37 -0
  366. package/src/components/color-picker/examples/presets.tsx +2 -2
  367. package/src/components/color-picker/examples/states.tsx +23 -14
  368. package/src/components/color-swatches/COMPONENT.md +1 -0
  369. package/src/components/composer/COMPONENT.md +2 -1
  370. package/src/components/composer/examples/attach-menu.tsx +78 -0
  371. package/src/components/composer/examples/attachments.tsx +2 -2
  372. package/src/components/crossfade/COMPONENT.md +1 -0
  373. package/src/components/crossfade/examples/screen.module.css +40 -0
  374. package/src/components/crossfade/examples/screen.tsx +197 -0
  375. package/src/components/data-table/COMPONENT.md +3 -2
  376. package/src/components/data-table/examples/detail-panel.tsx +36 -37
  377. package/src/components/data-table/examples/examples.module.css +0 -12
  378. package/src/components/data-table/examples/numeric.tsx +36 -4
  379. package/src/components/data-table/examples/overview.tsx +1 -0
  380. package/src/components/data-table/examples/row-open.tsx +7 -36
  381. package/src/components/data-table/examples/screen.module.css +13 -0
  382. package/src/components/data-table/examples/screen.tsx +354 -0
  383. package/src/components/datepicker/COMPONENT.md +6 -4
  384. package/src/components/datepicker/examples/examples.module.css +2 -6
  385. package/src/components/datepicker/examples/in-form.tsx +47 -55
  386. package/src/components/datepicker/examples/locale.tsx +35 -0
  387. package/src/components/datepicker/examples/range-presets.tsx +11 -2
  388. package/src/components/datepicker/examples/states.tsx +9 -1
  389. package/src/components/description-list/COMPONENT.md +1 -0
  390. package/src/components/description-list/examples/screen.module.css +64 -0
  391. package/src/components/description-list/examples/screen.tsx +214 -0
  392. package/src/components/description-list/examples/structure.tsx +1 -1
  393. package/src/components/digit-input/COMPONENT.md +3 -1
  394. package/src/components/digit-input/examples/states.tsx +3 -1
  395. package/src/components/digit-input/examples/without-focus-ring.tsx +13 -0
  396. package/src/components/divider/examples/with-icon.tsx +2 -2
  397. package/src/components/dnd/COMPONENT.md +7 -5
  398. package/src/components/dnd/examples/drop-zones.tsx +82 -49
  399. package/src/components/dnd/examples/examples.module.css +50 -0
  400. package/src/components/dnd/examples/states.tsx +54 -0
  401. package/src/components/dnd/examples/table.tsx +113 -0
  402. package/src/components/drawer/COMPONENT.md +1 -0
  403. package/src/components/drawer/examples/dismiss.tsx +5 -3
  404. package/src/components/drawer/examples/examples.module.css +0 -13
  405. package/src/components/drawer/examples/header-actions.tsx +5 -9
  406. package/src/components/drawer/examples/overview.tsx +6 -18
  407. package/src/components/drawer/examples/screen.module.css +14 -0
  408. package/src/components/drawer/examples/screen.tsx +298 -0
  409. package/src/components/dropdown/examples/examples.module.css +1 -5
  410. package/src/components/empty-page/COMPONENT.md +1 -1
  411. package/src/components/empty-page/examples/region-error.tsx +8 -2
  412. package/src/components/example-frame/COMPONENT.md +3 -2
  413. package/src/components/example-frame/examples/initial-view.tsx +44 -0
  414. package/src/components/field-list/COMPONENT.md +165 -0
  415. package/src/components/field-list/examples/base-row.tsx +76 -0
  416. package/src/components/field-list/examples/controlled.tsx +72 -0
  417. package/src/components/field-list/examples/errors.tsx +88 -0
  418. package/src/components/field-list/examples/examples.module.css +34 -0
  419. package/src/components/field-list/examples/limits.tsx +55 -0
  420. package/src/components/field-list/examples/locked.tsx +139 -0
  421. package/src/components/field-list/examples/narrow.tsx +68 -0
  422. package/src/components/field-list/examples/overview.tsx +66 -0
  423. package/src/components/field-list/examples/reorder.tsx +42 -0
  424. package/src/components/field-list/examples/screen.module.css +18 -0
  425. package/src/components/field-list/examples/screen.tsx +316 -0
  426. package/src/components/field-list/examples/sizes.tsx +42 -0
  427. package/src/components/field-list/examples/states.tsx +51 -0
  428. package/src/components/file-upload/COMPONENT.md +7 -6
  429. package/src/components/file-upload/examples/custom-body.tsx +2 -1
  430. package/src/components/file-upload/examples/examples.module.css +1 -7
  431. package/src/components/file-upload/examples/file-cards.tsx +10 -1
  432. package/src/components/file-upload/examples/gallery.tsx +2 -2
  433. package/src/components/file-upload/examples/in-form.tsx +4 -9
  434. package/src/components/file-upload/examples/overview.tsx +5 -1
  435. package/src/components/file-upload/examples/row-parts.tsx +24 -1
  436. package/src/components/file-upload/examples/screen.module.css +45 -0
  437. package/src/components/file-upload/examples/screen.tsx +646 -0
  438. package/src/components/file-upload/examples/states.tsx +6 -2
  439. package/src/components/file-upload/examples/validation.tsx +11 -2
  440. package/src/components/file-upload/examples/variants.tsx +3 -20
  441. package/src/components/gantt/COMPONENT.md +2 -1
  442. package/src/components/gantt/examples/screen.module.css +14 -0
  443. package/src/components/gantt/examples/screen.tsx +726 -0
  444. package/src/components/gantt/examples/states.tsx +6 -2
  445. package/src/components/input/COMPONENT.md +2 -2
  446. package/src/components/input/examples/examples.module.css +2 -13
  447. package/src/components/input/examples/in-form.tsx +1 -9
  448. package/src/components/input/examples/password-strength.tsx +34 -8
  449. package/src/components/input/examples/states.tsx +6 -1
  450. package/src/components/kanban/COMPONENT.md +16 -11
  451. package/src/components/kanban/examples/columns.tsx +8 -5
  452. package/src/components/kanban/examples/limits.tsx +2 -1
  453. package/src/components/kanban/examples/screen.module.css +17 -0
  454. package/src/components/kanban/examples/screen.tsx +572 -0
  455. package/src/components/kanban/examples/states.tsx +17 -6
  456. package/src/components/kanban/examples/variants.tsx +16 -8
  457. package/src/components/list/COMPONENT.md +1 -1
  458. package/src/components/login-form/COMPONENT.md +6 -5
  459. package/src/components/login-form/examples/examples.module.css +2 -21
  460. package/src/components/login-form/examples/forgot-password.tsx +28 -32
  461. package/src/components/login-form/examples/narrow.tsx +1 -1
  462. package/src/components/login-form/examples/overview.tsx +45 -47
  463. package/src/components/login-form/examples/register.tsx +64 -68
  464. package/src/components/login-form/examples/reset-password.tsx +50 -47
  465. package/src/components/login-form/examples/sizes.tsx +4 -6
  466. package/src/components/login-form/examples/states.tsx +53 -57
  467. package/src/components/login-form/examples/structure.tsx +18 -22
  468. package/src/components/login-form/examples/verification-code.tsx +41 -45
  469. package/src/components/media-viewer/COMPONENT.md +3 -3
  470. package/src/components/media-viewer/examples/dismiss.tsx +5 -1
  471. package/src/components/message/COMPONENT.md +6 -5
  472. package/src/components/message/examples/file.tsx +5 -1
  473. package/src/components/message/examples/media-open.tsx +48 -0
  474. package/src/components/message/examples/status.tsx +21 -3
  475. package/src/components/message/examples/text-formatting.tsx +7 -1
  476. package/src/components/modal/COMPONENT.md +2 -1
  477. package/src/components/modal/examples/custom-container.tsx +20 -20
  478. package/src/components/modal/examples/dismiss.tsx +5 -3
  479. package/src/components/modal/examples/enter-key.tsx +116 -0
  480. package/src/components/modal/examples/examples.module.css +7 -13
  481. package/src/components/modal/examples/structure.tsx +5 -2
  482. package/src/components/native-select/COMPONENT.md +1 -1
  483. package/src/components/native-select/examples/states.tsx +5 -1
  484. package/src/components/notification/COMPONENT.md +2 -1
  485. package/src/components/notification/examples/dismiss.tsx +2 -2
  486. package/src/components/page-content/COMPONENT.md +71 -14
  487. package/src/components/page-content/examples/grid.tsx +107 -0
  488. package/src/components/page-content/examples/list-detail.tsx +0 -3
  489. package/src/components/page-content/examples/overview.tsx +2 -2
  490. package/src/components/page-content/examples/screen.module.css +27 -0
  491. package/src/components/page-content/examples/screen.tsx +196 -0
  492. package/src/components/page-content/examples/sections.tsx +81 -0
  493. package/src/components/page-content/examples/variants.tsx +4 -11
  494. package/src/components/page-toolbar/COMPONENT.md +18 -16
  495. package/src/components/page-toolbar/examples/narrow.tsx +6 -3
  496. package/src/components/pagination/examples/controlled.tsx +29 -29
  497. package/src/components/pagination/examples/examples.module.css +0 -2
  498. package/src/components/progress-bar/COMPONENT.md +1 -1
  499. package/src/components/progress-bar/examples/segments.tsx +2 -2
  500. package/src/components/progress-circle/COMPONENT.md +1 -1
  501. package/src/components/progress-circle/examples/segments.tsx +8 -3
  502. package/src/components/radio/COMPONENT.md +1 -0
  503. package/src/components/radio/examples/examples.module.css +14 -0
  504. package/src/components/radio/examples/in-form.tsx +45 -0
  505. package/src/components/scroll-container/COMPONENT.md +1 -0
  506. package/src/components/scroll-container/examples/auto-scroll.tsx +3 -3
  507. package/src/components/scroll-container/examples/chat.tsx +3 -3
  508. package/src/components/scroll-container/examples/edges.tsx +6 -3
  509. package/src/components/scroll-container/examples/examples.module.css +4 -17
  510. package/src/components/scroll-container/examples/load-more.tsx +51 -0
  511. package/src/components/scroll-container/examples/lock.tsx +3 -5
  512. package/src/components/scroll-container/examples/overscroll.tsx +3 -3
  513. package/src/components/scroll-container/examples/overview.tsx +3 -3
  514. package/src/components/scroll-container/examples/scrollbar.tsx +13 -7
  515. package/src/components/scroll-container/examples/variants.tsx +13 -7
  516. package/src/components/segmented-control/COMPONENT.md +3 -2
  517. package/src/components/segmented-control/examples/in-form.tsx +5 -1
  518. package/src/components/segmented-control/examples/states.tsx +10 -1
  519. package/src/components/select/COMPONENT.md +5 -3
  520. package/src/components/select/examples/examples.module.css +2 -7
  521. package/src/components/select/examples/icon-only.tsx +38 -0
  522. package/src/components/select/examples/states.tsx +13 -1
  523. package/src/components/sheet/COMPONENT.md +2 -0
  524. package/src/components/sheet/examples/guard.tsx +72 -0
  525. package/src/components/sheet/examples/header-actions.tsx +56 -0
  526. package/src/components/slider/COMPONENT.md +2 -1
  527. package/src/components/slider/examples/examples.module.css +8 -0
  528. package/src/components/slider/examples/in-form.tsx +47 -0
  529. package/src/components/slider/examples/states.tsx +4 -1
  530. package/src/components/smart-filter/COMPONENT.md +1 -1
  531. package/src/components/smart-filter/examples/controlled.tsx +3 -3
  532. package/src/components/smart-filter/examples/ranges.tsx +44 -10
  533. package/src/components/sparkline/COMPONENT.md +83 -30
  534. package/src/components/sparkline/examples/compact.tsx +1 -1
  535. package/src/components/sparkline/examples/curve.tsx +28 -0
  536. package/src/components/sparkline/examples/gaps.tsx +33 -0
  537. package/src/components/sparkline/examples/overview.tsx +11 -2
  538. package/src/components/sparkline/examples/period.tsx +7 -2
  539. package/src/components/sparkline/examples/reference.tsx +38 -0
  540. package/src/components/sparkline/examples/variants.tsx +2 -2
  541. package/src/components/tabs/COMPONENT.md +1 -1
  542. package/src/components/tabs/examples/examples.module.css +0 -6
  543. package/src/components/tabs/examples/in-drawer.tsx +11 -13
  544. package/src/components/tabs/examples/sizes.tsx +1 -1
  545. package/src/components/tag-select/COMPONENT.md +1 -1
  546. package/src/components/tag-select/examples/states.tsx +8 -1
  547. package/src/components/textarea/COMPONENT.md +1 -1
  548. package/src/components/textarea/examples/examples.module.css +0 -6
  549. package/src/components/textarea/examples/in-form.tsx +1 -9
  550. package/src/components/textarea/examples/states.tsx +2 -1
  551. package/src/components/thumbnail/COMPONENT.md +2 -1
  552. package/src/components/thumbnail/examples/examples.module.css +1 -1
  553. package/src/components/thumbnail/examples/fit.tsx +24 -0
  554. package/src/components/thumbnail/examples/video.tsx +20 -1
  555. package/src/components/timeline/COMPONENT.md +1 -1
  556. package/src/components/timeline/examples/examples.module.css +0 -8
  557. package/src/components/timeline/examples/links.tsx +55 -14
  558. package/src/components/timeline/examples/narrow.tsx +2 -2
  559. package/src/components/timeline/examples/sizes.tsx +3 -3
  560. package/src/components/timeline/examples/variants.tsx +4 -4
  561. package/src/components/tooltip/COMPONENT.md +7 -5
  562. package/src/components/tooltip/examples/placement.tsx +2 -1
  563. package/src/components/tooltip/examples/toolbar.tsx +2 -2
  564. package/src/components/typography/examples/weights.tsx +3 -0
  565. package/src/components/video-note/COMPONENT.md +3 -3
  566. package/src/components/video-note/examples/controlled.tsx +19 -2
  567. package/src/components/video-note/examples/in-message.tsx +5 -2
  568. package/src/components/visually-hidden/COMPONENT.md +2 -1
  569. package/src/components/visually-hidden/examples/assertive.tsx +39 -0
  570. package/src/components/voice-player/COMPONENT.md +3 -3
  571. package/src/components/voice-player/examples/call-recording.tsx +19 -9
  572. package/src/components/voice-player/examples/controlled.tsx +20 -3
  573. package/src/layout/app-header/COMPONENT.md +46 -63
  574. package/src/layout/app-header/examples/breadcrumbs.tsx +10 -9
  575. package/src/layout/app-header/examples/examples.module.css +1 -1
  576. package/src/layout/app-header/examples/in-app-shell.tsx +2 -3
  577. package/src/layout/app-header/examples/narrow.tsx +4 -5
  578. package/src/layout/app-header/examples/overview.tsx +8 -10
  579. package/src/layout/app-header/examples/page-title.tsx +3 -10
  580. package/src/layout/app-shell/COMPONENT.md +5 -4
  581. package/src/layout/app-shell/examples/footer.tsx +2 -2
  582. package/src/layout/app-shell/examples/overview.tsx +17 -32
  583. package/src/layout/app-shell/examples/screen.module.css +11 -0
  584. package/src/layout/app-shell/examples/screen.tsx +262 -0
  585. package/src/layout/app-shell/examples/template.tsx +31 -11
  586. package/src/layout/bottom-nav/examples/floating-action.tsx +2 -2
  587. package/src/layout/bottom-nav/examples/floating.tsx +2 -2
  588. package/src/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
  589. package/src/layout/sidebar/COMPONENT.md +7 -4
  590. package/src/layout/sidebar/examples/account.tsx +2 -2
  591. package/src/layout/sidebar/examples/collapsible-groups.tsx +12 -4
  592. package/src/layout/sidebar/examples/custom-part.tsx +53 -0
  593. package/src/layout/sidebar/examples/examples.module.css +5 -0
  594. package/src/layout/sidebar/examples/narrow.tsx +53 -0
  595. package/src/layout/sidebar/examples/persist.tsx +57 -0
  596. package/src/layout/sidebar/examples/router.tsx +14 -2
  597. package/src/layout/sidebar/examples/structure.tsx +7 -2
  598. package/src/styles/theme-light.css +1 -0
  599. package/dist/skill/patterns/app-shell.tsx +0 -301
  600. package/dist/skill/patterns/chat.module.css +0 -8
  601. package/dist/skill/patterns/dashboard.module.css +0 -44
  602. package/dist/skill/patterns/dashboard.tsx +0 -326
  603. package/dist/skill/patterns/detail-page.tsx +0 -209
  604. package/dist/skill/patterns/form-drawer.tsx +0 -240
  605. package/dist/skill/patterns/kanban-board.module.css +0 -28
  606. package/dist/skill/patterns/media-library.tsx +0 -638
  607. package/dist/skill/patterns/schedule.module.css +0 -22
  608. package/dist/skill/patterns/screen-states.tsx +0 -186
  609. /package/dist/skill/{patterns/form-drawer.module.css → reference/components/drawer/examples/screen.module.css} +0 -0
@@ -1,7 +1,7 @@
1
- /** A support messenger on `Chat`: dialogs beside the conversation (one pane at a time on a phone), history that loads above as you scroll up, dates and runs from data, every kind of message, search, pinned messages, replies and edits from the menu with a jump to the quoted message, read receipts and unread counts from what was seen, the typing signal both ways, and the Composer whose messages rise into the list while the client answers. */
1
+ /** A support messenger as a work screen: the title and the unread count in the app header, the dialogs with a search over them beside the conversation (one pane at a time on a phone), history that loads above as you scroll up, the unread band, reply and edit from the menu, the typing signal both ways, unread counts from what was seen, and the Composer whose messages rise into the list while the client answers — `items`, `renderMessage`, `hasOlder`, `onLoadOlder`, `typing`. */
2
2
  import {
3
+ AppHeader,
3
4
  Avatar,
4
- Button,
5
5
  Card,
6
6
  Chat,
7
7
  ChatList,
@@ -15,29 +15,21 @@ import {
15
15
  hueOf,
16
16
  Icon,
17
17
  Message,
18
- type MessageReaction,
19
18
  type MessageStatus,
20
- type MessageUser,
21
19
  PageContent,
22
20
  type UploadContext,
23
21
  useUploadQueue,
24
- VideoNote,
25
22
  VoicePlayer,
26
23
  } from "prime-ui-kit";
27
24
  import * as React from "react";
28
25
 
29
- import styles from "./chat.module.css";
26
+ import styles from "./screen.module.css";
30
27
 
31
28
  type Content =
32
29
  | { kind: "text"; text: string }
33
30
  | { kind: "media"; items: GalleryItem[]; caption?: string }
34
- | { kind: "voice"; src: string; waveform: number[]; duration: number; transcribable?: boolean }
35
- | { kind: "videoNote"; src: string; duration: number; transcript?: string }
36
- | { kind: "file"; name: string; size: number; href: string }
37
- | { kind: "location"; title: string; address: string }
38
- | { kind: "contact"; name: string; phone: string }
39
- | { kind: "link"; text: string; href: string; site: string; title: string; description: string }
40
- | { kind: "service"; text: string };
31
+ | { kind: "voice"; src: string; waveform: number[]; duration: number }
32
+ | { kind: "file"; name: string; size: number; href: string };
41
33
 
42
34
  type ChatMessage = Content & {
43
35
  id: string;
@@ -45,14 +37,15 @@ type ChatMessage = Content & {
45
37
  sentAt: Date;
46
38
  status?: MessageStatus;
47
39
  edited?: boolean;
48
- forwardedFrom?: string;
49
40
  replyTo?: string;
50
- reactions?: MessageReaction[];
51
41
  };
52
42
 
53
43
  type Dialog = {
54
44
  id: string;
55
45
  name: string;
46
+ contact: string;
47
+ /** The contact in the dative, for «Ответ Ирине Беловой». */
48
+ contactTo: string;
56
49
  initials: string;
57
50
  unread: number;
58
51
  preview: string;
@@ -62,40 +55,12 @@ type Dialog = {
62
55
  const NOW = new Date(2026, 9, 8, 15, 0);
63
56
  const at = (day: number, hour: number, minute: number) => new Date(2026, 9, day, hour, minute);
64
57
 
65
- const AUDIO = "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3";
66
- const VIDEO = "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4";
67
- const MAP = "https://tile.openstreetmap.org/15/19808/10244.png";
68
- const WAVE = [
69
- 0.2, 0.4, 0.7, 0.5, 0.9, 0.6, 0.3, 0.5, 0.8, 0.6, 0.35, 0.55, 0.75, 0.4, 0.25, 0.6, 0.85, 0.5,
70
- 0.3, 0.45, 0.65, 0.4, 0.2,
71
- ];
72
-
73
- /** The reader (the support agent) and the client's contact, as reactors of a chip. */
74
- const ME: MessageUser = {
75
- id: "me",
76
- name: "Вы",
77
- src: "https://images.unsplash.com/photo-1599566150163-29194dcaad36?w=128&h=128&fit=crop",
78
- };
79
- const CLIENT: MessageUser = {
80
- id: "irina",
81
- name: "Ирина Белова",
82
- src: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=128&h=128&fit=crop",
83
- };
84
-
85
- /** The client's reaction to the reply. */
86
- const LIKE: MessageReaction = { emoji: "👍", count: 1, users: [CLIENT] };
87
-
88
- const photo = (seed: string, width: number, height: number, alt: string): GalleryItem => ({
89
- src: `https://picsum.photos/seed/${seed}/${width}/${height}`,
90
- width,
91
- height,
92
- alt,
93
- });
94
-
95
58
  const DIALOGS: Dialog[] = [
96
59
  {
97
60
  id: "vector",
98
61
  name: "ООО «Вектор»",
62
+ contact: "Ирина Белова",
63
+ contactTo: "Ирине Беловой",
99
64
  initials: "ВК",
100
65
  unread: 2,
101
66
  preview: "Ок, жду акт",
@@ -104,6 +69,8 @@ const DIALOGS: Dialog[] = [
104
69
  {
105
70
  id: "granit",
106
71
  name: "ООО «Гранит»",
72
+ contact: "Олег Савин",
73
+ contactTo: "Олегу Савину",
107
74
  initials: "ГР",
108
75
  unread: 0,
109
76
  preview: "Акт сверки подписан",
@@ -112,6 +79,8 @@ const DIALOGS: Dialog[] = [
112
79
  {
113
80
  id: "kozlov",
114
81
  name: "ИП Козлов",
82
+ contact: "Андрей Козлов",
83
+ contactTo: "Андрею Козлову",
115
84
  initials: "ИК",
116
85
  unread: 1,
117
86
  preview: "Подключите ЭДО",
@@ -145,14 +114,20 @@ const HISTORY: ChatMessage[] = [
145
114
  sentAt: at(7, 10, 12),
146
115
  kind: "text",
147
116
  text: "Не можем выгрузить счёт **INV-2048** в 1С, ошибка после «Экспорт».",
148
- reactions: [{ emoji: "👀", count: 1, selected: true, users: [ME] }],
149
117
  },
150
118
  {
151
119
  id: "m2",
152
120
  from: "client",
153
121
  sentAt: at(7, 10, 13),
154
122
  kind: "media",
155
- items: [photo("export-error", 800, 520, "Окно с ошибкой экспорта")],
123
+ items: [
124
+ {
125
+ src: "https://picsum.photos/seed/export-error/800/520",
126
+ width: 800,
127
+ height: 520,
128
+ alt: "Окно с ошибкой экспорта",
129
+ },
130
+ ],
156
131
  caption: "Вот так выглядит",
157
132
  },
158
133
  {
@@ -161,69 +136,26 @@ const HISTORY: ChatMessage[] = [
161
136
  sentAt: at(7, 10, 20),
162
137
  status: "read",
163
138
  kind: "text",
164
- text: "Похоже, в карточке не заполнен ИНН. Инструкция: https://prime.app/wiki/requisites",
139
+ text: "Похоже, в карточке контрагента не заполнен ИНН. Инструкция: https://prime.app/wiki/requisites",
165
140
  },
166
141
  {
167
142
  id: "m4",
168
- from: "me",
169
- sentAt: at(7, 10, 21),
170
- status: "read",
171
- kind: "link",
172
- text: "И статья о выгрузке:",
173
- href: "https://prime.app/blog/export-1c",
174
- site: "Блог Prime",
175
- title: "Выгрузка счетов в 1С за пять минут",
176
- description: "Настройка обмена, реквизиты контрагента и типичные ошибки экспорта.",
177
- },
178
- {
179
- id: "s1",
180
- from: "me",
181
- sentAt: at(8, 9, 0),
182
- kind: "service",
183
- text: "Ирина Белова добавила Дмитрия Орлова",
184
- },
185
- {
186
- id: "m5",
187
143
  from: "client",
188
144
  sentAt: at(8, 9, 40),
189
- kind: "media",
190
- items: [
191
- photo("dock-1", 600, 800, "Рампа 1"),
192
- photo("dock-2", 800, 600, "Рампа 2"),
193
- photo("dock-3", 800, 600, "Рампа 3"),
194
- ],
195
- },
196
- {
197
- id: "m6",
198
- from: "client",
199
- sentAt: at(8, 9, 41),
200
- kind: "videoNote",
201
- src: VIDEO,
202
- duration: 6,
203
- transcript: "Вот рампа номер два, машина встанет сюда задним ходом.",
204
- },
205
- {
206
- id: "m7",
207
- from: "client",
208
- sentAt: at(8, 9, 43),
209
- kind: "voice",
210
- src: AUDIO,
211
- waveform: WAVE,
212
- duration: 18,
213
- transcribable: true,
145
+ kind: "text",
146
+ text: "Заполнили, счёт выгрузился. Пришлите, пожалуйста, договор на второй склад.",
214
147
  },
215
148
  {
216
- id: "m8",
149
+ id: "m5",
217
150
  from: "me",
218
151
  sentAt: at(8, 10, 5),
219
152
  status: "read",
220
- replyTo: "m7",
153
+ replyTo: "m4",
221
154
  kind: "text",
222
- text: "Понял про вторую рампу. Высылаю договор и адрес склада.",
223
- reactions: [LIKE],
155
+ text: "Высылаю договор, акт подготовлю до пятницы.",
224
156
  },
225
157
  {
226
- id: "m9",
158
+ id: "m6",
227
159
  from: "me",
228
160
  sentAt: at(8, 10, 6),
229
161
  status: "read",
@@ -233,28 +165,16 @@ const HISTORY: ChatMessage[] = [
233
165
  href: "https://prime.app/files/contract-418.pdf",
234
166
  },
235
167
  {
236
- id: "m10",
237
- from: "me",
238
- sentAt: at(8, 10, 6),
239
- status: "read",
240
- kind: "location",
241
- title: "Склад «Центральный»",
242
- address: "Москва, ул. Складочная, 1, стр. 6",
243
- },
244
- {
245
- id: "m11",
168
+ id: "m7",
246
169
  from: "client",
247
170
  sentAt: at(8, 14, 30),
248
- forwardedFrom: "Дмитрий Орлов",
249
- kind: "contact",
250
- name: "Дмитрий Орлов",
251
- phone: "+7 916 204-18-77",
171
+ kind: "text",
172
+ text: "Подписали, скан у бухгалтерии.",
252
173
  },
253
- { id: "m12", from: "client", sentAt: at(8, 14, 31), kind: "text", text: "Ок, жду акт" },
174
+ { id: "m8", from: "client", sentAt: at(8, 14, 31), kind: "text", text: "Ок, жду акт" },
254
175
  ];
255
176
 
256
- const FIRST_UNREAD = "m11";
257
- const PINNED = ["m9"];
177
+ const FIRST_UNREAD = "m7";
258
178
 
259
179
  /** What the client answers, one after another. */
260
180
  const CLIENT_REPLIES = [
@@ -268,7 +188,6 @@ const MESSAGE_READ_MS = 1500;
268
188
  const CLIENT_TYPING_MS = 1800;
269
189
  const HISTORY_MS = 900;
270
190
  const DIALOG_MS = 800;
271
- const TRANSCRIBE_MS = 1400;
272
191
 
273
192
  /** A stand-in for the file server: sends an attachment in a few steps. */
274
193
  function sendFile(file: File, { signal, onProgress }: UploadContext): Promise<string> {
@@ -290,29 +209,26 @@ function sendFile(file: File, { signal, onProgress }: UploadContext): Promise<st
290
209
 
291
210
  const wait = (ms: number) => new Promise<void>((resolve) => window.setTimeout(resolve, ms));
292
211
 
293
- /** A stand-in for the speech service: the voice message's text, asked for on its first open. */
294
- const transcribeVoice = () =>
295
- wait(TRANSCRIBE_MS).then(
296
- () => "Машина будет в девять, водитель позвонит за полчаса. Пропуск заказан на рампу два.",
297
- );
212
+ /** «1 непрочитанный», «3 непрочитанных». */
213
+ const unreadLabel = (count: number) => {
214
+ const tens = count % 100;
215
+ const ones = count % 10;
216
+ const word = ones === 1 && tens !== 11 ? "непрочитанный" : "непрочитанных";
217
+ return count === 0 ? "Всё прочитано" : `${count} ${word}`;
218
+ };
298
219
 
299
220
  const excerpt = (message: ChatMessage) => {
300
221
  switch (message.kind) {
301
222
  case "text":
302
- case "link":
303
223
  return message.text;
304
224
  case "voice":
305
225
  return "Голосовое сообщение";
306
- case "videoNote":
307
- return "Видеосообщение";
308
226
  case "media":
309
227
  return (
310
228
  message.caption ?? (message.items.every((item) => item.type === "video") ? "Видео" : "Фото")
311
229
  );
312
230
  case "file":
313
231
  return message.name;
314
- default:
315
- return "Сообщение";
316
232
  }
317
233
  };
318
234
 
@@ -327,44 +243,15 @@ const albumsOf = (media: readonly ComposerMediaItem[]) =>
327
243
  const localSourcesOf = (message: Content): string[] =>
328
244
  (message.kind === "media"
329
245
  ? message.items.map((item) => item.src)
330
- : message.kind === "voice" || message.kind === "videoNote"
246
+ : message.kind === "voice"
331
247
  ? [message.src]
332
248
  : []
333
249
  ).filter((src) => src.startsWith("blob:"));
334
250
 
335
- /** Puts the reader's reaction or takes it back, with the reader among its `users`. */
336
- const toggleReactions = (reactions: MessageReaction[], emoji: string): MessageReaction[] =>
337
- reactions.some((reaction) => reaction.emoji === emoji)
338
- ? reactions
339
- .map((reaction) => {
340
- if (reaction.emoji !== emoji) return reaction;
341
- const others = (reaction.users ?? []).filter((user) => user.id !== ME.id);
342
- return {
343
- ...reaction,
344
- selected: !reaction.selected,
345
- count: reaction.count + (reaction.selected ? -1 : 1),
346
- users: reaction.selected ? others : [...others, ME],
347
- };
348
- })
349
- .filter((reaction) => reaction.count > 0)
350
- : [...reactions, { emoji, count: 1, selected: true, users: [ME] }];
351
-
352
251
  const renderContent = (message: ChatMessage) => {
353
252
  switch (message.kind) {
354
253
  case "text":
355
254
  return <Message.Text>{message.text}</Message.Text>;
356
- case "link":
357
- return (
358
- <>
359
- <Message.Text>{message.text}</Message.Text>
360
- <Message.LinkPreview
361
- href={message.href}
362
- site={message.site}
363
- title={message.title}
364
- description={message.description}
365
- />
366
- </>
367
- );
368
255
  case "media":
369
256
  return (
370
257
  <>
@@ -374,43 +261,16 @@ const renderContent = (message: ChatMessage) => {
374
261
  );
375
262
  case "voice":
376
263
  return (
377
- <VoicePlayer
378
- src={message.src}
379
- waveform={message.waveform}
380
- duration={message.duration}
381
- onTranscribe={message.transcribable ? transcribeVoice : undefined}
382
- />
383
- );
384
- case "videoNote":
385
- return (
386
- <VideoNote src={message.src} duration={message.duration} transcript={message.transcript} />
264
+ <VoicePlayer src={message.src} waveform={message.waveform} duration={message.duration} />
387
265
  );
388
266
  case "file":
389
267
  return <Message.File name={message.name} fileSize={message.size} href={message.href} />;
390
- case "location":
391
- return (
392
- <Message.Location
393
- src={MAP}
394
- href="https://www.openstreetmap.org/#map=16/55.7512/37.6184"
395
- title={message.title}
396
- address={message.address}
397
- />
398
- );
399
- case "contact":
400
- return (
401
- <Message.Contact name={message.name} phone={message.phone} color="teal">
402
- <Button.Root variant="soft" tone="neutral" size="s">
403
- Написать
404
- </Button.Root>
405
- </Message.Contact>
406
- );
407
- default:
408
- return null;
409
268
  }
410
269
  };
411
270
 
412
271
  type ChatComposerProps = {
413
272
  replyTo: ChatMessage | null;
273
+ replyAuthor: string;
414
274
  editing: ChatMessage | null;
415
275
  onReplyDismiss: () => void;
416
276
  onEditDismiss: () => void;
@@ -424,6 +284,7 @@ type ChatComposerProps = {
424
284
  /** The Composer with its upload queue: an upload tick re-renders the composer, not the thread. */
425
285
  const ChatComposer = React.memo(function ChatComposer({
426
286
  replyTo,
287
+ replyAuthor,
427
288
  editing,
428
289
  onReplyDismiss,
429
290
  onEditDismiss,
@@ -444,9 +305,8 @@ const ChatComposer = React.memo(function ChatComposer({
444
305
 
445
306
  // Optimistic: every message is in the list at once with `sending`, so the send returns at once
446
307
  // and the field is free for the next one. The bar's `value` says what it answers or edits.
447
- // Photos and videos go as albums in the tray's order with the text as their caption, other
448
- // files as file messages. The tray's previews are revoked after the send, so an album plays from
449
- // its own URLs of the files (the thread lets them go with the message).
308
+ // Photos and videos go as albums with the text as their caption, other files as file messages.
309
+ // The tray's previews are revoked after the send, so an album plays from its own URLs.
450
310
  const send = ({ text, media, files, replyTo: reply, editOf }: ComposerMessage) => {
451
311
  if (editOf) {
452
312
  onSave(editOf, text);
@@ -496,7 +356,7 @@ const ChatComposer = React.memo(function ChatComposer({
496
356
  <Composer.Attach />
497
357
  {replyTo ? (
498
358
  <Composer.Context value={replyTo.id} onDismiss={onReplyDismiss}>
499
- <Composer.Title>Ответ {replyTo.from === "me" ? "себе" : "Ирине Беловой"}</Composer.Title>
359
+ <Composer.Title>Ответ {replyTo.from === "me" ? "себе" : replyAuthor}</Composer.Title>
500
360
  <Composer.Description>{excerpt(replyTo)}</Composer.Description>
501
361
  </Composer.Context>
502
362
  ) : null}
@@ -517,14 +377,12 @@ const ChatComposer = React.memo(function ChatComposer({
517
377
  );
518
378
  });
519
379
 
520
- export default function ChatPattern() {
380
+ export default function ChatScreenExample() {
521
381
  const [dialogId, setDialogId] = React.useState<string | null>("vector");
522
382
  const [messages, setMessages] = React.useState<ChatMessage[]>(HISTORY);
523
383
  const [hasOlder, setHasOlder] = React.useState(true);
524
384
  const [replyTo, setReplyTo] = React.useState<ChatMessage | null>(null);
525
385
  const [editing, setEditing] = React.useState<ChatMessage | null>(null);
526
- const [selected, setSelected] = React.useState<readonly string[] | null>(null);
527
- const [pinned, setPinned] = React.useState<readonly string[]>(PINNED);
528
386
  const [clientTyping, setClientTyping] = React.useState(false);
529
387
  const [unread, setUnread] = React.useState<Record<string, number>>(() =>
530
388
  Object.fromEntries(DIALOGS.map((item) => [item.id, item.unread])),
@@ -550,6 +408,24 @@ export default function ChatPattern() {
550
408
  };
551
409
  }, []);
552
410
  const dialog = DIALOGS.find((item) => item.id === dialogId) ?? DIALOGS[0];
411
+ const unreadTotal = Object.values(unread).reduce((sum, count) => sum + count, 0);
412
+ /** The search over the dialogs: by name and by the last message a row shows. */
413
+ const [dialogQuery, setDialogQuery] = React.useState("");
414
+ // The open dialog shows its live last message; the others their stored one.
415
+ const lastOf = (item: Dialog) =>
416
+ item.id === dialogId ? messages[messages.length - 1] : undefined;
417
+ const previewOf = (item: Dialog) => {
418
+ const last = lastOf(item);
419
+ return last ? excerpt(last) : item.preview;
420
+ };
421
+ const needle = dialogQuery.trim().toLowerCase();
422
+ const foundDialogs = needle
423
+ ? DIALOGS.filter(
424
+ (item) =>
425
+ item.name.toLowerCase().includes(needle) ||
426
+ previewOf(item).toLowerCase().includes(needle),
427
+ )
428
+ : DIALOGS;
553
429
  /** The dialog whose history has arrived: opening another one loads it first. */
554
430
  const [loadedId, setLoadedId] = React.useState<string | null>(null);
555
431
  React.useEffect(() => {
@@ -643,25 +519,11 @@ export default function ChatPattern() {
643
519
  setReplyTo(message);
644
520
  }, []);
645
521
 
646
- const togglePin = React.useCallback(
647
- (id: string) =>
648
- setPinned((current) =>
649
- current.includes(id) ? current.filter((item) => item !== id) : [...current, id],
650
- ),
651
- [],
652
- );
653
-
654
522
  const reportActivity = React.useCallback((activity: ComposerActivity | null) => {
655
523
  // A real chat sends it over its socket; here the simulated client reads it.
656
524
  myActivity.current = activity;
657
525
  }, []);
658
526
 
659
- const toggleReaction = React.useCallback(
660
- (id: string, emoji: string) =>
661
- patch(id, (message) => ({ reactions: toggleReactions(message.reactions ?? [], emoji) })),
662
- [patch],
663
- );
664
-
665
527
  const remove = React.useCallback(
666
528
  (id: string) => setMessages((current) => current.filter((item) => item.id !== id)),
667
529
  [],
@@ -670,21 +532,16 @@ export default function ChatPattern() {
670
532
  const dismissReply = React.useCallback(() => setReplyTo(null), []);
671
533
  const dismissEdit = React.useCallback(() => setEditing(null), []);
672
534
 
673
- const pinnedItems = pinned.flatMap((id) => {
674
- const message = messages.find((item) => item.id === id);
675
- return message ? [{ value: id, text: excerpt(message) }] : [];
676
- });
677
-
678
535
  // The newest messages for what a row looks up (a reply's original), without making every row
679
536
  // render again when one message changes.
680
537
  const messagesRef = React.useRef(messages);
681
538
  messagesRef.current = messages;
539
+ const contact = dialog.contact;
682
540
 
683
- // A message renders again only when its data, its place or this function change: a reaction, a
684
- // status or an upload tick re-renders the one message it touches.
541
+ // A message renders again only when its data, its place or this function change: a status or an
542
+ // upload tick re-renders the one message it touches.
685
543
  const renderMessage = React.useCallback(
686
544
  (message: ChatMessage) => {
687
- if (message.kind === "service") return <Chat.Service>{message.text}</Chat.Service>;
688
545
  const own = message.from === "me";
689
546
  const original = message.replyTo
690
547
  ? messagesRef.current.find((item) => item.id === message.replyTo)
@@ -695,19 +552,13 @@ export default function ChatPattern() {
695
552
  time={message.sentAt}
696
553
  status={message.status}
697
554
  edited={message.edited}
698
- onReactionToggle={(emoji) => toggleReaction(message.id, emoji)}
699
555
  >
700
- {message.forwardedFrom ? <Message.Forwarded from={message.forwardedFrom} /> : null}
701
556
  {original ? (
702
- <Message.Reply
703
- author={original.from === "me" ? "Вы" : "Ирина Белова"}
704
- target={original.id}
705
- >
557
+ <Message.Reply author={original.from === "me" ? "Вы" : contact} target={original.id}>
706
558
  {excerpt(original)}
707
559
  </Message.Reply>
708
560
  ) : null}
709
561
  {renderContent(message)}
710
- {message.reactions?.length ? <Message.Reactions items={message.reactions} /> : null}
711
562
  <Message.Menu>
712
563
  <Dropdown.Item onSelect={() => startReply(message)}>
713
564
  <Dropdown.ItemIcon>
@@ -729,12 +580,6 @@ export default function ChatPattern() {
729
580
  </Dropdown.ItemIcon>
730
581
  Скопировать
731
582
  </Dropdown.Item>
732
- <Dropdown.Item onSelect={() => togglePin(message.id)}>
733
- <Dropdown.ItemIcon>
734
- <Icon name="action.pin" />
735
- </Dropdown.ItemIcon>
736
- {pinned.includes(message.id) ? "Открепить" : "Закрепить"}
737
- </Dropdown.Item>
738
583
  {own ? (
739
584
  <Dropdown.Item tone="danger" onSelect={() => remove(message.id)}>
740
585
  <Dropdown.ItemIcon>
@@ -747,135 +592,127 @@ export default function ChatPattern() {
747
592
  </Message.Root>
748
593
  );
749
594
  },
750
- [pinned, toggleReaction, startReply, startEdit, togglePin, remove],
595
+ [contact, startReply, startEdit, remove],
751
596
  );
752
597
 
753
598
  return (
754
- <PageContent.Root fill>
755
- <PageContent.Header>
756
- <PageContent.Title>Поддержка</PageContent.Title>
757
- </PageContent.Header>
758
- <PageContent.Body>
759
- <PageContent.Split
760
- open={dialogId !== null}
761
- onOpenChange={(next) => {
762
- if (!next) setDialogId(null);
763
- }}
764
- >
765
- <PageContent.List aria-label="Диалоги">
766
- <Card.Root className={styles.paneCard}>
767
- <ChatList.Root
768
- items={DIALOGS}
769
- getKey={(item) => item.id}
770
- value={dialogId}
771
- onValueChange={setDialogId}
772
- now={NOW}
773
- renderItem={(item) => {
774
- // The open dialog shows its live last message; the others their stored one.
775
- const last = item.id === dialogId ? messages[messages.length - 1] : undefined;
776
- return (
777
- <ChatList.Item
778
- time={last?.sentAt ?? item.at}
779
- status={last?.from === "me" ? last.status : undefined}
780
- unread={unread[item.id] ?? 0}
781
- typing={item.id === dialogId && clientTyping}
782
- >
783
- <ChatList.ItemIcon>
784
- <Avatar.Root color={hueOf(item.id)}>
785
- <Avatar.Fallback>{item.initials}</Avatar.Fallback>
786
- {item.id === "vector" ? <Avatar.Status status="online" /> : null}
787
- </Avatar.Root>
788
- </ChatList.ItemIcon>
789
- <ChatList.ItemText>{item.name}</ChatList.ItemText>
790
- <ChatList.ItemDescription author={last?.from === "me" ? "Вы" : undefined}>
791
- {last ? excerpt(last) : item.preview}
792
- </ChatList.ItemDescription>
793
- </ChatList.Item>
794
- );
795
- }}
796
- />
797
- </Card.Root>
798
- </PageContent.List>
799
-
800
- <PageContent.Detail aria-label="Переписка">
801
- <Card.Root className={styles.paneCard}>
802
- <Chat.Root typing={clientTyping} selected={selected} onSelectedChange={setSelected}>
803
- <Chat.Header>
804
- <PageContent.BackButton />
805
- <Avatar.Root color={hueOf(dialog.id)}>
806
- <Avatar.Fallback>{dialog.initials}</Avatar.Fallback>
807
- <Avatar.Status status="online" />
808
- </Avatar.Root>
809
- <Chat.Title>{dialog.name}</Chat.Title>
810
- <Chat.Description>Ирина Белова · в сети</Chat.Description>
811
- <Chat.Actions>
812
- <Chat.SearchButton />
813
- </Chat.Actions>
814
- </Chat.Header>
815
- <Chat.Search />
816
- <Chat.Pinned items={pinnedItems} onRemove={togglePin} />
817
- <Chat.Messages
818
- loading={loadedId !== dialogId}
819
- reader={ME}
820
- items={messages}
821
- getKey={(message) => message.id}
822
- getAuthor={(message) => message.from}
823
- getDate={(message) => message.sentAt}
824
- isService={(message) => message.kind === "service"}
825
- renderMessage={renderMessage}
826
- unread={FIRST_UNREAD}
599
+ <>
600
+ {/* A work screen: in an app this header fills the shell's `header` slot and carries the page —
601
+ the only h1 and one line of data; main has no PageContent.Header. */}
602
+ <AppHeader.Root>
603
+ <AppHeader.Start>
604
+ <AppHeader.Title>
605
+ Поддержка
606
+ <AppHeader.Description>{unreadLabel(unreadTotal)}</AppHeader.Description>
607
+ </AppHeader.Title>
608
+ </AppHeader.Start>
609
+ </AppHeader.Root>
610
+
611
+ <PageContent.Root fill>
612
+ <PageContent.Body>
613
+ <PageContent.Split
614
+ open={dialogId !== null}
615
+ onOpenChange={(next) => {
616
+ if (!next) setDialogId(null);
617
+ }}
618
+ >
619
+ <PageContent.List aria-label="Диалоги">
620
+ <Card.Root className={styles.paneCard}>
621
+ <ChatList.Root
622
+ items={foundDialogs}
623
+ getKey={(item) => item.id}
624
+ value={dialogId}
625
+ onValueChange={setDialogId}
626
+ search={dialogQuery}
627
+ onSearchChange={setDialogQuery}
827
628
  now={NOW}
828
- hasOlder={hasOlder}
829
- onLoadOlder={loadOlder}
830
- onNewMessage={(_, { direction }) => {
831
- if (direction !== "incoming" || !dialogId) return;
832
- setUnread((current) => ({
833
- ...current,
834
- [dialogId]: (current[dialogId] ?? 0) + 1,
835
- }));
836
- }}
837
- onRead={(values) => {
838
- if (!dialogId) return;
839
- setUnread((current) => ({
840
- ...current,
841
- [dialogId]: Math.max(0, (current[dialogId] ?? 0) - values.length),
842
- }));
629
+ renderItem={(item) => {
630
+ const last = lastOf(item);
631
+ return (
632
+ <ChatList.Item
633
+ time={last?.sentAt ?? item.at}
634
+ status={last?.from === "me" ? last.status : undefined}
635
+ unread={unread[item.id] ?? 0}
636
+ typing={item.id === dialogId && clientTyping}
637
+ >
638
+ <ChatList.ItemIcon>
639
+ <Avatar.Root color={hueOf(item.id)}>
640
+ <Avatar.Fallback>{item.initials}</Avatar.Fallback>
641
+ {item.id === "vector" ? <Avatar.Status status="online" /> : null}
642
+ </Avatar.Root>
643
+ </ChatList.ItemIcon>
644
+ <ChatList.ItemText>{item.name}</ChatList.ItemText>
645
+ <ChatList.ItemDescription author={last?.from === "me" ? "Вы" : undefined}>
646
+ {previewOf(item)}
647
+ </ChatList.ItemDescription>
648
+ </ChatList.Item>
649
+ );
843
650
  }}
844
- >
845
- <Chat.SelectionBar>
846
- <Button.Root
847
- variant="soft"
848
- tone="danger"
849
- size="s"
850
- disabled={!selected?.length}
851
- onClick={() => {
852
- setMessages((current) =>
853
- current.filter((item) => !selected?.includes(item.id)),
854
- );
855
- setSelected(null);
856
- }}
857
- >
858
- Удалить
859
- </Button.Root>
860
- </Chat.SelectionBar>
861
- </Chat.Messages>
862
- <Chat.Footer>
863
- <ChatComposer
864
- replyTo={replyTo}
865
- editing={editing}
866
- onReplyDismiss={dismissReply}
867
- onEditDismiss={dismissEdit}
868
- onEditLast={editLast}
869
- onPost={post}
870
- onSave={save}
871
- onActivityChange={reportActivity}
651
+ />
652
+ </Card.Root>
653
+ </PageContent.List>
654
+
655
+ <PageContent.Detail aria-label="Переписка">
656
+ <Card.Root className={styles.paneCard}>
657
+ <Chat.Root typing={clientTyping}>
658
+ <Chat.Header>
659
+ <PageContent.BackButton />
660
+ <Avatar.Root color={hueOf(dialog.id)}>
661
+ <Avatar.Fallback>{dialog.initials}</Avatar.Fallback>
662
+ {dialog.id === "vector" ? <Avatar.Status status="online" /> : null}
663
+ </Avatar.Root>
664
+ <Chat.Title>{dialog.name}</Chat.Title>
665
+ <Chat.Description>{dialog.contact}</Chat.Description>
666
+ <Chat.Actions>
667
+ <Chat.SearchButton />
668
+ </Chat.Actions>
669
+ </Chat.Header>
670
+ <Chat.Search />
671
+ <Chat.Messages
672
+ loading={loadedId !== dialogId}
673
+ items={messages}
674
+ getKey={(message) => message.id}
675
+ getAuthor={(message) => message.from}
676
+ getDate={(message) => message.sentAt}
677
+ renderMessage={renderMessage}
678
+ unread={FIRST_UNREAD}
679
+ now={NOW}
680
+ hasOlder={hasOlder}
681
+ onLoadOlder={loadOlder}
682
+ onNewMessage={(_, { direction }) => {
683
+ if (direction !== "incoming" || !dialogId) return;
684
+ setUnread((current) => ({
685
+ ...current,
686
+ [dialogId]: (current[dialogId] ?? 0) + 1,
687
+ }));
688
+ }}
689
+ onRead={(values) => {
690
+ if (!dialogId) return;
691
+ setUnread((current) => ({
692
+ ...current,
693
+ [dialogId]: Math.max(0, (current[dialogId] ?? 0) - values.length),
694
+ }));
695
+ }}
872
696
  />
873
- </Chat.Footer>
874
- </Chat.Root>
875
- </Card.Root>
876
- </PageContent.Detail>
877
- </PageContent.Split>
878
- </PageContent.Body>
879
- </PageContent.Root>
697
+ <Chat.Footer>
698
+ <ChatComposer
699
+ replyTo={replyTo}
700
+ replyAuthor={dialog.contactTo}
701
+ editing={editing}
702
+ onReplyDismiss={dismissReply}
703
+ onEditDismiss={dismissEdit}
704
+ onEditLast={editLast}
705
+ onPost={post}
706
+ onSave={save}
707
+ onActivityChange={reportActivity}
708
+ />
709
+ </Chat.Footer>
710
+ </Chat.Root>
711
+ </Card.Root>
712
+ </PageContent.Detail>
713
+ </PageContent.Split>
714
+ </PageContent.Body>
715
+ </PageContent.Root>
716
+ </>
880
717
  );
881
718
  }