@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,135 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ImageAspect } from "../components/image.js";
|
|
3
|
+
import type { MediaAsset } from "./types.js";
|
|
4
|
+
declare const videoLabels: {
|
|
5
|
+
player: string;
|
|
6
|
+
play: string;
|
|
7
|
+
pause: string;
|
|
8
|
+
replay: string;
|
|
9
|
+
playVideo: string;
|
|
10
|
+
seek: string;
|
|
11
|
+
time: string;
|
|
12
|
+
mute: string;
|
|
13
|
+
unmute: string;
|
|
14
|
+
volume: string;
|
|
15
|
+
captionsOn: string;
|
|
16
|
+
captionsOff: string;
|
|
17
|
+
speed: string;
|
|
18
|
+
speedValue: string;
|
|
19
|
+
normal: string;
|
|
20
|
+
pip: string;
|
|
21
|
+
fullscreen: string;
|
|
22
|
+
exitFullscreen: string;
|
|
23
|
+
error: string;
|
|
24
|
+
hlsUnsupported: string;
|
|
25
|
+
pauseBackground: string;
|
|
26
|
+
playBackground: string;
|
|
27
|
+
};
|
|
28
|
+
export type VideoPlayerLabels = typeof videoLabels;
|
|
29
|
+
export type VideoSource = string | MediaAsset | {
|
|
30
|
+
url: string;
|
|
31
|
+
type: "mp4" | "webm" | "hls";
|
|
32
|
+
}[];
|
|
33
|
+
export interface VideoTrack {
|
|
34
|
+
src: string;
|
|
35
|
+
/** BCP 47, e.g. "en", "tr". */
|
|
36
|
+
lang: string;
|
|
37
|
+
label: string;
|
|
38
|
+
kind?: "subtitles" | "captions";
|
|
39
|
+
default?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Minimal shape of the `hls.js` default export (optional peer, loaded on demand). */
|
|
42
|
+
export interface HlsConstructor {
|
|
43
|
+
new (config?: Record<string, unknown>): {
|
|
44
|
+
loadSource(url: string): void;
|
|
45
|
+
attachMedia(el: HTMLMediaElement): void;
|
|
46
|
+
destroy(): void;
|
|
47
|
+
on?(event: string, cb: (...args: unknown[]) => void): void;
|
|
48
|
+
};
|
|
49
|
+
isSupported(): boolean;
|
|
50
|
+
}
|
|
51
|
+
/** `1:02:05` / `3:07`. */
|
|
52
|
+
export declare function formatMediaTime(seconds: number, locale?: string): string;
|
|
53
|
+
export declare const videoPlayerVariants: (props?: ({
|
|
54
|
+
rounded?: "ui" | "ui-lg" | "none" | null | undefined;
|
|
55
|
+
chrome?: "overlay" | "bar" | null | undefined;
|
|
56
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
57
|
+
export interface VideoPlayerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onTimeUpdate" | "onEnded"> {
|
|
58
|
+
src: VideoSource;
|
|
59
|
+
poster?: string | MediaAsset;
|
|
60
|
+
/** Box ratio. Default: the asset's ratio, else 16/9. */
|
|
61
|
+
aspect?: ImageAspect;
|
|
62
|
+
tracks?: VideoTrack[];
|
|
63
|
+
autoPlay?: boolean;
|
|
64
|
+
muted?: boolean;
|
|
65
|
+
loop?: boolean;
|
|
66
|
+
playsInline?: boolean;
|
|
67
|
+
/** `custom` (default) kit controls · `native` browser controls · `none`. */
|
|
68
|
+
controls?: "custom" | "native" | "none";
|
|
69
|
+
/** `overlay` floats over the picture and hides while playing; `bar` stays visible. */
|
|
70
|
+
chrome?: "overlay" | "bar";
|
|
71
|
+
rounded?: "none" | "ui" | "ui-lg";
|
|
72
|
+
/** Accessible name, e.g. the video title. */
|
|
73
|
+
title?: string;
|
|
74
|
+
preload?: "none" | "metadata" | "auto";
|
|
75
|
+
/** Lazy loader for HLS streams in browsers without native HLS: `hls={() => import("hls.js")}`. */
|
|
76
|
+
hls?: () => Promise<{
|
|
77
|
+
default: HlsConstructor;
|
|
78
|
+
}>;
|
|
79
|
+
onEnded?: () => void;
|
|
80
|
+
onTimeUpdate?: (time: number) => void;
|
|
81
|
+
/** The `<video>` element. */
|
|
82
|
+
videoRef?: React.Ref<HTMLVideoElement>;
|
|
83
|
+
/** CORS mode, needed when caption tracks come from another origin. */
|
|
84
|
+
crossOrigin?: "anonymous" | "use-credentials";
|
|
85
|
+
labels?: Partial<VideoPlayerLabels>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Consistent controls for self-hosted video: play, seek, time, volume, captions, speed,
|
|
89
|
+
* picture-in-picture and full screen. Keyboard: Space/K play, ←/→ 5 s, ↑/↓ volume, F full screen,
|
|
90
|
+
* M mute, C captions. HLS loads `hls.js` only when needed. The chrome is always dark, because
|
|
91
|
+
* video content is.
|
|
92
|
+
*
|
|
93
|
+
* ```tsx
|
|
94
|
+
* <VideoPlayer src="/media/onboarding.mp4" poster="/media/onboarding.jpg" title="Onboarding: your first week"
|
|
95
|
+
* tracks={[{ src: "/media/onboarding.en.vtt", lang: "en", label: "English", default: true }]} />
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare const VideoPlayer: React.ForwardRefExoticComponent<VideoPlayerProps & React.RefAttributes<HTMLDivElement>>;
|
|
99
|
+
export interface VideoEmbedProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
100
|
+
provider: "youtube" | "vimeo";
|
|
101
|
+
/** Video id (`dQw4w9WgXcQ`, `76979871`). */
|
|
102
|
+
id: string;
|
|
103
|
+
/** Required: names the play button and the iframe. */
|
|
104
|
+
title: string;
|
|
105
|
+
/** Facade image. YouTube default: the video's own thumbnail. Vimeo needs one. */
|
|
106
|
+
poster?: string;
|
|
107
|
+
aspect?: ImageAspect;
|
|
108
|
+
/** Start at second. */
|
|
109
|
+
start?: number;
|
|
110
|
+
rounded?: "none" | "ui" | "ui-lg";
|
|
111
|
+
labels?: Partial<VideoPlayerLabels>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A privacy-friendly embed: a poster and a play button until clicked, then a
|
|
115
|
+
* `youtube-nocookie.com` (or `player.vimeo.com` with `dnt=1`) iframe. No third-party request,
|
|
116
|
+
* cookie or script before the visitor chooses to play.
|
|
117
|
+
*/
|
|
118
|
+
export declare const VideoEmbed: React.ForwardRefExoticComponent<VideoEmbedProps & React.RefAttributes<HTMLDivElement>>;
|
|
119
|
+
export interface BackgroundVideoProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
120
|
+
src: string | {
|
|
121
|
+
url: string;
|
|
122
|
+
type: "mp4" | "webm";
|
|
123
|
+
}[];
|
|
124
|
+
/** Shown before playback and, under reduced motion, instead of the video. */
|
|
125
|
+
poster: string;
|
|
126
|
+
/** Content on top (hero copy). */
|
|
127
|
+
children?: React.ReactNode;
|
|
128
|
+
labels?: Partial<VideoPlayerLabels>;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Muted, looping, decorative video (hero backgrounds). `aria-hidden`, with a visible pause
|
|
132
|
+
* button (WCAG 2.2.2). Reduced motion shows the poster only.
|
|
133
|
+
*/
|
|
134
|
+
export declare const BackgroundVideo: React.ForwardRefExoticComponent<BackgroundVideoProps & React.RefAttributes<HTMLDivElement>>;
|
|
135
|
+
export {};
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { Captions, CaptionsOff, Maximize, Minimize, Pause, PictureInPicture2, Play, RotateCcw, Volume1, Volume2, VolumeX, TriangleAlert } from "lucide-react";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
7
|
+
import { useLabels } from "../lib/labels.js";
|
|
8
|
+
import { useLocale } from "../lib/locale.js";
|
|
9
|
+
import { useReducedMotion } from "../lib/use-reduced-motion.js";
|
|
10
|
+
import { aspectRatioOf } from "../components/image.js";
|
|
11
|
+
import { Slider } from "../components/slider.js";
|
|
12
|
+
import { Spinner } from "../components/spinner.js";
|
|
13
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "../components/dropdown-menu.js";
|
|
14
|
+
import { PortalContainer } from "../lib/theme-scope.js";
|
|
15
|
+
import { isMediaAsset } from "./media-provider.js";
|
|
16
|
+
const videoLabels = {
|
|
17
|
+
player: "Video player",
|
|
18
|
+
play: "Play",
|
|
19
|
+
pause: "Pause",
|
|
20
|
+
replay: "Replay",
|
|
21
|
+
playVideo: "Play video: {title}",
|
|
22
|
+
seek: "Seek",
|
|
23
|
+
time: "{current} of {duration}",
|
|
24
|
+
mute: "Mute",
|
|
25
|
+
unmute: "Unmute",
|
|
26
|
+
volume: "Volume",
|
|
27
|
+
captionsOn: "Turn on captions",
|
|
28
|
+
captionsOff: "Turn off captions",
|
|
29
|
+
speed: "Playback speed",
|
|
30
|
+
speedValue: "{rate}×",
|
|
31
|
+
normal: "Normal",
|
|
32
|
+
pip: "Picture in picture",
|
|
33
|
+
fullscreen: "Full screen",
|
|
34
|
+
exitFullscreen: "Exit full screen",
|
|
35
|
+
error: "This video can't be played.",
|
|
36
|
+
hlsUnsupported: "This stream needs HLS support. Pass the `hls` loader.",
|
|
37
|
+
pauseBackground: "Pause background video",
|
|
38
|
+
playBackground: "Play background video",
|
|
39
|
+
};
|
|
40
|
+
/** `1:02:05` / `3:07`. */
|
|
41
|
+
export function formatMediaTime(seconds, locale = "en-US") {
|
|
42
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
43
|
+
seconds = 0;
|
|
44
|
+
const s = Math.floor(seconds % 60);
|
|
45
|
+
const m = Math.floor((seconds / 60) % 60);
|
|
46
|
+
const h = Math.floor(seconds / 3600);
|
|
47
|
+
const two = new Intl.NumberFormat(locale, { minimumIntegerDigits: 2, useGrouping: false });
|
|
48
|
+
const one = new Intl.NumberFormat(locale, { useGrouping: false });
|
|
49
|
+
return h > 0 ? `${one.format(h)}:${two.format(m)}:${two.format(s)}` : `${one.format(m)}:${two.format(s)}`;
|
|
50
|
+
}
|
|
51
|
+
const SPEEDS = [0.5, 0.75, 1, 1.25, 1.5, 2];
|
|
52
|
+
export const videoPlayerVariants = cva("vui-video group/video relative isolate overflow-hidden bg-scene", {
|
|
53
|
+
variants: {
|
|
54
|
+
rounded: { none: "", ui: "rounded-ui", "ui-lg": "rounded-ui-lg" },
|
|
55
|
+
chrome: { overlay: "", bar: "" },
|
|
56
|
+
},
|
|
57
|
+
defaultVariants: { rounded: "ui", chrome: "overlay" },
|
|
58
|
+
});
|
|
59
|
+
function sourcesOf(src) {
|
|
60
|
+
if (Array.isArray(src))
|
|
61
|
+
return src;
|
|
62
|
+
const url = isMediaAsset(src) ? src.url : src;
|
|
63
|
+
const type = /\.m3u8(\?|$)/i.test(url) || (isMediaAsset(src) && /mpegurl/i.test(src.mime)) ? "hls" : /\.webm(\?|$)/i.test(url) ? "webm" : "mp4";
|
|
64
|
+
return [{ url, type }];
|
|
65
|
+
}
|
|
66
|
+
const MIME = { mp4: "video/mp4", webm: "video/webm", hls: "application/vnd.apple.mpegurl" };
|
|
67
|
+
/**
|
|
68
|
+
* Consistent controls for self-hosted video: play, seek, time, volume, captions, speed,
|
|
69
|
+
* picture-in-picture and full screen. Keyboard: Space/K play, ←/→ 5 s, ↑/↓ volume, F full screen,
|
|
70
|
+
* M mute, C captions. HLS loads `hls.js` only when needed. The chrome is always dark, because
|
|
71
|
+
* video content is.
|
|
72
|
+
*
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <VideoPlayer src="/media/onboarding.mp4" poster="/media/onboarding.jpg" title="Onboarding: your first week"
|
|
75
|
+
* tracks={[{ src: "/media/onboarding.en.vtt", lang: "en", label: "English", default: true }]} />
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export const VideoPlayer = React.forwardRef(function VideoPlayer({ src, poster: posterProp, aspect, tracks, autoPlay, muted: mutedProp = false, loop, playsInline = true, controls = "custom", chrome = "overlay", rounded, title, preload = "metadata", hls, onEnded, onTimeUpdate, videoRef, crossOrigin, labels, className, style, onKeyDown, ...props }, ref) {
|
|
79
|
+
const t = useLabels("videoPlayer", videoLabels, labels);
|
|
80
|
+
const { locale } = useLocale();
|
|
81
|
+
const reduced = useReducedMotion();
|
|
82
|
+
const video = React.useRef(null);
|
|
83
|
+
const root = React.useRef(null);
|
|
84
|
+
const asset = isMediaAsset(src) ? src : undefined;
|
|
85
|
+
const poster = isMediaAsset(posterProp) ? posterProp.url : posterProp ?? asset?.variants?.poster?.url;
|
|
86
|
+
const ratio = aspectRatioOf(aspect ?? "auto", asset?.width, asset?.height) ?? 16 / 9;
|
|
87
|
+
const sources = React.useMemo(() => sourcesOf(src), [src]);
|
|
88
|
+
const isHls = sources.some((s) => s.type === "hls");
|
|
89
|
+
const [playing, setPlaying] = React.useState(false);
|
|
90
|
+
const [started, setStarted] = React.useState(false);
|
|
91
|
+
const [ended, setEnded] = React.useState(false);
|
|
92
|
+
const [buffering, setBuffering] = React.useState(false);
|
|
93
|
+
const [error, setError] = React.useState(null);
|
|
94
|
+
const [time, setTime] = React.useState(0);
|
|
95
|
+
const [duration, setDuration] = React.useState(asset?.duration ?? 0);
|
|
96
|
+
const [volume, setVolume] = React.useState(1);
|
|
97
|
+
const [muted, setMuted] = React.useState(mutedProp);
|
|
98
|
+
const [rate, setRate] = React.useState(1);
|
|
99
|
+
const [captions, setCaptions] = React.useState(Boolean(tracks?.some((tr) => tr.default)));
|
|
100
|
+
const [fullscreen, setFullscreen] = React.useState(false);
|
|
101
|
+
const [idle, setIdle] = React.useState(false);
|
|
102
|
+
const idleTimer = React.useRef(undefined);
|
|
103
|
+
React.useImperativeHandle(videoRef, () => video.current, []);
|
|
104
|
+
React.useImperativeHandle(ref, () => root.current, []);
|
|
105
|
+
const [rootEl, setRootEl] = React.useState(null);
|
|
106
|
+
const rootRef = React.useCallback((node) => {
|
|
107
|
+
root.current = node;
|
|
108
|
+
setRootEl(node);
|
|
109
|
+
}, []);
|
|
110
|
+
// HLS: native (Safari) or the lazy hls.js loader.
|
|
111
|
+
React.useEffect(() => {
|
|
112
|
+
const el = video.current;
|
|
113
|
+
if (!el || !isHls)
|
|
114
|
+
return;
|
|
115
|
+
const hlsUrl = sources.find((s) => s.type === "hls").url;
|
|
116
|
+
if (el.canPlayType(MIME.hls)) {
|
|
117
|
+
el.src = hlsUrl;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!hls) {
|
|
121
|
+
setError(t("hlsUnsupported"));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
let instance;
|
|
125
|
+
let cancelled = false;
|
|
126
|
+
hls().then(({ default: Hls }) => {
|
|
127
|
+
if (cancelled || !video.current)
|
|
128
|
+
return;
|
|
129
|
+
if (!Hls.isSupported())
|
|
130
|
+
return setError(t("error"));
|
|
131
|
+
const h = new Hls();
|
|
132
|
+
h.loadSource(hlsUrl);
|
|
133
|
+
h.attachMedia(video.current);
|
|
134
|
+
instance = h;
|
|
135
|
+
}, () => setError(t("error")));
|
|
136
|
+
return () => {
|
|
137
|
+
cancelled = true;
|
|
138
|
+
instance?.destroy();
|
|
139
|
+
};
|
|
140
|
+
}, [isHls, sources, hls, t]);
|
|
141
|
+
React.useEffect(() => {
|
|
142
|
+
const el = video.current;
|
|
143
|
+
if (!el || !tracks?.length)
|
|
144
|
+
return;
|
|
145
|
+
for (let i = 0; i < el.textTracks.length; i++) {
|
|
146
|
+
const tr = el.textTracks[i];
|
|
147
|
+
const def = tracks.findIndex((x) => x.default);
|
|
148
|
+
tr.mode = captions && i === (def === -1 ? 0 : def) ? "showing" : "hidden";
|
|
149
|
+
}
|
|
150
|
+
}, [captions, tracks]);
|
|
151
|
+
// Metadata can arrive before hydration attaches the listeners: read it once on mount.
|
|
152
|
+
React.useEffect(() => {
|
|
153
|
+
const el = video.current;
|
|
154
|
+
if (!el)
|
|
155
|
+
return;
|
|
156
|
+
if (el.readyState >= 1 && Number.isFinite(el.duration))
|
|
157
|
+
setDuration(el.duration);
|
|
158
|
+
setMuted(el.muted);
|
|
159
|
+
if (!el.paused) {
|
|
160
|
+
setPlaying(true);
|
|
161
|
+
setStarted(true);
|
|
162
|
+
}
|
|
163
|
+
}, []);
|
|
164
|
+
React.useEffect(() => {
|
|
165
|
+
const onFs = () => setFullscreen(document.fullscreenElement === root.current);
|
|
166
|
+
document.addEventListener("fullscreenchange", onFs);
|
|
167
|
+
return () => document.removeEventListener("fullscreenchange", onFs);
|
|
168
|
+
}, []);
|
|
169
|
+
const poke = React.useCallback(() => {
|
|
170
|
+
setIdle(false);
|
|
171
|
+
clearTimeout(idleTimer.current);
|
|
172
|
+
idleTimer.current = setTimeout(() => setIdle(true), 2600);
|
|
173
|
+
}, []);
|
|
174
|
+
React.useEffect(() => () => clearTimeout(idleTimer.current), []);
|
|
175
|
+
const togglePlay = React.useCallback(() => {
|
|
176
|
+
const el = video.current;
|
|
177
|
+
if (!el)
|
|
178
|
+
return;
|
|
179
|
+
if (el.paused || el.ended)
|
|
180
|
+
void el.play()?.catch?.(() => { });
|
|
181
|
+
else
|
|
182
|
+
el.pause();
|
|
183
|
+
}, []);
|
|
184
|
+
const seekBy = (d) => {
|
|
185
|
+
const el = video.current;
|
|
186
|
+
if (el)
|
|
187
|
+
el.currentTime = Math.min(Math.max(0, el.currentTime + d), el.duration || Infinity);
|
|
188
|
+
};
|
|
189
|
+
const setVol = (v) => {
|
|
190
|
+
const el = video.current;
|
|
191
|
+
if (!el)
|
|
192
|
+
return;
|
|
193
|
+
el.volume = Math.min(1, Math.max(0, v));
|
|
194
|
+
el.muted = el.volume === 0;
|
|
195
|
+
};
|
|
196
|
+
const toggleMute = () => {
|
|
197
|
+
const el = video.current;
|
|
198
|
+
if (el)
|
|
199
|
+
el.muted = !el.muted;
|
|
200
|
+
};
|
|
201
|
+
const toggleFullscreen = () => {
|
|
202
|
+
const el = root.current;
|
|
203
|
+
if (!el)
|
|
204
|
+
return;
|
|
205
|
+
if (document.fullscreenElement)
|
|
206
|
+
void document.exitFullscreen?.();
|
|
207
|
+
else if (el.requestFullscreen)
|
|
208
|
+
void el.requestFullscreen();
|
|
209
|
+
else
|
|
210
|
+
video.current?.webkitEnterFullscreen?.();
|
|
211
|
+
};
|
|
212
|
+
// Feature detection after mount, so server and client render the same controls.
|
|
213
|
+
const [pipSupported, setPipSupported] = React.useState(false);
|
|
214
|
+
React.useEffect(() => setPipSupported(Boolean(document.pictureInPictureEnabled)), []);
|
|
215
|
+
const togglePip = () => {
|
|
216
|
+
const el = video.current;
|
|
217
|
+
if (!el)
|
|
218
|
+
return;
|
|
219
|
+
const d = document;
|
|
220
|
+
if (d.pictureInPictureElement)
|
|
221
|
+
void d.exitPictureInPicture?.();
|
|
222
|
+
else
|
|
223
|
+
void el.requestPictureInPicture?.();
|
|
224
|
+
};
|
|
225
|
+
const handleKeyDown = (e) => {
|
|
226
|
+
onKeyDown?.(e);
|
|
227
|
+
if (e.defaultPrevented || controls !== "custom" || e.metaKey || e.ctrlKey || e.altKey)
|
|
228
|
+
return;
|
|
229
|
+
const target = e.target;
|
|
230
|
+
const onSlider = target.getAttribute("role") === "slider";
|
|
231
|
+
const onButton = target.tagName === "BUTTON";
|
|
232
|
+
const k = e.key.toLowerCase();
|
|
233
|
+
if ((k === " " && !onButton) || k === "k")
|
|
234
|
+
togglePlay();
|
|
235
|
+
else if (k === "arrowleft" && !onSlider)
|
|
236
|
+
seekBy(-5);
|
|
237
|
+
else if (k === "arrowright" && !onSlider)
|
|
238
|
+
seekBy(5);
|
|
239
|
+
else if (k === "arrowup" && !onSlider)
|
|
240
|
+
setVol((video.current?.volume ?? 1) + 0.1);
|
|
241
|
+
else if (k === "arrowdown" && !onSlider)
|
|
242
|
+
setVol((video.current?.volume ?? 1) - 0.1);
|
|
243
|
+
else if (k === "f")
|
|
244
|
+
toggleFullscreen();
|
|
245
|
+
else if (k === "m")
|
|
246
|
+
toggleMute();
|
|
247
|
+
else if (k === "c" && tracks?.length)
|
|
248
|
+
setCaptions((c) => !c);
|
|
249
|
+
else
|
|
250
|
+
return;
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
poke();
|
|
253
|
+
};
|
|
254
|
+
const nf = React.useMemo(() => new Intl.NumberFormat(locale, { maximumFractionDigits: 2 }), [locale]);
|
|
255
|
+
const showChrome = controls === "custom" && (chrome === "bar" || !playing || !idle);
|
|
256
|
+
const VolumeIcon = muted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;
|
|
257
|
+
const btn = "vui-video-btn focus-ring inline-flex size-9 shrink-0 items-center justify-center rounded-ui-sm text-fg transition-colors hover:bg-hover [&_svg]:size-[18px]";
|
|
258
|
+
return (_jsxs("div", { ref: rootRef, role: "group", "aria-label": title ? `${t("player")}: ${title}` : t("player"), "data-slot": "video-player", "data-state": error ? "error" : ended ? "ended" : playing ? "playing" : started ? "paused" : "poster", "data-chrome": chrome, "data-idle": showChrome ? undefined : "", className: cn(videoPlayerVariants({ rounded, chrome }), "dark", className), style: { aspectRatio: fullscreen ? undefined : String(ratio), ...style }, onKeyDown: handleKeyDown, onPointerMove: poke, onFocusCapture: poke, ...props, children: [_jsxs("video", { ref: video, className: "absolute inset-0 size-full bg-transparent object-contain", poster: poster, autoPlay: autoPlay && !reduced, muted: muted, loop: loop, playsInline: playsInline, preload: preload, controls: controls === "native", crossOrigin: crossOrigin, onClick: controls === "custom" ? togglePlay : undefined, onPlay: () => {
|
|
259
|
+
setPlaying(true);
|
|
260
|
+
setStarted(true);
|
|
261
|
+
setEnded(false);
|
|
262
|
+
poke();
|
|
263
|
+
}, onPause: () => setPlaying(false), onEnded: () => {
|
|
264
|
+
setPlaying(false);
|
|
265
|
+
setEnded(true);
|
|
266
|
+
onEnded?.();
|
|
267
|
+
}, onWaiting: () => setBuffering(true), onPlaying: () => setBuffering(false), onCanPlay: () => setBuffering(false), onTimeUpdate: (e) => {
|
|
268
|
+
setTime(e.currentTarget.currentTime);
|
|
269
|
+
onTimeUpdate?.(e.currentTarget.currentTime);
|
|
270
|
+
}, onLoadedMetadata: (e) => setDuration(e.currentTarget.duration), onDurationChange: (e) => Number.isFinite(e.currentTarget.duration) && setDuration(e.currentTarget.duration), onVolumeChange: (e) => {
|
|
271
|
+
setVolume(e.currentTarget.volume);
|
|
272
|
+
setMuted(e.currentTarget.muted);
|
|
273
|
+
}, onRateChange: (e) => setRate(e.currentTarget.playbackRate), onError: () => setError(t("error")), "aria-label": title, children: [isHls ? null : sources.map((s) => _jsx("source", { src: s.url, type: MIME[s.type] }, s.url)), tracks?.map((tr) => _jsx("track", { src: tr.src, srcLang: tr.lang, label: tr.label, kind: tr.kind ?? "subtitles", default: tr.default }, tr.src))] }), error ? (_jsxs("div", { "data-slot": "video-error", role: "alert", className: "absolute inset-0 z-20 flex flex-col items-center justify-center gap-2 bg-scene/80 p-6 text-center text-sm text-fg-muted", children: [_jsx(TriangleAlert, { "aria-hidden": true, className: "size-6 text-warning" }), error] })) : null, controls === "custom" && !error && (!started || ended) ? (_jsx("button", { type: "button", "data-slot": "video-big-play", "aria-label": ended ? t("replay") : title ? t("playVideo", { title }) : t("play"), onClick: togglePlay, className: "vui-video-bigplay focus-ring absolute start-1/2 top-1/2 z-10 flex size-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full surface-popover text-fg rtl:translate-x-1/2 [&_svg]:size-6", children: ended ? _jsx(RotateCcw, { "aria-hidden": true }) : _jsx(Play, { "aria-hidden": true, className: "ms-0.5 fill-current" }) })) : null, buffering && playing ? (_jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center", children: _jsx(Spinner, { size: "lg", className: "text-fg" }) })) : null, controls === "custom" ? (_jsxs("div", { "data-slot": "video-controls", "data-visible": showChrome ? "" : undefined, className: cn("vui-video-controls absolute inset-x-0 bottom-0 z-20 flex flex-col gap-1 px-2 pt-8 pb-1.5", !started && chrome === "overlay" && "invisible"), children: [_jsx(Slider, { "aria-label": t("seek"), size: "sm", min: 0, max: duration || 1, step: 0.1, value: [Math.min(time, duration || 0)], onValueChange: ([v]) => {
|
|
274
|
+
if (video.current && v !== undefined)
|
|
275
|
+
video.current.currentTime = v;
|
|
276
|
+
}, formatValue: (v) => t("time", { current: formatMediaTime(v, locale), duration: formatMediaTime(duration, locale) }), showValue: "never", dir: "ltr", className: "vui-video-seek px-1.5" }), _jsxs("div", { className: "flex items-center gap-0.5", children: [_jsx("button", { type: "button", "data-slot": "video-play", className: btn, "aria-label": playing ? t("pause") : t("play"), onClick: togglePlay, children: playing ? _jsx(Pause, { "aria-hidden": true, className: "fill-current" }) : _jsx(Play, { "aria-hidden": true, className: "fill-current" }) }), _jsxs("div", { className: "group/vol flex items-center", children: [_jsx("button", { type: "button", "data-slot": "video-mute", className: btn, "aria-label": muted ? t("unmute") : t("mute"), onClick: toggleMute, children: _jsx(VolumeIcon, { "aria-hidden": true }) }), _jsx("div", { className: "w-0 overflow-hidden opacity-0 transition-[width,opacity] duration-200 group-focus-within/vol:w-20 group-focus-within/vol:opacity-100 group-hover/vol:w-20 group-hover/vol:opacity-100", children: _jsx(Slider, { "aria-label": t("volume"), size: "sm", min: 0, max: 1, step: 0.05, value: [muted ? 0 : volume], onValueChange: ([v]) => v !== undefined && setVol(v), formatOptions: { style: "percent" }, showValue: "never", className: "w-18 px-1.5" }) })] }), _jsxs("span", { "data-slot": "video-time", className: "tabular ms-1.5 text-[12.5px] text-fg-muted", children: [_jsx("span", { className: "text-fg", children: formatMediaTime(time, locale) }), _jsx("span", { "aria-hidden": true, className: "mx-1 text-fg-subtle", children: "/" }), formatMediaTime(duration, locale)] }), _jsxs("div", { className: "ms-auto flex items-center gap-0.5", children: [tracks?.length ? (_jsx("button", { type: "button", "data-slot": "video-captions", className: btn, "aria-pressed": captions, "aria-label": captions ? t("captionsOff") : t("captionsOn"), onClick: () => setCaptions((c) => !c), children: captions ? _jsx(Captions, { "aria-hidden": true }) : _jsx(CaptionsOff, { "aria-hidden": true }) })) : null, _jsx(PortalContainer, { container: rootEl, children: _jsxs(DropdownMenu, { modal: false, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-slot": "video-speed", className: cn(btn, "w-auto px-2 text-[12.5px] font-medium tabular"), "aria-label": `${t("speed")}: ${t("speedValue", { rate: nf.format(rate) })}`, children: t("speedValue", { rate: nf.format(rate) }) }) }), _jsxs(DropdownMenuContent, { align: "end", side: "top", children: [_jsx(DropdownMenuLabel, { children: t("speed") }), _jsx(DropdownMenuRadioGroup, { value: String(rate), onValueChange: (v) => {
|
|
277
|
+
if (video.current)
|
|
278
|
+
video.current.playbackRate = Number(v);
|
|
279
|
+
}, children: SPEEDS.map((s) => (_jsx(DropdownMenuRadioItem, { value: String(s), children: s === 1 ? t("normal") : t("speedValue", { rate: nf.format(s) }) }, s))) })] })] }) }), pipSupported ? (_jsx("button", { type: "button", "data-slot": "video-pip", className: btn, "aria-label": t("pip"), onClick: togglePip, children: _jsx(PictureInPicture2, { "aria-hidden": true }) })) : null, _jsx("button", { type: "button", "data-slot": "video-fullscreen", className: btn, "aria-label": fullscreen ? t("exitFullscreen") : t("fullscreen"), onClick: toggleFullscreen, children: fullscreen ? _jsx(Minimize, { "aria-hidden": true }) : _jsx(Maximize, { "aria-hidden": true }) })] })] })] })) : null] }));
|
|
280
|
+
});
|
|
281
|
+
/**
|
|
282
|
+
* A privacy-friendly embed: a poster and a play button until clicked, then a
|
|
283
|
+
* `youtube-nocookie.com` (or `player.vimeo.com` with `dnt=1`) iframe. No third-party request,
|
|
284
|
+
* cookie or script before the visitor chooses to play.
|
|
285
|
+
*/
|
|
286
|
+
export const VideoEmbed = React.forwardRef(function VideoEmbed({ provider, id, title, poster, aspect = "16/9", start, rounded = "ui", labels, className, style, ...props }, ref) {
|
|
287
|
+
const t = useLabels("videoPlayer", videoLabels, labels);
|
|
288
|
+
const [active, setActive] = React.useState(false);
|
|
289
|
+
const ratio = aspectRatioOf(aspect) ?? 16 / 9;
|
|
290
|
+
const image = poster ?? (provider === "youtube" ? `https://i.ytimg.com/vi/${encodeURIComponent(id)}/hqdefault.jpg` : undefined);
|
|
291
|
+
const url = provider === "youtube"
|
|
292
|
+
? `https://www.youtube-nocookie.com/embed/${encodeURIComponent(id)}?autoplay=1&rel=0${start ? `&start=${start}` : ""}`
|
|
293
|
+
: `https://player.vimeo.com/video/${encodeURIComponent(id)}?autoplay=1&dnt=1${start ? `#t=${start}s` : ""}`;
|
|
294
|
+
return (_jsx("div", { ref: ref, "data-slot": "video-embed", "data-provider": provider, "data-state": active ? "active" : "facade", className: cn(videoPlayerVariants({ rounded }), "dark", className), style: { aspectRatio: String(ratio), ...style }, ...props, children: active ? (_jsx("iframe", { src: url, title: title, className: "absolute inset-0 size-full border-0", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen", allowFullScreen: true, referrerPolicy: "strict-origin-when-cross-origin" })) : (_jsxs("button", { type: "button", onClick: () => setActive(true), "aria-label": t("playVideo", { title }), className: "vui-video-facade focus-ring group/facade absolute inset-0 size-full", children: [image ? _jsx("img", { src: image, alt: "", loading: "lazy", decoding: "async", className: "absolute inset-0 size-full object-cover transition-transform duration-500 group-hover/facade:scale-[1.02] motion-reduce:transition-none" }) : null, _jsx("span", { "aria-hidden": true, className: "vui-video-facade-shade absolute inset-0" }), _jsx("span", { "aria-hidden": true, className: "absolute start-4 end-4 top-4 line-clamp-2 text-start text-[15px] font-medium text-fg", children: title }), _jsx("span", { "aria-hidden": true, className: "absolute start-1/2 top-1/2 flex size-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full surface-popover text-fg transition-transform group-hover/facade:scale-105 rtl:translate-x-1/2 [&_svg]:size-6", children: _jsx(Play, { className: "ms-0.5 fill-current" }) })] })) }));
|
|
295
|
+
});
|
|
296
|
+
/**
|
|
297
|
+
* Muted, looping, decorative video (hero backgrounds). `aria-hidden`, with a visible pause
|
|
298
|
+
* button (WCAG 2.2.2). Reduced motion shows the poster only.
|
|
299
|
+
*/
|
|
300
|
+
export const BackgroundVideo = React.forwardRef(function BackgroundVideo({ src, poster, labels, className, children, ...props }, ref) {
|
|
301
|
+
const t = useLabels("videoPlayer", videoLabels, labels);
|
|
302
|
+
const reduced = useReducedMotion();
|
|
303
|
+
const video = React.useRef(null);
|
|
304
|
+
const [paused, setPaused] = React.useState(false);
|
|
305
|
+
const list = typeof src === "string" ? sourcesOf(src) : src;
|
|
306
|
+
return (_jsxs("div", { ref: ref, "data-slot": "background-video", className: cn("relative isolate overflow-hidden", className), ...props, children: [reduced ? (_jsx("img", { src: poster, alt: "", "aria-hidden": true, className: "absolute inset-0 -z-10 size-full object-cover" })) : (_jsx("video", { ref: video, "aria-hidden": true, tabIndex: -1, className: "absolute inset-0 -z-10 size-full object-cover", poster: poster, autoPlay: true, muted: true, loop: true, playsInline: true, preload: "auto", children: list.map((s) => _jsx("source", { src: s.url, type: MIME[s.type] }, s.url)) })), children, reduced ? null : (_jsx("button", { type: "button", "data-slot": "background-video-toggle", "aria-label": paused ? t("playBackground") : t("pauseBackground"), onClick: () => {
|
|
307
|
+
const el = video.current;
|
|
308
|
+
if (!el)
|
|
309
|
+
return;
|
|
310
|
+
if (el.paused) {
|
|
311
|
+
void el.play()?.catch?.(() => { });
|
|
312
|
+
setPaused(false);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
el.pause();
|
|
316
|
+
setPaused(true);
|
|
317
|
+
}
|
|
318
|
+
}, className: "focus-ring surface-popover absolute end-4 bottom-4 z-10 inline-flex size-9 items-center justify-center rounded-full text-fg [&_svg]:size-4", children: paused ? _jsx(Play, { "aria-hidden": true, className: "fill-current" }) : _jsx(Pause, { "aria-hidden": true, className: "fill-current" }) }))] }));
|
|
319
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Motion core: level lookup, a shared IntersectionObserver pool and timing helpers.
|
|
3
|
+
* No React in here — every primitive in this folder builds on these.
|
|
4
|
+
*/
|
|
5
|
+
export type MotionLevel = "full" | "subtle" | "off";
|
|
6
|
+
/** `true` when the OS asks for reduced motion. `false` on the server. */
|
|
7
|
+
export declare function prefersReducedMotion(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The motion level that applies to an element: `data-motion="off"` on `<html>` always wins,
|
|
10
|
+
* then the closest `[data-motion]` ancestor (SiteShell sets one), then `"subtle"`.
|
|
11
|
+
* Reduced motion turns every level into `"off"`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function motionLevel(el?: Element | null): MotionLevel;
|
|
14
|
+
/** Shorthand: may this element animate at all? */
|
|
15
|
+
export declare const motionAllowed: (el?: Element | null) => boolean;
|
|
16
|
+
type Handler = (entry: IntersectionObserverEntry) => void;
|
|
17
|
+
export declare const ioSupported: () => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Observe an element with a pooled IntersectionObserver. Returns the unobserve function.
|
|
20
|
+
* Without IntersectionObserver the handler is never called — callers fall back themselves.
|
|
21
|
+
*/
|
|
22
|
+
export declare function observe(el: Element, handler: Handler, { rootMargin, threshold }?: {
|
|
23
|
+
rootMargin?: string;
|
|
24
|
+
threshold?: number;
|
|
25
|
+
}): () => void;
|
|
26
|
+
/** Is the element's box (at least partly) inside the viewport right now? */
|
|
27
|
+
export declare function inViewport(el: Element): boolean;
|
|
28
|
+
/** Longest `duration + delay` (ms) among the element's transitions — or its children's, for staggers. */
|
|
29
|
+
export declare function transitionEnd(el: Element, children?: boolean): number;
|
|
30
|
+
/** Easing used by the JS-driven primitives (count-up): ease-out quint. */
|
|
31
|
+
export declare const easeOutQuint: (t: number) => number;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Motion core: level lookup, a shared IntersectionObserver pool and timing helpers.
|
|
3
|
+
* No React in here — every primitive in this folder builds on these.
|
|
4
|
+
*/
|
|
5
|
+
const REDUCE = "(prefers-reduced-motion: reduce)";
|
|
6
|
+
/** `true` when the OS asks for reduced motion. `false` on the server. */
|
|
7
|
+
export function prefersReducedMotion() {
|
|
8
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(REDUCE).matches;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The motion level that applies to an element: `data-motion="off"` on `<html>` always wins,
|
|
12
|
+
* then the closest `[data-motion]` ancestor (SiteShell sets one), then `"subtle"`.
|
|
13
|
+
* Reduced motion turns every level into `"off"`.
|
|
14
|
+
*/
|
|
15
|
+
export function motionLevel(el) {
|
|
16
|
+
if (typeof document === "undefined" || prefersReducedMotion())
|
|
17
|
+
return "off";
|
|
18
|
+
if (document.documentElement.getAttribute("data-motion") === "off")
|
|
19
|
+
return "off";
|
|
20
|
+
const v = el?.closest("[data-motion]")?.getAttribute("data-motion");
|
|
21
|
+
return v === "off" || v === "full" ? v : "subtle";
|
|
22
|
+
}
|
|
23
|
+
/** Shorthand: may this element animate at all? */
|
|
24
|
+
export const motionAllowed = (el) => motionLevel(el) !== "off";
|
|
25
|
+
const pools = new Map();
|
|
26
|
+
export const ioSupported = () => typeof window !== "undefined" && typeof window.IntersectionObserver === "function";
|
|
27
|
+
/**
|
|
28
|
+
* Observe an element with a pooled IntersectionObserver. Returns the unobserve function.
|
|
29
|
+
* Without IntersectionObserver the handler is never called — callers fall back themselves.
|
|
30
|
+
*/
|
|
31
|
+
export function observe(el, handler, { rootMargin = "0px 0px -8% 0px", threshold = 0 } = {}) {
|
|
32
|
+
if (!ioSupported())
|
|
33
|
+
return () => { };
|
|
34
|
+
const key = `${rootMargin}|${threshold}`;
|
|
35
|
+
let pool = pools.get(key);
|
|
36
|
+
if (!pool) {
|
|
37
|
+
const handlers = new Map();
|
|
38
|
+
const io = new IntersectionObserver((entries) => entries.forEach((e) => handlers.get(e.target)?.(e)), { rootMargin, threshold });
|
|
39
|
+
pool = { io, handlers };
|
|
40
|
+
pools.set(key, pool);
|
|
41
|
+
}
|
|
42
|
+
const p = pool;
|
|
43
|
+
p.handlers.set(el, handler);
|
|
44
|
+
p.io.observe(el);
|
|
45
|
+
return () => {
|
|
46
|
+
p.handlers.delete(el);
|
|
47
|
+
p.io.unobserve(el);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Is the element's box (at least partly) inside the viewport right now? */
|
|
51
|
+
export function inViewport(el) {
|
|
52
|
+
if (typeof window === "undefined")
|
|
53
|
+
return false;
|
|
54
|
+
const r = el.getBoundingClientRect();
|
|
55
|
+
const h = window.innerHeight || document.documentElement.clientHeight;
|
|
56
|
+
const w = window.innerWidth || document.documentElement.clientWidth;
|
|
57
|
+
return r.bottom > 0 && r.top < h && r.right > 0 && r.left < w;
|
|
58
|
+
}
|
|
59
|
+
/** Longest `duration + delay` (ms) among the element's transitions — or its children's, for staggers. */
|
|
60
|
+
export function transitionEnd(el, children = false) {
|
|
61
|
+
if (typeof window === "undefined")
|
|
62
|
+
return 0;
|
|
63
|
+
const ms = (v) => v.split(",").map((s) => (s.trim().endsWith("ms") ? parseFloat(s) : parseFloat(s) * 1000) || 0);
|
|
64
|
+
const longest = (node) => {
|
|
65
|
+
const cs = window.getComputedStyle(node);
|
|
66
|
+
const d = ms(cs.transitionDuration);
|
|
67
|
+
const de = ms(cs.transitionDelay);
|
|
68
|
+
return d.reduce((m, v, i) => Math.max(m, v + (de[i] ?? de[0] ?? 0)), 0);
|
|
69
|
+
};
|
|
70
|
+
let max = longest(el);
|
|
71
|
+
if (children)
|
|
72
|
+
for (const c of Array.from(el.children))
|
|
73
|
+
max = Math.max(max, longest(c));
|
|
74
|
+
return max;
|
|
75
|
+
}
|
|
76
|
+
/** Easing used by the JS-driven primitives (count-up): ease-out quint. */
|
|
77
|
+
export const easeOutQuint = (t) => 1 - Math.pow(1 - t, 5);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CountUpProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
|
|
3
|
+
/** The final number. This is what the server renders and what screen readers always hear. */
|
|
4
|
+
value: number;
|
|
5
|
+
/** Where the count starts. Default 0. */
|
|
6
|
+
from?: number;
|
|
7
|
+
/** Animation length in ms. Default 1400 (subtle) / 1800 (full). */
|
|
8
|
+
duration?: number;
|
|
9
|
+
/** Delay after it becomes visible, in ms. */
|
|
10
|
+
delay?: number;
|
|
11
|
+
/** BCP 47 locale. Default: the surrounding LocaleProvider (`en-US`). */
|
|
12
|
+
locale?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Intl.NumberFormat options. Default: as many fraction digits as `value` has (max 2),
|
|
15
|
+
* so `4.8` counts as 0.0 → 4.8 and `1240` as 0 → 1,240.
|
|
16
|
+
*/
|
|
17
|
+
format?: Intl.NumberFormatOptions;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A number that counts up to its value when it scrolls into view. Tabular figures and a hidden
|
|
21
|
+
* copy of the final value reserve the width, so nothing around it moves. Screen readers read the
|
|
22
|
+
* final value only; reduced motion, `data-motion="off"` and server-rendered numbers already on
|
|
23
|
+
* screen show the final value at once.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <CountUp value={1240} /> reviews · <CountUp value={4.8} locale="tr-TR" />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const CountUp: React.ForwardRefExoticComponent<CountUpProps & React.RefAttributes<HTMLSpanElement>>;
|