@vamos-ui/react 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +27 -2
- package/dist/blocks/block-heading.d.ts +29 -0
- package/dist/blocks/block-heading.js +39 -0
- package/dist/blocks/block-image.d.ts +52 -0
- package/dist/blocks/block-image.js +48 -0
- package/dist/blocks/block-link.d.ts +30 -0
- package/dist/blocks/block-link.js +36 -0
- package/dist/blocks/create-blocks.d.ts +54 -0
- package/dist/blocks/create-blocks.js +52 -0
- package/dist/blocks/index.d.ts +55 -0
- package/dist/blocks/index.js +59 -0
- package/dist/blocks/json-ld.d.ts +18 -0
- package/dist/blocks/json-ld.js +44 -0
- package/dist/blocks/labels.d.ts +20 -0
- package/dist/blocks/labels.js +43 -0
- package/dist/blocks/rich-text.d.ts +36 -0
- package/dist/blocks/rich-text.js +106 -0
- package/dist/blocks/schema/define-block.d.ts +151 -0
- package/dist/blocks/schema/define-block.js +120 -0
- package/dist/blocks/schema/emphasis.d.ts +17 -0
- package/dist/blocks/schema/emphasis.js +69 -0
- package/dist/blocks/schema/fields.d.ts +497 -0
- package/dist/blocks/schema/fields.js +240 -0
- package/dist/blocks/schema/icons.d.ts +2 -0
- package/dist/blocks/schema/icons.js +26 -0
- package/dist/blocks/schema/index.d.ts +18 -0
- package/dist/blocks/schema/index.js +21 -0
- package/dist/blocks/schema/lint-types.d.ts +16 -0
- package/dist/blocks/schema/lint-types.js +2 -0
- package/dist/blocks/schema/lint.d.ts +32 -0
- package/dist/blocks/schema/lint.js +164 -0
- package/dist/blocks/schema/localize.d.ts +20 -0
- package/dist/blocks/schema/localize.js +29 -0
- package/dist/blocks/schema/localized.d.ts +25 -0
- package/dist/blocks/schema/localized.js +53 -0
- package/dist/blocks/schema/migrate.d.ts +24 -0
- package/dist/blocks/schema/migrate.js +75 -0
- package/dist/blocks/schema/nodes.d.ts +196 -0
- package/dist/blocks/schema/nodes.js +78 -0
- package/dist/blocks/schema/rich-doc-schema.d.ts +32 -0
- package/dist/blocks/schema/rich-doc-schema.js +66 -0
- package/dist/blocks/schema/rich-doc.d.ts +90 -0
- package/dist/blocks/schema/rich-doc.js +62 -0
- package/dist/blocks/schema/safety.d.ts +20 -0
- package/dist/blocks/schema/safety.js +49 -0
- package/dist/blocks/schema/types.d.ts +172 -0
- package/dist/blocks/schema/types.js +3 -0
- package/dist/blocks/schema/validate.d.ts +17 -0
- package/dist/blocks/schema/validate.js +32 -0
- package/dist/blocks/schema/walk.d.ts +22 -0
- package/dist/blocks/schema/walk.js +60 -0
- package/dist/blocks/section-header.d.ts +38 -0
- package/dist/blocks/section-header.js +22 -0
- package/dist/blocks/section.d.ts +59 -0
- package/dist/blocks/section.js +66 -0
- package/dist/blocks/site/_kit-1.d.ts +101 -0
- package/dist/blocks/site/_kit-1.js +137 -0
- package/dist/blocks/site/_site-icon-1.d.ts +6 -0
- package/dist/blocks/site/_site-icon-1.js +15 -0
- package/dist/blocks/site/announcement-bar.d.ts +42 -0
- package/dist/blocks/site/announcement-bar.js +38 -0
- package/dist/blocks/site/announcement-dismiss.d.ts +18 -0
- package/dist/blocks/site/announcement-dismiss.js +28 -0
- package/dist/blocks/site/article-layout.d.ts +65 -0
- package/dist/blocks/site/article-layout.js +88 -0
- package/dist/blocks/site/blog-list.d.ts +79 -0
- package/dist/blocks/site/blog-list.js +78 -0
- package/dist/blocks/site/comparison-table.d.ts +54 -0
- package/dist/blocks/site/comparison-table.js +38 -0
- package/dist/blocks/site/consent-banner.d.ts +52 -0
- package/dist/blocks/site/consent-banner.js +33 -0
- package/dist/blocks/site/contact-dock.d.ts +52 -0
- package/dist/blocks/site/contact-dock.js +55 -0
- package/dist/blocks/site/contact-form.d.ts +60 -0
- package/dist/blocks/site/contact-form.js +45 -0
- package/dist/blocks/site/cta-booking.d.ts +43 -0
- package/dist/blocks/site/cta-booking.js +69 -0
- package/dist/blocks/site/cta.d.ts +74 -0
- package/dist/blocks/site/cta.js +113 -0
- package/dist/blocks/site/embed-facade.d.ts +20 -0
- package/dist/blocks/site/embed-facade.js +21 -0
- package/dist/blocks/site/faq.d.ts +48 -0
- package/dist/blocks/site/faq.js +52 -0
- package/dist/blocks/site/feature-grid.d.ts +46 -0
- package/dist/blocks/site/feature-grid.js +50 -0
- package/dist/blocks/site/feature-tabs.d.ts +22 -0
- package/dist/blocks/site/feature-tabs.js +11 -0
- package/dist/blocks/site/footer.d.ts +68 -0
- package/dist/blocks/site/footer.js +61 -0
- package/dist/blocks/site/gallery-section.d.ts +42 -0
- package/dist/blocks/site/gallery-section.js +48 -0
- package/dist/blocks/site/hero-video.d.ts +15 -0
- package/dist/blocks/site/hero-video.js +31 -0
- package/dist/blocks/site/hero.d.ts +64 -0
- package/dist/blocks/site/hero.js +73 -0
- package/dist/blocks/site/logo-strip.d.ts +44 -0
- package/dist/blocks/site/logo-strip.js +27 -0
- package/dist/blocks/site/map-hours.d.ts +83 -0
- package/dist/blocks/site/map-hours.js +125 -0
- package/dist/blocks/site/media-text.d.ts +45 -0
- package/dist/blocks/site/media-text.js +56 -0
- package/dist/blocks/site/menu-list.d.ts +74 -0
- package/dist/blocks/site/menu-list.js +84 -0
- package/dist/blocks/site/navbar-submenu.d.ts +18 -0
- package/dist/blocks/site/navbar-submenu.js +51 -0
- package/dist/blocks/site/navbar.d.ts +67 -0
- package/dist/blocks/site/navbar.js +64 -0
- package/dist/blocks/site/not-found.d.ts +40 -0
- package/dist/blocks/site/not-found.js +38 -0
- package/dist/blocks/site/page-intro.d.ts +46 -0
- package/dist/blocks/site/page-intro.js +44 -0
- package/dist/blocks/site/pricing-table.d.ts +67 -0
- package/dist/blocks/site/pricing-table.js +83 -0
- package/dist/blocks/site/process.d.ts +36 -0
- package/dist/blocks/site/process.js +42 -0
- package/dist/blocks/site/registry-1.d.ts +720 -0
- package/dist/blocks/site/registry-1.js +783 -0
- package/dist/blocks/site/registry-2.d.ts +914 -0
- package/dist/blocks/site/registry-2.js +563 -0
- package/dist/blocks/site/rich-text-section.d.ts +34 -0
- package/dist/blocks/site/rich-text-section.js +32 -0
- package/dist/blocks/site/shared/brand-icons.d.ts +21 -0
- package/dist/blocks/site/shared/brand-icons.js +56 -0
- package/dist/blocks/site/shared/consent-gate.d.ts +41 -0
- package/dist/blocks/site/shared/consent-gate.js +43 -0
- package/dist/blocks/site/shared/consent-island.d.ts +38 -0
- package/dist/blocks/site/shared/consent-island.js +63 -0
- package/dist/blocks/site/shared/consent.d.ts +49 -0
- package/dist/blocks/site/shared/consent.js +130 -0
- package/dist/blocks/site/shared/contact-form-island.d.ts +41 -0
- package/dist/blocks/site/shared/contact-form-island.js +100 -0
- package/dist/blocks/site/shared/copy-link.d.ts +10 -0
- package/dist/blocks/site/shared/copy-link.js +25 -0
- package/dist/blocks/site/shared/dock-avoid.d.ts +15 -0
- package/dist/blocks/site/shared/dock-avoid.js +107 -0
- package/dist/blocks/site/shared/dock-hours.d.ts +13 -0
- package/dist/blocks/site/shared/dock-hours.js +25 -0
- package/dist/blocks/site/shared/gallery-lightbox.d.ts +12 -0
- package/dist/blocks/site/shared/gallery-lightbox.js +10 -0
- package/dist/blocks/site/shared/island-keys.d.ts +10 -0
- package/dist/blocks/site/shared/island-keys.js +44 -0
- package/dist/blocks/site/shared/kit-2.d.ts +55 -0
- package/dist/blocks/site/shared/kit-2.js +84 -0
- package/dist/blocks/site/shared/labels-2.d.ts +209 -0
- package/dist/blocks/site/shared/labels-2.js +427 -0
- package/dist/blocks/site/shared/open-now.d.ts +22 -0
- package/dist/blocks/site/shared/open-now.js +27 -0
- package/dist/blocks/site/shared/opening-hours.d.ts +117 -0
- package/dist/blocks/site/shared/opening-hours.js +245 -0
- package/dist/blocks/site/shared/site-accent.d.ts +48 -0
- package/dist/blocks/site/shared/site-accent.js +249 -0
- package/dist/blocks/site/shared/site-form.d.ts +79 -0
- package/dist/blocks/site/shared/site-form.js +111 -0
- package/dist/blocks/site/shared/site-routing.d.ts +54 -0
- package/dist/blocks/site/shared/site-routing.js +86 -0
- package/dist/blocks/site/shared/testimonials-carousel.d.ts +17 -0
- package/dist/blocks/site/shared/testimonials-carousel.js +64 -0
- package/dist/blocks/site/site-shell.d.ts +108 -0
- package/dist/blocks/site/site-shell.js +254 -0
- package/dist/blocks/site/stats-band.d.ts +42 -0
- package/dist/blocks/site/stats-band.js +45 -0
- package/dist/blocks/site/team.d.ts +44 -0
- package/dist/blocks/site/team.js +48 -0
- package/dist/blocks/site/testimonials.d.ts +68 -0
- package/dist/blocks/site/testimonials.js +66 -0
- package/dist/blocks/types.d.ts +63 -0
- package/dist/blocks/types.js +2 -0
- package/dist/business/approval-flow.d.ts +152 -0
- package/dist/business/approval-flow.js +221 -0
- package/dist/business/export-core.d.ts +55 -0
- package/dist/business/export-core.js +101 -0
- package/dist/business/export.d.ts +148 -0
- package/dist/business/export.js +264 -0
- package/dist/business/import-core.d.ts +104 -0
- package/dist/business/import-core.js +281 -0
- package/dist/business/import-wizard.d.ts +186 -0
- package/dist/business/import-wizard.js +401 -0
- package/dist/business/index.d.ts +12 -0
- package/dist/business/index.js +22 -0
- package/dist/business/line-items-core.d.ts +129 -0
- package/dist/business/line-items-core.js +183 -0
- package/dist/business/line-items.d.ts +119 -0
- package/dist/business/line-items.js +299 -0
- package/dist/business/multi-step-form.d.ts +131 -0
- package/dist/business/multi-step-form.js +337 -0
- package/dist/business/permission-core.d.ts +59 -0
- package/dist/business/permission-core.js +99 -0
- package/dist/business/permission-matrix.d.ts +158 -0
- package/dist/business/permission-matrix.js +341 -0
- package/dist/business/setup-checklist.d.ts +80 -0
- package/dist/business/setup-checklist.js +92 -0
- package/dist/business/signer-status.d.ts +53 -0
- package/dist/business/signer-status.js +76 -0
- package/dist/charts/area-chart.d.ts +35 -0
- package/dist/charts/area-chart.js +33 -0
- package/dist/charts/bar-chart.d.ts +27 -0
- package/dist/charts/bar-chart.js +46 -0
- package/dist/charts/bar-list.d.ts +47 -0
- package/dist/charts/bar-list.js +60 -0
- package/dist/charts/chart-shell.d.ts +173 -0
- package/dist/charts/chart-shell.js +205 -0
- package/dist/charts/chart.d.ts +73 -0
- package/dist/charts/chart.js +106 -0
- package/dist/charts/combo-chart.d.ts +29 -0
- package/dist/charts/combo-chart.js +47 -0
- package/dist/charts/donut-chart.d.ts +33 -0
- package/dist/charts/donut-chart.js +113 -0
- package/dist/charts/funnel.d.ts +51 -0
- package/dist/charts/funnel.js +69 -0
- package/dist/charts/gauge.d.ts +62 -0
- package/dist/charts/gauge.js +104 -0
- package/dist/charts/heatmap.d.ts +81 -0
- package/dist/charts/heatmap.js +338 -0
- package/dist/charts/index.d.ts +12 -0
- package/dist/charts/index.js +14 -0
- package/dist/charts/line-chart.d.ts +21 -0
- package/dist/charts/line-chart.js +36 -0
- package/dist/charts/test-utils.d.ts +2 -0
- package/dist/charts/test-utils.js +38 -0
- package/dist/charts/utils.d.ts +130 -0
- package/dist/charts/utils.js +262 -0
- package/dist/components/_qr-core.d.ts +26 -0
- package/dist/components/_qr-core.js +376 -0
- package/dist/components/accordion.d.ts +47 -0
- package/dist/components/accordion.js +70 -0
- package/dist/components/activity-timeline.d.ts +149 -0
- package/dist/components/activity-timeline.js +122 -0
- package/dist/components/address-field.d.ts +116 -0
- package/dist/components/address-field.js +219 -0
- package/dist/components/alert-dialog.d.ts +99 -0
- package/dist/components/alert-dialog.js +192 -0
- package/dist/components/alert.d.ts +42 -0
- package/dist/components/alert.js +82 -0
- package/dist/components/app-shell.d.ts +159 -0
- package/dist/components/app-shell.js +289 -0
- package/dist/components/attachment-list.d.ts +96 -0
- package/dist/components/attachment-list.js +196 -0
- package/dist/components/audit-log.d.ts +150 -0
- package/dist/components/audit-log.js +205 -0
- package/dist/components/avatar.d.ts +87 -0
- package/dist/components/avatar.js +126 -0
- package/dist/components/backup-codes.d.ts +42 -0
- package/dist/components/backup-codes.js +67 -0
- package/dist/components/badge.d.ts +41 -0
- package/dist/components/badge.js +68 -0
- package/dist/components/breadcrumb.d.ts +78 -0
- package/dist/components/breadcrumb.js +106 -0
- package/dist/components/button-group.d.ts +52 -0
- package/dist/components/button-group.js +77 -0
- package/dist/components/button.d.ts +58 -0
- package/dist/components/button.js +107 -0
- package/dist/components/calendar.d.ts +240 -0
- package/dist/components/calendar.js +483 -0
- package/dist/components/card.d.ts +66 -0
- package/dist/components/card.js +76 -0
- package/dist/components/carousel.d.ts +170 -0
- package/dist/components/carousel.js +348 -0
- package/dist/components/checkbox.d.ts +78 -0
- package/dist/components/checkbox.js +138 -0
- package/dist/components/color-picker.d.ts +112 -0
- package/dist/components/color-picker.js +235 -0
- package/dist/components/combobox.d.ts +136 -0
- package/dist/components/combobox.js +294 -0
- package/dist/components/command.d.ts +281 -0
- package/dist/components/command.js +498 -0
- package/dist/components/comment-thread.d.ts +252 -0
- package/dist/components/comment-thread.js +449 -0
- package/dist/components/context-menu.d.ts +77 -0
- package/dist/components/context-menu.js +82 -0
- package/dist/components/currency-input.d.ts +43 -0
- package/dist/components/currency-input.js +85 -0
- package/dist/components/date-picker.d.ts +141 -0
- package/dist/components/date-picker.js +241 -0
- package/dist/components/date-range-picker.d.ts +91 -0
- package/dist/components/date-range-picker.js +251 -0
- package/dist/components/description-list.d.ts +92 -0
- package/dist/components/description-list.js +42 -0
- package/dist/components/dialog.d.ts +139 -0
- package/dist/components/dialog.js +185 -0
- package/dist/components/dropdown-menu.d.ts +100 -0
- package/dist/components/dropdown-menu.js +102 -0
- package/dist/components/editor-layout.d.ts +166 -0
- package/dist/components/editor-layout.js +237 -0
- package/dist/components/empty-state.d.ts +49 -0
- package/dist/components/empty-state.js +68 -0
- package/dist/components/entity-card.d.ts +83 -0
- package/dist/components/entity-card.js +92 -0
- package/dist/components/file-upload.d.ts +256 -0
- package/dist/components/file-upload.js +490 -0
- package/dist/components/formatted-input.d.ts +177 -0
- package/dist/components/formatted-input.js +399 -0
- package/dist/components/hierarchy-chart.d.ts +190 -0
- package/dist/components/hierarchy-chart.js +890 -0
- package/dist/components/hover-card.d.ts +21 -0
- package/dist/components/hover-card.js +32 -0
- package/dist/components/iban-input.d.ts +38 -0
- package/dist/components/iban-input.js +112 -0
- package/dist/components/id-input.d.ts +65 -0
- package/dist/components/id-input.js +130 -0
- package/dist/components/image.d.ts +130 -0
- package/dist/components/image.js +168 -0
- package/dist/components/input-otp.d.ts +62 -0
- package/dist/components/input-otp.js +73 -0
- package/dist/components/input.d.ts +141 -0
- package/dist/components/input.js +187 -0
- package/dist/components/item.d.ts +96 -0
- package/dist/components/item.js +113 -0
- package/dist/components/kbd.d.ts +64 -0
- package/dist/components/kbd.js +119 -0
- package/dist/components/list-layout.d.ts +144 -0
- package/dist/components/list-layout.js +210 -0
- package/dist/components/native-select.d.ts +33 -0
- package/dist/components/native-select.js +48 -0
- package/dist/components/navigation-menu.d.ts +127 -0
- package/dist/components/navigation-menu.js +129 -0
- package/dist/components/notification-center.d.ts +164 -0
- package/dist/components/notification-center.js +399 -0
- package/dist/components/page-header.d.ts +60 -0
- package/dist/components/page-header.js +60 -0
- package/dist/components/pagination.d.ts +121 -0
- package/dist/components/pagination.js +174 -0
- package/dist/components/phone-input.d.ts +49 -0
- package/dist/components/phone-input.js +266 -0
- package/dist/components/pin-map.d.ts +58 -0
- package/dist/components/pin-map.js +167 -0
- package/dist/components/popover.d.ts +38 -0
- package/dist/components/popover.js +69 -0
- package/dist/components/progress.d.ts +79 -0
- package/dist/components/progress.js +97 -0
- package/dist/components/qr-code.d.ts +36 -0
- package/dist/components/qr-code.js +27 -0
- package/dist/components/radio-group.d.ts +43 -0
- package/dist/components/radio-group.js +81 -0
- package/dist/components/record-detail-layout.d.ts +167 -0
- package/dist/components/record-detail-layout.js +233 -0
- package/dist/components/record-picker.d.ts +199 -0
- package/dist/components/record-picker.js +650 -0
- package/dist/components/resizable.d.ts +50 -0
- package/dist/components/resizable.js +88 -0
- package/dist/components/scroll-area.d.ts +40 -0
- package/dist/components/scroll-area.js +56 -0
- package/dist/components/select.d.ts +126 -0
- package/dist/components/select.js +137 -0
- package/dist/components/separator.d.ts +31 -0
- package/dist/components/separator.js +41 -0
- package/dist/components/settings-layout.d.ts +134 -0
- package/dist/components/settings-layout.js +180 -0
- package/dist/components/sheet.d.ts +103 -0
- package/dist/components/sheet.js +165 -0
- package/dist/components/sidebar.d.ts +171 -0
- package/dist/components/sidebar.js +421 -0
- package/dist/components/signature-pad.d.ts +85 -0
- package/dist/components/signature-pad.js +283 -0
- package/dist/components/skeleton.d.ts +64 -0
- package/dist/components/skeleton.js +53 -0
- package/dist/components/sla-timer.d.ts +75 -0
- package/dist/components/sla-timer.js +142 -0
- package/dist/components/slider.d.ts +57 -0
- package/dist/components/slider.js +133 -0
- package/dist/components/slug-input.d.ts +69 -0
- package/dist/components/slug-input.js +201 -0
- package/dist/components/sparkline.d.ts +54 -0
- package/dist/components/sparkline.js +122 -0
- package/dist/components/spinner.d.ts +34 -0
- package/dist/components/spinner.js +34 -0
- package/dist/components/stat.d.ts +135 -0
- package/dist/components/stat.js +130 -0
- package/dist/components/status-picker.d.ts +107 -0
- package/dist/components/status-picker.js +175 -0
- package/dist/components/stepper.d.ts +86 -0
- package/dist/components/stepper.js +103 -0
- package/dist/components/switch.d.ts +34 -0
- package/dist/components/switch.js +70 -0
- package/dist/components/table.d.ts +101 -0
- package/dist/components/table.js +72 -0
- package/dist/components/tabs.d.ts +103 -0
- package/dist/components/tabs.js +173 -0
- package/dist/components/tag-input.d.ts +77 -0
- package/dist/components/tag-input.js +305 -0
- package/dist/components/task-list.d.ts +89 -0
- package/dist/components/task-list.js +238 -0
- package/dist/components/time-picker.d.ts +119 -0
- package/dist/components/time-picker.js +399 -0
- package/dist/components/toast.d.ts +87 -0
- package/dist/components/toast.js +142 -0
- package/dist/components/toggle.d.ts +77 -0
- package/dist/components/toggle.js +109 -0
- package/dist/components/tooltip.d.ts +69 -0
- package/dist/components/tooltip.js +105 -0
- package/dist/components/top-bar.d.ts +87 -0
- package/dist/components/top-bar.js +99 -0
- package/dist/components/tour.d.ts +60 -0
- package/dist/components/tour.js +139 -0
- package/dist/components/tree-select.d.ts +89 -0
- package/dist/components/tree-select.js +243 -0
- package/dist/components/tree-view.d.ts +109 -0
- package/dist/components/tree-view.js +170 -0
- package/dist/components/typography.d.ts +107 -0
- package/dist/components/typography.js +128 -0
- package/dist/components/user-picker.d.ts +89 -0
- package/dist/components/user-picker.js +162 -0
- package/dist/components/version-history.d.ts +191 -0
- package/dist/components/version-history.js +431 -0
- package/dist/data-table/csv.d.ts +27 -0
- package/dist/data-table/csv.js +68 -0
- package/dist/data-table/data-table.d.ts +423 -0
- package/dist/data-table/data-table.js +1259 -0
- package/dist/data-table/filter-bar.d.ts +146 -0
- package/dist/data-table/filter-bar.js +569 -0
- package/dist/data-table/filter-fns.d.ts +65 -0
- package/dist/data-table/filter-fns.js +382 -0
- package/dist/data-table/index.d.ts +8 -0
- package/dist/data-table/index.js +9 -0
- package/dist/data-table/saved-views.d.ts +100 -0
- package/dist/data-table/saved-views.js +251 -0
- package/dist/data-table/types.d.ts +168 -0
- package/dist/data-table/types.js +87 -0
- package/dist/data-table/url-state.d.ts +94 -0
- package/dist/data-table/url-state.js +303 -0
- package/dist/data-table/view-state.d.ts +16 -0
- package/dist/data-table/view-state.js +81 -0
- package/dist/editor/_test-setup.d.ts +1 -0
- package/dist/editor/_test-setup.js +33 -0
- package/dist/editor/block-editor.d.ts +137 -0
- package/dist/editor/block-editor.js +280 -0
- package/dist/editor/commands.d.ts +31 -0
- package/dist/editor/commands.js +150 -0
- package/dist/editor/context.d.ts +108 -0
- package/dist/editor/context.js +30 -0
- package/dist/editor/convert.d.ts +66 -0
- package/dist/editor/convert.js +567 -0
- package/dist/editor/drag-handle.d.ts +10 -0
- package/dist/editor/drag-handle.js +69 -0
- package/dist/editor/extensions.d.ts +34 -0
- package/dist/editor/extensions.js +239 -0
- package/dist/editor/index.d.ts +14 -0
- package/dist/editor/index.js +17 -0
- package/dist/editor/inserter.d.ts +12 -0
- package/dist/editor/inserter.js +88 -0
- package/dist/editor/inspector.d.ts +17 -0
- package/dist/editor/inspector.js +65 -0
- package/dist/editor/items.d.ts +62 -0
- package/dist/editor/items.js +195 -0
- package/dist/editor/labels.d.ts +119 -0
- package/dist/editor/labels.js +130 -0
- package/dist/editor/markdown.d.ts +14 -0
- package/dist/editor/markdown.js +209 -0
- package/dist/editor/menus.d.ts +20 -0
- package/dist/editor/menus.js +236 -0
- package/dist/editor/nodes.d.ts +14 -0
- package/dist/editor/nodes.js +201 -0
- package/dist/editor/outline.d.ts +11 -0
- package/dist/editor/outline.js +52 -0
- package/dist/editor/schema-form.d.ts +64 -0
- package/dist/editor/schema-form.js +290 -0
- package/dist/editor/slash-menu.d.ts +15 -0
- package/dist/editor/slash-menu.js +119 -0
- package/dist/fonts/catalog.d.ts +53 -0
- package/dist/fonts/catalog.js +121 -0
- package/dist/fonts/font-picker.d.ts +70 -0
- package/dist/fonts/font-picker.js +225 -0
- package/dist/fonts/index.d.ts +6 -0
- package/dist/fonts/index.js +7 -0
- package/dist/fonts/loader.d.ts +66 -0
- package/dist/fonts/loader.js +161 -0
- package/dist/fonts/pairing-picker.d.ts +31 -0
- package/dist/fonts/pairing-picker.js +81 -0
- package/dist/fonts/pairings.d.ts +84 -0
- package/dist/fonts/pairings.js +149 -0
- package/dist/fonts/provider.d.ts +34 -0
- package/dist/fonts/provider.js +51 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/form/index.js +1 -0
- package/dist/format/core.d.ts +149 -0
- package/dist/format/core.js +357 -0
- package/dist/format/index.d.ts +4 -0
- package/dist/format/index.js +5 -0
- package/dist/format/use-format.d.ts +1 -0
- package/dist/format/use-format.js +3 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.js +92 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/cn.js +16 -0
- package/dist/lib/color.d.ts +64 -0
- package/dist/lib/color.js +177 -0
- package/dist/lib/compose-refs.d.ts +24 -0
- package/dist/lib/compose-refs.js +45 -0
- package/dist/lib/data-islands.d.ts +194 -0
- package/dist/lib/data-islands.js +368 -0
- package/dist/lib/date.d.ts +129 -0
- package/dist/lib/date.js +386 -0
- package/dist/lib/field-context.d.ts +64 -0
- package/dist/lib/field-context.js +62 -0
- package/dist/lib/floating-arrow.d.ts +18 -0
- package/dist/lib/floating-arrow.js +15 -0
- package/dist/lib/islands.d.ts +38 -0
- package/dist/lib/islands.js +40 -0
- package/dist/lib/labels.d.ts +51 -0
- package/dist/lib/labels.js +56 -0
- package/dist/lib/layer.d.ts +36 -0
- package/dist/lib/layer.js +42 -0
- package/dist/lib/locale.d.ts +85 -0
- package/dist/lib/locale.js +105 -0
- package/dist/lib/menu.d.ts +58 -0
- package/dist/lib/menu.js +99 -0
- package/dist/lib/message-format.d.ts +20 -0
- package/dist/lib/message-format.js +116 -0
- package/dist/lib/nav.d.ts +132 -0
- package/dist/lib/nav.js +178 -0
- package/dist/lib/provider.d.ts +100 -0
- package/dist/lib/provider.js +105 -0
- package/dist/lib/public.d.ts +23 -0
- package/dist/lib/public.js +34 -0
- package/dist/lib/sr-name.d.ts +18 -0
- package/dist/lib/sr-name.js +17 -0
- package/dist/lib/text.d.ts +100 -0
- package/dist/lib/text.js +233 -0
- package/dist/lib/theme-scope.d.ts +58 -0
- package/dist/lib/theme-scope.js +59 -0
- package/dist/lib/use-async-list.d.ts +60 -0
- package/dist/lib/use-async-list.js +119 -0
- package/dist/lib/use-container-width.d.ts +19 -0
- package/dist/lib/use-container-width.js +39 -0
- package/dist/lib/use-controllable-state.d.ts +33 -0
- package/dist/lib/use-controllable-state.js +56 -0
- package/dist/lib/use-edge-fade.d.ts +13 -0
- package/dist/lib/use-edge-fade.js +43 -0
- package/dist/lib/use-formatted-input.d.ts +69 -0
- package/dist/lib/use-formatted-input.js +152 -0
- package/dist/lib/use-hotkeys.d.ts +80 -0
- package/dist/lib/use-hotkeys.js +221 -0
- package/dist/lib/use-hover-intent.d.ts +44 -0
- package/dist/lib/use-hover-intent.js +119 -0
- package/dist/lib/use-media-query.d.ts +21 -0
- package/dist/lib/use-media-query.js +28 -0
- package/dist/lib/use-reduced-motion.d.ts +8 -0
- package/dist/lib/use-reduced-motion.js +13 -0
- package/dist/lib/use-tree.d.ts +153 -0
- package/dist/lib/use-tree.js +534 -0
- package/dist/lib/value-format.d.ts +25 -0
- package/dist/lib/value-format.js +56 -0
- package/dist/lib/variants.d.ts +131 -0
- package/dist/lib/variants.js +109 -0
- package/dist/locale-data/core/date.d.ts +24 -0
- package/dist/locale-data/core/date.js +68 -0
- package/dist/locale-data/core/decimal.d.ts +19 -0
- package/dist/locale-data/core/decimal.js +79 -0
- package/dist/locale-data/core/holidays.d.ts +30 -0
- package/dist/locale-data/core/holidays.js +79 -0
- package/dist/locale-data/core/iban.d.ts +29 -0
- package/dist/locale-data/core/iban.js +74 -0
- package/dist/locale-data/core/index.d.ts +7 -0
- package/dist/locale-data/core/index.js +6 -0
- package/dist/locale-data/core/types.d.ts +173 -0
- package/dist/locale-data/core/types.js +6 -0
- package/dist/locale-data/core/week-info.d.ts +23 -0
- package/dist/locale-data/core/week-info.js +85 -0
- package/dist/locale-data/core/working-days.d.ts +27 -0
- package/dist/locale-data/core/working-days.js +133 -0
- package/dist/locale-data/index.d.ts +2 -0
- package/dist/locale-data/index.js +4 -0
- package/dist/locale-data/tr/address-tr.json +1 -0
- package/dist/locale-data/tr/address.d.ts +23 -0
- package/dist/locale-data/tr/address.js +52 -0
- package/dist/locale-data/tr/holidays.d.ts +31 -0
- package/dist/locale-data/tr/holidays.js +81 -0
- package/dist/locale-data/tr/iban.d.ts +21 -0
- package/dist/locale-data/tr/iban.js +45 -0
- package/dist/locale-data/tr/id.d.ts +36 -0
- package/dist/locale-data/tr/id.js +120 -0
- package/dist/locale-data/tr/index.d.ts +12 -0
- package/dist/locale-data/tr/index.js +33 -0
- package/dist/locale-data/tr/kdv.d.ts +91 -0
- package/dist/locale-data/tr/kdv.js +222 -0
- package/dist/locales/en.d.ts +2102 -0
- package/dist/locales/en.js +2088 -0
- package/dist/locales/tr.d.ts +2086 -0
- package/dist/locales/tr.js +2087 -0
- package/dist/media/focal-point.d.ts +42 -0
- package/dist/media/focal-point.js +96 -0
- package/dist/media/gallery-layout.d.ts +19 -0
- package/dist/media/gallery-layout.js +61 -0
- package/dist/media/gallery.d.ts +64 -0
- package/dist/media/gallery.js +140 -0
- package/dist/media/image-cropper.d.ts +86 -0
- package/dist/media/image-cropper.js +170 -0
- package/dist/media/image-field.d.ts +115 -0
- package/dist/media/image-field.js +212 -0
- package/dist/media/index.d.ts +19 -0
- package/dist/media/index.js +23 -0
- package/dist/media/lightbox.d.ts +82 -0
- package/dist/media/lightbox.js +171 -0
- package/dist/media/link-preview.d.ts +97 -0
- package/dist/media/link-preview.js +177 -0
- package/dist/media/media-library.d.ts +244 -0
- package/dist/media/media-library.js +776 -0
- package/dist/media/media-picker.d.ts +96 -0
- package/dist/media/media-picker.js +209 -0
- package/dist/media/media-provider.d.ts +23 -0
- package/dist/media/media-provider.js +44 -0
- package/dist/media/media-utils.d.ts +39 -0
- package/dist/media/media-utils.js +145 -0
- package/dist/media/memory-adapter.d.ts +22 -0
- package/dist/media/memory-adapter.js +162 -0
- package/dist/media/rest-adapter.d.ts +90 -0
- package/dist/media/rest-adapter.js +208 -0
- package/dist/media/serp.d.ts +62 -0
- package/dist/media/serp.js +108 -0
- package/dist/media/test-fixtures.d.ts +3 -0
- package/dist/media/test-fixtures.js +37 -0
- package/dist/media/types.d.ts +183 -0
- package/dist/media/types.js +3 -0
- package/dist/media/use-pan-zoom.d.ts +51 -0
- package/dist/media/use-pan-zoom.js +156 -0
- package/dist/media/use-upload-queue.d.ts +64 -0
- package/dist/media/use-upload-queue.js +115 -0
- package/dist/media/video-player.d.ts +135 -0
- package/dist/media/video-player.js +319 -0
- package/dist/motion/core.d.ts +32 -0
- package/dist/motion/core.js +77 -0
- package/dist/motion/count-up.d.ts +29 -0
- package/dist/motion/count-up.js +92 -0
- package/dist/motion/index.d.ts +11 -0
- package/dist/motion/index.js +13 -0
- package/dist/motion/motion-scope.d.ts +17 -0
- package/dist/motion/motion-scope.js +16 -0
- package/dist/motion/page-transition.d.ts +33 -0
- package/dist/motion/page-transition.js +61 -0
- package/dist/motion/parallax.d.ts +37 -0
- package/dist/motion/parallax.js +90 -0
- package/dist/motion/pointer.d.ts +38 -0
- package/dist/motion/pointer.js +117 -0
- package/dist/motion/reveal.d.ts +72 -0
- package/dist/motion/reveal.js +133 -0
- package/dist/motion/scroll-shrink.d.ts +18 -0
- package/dist/motion/scroll-shrink.js +47 -0
- package/dist/motion/skeleton-swap.d.ts +17 -0
- package/dist/motion/skeleton-swap.js +43 -0
- package/dist/motion/text-reveal.d.ts +30 -0
- package/dist/motion/text-reveal.js +29 -0
- package/dist/motion/ticker.d.ts +35 -0
- package/dist/motion/ticker.js +16 -0
- package/dist/next/index.d.ts +42 -0
- package/dist/next/index.js +36 -0
- package/dist/render/block-renderer.d.ts +56 -0
- package/dist/render/block-renderer.js +137 -0
- package/dist/render/index.d.ts +6 -0
- package/dist/render/index.js +7 -0
- package/dist/render/prepare.d.ts +61 -0
- package/dist/render/prepare.js +119 -0
- package/dist/scheduler/core/duration.d.ts +83 -0
- package/dist/scheduler/core/duration.js +174 -0
- package/dist/scheduler/core/gantt.d.ts +63 -0
- package/dist/scheduler/core/gantt.js +226 -0
- package/dist/scheduler/core/index.d.ts +6 -0
- package/dist/scheduler/core/index.js +7 -0
- package/dist/scheduler/core/layout.d.ts +97 -0
- package/dist/scheduler/core/layout.js +249 -0
- package/dist/scheduler/core/time-scale.d.ts +89 -0
- package/dist/scheduler/core/time-scale.js +173 -0
- package/dist/scheduler/gantt.d.ts +125 -0
- package/dist/scheduler/gantt.js +532 -0
- package/dist/scheduler/index.d.ts +6 -0
- package/dist/scheduler/index.js +7 -0
- package/dist/scheduler/resource-calendar.d.ts +218 -0
- package/dist/scheduler/resource-calendar.js +661 -0
- package/dist/scheduler/scheduler.d.ts +168 -0
- package/dist/scheduler/scheduler.js +768 -0
- package/dist/scheduler/shared.d.ts +63 -0
- package/dist/scheduler/shared.js +145 -0
- package/dist/scheduler/time-tracker.d.ts +138 -0
- package/dist/scheduler/time-tracker.js +403 -0
- package/dist/sortable/core.d.ts +67 -0
- package/dist/sortable/core.js +167 -0
- package/dist/sortable/index.d.ts +8 -0
- package/dist/sortable/index.js +10 -0
- package/dist/sortable/kanban-core.d.ts +70 -0
- package/dist/sortable/kanban-core.js +67 -0
- package/dist/sortable/kanban.d.ts +147 -0
- package/dist/sortable/kanban.js +472 -0
- package/dist/sortable/sortable-list.d.ts +71 -0
- package/dist/sortable/sortable-list.js +76 -0
- package/dist/sortable/sortable-tree.d.ts +105 -0
- package/dist/sortable/sortable-tree.js +462 -0
- package/dist/sortable/sortable.d.ts +188 -0
- package/dist/sortable/sortable.js +485 -0
- package/dist/sortable/use-pointer-drag.d.ts +75 -0
- package/dist/sortable/use-pointer-drag.js +173 -0
- package/dist/sortable/use-time-scale.d.ts +11 -0
- package/dist/sortable/use-time-scale.js +19 -0
- package/dist/styles/base.css +51 -0
- package/dist/styles/blocks.css +949 -0
- package/dist/styles/calendar.css +642 -0
- package/dist/styles/charts.css +264 -0
- package/dist/styles/data.css +474 -0
- package/dist/styles/editors.css +1022 -0
- package/dist/styles/forms.css +406 -0
- package/dist/styles/media.css +515 -0
- package/dist/styles/motion.css +389 -0
- package/dist/styles/navigation.css +293 -0
- package/dist/styles/overlays.css +244 -0
- package/dist/styles.css +743 -0
- package/package.json +160 -4
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Area, Bar, ComposedChart, Line } from "recharts";
|
|
5
|
+
import { useLocale } from "../lib/locale.js";
|
|
6
|
+
import { Chart, useChart } from "./chart-shell.js";
|
|
7
|
+
import { ChartFrame, ChartGrid, ChartTooltip, ChartXAxis, ChartYAxis, useValueAxisWidth } from "./chart.js";
|
|
8
|
+
import { alignZeroDomains, extent, patternDash, seriesColor } from "./utils.js";
|
|
9
|
+
/**
|
|
10
|
+
* Volume and rate on two axes — bars on the start axis, a line on the end axis, zero lines aligned
|
|
11
|
+
* so neither scale exaggerates. Axis sides are logical and swap in RTL.
|
|
12
|
+
*
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <ComboChart title="Quotes and win rate" data={rows} x="month" bars={["quotes"]} lines={["winRate"]} config={config} />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function ComboChart({ bars, lines, areas = [], endAxisFormat, endAxis = true, stackBars, startAxisLabel, endAxisLabel, ...props }) {
|
|
18
|
+
return (_jsx(Chart, { skeleton: "bar", ...props, children: _jsx(ComboPlot, { bars: bars, lines: lines, areas: areas, endAxisFormat: endAxisFormat, endAxis: endAxis, stackBars: stackBars, startAxisLabel: startAxisLabel, endAxisLabel: endAxisLabel }) }));
|
|
19
|
+
}
|
|
20
|
+
function ComboPlot({ bars, lines, areas = [], endAxisFormat, endAxis, stackBars, startAxisLabel, endAxisLabel }) {
|
|
21
|
+
const chart = useChart();
|
|
22
|
+
const rtl = useLocale().dir === "rtl";
|
|
23
|
+
const axisOf = (key, fallback) => chart.config[key]?.axis ?? fallback;
|
|
24
|
+
const visible = (k) => !chart.isHidden(k);
|
|
25
|
+
const startKeys = [...bars.filter((k) => axisOf(k, "start") === "start"), ...lines.filter((k) => axisOf(k, "end") === "start"), ...areas.filter((k) => axisOf(k, "start") === "start")].filter(visible);
|
|
26
|
+
const endKeys = [...bars.filter((k) => axisOf(k, "start") === "end"), ...lines.filter((k) => axisOf(k, "end") === "end"), ...areas.filter((k) => axisOf(k, "start") === "end")].filter(visible);
|
|
27
|
+
const startStacked = Boolean(stackBars);
|
|
28
|
+
const endFormat = endAxisFormat ?? chart.config[endKeys[0] ?? ""]?.format;
|
|
29
|
+
const startFormat = chart.config[startKeys[0] ?? ""]?.format ?? chart.yFormat;
|
|
30
|
+
const [startDomain, endDomain] = React.useMemo(() => {
|
|
31
|
+
const a = extent(chart.data, startKeys, startStacked);
|
|
32
|
+
const b = extent(chart.data, endKeys);
|
|
33
|
+
return alignZeroDomains(a, b);
|
|
34
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
+
}, [chart.data, startKeys.join(), endKeys.join(), startStacked]);
|
|
36
|
+
// Non-negative data: four equal steps on both axes, so the grid lines serve both scales.
|
|
37
|
+
const ticksOf = (d) => (d[0] === 0 ? [0, 1, 2, 3, 4].map((i) => Number(((d[1] * i) / 4).toPrecision(12))) : undefined);
|
|
38
|
+
const startWidth = useValueAxisWidth(startKeys, { stacked: startStacked, format: startFormat });
|
|
39
|
+
const endWidth = useValueAxisWidth(endKeys, { format: endFormat });
|
|
40
|
+
const left = rtl ? "end" : "start";
|
|
41
|
+
const yId = (key, fallback) => axisOf(key, fallback);
|
|
42
|
+
const titleProps = (value, side) => value ? { value, angle: -90, position: side === "left" ? "insideLeft" : "insideRight", className: "vui-chart-axis-title", offset: 0, style: { textAnchor: "middle" } } : undefined;
|
|
43
|
+
return (_jsx(ChartFrame, { children: _jsxs(ComposedChart, { data: chart.data, stackOffset: startStacked && startDomain[0] < 0 ? "sign" : undefined, margin: { top: 8, right: 4, bottom: 0, left: 4 }, barCategoryGap: "30%", children: [_jsx(ChartGrid, { yAxisId: "start" }), _jsx(ChartXAxis, {}), _jsx(ChartYAxis, { yAxisId: "start", orientation: left === "start" ? "left" : "right", domain: startDomain, ticks: ticksOf(startDomain), width: startWidth + (startAxisLabel ? 16 : 0), tickFormatter: (v) => chart.formatTick(v, startFormat), label: titleProps(startAxisLabel, left === "start" ? "left" : "right"), keys: startKeys }), _jsx(ChartYAxis, { yAxisId: "end", orientation: left === "start" ? "right" : "left", domain: endDomain, ticks: ticksOf(endDomain), hide: !endAxis || endKeys.length === 0, width: endWidth + (endAxisLabel ? 16 : 0), tickFormatter: (v) => chart.formatTick(v, endFormat), label: titleProps(endAxisLabel, left === "start" ? "right" : "left"), keys: endKeys }), _jsx(ChartTooltip, { cursor: { fill: "var(--hover)" } }), areas.map((key) => (_jsx(Area, { yAxisId: yId(key, "start"), dataKey: key, name: chart.config[key]?.label, hide: chart.isHidden(key), type: "monotone", stroke: seriesColor(key), strokeWidth: 1.5, fill: `color-mix(in oklch, ${seriesColor(key)} 16%, transparent)`, isAnimationActive: chart.animate }, key))), bars.map((key, i) => (_jsx(Bar, { yAxisId: yId(key, "start"), dataKey: key, name: chart.config[key]?.label, hide: chart.isHidden(key), stackId: stackBars ? "bars" : undefined, fill: seriesColor(key), radius: stackBars && i < bars.length - 1 ? 0 : [4, 4, 0, 0], maxBarSize: 40, isAnimationActive: chart.animate }, key))), lines.map((key) => {
|
|
44
|
+
const s = chart.series.find((x) => x.key === key);
|
|
45
|
+
return (_jsx(Line, { yAxisId: yId(key, "end"), dataKey: key, name: s?.label, hide: chart.isHidden(key), type: "monotone", stroke: seriesColor(key), strokeWidth: 2, strokeDasharray: patternDash(s?.pattern), dot: { r: 2.5, fill: seriesColor(key), stroke: "var(--chart-tooltip)", strokeWidth: 1.5 }, activeDot: { r: 4, strokeWidth: 2, stroke: "var(--chart-tooltip)", fill: seriesColor(key) }, isAnimationActive: chart.animate }, key));
|
|
46
|
+
})] }) }));
|
|
47
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ChartProps } from "./chart-shell.js";
|
|
3
|
+
import { type FormatSpec } from "./utils.js";
|
|
4
|
+
export interface DonutChartProps<T extends object> extends Omit<ChartProps<T>, "children" | "x" | "legend" | "height" | "aspect" | "aside" | "table"> {
|
|
5
|
+
/** Row key holding the slice id (matches config keys). */
|
|
6
|
+
nameKey: keyof T & string;
|
|
7
|
+
/** Row key holding the slice value. */
|
|
8
|
+
valueKey: keyof T & string;
|
|
9
|
+
/** Centre content: the visible total (default), your own node, or nothing. Hovering a slice shows that slice. */
|
|
10
|
+
center?: React.ReactNode | "total" | "none";
|
|
11
|
+
/** Label under the centre total. Default "Total". */
|
|
12
|
+
centerLabel?: string;
|
|
13
|
+
/** Slices beyond this count merge into "Other" (`fg-subtle`). Default 5. */
|
|
14
|
+
maxSlices?: number;
|
|
15
|
+
variant?: "donut" | "pie" | "half";
|
|
16
|
+
/** Legend list with value + share: beside the ring (default), under it, or none. */
|
|
17
|
+
legend?: "side" | "bottom" | "none";
|
|
18
|
+
size?: "sm" | "md" | "lg" | number;
|
|
19
|
+
/** Format of the values. Default: the first config entry's format, else `"number"`. */
|
|
20
|
+
format?: FormatSpec;
|
|
21
|
+
/** Controlled active slice (hover / legend focus). */
|
|
22
|
+
activeKey?: string | null;
|
|
23
|
+
onActiveChange?: (key: string | null) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parts of a whole (≤ 6 slices). The legend is a real list with value and share, so the chart never
|
|
27
|
+
* relies on colour alone; focusing an item highlights its slice and the centre shows its numbers.
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <DonutChart title="Leads by source" data={rows} nameKey="source" valueKey="leads" config={{ organic: { label: "Organic search" } }} />
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function DonutChart<T extends object>({ data, nameKey, valueKey, config, center, centerLabel, maxSlices, variant, legend, size, format, activeKey, onActiveChange, summary, ...props }: DonutChartProps<T>): React.JSX.Element;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Cell, Pie, PieChart, Sector } from "recharts";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { useControllableState } from "../lib/use-controllable-state.js";
|
|
7
|
+
import { useLabels } from "../lib/labels.js";
|
|
8
|
+
import { Chart, ChartIndicator, chartLabels, useChart } from "./chart-shell.js";
|
|
9
|
+
import { useFormat } from "../lib/locale.js";
|
|
10
|
+
import { formatValue, seriesColor } from "./utils.js";
|
|
11
|
+
const SIZES = { sm: 120, md: 180, lg: 240 };
|
|
12
|
+
const OTHER_KEY = "__other";
|
|
13
|
+
/**
|
|
14
|
+
* Parts of a whole (≤ 6 slices). The legend is a real list with value and share, so the chart never
|
|
15
|
+
* relies on colour alone; focusing an item highlights its slice and the centre shows its numbers.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <DonutChart title="Leads by source" data={rows} nameKey="source" valueKey="leads" config={{ organic: { label: "Organic search" } }} />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function DonutChart({ data, nameKey, valueKey, config, center = "total", centerLabel, maxSlices = 5, variant = "donut", legend = "side", size = "md", format, activeKey, onActiveChange, summary, ...props }) {
|
|
22
|
+
const rows = data;
|
|
23
|
+
const f = useFormat();
|
|
24
|
+
const t = useLabels("chart", chartLabels, props.labels);
|
|
25
|
+
const valueFormat = format ?? Object.values(config)[0]?.format;
|
|
26
|
+
const [active, setActive] = useControllableState({ value: activeKey, defaultValue: null, onChange: onActiveChange, name: "DonutChart" });
|
|
27
|
+
const px = typeof size === "number" ? size : SIZES[size];
|
|
28
|
+
const height = variant === "half" ? Math.round(px / 2) + 10 : px;
|
|
29
|
+
const { slices, effectiveConfig } = React.useMemo(() => {
|
|
30
|
+
const raw = rows.map((r) => ({ key: String(r[nameKey]), value: Math.max(0, Number(r[valueKey]) || 0) }));
|
|
31
|
+
let list = raw;
|
|
32
|
+
if (raw.length > maxSlices) {
|
|
33
|
+
const sorted = [...raw].sort((a, b) => b.value - a.value);
|
|
34
|
+
const keep = new Set(sorted.slice(0, maxSlices - 1).map((s) => s.key));
|
|
35
|
+
const rest = raw.filter((s) => !keep.has(s.key));
|
|
36
|
+
list = [...raw.filter((s) => keep.has(s.key)), { key: OTHER_KEY, value: rest.reduce((s, r) => s + r.value, 0) }];
|
|
37
|
+
}
|
|
38
|
+
const cfg = {};
|
|
39
|
+
for (const s of list)
|
|
40
|
+
cfg[s.key] = s.key === OTHER_KEY ? { label: config[OTHER_KEY]?.label ?? "", color: "fg-subtle", format } : { ...config[s.key], label: config[s.key]?.label ?? s.key, format: valueFormat };
|
|
41
|
+
return { slices: list, effectiveConfig: cfg };
|
|
42
|
+
}, [rows, nameKey, valueKey, maxSlices, config, valueFormat]);
|
|
43
|
+
const total = slices.reduce((s, r) => s + r.value, 0);
|
|
44
|
+
const otherLabel = t("other");
|
|
45
|
+
const labelOf = (k) => (k === OTHER_KEY ? effectiveConfig[k]?.label || otherLabel : (effectiveConfig[k]?.label ?? k));
|
|
46
|
+
const table = {
|
|
47
|
+
columns: [
|
|
48
|
+
{ key: "label", label: t("category"), header: true },
|
|
49
|
+
{ key: "value", label: t("value"), format: valueFormat },
|
|
50
|
+
{ key: "share", label: t("share"), format: "percent" },
|
|
51
|
+
],
|
|
52
|
+
rows: slices.map((s) => ({ label: labelOf(s.key), value: s.value, share: total ? s.value / total : 0 })),
|
|
53
|
+
};
|
|
54
|
+
const summaryText = summary ?? (total ? slices.map((s) => `${labelOf(s.key)} ${f.percent(s.value / total)} (${formatValue(f, valueFormat, s.value)})`).join(", ") + "." : "");
|
|
55
|
+
const ctx = React.useMemo(() => ({ active, setActive, raw: slices }), [active, setActive, slices]);
|
|
56
|
+
return (_jsx(DonutContext.Provider, { value: ctx, children: _jsx(Chart, { ...props, data: slices, config: effectiveConfig, height: height, legend: "none", skeleton: "donut", summary: summaryText, table: table, state: props.state ?? (rows.length === 0 ? { status: "empty" } : undefined), aside: legend === "none" ? undefined : _jsx(DonutLegend, {}), asidePosition: legend === "bottom" ? "bottom" : "side", children: _jsx(DonutPlot, { px: px, height: height, variant: variant, center: center, centerLabel: centerLabel }) }) }));
|
|
57
|
+
}
|
|
58
|
+
const DonutContext = React.createContext(null);
|
|
59
|
+
const useDonut = () => React.useContext(DonutContext);
|
|
60
|
+
function useSlices(slices) {
|
|
61
|
+
const chart = useChart();
|
|
62
|
+
return React.useMemo(() => {
|
|
63
|
+
const visible = slices.filter((s) => !chart.isHidden(s.key));
|
|
64
|
+
const total = visible.reduce((s, r) => s + r.value, 0);
|
|
65
|
+
return slices.map((s) => ({
|
|
66
|
+
key: s.key,
|
|
67
|
+
label: s.key === OTHER_KEY ? chart.config[s.key]?.label || chart.t("other") : (chart.config[s.key]?.label ?? s.key),
|
|
68
|
+
value: s.value,
|
|
69
|
+
share: total && !chart.isHidden(s.key) ? s.value / total : 0,
|
|
70
|
+
}));
|
|
71
|
+
}, [slices, chart]);
|
|
72
|
+
}
|
|
73
|
+
function DonutPlot({ px, height, variant, center, centerLabel, }) {
|
|
74
|
+
const chart = useChart();
|
|
75
|
+
const { active, setActive, raw } = useDonut();
|
|
76
|
+
const slices = useSlices(raw);
|
|
77
|
+
const visible = slices.filter((s) => !chart.isHidden(s.key) && s.value > 0);
|
|
78
|
+
const total = visible.reduce((s, r) => s + r.value, 0);
|
|
79
|
+
const half = variant === "half";
|
|
80
|
+
const outer = half ? px / 2 - 4 : px / 2 - 4;
|
|
81
|
+
const inner = variant === "pie" ? 0 : outer * (px < 140 ? 0.66 : 0.72);
|
|
82
|
+
const activeSlice = active ? slices.find((s) => s.key === active && !chart.isHidden(s.key)) : undefined;
|
|
83
|
+
const fmt = (v) => chart.formatSeries(raw[0]?.key ?? "", v);
|
|
84
|
+
let centerNode = null;
|
|
85
|
+
if (variant !== "pie" && center !== "none") {
|
|
86
|
+
if (activeSlice)
|
|
87
|
+
centerNode = (_jsxs(_Fragment, { children: [_jsx("span", { className: "max-w-[80%] truncate text-[11.5px] text-fg-muted", children: activeSlice.label }), _jsx("span", { className: cn("font-mono leading-none font-medium tracking-[-0.02em] text-fg tabular", px >= 180 ? "text-[22px]" : "text-[17px]"), children: fmt(activeSlice.value) }), _jsx("span", { className: "font-mono text-[11.5px] text-fg-subtle tabular", children: chart.f.percent(activeSlice.share) })] }));
|
|
88
|
+
else if (center === "total" || center === undefined)
|
|
89
|
+
centerNode = (_jsxs(_Fragment, { children: [_jsx("span", { className: cn("font-mono leading-none font-medium tracking-[-0.02em] text-fg tabular", px >= 180 ? "text-[24px]" : "text-[17px]"), children: fmt(total) }), _jsx("span", { className: "text-[11.5px] text-fg-muted", children: centerLabel ?? chart.t("total") })] }));
|
|
90
|
+
else
|
|
91
|
+
centerNode = center;
|
|
92
|
+
}
|
|
93
|
+
const shape = (p) => {
|
|
94
|
+
const key = String(p.payload?.key ?? "");
|
|
95
|
+
const isActive = key === active;
|
|
96
|
+
const dim = active && !isActive;
|
|
97
|
+
const { key: _key, ...sector } = p;
|
|
98
|
+
void _key;
|
|
99
|
+
return _jsx(Sector, { ...sector, outerRadius: (p.outerRadius ?? outer) + (isActive ? 4 : 0), fillOpacity: dim ? 0.45 : 1, style: { transition: "fill-opacity 160ms" } });
|
|
100
|
+
};
|
|
101
|
+
return (_jsx("div", { className: "flex size-full items-center justify-center", onMouseLeave: () => setActive(null), children: _jsxs("div", { className: "relative", style: { width: px, height }, children: [_jsx(PieChart, { width: px, height: height, accessibilityLayer: false, margin: { top: 0, right: 0, bottom: 0, left: 0 }, children: total === 0 ? (_jsx(Pie, { data: [{ key: "empty", value: 1 }], dataKey: "value", cx: "50%", cy: half ? height - 6 : "50%", innerRadius: inner, outerRadius: outer, startAngle: half ? 180 : 90, endAngle: half ? 0 : -270, stroke: "none", isAnimationActive: false, rootTabIndex: -1, children: _jsx(Cell, { fill: "var(--track)" }) })) : (_jsx(Pie, { data: visible, dataKey: "value", nameKey: "label", cx: "50%", cy: half ? height - 6 : "50%", innerRadius: inner, outerRadius: outer, startAngle: half ? 180 : 90, endAngle: half ? 0 : -270, paddingAngle: visible.length > 1 ? (variant === "pie" ? 0.8 : 1.6) : 0, cornerRadius: variant === "pie" ? 0 : 3, stroke: variant === "pie" ? "var(--chart-tooltip)" : "none", strokeWidth: variant === "pie" ? 1.5 : 0, shape: shape, isAnimationActive: chart.animate, animationDuration: 600, rootTabIndex: -1, onMouseEnter: (d) => setActive(d.payload?.key ?? null), children: visible.map((s) => (_jsx(Cell, { fill: seriesColor(s.key) }, s.key))) })) }), centerNode ? (_jsx("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-x-0 flex flex-col items-center gap-1 text-center", half ? "bottom-1.5" : "inset-y-0 justify-center"), children: total === 0 && !activeSlice ? _jsx("span", { className: "text-[12px] text-fg-muted", children: chart.t("empty") }) : centerNode })) : null] }) }));
|
|
102
|
+
}
|
|
103
|
+
/** Legend list for a donut: a `<ul>` with swatch, label, value and share. Click hides a slice; focus highlights it. */
|
|
104
|
+
function DonutLegend() {
|
|
105
|
+
const chart = useChart();
|
|
106
|
+
const { active, setActive, raw } = useDonut();
|
|
107
|
+
const slices = useSlices(raw);
|
|
108
|
+
return (_jsx("ul", { "data-slot": "donut-legend", "aria-label": chart.t("legend"), className: "grid gap-0.5", children: slices.map((s) => {
|
|
109
|
+
const hidden = chart.isHidden(s.key);
|
|
110
|
+
const locked = !hidden && chart.visibleSeries.length <= 1;
|
|
111
|
+
return (_jsx("li", { children: _jsxs("button", { type: "button", "aria-pressed": !hidden, "aria-disabled": locked || undefined, onClick: () => chart.toggleSeries(s.key), onFocus: () => setActive(hidden ? null : s.key), onBlur: () => setActive(null), onMouseEnter: () => setActive(hidden ? null : s.key), onMouseLeave: () => setActive(null), className: cn("flex h-8 w-full items-center gap-2.5 rounded-ui-sm px-2 text-start text-[13px] transition-[background-color,opacity] focus-ring hover:bg-hover", active === s.key && "bg-hover", hidden && "opacity-50"), children: [_jsx(ChartIndicator, { color: seriesColor(s.key) }), _jsx("span", { className: cn("me-auto truncate text-fg", hidden && "line-through decoration-fg-subtle"), children: s.label }), _jsx("span", { className: "font-mono text-[12.5px] text-fg tabular", children: chart.formatSeries(s.key, s.value) }), _jsx("span", { className: "w-11 text-end font-mono text-[12px] text-fg-subtle tabular", children: hidden ? "—" : chart.f.percent(s.share) })] }) }, s.key));
|
|
112
|
+
}) }));
|
|
113
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ChartColor, type FormatSpec } from "./utils.js";
|
|
3
|
+
export declare const funnelLabels: {
|
|
4
|
+
conversion: string;
|
|
5
|
+
overall: string;
|
|
6
|
+
dropoff: string;
|
|
7
|
+
stage: string;
|
|
8
|
+
stageWithConversion: string;
|
|
9
|
+
compare: string;
|
|
10
|
+
points: string;
|
|
11
|
+
loading: string;
|
|
12
|
+
empty: string;
|
|
13
|
+
};
|
|
14
|
+
export type FunnelLabels = typeof funnelLabels;
|
|
15
|
+
export interface FunnelStep {
|
|
16
|
+
key: string;
|
|
17
|
+
label: string;
|
|
18
|
+
value: number;
|
|
19
|
+
/** Money (or any second number) per stage, e.g. pipeline value. */
|
|
20
|
+
amount?: number;
|
|
21
|
+
href?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface FunnelProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onClick"> {
|
|
24
|
+
steps: FunnelStep[];
|
|
25
|
+
/** `horizontal` = stage columns (falls back to rows in a narrow container); `vertical` = stacked rows (mobile). */
|
|
26
|
+
orientation?: "horizontal" | "vertical";
|
|
27
|
+
format?: FormatSpec;
|
|
28
|
+
/** Format of `amount`. Default compact currency. */
|
|
29
|
+
amountFormat?: FormatSpec;
|
|
30
|
+
/** Metrics under each stage. Default `["conversion", "dropoff"]`. */
|
|
31
|
+
show?: ("conversion" | "overall" | "dropoff")[];
|
|
32
|
+
/** Base colour; later stages fade. Default `chart-1`. */
|
|
33
|
+
color?: ChartColor;
|
|
34
|
+
/** The same stages for a previous period — adds a marker and the conversion change. */
|
|
35
|
+
compareTo?: FunnelStep[];
|
|
36
|
+
onStepClick?: (step: FunnelStep) => void;
|
|
37
|
+
size?: "sm" | "md";
|
|
38
|
+
loading?: boolean;
|
|
39
|
+
/** Accessible name of the list. */
|
|
40
|
+
title?: string;
|
|
41
|
+
labels?: Partial<FunnelLabels>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Stage-by-stage conversion as aligned bars: value, conversion from the previous stage, drop-off and
|
|
45
|
+
* an optional amount. Drop-off is muted, not red — losing leads between stages is normal.
|
|
46
|
+
*
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <Funnel title="Sales pipeline" steps={[{ key: "leads", label: "Leads", value: 1240 }, …]} />
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const Funnel: React.ForwardRefExoticComponent<FunnelProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { CornerDownRight } from "lucide-react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { useFormat } from "../lib/locale.js";
|
|
7
|
+
import { useLabels } from "../lib/labels.js";
|
|
8
|
+
import { Skeleton } from "../components/skeleton.js";
|
|
9
|
+
import { formatValue, resolveChartColor } from "./utils.js";
|
|
10
|
+
export const funnelLabels = {
|
|
11
|
+
conversion: "{percent} of {previous}",
|
|
12
|
+
overall: "{percent} overall",
|
|
13
|
+
dropoff: "−{count}",
|
|
14
|
+
stage: "{label}: {value}",
|
|
15
|
+
stageWithConversion: "{label}: {value} ({percent} of {previous})",
|
|
16
|
+
compare: "{delta} vs previous period",
|
|
17
|
+
points: "{value} pt",
|
|
18
|
+
loading: "Loading…",
|
|
19
|
+
empty: "No stages yet",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Stage-by-stage conversion as aligned bars: value, conversion from the previous stage, drop-off and
|
|
23
|
+
* an optional amount. Drop-off is muted, not red — losing leads between stages is normal.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <Funnel title="Sales pipeline" steps={[{ key: "leads", label: "Leads", value: 1240 }, …]} />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const Funnel = React.forwardRef(function Funnel({ steps, orientation = "horizontal", format = "integer", amountFormat = "currency", show = ["conversion", "dropoff"], color = "chart-1", compareTo, onStepClick, size = "md", loading, title, labels, className, style, ...props }, ref) {
|
|
30
|
+
const f = useFormat();
|
|
31
|
+
const t = useLabels("funnel", funnelLabels, labels);
|
|
32
|
+
const first = steps[0]?.value ?? 0;
|
|
33
|
+
const max = Math.max(first, ...steps.map((s) => s.value), 1);
|
|
34
|
+
const base = resolveChartColor(color);
|
|
35
|
+
if (process.env.NODE_ENV !== "production") {
|
|
36
|
+
steps.forEach((s, i) => {
|
|
37
|
+
if (i > 0 && s.value > steps[i - 1].value)
|
|
38
|
+
console.warn(`[vamos-ui] Funnel: stage "${s.key}" is larger than the stage before it.`);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (loading)
|
|
42
|
+
return (_jsxs("div", { ref: ref, "aria-busy": true, className: cn("grid gap-3", className), ...props, children: [_jsx("span", { role: "status", className: "sr-only", children: t("loading") }), [100, 72, 48, 30, 18].map((w, i) => (_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Skeleton, { shape: "text", className: "w-24 text-[13px]" }), _jsx(Skeleton, { className: "h-6", style: { width: `${w}%` } })] }, i)))] }));
|
|
43
|
+
if (!steps.length)
|
|
44
|
+
return _jsx("p", { className: cn("py-6 text-center text-[13px] text-fg-muted", className), children: t("empty") });
|
|
45
|
+
const pct = (v) => f.percent(v, { maximumFractionDigits: v < 0.1 ? 1 : 0 });
|
|
46
|
+
const prevSteps = compareTo ? new Map(compareTo.map((s, i) => [s.key, { step: s, prev: compareTo[i - 1] }])) : null;
|
|
47
|
+
return (_jsx("div", { ref: ref, "data-slot": "funnel", "data-orientation": orientation, "data-size": size, className: cn("vui-funnel @container", className), style: style, ...props, children: _jsx("ol", { "aria-label": title, className: "vui-funnel-list", style: { "--funnel-n": steps.length }, children: steps.map((s, i) => {
|
|
48
|
+
const prev = steps[i - 1];
|
|
49
|
+
const conv = prev ? (prev.value > 0 ? s.value / prev.value : null) : null;
|
|
50
|
+
const overall = first > 0 ? s.value / first : null;
|
|
51
|
+
const drop = prev ? prev.value - s.value : 0;
|
|
52
|
+
const valueText = formatValue(f, format, s.value);
|
|
53
|
+
const convText = conv === null ? "—" : pct(conv);
|
|
54
|
+
const fade = steps.length > 1 ? 100 - (i / (steps.length - 1)) * 52 : 100;
|
|
55
|
+
const fill = `color-mix(in oklch, ${base} ${fade}%, var(--surface-solid, var(--surface)))`;
|
|
56
|
+
const cmp = prevSteps?.get(s.key);
|
|
57
|
+
const prevConv = cmp?.prev && cmp.prev.value > 0 ? cmp.step.value / cmp.prev.value : null;
|
|
58
|
+
const convDelta = conv !== null && prevConv !== null ? conv - prevConv : null;
|
|
59
|
+
const deltaText = convDelta === null ? null : `${convDelta >= 0 ? "+" : "−"}${t("points", { value: f.number(Math.abs(convDelta) * 100, { maximumFractionDigits: 1 }) })}`;
|
|
60
|
+
const srText = [
|
|
61
|
+
prev ? t("stageWithConversion", { label: s.label, value: valueText, percent: convText, previous: prev.label }) : t("stage", { label: s.label, value: valueText }),
|
|
62
|
+
s.amount !== undefined ? formatValue(f, amountFormat, s.amount) : null,
|
|
63
|
+
deltaText ? t("compare", { delta: deltaText }) : null,
|
|
64
|
+
]
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.join(", ");
|
|
67
|
+
return (_jsxs("li", { className: "vui-funnel-step group/step relative", children: [_jsxs("div", { className: "vui-funnel-head flex min-w-0 items-baseline justify-between gap-3", children: [s.href ? (_jsx("a", { href: s.href, "aria-label": srText, className: "truncate rounded-ui-sm text-[13px] text-fg focus-ring after:absolute after:inset-0 hover:underline hover:underline-offset-4", children: s.label })) : onStepClick ? (_jsx("button", { type: "button", "aria-label": srText, onClick: () => onStepClick(s), className: "truncate rounded-ui-sm text-start text-[13px] text-fg focus-ring after:absolute after:inset-0 group-hover/step:underline group-hover/step:underline-offset-4", children: s.label })) : (_jsxs("span", { className: "truncate text-[13px] text-fg", children: [_jsx("span", { "aria-hidden": true, children: s.label }), _jsx("span", { className: "sr-only", children: srText })] })), _jsx("span", { "aria-hidden": true, className: "vui-funnel-value font-mono text-fg tabular", children: valueText })] }), _jsxs("div", { "aria-hidden": true, className: "vui-funnel-track", children: [_jsx("div", { className: "vui-funnel-fill", style: { "--p": Math.max(1.5, (s.value / max) * 100), background: fill } }), cmp ? _jsx("div", { className: "vui-funnel-marker", style: { "--p": Math.min(100, (cmp.step.value / Math.max(max, compareTo?.[0]?.value ?? 0)) * 100) } }) : null] }), _jsxs("div", { "aria-hidden": true, className: "vui-funnel-meta flex flex-wrap items-center gap-x-2.5 gap-y-0.5 font-mono text-[11.5px] text-fg-muted tabular", children: [s.amount !== undefined ? _jsx("span", { className: "text-fg", children: formatValue(f, amountFormat, s.amount, { compact: true }) }) : null, prev && show.includes("conversion") ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-fg", title: t("conversion", { percent: convText, previous: prev.label }), children: [_jsx(CornerDownRight, { className: "size-3 text-fg-subtle" }), convText] })) : null, prev && show.includes("dropoff") && drop > 0 ? _jsx("span", { className: "text-fg-subtle", children: t("dropoff", { count: formatValue(f, format, drop) }) }) : null, i > 0 && show.includes("overall") && overall !== null ? _jsx("span", { className: "text-fg-subtle", children: t("overall", { percent: pct(overall) }) }) : null, deltaText ? _jsx("span", { className: cn(convDelta >= 0 ? "text-success" : "text-danger"), children: deltaText }) : null] })] }, s.key));
|
|
68
|
+
}) }) }));
|
|
69
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ChartColor, type FormatSpec } from "./utils.js";
|
|
3
|
+
export declare const gaugeLabels: {
|
|
4
|
+
valueText: string;
|
|
5
|
+
valueTextWithLabel: string;
|
|
6
|
+
target: string;
|
|
7
|
+
noValue: string;
|
|
8
|
+
};
|
|
9
|
+
export type GaugeLabels = typeof gaugeLabels;
|
|
10
|
+
export interface GaugeThreshold {
|
|
11
|
+
/** Applies from this value up. */
|
|
12
|
+
at: number;
|
|
13
|
+
color: ChartColor;
|
|
14
|
+
/** Word for the band ("Fair") — shown under the value and read in `aria-valuetext`. */
|
|
15
|
+
label?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ProgressRingProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "color"> {
|
|
18
|
+
/** Current value. `null` = unknown (empty track, "—"). */
|
|
19
|
+
value: number | null;
|
|
20
|
+
/** Default 100. */
|
|
21
|
+
max?: number;
|
|
22
|
+
size?: "xs" | "sm" | "md" | "lg" | number;
|
|
23
|
+
/** Stroke width in px. Default: about a tenth of the size. */
|
|
24
|
+
thickness?: number;
|
|
25
|
+
/** Fill token, or `"auto"` to take it from `thresholds`. Default `chart-1`. */
|
|
26
|
+
color?: ChartColor | "auto";
|
|
27
|
+
thresholds?: GaugeThreshold[];
|
|
28
|
+
/** Centre content (md and lg). Default: the formatted value. Pass `null` for none. */
|
|
29
|
+
label?: React.ReactNode;
|
|
30
|
+
/** `percent` shows value / max; any other spec formats the value itself. */
|
|
31
|
+
format?: FormatSpec;
|
|
32
|
+
/** `progress` (task completion) → role="progressbar"; `meter` (a score) → role="meter". Default `progress`. */
|
|
33
|
+
semantic?: "progress" | "meter";
|
|
34
|
+
"aria-label": string;
|
|
35
|
+
labels?: Partial<GaugeLabels>;
|
|
36
|
+
}
|
|
37
|
+
export interface GaugeProps extends ProgressRingProps {
|
|
38
|
+
/** Sweep of the arc. Default 270. */
|
|
39
|
+
arc?: 180 | 270;
|
|
40
|
+
/** Paint the threshold ranges as a thin outer band. */
|
|
41
|
+
showThresholdBands?: boolean;
|
|
42
|
+
/** A marker on the arc (quota, goal). */
|
|
43
|
+
target?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A full ring for progress to a target — profile completeness, quota, upload. Plain SVG; `xs` fits
|
|
47
|
+
* in a table cell.
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <ProgressRing value={85} aria-label="Profile completeness" format="percent" size="md" />
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare const ProgressRing: React.ForwardRefExoticComponent<ProgressRingProps & React.RefAttributes<HTMLDivElement>>;
|
|
54
|
+
/**
|
|
55
|
+
* A score or attainment on a 180° / 270° arc with optional threshold bands and a target marker —
|
|
56
|
+
* SEO score, quota, NPS. `semantic="meter"` for scores.
|
|
57
|
+
*
|
|
58
|
+
* ```tsx
|
|
59
|
+
* <Gauge value={64} aria-label="SEO score" semantic="meter" thresholds={[{ at: 0, color: "danger", label: "Poor" }, { at: 50, color: "warning", label: "Fair" }, { at: 80, color: "success", label: "Good" }]} color="auto" />
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const Gauge: React.ForwardRefExoticComponent<GaugeProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { useFormat } from "../lib/locale.js";
|
|
6
|
+
import { useLabels } from "../lib/labels.js";
|
|
7
|
+
import { formatValue, resolveChartColor } from "./utils.js";
|
|
8
|
+
export const gaugeLabels = {
|
|
9
|
+
valueText: "{value} of {max}",
|
|
10
|
+
valueTextWithLabel: "{value} of {max}, {label}",
|
|
11
|
+
target: "Target {value}",
|
|
12
|
+
noValue: "No value",
|
|
13
|
+
};
|
|
14
|
+
const SIZES = { xs: 20, sm: 36, md: 96, lg: 160 };
|
|
15
|
+
function pickThreshold(value, thresholds) {
|
|
16
|
+
if (value === null || !thresholds?.length)
|
|
17
|
+
return undefined;
|
|
18
|
+
return [...thresholds].sort((a, b) => a.at - b.at).filter((t) => value >= t.at).pop();
|
|
19
|
+
}
|
|
20
|
+
function useGaugeText(value, max, format, threshold, labels) {
|
|
21
|
+
const f = useFormat();
|
|
22
|
+
const t = useLabels("gauge", gaugeLabels, labels);
|
|
23
|
+
const fmt = (v) => (format === "percent" ? f.percent(v / max) : formatValue(f, format, v));
|
|
24
|
+
const display = value === null ? "—" : fmt(value);
|
|
25
|
+
const maxText = format === "percent" ? f.percent(1) : formatValue(f, format, max);
|
|
26
|
+
const valueText = value === null ? t("noValue") : threshold?.label ? t("valueTextWithLabel", { value: fmt(value), max: maxText, label: threshold.label }) : t("valueText", { value: fmt(value), max: maxText });
|
|
27
|
+
return { display, valueText, t, fmt };
|
|
28
|
+
}
|
|
29
|
+
function a11yProps(semantic, value, max, valueText, label) {
|
|
30
|
+
return {
|
|
31
|
+
role: semantic === "meter" ? "meter" : "progressbar",
|
|
32
|
+
"aria-label": label,
|
|
33
|
+
"aria-valuemin": 0,
|
|
34
|
+
"aria-valuemax": max,
|
|
35
|
+
"aria-valuenow": value === null ? undefined : Math.min(value, max),
|
|
36
|
+
"aria-valuetext": valueText,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A full ring for progress to a target — profile completeness, quota, upload. Plain SVG; `xs` fits
|
|
41
|
+
* in a table cell.
|
|
42
|
+
*
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <ProgressRing value={85} aria-label="Profile completeness" format="percent" size="md" />
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const ProgressRing = React.forwardRef(function ProgressRing({ value, max = 100, size = "md", thickness, color = "chart-1", thresholds, label, format, semantic = "progress", labels, className, style, "aria-label": ariaLabel, ...props }, ref) {
|
|
48
|
+
const px = typeof size === "number" ? size : SIZES[size];
|
|
49
|
+
const sw = thickness ?? Math.max(2.5, Math.round(px * 0.09 * 10) / 10);
|
|
50
|
+
const threshold = pickThreshold(value, thresholds);
|
|
51
|
+
const { display, valueText } = useGaugeText(value, max, format, threshold, labels);
|
|
52
|
+
const ratio = value === null ? 0 : Math.max(0, Math.min(1, value / max));
|
|
53
|
+
const stroke = resolveChartColor(color === "auto" ? (threshold?.color ?? "chart-1") : color);
|
|
54
|
+
const r = (px - sw) / 2;
|
|
55
|
+
const c = 2 * Math.PI * r;
|
|
56
|
+
const showLabel = px >= 64 && label !== null;
|
|
57
|
+
return (_jsxs("div", { ref: ref, "data-slot": "progress-ring", ...a11yProps(semantic, value, max, valueText, ariaLabel), className: cn("relative inline-grid shrink-0 place-items-center align-middle", className), style: { width: px, height: px, ...style }, ...props, children: [_jsxs("svg", { width: px, height: px, viewBox: `0 0 ${px} ${px}`, "aria-hidden": true, "data-ring": "", className: "vui-gauge-arc -rotate-90", children: [_jsx("circle", { cx: px / 2, cy: px / 2, r: r, fill: "none", stroke: "var(--track)", strokeWidth: sw }), ratio > 0 ? (_jsx("circle", { cx: px / 2, cy: px / 2, r: r, fill: "none", stroke: stroke, strokeWidth: sw, strokeLinecap: ratio >= 1 ? "butt" : "round", strokeDasharray: `${c * ratio} ${c}`, className: "vui-gauge-value" })) : null] }), showLabel ? (_jsx("div", { "aria-hidden": true, className: "absolute inset-0 flex flex-col items-center justify-center text-center", children: label ?? (_jsxs(_Fragment, { children: [_jsx("span", { className: cn("font-mono leading-none font-medium tracking-[-0.02em] text-fg tabular", px >= 140 ? "text-[30px]" : "text-[17px]"), children: display }), threshold?.label && px >= 120 ? _jsx("span", { className: "mt-1.5 text-[12px] text-fg-muted", children: threshold.label }) : null] })) })) : null] }));
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* A score or attainment on a 180° / 270° arc with optional threshold bands and a target marker —
|
|
61
|
+
* SEO score, quota, NPS. `semantic="meter"` for scores.
|
|
62
|
+
*
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <Gauge value={64} aria-label="SEO score" semantic="meter" thresholds={[{ at: 0, color: "danger", label: "Poor" }, { at: 50, color: "warning", label: "Fair" }, { at: 80, color: "success", label: "Good" }]} color="auto" />
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export const Gauge = React.forwardRef(function Gauge({ value, max = 100, size = "lg", thickness, color = "chart-1", thresholds, label, format, semantic = "meter", arc = 270, showThresholdBands, target, labels, className, style, "aria-label": ariaLabel, ...props }, ref) {
|
|
68
|
+
const px = typeof size === "number" ? size : SIZES[size];
|
|
69
|
+
const sw = thickness ?? Math.max(3, Math.round(px * 0.075 * 10) / 10);
|
|
70
|
+
const threshold = pickThreshold(value, thresholds);
|
|
71
|
+
const { display, valueText, t, fmt } = useGaugeText(value, max, format, threshold, labels);
|
|
72
|
+
const ratio = value === null ? 0 : Math.max(0, Math.min(1, value / max));
|
|
73
|
+
const over = value !== null && value > max;
|
|
74
|
+
const stroke = resolveChartColor(color === "auto" ? (threshold?.color ?? "chart-1") : color);
|
|
75
|
+
const band = showThresholdBands && thresholds?.length ? sw * 0.35 : 0;
|
|
76
|
+
const gap = band ? 3 : 0;
|
|
77
|
+
const cx = px / 2;
|
|
78
|
+
const r = (px - sw) / 2 - band - gap;
|
|
79
|
+
const rb = (px - band) / 2;
|
|
80
|
+
const sweep = arc;
|
|
81
|
+
const start = arc === 180 ? 180 : 135; // degrees, clockwise from +x
|
|
82
|
+
const height = arc === 180 ? Math.ceil(px / 2 + sw / 2 + 2) : Math.ceil(px / 2 + Math.sin(Math.PI / 4) * (px / 2) + 2);
|
|
83
|
+
const len = (rad) => (2 * Math.PI * rad * sweep) / 360;
|
|
84
|
+
const C = (rad) => 2 * Math.PI * rad;
|
|
85
|
+
const point = (deg, rad) => [cx + rad * Math.cos((deg * Math.PI) / 180), cx + rad * Math.sin((deg * Math.PI) / 180)];
|
|
86
|
+
const sorted = thresholds ? [...thresholds].sort((a, b) => a.at - b.at) : [];
|
|
87
|
+
const targetDeg = target !== undefined ? start + (Math.max(0, Math.min(1, target / max)) * sweep) : undefined;
|
|
88
|
+
return (_jsxs("div", { ref: ref, "data-slot": "gauge", "data-arc": arc, ...a11yProps(semantic, value, max, valueText + (target !== undefined ? `, ${t("target", { value: fmt(target) })}` : ""), ariaLabel), className: cn("relative inline-block shrink-0 align-middle", className), style: { width: px, height, ...style }, ...props, children: [_jsxs("svg", { width: px, height: height, viewBox: `0 0 ${px} ${height}`, "aria-hidden": true, className: "vui-gauge-arc overflow-visible", children: [_jsxs("g", { transform: `rotate(${start} ${cx} ${cx})`, children: [_jsx("circle", { cx: cx, cy: cx, r: r, fill: "none", stroke: "var(--track)", strokeWidth: sw, strokeLinecap: "round", strokeDasharray: `${len(r)} ${C(r)}` }), ratio > 0 ? (_jsx("circle", { cx: cx, cy: cx, r: r, fill: "none", stroke: stroke, strokeWidth: sw, strokeLinecap: "round", strokeDasharray: `${len(r) * ratio} ${C(r)}`, className: "vui-gauge-value" })) : null, band
|
|
89
|
+
? sorted.map((th, i) => {
|
|
90
|
+
const from = Math.max(0, th.at / max);
|
|
91
|
+
const to = Math.min(1, (sorted[i + 1]?.at ?? max) / max);
|
|
92
|
+
if (to <= from)
|
|
93
|
+
return null;
|
|
94
|
+
return (_jsx("circle", { cx: cx, cy: cx, r: rb, fill: "none", stroke: `color-mix(in oklch, ${resolveChartColor(th.color)} 55%, transparent)`, strokeWidth: band, strokeDasharray: `${Math.max(0, len(rb) * (to - from) - 1.5)} ${C(rb)}`, strokeDashoffset: -len(rb) * from }, i));
|
|
95
|
+
})
|
|
96
|
+
: null] }), targetDeg !== undefined ? ((() => {
|
|
97
|
+
const [x1, y1] = point(targetDeg, r - sw / 2 - 3);
|
|
98
|
+
const [x2, y2] = point(targetDeg, r + sw / 2 + 3);
|
|
99
|
+
return _jsx("line", { x1: x1, y1: y1, x2: x2, y2: y2, stroke: "var(--fg)", strokeWidth: 2, strokeLinecap: "round" });
|
|
100
|
+
})()) : null, over ? ((() => {
|
|
101
|
+
const [x, y] = point(start + sweep, r);
|
|
102
|
+
return _jsx("circle", { cx: x, cy: y, r: sw / 2 + 1.5, fill: "none", stroke: "var(--fg)", strokeWidth: 1.5 });
|
|
103
|
+
})()) : null] }), label !== null && px >= 64 ? (_jsx("div", { "aria-hidden": true, className: cn("absolute inset-x-0 flex flex-col items-center text-center", arc === 180 ? "bottom-0" : "top-0 bottom-[12%] justify-center"), children: label ?? (_jsxs(_Fragment, { children: [_jsx("span", { className: cn("font-mono leading-none font-medium tracking-[-0.03em] text-fg tabular", px >= 140 ? "text-[32px]" : "text-[18px]"), children: display }), threshold?.label || target !== undefined ? (_jsx("span", { className: "mt-1.5 text-[12px] text-fg-muted", children: threshold?.label ?? t("target", { value: fmt(target) }) })) : null] })) })) : null] }));
|
|
104
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ChartLabels } from "./chart-shell.js";
|
|
3
|
+
import { type ChartColor, type ChartState, type FormatSpec } from "./utils.js";
|
|
4
|
+
export declare const heatmapLabels: {
|
|
5
|
+
less: string;
|
|
6
|
+
more: string;
|
|
7
|
+
cell: string;
|
|
8
|
+
noData: string;
|
|
9
|
+
date: string;
|
|
10
|
+
value: string;
|
|
11
|
+
calendarSummary: string;
|
|
12
|
+
matrixSummary: string;
|
|
13
|
+
};
|
|
14
|
+
export type HeatmapLabels = typeof heatmapLabels;
|
|
15
|
+
export interface HeatmapCell {
|
|
16
|
+
/** Calendar: `"YYYY-MM-DD"` (or a Date). Matrix: the column label. */
|
|
17
|
+
x: string | Date;
|
|
18
|
+
/** Matrix: the row label. */
|
|
19
|
+
y?: string;
|
|
20
|
+
value: number | null;
|
|
21
|
+
/** Categorical scale: the category value of this cell. */
|
|
22
|
+
category?: string;
|
|
23
|
+
meta?: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface HeatmapCategory {
|
|
26
|
+
value: string;
|
|
27
|
+
label: string;
|
|
28
|
+
color: ChartColor;
|
|
29
|
+
}
|
|
30
|
+
export interface HeatmapProps extends Omit<React.HTMLAttributes<HTMLElement>, "title" | "onClick"> {
|
|
31
|
+
/** `calendar`: weeks × weekdays (activity, attendance). `matrix`: rows × columns (weekday × hour). */
|
|
32
|
+
mode: "calendar" | "matrix";
|
|
33
|
+
data: HeatmapCell[];
|
|
34
|
+
/** Calendar range. Default: first to last date in `data`. */
|
|
35
|
+
range?: {
|
|
36
|
+
from: string | Date;
|
|
37
|
+
to: string | Date;
|
|
38
|
+
};
|
|
39
|
+
/** Matrix column order. Default: order of appearance. */
|
|
40
|
+
xLabels?: string[];
|
|
41
|
+
/** Matrix row order. Default: order of appearance. */
|
|
42
|
+
yLabels?: string[];
|
|
43
|
+
scale?: "sequential" | "diverging" | "categorical";
|
|
44
|
+
categories?: HeatmapCategory[];
|
|
45
|
+
/** Colour steps. Default 5. */
|
|
46
|
+
steps?: 4 | 5 | 7;
|
|
47
|
+
/** Linear breaks between these values. Default: quantile breaks (equal-count buckets). */
|
|
48
|
+
domain?: [number, number];
|
|
49
|
+
/** Base colour (sequential). Default `chart-1` — follows the accent. */
|
|
50
|
+
color?: ChartColor;
|
|
51
|
+
format?: FormatSpec;
|
|
52
|
+
/** Name of the measured thing, for table header and cell labels ("Posts"). */
|
|
53
|
+
valueLabel?: string;
|
|
54
|
+
tooltip?: (cell: HeatmapCell) => React.ReactNode;
|
|
55
|
+
onCellClick?: (cell: HeatmapCell) => void;
|
|
56
|
+
/** `auto` fills the width; a number fixes the cell size in px (scrolls when wider). */
|
|
57
|
+
cellSize?: "auto" | number;
|
|
58
|
+
/** Accessible name of the grid and the table caption. */
|
|
59
|
+
title: string;
|
|
60
|
+
/** Override the week start (0 = Sunday … 6 = Saturday). Default: from the locale. */
|
|
61
|
+
weekStart?: number;
|
|
62
|
+
/** Ring this day (`YYYY-MM-DD`). Default: today in the provider's time zone (set after mount). */
|
|
63
|
+
today?: string | null;
|
|
64
|
+
showLegend?: boolean;
|
|
65
|
+
tableToggle?: boolean;
|
|
66
|
+
state?: ChartState;
|
|
67
|
+
summary?: string;
|
|
68
|
+
labels?: Partial<HeatmapLabels & ChartLabels>;
|
|
69
|
+
}
|
|
70
|
+
/** First day of the week for a locale: 0 = Sunday … 6 = Saturday. */
|
|
71
|
+
export declare function weekStartOf(locale: string): number;
|
|
72
|
+
/**
|
|
73
|
+
* Density patterns as a grid of tinted cells: a **calendar** (weeks × weekdays, like a contribution
|
|
74
|
+
* graph) or a **matrix** (weekday × hour, channel × week). Plain DOM — no chart library. An ARIA grid
|
|
75
|
+
* with arrow keys, Home / End and PageUp / PageDown, plus a data-table alternative.
|
|
76
|
+
*
|
|
77
|
+
* ```tsx
|
|
78
|
+
* <Heatmap mode="calendar" title="Posts published" data={days} valueLabel="Posts" />
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function Heatmap({ mode, data, range, xLabels: xLabelsProp, yLabels: yLabelsProp, scale, categories, steps, domain, color, format, valueLabel, tooltip, onCellClick, cellSize, title, weekStart: weekStartProp, today: todayProp, showLegend, tableToggle, state, summary, labels, className, ...props }: HeatmapProps): React.JSX.Element;
|