prime-ui-kit 0.14.0 → 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 (490) hide show
  1. package/README.md +13 -14
  2. package/dist/chunks/{chunk-P6ZO37JM.js → chunk-2IKH55MI.js} +1 -1
  3. package/dist/chunks/{chunk-SYEX7OVT.js → chunk-THFZIHKU.js} +276 -263
  4. package/dist/chunks/{chunk-WXKRUVSE.js → chunk-XJAVS6FH.js} +49 -48
  5. package/dist/color-picker.js +2 -2
  6. package/dist/components/dnd/Dnd.d.ts +1 -1
  7. package/dist/components/login-form/LoginForm.d.ts +5 -1
  8. package/dist/index.css +1 -1
  9. package/dist/index.js +2 -2
  10. package/dist/internal/swatch.d.ts +6 -2
  11. package/dist/layout/app-header/AppHeader.d.ts +9 -28
  12. package/dist/layout/index.d.ts +1 -1
  13. package/dist/skill/SKILL.md +9 -7
  14. package/dist/skill/api-contract.md +2 -2
  15. package/dist/skill/cheatsheet.md +9 -2
  16. package/dist/skill/checklist.md +9 -5
  17. package/dist/skill/choosing.md +7 -9
  18. package/dist/skill/components.md +5 -12
  19. package/dist/skill/composition.md +281 -54
  20. package/dist/skill/foundations.md +1 -1
  21. package/dist/skill/layouts.md +70 -37
  22. package/dist/skill/reference/components/avatar/examples/states.tsx +4 -4
  23. package/dist/skill/reference/components/badge/examples/applied-filters.tsx +13 -19
  24. package/dist/skill/reference/components/badge/examples/examples.module.css +1 -8
  25. package/dist/skill/reference/components/badge/examples/server-tags.tsx +2 -6
  26. package/dist/skill/reference/components/banner/examples/examples.module.css +1 -5
  27. package/dist/skill/reference/components/banner/examples/page-strip.tsx +16 -22
  28. package/dist/skill/reference/components/breadcrumb/COMPONENT.md +4 -3
  29. package/dist/skill/reference/components/breadcrumb/examples/ellipsis.tsx +2 -2
  30. package/dist/skill/reference/components/button-group/COMPONENT.md +2 -2
  31. package/dist/skill/reference/components/button-group/examples/in-form.tsx +22 -2
  32. package/dist/skill/reference/components/button-group/examples/states.tsx +10 -1
  33. package/dist/skill/reference/components/card/COMPONENT.md +2 -1
  34. package/dist/skill/reference/components/card/examples/screen.tsx +362 -0
  35. package/dist/skill/reference/components/card/examples/variants.tsx +15 -1
  36. package/dist/skill/reference/components/chart-frame/COMPONENT.md +2 -1
  37. package/dist/skill/reference/components/chart-frame/examples/fill-height.tsx +119 -0
  38. package/dist/skill/reference/components/chart-frame/examples/states.tsx +3 -1
  39. package/dist/skill/reference/components/chat/COMPONENT.md +3 -1
  40. package/dist/skill/reference/components/chat/examples/group-chat.tsx +15 -2
  41. package/dist/skill/reference/components/chat/examples/reactions.tsx +121 -0
  42. package/dist/skill/reference/components/chat/examples/screen.module.css +9 -0
  43. package/dist/skill/{patterns/chat.tsx → reference/components/chat/examples/screen.tsx} +170 -351
  44. package/dist/skill/reference/components/chat-list/COMPONENT.md +1 -0
  45. package/dist/skill/reference/components/chat-list/examples/links.tsx +72 -0
  46. package/dist/skill/reference/components/checkbox/COMPONENT.md +1 -1
  47. package/dist/skill/reference/components/checkbox/examples/examples.module.css +5 -1
  48. package/dist/skill/reference/components/checkbox/examples/indicator.tsx +13 -7
  49. package/dist/skill/reference/components/checkbox/examples/states.tsx +6 -1
  50. package/dist/skill/reference/components/color-field/COMPONENT.md +1 -1
  51. package/dist/skill/reference/components/color-picker/COMPONENT.md +4 -3
  52. package/dist/skill/reference/components/color-picker/examples/controlled-open.tsx +37 -0
  53. package/dist/skill/reference/components/color-picker/examples/presets.tsx +2 -2
  54. package/dist/skill/reference/components/color-picker/examples/states.tsx +23 -14
  55. package/dist/skill/reference/components/composer/COMPONENT.md +2 -1
  56. package/dist/skill/reference/components/composer/examples/attach-menu.tsx +78 -0
  57. package/dist/skill/reference/components/composer/examples/attachments.tsx +2 -2
  58. package/dist/skill/reference/components/crossfade/COMPONENT.md +1 -0
  59. package/dist/skill/reference/components/crossfade/examples/screen.tsx +197 -0
  60. package/dist/skill/reference/components/data-table/COMPONENT.md +3 -2
  61. package/dist/skill/reference/components/data-table/examples/detail-panel.tsx +36 -37
  62. package/dist/skill/reference/components/data-table/examples/examples.module.css +0 -12
  63. package/dist/skill/reference/components/data-table/examples/numeric.tsx +36 -4
  64. package/dist/skill/reference/components/data-table/examples/overview.tsx +1 -0
  65. package/dist/skill/reference/components/data-table/examples/row-open.tsx +7 -36
  66. package/dist/skill/{patterns/list-page.module.css → reference/components/data-table/examples/screen.module.css} +1 -7
  67. package/dist/skill/{patterns/list-page.tsx → reference/components/data-table/examples/screen.tsx} +84 -64
  68. package/dist/skill/reference/components/datepicker/COMPONENT.md +5 -4
  69. package/dist/skill/reference/components/datepicker/examples/examples.module.css +2 -6
  70. package/dist/skill/reference/components/datepicker/examples/in-form.tsx +47 -55
  71. package/dist/skill/reference/components/datepicker/examples/locale.tsx +35 -0
  72. package/dist/skill/reference/components/datepicker/examples/range-presets.tsx +11 -2
  73. package/dist/skill/reference/components/datepicker/examples/states.tsx +9 -1
  74. package/dist/skill/reference/components/description-list/COMPONENT.md +1 -0
  75. package/dist/skill/{patterns/detail-page.module.css → reference/components/description-list/examples/screen.module.css} +2 -9
  76. package/dist/skill/reference/components/description-list/examples/screen.tsx +214 -0
  77. package/dist/skill/reference/components/description-list/examples/structure.tsx +1 -1
  78. package/dist/skill/reference/components/digit-input/COMPONENT.md +3 -1
  79. package/dist/skill/reference/components/digit-input/examples/states.tsx +3 -1
  80. package/dist/skill/reference/components/digit-input/examples/without-focus-ring.tsx +13 -0
  81. package/dist/skill/reference/components/divider/examples/with-icon.tsx +2 -2
  82. package/dist/skill/reference/components/dnd/COMPONENT.md +4 -2
  83. package/dist/skill/reference/components/dnd/examples/drop-zones.tsx +82 -49
  84. package/dist/skill/reference/components/dnd/examples/examples.module.css +50 -0
  85. package/dist/skill/reference/components/dnd/examples/states.tsx +54 -0
  86. package/dist/skill/reference/components/dnd/examples/table.tsx +113 -0
  87. package/dist/skill/reference/components/drawer/COMPONENT.md +1 -0
  88. package/dist/skill/reference/components/drawer/examples/dismiss.tsx +5 -3
  89. package/dist/skill/reference/components/drawer/examples/examples.module.css +0 -13
  90. package/dist/skill/reference/components/drawer/examples/header-actions.tsx +5 -9
  91. package/dist/skill/reference/components/drawer/examples/overview.tsx +6 -18
  92. package/dist/skill/reference/components/drawer/examples/screen.tsx +298 -0
  93. package/dist/skill/reference/components/dropdown/examples/examples.module.css +1 -5
  94. package/dist/skill/reference/components/empty-page/COMPONENT.md +1 -1
  95. package/dist/skill/reference/components/empty-page/examples/region-error.tsx +8 -2
  96. package/dist/skill/reference/components/example-frame/COMPONENT.md +3 -2
  97. package/dist/skill/reference/components/example-frame/examples/initial-view.tsx +44 -0
  98. package/dist/skill/reference/components/field-list/COMPONENT.md +2 -1
  99. package/dist/skill/reference/components/field-list/examples/errors.tsx +5 -2
  100. package/dist/skill/{patterns/record-editor.tsx → reference/components/field-list/examples/screen.tsx} +3 -43
  101. package/dist/skill/reference/components/file-upload/COMPONENT.md +7 -6
  102. package/dist/skill/reference/components/file-upload/examples/custom-body.tsx +2 -1
  103. package/dist/skill/reference/components/file-upload/examples/examples.module.css +1 -7
  104. package/dist/skill/reference/components/file-upload/examples/file-cards.tsx +10 -1
  105. package/dist/skill/reference/components/file-upload/examples/gallery.tsx +2 -2
  106. package/dist/skill/reference/components/file-upload/examples/in-form.tsx +4 -9
  107. package/dist/skill/reference/components/file-upload/examples/overview.tsx +5 -1
  108. package/dist/skill/reference/components/file-upload/examples/row-parts.tsx +24 -1
  109. package/dist/skill/{patterns/media-library.module.css → reference/components/file-upload/examples/screen.module.css} +2 -1
  110. package/dist/skill/reference/components/file-upload/examples/screen.tsx +646 -0
  111. package/dist/skill/reference/components/file-upload/examples/states.tsx +6 -2
  112. package/dist/skill/reference/components/file-upload/examples/validation.tsx +11 -2
  113. package/dist/skill/reference/components/file-upload/examples/variants.tsx +3 -20
  114. package/dist/skill/reference/components/gantt/COMPONENT.md +2 -1
  115. package/dist/skill/reference/components/gantt/examples/screen.module.css +14 -0
  116. package/dist/skill/{patterns/schedule.tsx → reference/components/gantt/examples/screen.tsx} +174 -170
  117. package/dist/skill/reference/components/gantt/examples/states.tsx +6 -2
  118. package/dist/skill/reference/components/input/COMPONENT.md +2 -2
  119. package/dist/skill/reference/components/input/examples/examples.module.css +0 -6
  120. package/dist/skill/reference/components/input/examples/in-form.tsx +1 -9
  121. package/dist/skill/reference/components/input/examples/password-strength.tsx +34 -8
  122. package/dist/skill/reference/components/input/examples/states.tsx +6 -1
  123. package/dist/skill/reference/components/kanban/COMPONENT.md +3 -2
  124. package/dist/skill/reference/components/kanban/examples/columns.tsx +8 -5
  125. package/dist/skill/reference/components/kanban/examples/screen.module.css +17 -0
  126. package/dist/skill/{patterns/kanban-board.tsx → reference/components/kanban/examples/screen.tsx} +130 -172
  127. package/dist/skill/reference/components/kanban/examples/states.tsx +17 -6
  128. package/dist/skill/reference/components/login-form/COMPONENT.md +6 -5
  129. package/dist/skill/reference/components/login-form/examples/examples.module.css +2 -21
  130. package/dist/skill/reference/components/login-form/examples/forgot-password.tsx +28 -32
  131. package/dist/skill/reference/components/login-form/examples/narrow.tsx +1 -1
  132. package/dist/skill/reference/components/login-form/examples/overview.tsx +45 -47
  133. package/dist/skill/reference/components/login-form/examples/register.tsx +64 -68
  134. package/dist/skill/reference/components/login-form/examples/reset-password.tsx +50 -47
  135. package/dist/skill/reference/components/login-form/examples/sizes.tsx +4 -6
  136. package/dist/skill/reference/components/login-form/examples/states.tsx +53 -57
  137. package/dist/skill/reference/components/login-form/examples/structure.tsx +18 -22
  138. package/dist/skill/reference/components/login-form/examples/verification-code.tsx +41 -45
  139. package/dist/skill/reference/components/media-viewer/COMPONENT.md +1 -1
  140. package/dist/skill/reference/components/media-viewer/examples/dismiss.tsx +5 -1
  141. package/dist/skill/reference/components/message/COMPONENT.md +4 -3
  142. package/dist/skill/reference/components/message/examples/file.tsx +5 -1
  143. package/dist/skill/reference/components/message/examples/media-open.tsx +48 -0
  144. package/dist/skill/reference/components/message/examples/status.tsx +21 -3
  145. package/dist/skill/reference/components/message/examples/text-formatting.tsx +7 -1
  146. package/dist/skill/reference/components/modal/COMPONENT.md +2 -1
  147. package/dist/skill/reference/components/modal/examples/custom-container.tsx +20 -20
  148. package/dist/skill/reference/components/modal/examples/dismiss.tsx +5 -3
  149. package/dist/skill/reference/components/modal/examples/enter-key.tsx +116 -0
  150. package/dist/skill/reference/components/modal/examples/examples.module.css +7 -13
  151. package/dist/skill/reference/components/modal/examples/structure.tsx +5 -2
  152. package/dist/skill/reference/components/native-select/COMPONENT.md +1 -1
  153. package/dist/skill/reference/components/native-select/examples/states.tsx +5 -1
  154. package/dist/skill/reference/components/notification/COMPONENT.md +1 -1
  155. package/dist/skill/reference/components/notification/examples/dismiss.tsx +2 -2
  156. package/dist/skill/reference/components/page-content/COMPONENT.md +1 -0
  157. package/dist/skill/reference/components/page-content/examples/list-detail.tsx +0 -3
  158. package/dist/skill/{patterns/settings-page.tsx → reference/components/page-content/examples/screen.tsx} +3 -3
  159. package/dist/skill/reference/components/page-content/examples/variants.tsx +4 -11
  160. package/dist/skill/reference/components/page-toolbar/COMPONENT.md +17 -15
  161. package/dist/skill/reference/components/page-toolbar/examples/narrow.tsx +6 -3
  162. package/dist/skill/reference/components/pagination/examples/controlled.tsx +29 -29
  163. package/dist/skill/reference/components/pagination/examples/examples.module.css +0 -2
  164. package/dist/skill/reference/components/progress-bar/COMPONENT.md +1 -1
  165. package/dist/skill/reference/components/progress-bar/examples/segments.tsx +2 -2
  166. package/dist/skill/reference/components/progress-circle/COMPONENT.md +1 -1
  167. package/dist/skill/reference/components/progress-circle/examples/segments.tsx +8 -3
  168. package/dist/skill/reference/components/radio/COMPONENT.md +1 -0
  169. package/dist/skill/reference/components/radio/examples/examples.module.css +14 -0
  170. package/dist/skill/reference/components/radio/examples/in-form.tsx +45 -0
  171. package/dist/skill/reference/components/scroll-container/COMPONENT.md +1 -0
  172. package/dist/skill/reference/components/scroll-container/examples/auto-scroll.tsx +3 -3
  173. package/dist/skill/reference/components/scroll-container/examples/chat.tsx +3 -3
  174. package/dist/skill/reference/components/scroll-container/examples/edges.tsx +6 -3
  175. package/dist/skill/reference/components/scroll-container/examples/examples.module.css +4 -17
  176. package/dist/skill/reference/components/scroll-container/examples/load-more.tsx +51 -0
  177. package/dist/skill/reference/components/scroll-container/examples/lock.tsx +3 -5
  178. package/dist/skill/reference/components/scroll-container/examples/overscroll.tsx +3 -3
  179. package/dist/skill/reference/components/scroll-container/examples/overview.tsx +3 -3
  180. package/dist/skill/reference/components/scroll-container/examples/scrollbar.tsx +13 -7
  181. package/dist/skill/reference/components/scroll-container/examples/variants.tsx +13 -7
  182. package/dist/skill/reference/components/segmented-control/COMPONENT.md +2 -2
  183. package/dist/skill/reference/components/segmented-control/examples/in-form.tsx +5 -1
  184. package/dist/skill/reference/components/segmented-control/examples/states.tsx +10 -1
  185. package/dist/skill/reference/components/select/COMPONENT.md +1 -1
  186. package/dist/skill/reference/components/select/examples/examples.module.css +2 -7
  187. package/dist/skill/reference/components/select/examples/states.tsx +13 -1
  188. package/dist/skill/reference/components/sheet/COMPONENT.md +2 -0
  189. package/dist/skill/reference/components/sheet/examples/guard.tsx +72 -0
  190. package/dist/skill/reference/components/sheet/examples/header-actions.tsx +56 -0
  191. package/dist/skill/reference/components/slider/COMPONENT.md +2 -1
  192. package/dist/skill/reference/components/slider/examples/examples.module.css +8 -0
  193. package/dist/skill/reference/components/slider/examples/in-form.tsx +47 -0
  194. package/dist/skill/reference/components/slider/examples/states.tsx +4 -1
  195. package/dist/skill/reference/components/smart-filter/COMPONENT.md +1 -1
  196. package/dist/skill/reference/components/smart-filter/examples/controlled.tsx +3 -3
  197. package/dist/skill/reference/components/smart-filter/examples/ranges.tsx +44 -10
  198. package/dist/skill/reference/components/sparkline/COMPONENT.md +1 -1
  199. package/dist/skill/reference/components/sparkline/examples/reference.tsx +2 -1
  200. package/dist/skill/reference/components/tabs/COMPONENT.md +1 -1
  201. package/dist/skill/reference/components/tabs/examples/sizes.tsx +1 -1
  202. package/dist/skill/reference/components/tag-select/COMPONENT.md +1 -1
  203. package/dist/skill/reference/components/tag-select/examples/states.tsx +8 -1
  204. package/dist/skill/reference/components/textarea/COMPONENT.md +1 -1
  205. package/dist/skill/reference/components/textarea/examples/examples.module.css +0 -6
  206. package/dist/skill/reference/components/textarea/examples/in-form.tsx +1 -9
  207. package/dist/skill/reference/components/textarea/examples/states.tsx +2 -1
  208. package/dist/skill/reference/components/thumbnail/COMPONENT.md +2 -1
  209. package/dist/skill/reference/components/thumbnail/examples/examples.module.css +1 -1
  210. package/dist/skill/reference/components/thumbnail/examples/fit.tsx +24 -0
  211. package/dist/skill/reference/components/thumbnail/examples/video.tsx +20 -1
  212. package/dist/skill/reference/components/timeline/COMPONENT.md +1 -1
  213. package/dist/skill/reference/components/timeline/examples/links.tsx +55 -14
  214. package/dist/skill/reference/components/tooltip/COMPONENT.md +1 -1
  215. package/dist/skill/reference/components/tooltip/examples/toolbar.tsx +2 -2
  216. package/dist/skill/reference/components/typography/examples/weights.tsx +3 -0
  217. package/dist/skill/reference/components/video-note/COMPONENT.md +2 -2
  218. package/dist/skill/reference/components/video-note/examples/controlled.tsx +19 -2
  219. package/dist/skill/reference/components/video-note/examples/in-message.tsx +5 -2
  220. package/dist/skill/reference/components/visually-hidden/COMPONENT.md +2 -1
  221. package/dist/skill/reference/components/visually-hidden/examples/assertive.tsx +39 -0
  222. package/dist/skill/reference/components/voice-player/COMPONENT.md +2 -2
  223. package/dist/skill/reference/components/voice-player/examples/call-recording.tsx +19 -9
  224. package/dist/skill/reference/components/voice-player/examples/controlled.tsx +20 -3
  225. package/dist/skill/reference/layout/app-header/COMPONENT.md +46 -63
  226. package/dist/skill/reference/layout/app-header/examples/breadcrumbs.tsx +10 -9
  227. package/dist/skill/reference/layout/app-header/examples/examples.module.css +1 -1
  228. package/dist/skill/reference/layout/app-header/examples/in-app-shell.tsx +0 -1
  229. package/dist/skill/reference/layout/app-header/examples/narrow.tsx +4 -5
  230. package/dist/skill/reference/layout/app-header/examples/overview.tsx +8 -10
  231. package/dist/skill/reference/layout/app-header/examples/page-title.tsx +3 -10
  232. package/dist/skill/reference/layout/app-shell/COMPONENT.md +4 -3
  233. package/dist/skill/reference/layout/app-shell/examples/overview.tsx +15 -30
  234. package/dist/skill/reference/layout/app-shell/examples/screen.tsx +262 -0
  235. package/dist/skill/reference/layout/app-shell/examples/template.tsx +29 -9
  236. package/dist/skill/reference/layout/sidebar/COMPONENT.md +7 -4
  237. package/dist/skill/reference/layout/sidebar/examples/account.tsx +2 -2
  238. package/dist/skill/reference/layout/sidebar/examples/collapsible-groups.tsx +12 -4
  239. package/dist/skill/reference/layout/sidebar/examples/custom-part.tsx +53 -0
  240. package/dist/skill/reference/layout/sidebar/examples/examples.module.css +5 -0
  241. package/dist/skill/reference/layout/sidebar/examples/narrow.tsx +53 -0
  242. package/dist/skill/reference/layout/sidebar/examples/persist.tsx +57 -0
  243. package/dist/skill/reference/layout/sidebar/examples/router.tsx +14 -2
  244. package/dist/skill/reference/layout/sidebar/examples/structure.tsx +7 -2
  245. package/dist/skill/responsive.md +2 -2
  246. package/package.json +1 -1
  247. package/src/components/avatar/examples/states.tsx +4 -4
  248. package/src/components/badge/examples/applied-filters.tsx +13 -19
  249. package/src/components/badge/examples/examples.module.css +1 -8
  250. package/src/components/badge/examples/server-tags.tsx +2 -6
  251. package/src/components/banner/examples/examples.module.css +1 -5
  252. package/src/components/banner/examples/page-strip.tsx +16 -22
  253. package/src/components/breadcrumb/COMPONENT.md +4 -3
  254. package/src/components/breadcrumb/examples/ellipsis.tsx +2 -2
  255. package/src/components/button-group/COMPONENT.md +2 -2
  256. package/src/components/button-group/examples/in-form.tsx +22 -2
  257. package/src/components/button-group/examples/states.tsx +10 -1
  258. package/src/components/card/COMPONENT.md +2 -1
  259. package/src/components/card/examples/screen.module.css +14 -0
  260. package/src/components/card/examples/screen.tsx +362 -0
  261. package/src/components/card/examples/variants.tsx +15 -1
  262. package/src/components/chart-frame/COMPONENT.md +2 -1
  263. package/src/components/chart-frame/examples/fill-height.tsx +119 -0
  264. package/src/components/chart-frame/examples/states.tsx +3 -1
  265. package/src/components/chat/COMPONENT.md +3 -1
  266. package/src/components/chat/examples/group-chat.tsx +15 -2
  267. package/src/components/chat/examples/reactions.tsx +121 -0
  268. package/src/components/chat/examples/screen.module.css +9 -0
  269. package/src/components/chat/examples/screen.tsx +718 -0
  270. package/src/components/chat-list/COMPONENT.md +1 -0
  271. package/src/components/chat-list/examples/links.tsx +72 -0
  272. package/src/components/checkbox/COMPONENT.md +1 -1
  273. package/src/components/checkbox/examples/examples.module.css +5 -1
  274. package/src/components/checkbox/examples/indicator.tsx +13 -7
  275. package/src/components/checkbox/examples/states.tsx +6 -1
  276. package/src/components/color-field/COMPONENT.md +1 -1
  277. package/src/components/color-picker/COMPONENT.md +4 -3
  278. package/src/components/color-picker/examples/controlled-open.tsx +37 -0
  279. package/src/components/color-picker/examples/presets.tsx +2 -2
  280. package/src/components/color-picker/examples/states.tsx +23 -14
  281. package/src/components/composer/COMPONENT.md +2 -1
  282. package/src/components/composer/examples/attach-menu.tsx +78 -0
  283. package/src/components/composer/examples/attachments.tsx +2 -2
  284. package/src/components/crossfade/COMPONENT.md +1 -0
  285. package/src/components/crossfade/examples/screen.module.css +40 -0
  286. package/src/components/crossfade/examples/screen.tsx +197 -0
  287. package/src/components/data-table/COMPONENT.md +3 -2
  288. package/src/components/data-table/examples/detail-panel.tsx +36 -37
  289. package/src/components/data-table/examples/examples.module.css +0 -12
  290. package/src/components/data-table/examples/numeric.tsx +36 -4
  291. package/src/components/data-table/examples/overview.tsx +1 -0
  292. package/src/components/data-table/examples/row-open.tsx +7 -36
  293. package/src/components/data-table/examples/screen.module.css +13 -0
  294. package/src/components/data-table/examples/screen.tsx +354 -0
  295. package/src/components/datepicker/COMPONENT.md +5 -4
  296. package/src/components/datepicker/examples/examples.module.css +2 -6
  297. package/src/components/datepicker/examples/in-form.tsx +47 -55
  298. package/src/components/datepicker/examples/locale.tsx +35 -0
  299. package/src/components/datepicker/examples/range-presets.tsx +11 -2
  300. package/src/components/datepicker/examples/states.tsx +9 -1
  301. package/src/components/description-list/COMPONENT.md +1 -0
  302. package/src/components/description-list/examples/screen.module.css +64 -0
  303. package/src/components/description-list/examples/screen.tsx +214 -0
  304. package/src/components/description-list/examples/structure.tsx +1 -1
  305. package/src/components/digit-input/COMPONENT.md +3 -1
  306. package/src/components/digit-input/examples/states.tsx +3 -1
  307. package/src/components/digit-input/examples/without-focus-ring.tsx +13 -0
  308. package/src/components/divider/examples/with-icon.tsx +2 -2
  309. package/src/components/dnd/COMPONENT.md +4 -2
  310. package/src/components/dnd/examples/drop-zones.tsx +82 -49
  311. package/src/components/dnd/examples/examples.module.css +50 -0
  312. package/src/components/dnd/examples/states.tsx +54 -0
  313. package/src/components/dnd/examples/table.tsx +113 -0
  314. package/src/components/drawer/COMPONENT.md +1 -0
  315. package/src/components/drawer/examples/dismiss.tsx +5 -3
  316. package/src/components/drawer/examples/examples.module.css +0 -13
  317. package/src/components/drawer/examples/header-actions.tsx +5 -9
  318. package/src/components/drawer/examples/overview.tsx +6 -18
  319. package/src/components/drawer/examples/screen.module.css +14 -0
  320. package/src/components/drawer/examples/screen.tsx +298 -0
  321. package/src/components/dropdown/examples/examples.module.css +1 -5
  322. package/src/components/empty-page/COMPONENT.md +1 -1
  323. package/src/components/empty-page/examples/region-error.tsx +8 -2
  324. package/src/components/example-frame/COMPONENT.md +3 -2
  325. package/src/components/example-frame/examples/initial-view.tsx +44 -0
  326. package/src/components/field-list/COMPONENT.md +2 -1
  327. package/src/components/field-list/examples/errors.tsx +5 -2
  328. package/src/components/field-list/examples/screen.module.css +18 -0
  329. package/src/components/field-list/examples/screen.tsx +316 -0
  330. package/src/components/file-upload/COMPONENT.md +7 -6
  331. package/src/components/file-upload/examples/custom-body.tsx +2 -1
  332. package/src/components/file-upload/examples/examples.module.css +1 -7
  333. package/src/components/file-upload/examples/file-cards.tsx +10 -1
  334. package/src/components/file-upload/examples/gallery.tsx +2 -2
  335. package/src/components/file-upload/examples/in-form.tsx +4 -9
  336. package/src/components/file-upload/examples/overview.tsx +5 -1
  337. package/src/components/file-upload/examples/row-parts.tsx +24 -1
  338. package/src/components/file-upload/examples/screen.module.css +45 -0
  339. package/src/components/file-upload/examples/screen.tsx +646 -0
  340. package/src/components/file-upload/examples/states.tsx +6 -2
  341. package/src/components/file-upload/examples/validation.tsx +11 -2
  342. package/src/components/file-upload/examples/variants.tsx +3 -20
  343. package/src/components/gantt/COMPONENT.md +2 -1
  344. package/src/components/gantt/examples/screen.module.css +14 -0
  345. package/src/components/gantt/examples/screen.tsx +726 -0
  346. package/src/components/gantt/examples/states.tsx +6 -2
  347. package/src/components/input/COMPONENT.md +2 -2
  348. package/src/components/input/examples/examples.module.css +0 -6
  349. package/src/components/input/examples/in-form.tsx +1 -9
  350. package/src/components/input/examples/password-strength.tsx +34 -8
  351. package/src/components/input/examples/states.tsx +6 -1
  352. package/src/components/kanban/COMPONENT.md +3 -2
  353. package/src/components/kanban/examples/columns.tsx +8 -5
  354. package/src/components/kanban/examples/screen.module.css +17 -0
  355. package/src/components/kanban/examples/screen.tsx +572 -0
  356. package/src/components/kanban/examples/states.tsx +17 -6
  357. package/src/components/login-form/COMPONENT.md +6 -5
  358. package/src/components/login-form/examples/examples.module.css +2 -21
  359. package/src/components/login-form/examples/forgot-password.tsx +28 -32
  360. package/src/components/login-form/examples/narrow.tsx +1 -1
  361. package/src/components/login-form/examples/overview.tsx +45 -47
  362. package/src/components/login-form/examples/register.tsx +64 -68
  363. package/src/components/login-form/examples/reset-password.tsx +50 -47
  364. package/src/components/login-form/examples/sizes.tsx +4 -6
  365. package/src/components/login-form/examples/states.tsx +53 -57
  366. package/src/components/login-form/examples/structure.tsx +18 -22
  367. package/src/components/login-form/examples/verification-code.tsx +41 -45
  368. package/src/components/media-viewer/COMPONENT.md +1 -1
  369. package/src/components/media-viewer/examples/dismiss.tsx +5 -1
  370. package/src/components/message/COMPONENT.md +4 -3
  371. package/src/components/message/examples/file.tsx +5 -1
  372. package/src/components/message/examples/media-open.tsx +48 -0
  373. package/src/components/message/examples/status.tsx +21 -3
  374. package/src/components/message/examples/text-formatting.tsx +7 -1
  375. package/src/components/modal/COMPONENT.md +2 -1
  376. package/src/components/modal/examples/custom-container.tsx +20 -20
  377. package/src/components/modal/examples/dismiss.tsx +5 -3
  378. package/src/components/modal/examples/enter-key.tsx +116 -0
  379. package/src/components/modal/examples/examples.module.css +7 -13
  380. package/src/components/modal/examples/structure.tsx +5 -2
  381. package/src/components/native-select/COMPONENT.md +1 -1
  382. package/src/components/native-select/examples/states.tsx +5 -1
  383. package/src/components/notification/COMPONENT.md +1 -1
  384. package/src/components/notification/examples/dismiss.tsx +2 -2
  385. package/src/components/page-content/COMPONENT.md +1 -0
  386. package/src/components/page-content/examples/list-detail.tsx +0 -3
  387. package/src/components/page-content/examples/screen.module.css +27 -0
  388. package/src/components/page-content/examples/screen.tsx +196 -0
  389. package/src/components/page-content/examples/variants.tsx +4 -11
  390. package/src/components/page-toolbar/COMPONENT.md +17 -15
  391. package/src/components/page-toolbar/examples/narrow.tsx +6 -3
  392. package/src/components/pagination/examples/controlled.tsx +29 -29
  393. package/src/components/pagination/examples/examples.module.css +0 -2
  394. package/src/components/progress-bar/COMPONENT.md +1 -1
  395. package/src/components/progress-bar/examples/segments.tsx +2 -2
  396. package/src/components/progress-circle/COMPONENT.md +1 -1
  397. package/src/components/progress-circle/examples/segments.tsx +8 -3
  398. package/src/components/radio/COMPONENT.md +1 -0
  399. package/src/components/radio/examples/examples.module.css +14 -0
  400. package/src/components/radio/examples/in-form.tsx +45 -0
  401. package/src/components/scroll-container/COMPONENT.md +1 -0
  402. package/src/components/scroll-container/examples/auto-scroll.tsx +3 -3
  403. package/src/components/scroll-container/examples/chat.tsx +3 -3
  404. package/src/components/scroll-container/examples/edges.tsx +6 -3
  405. package/src/components/scroll-container/examples/examples.module.css +4 -17
  406. package/src/components/scroll-container/examples/load-more.tsx +51 -0
  407. package/src/components/scroll-container/examples/lock.tsx +3 -5
  408. package/src/components/scroll-container/examples/overscroll.tsx +3 -3
  409. package/src/components/scroll-container/examples/overview.tsx +3 -3
  410. package/src/components/scroll-container/examples/scrollbar.tsx +13 -7
  411. package/src/components/scroll-container/examples/variants.tsx +13 -7
  412. package/src/components/segmented-control/COMPONENT.md +2 -2
  413. package/src/components/segmented-control/examples/in-form.tsx +5 -1
  414. package/src/components/segmented-control/examples/states.tsx +10 -1
  415. package/src/components/select/COMPONENT.md +1 -1
  416. package/src/components/select/examples/examples.module.css +2 -7
  417. package/src/components/select/examples/states.tsx +13 -1
  418. package/src/components/sheet/COMPONENT.md +2 -0
  419. package/src/components/sheet/examples/guard.tsx +72 -0
  420. package/src/components/sheet/examples/header-actions.tsx +56 -0
  421. package/src/components/slider/COMPONENT.md +2 -1
  422. package/src/components/slider/examples/examples.module.css +8 -0
  423. package/src/components/slider/examples/in-form.tsx +47 -0
  424. package/src/components/slider/examples/states.tsx +4 -1
  425. package/src/components/smart-filter/COMPONENT.md +1 -1
  426. package/src/components/smart-filter/examples/controlled.tsx +3 -3
  427. package/src/components/smart-filter/examples/ranges.tsx +44 -10
  428. package/src/components/sparkline/COMPONENT.md +1 -1
  429. package/src/components/sparkline/examples/reference.tsx +2 -1
  430. package/src/components/tabs/COMPONENT.md +1 -1
  431. package/src/components/tabs/examples/sizes.tsx +1 -1
  432. package/src/components/tag-select/COMPONENT.md +1 -1
  433. package/src/components/tag-select/examples/states.tsx +8 -1
  434. package/src/components/textarea/COMPONENT.md +1 -1
  435. package/src/components/textarea/examples/examples.module.css +0 -6
  436. package/src/components/textarea/examples/in-form.tsx +1 -9
  437. package/src/components/textarea/examples/states.tsx +2 -1
  438. package/src/components/thumbnail/COMPONENT.md +2 -1
  439. package/src/components/thumbnail/examples/examples.module.css +1 -1
  440. package/src/components/thumbnail/examples/fit.tsx +24 -0
  441. package/src/components/thumbnail/examples/video.tsx +20 -1
  442. package/src/components/timeline/COMPONENT.md +1 -1
  443. package/src/components/timeline/examples/links.tsx +55 -14
  444. package/src/components/tooltip/COMPONENT.md +1 -1
  445. package/src/components/tooltip/examples/toolbar.tsx +2 -2
  446. package/src/components/typography/examples/weights.tsx +3 -0
  447. package/src/components/video-note/COMPONENT.md +2 -2
  448. package/src/components/video-note/examples/controlled.tsx +19 -2
  449. package/src/components/video-note/examples/in-message.tsx +5 -2
  450. package/src/components/visually-hidden/COMPONENT.md +2 -1
  451. package/src/components/visually-hidden/examples/assertive.tsx +39 -0
  452. package/src/components/voice-player/COMPONENT.md +2 -2
  453. package/src/components/voice-player/examples/call-recording.tsx +19 -9
  454. package/src/components/voice-player/examples/controlled.tsx +20 -3
  455. package/src/layout/app-header/COMPONENT.md +46 -63
  456. package/src/layout/app-header/examples/breadcrumbs.tsx +10 -9
  457. package/src/layout/app-header/examples/examples.module.css +1 -1
  458. package/src/layout/app-header/examples/in-app-shell.tsx +0 -1
  459. package/src/layout/app-header/examples/narrow.tsx +4 -5
  460. package/src/layout/app-header/examples/overview.tsx +8 -10
  461. package/src/layout/app-header/examples/page-title.tsx +3 -10
  462. package/src/layout/app-shell/COMPONENT.md +4 -3
  463. package/src/layout/app-shell/examples/overview.tsx +15 -30
  464. package/src/layout/app-shell/examples/screen.module.css +11 -0
  465. package/src/layout/app-shell/examples/screen.tsx +262 -0
  466. package/src/layout/app-shell/examples/template.tsx +29 -9
  467. package/src/layout/sidebar/COMPONENT.md +7 -4
  468. package/src/layout/sidebar/examples/account.tsx +2 -2
  469. package/src/layout/sidebar/examples/collapsible-groups.tsx +12 -4
  470. package/src/layout/sidebar/examples/custom-part.tsx +53 -0
  471. package/src/layout/sidebar/examples/examples.module.css +5 -0
  472. package/src/layout/sidebar/examples/narrow.tsx +53 -0
  473. package/src/layout/sidebar/examples/persist.tsx +57 -0
  474. package/src/layout/sidebar/examples/router.tsx +14 -2
  475. package/src/layout/sidebar/examples/structure.tsx +7 -2
  476. package/dist/skill/patterns/app-shell.tsx +0 -303
  477. package/dist/skill/patterns/chat.module.css +0 -8
  478. package/dist/skill/patterns/dashboard.tsx +0 -340
  479. package/dist/skill/patterns/detail-page.tsx +0 -206
  480. package/dist/skill/patterns/form-drawer.tsx +0 -240
  481. package/dist/skill/patterns/kanban-board.module.css +0 -28
  482. package/dist/skill/patterns/media-library.tsx +0 -637
  483. package/dist/skill/patterns/schedule.module.css +0 -22
  484. package/dist/skill/patterns/screen-states.tsx +0 -187
  485. /package/dist/skill/{patterns/dashboard.module.css → reference/components/card/examples/screen.module.css} +0 -0
  486. /package/dist/skill/{patterns/screen-states.module.css → reference/components/crossfade/examples/screen.module.css} +0 -0
  487. /package/dist/skill/{patterns/form-drawer.module.css → reference/components/drawer/examples/screen.module.css} +0 -0
  488. /package/dist/skill/{patterns/record-editor.module.css → reference/components/field-list/examples/screen.module.css} +0 -0
  489. /package/dist/skill/{patterns/settings-page.module.css → reference/components/page-content/examples/screen.module.css} +0 -0
  490. /package/dist/skill/{patterns/app-shell.module.css → reference/layout/app-shell/examples/screen.module.css} +0 -0
@@ -0,0 +1,44 @@
1
+ /** A matrix frame that opens at phone width in the dark theme with no theme switch and counts code copies — `previewLayout`, `defaultViewport`, `defaultColorScheme`, `showThemeToggle`, `onCopy`. */
2
+ import { Badge, ExampleFrame, Typography } from "prime-ui-kit";
3
+ import * as React from "react";
4
+
5
+ const STATUSES = [
6
+ { color: "gray", label: "Черновик" },
7
+ { color: "blue", label: "На ревью" },
8
+ { color: "green", label: "Опубликован" },
9
+ ] as const;
10
+
11
+ const CODE = STATUSES.map(
12
+ ({ color, label }) => `<Badge.Root color="${color}">${label}</Badge.Root>`,
13
+ ).join("\n");
14
+
15
+ export default function ExampleFrameInitialViewExample() {
16
+ const [copies, setCopies] = React.useState(0);
17
+
18
+ return (
19
+ <>
20
+ <ExampleFrame
21
+ code={CODE}
22
+ previewLayout="matrix"
23
+ defaultViewport="mobile"
24
+ defaultColorScheme="dark"
25
+ showThemeToggle={false}
26
+ onCopy={() => setCopies((count) => count + 1)}
27
+ >
28
+ <div>
29
+ {STATUSES.map(({ color, label }) => (
30
+ <div key={color}>
31
+ <Badge.Root color={color}>{label}</Badge.Root>
32
+ <Typography as="span" variant="caption" tone="muted">
33
+ {color}
34
+ </Typography>
35
+ </div>
36
+ ))}
37
+ </div>
38
+ </ExampleFrame>
39
+ <Typography variant="body-s" tone="secondary">
40
+ Код скопирован: {copies}
41
+ </Typography>
42
+ </>
43
+ );
44
+ }
@@ -144,10 +144,11 @@ Generic `FieldList<T>`; `ref` → `HTMLDivElement` (the field frame). An editabl
144
144
  | [locked.tsx](examples/locked.tsx) | Specs of a plan on one line each: an icon picker and a color swatch take compact columns, the first three specs are pinned with a lock and the rest reorder below them — `getLocked`, `width`, `reorderable`. |
145
145
  | [base-row.tsx](examples/base-row.tsx) | A plan price and its changes by month in one table: the base price is the first, pinned row, each change is a row with its month and its price, and the unit sits in the field, not in a heading — `getLocked`, `width`. |
146
146
  | [limits.tsx](examples/limits.tsx) | Recipients of invoice reminders, from one to three: the last row cannot be removed and the add button says why it is off once the list is full — `min`, `max`, `hint`. |
147
- | [errors.tsx](examples/errors.tsx) | Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field — `error`. |
147
+ | [errors.tsx](examples/errors.tsx) | Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field; a `*` after a heading marks a required column — `error`, `required`. |
148
148
  | [states.tsx](examples/states.tsx) | The same list editable and disabled while the request saves it: fields, handles and buttons turn off together — `disabled`. |
149
149
  | [controlled.tsx](examples/controlled.tsx) | The parent owns the lines: it sums them under the list and puts the saved lines back on reset — `value`, `onValueChange`. |
150
150
  | [narrow.tsx](examples/narrow.tsx) | The invoice lines in a 320 px column: the headings give way, each row stacks its fields with their own labels and rows stand a group apart — `columns`. |
151
+ | [screen.tsx](examples/screen.tsx) | A record editor as a document page, a long form whose title, description and save stand in the content header: a plan's name, its specs and prices in one form; repeating records as FieldList rows with the headings once, a base price pinned above its changes, one value in three currencies in one row — `getLocked`, `compact`. |
151
152
 
152
153
  ## Mistakes
153
154
  - A `label` above every field of every row («Иконка», «Параметр», «Значение» four times) → a FieldList: the headings stand once, the fields take them as hidden labels.
@@ -1,4 +1,4 @@
1
- /** Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field — `error`. */
1
+ /** Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field; a `*` after a heading marks a required column — `error`, `required`. */
2
2
  import { Button, FieldList, type FieldListColumn, Input } from "prime-ui-kit";
3
3
  import * as React from "react";
4
4
 
@@ -6,7 +6,10 @@ import styles from "./examples.module.css";
6
6
 
7
7
  type Contact = { id: string; role: string; phone: string };
8
8
 
9
- const COLUMNS: FieldListColumn[] = [{ label: "Должность" }, { label: "Телефон", width: "m" }];
9
+ const COLUMNS: FieldListColumn[] = [
10
+ { label: "Должность", required: true },
11
+ { label: "Телефон", width: "m", required: true },
12
+ ];
10
13
 
11
14
  const CONTACTS: Contact[] = [
12
15
  { id: "buyer", role: "Закупщик", phone: "+7 912 404-18-20" },
@@ -0,0 +1,18 @@
1
+ /* Record editor: the sections are PageContent.Section layout="aside"; here only the panels' insides. */
2
+
3
+ /* Two groups in one panel, a group apart. */
4
+ .groups {
5
+ display: grid;
6
+ gap: var(--prime-space-8);
7
+ }
8
+
9
+ /* One value in three currencies: one row while there is room, the unit inside each field. */
10
+ .currencies {
11
+ display: grid;
12
+ grid-template-columns: repeat(
13
+ auto-fit,
14
+ minmax(min(100%, calc(var(--prime-space-24) + var(--prime-space-8))), 1fr)
15
+ );
16
+ align-items: start;
17
+ gap: var(--prime-space-3);
18
+ }
@@ -0,0 +1,316 @@
1
+ /** A record editor as a document page, a long form whose title, description and save stand in the content header: a plan's name, its specs and prices in one form; repeating records as FieldList rows with the headings once, a base price pinned above its changes, one value in three currencies in one row — `getLocked`, `compact`. */
2
+ import {
3
+ Button,
4
+ Card,
5
+ ColorPresets,
6
+ FieldList,
7
+ type FieldListColumn,
8
+ Fieldset,
9
+ Icon,
10
+ type IconName,
11
+ Input,
12
+ PageContent,
13
+ Select,
14
+ Textarea,
15
+ } from "prime-ui-kit";
16
+ import * as React from "react";
17
+
18
+ import styles from "./screen.module.css";
19
+
20
+ type Spec = {
21
+ id: string;
22
+ icon: IconName;
23
+ name: string;
24
+ value: string;
25
+ color: string;
26
+ pinned?: boolean;
27
+ };
28
+ type Period = { id: string; from: string; price: string; base?: boolean };
29
+
30
+ const SPEC_COLUMNS: FieldListColumn[] = [
31
+ { label: "Иконка", width: "compact" },
32
+ { label: "Параметр" },
33
+ { label: "Значение" },
34
+ { label: "Цвет", width: "compact" },
35
+ ];
36
+
37
+ const SPEC_ICONS: { name: IconName; label: string }[] = [
38
+ { name: "object.users", label: "Сотрудники" },
39
+ { name: "object.storage", label: "Хранилище" },
40
+ { name: "object.headset", label: "Поддержка" },
41
+ { name: "object.chart", label: "Отчёты" },
42
+ { name: "object.key", label: "Доступ" },
43
+ { name: "object.globe", label: "Интеграции" },
44
+ ];
45
+
46
+ const SPECS: Spec[] = [
47
+ {
48
+ id: "seats",
49
+ icon: "object.users",
50
+ name: "Сотрудники",
51
+ value: "до 50",
52
+ color: "#5068f5",
53
+ pinned: true,
54
+ },
55
+ {
56
+ id: "storage",
57
+ icon: "object.storage",
58
+ name: "Хранилище",
59
+ value: "200 ГБ",
60
+ color: "#22c55e",
61
+ pinned: true,
62
+ },
63
+ {
64
+ id: "support",
65
+ icon: "object.headset",
66
+ name: "Поддержка",
67
+ value: "8/5, ответ за 2 часа",
68
+ color: "#f97316",
69
+ pinned: true,
70
+ },
71
+ { id: "reports", icon: "object.chart", name: "Отчёты", value: "12 шаблонов", color: "#a855f7" },
72
+ { id: "sso", icon: "object.key", name: "Вход через SSO", value: "SAML, OIDC", color: "#14b8a6" },
73
+ ];
74
+
75
+ const PRICE_COLUMNS: FieldListColumn[] = [{ label: "Действует" }, { label: "Цена", width: "m" }];
76
+
77
+ const MONTHS = [
78
+ { value: "01", label: "С 1 января" },
79
+ { value: "04", label: "С 1 апреля" },
80
+ { value: "07", label: "С 1 июля" },
81
+ { value: "10", label: "С 1 октября" },
82
+ ];
83
+
84
+ const PERIODS: Period[] = [
85
+ { id: "base", from: "", price: "4 900", base: true },
86
+ { id: "autumn", from: "10", price: "5 400" },
87
+ ];
88
+
89
+ const SETUP_FEE = [
90
+ { currency: "₽", name: "setupRub", label: "Подключение в рублях", value: "15 000" },
91
+ { currency: "$", name: "setupUsd", label: "Подключение в долларах", value: "170" },
92
+ { currency: "€", name: "setupEur", label: "Подключение в евро", value: "" },
93
+ ];
94
+
95
+ const SAVE_MS = 900;
96
+ const SAVED_MS = 2000;
97
+
98
+ export default function FieldListScreenExample() {
99
+ const formId = React.useId();
100
+ const [specs, setSpecs] = React.useState(SPECS);
101
+ const [periods, setPeriods] = React.useState(PERIODS);
102
+ const [nameError, setNameError] = React.useState<string>();
103
+ const [saving, setSaving] = React.useState(false);
104
+ const [saved, setSaved] = React.useState(false);
105
+
106
+ const save = (event: React.FormEvent<HTMLFormElement>) => {
107
+ event.preventDefault();
108
+ const name = String(new FormData(event.currentTarget).get("name") ?? "").trim();
109
+ if (name === "") {
110
+ setNameError("Назовите тариф: так его увидят клиенты");
111
+ event.currentTarget.querySelector<HTMLInputElement>("[name='name']")?.focus();
112
+ return;
113
+ }
114
+ setNameError(undefined);
115
+ setSaving(true);
116
+ window.setTimeout(() => {
117
+ setSaving(false);
118
+ setSaved(true);
119
+ window.setTimeout(() => setSaved(false), SAVED_MS);
120
+ }, SAVE_MS);
121
+ };
122
+
123
+ return (
124
+ <PageContent.Root maxWidth="wide" aria-labelledby="plan-title">
125
+ <PageContent.Header>
126
+ <PageContent.Title id="plan-title">Тариф «Команда»</PageContent.Title>
127
+ <PageContent.Description>
128
+ Так тариф выглядит на странице цен и в счетах.
129
+ </PageContent.Description>
130
+ <PageContent.Actions>
131
+ <Button.Root type="submit" form={formId} loading={saving}>
132
+ {saved ? "Сохранено" : "Сохранить тариф"}
133
+ </Button.Root>
134
+ </PageContent.Actions>
135
+ </PageContent.Header>
136
+ <PageContent.Body>
137
+ <PageContent.Section layout="aside" label="Основное">
138
+ <form id={formId} noValidate onSubmit={save}>
139
+ <Card.Root variant="panel">
140
+ <Card.Body>
141
+ <Fieldset disabled={saving} aria-label="Основное">
142
+ <Input.Root label="Название" error={nameError}>
143
+ <Input.Wrapper>
144
+ <Input.Field name="name" defaultValue="Команда" />
145
+ </Input.Wrapper>
146
+ </Input.Root>
147
+ <Textarea.Root
148
+ name="summary"
149
+ label="Описание"
150
+ optional
151
+ rows={2}
152
+ defaultValue="Для отделов до 50 человек: задачи, документы и отчёты в одном месте."
153
+ />
154
+ </Fieldset>
155
+ </Card.Body>
156
+ </Card.Root>
157
+ </form>
158
+ </PageContent.Section>
159
+
160
+ <PageContent.Section layout="aside" label="Характеристики">
161
+ <Card.Root variant="panel">
162
+ <Card.Body>
163
+ <FieldList
164
+ aria-label="Характеристики"
165
+ disabled={saving}
166
+ columns={SPEC_COLUMNS}
167
+ reorderable
168
+ value={specs}
169
+ onValueChange={setSpecs}
170
+ getId={(spec) => spec.id}
171
+ getLabel={(spec) => spec.name}
172
+ getLocked={(spec) => spec.pinned ?? false}
173
+ createItem={(): Spec => ({
174
+ id: crypto.randomUUID(),
175
+ icon: "object.globe",
176
+ name: "",
177
+ value: "",
178
+ color: "#14b8a6",
179
+ })}
180
+ addLabel="Добавить характеристику"
181
+ renderItem={(spec, row) => (
182
+ <>
183
+ <Select.Root
184
+ value={spec.icon}
185
+ onValueChange={(icon) => row.update({ icon: icon as IconName })}
186
+ >
187
+ <Select.Trigger>
188
+ <Select.TriggerIcon>
189
+ <Icon name={spec.icon} />
190
+ </Select.TriggerIcon>
191
+ </Select.Trigger>
192
+ <Select.Content>
193
+ {SPEC_ICONS.map((icon) => (
194
+ <Select.Item key={icon.name} value={icon.name}>
195
+ <Select.ItemIcon>
196
+ <Icon name={icon.name} />
197
+ </Select.ItemIcon>
198
+ {icon.label}
199
+ </Select.Item>
200
+ ))}
201
+ </Select.Content>
202
+ </Select.Root>
203
+ <Input.Root>
204
+ <Input.Wrapper>
205
+ <Input.Field
206
+ value={spec.name}
207
+ onChange={(event) => row.update({ name: event.target.value })}
208
+ />
209
+ </Input.Wrapper>
210
+ </Input.Root>
211
+ <Input.Root>
212
+ <Input.Wrapper>
213
+ <Input.Field
214
+ value={spec.value}
215
+ onChange={(event) => row.update({ value: event.target.value })}
216
+ />
217
+ </Input.Wrapper>
218
+ </Input.Root>
219
+ <ColorPresets.Root
220
+ value={spec.color}
221
+ onValueChange={(color) => row.update({ color: color ?? spec.color })}
222
+ >
223
+ <ColorPresets.Trigger>
224
+ <ColorPresets.SwatchButton />
225
+ </ColorPresets.Trigger>
226
+ <ColorPresets.Content />
227
+ </ColorPresets.Root>
228
+ </>
229
+ )}
230
+ />
231
+ </Card.Body>
232
+ </Card.Root>
233
+ </PageContent.Section>
234
+
235
+ <PageContent.Section layout="aside" label="Стоимость">
236
+ <Card.Root variant="panel">
237
+ <Card.Body className={styles.groups}>
238
+ <Fieldset label="За месяц" disabled={saving}>
239
+ <FieldList
240
+ columns={PRICE_COLUMNS}
241
+ value={periods}
242
+ onValueChange={setPeriods}
243
+ getId={(period) => period.id}
244
+ getLocked={(period) => period.base ?? false}
245
+ createItem={() => ({ id: crypto.randomUUID(), from: "", price: "" })}
246
+ addLabel="Добавить изменение цены"
247
+ renderItem={(period, row) => (
248
+ <>
249
+ {period.base ? (
250
+ <Input.Root>
251
+ <Input.Wrapper>
252
+ <Input.Field value="Всегда, если нет изменений" readOnly />
253
+ </Input.Wrapper>
254
+ </Input.Root>
255
+ ) : (
256
+ <Select.Root
257
+ value={period.from}
258
+ onValueChange={(from) => row.update({ from })}
259
+ placeholder="Выберите месяц"
260
+ >
261
+ <Select.Trigger>
262
+ <Select.Value />
263
+ </Select.Trigger>
264
+ <Select.Content>
265
+ {MONTHS.map((month) => (
266
+ <Select.Item key={month.value} value={month.value}>
267
+ {month.label}
268
+ </Select.Item>
269
+ ))}
270
+ </Select.Content>
271
+ </Select.Root>
272
+ )}
273
+ <Input.Root>
274
+ <Input.Wrapper>
275
+ <Input.Field
276
+ value={period.price}
277
+ inputMode="decimal"
278
+ placeholder="0"
279
+ onChange={(event) => row.update({ price: event.target.value })}
280
+ />
281
+ <Input.InlineAffix side="end">₽</Input.InlineAffix>
282
+ </Input.Wrapper>
283
+ </Input.Root>
284
+ </>
285
+ )}
286
+ />
287
+ </Fieldset>
288
+ <Fieldset
289
+ label="Подключение"
290
+ description="Разовый платёж; пустая валюта не выставляется."
291
+ disabled={saving}
292
+ >
293
+ <div className={styles.currencies}>
294
+ {SETUP_FEE.map((fee) => (
295
+ <Input.Root key={fee.name}>
296
+ <Input.Wrapper>
297
+ <Input.Field
298
+ name={fee.name}
299
+ aria-label={fee.label}
300
+ inputMode="decimal"
301
+ placeholder="0"
302
+ defaultValue={fee.value}
303
+ />
304
+ <Input.InlineAffix side="end">{fee.currency}</Input.InlineAffix>
305
+ </Input.Wrapper>
306
+ </Input.Root>
307
+ ))}
308
+ </div>
309
+ </Fieldset>
310
+ </Card.Body>
311
+ </Card.Root>
312
+ </PageContent.Section>
313
+ </PageContent.Body>
314
+ </PageContent.Root>
315
+ );
316
+ }
@@ -288,7 +288,7 @@ A rejection of `upload` fails the file with its message as the reason; retry que
288
288
  | disabled | `disabled` | `data-disabled="true"`, disabled input, disabled fill and text, drops ignored; no add tile, actions or drag; a disabled button with `trigger="button"` |
289
289
  | empty | no files, `trigger="tile"` | the add tile spans the row with «Нажмите или перетащите файлы» |
290
290
  | cover | `cover`, the first tile | «Обложка» in place of the format pill, `data-cover` on the tiles wrapper (the first tile takes a 2 × 2 cell in a grid) |
291
- | full | the set reaches `max` | `data-full` on the add tile: «Лимит файлов», faded, the file input disabled |
291
+ | full | the set reaches `max` | `data-full` on the add tile: «Лимит файлов», faded; the file input is `aria-disabled` and opens no picker, so the field label stays undimmed |
292
292
  | queued | queue item `status: "queued"` | a row reads «size · В очереди» over an empty bar; a tile (`data-upload="queued"`) dims under a 40px disk on the `media` shade (Button `shape="circle"` `variant="shade"`) whose ring turns at its least arc, described by «В очереди» |
293
293
  | loading | `status: "loading"` | a row reads «size · Загрузка 40%» and its bar fills (`accent`); a tile's white arc grows clockwise from 12 o'clock with the share sent (the `progress` ring of a shade circle Button, one variable `--ring-value`, gliding `base` while it turns); the disk is the remove («Отменить загрузку: name», described by the state), the corner × is not drawn; the tile still reorders, its carried copy keeps the disk |
294
294
  | done | `status: "done"` | a row reads «size» over a full `success` bar; a tile's ring fills, then its disk fades and shrinks to 0.9 (`fast`, `inert`), the picture returns to full or the sheet comes back |
@@ -372,20 +372,21 @@ Also `data-size`, `data-variant` on the zone, `data-size` on Item, `data-status`
372
372
  | Example | Shows |
373
373
  |---|---|
374
374
  | [overview.tsx](examples/overview.tsx) | Documents of a deal: a drop zone, the files already attached as rows whose names open them, and new files uploading through a queue with progress, a reason and a retry — `label`, `hint`, `multiple`, `defaultValue`, `href`, `queue`. |
375
- | [variants.tsx](examples/variants.tsx) | How files are added: the dashed drop zone, the zone with only its fill for cards and modals, the compact picker button and the add tile after the files — `variant`, `trigger`. |
375
+ | [variants.tsx](examples/variants.tsx) | How files are added: the dashed drop zone, the zone with only its fill for cards and modals, the compact picker button and the add tile that starts an empty set of tiles — `variant`, `trigger`. |
376
376
  | [sizes.tsx](examples/sizes.tsx) | Every tier of the zone and of its file rows: padding, icon, button, text and the format badge follow it — `size`. |
377
377
  | [states.tsx](examples/states.tsx) | A default zone, a disabled one whose files are read-only and an invalid one without a message — `disabled`, `invalid`. |
378
378
  | [validation.tsx](examples/validation.tsx) | A required scan checked as soon as it is picked: a wrong type or a large file shakes in an error that leaves when the file is removed; a hint and an optional zone — `required`, `hint`, `error`, `optional`. |
379
- | [gallery.tsx](examples/gallery.tsx) | An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, and the add tile counts up to the limit — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. |
380
- | [file-cards.tsx](examples/file-cards.tsx) | Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`. |
379
+ | [gallery.tsx](examples/gallery.tsx) | An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, one fails and retries, and the add tile counts up to the limit and then says so — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. |
380
+ | [file-cards.tsx](examples/file-cards.tsx) | Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size in megabytes as the report gives it; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`, `formatSize`. |
381
381
  | [attachment-tray.tsx](examples/attachment-tray.tsx) | A reply to a client with a paperclip instead of a drop zone: the icon-only picker button, and the attachments as one scrolling row of tiles above the message — `trigger`, `aria-label`, `FileUpload.Queue`, `layout`. |
382
382
  | [saving.tsx](examples/saving.tsx) | Published listing photos with no picker, every change saved on the server: a moved or removed photo waits busy, and a change the server refuses puts the set back — `FileUpload.Queue`, `onValueChange`, `value`, `cover`. |
383
- | [custom-body.tsx](examples/custom-body.tsx) | A custom body: a muted title with a browse link and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`. |
383
+ | [custom-body.tsx](examples/custom-body.tsx) | A custom body: a muted title with a browse link and the formats line and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`, `FileUpload.Description`. |
384
384
  | [avatar-upload.tsx](examples/avatar-upload.tsx) | A round zone around an Avatar that takes images and shows a preview; buttons open the same input — `inputRef`, `accept`, `className`. |
385
- | [row-parts.tsx](examples/row-parts.tsx) | Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview and a report still being prepared — `FileUpload.Item`, `FileUpload.FormatBadge`, `FileUpload.ItemPreview`, `FileUpload.ItemActions`, `FileUpload.ItemProgress`. |
385
+ | [row-parts.tsx](examples/row-parts.tsx) | Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview, a report still being prepared and one that failed with a retry — `FileUpload.Item`, `FileUpload.FormatBadge`, `FileUpload.ItemPreview`, `FileUpload.ItemActions`, `FileUpload.ItemProgress`, `invalid`, `tone`. |
386
386
  | [controlled.tsx](examples/controlled.tsx) | Documents of a deal in one list: the files already on the server and new uploads after them, saved on every change, and a button brings back the saved set — `value`, `onValueChange`, `queue`. |
387
387
  | [in-form.tsx](examples/in-form.tsx) | A contract upload form: submit checks the required scan, its error shakes in and leaves once a file is picked or removed — `required`, `error`, `name`, `value`. |
388
388
  | [narrow.tsx](examples/narrow.tsx) | In a phone-width column the zone text wraps, a long file name truncates, and a gallery goes three across and then two, the cover keeping two columns and the remove buttons shown without hover. |
389
+ | [screen.tsx](examples/screen.tsx) | A media library of a catalog object as a work screen: the title, the object and a PageToolbar with sections, search, order and upload in the app header; uploads in FileUpload tiles through a queue; a grid of Thumbnails that open MediaViewer out of the tile or are picked for bulk download and delete; a Skeleton first load and a filtered empty state in a Crossfade — `trigger`, `layout`. |
389
390
 
390
391
  ## Mistakes
391
392
  - A `Label` and a `Hint` placed around the zone by hand → pass `label`, `hint`, `error`.
@@ -1,4 +1,4 @@
1
- /** A custom body: a muted title with a browse link and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`. */
1
+ /** A custom body: a muted title with a browse link and the formats line and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`, `FileUpload.Description`. */
2
2
  import { Button, FileUpload, Icon, LinkButton } from "prime-ui-kit";
3
3
  import * as React from "react";
4
4
 
@@ -23,6 +23,7 @@ export default function FileUploadCustomBodyExample() {
23
23
  </button>
24
24
  </LinkButton>
25
25
  </FileUpload.Title>
26
+ <FileUpload.Description>PDF, JPG или PNG до 20 МБ</FileUpload.Description>
26
27
  <div className={styles.sources}>
27
28
  <Button.Root variant="soft" tone="neutral" size="s" onClick={openPicker}>
28
29
  <Button.Icon>
@@ -28,7 +28,7 @@
28
28
  flex: 1;
29
29
  }
30
30
 
31
- /* in-form.tsx: header → field 32 → actions 32 (foundation §1). */
31
+ /* in-form.tsx: field → actions 32 (foundation §1). */
32
32
  .form {
33
33
  display: flex;
34
34
  flex-direction: column;
@@ -36,12 +36,6 @@
36
36
  width: min(100%, var(--prime-modal-width-s));
37
37
  }
38
38
 
39
- .formHeader {
40
- display: flex;
41
- flex-direction: column;
42
- gap: var(--prime-space-1);
43
- }
44
-
45
39
  .formActions {
46
40
  display: flex;
47
41
  justify-content: flex-end;
@@ -1,4 +1,4 @@
1
- /** Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`. */
1
+ /** Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size in megabytes as the report gives it; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`, `formatSize`. */
2
2
  import { FileUpload, type FileUploadFile, type UploadContext, useUploadQueue } from "prime-ui-kit";
3
3
 
4
4
  import styles from "./examples.module.css";
@@ -27,6 +27,14 @@ const MATERIALS: readonly FileUploadFile[] = [
27
27
  { id: "insp-stock", name: "Остатки на 12 марта.xlsx", size: 96_000 },
28
28
  ];
29
29
 
30
+ /** Sizes as the inspection report gives them: megabytes with two decimals. */
31
+ const MEGABYTES = new Intl.NumberFormat("ru-RU", {
32
+ minimumFractionDigits: 2,
33
+ maximumFractionDigits: 2,
34
+ });
35
+
36
+ const formatMegabytes = (bytes: number) => `${MEGABYTES.format(bytes / 1024 / 1024)} МБ`;
37
+
30
38
  /** A stand-in for the server: sends a file in a few steps and answers with its address. */
31
39
  function sendFile(file: File, { signal, onProgress }: UploadContext): Promise<string> {
32
40
  return new Promise((resolve, reject) => {
@@ -58,6 +66,7 @@ export default function FileUploadFileCardsExample() {
58
66
  multiple
59
67
  defaultValue={MATERIALS}
60
68
  queue={queue}
69
+ formatSize={formatMegabytes}
61
70
  />
62
71
  </div>
63
72
  );
@@ -1,4 +1,4 @@
1
- /** An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, and the add tile counts up to the limit — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. */
1
+ /** An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, one fails and retries, and the add tile counts up to the limit and then says so — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. */
2
2
  import { FileUpload, type FileUploadFile, type UploadContext, useUploadQueue } from "prime-ui-kit";
3
3
  import * as React from "react";
4
4
 
@@ -94,7 +94,7 @@ export default function FileUploadGalleryExample() {
94
94
  cover
95
95
  accept="image/*"
96
96
  multiple
97
- max={12}
97
+ max={6}
98
98
  value={photos}
99
99
  onValueChange={setPhotos}
100
100
  queue={queue}
@@ -4,7 +4,9 @@ import * as React from "react";
4
4
 
5
5
  import styles from "./examples.module.css";
6
6
 
7
- const HINT = "PDF до 20 МБ, все страницы";
7
+ const HINT = "Все страницы, с подписями обеих сторон";
8
+ /** The zone names the formats the check takes. */
9
+ const ZONE_LABELS = { description: "PDF до 20 МБ" };
8
10
  const MAX_SIZE = 20 * 1024 * 1024;
9
11
 
10
12
  /** A picked file as a file of the set. */
@@ -44,20 +46,13 @@ export default function FileUploadInFormExample() {
44
46
 
45
47
  return (
46
48
  <form className={styles.form} noValidate onSubmit={submit} onReset={() => change([])}>
47
- <div className={styles.formHeader}>
48
- <Typography as="h3" variant="title-m">
49
- Договор поставки
50
- </Typography>
51
- <Typography as="p" variant="body-s" tone="secondary">
52
- Подписанный скан нужен до первой отгрузки.
53
- </Typography>
54
- </div>
55
49
  <FileUpload.Root
56
50
  label="Скан договора"
57
51
  name="contract"
58
52
  accept=".pdf"
59
53
  required
60
54
  hint={HINT}
55
+ labels={ZONE_LABELS}
61
56
  error={error}
62
57
  value={scan}
63
58
  onValueChange={change}
@@ -5,6 +5,9 @@ import styles from "./examples.module.css";
5
5
 
6
6
  const MAX_SIZE = 10 * 1024 * 1024;
7
7
 
8
+ /** The zone names the limit the stand-in server holds. */
9
+ const ZONE_LABELS = { description: "Любые файлы до 10 МБ" };
10
+
8
11
  const ATTACHED: readonly FileUploadFile[] = [
9
12
  {
10
13
  id: "deal-contract",
@@ -50,7 +53,8 @@ export default function FileUploadOverviewExample() {
50
53
  <div className={styles.column}>
51
54
  <FileUpload.Root
52
55
  label="Документы сделки"
53
- hint="Любые файлы до 10 МБ, можно несколько"
56
+ hint="Договор, смета и акты по сделке; можно несколько сразу"
57
+ labels={ZONE_LABELS}
54
58
  multiple
55
59
  defaultValue={ATTACHED}
56
60
  queue={queue}
@@ -1,4 +1,4 @@
1
- /** Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview and a report still being prepared — `FileUpload.Item`, `FileUpload.FormatBadge`, `FileUpload.ItemPreview`, `FileUpload.ItemActions`, `FileUpload.ItemProgress`. */
1
+ /** Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview, a report still being prepared and one that failed with a retry — `FileUpload.Item`, `FileUpload.FormatBadge`, `FileUpload.ItemPreview`, `FileUpload.ItemActions`, `FileUpload.ItemProgress`, `invalid`, `tone`. */
2
2
  import { Button, FileUpload, Icon } from "prime-ui-kit";
3
3
 
4
4
  import styles from "./examples.module.css";
@@ -36,6 +36,29 @@ export default function FileUploadRowPartsExample() {
36
36
  <FileUpload.ItemDescription>Формируется · 60%</FileUpload.ItemDescription>
37
37
  <FileUpload.ItemProgress value={60} aria-label="Формируется: Отчёт по заказу.xlsx" />
38
38
  </FileUpload.Item>
39
+ <FileUpload.Item invalid>
40
+ <FileUpload.FormatBadge format="pdf" color="red" />
41
+ <FileUpload.ItemName>Акт сверки за март.pdf</FileUpload.ItemName>
42
+ <FileUpload.ItemDescription>
43
+ Не удалось сформировать: нет данных за 31 марта
44
+ </FileUpload.ItemDescription>
45
+ <FileUpload.ItemActions>
46
+ <Button.Root
47
+ variant="ghost"
48
+ tone="neutral"
49
+ aria-label="Сформировать заново: Акт сверки за март.pdf"
50
+ >
51
+ <Button.Icon>
52
+ <Icon name="action.refresh" />
53
+ </Button.Icon>
54
+ </Button.Root>
55
+ </FileUpload.ItemActions>
56
+ <FileUpload.ItemProgress
57
+ value={35}
58
+ tone="danger"
59
+ aria-label="Остановлено: Акт сверки за март.pdf"
60
+ />
61
+ </FileUpload.Item>
39
62
  </div>
40
63
  );
41
64
  }