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,298 @@
|
|
|
1
|
+
/** A create form in a Drawer opened from the primary action in the app header: grouped fields, errors on submit with focus on the first invalid field, a loading submit, a toast and the new row in the list — `Drawer.Trigger`, `Drawer.Guard`. */
|
|
2
|
+
import {
|
|
3
|
+
AppHeader,
|
|
4
|
+
Badge,
|
|
5
|
+
Button,
|
|
6
|
+
Checkbox,
|
|
7
|
+
DataTable,
|
|
8
|
+
type DataTableColumn,
|
|
9
|
+
Drawer,
|
|
10
|
+
Fieldset,
|
|
11
|
+
Icon,
|
|
12
|
+
Input,
|
|
13
|
+
PageContent,
|
|
14
|
+
PageToolbar,
|
|
15
|
+
Radio,
|
|
16
|
+
Select,
|
|
17
|
+
SmartFilter,
|
|
18
|
+
Textarea,
|
|
19
|
+
useNotifications,
|
|
20
|
+
} from "prime-ui-kit";
|
|
21
|
+
import * as React from "react";
|
|
22
|
+
|
|
23
|
+
import styles from "./screen.module.css";
|
|
24
|
+
|
|
25
|
+
type Client = { id: string; name: string; kind: "company" | "person"; manager: string };
|
|
26
|
+
type Errors = Partial<Record<"name" | "inn" | "email", string>>;
|
|
27
|
+
|
|
28
|
+
const MANAGERS = ["Анна Климова", "Илья Петров", "Марат Хасанов"];
|
|
29
|
+
|
|
30
|
+
const CLIENTS: Client[] = [
|
|
31
|
+
{ id: "c1", name: "ООО «Северный ветер»", kind: "company", manager: "Анна Климова" },
|
|
32
|
+
{ id: "c2", name: "АО «Техностиль»", kind: "company", manager: "Илья Петров" },
|
|
33
|
+
{ id: "c3", name: "ИП Соколова М. А.", kind: "person", manager: "Анна Климова" },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const COLUMNS: DataTableColumn<Client>[] = [
|
|
37
|
+
{ id: "name", header: "Клиент", accessor: "name" },
|
|
38
|
+
{
|
|
39
|
+
id: "kind",
|
|
40
|
+
header: "Тип",
|
|
41
|
+
cell: (row) =>
|
|
42
|
+
row.kind === "company" ? (
|
|
43
|
+
<Badge.Root color="blue">Компания</Badge.Root>
|
|
44
|
+
) : (
|
|
45
|
+
<Badge.Root color="purple">ИП</Badge.Root>
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
{ id: "manager", header: "Менеджер", accessor: "manager" },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const CLIENT_WORDS = ["клиент", "клиента", "клиентов"] as const;
|
|
52
|
+
const COMPANY_WORDS = ["компания", "компании", "компаний"] as const;
|
|
53
|
+
|
|
54
|
+
/** «1 клиент», «3 клиента», «5 клиентов». */
|
|
55
|
+
const plural = (count: number, [one, few, many]: readonly [string, string, string]) => {
|
|
56
|
+
const tens = count % 100;
|
|
57
|
+
const ones = count % 10;
|
|
58
|
+
if (tens >= 11 && tens <= 14) return `${count} ${many}`;
|
|
59
|
+
if (ones === 1) return `${count} ${one}`;
|
|
60
|
+
if (ones >= 2 && ones <= 4) return `${count} ${few}`;
|
|
61
|
+
return `${count} ${many}`;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function validate(data: FormData): Errors {
|
|
65
|
+
const errors: Errors = {};
|
|
66
|
+
const name = String(data.get("name") ?? "").trim();
|
|
67
|
+
const inn = String(data.get("inn") ?? "").replace(/\s/g, "");
|
|
68
|
+
const email = String(data.get("email") ?? "").trim();
|
|
69
|
+
if (!name) errors.name = "Введите название клиента";
|
|
70
|
+
if (!/^\d{10}(\d{2})?$/.test(inn)) errors.inn = "ИНН — 10 цифр для компании или 12 для ИП";
|
|
71
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
|
|
72
|
+
errors.email = "Введите почту в формате name@company.ru";
|
|
73
|
+
return errors;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default function DrawerScreenExample() {
|
|
77
|
+
const { notify } = useNotifications();
|
|
78
|
+
const formId = React.useId();
|
|
79
|
+
const [clients, setClients] = React.useState(CLIENTS);
|
|
80
|
+
const [open, setOpen] = React.useState(false);
|
|
81
|
+
const [errors, setErrors] = React.useState<Errors>({});
|
|
82
|
+
const [saving, setSaving] = React.useState(false);
|
|
83
|
+
const [dirty, setDirty] = React.useState(false);
|
|
84
|
+
const [manager, setManager] = React.useState(MANAGERS[0]);
|
|
85
|
+
const [search, setSearch] = React.useState("");
|
|
86
|
+
|
|
87
|
+
// Drawer.Guard holds every way out while saving and asks before an edited form is discarded.
|
|
88
|
+
const changeOpen = (next: boolean) => {
|
|
89
|
+
setOpen(next);
|
|
90
|
+
if (!next) {
|
|
91
|
+
setErrors({});
|
|
92
|
+
setDirty(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const submit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
const form = event.currentTarget;
|
|
99
|
+
const data = new FormData(form);
|
|
100
|
+
const found = validate(data);
|
|
101
|
+
setErrors(found);
|
|
102
|
+
const firstInvalid = (["name", "inn", "email"] as const).find((key) => found[key]);
|
|
103
|
+
if (firstInvalid) {
|
|
104
|
+
form.querySelector<HTMLInputElement>(`[name="${firstInvalid}"]`)?.focus();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
setSaving(true);
|
|
108
|
+
window.setTimeout(() => {
|
|
109
|
+
const name = String(data.get("name")).trim();
|
|
110
|
+
setClients((list) => [
|
|
111
|
+
{
|
|
112
|
+
id: `c${list.length + 1}`,
|
|
113
|
+
name,
|
|
114
|
+
kind: data.get("kind") === "person" ? "person" : "company",
|
|
115
|
+
manager,
|
|
116
|
+
},
|
|
117
|
+
...list,
|
|
118
|
+
]);
|
|
119
|
+
setSaving(false);
|
|
120
|
+
setDirty(false);
|
|
121
|
+
setOpen(false);
|
|
122
|
+
notify({ tone: "success", title: "Клиент добавлен", description: name });
|
|
123
|
+
}, 900);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const query = search.trim().toLowerCase();
|
|
127
|
+
const shown = clients.filter((client) => client.name.toLowerCase().includes(query));
|
|
128
|
+
const people = clients.filter((client) => client.kind === "person").length;
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<>
|
|
132
|
+
{/* The page lives in the app header: the only h1, the counts under it, search and the one
|
|
133
|
+
primary action — the Drawer trigger — in the tools row; main has no PageContent.Header. */}
|
|
134
|
+
<AppHeader.Root>
|
|
135
|
+
<AppHeader.Start>
|
|
136
|
+
<AppHeader.Title>
|
|
137
|
+
Клиенты
|
|
138
|
+
<AppHeader.Description>
|
|
139
|
+
{plural(clients.length, CLIENT_WORDS)} ·{" "}
|
|
140
|
+
{plural(clients.length - people, COMPANY_WORDS)} и {people} ИП
|
|
141
|
+
</AppHeader.Description>
|
|
142
|
+
</AppHeader.Title>
|
|
143
|
+
</AppHeader.Start>
|
|
144
|
+
<AppHeader.Tools>
|
|
145
|
+
<SmartFilter.Root fields={[]} search={search} onSearchChange={setSearch}>
|
|
146
|
+
<PageToolbar.Root aria-label="Клиенты">
|
|
147
|
+
<PageToolbar.Tools>
|
|
148
|
+
<SmartFilter.Toolbar />
|
|
149
|
+
</PageToolbar.Tools>
|
|
150
|
+
<PageToolbar.Actions>
|
|
151
|
+
<Drawer.Root open={open} onOpenChange={changeOpen}>
|
|
152
|
+
<Drawer.Trigger>
|
|
153
|
+
<Button.Root>
|
|
154
|
+
<Button.Icon>
|
|
155
|
+
<Icon name="action.add" />
|
|
156
|
+
</Button.Icon>
|
|
157
|
+
Новый клиент
|
|
158
|
+
</Button.Root>
|
|
159
|
+
</Drawer.Trigger>
|
|
160
|
+
<Drawer.Content>
|
|
161
|
+
<Drawer.Header>
|
|
162
|
+
<Drawer.Title>Новый клиент</Drawer.Title>
|
|
163
|
+
<Drawer.Description>
|
|
164
|
+
Появится в списке и в выборе клиента при выставлении счёта.
|
|
165
|
+
</Drawer.Description>
|
|
166
|
+
</Drawer.Header>
|
|
167
|
+
<Drawer.Body>
|
|
168
|
+
<Drawer.Guard busy={saving} dirty={dirty} />
|
|
169
|
+
<form
|
|
170
|
+
id={formId}
|
|
171
|
+
className={styles.form}
|
|
172
|
+
noValidate
|
|
173
|
+
onSubmit={submit}
|
|
174
|
+
onChange={() => setDirty(true)}
|
|
175
|
+
>
|
|
176
|
+
<Fieldset label="Реквизиты" disabled={saving}>
|
|
177
|
+
<Radio.Group
|
|
178
|
+
name="kind"
|
|
179
|
+
label="Тип клиента"
|
|
180
|
+
defaultValue="company"
|
|
181
|
+
orientation="horizontal"
|
|
182
|
+
>
|
|
183
|
+
<Radio.Root value="company">
|
|
184
|
+
<Radio.Label>Компания</Radio.Label>
|
|
185
|
+
</Radio.Root>
|
|
186
|
+
<Radio.Root value="person">
|
|
187
|
+
<Radio.Label>ИП</Radio.Label>
|
|
188
|
+
</Radio.Root>
|
|
189
|
+
</Radio.Group>
|
|
190
|
+
<Input.Root label="Название" error={errors.name}>
|
|
191
|
+
<Input.Wrapper>
|
|
192
|
+
<Input.Field
|
|
193
|
+
name="name"
|
|
194
|
+
placeholder="ООО «Ромашка»"
|
|
195
|
+
autoComplete="organization"
|
|
196
|
+
/>
|
|
197
|
+
</Input.Wrapper>
|
|
198
|
+
</Input.Root>
|
|
199
|
+
<div className={styles.pair}>
|
|
200
|
+
<Input.Root label="ИНН" error={errors.inn} reserveSupportRow>
|
|
201
|
+
<Input.Wrapper>
|
|
202
|
+
<Input.Field
|
|
203
|
+
name="inn"
|
|
204
|
+
inputMode="numeric"
|
|
205
|
+
placeholder="7704512908"
|
|
206
|
+
/>
|
|
207
|
+
</Input.Wrapper>
|
|
208
|
+
</Input.Root>
|
|
209
|
+
<Input.Root label="КПП" optional reserveSupportRow>
|
|
210
|
+
<Input.Wrapper>
|
|
211
|
+
<Input.Field
|
|
212
|
+
name="kpp"
|
|
213
|
+
inputMode="numeric"
|
|
214
|
+
placeholder="770401001"
|
|
215
|
+
/>
|
|
216
|
+
</Input.Wrapper>
|
|
217
|
+
</Input.Root>
|
|
218
|
+
</div>
|
|
219
|
+
</Fieldset>
|
|
220
|
+
<Fieldset label="Контакты" disabled={saving}>
|
|
221
|
+
<Input.Root
|
|
222
|
+
label="Почта для счетов"
|
|
223
|
+
error={errors.email}
|
|
224
|
+
hint="На неё уйдут счета и акты"
|
|
225
|
+
>
|
|
226
|
+
<Input.Wrapper>
|
|
227
|
+
<Input.Icon side="start">
|
|
228
|
+
<Icon name="field.email" />
|
|
229
|
+
</Input.Icon>
|
|
230
|
+
<Input.Field
|
|
231
|
+
name="email"
|
|
232
|
+
type="email"
|
|
233
|
+
placeholder="billing@company.ru"
|
|
234
|
+
/>
|
|
235
|
+
</Input.Wrapper>
|
|
236
|
+
</Input.Root>
|
|
237
|
+
<Select.Root
|
|
238
|
+
label="Менеджер"
|
|
239
|
+
value={manager}
|
|
240
|
+
onValueChange={(next) => {
|
|
241
|
+
setManager(next);
|
|
242
|
+
setDirty(true);
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
<Select.Trigger>
|
|
246
|
+
<Select.Value />
|
|
247
|
+
</Select.Trigger>
|
|
248
|
+
<Select.Content>
|
|
249
|
+
{MANAGERS.map((name) => (
|
|
250
|
+
<Select.Item key={name} value={name}>
|
|
251
|
+
{name}
|
|
252
|
+
</Select.Item>
|
|
253
|
+
))}
|
|
254
|
+
</Select.Content>
|
|
255
|
+
</Select.Root>
|
|
256
|
+
<Textarea.Root name="note" label="Комментарий" optional rows={2} />
|
|
257
|
+
<Checkbox.Root
|
|
258
|
+
name="invite"
|
|
259
|
+
defaultChecked
|
|
260
|
+
hint="Клиент увидит свои счета и акты онлайн"
|
|
261
|
+
>
|
|
262
|
+
<Checkbox.Label>Пригласить в личный кабинет</Checkbox.Label>
|
|
263
|
+
</Checkbox.Root>
|
|
264
|
+
</Fieldset>
|
|
265
|
+
</form>
|
|
266
|
+
</Drawer.Body>
|
|
267
|
+
<Drawer.Footer>
|
|
268
|
+
<Drawer.Close>
|
|
269
|
+
<Button.Root variant="outline" tone="neutral">
|
|
270
|
+
Отмена
|
|
271
|
+
</Button.Root>
|
|
272
|
+
</Drawer.Close>
|
|
273
|
+
<Button.Root type="submit" form={formId} loading={saving}>
|
|
274
|
+
Добавить клиента
|
|
275
|
+
</Button.Root>
|
|
276
|
+
</Drawer.Footer>
|
|
277
|
+
</Drawer.Content>
|
|
278
|
+
</Drawer.Root>
|
|
279
|
+
</PageToolbar.Actions>
|
|
280
|
+
</PageToolbar.Root>
|
|
281
|
+
</SmartFilter.Root>
|
|
282
|
+
</AppHeader.Tools>
|
|
283
|
+
</AppHeader.Root>
|
|
284
|
+
|
|
285
|
+
<PageContent.Root>
|
|
286
|
+
<PageContent.Body>
|
|
287
|
+
<DataTable
|
|
288
|
+
columns={COLUMNS}
|
|
289
|
+
rows={shown}
|
|
290
|
+
getRowKey={(row) => row.id}
|
|
291
|
+
paging="none"
|
|
292
|
+
empty="Клиентов не найдено"
|
|
293
|
+
/>
|
|
294
|
+
</PageContent.Body>
|
|
295
|
+
</PageContent.Root>
|
|
296
|
+
</>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
@@ -8,15 +8,11 @@
|
|
|
8
8
|
max-width: calc(var(--prime-space-24) * 3);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
/* overview.tsx:
|
|
11
|
+
/* overview.tsx: the record on the left, its actions button at the end. */
|
|
12
12
|
.row {
|
|
13
13
|
display: flex;
|
|
14
14
|
align-items: center;
|
|
15
15
|
justify-content: space-between;
|
|
16
16
|
gap: var(--prime-space-4);
|
|
17
17
|
width: min(100%, calc(var(--prime-space-24) * 4));
|
|
18
|
-
padding-block: var(--prime-space-1);
|
|
19
|
-
padding-inline: var(--prime-space-4) var(--prime-space-1);
|
|
20
|
-
border-radius: var(--prime-radius-l);
|
|
21
|
-
background: var(--prime-color-layer-nested);
|
|
22
18
|
}
|
|
@@ -148,7 +148,7 @@ EmptyPage.Root centered column; size, layout, tone (role="alert" w
|
|
|
148
148
|
| [variants.tsx](examples/variants.tsx) | The tone tells why the area is empty: no data yet, a first run, or a failed load with a retry — `tone`, `EmptyPage.RetryButton`. |
|
|
149
149
|
| [sizes.tsx](examples/sizes.tsx) | Every tier changes the icon tile, the title and the padding; buttons in Actions take the same size — `size`. |
|
|
150
150
|
| [data-region.tsx](examples/data-region.tsx) | An empty data region: the empty state stretches over the rest of a card with a header — `layout`. |
|
|
151
|
-
| [region-error.tsx](examples/region-error.tsx) | A data region that failed to load: the error state takes the region, the retry shows its loading until the data cross-fades in — `tone`, `layout`, `EmptyPage.RetryButton`, `onRetry`. |
|
|
151
|
+
| [region-error.tsx](examples/region-error.tsx) | A data region that failed to load: the error state takes the region, the retry shows its loading until the data cross-fades in; its text comes from labels — `tone`, `layout`, `EmptyPage.RetryButton`, `onRetry`, `labels`. |
|
|
152
152
|
| [compact.tsx](examples/compact.tsx) | The quiet empty state of a search panel: no entrance motion, smaller text, a paragraph title, one action — `layout`, `as`. |
|
|
153
153
|
| [narrow.tsx](examples/narrow.tsx) | In a 320 px side panel the text wraps under the tile and the actions wrap to a second line. |
|
|
154
154
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** A data region that failed to load: the error state takes the region, the retry shows its loading until the data cross-fades in — `tone`, `layout`, `EmptyPage.RetryButton`, `onRetry`. */
|
|
1
|
+
/** A data region that failed to load: the error state takes the region, the retry shows its loading until the data cross-fades in; its text comes from labels — `tone`, `layout`, `EmptyPage.RetryButton`, `onRetry`, `labels`. */
|
|
2
2
|
import { Button, Card, Crossfade, EmptyPage, Icon, Skeleton, Typography } from "prime-ui-kit";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
@@ -53,7 +53,13 @@ export default function EmptyPageRegionErrorExample() {
|
|
|
53
53
|
{state === "loading" ? (
|
|
54
54
|
<Skeleton lines={3} />
|
|
55
55
|
) : state === "error" ? (
|
|
56
|
-
<EmptyPage.Root
|
|
56
|
+
<EmptyPage.Root
|
|
57
|
+
layout="fill"
|
|
58
|
+
size="s"
|
|
59
|
+
tone="danger"
|
|
60
|
+
labels={{ retry: "Загрузить снова" }}
|
|
61
|
+
aria-labelledby="invoices-error"
|
|
62
|
+
>
|
|
57
63
|
<EmptyPage.Icon>
|
|
58
64
|
<Icon name="status.offline" />
|
|
59
65
|
</EmptyPage.Icon>
|
|
@@ -59,7 +59,7 @@ ExampleFrame frame: toolbar + preview stage or code pane
|
|
|
59
59
|
| `stack-narrow` | column, children capped at `7 × --prime-space-16` and centered | forms and narrow columns | |
|
|
60
60
|
| `full` | column, gap 16, every child takes the whole stage width | page structure: app shells, page regions | |
|
|
61
61
|
| `row` | centered wrapping row, gap 12, extra vertical padding | a few buttons or controls side by side | |
|
|
62
|
-
| `matrix` | centered grid of labelled cells: each direct child is a row, its children are cells (specimen above its caption); columns (up to 12) line up across rows, are never narrower than their content and grow to 320 / 160 / 128px for 1 / 2 / 3+ columns, so width-less specimens (Slider, `width: 100%` blocks) get a real cell;
|
|
62
|
+
| `matrix` | centered grid of labelled cells: each direct child is a row, its children are cells (specimen above its caption); columns (up to 12) line up across rows, are never narrower than their content and grow to 320 / 160 / 128px for 1 / 2 / 3+ columns, so width-less specimens (Slider, `width: 100%` blocks) get a real cell; centered vertically too; when the grid is wider than the stage (a phone frame) each row wraps its cells, centered (`data-matrix-wrap` on the stage) | variant, size and state matrices | |
|
|
63
63
|
|
|
64
64
|
### viewport
|
|
65
65
|
| Value | Looks like | Use when | Default |
|
|
@@ -87,7 +87,7 @@ Frame look: the chrome is a layer of the surface ladder (`data-depth`, one above
|
|
|
87
87
|
|
|
88
88
|
## Layout & spacing
|
|
89
89
|
- The frame is `max-width: 100%`; long code lines scroll inside the code pane instead of widening the page. The code pane is at most `min(512px, 70vh)` high and scrolls both ways.
|
|
90
|
-
- The stage is at least 160 high with `--prime-space-6` / `--prime-space-4` padding; content wider than it is clipped (`matrix`
|
|
90
|
+
- The stage is at least 160 high with `--prime-space-6` / `--prime-space-4` padding; content wider than it is clipped (`matrix` wraps its rows instead).
|
|
91
91
|
- The toolbar wraps below 40rem of frame width; below 25rem the visible device labels are hidden (icons stay, each option keeps a screen-reader name).
|
|
92
92
|
- The device width switches at once: `max-width` is layout, so it does not animate.
|
|
93
93
|
- Stack frames one per demo block; spacing between blocks comes from the page.
|
|
@@ -128,6 +128,7 @@ Frame look: the chrome is a layer of the surface ladder (`data-depth`, one above
|
|
|
128
128
|
| Example | Shows |
|
|
129
129
|
|---|---|
|
|
130
130
|
| [overview.tsx](examples/overview.tsx) | A live example next to its source, with the pane, width, theme and copy controls — `code`, `previewLayout`. |
|
|
131
|
+
| [initial-view.tsx](examples/initial-view.tsx) | A matrix frame that opens at phone width in the dark theme with no theme switch and counts code copies — `previewLayout`, `defaultViewport`, `defaultColorScheme`, `showThemeToggle`, `onCopy`. |
|
|
131
132
|
| [controlled.tsx](examples/controlled.tsx) | Frames of one page share the preview width and theme: the parent owns both — `viewport`, `colorScheme`. |
|
|
132
133
|
|
|
133
134
|
## Mistakes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** A matrix frame that opens at phone width in the dark theme with no theme switch and counts code copies — `previewLayout`, `defaultViewport`, `defaultColorScheme`, `showThemeToggle`, `onCopy`. */
|
|
2
|
+
import { Badge, ExampleFrame, Typography } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
const STATUSES = [
|
|
6
|
+
{ color: "gray", label: "Черновик" },
|
|
7
|
+
{ color: "blue", label: "На ревью" },
|
|
8
|
+
{ color: "green", label: "Опубликован" },
|
|
9
|
+
] as const;
|
|
10
|
+
|
|
11
|
+
const CODE = STATUSES.map(
|
|
12
|
+
({ color, label }) => `<Badge.Root color="${color}">${label}</Badge.Root>`,
|
|
13
|
+
).join("\n");
|
|
14
|
+
|
|
15
|
+
export default function ExampleFrameInitialViewExample() {
|
|
16
|
+
const [copies, setCopies] = React.useState(0);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<>
|
|
20
|
+
<ExampleFrame
|
|
21
|
+
code={CODE}
|
|
22
|
+
previewLayout="matrix"
|
|
23
|
+
defaultViewport="mobile"
|
|
24
|
+
defaultColorScheme="dark"
|
|
25
|
+
showThemeToggle={false}
|
|
26
|
+
onCopy={() => setCopies((count) => count + 1)}
|
|
27
|
+
>
|
|
28
|
+
<div>
|
|
29
|
+
{STATUSES.map(({ color, label }) => (
|
|
30
|
+
<div key={color}>
|
|
31
|
+
<Badge.Root color={color}>{label}</Badge.Root>
|
|
32
|
+
<Typography as="span" variant="caption" tone="muted">
|
|
33
|
+
{color}
|
|
34
|
+
</Typography>
|
|
35
|
+
</div>
|
|
36
|
+
))}
|
|
37
|
+
</div>
|
|
38
|
+
</ExampleFrame>
|
|
39
|
+
<Typography variant="body-s" tone="secondary">
|
|
40
|
+
Код скопирован: {copies}
|
|
41
|
+
</Typography>
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -144,10 +144,11 @@ Generic `FieldList<T>`; `ref` → `HTMLDivElement` (the field frame). An editabl
|
|
|
144
144
|
| [locked.tsx](examples/locked.tsx) | Specs of a plan on one line each: an icon picker and a color swatch take compact columns, the first three specs are pinned with a lock and the rest reorder below them — `getLocked`, `width`, `reorderable`. |
|
|
145
145
|
| [base-row.tsx](examples/base-row.tsx) | A plan price and its changes by month in one table: the base price is the first, pinned row, each change is a row with its month and its price, and the unit sits in the field, not in a heading — `getLocked`, `width`. |
|
|
146
146
|
| [limits.tsx](examples/limits.tsx) | Recipients of invoice reminders, from one to three: the last row cannot be removed and the add button says why it is off once the list is full — `min`, `max`, `hint`. |
|
|
147
|
-
| [errors.tsx](examples/errors.tsx) | Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field — `error`. |
|
|
147
|
+
| [errors.tsx](examples/errors.tsx) | Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field; a `*` after a heading marks a required column — `error`, `required`. |
|
|
148
148
|
| [states.tsx](examples/states.tsx) | The same list editable and disabled while the request saves it: fields, handles and buttons turn off together — `disabled`. |
|
|
149
149
|
| [controlled.tsx](examples/controlled.tsx) | The parent owns the lines: it sums them under the list and puts the saved lines back on reset — `value`, `onValueChange`. |
|
|
150
150
|
| [narrow.tsx](examples/narrow.tsx) | The invoice lines in a 320 px column: the headings give way, each row stacks its fields with their own labels and rows stand a group apart — `columns`. |
|
|
151
|
+
| [screen.tsx](examples/screen.tsx) | A record editor as a document page, a long form whose title, description and save stand in the content header: a plan's name, its specs and prices in one form; repeating records as FieldList rows with the headings once, a base price pinned above its changes, one value in three currencies in one row — `getLocked`, `compact`. |
|
|
151
152
|
|
|
152
153
|
## Mistakes
|
|
153
154
|
- A `label` above every field of every row («Иконка», «Параметр», «Значение» four times) → a FieldList: the headings stand once, the fields take them as hidden labels.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field — `error`. */
|
|
1
|
+
/** Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field; a `*` after a heading marks a required column — `error`, `required`. */
|
|
2
2
|
import { Button, FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
@@ -6,7 +6,10 @@ import styles from "./examples.module.css";
|
|
|
6
6
|
|
|
7
7
|
type Contact = { id: string; role: string; phone: string };
|
|
8
8
|
|
|
9
|
-
const COLUMNS: FieldListColumn[] = [
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [
|
|
10
|
+
{ label: "Должность", required: true },
|
|
11
|
+
{ label: "Телефон", width: "m", required: true },
|
|
12
|
+
];
|
|
10
13
|
|
|
11
14
|
const CONTACTS: Contact[] = [
|
|
12
15
|
{ id: "buyer", role: "Закупщик", phone: "+7 912 404-18-20" },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** A record editor: a plan's name, its specs
|
|
1
|
+
/** A record editor as a document page, a long form whose title, description and save stand in the content header: a plan's name, its specs and prices in one form; repeating records as FieldList rows with the headings once, a base price pinned above its changes, one value in three currencies in one row — `getLocked`, `compact`. */
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
4
|
Card,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "prime-ui-kit";
|
|
16
16
|
import * as React from "react";
|
|
17
17
|
|
|
18
|
-
import styles from "./
|
|
18
|
+
import styles from "./screen.module.css";
|
|
19
19
|
|
|
20
20
|
type Spec = {
|
|
21
21
|
id: string;
|
|
@@ -25,7 +25,6 @@ type Spec = {
|
|
|
25
25
|
color: string;
|
|
26
26
|
pinned?: boolean;
|
|
27
27
|
};
|
|
28
|
-
type Point = { id: string; text: string };
|
|
29
28
|
type Period = { id: string; from: string; price: string; base?: boolean };
|
|
30
29
|
|
|
31
30
|
const SPEC_COLUMNS: FieldListColumn[] = [
|
|
@@ -73,14 +72,6 @@ const SPECS: Spec[] = [
|
|
|
73
72
|
{ id: "sso", icon: "object.key", name: "Вход через SSO", value: "SAML, OIDC", color: "#14b8a6" },
|
|
74
73
|
];
|
|
75
74
|
|
|
76
|
-
const POINT_COLUMNS: FieldListColumn[] = [{ label: "Преимущество" }];
|
|
77
|
-
|
|
78
|
-
const POINTS: Point[] = [
|
|
79
|
-
{ id: "space", text: "Вся команда в одном пространстве" },
|
|
80
|
-
{ id: "files", text: "Документы и вложения без ограничений по типу" },
|
|
81
|
-
{ id: "api", text: "API и вебхуки для своих интеграций" },
|
|
82
|
-
];
|
|
83
|
-
|
|
84
75
|
const PRICE_COLUMNS: FieldListColumn[] = [{ label: "Действует" }, { label: "Цена", width: "m" }];
|
|
85
76
|
|
|
86
77
|
const MONTHS = [
|
|
@@ -104,10 +95,9 @@ const SETUP_FEE = [
|
|
|
104
95
|
const SAVE_MS = 900;
|
|
105
96
|
const SAVED_MS = 2000;
|
|
106
97
|
|
|
107
|
-
export default function
|
|
98
|
+
export default function FieldListScreenExample() {
|
|
108
99
|
const formId = React.useId();
|
|
109
100
|
const [specs, setSpecs] = React.useState(SPECS);
|
|
110
|
-
const [points, setPoints] = React.useState(POINTS);
|
|
111
101
|
const [periods, setPeriods] = React.useState(PERIODS);
|
|
112
102
|
const [nameError, setNameError] = React.useState<string>();
|
|
113
103
|
const [saving, setSaving] = React.useState(false);
|
|
@@ -242,36 +232,6 @@ export default function RecordEditorPattern() {
|
|
|
242
232
|
</Card.Root>
|
|
243
233
|
</PageContent.Section>
|
|
244
234
|
|
|
245
|
-
<PageContent.Section layout="aside" label="Преимущества">
|
|
246
|
-
<Card.Root variant="panel">
|
|
247
|
-
<Card.Body>
|
|
248
|
-
<FieldList
|
|
249
|
-
aria-label="Преимущества"
|
|
250
|
-
disabled={saving}
|
|
251
|
-
columns={POINT_COLUMNS}
|
|
252
|
-
reorderable
|
|
253
|
-
max={6}
|
|
254
|
-
value={points}
|
|
255
|
-
onValueChange={setPoints}
|
|
256
|
-
getId={(point) => point.id}
|
|
257
|
-
getLabel={(point) => point.text}
|
|
258
|
-
createItem={() => ({ id: crypto.randomUUID(), text: "" })}
|
|
259
|
-
addLabel="Добавить преимущество"
|
|
260
|
-
renderItem={(point, row) => (
|
|
261
|
-
<Input.Root>
|
|
262
|
-
<Input.Wrapper>
|
|
263
|
-
<Input.Field
|
|
264
|
-
value={point.text}
|
|
265
|
-
onChange={(event) => row.update({ text: event.target.value })}
|
|
266
|
-
/>
|
|
267
|
-
</Input.Wrapper>
|
|
268
|
-
</Input.Root>
|
|
269
|
-
)}
|
|
270
|
-
/>
|
|
271
|
-
</Card.Body>
|
|
272
|
-
</Card.Root>
|
|
273
|
-
</PageContent.Section>
|
|
274
|
-
|
|
275
235
|
<PageContent.Section layout="aside" label="Стоимость">
|
|
276
236
|
<Card.Root variant="panel">
|
|
277
237
|
<Card.Body className={styles.groups}>
|
|
@@ -288,7 +288,7 @@ A rejection of `upload` fails the file with its message as the reason; retry que
|
|
|
288
288
|
| disabled | `disabled` | `data-disabled="true"`, disabled input, disabled fill and text, drops ignored; no add tile, actions or drag; a disabled button with `trigger="button"` |
|
|
289
289
|
| empty | no files, `trigger="tile"` | the add tile spans the row with «Нажмите или перетащите файлы» |
|
|
290
290
|
| cover | `cover`, the first tile | «Обложка» in place of the format pill, `data-cover` on the tiles wrapper (the first tile takes a 2 × 2 cell in a grid) |
|
|
291
|
-
| full | the set reaches `max` | `data-full` on the add tile: «Лимит файлов», faded
|
|
291
|
+
| full | the set reaches `max` | `data-full` on the add tile: «Лимит файлов», faded; the file input is `aria-disabled` and opens no picker, so the field label stays undimmed |
|
|
292
292
|
| queued | queue item `status: "queued"` | a row reads «size · В очереди» over an empty bar; a tile (`data-upload="queued"`) dims under a 40px disk on the `media` shade (Button `shape="circle"` `variant="shade"`) whose ring turns at its least arc, described by «В очереди» |
|
|
293
293
|
| loading | `status: "loading"` | a row reads «size · Загрузка 40%» and its bar fills (`accent`); a tile's white arc grows clockwise from 12 o'clock with the share sent (the `progress` ring of a shade circle Button, one variable `--ring-value`, gliding `base` while it turns); the disk is the remove («Отменить загрузку: name», described by the state), the corner × is not drawn; the tile still reorders, its carried copy keeps the disk |
|
|
294
294
|
| done | `status: "done"` | a row reads «size» over a full `success` bar; a tile's ring fills, then its disk fades and shrinks to 0.9 (`fast`, `inert`), the picture returns to full or the sheet comes back |
|
|
@@ -372,20 +372,21 @@ Also `data-size`, `data-variant` on the zone, `data-size` on Item, `data-status`
|
|
|
372
372
|
| Example | Shows |
|
|
373
373
|
|---|---|
|
|
374
374
|
| [overview.tsx](examples/overview.tsx) | Documents of a deal: a drop zone, the files already attached as rows whose names open them, and new files uploading through a queue with progress, a reason and a retry — `label`, `hint`, `multiple`, `defaultValue`, `href`, `queue`. |
|
|
375
|
-
| [variants.tsx](examples/variants.tsx) | How files are added: the dashed drop zone, the zone with only its fill for cards and modals, the compact picker button and the add tile
|
|
375
|
+
| [variants.tsx](examples/variants.tsx) | How files are added: the dashed drop zone, the zone with only its fill for cards and modals, the compact picker button and the add tile that starts an empty set of tiles — `variant`, `trigger`. |
|
|
376
376
|
| [sizes.tsx](examples/sizes.tsx) | Every tier of the zone and of its file rows: padding, icon, button, text and the format badge follow it — `size`. |
|
|
377
377
|
| [states.tsx](examples/states.tsx) | A default zone, a disabled one whose files are read-only and an invalid one without a message — `disabled`, `invalid`. |
|
|
378
378
|
| [validation.tsx](examples/validation.tsx) | A required scan checked as soon as it is picked: a wrong type or a large file shakes in an error that leaves when the file is removed; a hint and an optional zone — `required`, `hint`, `error`, `optional`. |
|
|
379
|
-
| [gallery.tsx](examples/gallery.tsx) | An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, and the add tile counts up to the limit — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. |
|
|
380
|
-
| [file-cards.tsx](examples/file-cards.tsx) | Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`. |
|
|
379
|
+
| [gallery.tsx](examples/gallery.tsx) | An image gallery of an office listing: the first photo is the cover on two tiles and a photo dragged first takes its place, new photos upload in their tiles, one fails and retries, and the add tile counts up to the limit and then says so — `trigger`, `layout`, `cover`, `max`, `value`, `queue`. |
|
|
380
|
+
| [file-cards.tsx](examples/file-cards.tsx) | Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size in megabytes as the report gives it; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`, `formatSize`. |
|
|
381
381
|
| [attachment-tray.tsx](examples/attachment-tray.tsx) | A reply to a client with a paperclip instead of a drop zone: the icon-only picker button, and the attachments as one scrolling row of tiles above the message — `trigger`, `aria-label`, `FileUpload.Queue`, `layout`. |
|
|
382
382
|
| [saving.tsx](examples/saving.tsx) | Published listing photos with no picker, every change saved on the server: a moved or removed photo waits busy, and a change the server refuses puts the set back — `FileUpload.Queue`, `onValueChange`, `value`, `cover`. |
|
|
383
|
-
| [custom-body.tsx](examples/custom-body.tsx) | A custom body: a muted title with a browse link and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`. |
|
|
383
|
+
| [custom-body.tsx](examples/custom-body.tsx) | A custom body: a muted title with a browse link and the formats line and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`, `FileUpload.Description`. |
|
|
384
384
|
| [avatar-upload.tsx](examples/avatar-upload.tsx) | A round zone around an Avatar that takes images and shows a preview; buttons open the same input — `inputRef`, `accept`, `className`. |
|
|
385
|
-
| [row-parts.tsx](examples/row-parts.tsx) | Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview
|
|
385
|
+
| [row-parts.tsx](examples/row-parts.tsx) | Rows the set does not draw, built from parts: order documents with a download button, a photo with its preview, a report still being prepared and one that failed with a retry — `FileUpload.Item`, `FileUpload.FormatBadge`, `FileUpload.ItemPreview`, `FileUpload.ItemActions`, `FileUpload.ItemProgress`, `invalid`, `tone`. |
|
|
386
386
|
| [controlled.tsx](examples/controlled.tsx) | Documents of a deal in one list: the files already on the server and new uploads after them, saved on every change, and a button brings back the saved set — `value`, `onValueChange`, `queue`. |
|
|
387
387
|
| [in-form.tsx](examples/in-form.tsx) | A contract upload form: submit checks the required scan, its error shakes in and leaves once a file is picked or removed — `required`, `error`, `name`, `value`. |
|
|
388
388
|
| [narrow.tsx](examples/narrow.tsx) | In a phone-width column the zone text wraps, a long file name truncates, and a gallery goes three across and then two, the cover keeping two columns and the remove buttons shown without hover. |
|
|
389
|
+
| [screen.tsx](examples/screen.tsx) | A media library of a catalog object as a work screen: the title, the object and a PageToolbar with sections, search, order and upload in the app header; uploads in FileUpload tiles through a queue; a grid of Thumbnails that open MediaViewer out of the tile or are picked for bulk download and delete; a Skeleton first load and a filtered empty state in a Crossfade — `trigger`, `layout`. |
|
|
389
390
|
|
|
390
391
|
## Mistakes
|
|
391
392
|
- A `Label` and a `Hint` placed around the zone by hand → pass `label`, `hint`, `error`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** A custom body: a muted title with a browse link and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`. */
|
|
1
|
+
/** A custom body: a muted title with a browse link and the formats line and source buttons instead of the built-in one — `FileUpload.Body`, `FileUpload.Title`, `FileUpload.Description`. */
|
|
2
2
|
import { Button, FileUpload, Icon, LinkButton } from "prime-ui-kit";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
@@ -23,6 +23,7 @@ export default function FileUploadCustomBodyExample() {
|
|
|
23
23
|
</button>
|
|
24
24
|
</LinkButton>
|
|
25
25
|
</FileUpload.Title>
|
|
26
|
+
<FileUpload.Description>PDF, JPG или PNG до 20 МБ</FileUpload.Description>
|
|
26
27
|
<div className={styles.sources}>
|
|
27
28
|
<Button.Root variant="soft" tone="neutral" size="s" onClick={openPicker}>
|
|
28
29
|
<Button.Icon>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
flex: 1;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/* in-form.tsx:
|
|
31
|
+
/* in-form.tsx: field → actions 32 (foundation §1). */
|
|
32
32
|
.form {
|
|
33
33
|
display: flex;
|
|
34
34
|
flex-direction: column;
|
|
@@ -36,12 +36,6 @@
|
|
|
36
36
|
width: min(100%, var(--prime-modal-width-s));
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
.formHeader {
|
|
40
|
-
display: flex;
|
|
41
|
-
flex-direction: column;
|
|
42
|
-
gap: var(--prime-space-1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
39
|
.formActions {
|
|
46
40
|
display: flex;
|
|
47
41
|
justify-content: flex-end;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`. */
|
|
1
|
+
/** Materials of a warehouse inspection as cards: photos and documents in one grid, each with its picture or format and the name with the size in megabytes as the report gives it; new files upload in their cards and the order is set by drag or Alt + arrows — `trigger`, `layout`, `defaultValue`, `queue`, `formatSize`. */
|
|
2
2
|
import { FileUpload, type FileUploadFile, type UploadContext, useUploadQueue } from "prime-ui-kit";
|
|
3
3
|
|
|
4
4
|
import styles from "./examples.module.css";
|
|
@@ -27,6 +27,14 @@ const MATERIALS: readonly FileUploadFile[] = [
|
|
|
27
27
|
{ id: "insp-stock", name: "Остатки на 12 марта.xlsx", size: 96_000 },
|
|
28
28
|
];
|
|
29
29
|
|
|
30
|
+
/** Sizes as the inspection report gives them: megabytes with two decimals. */
|
|
31
|
+
const MEGABYTES = new Intl.NumberFormat("ru-RU", {
|
|
32
|
+
minimumFractionDigits: 2,
|
|
33
|
+
maximumFractionDigits: 2,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const formatMegabytes = (bytes: number) => `${MEGABYTES.format(bytes / 1024 / 1024)} МБ`;
|
|
37
|
+
|
|
30
38
|
/** A stand-in for the server: sends a file in a few steps and answers with its address. */
|
|
31
39
|
function sendFile(file: File, { signal, onProgress }: UploadContext): Promise<string> {
|
|
32
40
|
return new Promise((resolve, reject) => {
|
|
@@ -58,6 +66,7 @@ export default function FileUploadFileCardsExample() {
|
|
|
58
66
|
multiple
|
|
59
67
|
defaultValue={MATERIALS}
|
|
60
68
|
queue={queue}
|
|
69
|
+
formatSize={formatMegabytes}
|
|
61
70
|
/>
|
|
62
71
|
</div>
|
|
63
72
|
);
|