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
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/** A sales pipeline as a work screen: the title with the open deals and their sum, search, filter, the board / list switch and the one primary action in the app header, a full-height Kanban of deals by stage with totals, moves saved on the server that can be refused, and the deal in a Drawer — `value`, `onValueChange`, `renderColumnMeta`, `onItemClick`. */
|
|
2
|
+
import {
|
|
3
|
+
AppHeader,
|
|
4
|
+
Avatar,
|
|
5
|
+
Badge,
|
|
6
|
+
Button,
|
|
7
|
+
Crossfade,
|
|
8
|
+
DataTable,
|
|
9
|
+
type DataTableColumn,
|
|
10
|
+
DescriptionList,
|
|
11
|
+
Drawer,
|
|
12
|
+
Dropdown,
|
|
13
|
+
EmptyPage,
|
|
14
|
+
Icon,
|
|
15
|
+
Kanban,
|
|
16
|
+
type KanbanColumn,
|
|
17
|
+
type KanbanValue,
|
|
18
|
+
matchesSmartFilter,
|
|
19
|
+
PageContent,
|
|
20
|
+
PageToolbar,
|
|
21
|
+
type PaletteColor,
|
|
22
|
+
SegmentedControl,
|
|
23
|
+
SmartFilter,
|
|
24
|
+
type SmartFilterField,
|
|
25
|
+
type SmartFilterValue,
|
|
26
|
+
Typography,
|
|
27
|
+
useNotifications,
|
|
28
|
+
} from "prime-ui-kit";
|
|
29
|
+
import * as React from "react";
|
|
30
|
+
|
|
31
|
+
import styles from "./screen.module.css";
|
|
32
|
+
|
|
33
|
+
type Owner = { name: string; initials: string; color: PaletteColor };
|
|
34
|
+
|
|
35
|
+
type Deal = {
|
|
36
|
+
id: string;
|
|
37
|
+
company: string;
|
|
38
|
+
amount: number;
|
|
39
|
+
owner: Owner;
|
|
40
|
+
due: string;
|
|
41
|
+
contact: string;
|
|
42
|
+
source: string;
|
|
43
|
+
probability: number;
|
|
44
|
+
contract: boolean;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type DealRow = Deal & { stage: string };
|
|
48
|
+
|
|
49
|
+
/** The stages of the pipeline, in order; the stage color repeats on its count and its Badge. */
|
|
50
|
+
const STAGES: KanbanColumn[] = [
|
|
51
|
+
{ id: "new", title: "Новая", color: "blue" },
|
|
52
|
+
{ id: "qualified", title: "Квалификация", color: "purple" },
|
|
53
|
+
{ id: "proposal", title: "Предложение", color: "orange" },
|
|
54
|
+
{ id: "negotiation", title: "Переговоры", color: "yellow" },
|
|
55
|
+
{ id: "won", title: "Выиграна", color: "green" },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const ANNA: Owner = { name: "Анна Климова", initials: "АК", color: "purple" };
|
|
59
|
+
const ILYA: Owner = { name: "Илья Петров", initials: "ИП", color: "teal" };
|
|
60
|
+
const MARAT: Owner = { name: "Марат Хасанов", initials: "МХ", color: "orange" };
|
|
61
|
+
|
|
62
|
+
const DEALS: Deal[] = [
|
|
63
|
+
{
|
|
64
|
+
id: "DL-341",
|
|
65
|
+
company: "ООО «Северный ветер»",
|
|
66
|
+
amount: 480_000,
|
|
67
|
+
owner: ANNA,
|
|
68
|
+
due: "2026-10-24",
|
|
69
|
+
contact: "Ольга Белова, закупки",
|
|
70
|
+
source: "Сайт",
|
|
71
|
+
probability: 20,
|
|
72
|
+
contract: false,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "DL-338",
|
|
76
|
+
company: "АО «Техностиль»",
|
|
77
|
+
amount: 1_240_000,
|
|
78
|
+
owner: ILYA,
|
|
79
|
+
due: "2026-10-30",
|
|
80
|
+
contact: "Дмитрий Орлов, ИТ-директор",
|
|
81
|
+
source: "Выставка",
|
|
82
|
+
probability: 25,
|
|
83
|
+
contract: false,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "DL-332",
|
|
87
|
+
company: "ООО «Логистик Плюс»",
|
|
88
|
+
amount: 312_000,
|
|
89
|
+
owner: MARAT,
|
|
90
|
+
due: "2026-10-19",
|
|
91
|
+
contact: "Сергей Ким, операционный директор",
|
|
92
|
+
source: "Рекомендация",
|
|
93
|
+
probability: 40,
|
|
94
|
+
contract: false,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: "DL-327",
|
|
98
|
+
company: "ООО «Гранит»",
|
|
99
|
+
amount: 94_750,
|
|
100
|
+
owner: ANNA,
|
|
101
|
+
due: "2026-10-12",
|
|
102
|
+
contact: "Наталья Фомина, финансы",
|
|
103
|
+
source: "Сайт",
|
|
104
|
+
probability: 40,
|
|
105
|
+
contract: false,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "DL-321",
|
|
109
|
+
company: "ЗАО «Альфа Медиа»",
|
|
110
|
+
amount: 760_000,
|
|
111
|
+
owner: ILYA,
|
|
112
|
+
due: "2026-10-28",
|
|
113
|
+
contact: "Екатерина Лаптева, маркетинг",
|
|
114
|
+
source: "Холодный звонок",
|
|
115
|
+
probability: 60,
|
|
116
|
+
contract: false,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "DL-316",
|
|
120
|
+
company: "ООО «Мостострой»",
|
|
121
|
+
amount: 2_480_000,
|
|
122
|
+
owner: MARAT,
|
|
123
|
+
due: "2026-11-06",
|
|
124
|
+
contact: "Андрей Зуев, генеральный директор",
|
|
125
|
+
source: "Рекомендация",
|
|
126
|
+
probability: 75,
|
|
127
|
+
contract: true,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "DL-309",
|
|
131
|
+
company: "АО «Волга-Энерго»",
|
|
132
|
+
amount: 1_095_000,
|
|
133
|
+
owner: ANNA,
|
|
134
|
+
due: "2026-10-21",
|
|
135
|
+
contact: "Игорь Щукин, закупки",
|
|
136
|
+
source: "Выставка",
|
|
137
|
+
probability: 80,
|
|
138
|
+
contract: false,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: "DL-298",
|
|
142
|
+
company: "ООО «Зелёный квартал»",
|
|
143
|
+
amount: 205_300,
|
|
144
|
+
owner: ILYA,
|
|
145
|
+
due: "2026-10-08",
|
|
146
|
+
contact: "Мария Глебова, офис-менеджер",
|
|
147
|
+
source: "Сайт",
|
|
148
|
+
probability: 100,
|
|
149
|
+
contract: true,
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const PLACEMENT: KanbanValue = {
|
|
154
|
+
new: ["DL-341", "DL-338"],
|
|
155
|
+
qualified: ["DL-332", "DL-327"],
|
|
156
|
+
proposal: ["DL-321"],
|
|
157
|
+
negotiation: ["DL-316", "DL-309"],
|
|
158
|
+
won: ["DL-298"],
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const BY_ID = new Map(DEALS.map((deal) => [deal.id, deal]));
|
|
162
|
+
const STAGE_BY_ID = new Map(STAGES.map((stage) => [stage.id, stage]));
|
|
163
|
+
const OWNERS = [ANNA, ILYA, MARAT];
|
|
164
|
+
|
|
165
|
+
const RUBLES = new Intl.NumberFormat("ru-RU", {
|
|
166
|
+
style: "currency",
|
|
167
|
+
currency: "RUB",
|
|
168
|
+
maximumFractionDigits: 0,
|
|
169
|
+
});
|
|
170
|
+
const DAY = new Intl.DateTimeFormat("ru-RU", { day: "numeric", month: "short" });
|
|
171
|
+
|
|
172
|
+
const FIELDS: SmartFilterField[] = [
|
|
173
|
+
{
|
|
174
|
+
key: "stage",
|
|
175
|
+
label: "Этап",
|
|
176
|
+
options: STAGES.map((stage) => ({ value: stage.id, label: stage.title })),
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
key: "owner",
|
|
180
|
+
label: "Ответственный",
|
|
181
|
+
options: OWNERS.map((owner) => ({ value: owner.name, label: owner.name })),
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
const LOAD_MS = 900;
|
|
186
|
+
const SAVE_MS = 800;
|
|
187
|
+
|
|
188
|
+
const dealsWord = (count: number) => {
|
|
189
|
+
const tens = count % 100;
|
|
190
|
+
const ones = count % 10;
|
|
191
|
+
if (tens >= 11 && tens <= 14) return "сделок";
|
|
192
|
+
if (ones === 1) return "сделка";
|
|
193
|
+
if (ones >= 2 && ones <= 4) return "сделки";
|
|
194
|
+
return "сделок";
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const stageOf = (placement: KanbanValue, id: string) =>
|
|
198
|
+
Object.keys(placement).find((stage) => placement[stage]?.includes(id)) ?? "new";
|
|
199
|
+
|
|
200
|
+
/** `placement` with deal `id` moved to the top of stage `to`. */
|
|
201
|
+
const placeOnTop = (placement: KanbanValue, id: string, to: string): KanbanValue => {
|
|
202
|
+
const next: Record<string, readonly string[]> = {};
|
|
203
|
+
for (const stage of Object.keys(placement)) {
|
|
204
|
+
next[stage] = (placement[stage] ?? []).filter((card) => card !== id);
|
|
205
|
+
}
|
|
206
|
+
next[to] = [id, ...(next[to] ?? [])];
|
|
207
|
+
return next;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/** The server's answer to a stage change, a beat later: no signed contract — no won deal. */
|
|
211
|
+
function saveStage(deal: Deal, to: string) {
|
|
212
|
+
return new Promise<void>((resolve, reject) => {
|
|
213
|
+
window.setTimeout(() => {
|
|
214
|
+
if (to === "won" && !deal.contract) {
|
|
215
|
+
reject(new Error(`${deal.company}: договор ещё не подписан`));
|
|
216
|
+
} else {
|
|
217
|
+
resolve();
|
|
218
|
+
}
|
|
219
|
+
}, SAVE_MS);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const ownerAvatar = (owner: Owner) => (
|
|
224
|
+
<Avatar.Root size="s" color={owner.color} aria-label={owner.name}>
|
|
225
|
+
<Avatar.Fallback>{owner.initials}</Avatar.Fallback>
|
|
226
|
+
</Avatar.Root>
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
const stageBadge = (stageId: string) => {
|
|
230
|
+
const stage = STAGE_BY_ID.get(stageId);
|
|
231
|
+
return <Badge.Root color={stage?.color}>{stage?.title}</Badge.Root>;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const COLUMNS: DataTableColumn<DealRow>[] = [
|
|
235
|
+
{
|
|
236
|
+
id: "company",
|
|
237
|
+
header: "Компания",
|
|
238
|
+
accessor: "company",
|
|
239
|
+
sortable: true,
|
|
240
|
+
cell: (row) => (
|
|
241
|
+
<span className={styles.company}>
|
|
242
|
+
<Typography as="span" variant="body-m">
|
|
243
|
+
{row.company}
|
|
244
|
+
</Typography>
|
|
245
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
246
|
+
{row.id}
|
|
247
|
+
</Typography>
|
|
248
|
+
</span>
|
|
249
|
+
),
|
|
250
|
+
},
|
|
251
|
+
{ id: "stage", header: "Этап", accessor: "stage", cell: (row) => stageBadge(row.stage) },
|
|
252
|
+
{
|
|
253
|
+
id: "owner",
|
|
254
|
+
header: "Ответственный",
|
|
255
|
+
cell: (row) => (
|
|
256
|
+
<span className={styles.owner}>
|
|
257
|
+
{ownerAvatar(row.owner)}
|
|
258
|
+
{row.owner.name}
|
|
259
|
+
</span>
|
|
260
|
+
),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: "due",
|
|
264
|
+
header: "Срок",
|
|
265
|
+
accessor: "due",
|
|
266
|
+
sortable: true,
|
|
267
|
+
numeric: true,
|
|
268
|
+
headerAlign: "end",
|
|
269
|
+
cell: (row) => DAY.format(new Date(row.due)),
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: "amount",
|
|
273
|
+
header: "Сумма",
|
|
274
|
+
accessor: "amount",
|
|
275
|
+
sortable: true,
|
|
276
|
+
numeric: true,
|
|
277
|
+
headerAlign: "end",
|
|
278
|
+
cell: (row) => RUBLES.format(row.amount),
|
|
279
|
+
},
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
export default function KanbanScreenExample() {
|
|
283
|
+
const { notify } = useNotifications();
|
|
284
|
+
const [loading, setLoading] = React.useState(true);
|
|
285
|
+
const [view, setView] = React.useState("board");
|
|
286
|
+
const [filter, setFilter] = React.useState<SmartFilterValue>({});
|
|
287
|
+
const [search, setSearch] = React.useState("");
|
|
288
|
+
const [placement, setPlacement] = React.useState(PLACEMENT);
|
|
289
|
+
const [openId, setOpenId] = React.useState<string | null>(null);
|
|
290
|
+
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
|
291
|
+
const [saving, setSaving] = React.useState(false);
|
|
292
|
+
|
|
293
|
+
// The first load: skeleton cards and rows hold the geometry until the deals arrive.
|
|
294
|
+
React.useEffect(() => {
|
|
295
|
+
const timer = window.setTimeout(() => setLoading(false), LOAD_MS);
|
|
296
|
+
return () => window.clearTimeout(timer);
|
|
297
|
+
}, []);
|
|
298
|
+
|
|
299
|
+
const query = search.trim().toLowerCase();
|
|
300
|
+
const deals = DEALS.filter(
|
|
301
|
+
(deal) =>
|
|
302
|
+
matchesSmartFilter(filter.stage, stageOf(placement, deal.id)) &&
|
|
303
|
+
matchesSmartFilter(filter.owner, deal.owner.name) &&
|
|
304
|
+
(deal.company.toLowerCase().includes(query) || deal.id.toLowerCase().includes(query)),
|
|
305
|
+
);
|
|
306
|
+
const rows: DealRow[] = deals.map((deal) => ({ ...deal, stage: stageOf(placement, deal.id) }));
|
|
307
|
+
const shown = new Set(deals.map((deal) => deal.id));
|
|
308
|
+
// The header's data line: what the filtered pipeline holds, open deals only.
|
|
309
|
+
const inWork = deals.filter((deal) => stageOf(placement, deal.id) !== "won");
|
|
310
|
+
const pipeline = `${inWork.length} ${dealsWord(inWork.length)} в работе · ${RUBLES.format(
|
|
311
|
+
inWork.reduce((total, deal) => total + deal.amount, 0),
|
|
312
|
+
)}`;
|
|
313
|
+
|
|
314
|
+
const figures = (column: KanbanColumn) => {
|
|
315
|
+
const ids = (placement[column.id] ?? []).filter((id) => shown.has(id));
|
|
316
|
+
const sum = ids.reduce((total, id) => total + (BY_ID.get(id)?.amount ?? 0), 0);
|
|
317
|
+
return `${ids.length} ${dealsWord(ids.length)} · ${RUBLES.format(sum)}`;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const refuse = (error: unknown) =>
|
|
321
|
+
notify({
|
|
322
|
+
tone: "danger",
|
|
323
|
+
title: "Этап не изменён",
|
|
324
|
+
description: error instanceof Error ? error.message : String(error),
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const openDeal = (id: string) => {
|
|
328
|
+
setOpenId(id);
|
|
329
|
+
setDrawerOpen(true);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const resetFilters = () => {
|
|
333
|
+
setFilter({});
|
|
334
|
+
setSearch("");
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// From the drawer: the stage changes only after the server agrees.
|
|
338
|
+
const moveDeal = async (deal: Deal, to: string) => {
|
|
339
|
+
setSaving(true);
|
|
340
|
+
try {
|
|
341
|
+
await saveStage(deal, to);
|
|
342
|
+
setPlacement((current) => placeOnTop(current, deal.id, to));
|
|
343
|
+
notify({
|
|
344
|
+
tone: "success",
|
|
345
|
+
title: `Сделка на этапе «${STAGE_BY_ID.get(to)?.title}»`,
|
|
346
|
+
description: deal.company,
|
|
347
|
+
});
|
|
348
|
+
} catch (error) {
|
|
349
|
+
refuse(error);
|
|
350
|
+
} finally {
|
|
351
|
+
setSaving(false);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const deal = openId === null ? undefined : BY_ID.get(openId);
|
|
356
|
+
const dealStage = deal ? stageOf(placement, deal.id) : "new";
|
|
357
|
+
const nextStage = STAGES[STAGES.findIndex((stage) => stage.id === dealStage) + 1];
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<>
|
|
361
|
+
{/* A work screen: in an app this header fills the shell's `header` slot and carries the page —
|
|
362
|
+
the only h1 and the page's tools; main has no PageContent.Header. */}
|
|
363
|
+
<AppHeader.Root>
|
|
364
|
+
<AppHeader.Start>
|
|
365
|
+
<AppHeader.Title>
|
|
366
|
+
Сделки
|
|
367
|
+
<AppHeader.Description>
|
|
368
|
+
{loading ? "Загружаем воронку…" : pipeline}
|
|
369
|
+
</AppHeader.Description>
|
|
370
|
+
</AppHeader.Title>
|
|
371
|
+
</AppHeader.Start>
|
|
372
|
+
<AppHeader.Tools>
|
|
373
|
+
<SmartFilter.Root
|
|
374
|
+
fields={FIELDS}
|
|
375
|
+
value={filter}
|
|
376
|
+
onValueChange={setFilter}
|
|
377
|
+
search={search}
|
|
378
|
+
onSearchChange={setSearch}
|
|
379
|
+
>
|
|
380
|
+
<PageToolbar.Root aria-label="Сделки">
|
|
381
|
+
<PageToolbar.Tools>
|
|
382
|
+
<SmartFilter.Toolbar />
|
|
383
|
+
</PageToolbar.Tools>
|
|
384
|
+
<PageToolbar.View>
|
|
385
|
+
<SegmentedControl.Root value={view} onValueChange={setView} aria-label="Вид">
|
|
386
|
+
<SegmentedControl.Item value="board">
|
|
387
|
+
<SegmentedControl.Icon>
|
|
388
|
+
<Icon name="view.columns" />
|
|
389
|
+
</SegmentedControl.Icon>
|
|
390
|
+
Доска
|
|
391
|
+
</SegmentedControl.Item>
|
|
392
|
+
<SegmentedControl.Item value="list">
|
|
393
|
+
<SegmentedControl.Icon>
|
|
394
|
+
<Icon name="format.list" />
|
|
395
|
+
</SegmentedControl.Icon>
|
|
396
|
+
Список
|
|
397
|
+
</SegmentedControl.Item>
|
|
398
|
+
</SegmentedControl.Root>
|
|
399
|
+
</PageToolbar.View>
|
|
400
|
+
<PageToolbar.Actions>
|
|
401
|
+
<Button.Root>
|
|
402
|
+
<Button.Icon>
|
|
403
|
+
<Icon name="action.add" />
|
|
404
|
+
</Button.Icon>
|
|
405
|
+
Новая сделка
|
|
406
|
+
</Button.Root>
|
|
407
|
+
</PageToolbar.Actions>
|
|
408
|
+
<PageToolbar.Chips>
|
|
409
|
+
<SmartFilter.Chips />
|
|
410
|
+
</PageToolbar.Chips>
|
|
411
|
+
</PageToolbar.Root>
|
|
412
|
+
</SmartFilter.Root>
|
|
413
|
+
</AppHeader.Tools>
|
|
414
|
+
</AppHeader.Root>
|
|
415
|
+
|
|
416
|
+
<PageContent.Root fill>
|
|
417
|
+
<PageContent.Body>
|
|
418
|
+
<Crossfade state={view} fill>
|
|
419
|
+
{view === "board" ? (
|
|
420
|
+
// `plain` (the default): the board is the page's main region, so the stages are no
|
|
421
|
+
// boxes — their headers and the deal cards stand on the page, one level of nesting.
|
|
422
|
+
<Kanban.Root
|
|
423
|
+
aria-label="Воронка продаж"
|
|
424
|
+
columns={STAGES}
|
|
425
|
+
items={deals}
|
|
426
|
+
getId={(item) => item.id}
|
|
427
|
+
getLabel={(item) => item.company}
|
|
428
|
+
value={placement}
|
|
429
|
+
onValueChange={async (next, move) => {
|
|
430
|
+
const moved = BY_ID.get(move.id);
|
|
431
|
+
if (moved && move.from !== move.to) {
|
|
432
|
+
try {
|
|
433
|
+
await saveStage(moved, move.to);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
refuse(error);
|
|
436
|
+
throw error;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
setPlacement(next);
|
|
440
|
+
}}
|
|
441
|
+
renderColumnMeta={figures}
|
|
442
|
+
loading={loading}
|
|
443
|
+
onItemClick={(item) => openDeal(item.id)}
|
|
444
|
+
renderItem={(item) => (
|
|
445
|
+
<Kanban.Item>
|
|
446
|
+
<Kanban.ItemTitle>{item.company}</Kanban.ItemTitle>
|
|
447
|
+
<Kanban.ItemDescription>
|
|
448
|
+
{RUBLES.format(item.amount)} · до {DAY.format(new Date(item.due))}
|
|
449
|
+
</Kanban.ItemDescription>
|
|
450
|
+
<Kanban.ItemFooter>{ownerAvatar(item.owner)}</Kanban.ItemFooter>
|
|
451
|
+
</Kanban.Item>
|
|
452
|
+
)}
|
|
453
|
+
/>
|
|
454
|
+
) : (
|
|
455
|
+
<DataTable
|
|
456
|
+
columns={COLUMNS}
|
|
457
|
+
rows={loading ? [] : rows}
|
|
458
|
+
loading={loading}
|
|
459
|
+
getRowKey={(row) => row.id}
|
|
460
|
+
getRowLabel={(row) => row.company}
|
|
461
|
+
onRowClick={(row) => openDeal(row.id)}
|
|
462
|
+
paging="none"
|
|
463
|
+
scrollHeight="fill"
|
|
464
|
+
stickyHeader
|
|
465
|
+
defaultSort={{ columnId: "due", order: "asc" }}
|
|
466
|
+
empty={
|
|
467
|
+
<EmptyPage.Root size="s" role="status" aria-labelledby="deals-empty">
|
|
468
|
+
<EmptyPage.Icon>
|
|
469
|
+
<Icon name="action.search" />
|
|
470
|
+
</EmptyPage.Icon>
|
|
471
|
+
<EmptyPage.Title as="p" id="deals-empty">
|
|
472
|
+
Сделок не найдено
|
|
473
|
+
</EmptyPage.Title>
|
|
474
|
+
<EmptyPage.Description>
|
|
475
|
+
Измените запрос или сбросьте фильтры.
|
|
476
|
+
</EmptyPage.Description>
|
|
477
|
+
<EmptyPage.Actions>
|
|
478
|
+
<Button.Root variant="soft" tone="neutral" onClick={resetFilters}>
|
|
479
|
+
Сбросить фильтры
|
|
480
|
+
</Button.Root>
|
|
481
|
+
</EmptyPage.Actions>
|
|
482
|
+
</EmptyPage.Root>
|
|
483
|
+
}
|
|
484
|
+
/>
|
|
485
|
+
)}
|
|
486
|
+
</Crossfade>
|
|
487
|
+
<Drawer.Root open={drawerOpen} onOpenChange={setDrawerOpen}>
|
|
488
|
+
<Drawer.Content>
|
|
489
|
+
<Drawer.Guard busy={saving} />
|
|
490
|
+
<Drawer.Header>
|
|
491
|
+
<Drawer.Title>{deal?.company}</Drawer.Title>
|
|
492
|
+
<Drawer.Description>
|
|
493
|
+
{deal?.id} · {STAGE_BY_ID.get(dealStage)?.title}
|
|
494
|
+
</Drawer.Description>
|
|
495
|
+
</Drawer.Header>
|
|
496
|
+
<Drawer.Body>
|
|
497
|
+
{deal ? (
|
|
498
|
+
<DescriptionList.Root>
|
|
499
|
+
<DescriptionList.Item label="Этап">
|
|
500
|
+
{stageBadge(dealStage)}
|
|
501
|
+
</DescriptionList.Item>
|
|
502
|
+
<DescriptionList.Item label="Сумма">
|
|
503
|
+
{RUBLES.format(deal.amount)}
|
|
504
|
+
</DescriptionList.Item>
|
|
505
|
+
<DescriptionList.Item label="Вероятность">
|
|
506
|
+
{deal.probability} %
|
|
507
|
+
</DescriptionList.Item>
|
|
508
|
+
<DescriptionList.Item label="Срок закрытия">
|
|
509
|
+
{DAY.format(new Date(deal.due))}
|
|
510
|
+
</DescriptionList.Item>
|
|
511
|
+
<DescriptionList.Item label="Ответственный">
|
|
512
|
+
<span className={styles.owner}>
|
|
513
|
+
{ownerAvatar(deal.owner)}
|
|
514
|
+
{deal.owner.name}
|
|
515
|
+
</span>
|
|
516
|
+
</DescriptionList.Item>
|
|
517
|
+
<DescriptionList.Item label="Контакт">{deal.contact}</DescriptionList.Item>
|
|
518
|
+
<DescriptionList.Item label="Источник">{deal.source}</DescriptionList.Item>
|
|
519
|
+
<DescriptionList.Item label="Договор">
|
|
520
|
+
{deal.contract ? (
|
|
521
|
+
<Badge.Root color="green">Подписан</Badge.Root>
|
|
522
|
+
) : (
|
|
523
|
+
<Badge.Root color="gray">Не подписан</Badge.Root>
|
|
524
|
+
)}
|
|
525
|
+
</DescriptionList.Item>
|
|
526
|
+
</DescriptionList.Root>
|
|
527
|
+
) : null}
|
|
528
|
+
</Drawer.Body>
|
|
529
|
+
<Drawer.Footer>
|
|
530
|
+
<Drawer.Close>
|
|
531
|
+
<Button.Root variant="outline" tone="neutral">
|
|
532
|
+
Закрыть
|
|
533
|
+
</Button.Root>
|
|
534
|
+
</Drawer.Close>
|
|
535
|
+
<Dropdown.Root>
|
|
536
|
+
<Dropdown.Trigger>
|
|
537
|
+
<Button.Root variant="soft" tone="neutral" disabled={saving}>
|
|
538
|
+
Сменить этап
|
|
539
|
+
</Button.Root>
|
|
540
|
+
</Dropdown.Trigger>
|
|
541
|
+
<Dropdown.Content>
|
|
542
|
+
{STAGES.map((stage) => (
|
|
543
|
+
<Dropdown.Item
|
|
544
|
+
key={stage.id}
|
|
545
|
+
disabled={stage.id === dealStage}
|
|
546
|
+
onSelect={() => {
|
|
547
|
+
if (deal) void moveDeal(deal, stage.id);
|
|
548
|
+
}}
|
|
549
|
+
>
|
|
550
|
+
{stage.title}
|
|
551
|
+
</Dropdown.Item>
|
|
552
|
+
))}
|
|
553
|
+
</Dropdown.Content>
|
|
554
|
+
</Dropdown.Root>
|
|
555
|
+
{nextStage ? (
|
|
556
|
+
<Button.Root
|
|
557
|
+
loading={saving}
|
|
558
|
+
onClick={() => {
|
|
559
|
+
if (deal) void moveDeal(deal, nextStage.id);
|
|
560
|
+
}}
|
|
561
|
+
>
|
|
562
|
+
В «{nextStage.title}»
|
|
563
|
+
</Button.Root>
|
|
564
|
+
) : null}
|
|
565
|
+
</Drawer.Footer>
|
|
566
|
+
</Drawer.Content>
|
|
567
|
+
</Drawer.Root>
|
|
568
|
+
</PageContent.Body>
|
|
569
|
+
</PageContent.Root>
|
|
570
|
+
</>
|
|
571
|
+
);
|
|
572
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/** Loading draws skeleton cards in the card geometry and cross-fades the cards in; an empty column keeps its drop area; a read-only board drags nothing — `loading`, `disabled`. */
|
|
2
|
-
import { Button, Icon, Kanban, Switch } from "prime-ui-kit";
|
|
1
|
+
/** Loading draws skeleton cards in the card geometry and cross-fades the cards in; an empty column keeps its drop area; a closed order stays in place while the rest move; a read-only board drags nothing — `loading`, `disabled`. */
|
|
2
|
+
import { Badge, Button, Icon, Kanban, Switch } from "prime-ui-kit";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
5
5
|
import styles from "./examples.module.css";
|
|
6
6
|
|
|
7
|
-
type Order = { id: string; title: string; total: string };
|
|
7
|
+
type Order = { id: string; title: string; total: string; closed?: boolean };
|
|
8
8
|
|
|
9
9
|
const COLUMNS = [
|
|
10
10
|
{ id: "new", title: "Новые" },
|
|
@@ -12,13 +12,19 @@ const COLUMNS = [
|
|
|
12
12
|
{ id: "shipped", title: "Отгружены" },
|
|
13
13
|
];
|
|
14
14
|
|
|
15
|
+
/** A closed order has signed documents: its card stays where it is. */
|
|
15
16
|
const ORDERS: Order[] = [
|
|
16
17
|
{ id: "ORD-5531", title: "ООО «Север» · 12 позиций", total: "48 300 ₽" },
|
|
17
18
|
{ id: "ORD-5529", title: "ИП Лебедев · 3 позиции", total: "7 950 ₽" },
|
|
18
|
-
{ id: "ORD-5524", title: "АО «Гранит» · 40 позиций", total: "212 000 ₽" },
|
|
19
|
+
{ id: "ORD-5524", title: "АО «Гранит» · 40 позиций", total: "212 000 ₽", closed: true },
|
|
20
|
+
{ id: "ORD-5518", title: "ООО «Вектор» · 6 позиций", total: "31 400 ₽" },
|
|
19
21
|
];
|
|
20
22
|
|
|
21
|
-
const PLACEMENT = {
|
|
23
|
+
const PLACEMENT = {
|
|
24
|
+
new: ["ORD-5531", "ORD-5529"],
|
|
25
|
+
packing: [],
|
|
26
|
+
shipped: ["ORD-5524", "ORD-5518"],
|
|
27
|
+
};
|
|
22
28
|
|
|
23
29
|
const LOAD_MS = 1200;
|
|
24
30
|
|
|
@@ -62,11 +68,16 @@ export default function KanbanStatesExample() {
|
|
|
62
68
|
loading={loading}
|
|
63
69
|
disabled={readOnly}
|
|
64
70
|
renderItem={(order) => (
|
|
65
|
-
<Kanban.Item>
|
|
71
|
+
<Kanban.Item disabled={order.closed}>
|
|
66
72
|
<Kanban.ItemTitle>{order.id}</Kanban.ItemTitle>
|
|
67
73
|
<Kanban.ItemDescription>
|
|
68
74
|
{order.title} · {order.total}
|
|
69
75
|
</Kanban.ItemDescription>
|
|
76
|
+
{order.closed ? (
|
|
77
|
+
<Kanban.ItemBadges>
|
|
78
|
+
<Badge.Root color="gray">Закрыт</Badge.Root>
|
|
79
|
+
</Kanban.ItemBadges>
|
|
80
|
+
) : null}
|
|
70
81
|
</Kanban.Item>
|
|
71
82
|
)}
|
|
72
83
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LoginForm
|
|
2
2
|
|
|
3
|
-
**Category:**
|
|
3
|
+
**Category:** page
|
|
4
4
|
**Kind:** composite
|
|
5
5
|
|
|
6
6
|
> A sign-in card with a logo, title, provider buttons and a form; covers sign-in, sign-up, password reset and code confirmation.
|
|
@@ -54,7 +54,7 @@ Every part is optional except `Root`, `Title` and `Form`. Fields, buttons, divid
|
|
|
54
54
|
`ref` → `HTMLElement`. `<header>` with the logo, title and description, laid out by Root `align`. Native props.
|
|
55
55
|
|
|
56
56
|
### LoginForm.Logo
|
|
57
|
-
`ref` → `HTMLDivElement`. A tile for the product mark or an icon (accent tile with `start`, round with `center`); decorative unless it has an `aria-label
|
|
57
|
+
`ref` → `HTMLDivElement`. A tile for the product mark or an icon (accent tile with `start`, round with `center`); decorative unless it has an `aria-label` — then it is the product mark image (`role="img"`). Native `<div>` props.
|
|
58
58
|
|
|
59
59
|
### LoginForm.Title
|
|
60
60
|
`ref` → `HTMLHeadingElement`. The heading (kit Typography, text role by the tier).
|
|
@@ -119,7 +119,7 @@ Root carries `data-size`, `data-align` and `data-flat`.
|
|
|
119
119
|
## Layout & spacing
|
|
120
120
|
- header → body `--prime-space-8` (gap on Root); provider buttons → divider → form `--prime-space-4`; field → field → submit `--prime-space-5`; submit → back action `--prime-space-3`; form → footer `--prime-space-6`.
|
|
121
121
|
- Spacing is `gap` on parents; no margins between parts.
|
|
122
|
-
- The card has no border
|
|
122
|
+
- The card has no border, takes the full width up to the small modal width. To center it on a page, wrap it in your own flex container on the page.
|
|
123
123
|
- The form is a layer of the surface ladder like Card (`data-depth`): on the page it is white in light with the raised whisper, fields inside are one step off it.
|
|
124
124
|
|
|
125
125
|
## Accessibility
|
|
@@ -129,6 +129,7 @@ No keyboard interaction.
|
|
|
129
129
|
|
|
130
130
|
### ARIA
|
|
131
131
|
- The title is a real heading (`h1` by default) and the form is a native `<form>`: Enter submits.
|
|
132
|
+
- The logo is decorative; with an `aria-label` it is the product mark image (`role="img"`).
|
|
132
133
|
- Give `LoginForm.Form` an `aria-label` (or `aria-labelledby` pointing to the title id) so the form is a landmark.
|
|
133
134
|
- Fields use `autoComplete` (`email`, `current-password`, `new-password`, `one-time-code`) so password managers and OTP autofill work.
|
|
134
135
|
- Server errors in a Banner need `role="alert"`; field errors come from the fields (`aria-invalid`, described by the error).
|
|
@@ -141,9 +142,9 @@ No `labels`.
|
|
|
141
142
|
## Examples
|
|
142
143
|
| Example | Shows |
|
|
143
144
|
|---|---|
|
|
144
|
-
| [overview.tsx](examples/overview.tsx) | Sign in with a provider button, e-mail and password, a «forgot password» link and a sign-up link under a centered header — `align`, `LoginForm.Actions`, `LoginForm.Form`, `LoginForm.Footer`. |
|
|
145
|
+
| [overview.tsx](examples/overview.tsx) | Sign in with a provider button, e-mail and password, a «forgot password» link and a sign-up link under a centered header with the product's named mark — `align`, `LoginForm.Logo`, `LoginForm.Actions`, `LoginForm.Form`, `LoginForm.Footer`. |
|
|
145
146
|
| [sizes.tsx](examples/sizes.tsx) | Padding, gaps and text roles of the card follow the tier; the fields and buttons take the same one — `size`. |
|
|
146
|
-
| [structure.tsx](examples/structure.tsx) | The minimal form: no logo, description or footer,
|
|
147
|
+
| [structure.tsx](examples/structure.tsx) | The minimal form: no logo, description or footer, no shadow for a host that already is a surface and a second-level title under the host page's own heading — `flat`, `as`. |
|
|
147
148
|
| [register.tsx](examples/register.tsx) | Sign-up: five fields in one column, a strength meter on the new password and a mismatch shown as the field error — `strength`, `error`, `LoginForm.Form`. |
|
|
148
149
|
| [forgot-password.tsx](examples/forgot-password.tsx) | Password reset request: one field, the primary action and a quiet way back — `LoginForm.Actions`. |
|
|
149
150
|
| [reset-password.tsx](examples/reset-password.tsx) | A new password after the e-mail link: a strength meter on the first field and a mismatch error under the second one — `strength`, `error`. |
|