prime-ui-kit 0.13.1 → 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 +20 -20
- package/dist/chunks/{chunk-XNOJEX55.js → chunk-2IKH55MI.js} +1 -1
- package/dist/chunks/{chunk-JV2KB5JZ.js → chunk-THFZIHKU.js} +3761 -3041
- package/dist/chunks/{chunk-PK2GC77E.js → chunk-XJAVS6FH.js} +213 -188
- package/dist/color-picker.js +2 -2
- package/dist/components/banner/Banner.d.ts +5 -2
- package/dist/components/chart-frame/ChartFrame.d.ts +19 -6
- package/dist/components/chat/Chat.d.ts +2 -2
- package/dist/components/chat/ChatPinned.d.ts +2 -2
- package/dist/components/chat/MessageList.d.ts +1 -1
- package/dist/components/chat/chatContext.d.ts +1 -1
- package/dist/components/dnd/Dnd.d.ts +1 -1
- package/dist/components/field-list/FieldList.d.ts +90 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/input/Input.d.ts +2 -2
- package/dist/components/kanban/Kanban.d.ts +6 -3
- package/dist/components/login-form/LoginForm.d.ts +5 -1
- package/dist/components/page-content/PageContent.d.ts +55 -4
- package/dist/components/sparkline/Sparkline.d.ts +64 -15
- package/dist/components/sparkline/geometry.d.ts +26 -0
- package/dist/components/tooltip/Tooltip.d.ts +5 -2
- package/dist/hooks/usePosition.d.ts +15 -4
- package/dist/index.css +1 -1
- package/dist/index.js +4 -2
- package/dist/internal/ChartTooltip.d.ts +26 -0
- package/dist/internal/FieldAction.d.ts +6 -7
- package/dist/internal/fieldCell.d.ts +21 -0
- package/dist/internal/messageList.d.ts +2 -2
- package/dist/internal/palette.d.ts +7 -0
- 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 +32 -20
- package/dist/skill/anti-slop.md +77 -4
- package/dist/skill/api-contract.md +2 -2
- package/dist/skill/cheatsheet.md +33 -7
- package/dist/skill/checklist.md +28 -6
- package/dist/skill/choosing.md +17 -14
- package/dist/skill/components.md +9 -15
- package/dist/skill/composition.md +301 -61
- package/dist/skill/foundations.md +9 -7
- package/dist/skill/layouts.md +70 -37
- package/dist/skill/reference/components/avatar/COMPONENT.md +4 -4
- package/dist/skill/reference/components/avatar/examples/presence.tsx +1 -1
- package/dist/skill/reference/components/avatar/examples/states.tsx +5 -5
- 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/COMPONENT.md +6 -6
- package/dist/skill/reference/components/banner/examples/dismissible.tsx +22 -11
- package/dist/skill/reference/components/banner/examples/examples.module.css +4 -8
- package/dist/skill/reference/components/banner/examples/narrow.tsx +1 -1
- package/dist/skill/reference/components/banner/examples/page-strip.tsx +16 -22
- package/dist/skill/reference/components/breadcrumb/COMPONENT.md +5 -4
- package/dist/skill/reference/components/breadcrumb/examples/ellipsis.tsx +2 -2
- package/dist/skill/reference/components/breadcrumb/examples/overflow.tsx +1 -1
- 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 +7 -5
- package/dist/skill/reference/components/card/examples/examples.module.css +0 -28
- package/dist/skill/reference/components/card/examples/kpi-media.tsx +13 -11
- package/dist/skill/reference/components/card/examples/narrow.tsx +1 -1
- package/dist/skill/reference/components/card/examples/panel-chart.tsx +45 -22
- package/dist/skill/reference/components/card/examples/screen.module.css +14 -0
- 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 +12 -8
- 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/chart-frame/examples/tooltip.tsx +20 -24
- package/dist/skill/reference/components/chat/COMPONENT.md +6 -4
- 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} +187 -350
- package/dist/skill/reference/components/chat/examples/search.tsx +1 -1
- package/dist/skill/reference/components/chat-list/COMPONENT.md +2 -1
- 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 +37 -9
- 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 +6 -5
- 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/color-swatches/COMPONENT.md +1 -0
- 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/{patterns/screen-states.module.css → reference/components/crossfade/examples/screen.module.css} +3 -17
- 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 +6 -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 -12
- 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 +7 -5
- 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 +165 -0
- package/dist/skill/reference/components/field-list/examples/base-row.tsx +76 -0
- package/dist/skill/reference/components/field-list/examples/controlled.tsx +72 -0
- package/dist/skill/reference/components/field-list/examples/errors.tsx +88 -0
- package/dist/skill/reference/components/field-list/examples/examples.module.css +34 -0
- package/dist/skill/reference/components/field-list/examples/limits.tsx +55 -0
- package/dist/skill/reference/components/field-list/examples/locked.tsx +139 -0
- package/dist/skill/reference/components/field-list/examples/narrow.tsx +68 -0
- package/dist/skill/reference/components/field-list/examples/overview.tsx +66 -0
- package/dist/skill/reference/components/field-list/examples/reorder.tsx +42 -0
- package/dist/skill/reference/components/field-list/examples/screen.module.css +18 -0
- package/dist/skill/reference/components/field-list/examples/screen.tsx +316 -0
- package/dist/skill/reference/components/field-list/examples/sizes.tsx +42 -0
- package/dist/skill/reference/components/field-list/examples/states.tsx +51 -0
- 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 -23
- 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 +2 -13
- 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 +16 -11
- package/dist/skill/reference/components/kanban/examples/columns.tsx +8 -5
- package/dist/skill/reference/components/kanban/examples/limits.tsx +2 -1
- 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} +132 -172
- package/dist/skill/reference/components/kanban/examples/states.tsx +17 -6
- package/dist/skill/reference/components/kanban/examples/variants.tsx +16 -8
- package/dist/skill/reference/components/list/COMPONENT.md +1 -1
- 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 +3 -3
- package/dist/skill/reference/components/media-viewer/examples/dismiss.tsx +5 -1
- package/dist/skill/reference/components/message/COMPONENT.md +6 -5
- 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 +2 -1
- package/dist/skill/reference/components/notification/examples/dismiss.tsx +2 -2
- package/dist/skill/reference/components/page-content/COMPONENT.md +71 -14
- package/dist/skill/reference/components/page-content/examples/grid.tsx +107 -0
- package/dist/skill/reference/components/page-content/examples/list-detail.tsx +0 -3
- package/dist/skill/reference/components/page-content/examples/overview.tsx +2 -2
- package/dist/skill/{patterns/settings-page.module.css → reference/components/page-content/examples/screen.module.css} +1 -21
- package/dist/skill/{patterns/settings-page.tsx → reference/components/page-content/examples/screen.tsx} +61 -82
- package/dist/skill/reference/components/page-content/examples/sections.tsx +81 -0
- package/dist/skill/reference/components/page-content/examples/variants.tsx +4 -11
- package/dist/skill/reference/components/page-toolbar/COMPONENT.md +18 -16
- 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 +3 -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 +5 -3
- package/dist/skill/reference/components/select/examples/examples.module.css +2 -7
- package/dist/skill/reference/components/select/examples/icon-only.tsx +38 -0
- 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 +83 -30
- package/dist/skill/reference/components/sparkline/examples/compact.tsx +1 -1
- package/dist/skill/reference/components/sparkline/examples/curve.tsx +28 -0
- package/dist/skill/reference/components/sparkline/examples/gaps.tsx +33 -0
- package/dist/skill/reference/components/sparkline/examples/overview.tsx +11 -2
- package/dist/skill/reference/components/sparkline/examples/period.tsx +7 -2
- package/dist/skill/reference/components/sparkline/examples/reference.tsx +38 -0
- package/dist/skill/reference/components/sparkline/examples/variants.tsx +2 -2
- package/dist/skill/reference/components/tabs/COMPONENT.md +1 -1
- package/dist/skill/reference/components/tabs/examples/examples.module.css +0 -6
- package/dist/skill/reference/components/tabs/examples/in-drawer.tsx +11 -13
- 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/examples.module.css +0 -8
- package/dist/skill/reference/components/timeline/examples/links.tsx +55 -14
- package/dist/skill/reference/components/timeline/examples/narrow.tsx +2 -2
- package/dist/skill/reference/components/timeline/examples/sizes.tsx +3 -3
- package/dist/skill/reference/components/timeline/examples/variants.tsx +4 -4
- package/dist/skill/reference/components/tooltip/COMPONENT.md +7 -5
- package/dist/skill/reference/components/tooltip/examples/placement.tsx +2 -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 +3 -3
- 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 +3 -3
- 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 +2 -3
- 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 +5 -4
- package/dist/skill/reference/layout/app-shell/examples/footer.tsx +2 -2
- package/dist/skill/reference/layout/app-shell/examples/overview.tsx +17 -32
- package/dist/skill/{patterns/app-shell.module.css → reference/layout/app-shell/examples/screen.module.css} +1 -8
- package/dist/skill/reference/layout/app-shell/examples/screen.tsx +262 -0
- package/dist/skill/reference/layout/app-shell/examples/template.tsx +31 -11
- package/dist/skill/reference/layout/bottom-nav/examples/floating-action.tsx +2 -2
- package/dist/skill/reference/layout/bottom-nav/examples/floating.tsx +2 -2
- package/dist/skill/reference/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
- 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 +7 -5
- package/dist/skill/ux.md +145 -0
- package/dist/tokens/semantic.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/avatar/COMPONENT.md +4 -4
- package/src/components/avatar/examples/presence.tsx +1 -1
- package/src/components/avatar/examples/states.tsx +5 -5
- 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/COMPONENT.md +6 -6
- package/src/components/banner/examples/dismissible.tsx +22 -11
- package/src/components/banner/examples/examples.module.css +4 -8
- package/src/components/banner/examples/narrow.tsx +1 -1
- package/src/components/banner/examples/page-strip.tsx +16 -22
- package/src/components/breadcrumb/COMPONENT.md +5 -4
- package/src/components/breadcrumb/examples/ellipsis.tsx +2 -2
- package/src/components/breadcrumb/examples/overflow.tsx +1 -1
- 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 +7 -5
- package/src/components/card/examples/examples.module.css +0 -28
- package/src/components/card/examples/kpi-media.tsx +13 -11
- package/src/components/card/examples/narrow.tsx +1 -1
- package/src/components/card/examples/panel-chart.tsx +45 -22
- 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 +12 -8
- package/src/components/chart-frame/examples/fill-height.tsx +119 -0
- package/src/components/chart-frame/examples/states.tsx +3 -1
- package/src/components/chart-frame/examples/tooltip.tsx +20 -24
- package/src/components/chat/COMPONENT.md +6 -4
- 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/examples/search.tsx +1 -1
- package/src/components/chat-list/COMPONENT.md +2 -1
- 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 +37 -9
- 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 +6 -5
- 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/color-swatches/COMPONENT.md +1 -0
- 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 +6 -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 +7 -5
- 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 +165 -0
- package/src/components/field-list/examples/base-row.tsx +76 -0
- package/src/components/field-list/examples/controlled.tsx +72 -0
- package/src/components/field-list/examples/errors.tsx +88 -0
- package/src/components/field-list/examples/examples.module.css +34 -0
- package/src/components/field-list/examples/limits.tsx +55 -0
- package/src/components/field-list/examples/locked.tsx +139 -0
- package/src/components/field-list/examples/narrow.tsx +68 -0
- package/src/components/field-list/examples/overview.tsx +66 -0
- package/src/components/field-list/examples/reorder.tsx +42 -0
- package/src/components/field-list/examples/screen.module.css +18 -0
- package/src/components/field-list/examples/screen.tsx +316 -0
- package/src/components/field-list/examples/sizes.tsx +42 -0
- package/src/components/field-list/examples/states.tsx +51 -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 +2 -13
- 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 +16 -11
- package/src/components/kanban/examples/columns.tsx +8 -5
- package/src/components/kanban/examples/limits.tsx +2 -1
- 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/kanban/examples/variants.tsx +16 -8
- package/src/components/list/COMPONENT.md +1 -1
- 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 +3 -3
- package/src/components/media-viewer/examples/dismiss.tsx +5 -1
- package/src/components/message/COMPONENT.md +6 -5
- 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 +2 -1
- package/src/components/notification/examples/dismiss.tsx +2 -2
- package/src/components/page-content/COMPONENT.md +71 -14
- package/src/components/page-content/examples/grid.tsx +107 -0
- package/src/components/page-content/examples/list-detail.tsx +0 -3
- package/src/components/page-content/examples/overview.tsx +2 -2
- 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/sections.tsx +81 -0
- package/src/components/page-content/examples/variants.tsx +4 -11
- package/src/components/page-toolbar/COMPONENT.md +18 -16
- 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 +3 -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 +5 -3
- package/src/components/select/examples/examples.module.css +2 -7
- package/src/components/select/examples/icon-only.tsx +38 -0
- 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 +83 -30
- package/src/components/sparkline/examples/compact.tsx +1 -1
- package/src/components/sparkline/examples/curve.tsx +28 -0
- package/src/components/sparkline/examples/gaps.tsx +33 -0
- package/src/components/sparkline/examples/overview.tsx +11 -2
- package/src/components/sparkline/examples/period.tsx +7 -2
- package/src/components/sparkline/examples/reference.tsx +38 -0
- package/src/components/sparkline/examples/variants.tsx +2 -2
- package/src/components/tabs/COMPONENT.md +1 -1
- package/src/components/tabs/examples/examples.module.css +0 -6
- package/src/components/tabs/examples/in-drawer.tsx +11 -13
- 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/examples.module.css +0 -8
- package/src/components/timeline/examples/links.tsx +55 -14
- package/src/components/timeline/examples/narrow.tsx +2 -2
- package/src/components/timeline/examples/sizes.tsx +3 -3
- package/src/components/timeline/examples/variants.tsx +4 -4
- package/src/components/tooltip/COMPONENT.md +7 -5
- package/src/components/tooltip/examples/placement.tsx +2 -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 +3 -3
- 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 +3 -3
- 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 +2 -3
- 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 +5 -4
- package/src/layout/app-shell/examples/footer.tsx +2 -2
- package/src/layout/app-shell/examples/overview.tsx +17 -32
- 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 +31 -11
- package/src/layout/bottom-nav/examples/floating-action.tsx +2 -2
- package/src/layout/bottom-nav/examples/floating.tsx +2 -2
- package/src/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
- 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/src/styles/theme-light.css +1 -0
- package/dist/skill/patterns/app-shell.tsx +0 -301
- package/dist/skill/patterns/chat.module.css +0 -8
- package/dist/skill/patterns/dashboard.module.css +0 -44
- package/dist/skill/patterns/dashboard.tsx +0 -326
- package/dist/skill/patterns/detail-page.tsx +0 -209
- 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 -638
- package/dist/skill/patterns/schedule.module.css +0 -22
- package/dist/skill/patterns/screen-states.tsx +0 -186
- /package/dist/skill/{patterns/form-drawer.module.css → reference/components/drawer/examples/screen.module.css} +0 -0
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# FieldList
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Kind:** composite
|
|
5
|
+
|
|
6
|
+
> An editable list of records of one shape — invoice lines, specs, contacts, prices by period: one row per record, the column headings once above the rows, a remove button per row and an add button under them.
|
|
7
|
+
|
|
8
|
+
## When to use
|
|
9
|
+
- A form part where a person adds, edits and removes several records of the same fields: invoice lines, contacts of a client, specs of a plan, recipients.
|
|
10
|
+
- A base value with overrides (a price and its changes by month): the base is the first row, pinned with `getLocked`, each override is a row.
|
|
11
|
+
- A list of short texts in the order a person sets (selling points, checklist items): one column, `reorderable`.
|
|
12
|
+
- Small attributes of a record beside its text (an icon, a color): `width="compact"` columns with an icon-only `Select` (`Select.TriggerIcon` and no `Select.Value`) and a `ColorPresets` swatch.
|
|
13
|
+
|
|
14
|
+
## When not to use
|
|
15
|
+
- Records that are only read, sorted or filtered → [DataTable](../data-table/COMPONENT.md); its rows are data, not form fields.
|
|
16
|
+
- One value in several units or currencies (a deposit in ₽, $, ฿) → fields side by side in one row of the form, each unit in `Input.InlineAffix`, under one heading; not a list a person grows.
|
|
17
|
+
- A set of tags or values picked from options → [TagSelect](../tag-select/COMPONENT.md).
|
|
18
|
+
- Reordering items that are not form rows (menu sections, cards) → [Dnd](../dnd/COMPONENT.md) or [List](../list/COMPONENT.md) `onReorder`.
|
|
19
|
+
- A record with many fields or long texts per row → a list of records that opens each one in a [Drawer](../drawer/COMPONENT.md); a row holds up to four short fields.
|
|
20
|
+
|
|
21
|
+
## Import
|
|
22
|
+
```tsx
|
|
23
|
+
import { FieldList, type FieldListColumn } from "prime-ui-kit";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Anatomy
|
|
27
|
+
```
|
|
28
|
+
FieldList field frame: label · the list · hint / error
|
|
29
|
+
├─ heading row the column headings, once (aria-hidden; each field carries its heading as its label)
|
|
30
|
+
├─ <ol> the rows (Dnd.Sortable with `reorderable`)
|
|
31
|
+
│ └─ <li> row [lead: handle | lock] [a cell per column] [end: remove]
|
|
32
|
+
│ └─ cell one kit field without `label`, named by its column heading
|
|
33
|
+
└─ add row Button «addLabel» (+ `labels.maxReached` at `max`)
|
|
34
|
+
```
|
|
35
|
+
A leaf: rows come from `value` through `renderItem`, which returns one element per column (a fragment). Every framed kit field (Input, Select, Datepicker, NativeSelect, ColorField…) in a cell takes its column heading as its label: read by screen readers, not shown while the heading row is on screen, shown above the field once the rows stack in a narrow container. `ColorPresets` takes it as the name of its trigger.
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
40
|
+
|
|
41
|
+
### FieldList
|
|
42
|
+
Generic `FieldList<T>`; `ref` → `HTMLDivElement` (the field frame). An editable list of records of one shape: column headings once, a row of fields per record (`<ol>`), remove per row, add under the rows; rows stack under 480 px.
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Description |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| `columns` | `readonly FieldListColumn[]` | — (required) | The columns in cell order: `label` (the heading; it names the field of the column in every row), `width` (`fill` \| `compact` \| `s` \| `m`), `required` (a `*` after the heading). |
|
|
47
|
+
| `renderItem` | `(item: T, row: FieldListRow<T>) => ReactNode` | — (required) | The cells of a row, one element per column (a fragment): kit fields without `label`. `row` has `index`, `update(patch)` and `remove()`. |
|
|
48
|
+
| `getId` | `(item: T) => string` | — (required) | Stable unique id of an item: the row key and the drag id. |
|
|
49
|
+
| `value` | `readonly T[]` | — | The rows (controlled). |
|
|
50
|
+
| `defaultValue` | `readonly T[]` | `[]` | The first rows (uncontrolled). |
|
|
51
|
+
| `onValueChange` | `(value: T[]) => void` | — | The new list after an edit (`row.update`), an added, removed or moved row. |
|
|
52
|
+
| `createItem` | `() => T` | — | A new empty item; with it the add button shows under the rows and focus goes to the new row's first field. |
|
|
53
|
+
| `addLabel` | `string` | — | Text of the add button: what is added («Добавить позицию»). |
|
|
54
|
+
| `getLabel` | `(item: T) => string` | — | The row's own text (its title field) for the remove button, the handle and drag announcements; else the row number. |
|
|
55
|
+
| `getLocked` | `(item: T) => boolean` | — | Pinned rows: a lock in the lead column, no remove button, they hold their place while others move. |
|
|
56
|
+
| `reorderable` | `boolean` | `false` | Rows move by a leading handle: drag, a touch hold, Alt + ↑ / ↓. |
|
|
57
|
+
| `min` | `number` | `0` | The fewest rows: at this count the remove buttons are disabled. |
|
|
58
|
+
| `max` | `number` | — | The most rows: at this count the add button is disabled with `labels.maxReached` beside it. |
|
|
59
|
+
| `label` | `ReactNode` | — | Heading of the list; names the `<ol>`. Omit it inside a `Fieldset` whose legend names the list. |
|
|
60
|
+
| `aria-label` | `string` | — | Name of the `<ol>` when no visible `label` names it (a section heading above the list). |
|
|
61
|
+
| `hint` | `ReactNode` | — | Help text under the list; hidden while `error` shows. |
|
|
62
|
+
| `error` | `ReactNode` | — | A problem of the list as a whole («Добавьте хотя бы одну позицию»); a field's own error goes on that field. |
|
|
63
|
+
| `disabled` | `boolean` | `false` | Disables every field, handle and button; a disabled `Fieldset` around it sets it too. |
|
|
64
|
+
| `size` | `"xs" \| "s" \| "m" \| "l" \| "xl"` | `"m"` | Tier of the headings, buttons and the kit fields that read the host tier. Without it the host tier, else `m`. |
|
|
65
|
+
| `labels` | `Partial<FieldListLabels>` | — | Built-in strings, see Labels. |
|
|
66
|
+
| `…rest` | `Omit<HTMLAttributes<HTMLDivElement>, "id" \| "children" \| "defaultValue" \| "defaultChecked" \| "onChange">` | — | `className`, `data-*` and the other attributes of the field frame `<div>` (field-root rule: `className`, `ref` and the rest → frame, `id` → control). |
|
|
67
|
+
|
|
68
|
+
## Variants
|
|
69
|
+
|
|
70
|
+
### width (column)
|
|
71
|
+
| Value | Looks like | Use when | Default |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `fill` | shares the free width with the other `fill` columns | names, descriptions, any text | yes |
|
|
74
|
+
| `compact` | two control heights wide | an icon-only `Select`, a `ColorPresets` swatch, a checkbox | |
|
|
75
|
+
| `s` | 144 px | a quantity, a code, a number of days | |
|
|
76
|
+
| `m` | 192 px | an amount with its unit, a date, a phone | |
|
|
77
|
+
|
|
78
|
+
### Flags
|
|
79
|
+
| Value | Looks like | Use when | Default |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `reorderable` | a grip before every row; Alt + ↑ / ↓ on it | the order of the records matters (a pricing page, a checklist) | `false` |
|
|
82
|
+
| `getLocked` | a lock where the grip is, no remove button; the row holds its place | a base value, system records a person cannot drop | — |
|
|
83
|
+
| `createItem` | the add button under the rows, aligned with the first column | the person grows the list | — |
|
|
84
|
+
| `min` · `max` | remove buttons off at `min`; the add button off with «Не больше {max}» at `max` | the record count is bounded | `0` · — |
|
|
85
|
+
|
|
86
|
+
**Combinations**
|
|
87
|
+
- Recommended: `label` on the list (or a `Fieldset` legend around it), one heading per column, a `getLabel` from the title field, an `addLabel` that says what is added.
|
|
88
|
+
- Allowed but rare: one column — the heading row is not drawn, the list label names the rows.
|
|
89
|
+
- Pointless: `getLocked` on every row with `createItem` — nothing can be removed or moved.
|
|
90
|
+
- Forbidden: a `label` on every field of a row, a numbered label («Пункт 1», «Пункт 2»), a unit in a heading when the field shows it.
|
|
91
|
+
|
|
92
|
+
## States
|
|
93
|
+
| State | Driven by | DOM |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| empty | `value` with no items | no heading row; only the add button (with `createItem`) |
|
|
96
|
+
| at min | `value.length <= min` | remove buttons `disabled` |
|
|
97
|
+
| at max | `value.length >= max` | add button `disabled`, `labels.maxReached` beside it |
|
|
98
|
+
| pinned row | `getLocked(item)` | `data-locked="true"` on the `<li>`; a lock, no remove button |
|
|
99
|
+
| invalid | `error` (the list), a field's own `error` | the list's message under the add row; a field's under the field in its row |
|
|
100
|
+
| disabled | `disabled` (or a disabled Fieldset) | `data-disabled="true"` on the frame; fields, handles and buttons disabled through the kit's disabled context |
|
|
101
|
+
| stacked | container narrower than 480 px | heading row hidden, each row's fields in one column with their labels shown |
|
|
102
|
+
|
|
103
|
+
## Layout & spacing
|
|
104
|
+
- Rows 12 apart (`--prime-space-3`); columns 12 apart; the heading row sits at the tier's label gap above the first row.
|
|
105
|
+
- Every row and the heading row share one track list: `[lead] [columns] [end]`; the lead fits the grip, the end fits a remove button of the tier.
|
|
106
|
+
- The handle, the lock and the remove button stand on the middle of the first line of fields, so a field's error under it grows the row downwards only.
|
|
107
|
+
- The add button lines up with the first column of fields, 12 under the last row.
|
|
108
|
+
- Under 480 px of its own width (a container query): rows stack, fields 16 apart inside a row, rows 24 apart.
|
|
109
|
+
|
|
110
|
+
## Accessibility
|
|
111
|
+
|
|
112
|
+
### Keyboard
|
|
113
|
+
| Key | Action |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `Tab` | Moves through the fields of a row, then to its remove button and on. |
|
|
116
|
+
| `Enter` · `Space` | On the add button adds a row and focuses its first field; on a remove button removes the row and focuses the next row's remove button. |
|
|
117
|
+
| `Alt + ↑` · `Alt + ↓` | With `reorderable`, moves the row up or down (from its handle). |
|
|
118
|
+
|
|
119
|
+
### ARIA
|
|
120
|
+
- The rows are an `<ol>` named by the list `label` (`aria-labelledby`); the list gives each row its position.
|
|
121
|
+
- The heading row is `aria-hidden`: each field in a cell carries its column heading as its own label, read but not shown on wide rows.
|
|
122
|
+
- In a narrow container the heading row goes and each field's label shows above it.
|
|
123
|
+
- The remove button is «Удалить {row}», the handle «Переместить {row}»: the row's name from `getLabel`, else its number.
|
|
124
|
+
- A pinned row has a lock in place of the handle and no remove button; without `reorderable` the lock is an image named «Закреплена».
|
|
125
|
+
|
|
126
|
+
### Labels
|
|
127
|
+
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
128
|
+
|
|
129
|
+
| Key | Default | Used for |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `remove` | `"Удалить {row}"` | `aria-label` of a row's remove button; `{row}` is the row's name. |
|
|
132
|
+
| `reorder` | `"Переместить {row}"` | `aria-label` of a row's handle (`reorderable`); `{row}` is the row's name. |
|
|
133
|
+
| `row` | `"строку {index}"` | Name of a row without `getLabel` text; `{index}` counts from 1. |
|
|
134
|
+
| `namedRow` | `"«{label}»"` | Name of a row with `getLabel` text; `{label}` is that text. |
|
|
135
|
+
| `locked` | `"Закреплена"` | Spoken name of the lock of a pinned row in a list without `reorderable`. |
|
|
136
|
+
| `maxReached` | `"Не больше {max}"` | Text beside the disabled add button once the list holds `max` rows. |
|
|
137
|
+
|
|
138
|
+
## Examples
|
|
139
|
+
| Example | Shows |
|
|
140
|
+
|---|---|
|
|
141
|
+
| [overview.tsx](examples/overview.tsx) | Lines of an invoice: the column headings stand once above the rows, each row has a remove button and the add button sits under them — `columns`, `renderItem`, `createItem`, `addLabel`. |
|
|
142
|
+
| [sizes.tsx](examples/sizes.tsx) | Every tier: the headings, the fields, the handle and the buttons follow the list's size — `size`. |
|
|
143
|
+
| [reorder.tsx](examples/reorder.tsx) | Selling points of a plan in the order of the pricing page: a one-column list has no headings and no numbers, a point moves by its handle or Alt+arrows — `reorderable`, `getLabel`. |
|
|
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
|
+
| [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
|
+
| [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; a `*` after a heading marks a required column — `error`, `required`. |
|
|
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
|
+
| [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
|
+
| [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`. |
|
|
152
|
+
|
|
153
|
+
## Mistakes
|
|
154
|
+
- A `label` above every field of every row («Иконка», «Параметр», «Значение» four times) → a FieldList: the headings stand once, the fields take them as hidden labels.
|
|
155
|
+
- Numbered labels («Преимущество 1», «Преимущество 2») → none: the list label names the rows and the order is visible.
|
|
156
|
+
- One record split over two lines of half-width fields → one row; small attributes go to `compact` columns (icon-only `Select`, `ColorPresets`).
|
|
157
|
+
- A base value as a separate field above its overrides, in another geometry → the first row, pinned with `getLocked`.
|
|
158
|
+
- The unit in every heading («Цена, ₽ / день») and again in the field → the unit once, in `Input.InlineAffix`.
|
|
159
|
+
- A hint that explains what the lock already shows («Первые три всегда первыми») → no hint; the lock says it.
|
|
160
|
+
- `aria-label` written on every field in a cell → none: the column heading names the field.
|
|
161
|
+
- A grip, a remove button and an add button drawn by hand around a `.map()` of fields → FieldList.
|
|
162
|
+
|
|
163
|
+
## Related
|
|
164
|
+
- **Built from:** [Button](../button/COMPONENT.md) (add, remove), [Dnd](../dnd/COMPONENT.md) (`reorderable`: `Dnd.Sortable`, `Dnd.Handle`), [Label](../label/COMPONENT.md) (headings), `Icon` (lock), the field frame (label, hint, error)
|
|
165
|
+
- **See also:** [Input](../input/COMPONENT.md), [Select](../select/COMPONENT.md) (icon-only trigger), [ColorPicker](../color-picker/COMPONENT.md) (`ColorPresets`), [Fieldset](../fieldset/COMPONENT.md), [DataTable](../data-table/COMPONENT.md)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** 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`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input, Select } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
type Period = { id: string; from: string; price: string; base?: boolean };
|
|
6
|
+
|
|
7
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Действует" }, { label: "Цена за месяц", width: "m" }];
|
|
8
|
+
|
|
9
|
+
const MONTHS = [
|
|
10
|
+
{ value: "01", label: "С 1 января" },
|
|
11
|
+
{ value: "04", label: "С 1 апреля" },
|
|
12
|
+
{ value: "07", label: "С 1 июля" },
|
|
13
|
+
{ value: "10", label: "С 1 октября" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const PERIODS: Period[] = [
|
|
17
|
+
{ id: "base", from: "", price: "4 900", base: true },
|
|
18
|
+
{ id: "q3", from: "07", price: "5 400" },
|
|
19
|
+
{ id: "q4", from: "10", price: "5 900" },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export default function FieldListBaseRowExample() {
|
|
23
|
+
const [periods, setPeriods] = React.useState(PERIODS);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<FieldList
|
|
27
|
+
label="Цена тарифа"
|
|
28
|
+
columns={COLUMNS}
|
|
29
|
+
value={periods}
|
|
30
|
+
onValueChange={setPeriods}
|
|
31
|
+
getId={(period) => period.id}
|
|
32
|
+
getLocked={(period) => period.base ?? false}
|
|
33
|
+
createItem={() => ({ id: crypto.randomUUID(), from: "", price: "" })}
|
|
34
|
+
addLabel="Добавить изменение цены"
|
|
35
|
+
renderItem={(period, row) => (
|
|
36
|
+
<>
|
|
37
|
+
{period.base ? (
|
|
38
|
+
<Input.Root>
|
|
39
|
+
<Input.Wrapper>
|
|
40
|
+
<Input.Field value="Всегда, если нет изменений" readOnly />
|
|
41
|
+
</Input.Wrapper>
|
|
42
|
+
</Input.Root>
|
|
43
|
+
) : (
|
|
44
|
+
<Select.Root
|
|
45
|
+
value={period.from}
|
|
46
|
+
onValueChange={(from) => row.update({ from })}
|
|
47
|
+
placeholder="Выберите месяц"
|
|
48
|
+
>
|
|
49
|
+
<Select.Trigger>
|
|
50
|
+
<Select.Value />
|
|
51
|
+
</Select.Trigger>
|
|
52
|
+
<Select.Content>
|
|
53
|
+
{MONTHS.map((month) => (
|
|
54
|
+
<Select.Item key={month.value} value={month.value}>
|
|
55
|
+
{month.label}
|
|
56
|
+
</Select.Item>
|
|
57
|
+
))}
|
|
58
|
+
</Select.Content>
|
|
59
|
+
</Select.Root>
|
|
60
|
+
)}
|
|
61
|
+
<Input.Root>
|
|
62
|
+
<Input.Wrapper>
|
|
63
|
+
<Input.Field
|
|
64
|
+
value={period.price}
|
|
65
|
+
inputMode="decimal"
|
|
66
|
+
placeholder="0"
|
|
67
|
+
onChange={(event) => row.update({ price: event.target.value })}
|
|
68
|
+
/>
|
|
69
|
+
<Input.InlineAffix side="end">₽</Input.InlineAffix>
|
|
70
|
+
</Input.Wrapper>
|
|
71
|
+
</Input.Root>
|
|
72
|
+
</>
|
|
73
|
+
)}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** The parent owns the lines: it sums them under the list and puts the saved lines back on reset — `value`, `onValueChange`. */
|
|
2
|
+
import { Button, FieldList, type FieldListColumn, Input, Typography } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
type Line = { id: string; service: string; amount: string };
|
|
8
|
+
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Услуга" }, { label: "Сумма", width: "m" }];
|
|
10
|
+
|
|
11
|
+
const SAVED: Line[] = [
|
|
12
|
+
{ id: "license", service: "Лицензия на 12 месяцев", amount: "96 000" },
|
|
13
|
+
{ id: "migration", service: "Перенос данных", amount: "24 000" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const RUB = new Intl.NumberFormat("ru-RU", {
|
|
17
|
+
style: "currency",
|
|
18
|
+
currency: "RUB",
|
|
19
|
+
maximumFractionDigits: 0,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
function totalOf(lines: Line[]) {
|
|
23
|
+
return lines.reduce((sum, line) => sum + (Number(line.amount.replace(/\s/g, "")) || 0), 0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function FieldListControlledExample() {
|
|
27
|
+
const [lines, setLines] = React.useState(SAVED);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className={styles.stack}>
|
|
31
|
+
<FieldList
|
|
32
|
+
label="Состав сделки"
|
|
33
|
+
columns={COLUMNS}
|
|
34
|
+
value={lines}
|
|
35
|
+
onValueChange={setLines}
|
|
36
|
+
getId={(line) => line.id}
|
|
37
|
+
getLabel={(line) => line.service}
|
|
38
|
+
createItem={() => ({ id: crypto.randomUUID(), service: "", amount: "" })}
|
|
39
|
+
addLabel="Добавить услугу"
|
|
40
|
+
renderItem={(line, row) => (
|
|
41
|
+
<>
|
|
42
|
+
<Input.Root>
|
|
43
|
+
<Input.Wrapper>
|
|
44
|
+
<Input.Field
|
|
45
|
+
value={line.service}
|
|
46
|
+
onChange={(event) => row.update({ service: event.target.value })}
|
|
47
|
+
/>
|
|
48
|
+
</Input.Wrapper>
|
|
49
|
+
</Input.Root>
|
|
50
|
+
<Input.Root>
|
|
51
|
+
<Input.Wrapper>
|
|
52
|
+
<Input.Field
|
|
53
|
+
value={line.amount}
|
|
54
|
+
inputMode="decimal"
|
|
55
|
+
placeholder="0"
|
|
56
|
+
onChange={(event) => row.update({ amount: event.target.value })}
|
|
57
|
+
/>
|
|
58
|
+
<Input.InlineAffix side="end">₽</Input.InlineAffix>
|
|
59
|
+
</Input.Wrapper>
|
|
60
|
+
</Input.Root>
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
/>
|
|
64
|
+
<div className={styles.summary}>
|
|
65
|
+
<Typography variant="title-m">Итого {RUB.format(totalOf(lines))}</Typography>
|
|
66
|
+
<Button.Root variant="ghost" tone="neutral" onClick={() => setLines(SAVED)}>
|
|
67
|
+
Вернуть сохранённое
|
|
68
|
+
</Button.Root>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
import { Button, FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
type Contact = { id: string; role: string; phone: string };
|
|
8
|
+
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [
|
|
10
|
+
{ label: "Должность", required: true },
|
|
11
|
+
{ label: "Телефон", width: "m", required: true },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const CONTACTS: Contact[] = [
|
|
15
|
+
{ id: "buyer", role: "Закупщик", phone: "+7 912 404-18-20" },
|
|
16
|
+
{ id: "lawyer", role: "Юрист", phone: "+7 912 40" },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const PHONE = /^\+7 \d{3} \d{3}-\d{2}-\d{2}$/;
|
|
20
|
+
|
|
21
|
+
function phoneError(phone: string) {
|
|
22
|
+
if (phone.trim() === "") return "Укажите телефон";
|
|
23
|
+
return PHONE.test(phone) ? undefined : "Формат: +7 912 404-18-20";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function FieldListErrorsExample() {
|
|
27
|
+
const [contacts, setContacts] = React.useState(CONTACTS);
|
|
28
|
+
// Every save attempt validates the form; after it renders, focus goes to the first wrong field.
|
|
29
|
+
const [attempts, setAttempts] = React.useState(0);
|
|
30
|
+
const formRef = React.useRef<HTMLFormElement>(null);
|
|
31
|
+
const checked = attempts > 0;
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
if (attempts === 0) return;
|
|
34
|
+
formRef.current?.querySelector<HTMLElement>("[aria-invalid='true']")?.focus();
|
|
35
|
+
}, [attempts]);
|
|
36
|
+
const listError = checked && contacts.length === 0 ? "Добавьте хотя бы один контакт" : undefined;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<form
|
|
40
|
+
ref={formRef}
|
|
41
|
+
noValidate
|
|
42
|
+
className={styles.form}
|
|
43
|
+
onSubmit={(event) => {
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
setAttempts((count) => count + 1);
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<FieldList
|
|
49
|
+
label="Контакты клиента"
|
|
50
|
+
error={listError}
|
|
51
|
+
columns={COLUMNS}
|
|
52
|
+
value={contacts}
|
|
53
|
+
onValueChange={setContacts}
|
|
54
|
+
getId={(contact) => contact.id}
|
|
55
|
+
getLabel={(contact) => contact.role}
|
|
56
|
+
createItem={() => ({ id: crypto.randomUUID(), role: "", phone: "" })}
|
|
57
|
+
addLabel="Добавить контакт"
|
|
58
|
+
renderItem={(contact, row) => (
|
|
59
|
+
<>
|
|
60
|
+
<Input.Root
|
|
61
|
+
error={checked && contact.role.trim() === "" ? "Укажите должность" : undefined}
|
|
62
|
+
>
|
|
63
|
+
<Input.Wrapper>
|
|
64
|
+
<Input.Field
|
|
65
|
+
value={contact.role}
|
|
66
|
+
onChange={(event) => row.update({ role: event.target.value })}
|
|
67
|
+
/>
|
|
68
|
+
</Input.Wrapper>
|
|
69
|
+
</Input.Root>
|
|
70
|
+
<Input.Root error={checked ? phoneError(contact.phone) : undefined}>
|
|
71
|
+
<Input.Wrapper>
|
|
72
|
+
<Input.Field
|
|
73
|
+
type="tel"
|
|
74
|
+
value={contact.phone}
|
|
75
|
+
placeholder="+7 912 404-18-20"
|
|
76
|
+
onChange={(event) => row.update({ phone: event.target.value })}
|
|
77
|
+
/>
|
|
78
|
+
</Input.Wrapper>
|
|
79
|
+
</Input.Root>
|
|
80
|
+
</>
|
|
81
|
+
)}
|
|
82
|
+
/>
|
|
83
|
+
<Button.Root type="submit" className={styles.submit}>
|
|
84
|
+
Сохранить контакты
|
|
85
|
+
</Button.Root>
|
|
86
|
+
</form>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Layout of the FieldList scenarios: semantic tokens only. */
|
|
2
|
+
|
|
3
|
+
/* A form: the list, then its submit button at the start, a group apart. */
|
|
4
|
+
.form {
|
|
5
|
+
display: grid;
|
|
6
|
+
gap: var(--prime-space-8);
|
|
7
|
+
width: 100%;
|
|
8
|
+
min-width: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.submit {
|
|
12
|
+
justify-self: start;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* A 320 px column: the rows stack into blocks and every field shows its label. */
|
|
16
|
+
.narrow {
|
|
17
|
+
inline-size: min(100%, calc(var(--prime-space-20) * 4));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* The total of the lines and the reset beside it. */
|
|
21
|
+
.summary {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-wrap: wrap;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: space-between;
|
|
26
|
+
gap: var(--prime-space-3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.stack {
|
|
30
|
+
display: grid;
|
|
31
|
+
gap: var(--prime-space-6);
|
|
32
|
+
width: 100%;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** 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`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
type Recipient = { id: string; name: string; email: string };
|
|
6
|
+
|
|
7
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Имя" }, { label: "Почта" }];
|
|
8
|
+
|
|
9
|
+
const RECIPIENTS: Recipient[] = [
|
|
10
|
+
{ id: "accounting", name: "Бухгалтерия", email: "buh@severstroy.ru" },
|
|
11
|
+
{ id: "director", name: "Ирина Котова", email: "kotova@severstroy.ru" },
|
|
12
|
+
{ id: "manager", name: "Олег Демин", email: "demin@severstroy.ru" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export default function FieldListLimitsExample() {
|
|
16
|
+
const [recipients, setRecipients] = React.useState(RECIPIENTS);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FieldList
|
|
20
|
+
label="Кому напоминать об оплате"
|
|
21
|
+
hint="Письмо уходит за три дня до срока."
|
|
22
|
+
columns={COLUMNS}
|
|
23
|
+
min={1}
|
|
24
|
+
max={3}
|
|
25
|
+
value={recipients}
|
|
26
|
+
onValueChange={setRecipients}
|
|
27
|
+
getId={(recipient) => recipient.id}
|
|
28
|
+
getLabel={(recipient) => recipient.name}
|
|
29
|
+
createItem={() => ({ id: crypto.randomUUID(), name: "", email: "" })}
|
|
30
|
+
addLabel="Добавить получателя"
|
|
31
|
+
renderItem={(recipient, row) => (
|
|
32
|
+
<>
|
|
33
|
+
<Input.Root>
|
|
34
|
+
<Input.Wrapper>
|
|
35
|
+
<Input.Field
|
|
36
|
+
value={recipient.name}
|
|
37
|
+
onChange={(event) => row.update({ name: event.target.value })}
|
|
38
|
+
/>
|
|
39
|
+
</Input.Wrapper>
|
|
40
|
+
</Input.Root>
|
|
41
|
+
<Input.Root>
|
|
42
|
+
<Input.Wrapper>
|
|
43
|
+
<Input.Field
|
|
44
|
+
type="email"
|
|
45
|
+
value={recipient.email}
|
|
46
|
+
placeholder="name@company.ru"
|
|
47
|
+
onChange={(event) => row.update({ email: event.target.value })}
|
|
48
|
+
/>
|
|
49
|
+
</Input.Wrapper>
|
|
50
|
+
</Input.Root>
|
|
51
|
+
</>
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|