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