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
@@ -1,637 +0,0 @@
1
- /** A media library of a catalog object: PageToolbar with sections, search, order and upload; 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. */
2
- import {
3
- Button,
4
- ConfirmDialog,
5
- Crossfade,
6
- EmptyPage,
7
- FileUpload,
8
- formatFileSize,
9
- Icon,
10
- MediaViewer,
11
- type MediaViewerItem,
12
- PageContent,
13
- PageToolbar,
14
- SegmentedControl,
15
- Select,
16
- Skeleton,
17
- SmartFilter,
18
- Thumbnail,
19
- Typography,
20
- type UploadContext,
21
- type UploadItem,
22
- useNotifications,
23
- useUploadQueue,
24
- } from "prime-ui-kit";
25
- import * as React from "react";
26
-
27
- import styles from "./media-library.module.css";
28
-
29
- type Kind = "photo" | "video" | "document";
30
- type Section = "all" | Kind;
31
- type Order = "new" | "old" | "name";
32
-
33
- type Media = {
34
- id: string;
35
- kind: Kind;
36
- name: string;
37
- /** The full file: the picture, the video or the scan the viewer shows. */
38
- src: string;
39
- /** A small copy for the grid; the viewer shows it at once while `src` loads. */
40
- thumbnail?: string;
41
- width?: number;
42
- height?: number;
43
- size: number;
44
- added: string;
45
- };
46
-
47
- const CLIP = "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4";
48
-
49
- const photo = (seed: string): Pick<Media, "src" | "thumbnail" | "width" | "height"> => ({
50
- src: `https://picsum.photos/seed/tower-${seed}/1600/1200`,
51
- thumbnail: `https://picsum.photos/seed/tower-${seed}/480/360`,
52
- width: 1600,
53
- height: 1200,
54
- });
55
-
56
- const scan = (seed: string): Pick<Media, "src" | "thumbnail" | "width" | "height"> => ({
57
- src: `https://picsum.photos/seed/tower-${seed}/1240/1754`,
58
- thumbnail: `https://picsum.photos/seed/tower-${seed}/360/510`,
59
- width: 1240,
60
- height: 1754,
61
- });
62
-
63
- /** What the server returns for the object's library. */
64
- const LIBRARY: Media[] = [
65
- {
66
- id: "m01",
67
- kind: "photo",
68
- name: "Фасад с Невского.jpg",
69
- size: 2_480_000,
70
- added: "2026-10-09",
71
- ...photo("facade"),
72
- },
73
- {
74
- id: "m02",
75
- kind: "photo",
76
- name: "Входная группа.jpg",
77
- size: 1_960_000,
78
- added: "2026-10-09",
79
- ...photo("entrance"),
80
- },
81
- {
82
- id: "m03",
83
- kind: "video",
84
- name: "Обход этажа 7.mp4",
85
- size: 48_200_000,
86
- added: "2026-10-08",
87
- src: CLIP,
88
- width: 1280,
89
- height: 720,
90
- },
91
- {
92
- id: "m04",
93
- kind: "photo",
94
- name: "Лобби и ресепшен.jpg",
95
- size: 2_120_000,
96
- added: "2026-10-07",
97
- ...photo("lobby"),
98
- },
99
- {
100
- id: "m05",
101
- kind: "photo",
102
- name: "Опенспейс, этаж 7.jpg",
103
- size: 2_730_000,
104
- added: "2026-10-07",
105
- ...photo("openspace"),
106
- },
107
- {
108
- id: "m06",
109
- kind: "document",
110
- name: "Поэтажный план.jpg",
111
- size: 860_000,
112
- added: "2026-10-06",
113
- ...scan("plan"),
114
- },
115
- {
116
- id: "m07",
117
- kind: "photo",
118
- name: "Переговорная «Нева».jpg",
119
- size: 1_840_000,
120
- added: "2026-10-05",
121
- ...photo("meeting"),
122
- },
123
- {
124
- id: "m08",
125
- kind: "video",
126
- name: "Подъезд к парковке.mp4",
127
- size: 31_500_000,
128
- added: "2026-10-04",
129
- src: CLIP,
130
- width: 1280,
131
- height: 720,
132
- },
133
- {
134
- id: "m09",
135
- kind: "photo",
136
- name: "Терраса на крыше.jpg",
137
- size: 3_050_000,
138
- added: "2026-10-03",
139
- ...photo("terrace"),
140
- },
141
- {
142
- id: "m10",
143
- kind: "document",
144
- name: "Выписка из ЕГРН.jpg",
145
- size: 640_000,
146
- added: "2026-10-02",
147
- ...scan("egrn"),
148
- },
149
- {
150
- id: "m11",
151
- kind: "photo",
152
- name: "Паркинг, уровень −1.jpg",
153
- size: 1_720_000,
154
- added: "2026-09-30",
155
- ...photo("parking"),
156
- },
157
- {
158
- id: "m12",
159
- kind: "document",
160
- name: "Техпаспорт, стр. 1.jpg",
161
- size: 720_000,
162
- added: "2026-09-28",
163
- ...scan("passport"),
164
- },
165
- ];
166
-
167
- const SECTIONS: { value: Section; label: string }[] = [
168
- { value: "all", label: "Все" },
169
- { value: "photo", label: "Фото" },
170
- { value: "video", label: "Видео" },
171
- { value: "document", label: "Документы" },
172
- ];
173
-
174
- const ORDERS: { value: Order; label: string }[] = [
175
- { value: "new", label: "Сначала новые" },
176
- { value: "old", label: "Сначала старые" },
177
- { value: "name", label: "По названию" },
178
- ];
179
-
180
- const FALLBACK_ICON = {
181
- photo: "object.image",
182
- video: "action.video",
183
- document: "object.document",
184
- } as const;
185
-
186
- /** Placeholder tiles of the first load: the grid's own geometry. */
187
- const PLACEHOLDER_TILES = ["p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"];
188
-
189
- /** How long a finished upload keeps its tile, so its ring fills and the disk fades before it moves. */
190
- const DONE_HOLD_MS = 900;
191
-
192
- const DAY = new Intl.DateTimeFormat("ru-RU", { day: "numeric", month: "short" });
193
-
194
- const filesWord = (count: number) => {
195
- const tens = count % 100;
196
- const units = count % 10;
197
- if (tens >= 11 && tens <= 14) return "файлов";
198
- if (units === 1) return "файл";
199
- if (units >= 2 && units <= 4) return "файла";
200
- return "файлов";
201
- };
202
-
203
- const today = () => new Date().toISOString().slice(0, 10);
204
-
205
- /** Upload attempts per file, and how many files have started: the stand-in drops every third one once. */
206
- const attempts = new WeakMap<File, number>();
207
- let started = 0;
208
-
209
- /** A stand-in for the server: sends the file in steps and answers with its address (a local URL here). */
210
- function sendFile(file: File, { signal, onProgress }: UploadContext): Promise<string> {
211
- const attempt = (attempts.get(file) ?? 0) + 1;
212
- attempts.set(file, attempt);
213
- if (attempt === 1) started += 1;
214
- const flaky = attempt === 1 && started % 3 === 0;
215
- return new Promise((resolve, reject) => {
216
- let sent = 0;
217
- const timer = window.setInterval(() => {
218
- sent = Math.min(1, sent + 0.08 + Math.random() * 0.1);
219
- if (flaky && sent > 0.5) {
220
- window.clearInterval(timer);
221
- reject(new Error("Нет связи с сервером"));
222
- return;
223
- }
224
- onProgress(sent);
225
- if (sent < 1) return;
226
- window.clearInterval(timer);
227
- resolve(URL.createObjectURL(file));
228
- }, 350);
229
- signal.addEventListener("abort", () => {
230
- window.clearInterval(timer);
231
- reject(signal.reason);
232
- });
233
- });
234
- }
235
-
236
- /** A finished upload as a file of the library. */
237
- const toMedia = (item: UploadItem<string>): Media => ({
238
- id: item.id,
239
- kind: item.file.type.startsWith("video/") ? "video" : "photo",
240
- name: item.file.name,
241
- src: item.result ?? "",
242
- size: item.file.size,
243
- added: today(),
244
- });
245
-
246
- const toViewerItem = (media: Media): MediaViewerItem => ({
247
- type: media.kind === "video" ? "video" : "image",
248
- src: media.src,
249
- thumbnail: media.thumbnail,
250
- width: media.width,
251
- height: media.height,
252
- alt: media.name,
253
- caption: `${media.name} · ${formatFileSize(media.size)} · ${DAY.format(new Date(media.added))}`,
254
- });
255
-
256
- export default function MediaLibraryPattern() {
257
- const { notify } = useNotifications();
258
- const [loading, setLoading] = React.useState(true);
259
- const [library, setLibrary] = React.useState<Media[]>([]);
260
- const [section, setSection] = React.useState<Section>("all");
261
- const [search, setSearch] = React.useState("");
262
- const [order, setOrder] = React.useState<Order>("new");
263
- const [selecting, setSelecting] = React.useState(false);
264
- const [selected, setSelected] = React.useState<ReadonlySet<string>>(new Set());
265
- const [open, setOpen] = React.useState(false);
266
- const [index, setIndex] = React.useState(0);
267
-
268
- const queue = useUploadQueue({ upload: sendFile, concurrency: 2 });
269
- const inputRef = React.useRef<HTMLInputElement>(null);
270
- const tiles = React.useRef(new Map<string, HTMLElement>());
271
- const moving = React.useRef(new Set<string>());
272
-
273
- // First load: the server answers after a moment; the grid holds its shape meanwhile.
274
- React.useEffect(() => {
275
- const timer = window.setTimeout(() => {
276
- setLibrary(LIBRARY);
277
- setLoading(false);
278
- }, 1200);
279
- return () => window.clearTimeout(timer);
280
- }, []);
281
-
282
- // A finished upload leaves its tile for the library, first in it.
283
- const { items: uploads, remove: removeUpload } = queue;
284
- React.useEffect(() => {
285
- for (const item of uploads) {
286
- if (item.status !== "done" || moving.current.has(item.id)) continue;
287
- moving.current.add(item.id);
288
- window.setTimeout(() => {
289
- setLibrary((current) => [toMedia(item), ...current]);
290
- removeUpload(item.id);
291
- }, DONE_HOLD_MS);
292
- }
293
- }, [uploads, removeUpload]);
294
-
295
- const query = search.trim().toLowerCase();
296
- const visible = library
297
- .filter(
298
- (media) =>
299
- (section === "all" || media.kind === section) && media.name.toLowerCase().includes(query),
300
- )
301
- .sort((a, b) => {
302
- if (order === "name") return a.name.localeCompare(b.name, "ru");
303
- const byDate = a.added.localeCompare(b.added);
304
- return order === "new" ? -byDate : byDate;
305
- });
306
- const viewerItems = visible.map(toViewerItem);
307
- const count = (value: Section) =>
308
- value === "all" ? library.length : library.filter((media) => media.kind === value).length;
309
-
310
- const state = loading
311
- ? "loading"
312
- : visible.length > 0
313
- ? `ready:${section}:${order}`
314
- : library.length > 0
315
- ? "nothing"
316
- : "empty";
317
-
318
- const toggle = (id: string, checked: boolean) =>
319
- setSelected((current) => {
320
- const next = new Set(current);
321
- if (checked) next.add(id);
322
- else next.delete(id);
323
- return next;
324
- });
325
-
326
- const stopSelecting = () => {
327
- setSelecting(false);
328
- setSelected(new Set());
329
- };
330
-
331
- const resetFilters = () => {
332
- setSection("all");
333
- setSearch("");
334
- };
335
-
336
- const download = () => {
337
- notify({
338
- tone: "success",
339
- title: `Скачиваем ${selected.size} ${filesWord(selected.size)}`,
340
- description: "Архив сохранится в папку загрузок.",
341
- });
342
- stopSelecting();
343
- };
344
-
345
- // A stand-in for the delete request: the dialog stays busy until it answers.
346
- const removeSelected = () =>
347
- new Promise<void>((resolve) => window.setTimeout(resolve, 800)).then(() => {
348
- const removed = selected.size;
349
- for (const media of library) {
350
- if (selected.has(media.id) && media.src.startsWith("blob:")) URL.revokeObjectURL(media.src);
351
- }
352
- setLibrary((current) => current.filter((media) => !selected.has(media.id)));
353
- stopSelecting();
354
- notify({ tone: "success", title: `Удалено: ${removed} ${filesWord(removed)}` });
355
- });
356
-
357
- const openAt = (at: number) => {
358
- setIndex(at);
359
- setOpen(true);
360
- };
361
-
362
- const totalSize = visible.reduce((sum, media) => sum + media.size, 0);
363
-
364
- return (
365
- <PageContent.Page aria-labelledby="media-title">
366
- <PageContent.Header>
367
- <PageContent.Title id="media-title">Медиатека объекта</PageContent.Title>
368
- <PageContent.Description>
369
- БЦ «Северная башня», Невский пр., 112: фото, видео и сканы для карточки в каталоге.
370
- </PageContent.Description>
371
- </PageContent.Header>
372
- <PageContent.Body>
373
- <SmartFilter.Root
374
- fields={[]}
375
- search={search}
376
- onSearchChange={setSearch}
377
- labels={{ searchPlaceholder: "Поиск по названию" }}
378
- >
379
- <PageToolbar.Root aria-label="Медиатека">
380
- <PageToolbar.Tools>
381
- <SmartFilter.Toolbar />
382
- </PageToolbar.Tools>
383
- <PageToolbar.Sections>
384
- <SegmentedControl.Root
385
- fullWidth
386
- value={section}
387
- onValueChange={(value) => setSection(value as Section)}
388
- aria-label="Раздел"
389
- >
390
- {SECTIONS.map((item) => (
391
- <SegmentedControl.Item key={item.value} value={item.value}>
392
- {item.label}
393
- {loading ? null : (
394
- <SegmentedControl.Count>{count(item.value)}</SegmentedControl.Count>
395
- )}
396
- </SegmentedControl.Item>
397
- ))}
398
- </SegmentedControl.Root>
399
- </PageToolbar.Sections>
400
- <PageToolbar.View>
401
- <Select.Root value={order} onValueChange={(value) => setOrder(value as Order)}>
402
- <Select.Trigger aria-label="Порядок">
403
- <Select.TriggerIcon>
404
- <Icon name="sort.descending" />
405
- </Select.TriggerIcon>
406
- <Select.Value />
407
- </Select.Trigger>
408
- <Select.Content>
409
- {ORDERS.map((item) => (
410
- <Select.Item key={item.value} value={item.value}>
411
- {item.label}
412
- </Select.Item>
413
- ))}
414
- </Select.Content>
415
- </Select.Root>
416
- </PageToolbar.View>
417
- <PageToolbar.Actions>
418
- <Button.Root onClick={() => inputRef.current?.click()}>
419
- <Button.Icon>
420
- <Icon name="action.upload" />
421
- </Button.Icon>
422
- Загрузить
423
- </Button.Root>
424
- </PageToolbar.Actions>
425
- </PageToolbar.Root>
426
- </SmartFilter.Root>
427
-
428
- {/* Uploads in flight: the add tile is also the drop zone; a done file moves into the grid. */}
429
- <FileUpload.Root
430
- label="Новые файлы"
431
- hint="Фото и видео до 200 МБ. Загруженные появятся в медиатеке первыми."
432
- trigger="tile"
433
- layout="grid"
434
- accept="image/*,video/*"
435
- multiple
436
- queue={queue}
437
- inputRef={inputRef}
438
- />
439
-
440
- <PageContent.Section
441
- label="Файлы"
442
- description={
443
- <span aria-live="polite">
444
- {selecting
445
- ? `Выбрано: ${selected.size}`
446
- : loading
447
- ? "Загружаем…"
448
- : `${visible.length} ${filesWord(visible.length)} · ${formatFileSize(totalSize)}`}
449
- </span>
450
- }
451
- >
452
- <PageContent.Actions>
453
- <Crossfade state={selecting ? "select" : "browse"}>
454
- {selecting ? (
455
- <div className={styles.bar}>
456
- <Button.Root
457
- variant="soft"
458
- tone="neutral"
459
- disabled={selected.size === 0}
460
- onClick={download}
461
- >
462
- <Button.Icon>
463
- <Icon name="action.download" />
464
- </Button.Icon>
465
- Скачать
466
- </Button.Root>
467
- <ConfirmDialog.Root
468
- title={`Удалить ${selected.size} ${filesWord(selected.size)}?`}
469
- description="Файлы пропадут из карточки объекта в каталоге. Восстановить их будет нельзя."
470
- confirmLabel="Удалить"
471
- onConfirm={removeSelected}
472
- >
473
- <ConfirmDialog.Trigger>
474
- <Button.Root variant="outline" tone="danger" disabled={selected.size === 0}>
475
- <Button.Icon>
476
- <Icon name="action.delete" />
477
- </Button.Icon>
478
- Удалить
479
- </Button.Root>
480
- </ConfirmDialog.Trigger>
481
- </ConfirmDialog.Root>
482
- <Button.Root variant="ghost" tone="neutral" onClick={stopSelecting}>
483
- Отмена
484
- </Button.Root>
485
- </div>
486
- ) : (
487
- <div className={styles.bar}>
488
- <Button.Root
489
- variant="soft"
490
- tone="neutral"
491
- disabled={loading || visible.length === 0}
492
- onClick={() => setSelecting(true)}
493
- >
494
- <Button.Icon>
495
- <Icon name="action.check" />
496
- </Button.Icon>
497
- Выбрать
498
- </Button.Root>
499
- </div>
500
- )}
501
- </Crossfade>
502
- </PageContent.Actions>
503
-
504
- <Crossfade state={state} aria-busy={loading}>
505
- {loading ? (
506
- <ul className={styles.grid}>
507
- {PLACEHOLDER_TILES.map((key) => (
508
- <li key={key} className={styles.tile}>
509
- <Skeleton shape="block" className={styles.picture} />
510
- <div className={styles.tileText}>
511
- <Skeleton size="s" className={styles.nameBar} />
512
- <Skeleton size="xs" className={styles.metaBar} />
513
- </div>
514
- </li>
515
- ))}
516
- </ul>
517
- ) : null}
518
-
519
- {state.startsWith("ready") ? (
520
- <ul className={styles.grid}>
521
- {visible.map((media, at) => {
522
- const picture =
523
- media.kind === "video" ? (
524
- <Thumbnail.Video src={media.src} aria-label={media.name} />
525
- ) : (
526
- <Thumbnail.Image
527
- src={media.thumbnail ?? media.src}
528
- fit={media.kind === "document" ? "contain" : "cover"}
529
- />
530
- );
531
- const fallback = (
532
- <Thumbnail.Fallback>
533
- <Icon name={FALLBACK_ICON[media.kind]} />
534
- </Thumbnail.Fallback>
535
- );
536
- return (
537
- <li key={media.id} className={styles.tile}>
538
- {/* Browsing, a press opens the viewer out of the tile; selecting, it picks the file. */}
539
- {selecting ? (
540
- <Thumbnail.Root
541
- fullWidth
542
- ratio="4:3"
543
- aria-label={media.name}
544
- checked={selected.has(media.id)}
545
- onCheckedChange={(checked) => toggle(media.id, checked)}
546
- >
547
- {picture}
548
- {fallback}
549
- </Thumbnail.Root>
550
- ) : (
551
- <Thumbnail.Root asChild fullWidth ratio="4:3">
552
- <button
553
- ref={(node) => {
554
- if (node) tiles.current.set(media.id, node);
555
- else tiles.current.delete(media.id);
556
- }}
557
- type="button"
558
- aria-label={`Открыть: ${media.name}`}
559
- aria-haspopup="dialog"
560
- onClick={() => openAt(at)}
561
- >
562
- {picture}
563
- {fallback}
564
- </button>
565
- </Thumbnail.Root>
566
- )}
567
- <div className={styles.tileText}>
568
- <Typography as="span" variant="body-s" truncate title={media.name}>
569
- {media.name}
570
- </Typography>
571
- <Typography as="span" variant="caption" tone="muted">
572
- {formatFileSize(media.size)} · {DAY.format(new Date(media.added))}
573
- </Typography>
574
- </div>
575
- </li>
576
- );
577
- })}
578
- </ul>
579
- ) : null}
580
-
581
- {state === "nothing" ? (
582
- <EmptyPage.Root size="s" role="status" aria-labelledby="media-nothing">
583
- <EmptyPage.Icon>
584
- <Icon name="action.search" />
585
- </EmptyPage.Icon>
586
- <EmptyPage.Title as="h3" id="media-nothing">
587
- Ничего не найдено
588
- </EmptyPage.Title>
589
- <EmptyPage.Description>
590
- В этом разделе нет файлов с таким названием.
591
- </EmptyPage.Description>
592
- <EmptyPage.Actions>
593
- <Button.Root variant="soft" tone="neutral" onClick={resetFilters}>
594
- Показать все файлы
595
- </Button.Root>
596
- </EmptyPage.Actions>
597
- </EmptyPage.Root>
598
- ) : null}
599
-
600
- {state === "empty" ? (
601
- <EmptyPage.Root size="s" aria-labelledby="media-empty">
602
- <EmptyPage.Icon tone="accent">
603
- <Icon name="object.image" />
604
- </EmptyPage.Icon>
605
- <EmptyPage.Title as="h3" id="media-empty">
606
- Файлов пока нет
607
- </EmptyPage.Title>
608
- <EmptyPage.Description>
609
- Перетащите фото и видео объекта в поле выше или нажмите «Загрузить».
610
- </EmptyPage.Description>
611
- </EmptyPage.Root>
612
- ) : null}
613
- </Crossfade>
614
- </PageContent.Section>
615
-
616
- <MediaViewer
617
- items={viewerItems}
618
- open={open}
619
- onOpenChange={setOpen}
620
- index={index}
621
- onIndexChange={setIndex}
622
- getOrigin={(at) => tiles.current.get(visible[at]?.id ?? "") ?? null}
623
- thumbnails
624
- renderActions={(item) => (
625
- <Button.Root shape="circle" variant="shade" aria-label="Скачать файл" asChild>
626
- <a href={item.src} download>
627
- <Button.Icon>
628
- <Icon name="action.download" />
629
- </Button.Icon>
630
- </a>
631
- </Button.Root>
632
- )}
633
- />
634
- </PageContent.Body>
635
- </PageContent.Page>
636
- );
637
- }
@@ -1,22 +0,0 @@
1
- /* Schedule: the page fills the app panel (`AppShell.Root fillViewport` + `PageContent.Root fill`);
2
- the page panel sits close over the chart it filters and the chart takes the free height. */
3
-
4
- .board {
5
- display: flex;
6
- flex: 1 1 auto;
7
- flex-direction: column;
8
- gap: var(--prime-space-4);
9
- min-width: 0;
10
- min-height: 0;
11
- }
12
-
13
- /* On a short screen the chart keeps room for a few rows; the page scrolls instead. */
14
- .chart {
15
- min-height: calc(var(--prime-space-24) * 3);
16
- }
17
-
18
- /* First column: the name over the role. */
19
- .person {
20
- display: grid;
21
- min-width: 0;
22
- }