@vamos-ui/react 0.0.0-stage → 0.2.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 +100 -0
- package/dist/blocks/site/_kit-1.js +135 -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 +112 -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 +51 -0
- package/dist/blocks/site/feature-grid.d.ts +46 -0
- package/dist/blocks/site/feature-grid.js +49 -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 +47 -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 +67 -0
- package/dist/blocks/site/logo-strip.d.ts +42 -0
- package/dist/blocks/site/logo-strip.js +26 -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 +55 -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 +82 -0
- package/dist/blocks/site/process.d.ts +36 -0
- package/dist/blocks/site/process.js +41 -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 +97 -0
- package/dist/blocks/site/site-shell.js +227 -0
- package/dist/blocks/site/stats-band.d.ts +40 -0
- package/dist/blocks/site/stats-band.js +41 -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 +65 -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 +11 -0
- package/dist/business/index.js +20 -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/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 +42 -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/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/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 +275 -0
- package/dist/components/command.js +493 -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/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/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/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/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 +86 -0
- package/dist/index.js +87 -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 +22 -0
- package/dist/lib/public.js +33 -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 +138 -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/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 +101 -0
- package/dist/sortable/sortable-tree.js +450 -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/navigation.css +293 -0
- package/dist/styles/overlays.css +244 -0
- package/dist/styles.css +742 -0
- package/package.json +156 -4
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowLeft, ArrowRight } from "lucide-react";
|
|
3
|
+
import { cn2 as cn } from "./shared/kit-2.js";
|
|
4
|
+
import { Section, Container } from "../section.js";
|
|
5
|
+
import { SectionHeader } from "../section-header.js";
|
|
6
|
+
import { BlockImage } from "../block-image.js";
|
|
7
|
+
import { BlockLink } from "../block-link.js";
|
|
8
|
+
import { site2Text } from "./shared/labels-2.js";
|
|
9
|
+
import { fieldAttr, formatDate2, isoDay, useBlockIds2 } from "./shared/kit-2.js";
|
|
10
|
+
/**
|
|
11
|
+
* Latest posts and category archives. Receives posts as data (`PostSummary`); fetching is the
|
|
12
|
+
* app's job (or the renderer's `resolvers.posts`). Each post is an `article` with one link on the
|
|
13
|
+
* title that covers the card. Server component.
|
|
14
|
+
*
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <BlogList variant="editorial" title="From the *studio*" posts={posts} pagination={{ page: 1, total: 4, hrefTemplate: "/blog?page={page}" }} />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function BlogList({ variant = "editorial", eyebrow, title, lead, allLink, posts, categories, pagination, showCovers = true, empty, postHeadingLevel, id, anchor, theme, headingLevel = 2, className, labels, locale = "en-US", components, editMode, }) {
|
|
20
|
+
const t = site2Text(labels, locale);
|
|
21
|
+
const { headingId } = useBlockIds2(id, "blog");
|
|
22
|
+
const level = postHeadingLevel ?? (title ? 3 : 2);
|
|
23
|
+
const ctx = { t, locale, components, labels, editMode, level, covers: showCovers && variant !== "compact" };
|
|
24
|
+
const actions = allLink ? (_jsxs(BlockLink, { href: allLink.href, appearance: "link", components: components, labels: labels, locale: locale, children: [allLink.label, _jsx(ArrowRight, { "aria-hidden": true, strokeWidth: 1.5, className: "size-[1em] rtl:-scale-x-100" })] })) : undefined;
|
|
25
|
+
const compact = variant === "compact";
|
|
26
|
+
return (_jsx(Section, { theme: theme, anchor: anchor, headingId: title ? headingId : undefined, blockId: id, blockType: "blog-list", editMode: editMode, className: cn("vb-blog", className), "data-variant": variant, children: _jsxs(Container, { className: cn("flex flex-col", compact ? "gap-6" : "gap-10 @4xl:gap-14"), children: [title || eyebrow || lead || actions ? (compact ? (_jsxs("div", { className: "flex items-baseline justify-between gap-4", children: [title ? (_jsx("h2", { id: headingId, className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", ...fieldAttr(editMode, "title"), children: title })) : null, actions] })) : (_jsx(SectionHeader, { eyebrow: eyebrow, title: title, lead: lead, headingId: headingId, headingLevel: headingLevel, align: actions ? "split" : "start", actions: actions, editMode: editMode, labels: labels, locale: locale }))) : null, categories?.length ? (_jsx("nav", { "aria-label": t("categories"), className: "-mx-1 overflow-x-auto scrollbar-none", children: _jsx("ul", { className: "flex gap-1 px-1", children: categories.map((c, i) => (_jsx("li", { children: _jsx(BlockLink, { href: c.href, "aria-current": c.active ? "page" : undefined, components: components, labels: labels, locale: locale, className: cn("inline-flex h-9 items-center whitespace-nowrap rounded-full px-3.5 text-sm transition-colors focus-ring", c.active ? "bg-fg text-scene" : "text-fg-muted hover:bg-hover hover:text-fg"), children: c.label }) }, i))) }) })) : null, posts.length === 0 ? (_jsxs("div", { className: "flex flex-col items-start gap-3 border-t border-line pt-8", children: [_jsx("p", { className: "text-h3 font-semibold tracking-[-0.012em] text-fg", children: empty?.title ?? t("noPosts") }), _jsx("p", { className: "max-w-(--measure) text-fg-muted", children: empty?.text ?? t("noPostsHint") }), empty?.action ? _jsx("div", { className: "pt-3", children: empty.action }) : null] })) : variant === "editorial" ? (_jsx(Editorial, { posts: posts, ctx: ctx })) : variant === "list" ? (_jsx("ul", { className: "flex flex-col border-b border-line", children: posts.map((p, i) => (_jsx("li", { className: "border-t border-line", children: _jsx(ListPost, { post: p, ctx: ctx }) }, p.href + i))) })) : variant === "grid" ? (_jsx("ul", { className: "grid gap-x-(--gutter) gap-y-12 @2xl:grid-cols-2 @4xl:grid-cols-3", children: posts.map((p, i) => (_jsx("li", { children: _jsx(GridPost, { post: p, ctx: ctx }) }, p.href + i))) })) : (_jsx("ul", { className: "flex flex-col", children: posts.slice(0, 5).map((p, i) => (_jsx("li", { className: "border-t border-line first:border-t-0", children: _jsx(CompactPost, { post: p, ctx: ctx }) }, p.href + i))) })), pagination && pagination.total > 1 ? _jsx(Pager, { pagination: pagination, ctx: ctx }) : null] }) }));
|
|
27
|
+
}
|
|
28
|
+
function PostTitle({ post, ctx, className }) {
|
|
29
|
+
const H = `h${ctx.level}`;
|
|
30
|
+
return (_jsx(H, { className: cn("text-fg text-balance", className), children: _jsx(BlockLink, { href: post.href, components: ctx.components, labels: ctx.labels, locale: ctx.locale, className: "vb-post-link rounded-[2px] focus-ring after:absolute after:inset-0 after:content-['']", children: post.title }) }));
|
|
31
|
+
}
|
|
32
|
+
function PostDate({ post, ctx, className }) {
|
|
33
|
+
return (_jsx("time", { dateTime: isoDay(post.publishedAt), className: cn("font-mono text-eyebrow tabular uppercase tracking-[0.06em] text-fg-muted", className), children: formatDate2(isoDay(post.publishedAt), ctx.locale, "medium") }));
|
|
34
|
+
}
|
|
35
|
+
function Meta({ post, ctx }) {
|
|
36
|
+
return (_jsxs("p", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 font-mono text-eyebrow uppercase tracking-[0.06em] text-fg-muted", children: [_jsx(PostDate, { post: post, ctx: ctx }), post.readingMinutes ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("span", { children: ctx.t("minRead", { count: post.readingMinutes }) })] })) : null, post.author ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("span", { children: ctx.t("by", { name: post.author.name }) })] })) : null] }));
|
|
37
|
+
}
|
|
38
|
+
function Category({ post }) {
|
|
39
|
+
if (!post.category)
|
|
40
|
+
return null;
|
|
41
|
+
// Text only (the card link covers the article; a nested link would steal its click area).
|
|
42
|
+
return _jsx("p", { className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-accent-ink", children: post.category.label });
|
|
43
|
+
}
|
|
44
|
+
function Cover({ post, ctx, sizes, priority, className }) {
|
|
45
|
+
if (!ctx.covers || !post.cover?.src)
|
|
46
|
+
return null;
|
|
47
|
+
return _jsx(BlockImage, { ...post.cover, alt: post.cover.alt ?? "", decorative: !post.cover.alt, aspect: "3:2", sizes: sizes, priority: priority, className: cn("vb-post-cover rounded-ui", className), components: ctx.components });
|
|
48
|
+
}
|
|
49
|
+
function Editorial({ posts, ctx }) {
|
|
50
|
+
const [first, ...rest] = posts;
|
|
51
|
+
return (_jsxs("div", { className: "flex flex-col gap-12", children: [_jsxs("article", { className: "vb-post group/post relative grid gap-x-(--gutter) gap-y-6 @4xl:grid-cols-12 @4xl:items-end", children: [ctx.covers && first.cover ? (_jsx("div", { className: "@4xl:col-span-7", children: _jsx(Cover, { post: first, ctx: ctx, sizes: "(min-width: 56rem) 58vw, 100vw" }) })) : null, _jsxs("div", { className: cn("flex flex-col gap-4", ctx.covers && first.cover ? "@4xl:col-span-5" : "@4xl:col-span-9"), children: [_jsx(Category, { post: first }), _jsx(PostTitle, { post: first, ctx: ctx, className: "font-display text-display-m" }), first.excerpt ? _jsx("p", { className: "max-w-[52ch] text-fg-muted text-pretty", children: first.excerpt }) : null, _jsx(Meta, { post: first, ctx: ctx })] })] }), rest.length ? (_jsx("ul", { className: "grid gap-x-(--gutter) @2xl:grid-cols-2", children: rest.map((p, i) => (_jsx("li", { className: "border-t border-line", children: _jsxs("article", { className: "vb-post group/post relative flex flex-col gap-2 py-6", children: [_jsx(PostDate, { post: p, ctx: ctx }), _jsx(PostTitle, { post: p, ctx: ctx, className: "text-h3 font-semibold tracking-[-0.012em]" }), p.category ? _jsx("p", { className: "text-small text-fg-muted", children: p.category.label }) : null] }) }, p.href + i))) })) : null] }));
|
|
52
|
+
}
|
|
53
|
+
function ListPost({ post, ctx }) {
|
|
54
|
+
return (_jsxs("article", { className: "vb-post group/post relative grid gap-x-(--gutter) gap-y-2 py-6 @2xl:grid-cols-12 @2xl:items-baseline", children: [_jsx(PostDate, { post: post, ctx: ctx, className: "@2xl:col-span-2" }), _jsxs("div", { className: "flex flex-col gap-1.5 @2xl:col-span-8", children: [_jsx(PostTitle, { post: post, ctx: ctx, className: "text-h3 font-semibold tracking-[-0.012em]" }), post.excerpt ? _jsx("p", { className: "line-clamp-1 text-small text-fg-muted", children: post.excerpt }) : null] }), _jsx("p", { className: "text-small text-fg-muted @2xl:col-span-2 @2xl:text-end", children: post.readingMinutes ? ctx.t("minRead", { count: post.readingMinutes }) : null })] }));
|
|
55
|
+
}
|
|
56
|
+
function GridPost({ post, ctx }) {
|
|
57
|
+
return (_jsxs("article", { className: "vb-post group/post relative flex flex-col gap-4", children: [ctx.covers ? post.cover ? _jsx(Cover, { post: post, ctx: ctx, sizes: "(min-width: 56rem) 33vw, (min-width: 42rem) 50vw, 100vw" }) : _jsx("span", { "aria-hidden": true, className: "block aspect-[3/2] rounded-ui bg-surface-2" }) : null, _jsxs("div", { className: "flex flex-col gap-2.5", children: [_jsx(Category, { post: post }), _jsx(PostTitle, { post: post, ctx: ctx, className: "text-h3 font-semibold tracking-[-0.012em]" }), _jsx(Meta, { post: post, ctx: ctx })] })] }));
|
|
58
|
+
}
|
|
59
|
+
function CompactPost({ post, ctx }) {
|
|
60
|
+
return (_jsxs("article", { className: "vb-post group/post relative flex flex-col gap-1 py-4", children: [_jsx(PostTitle, { post: post, ctx: ctx, className: "text-body font-medium" }), _jsx(PostDate, { post: post, ctx: ctx })] }));
|
|
61
|
+
}
|
|
62
|
+
function pageHref(p, page) {
|
|
63
|
+
if (p.href)
|
|
64
|
+
return p.href(page);
|
|
65
|
+
const tpl = p.hrefTemplate ?? "?page={page}";
|
|
66
|
+
if (page === 1 && /[?&]page=\{page\}$/.test(tpl))
|
|
67
|
+
return tpl.replace(/[?&]page=\{page\}$/, "") || "?";
|
|
68
|
+
return tpl.replace("{page}", String(page));
|
|
69
|
+
}
|
|
70
|
+
function Pager({ pagination, ctx }) {
|
|
71
|
+
const { page, total } = pagination;
|
|
72
|
+
const linkClass = "inline-flex h-11 items-center gap-2 rounded-ui px-1 text-sm font-medium text-fg underline decoration-line underline-offset-[0.3em] hover:decoration-current focus-ring";
|
|
73
|
+
return (_jsxs("nav", { "aria-label": ctx.t("pagination"), className: "flex items-center justify-between gap-4 border-t border-line pt-6", children: [page > 1 ? (_jsxs(BlockLink, { href: pageHref(pagination, page - 1), rel: "prev", components: ctx.components, labels: ctx.labels, locale: ctx.locale, className: linkClass, children: [_jsx(ArrowLeft, { "aria-hidden": true, strokeWidth: 1.5, className: "size-4 rtl:-scale-x-100" }), ctx.t("previousPage")] })) : (_jsx("span", {})), _jsx("p", { className: "font-mono text-eyebrow tabular uppercase tracking-[0.08em] text-fg-muted", "aria-current": "page", children: ctx.t("pageOf", { page, total }) }), page < total ? (_jsxs(BlockLink, { href: pageHref(pagination, page + 1), rel: "next", components: ctx.components, labels: ctx.labels, locale: ctx.locale, className: linkClass, children: [ctx.t("nextPage"), _jsx(ArrowRight, { "aria-hidden": true, strokeWidth: 1.5, className: "size-4 rtl:-scale-x-100" })] })) : (_jsx("span", {}))] }));
|
|
74
|
+
}
|
|
75
|
+
/** Streaming fallback for `<Suspense fallback={<BlogListSkeleton />}>`. */
|
|
76
|
+
export function BlogListSkeleton({ variant = "grid", count = 3, className }) {
|
|
77
|
+
return (_jsxs("div", { "aria-hidden": true, className: cn("vb-container py-(--section-y)", className), "data-skeleton": "", children: [_jsx("div", { className: "mb-10 h-10 w-2/5 rounded-ui-sm bg-skeleton" }), _jsx("div", { className: cn("grid gap-x-(--gutter) gap-y-10", variant === "grid" ? "@2xl:grid-cols-2 @4xl:grid-cols-3" : ""), children: Array.from({ length: count }, (_, i) => (_jsxs("div", { className: "flex flex-col gap-3", children: [variant === "grid" ? _jsx("div", { className: "aspect-[3/2] rounded-ui bg-skeleton" }) : null, _jsx("div", { className: "h-3 w-24 rounded-ui-sm bg-skeleton" }), _jsx("div", { className: "h-5 w-4/5 rounded-ui-sm bg-skeleton" }), variant !== "compact" ? _jsx("div", { className: "h-4 w-3/5 rounded-ui-sm bg-skeleton" }) : null] }, i))) })] }));
|
|
78
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { BlockBaseProps } from "../types.js";
|
|
3
|
+
import type { CtaStyle } from "../schema/types.js";
|
|
4
|
+
import { type Site2BlockLabels } from "./shared/labels-2.js";
|
|
5
|
+
import { type SiteLink2 } from "./shared/kit-2.js";
|
|
6
|
+
export type ComparisonVariant = "table" | "versus";
|
|
7
|
+
/** `true` = yes, `false` = no, a string = the value ("5 GB"), `null` = not applicable (—). */
|
|
8
|
+
export type ComparisonValue = boolean | string | null;
|
|
9
|
+
export interface ComparisonColumn {
|
|
10
|
+
name: React.ReactNode;
|
|
11
|
+
/** Small line under the name ("$49 / mo"). */
|
|
12
|
+
note?: React.ReactNode;
|
|
13
|
+
cta?: {
|
|
14
|
+
link: SiteLink2;
|
|
15
|
+
style?: CtaStyle;
|
|
16
|
+
};
|
|
17
|
+
/** Faint accent band down the column. */
|
|
18
|
+
highlight?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface ComparisonRow {
|
|
21
|
+
feature: React.ReactNode;
|
|
22
|
+
/** Small text under the feature — never a "?" tooltip. */
|
|
23
|
+
hint?: React.ReactNode;
|
|
24
|
+
/** One value per column. */
|
|
25
|
+
values: ComparisonValue[];
|
|
26
|
+
}
|
|
27
|
+
export interface ComparisonGroup {
|
|
28
|
+
title?: React.ReactNode;
|
|
29
|
+
rows: ComparisonRow[];
|
|
30
|
+
}
|
|
31
|
+
export interface ComparisonTableProps extends Omit<BlockBaseProps, "variant" | "labels"> {
|
|
32
|
+
/** table: plans × features with sticky header and a mobile plan picker. versus: "Us" vs "Template site", two columns everywhere. */
|
|
33
|
+
variant?: ComparisonVariant;
|
|
34
|
+
eyebrow?: React.ReactNode;
|
|
35
|
+
title?: React.ReactNode;
|
|
36
|
+
lead?: React.ReactNode;
|
|
37
|
+
/** 2–5 columns. */
|
|
38
|
+
columns: ComparisonColumn[];
|
|
39
|
+
groups: ComparisonGroup[];
|
|
40
|
+
/** Table caption for screen readers. Default: the title. */
|
|
41
|
+
caption?: string;
|
|
42
|
+
labels?: Site2BlockLabels;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Plan × feature detail table, or a two-column "us vs. them" comparison. A real `<table>` with
|
|
46
|
+
* scoped headers and a caption; booleans carry hidden Yes/No text. On narrow containers a radio
|
|
47
|
+
* plan picker shows one column at a time (0 JS). Server component.
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <ComparisonTable columns={[{ name: "Starter" }, { name: "Studio", highlight: true }]}
|
|
51
|
+
* groups={[{ title: "Publishing", rows: [{ feature: "Pages", values: ["10", "Unlimited"] }] }]} />
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function ComparisonTable({ variant, eyebrow, title, lead, columns: columnsProp, groups, caption, id, anchor, theme, headingLevel, className, labels, locale, components, editMode, }: ComparisonTableProps): React.JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Check, Minus } from "lucide-react";
|
|
3
|
+
import { cn2 as cn } from "./shared/kit-2.js";
|
|
4
|
+
import { Section, Container } from "../section.js";
|
|
5
|
+
import { SectionHeader } from "../section-header.js";
|
|
6
|
+
import { BlockLink } from "../block-link.js";
|
|
7
|
+
import { site2Text } from "./shared/labels-2.js";
|
|
8
|
+
import { fieldAttr, textOf, useBlockIds2 } from "./shared/kit-2.js";
|
|
9
|
+
/**
|
|
10
|
+
* Plan × feature detail table, or a two-column "us vs. them" comparison. A real `<table>` with
|
|
11
|
+
* scoped headers and a caption; booleans carry hidden Yes/No text. On narrow containers a radio
|
|
12
|
+
* plan picker shows one column at a time (0 JS). Server component.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ComparisonTable columns={[{ name: "Starter" }, { name: "Studio", highlight: true }]}
|
|
16
|
+
* groups={[{ title: "Publishing", rows: [{ feature: "Pages", values: ["10", "Unlimited"] }] }]} />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function ComparisonTable({ variant = "table", eyebrow, title, lead, columns: columnsProp, groups, caption, id, anchor, theme, headingLevel = 2, className, labels, locale = "en-US", components, editMode, }) {
|
|
20
|
+
const t = site2Text(labels, locale);
|
|
21
|
+
const { base, headingId } = useBlockIds2(id, "comparison");
|
|
22
|
+
const versus = variant === "versus";
|
|
23
|
+
const columns = versus ? columnsProp.slice(0, 2) : columnsProp.slice(0, 5);
|
|
24
|
+
if (process.env.NODE_ENV !== "production" && columnsProp.length > 5)
|
|
25
|
+
console.warn("[vamos-ui] ComparisonTable: more than 5 columns are not supported; extra columns were dropped.");
|
|
26
|
+
const picked = Math.max(0, columns.findIndex((c) => c.highlight));
|
|
27
|
+
const pickerName = `${base}-plan`;
|
|
28
|
+
return (_jsx(Section, { theme: theme, anchor: anchor, headingId: title ? headingId : undefined, blockId: id, blockType: "comparison", editMode: editMode, className: cn("vb-cmp", className), "data-variant": variant, "data-cols": columns.length, children: _jsxs(Container, { className: "flex flex-col gap-10 @4xl:gap-14", children: [title || eyebrow || lead ? _jsx(SectionHeader, { eyebrow: eyebrow, title: title, lead: lead, headingId: headingId, headingLevel: headingLevel, editMode: editMode, labels: labels, locale: locale }) : null, !versus && columns.length > 1 ? (_jsxs("fieldset", { className: "vb-cmp-pick flex flex-col gap-2 @2xl:hidden", children: [_jsx("legend", { className: "mb-2 font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", children: t("showPlan") }), _jsx("div", { className: "flex flex-wrap gap-2", children: columns.map((c, i) => (_jsxs("label", { className: "vb-cmp-option inline-flex h-11 cursor-pointer items-center rounded-ui border border-line px-4 text-sm font-medium text-fg-muted", children: [_jsx("input", { type: "radio", name: pickerName, value: i, defaultChecked: i === picked, className: "sr-only" }), c.name] }, i))) })] })) : null, _jsxs("table", { className: "vb-cmp-table w-full table-fixed border-collapse text-small", children: [_jsx("caption", { className: "sr-only", children: caption ?? (textOf(title).replace(/\*/g, "") || t("comparePlans")) }), _jsxs("colgroup", { children: [_jsx("col", { className: versus ? "w-[34%]" : "w-[40%] @4xl:w-[34%]" }), columns.map((c, i) => (_jsx("col", { "data-col": i }, i)))] }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { scope: "col", className: "vb-cmp-head pb-5 text-start align-bottom font-mono text-eyebrow font-normal uppercase tracking-[0.08em] text-fg-muted", children: t("feature") }), columns.map((c, i) => (_jsx("th", { scope: "col", "data-col": i, "data-highlight": c.highlight ? "" : undefined, className: cn("vb-cmp-head px-3 pb-5 text-start align-bottom font-normal @4xl:px-5", versus && i === 1 && "text-fg-muted"), children: _jsxs("span", { className: "flex flex-col items-start gap-1.5", children: [_jsx("span", { className: cn("text-h3 font-semibold tracking-[-0.012em]", versus && i === 1 ? "text-fg-muted" : "text-fg"), ...fieldAttr(editMode, `columns.${i}.name`), children: c.name }), c.note ? _jsx("span", { className: "text-small text-fg-muted", children: c.note }) : null, c.cta ? (_jsx(BlockLink, { href: c.cta.link.href, newTab: c.cta.link.newTab, appearance: c.cta.style === "primary" && c.highlight ? "primary" : c.cta.style === "link" ? "link" : "secondary", size: "md", components: components, labels: labels, locale: locale, className: "mt-2", "data-track": `comparison:${i}`, children: c.cta.link.label })) : null] }) }, i)))] }) }), groups.map((g, gi) => (_jsxs("tbody", { children: [g.title ? (_jsx("tr", { children: _jsx("th", { scope: "colgroup", colSpan: columns.length + 1, className: "bg-surface-2 px-3 py-2.5 text-start font-mono text-eyebrow font-normal uppercase tracking-[0.08em] text-fg-muted @4xl:px-4", children: g.title }) })) : null, g.rows.map((r, ri) => (_jsxs("tr", { className: "border-b border-line", children: [_jsxs("th", { scope: "row", className: "py-4 pe-4 text-start align-top font-normal", children: [_jsx("span", { className: "block text-fg", children: r.feature }), r.hint ? _jsx("span", { className: "mt-1 block text-xs text-fg-muted text-pretty", children: r.hint }) : null] }), columns.map((c, ci) => (_jsx("td", { "data-col": ci, "data-highlight": c.highlight ? "" : undefined, className: cn("px-3 py-4 align-top @4xl:px-5", versus && ci === 1 ? "text-fg-muted" : "text-fg"), children: _jsx(ValueCell, { value: r.values[ci] ?? null, t: t }) }, ci)))] }, ri)))] }, gi)))] })] }) }));
|
|
29
|
+
}
|
|
30
|
+
function ValueCell({ value, t }) {
|
|
31
|
+
if (value === true)
|
|
32
|
+
return (_jsxs(_Fragment, { children: [_jsx(Check, { "aria-hidden": true, strokeWidth: 1.5, className: "size-[18px] text-fg" }), _jsx("span", { className: "sr-only", children: t("yes") })] }));
|
|
33
|
+
if (value === false)
|
|
34
|
+
return (_jsxs(_Fragment, { children: [_jsx(Minus, { "aria-hidden": true, strokeWidth: 1.5, className: "size-[18px] text-fg-subtle" }), _jsx("span", { className: "sr-only", children: t("no") })] }));
|
|
35
|
+
if (value === null || value === "")
|
|
36
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, className: "text-fg-subtle", children: "\u2014" }), _jsx("span", { className: "sr-only", children: t("no") })] }));
|
|
37
|
+
return _jsx("span", { className: "tabular", children: value });
|
|
38
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { BlockBaseProps } from "../types.js";
|
|
3
|
+
import type { RichDoc } from "../schema/rich-doc.js";
|
|
4
|
+
import { type Site2BlockLabels } from "./shared/labels-2.js";
|
|
5
|
+
import { consentDefaultsScript, type ConsentCategory } from "./shared/consent.js";
|
|
6
|
+
export type ConsentVariant = "bar" | "box";
|
|
7
|
+
export interface ConsentBannerProps extends Omit<BlockBaseProps, "variant" | "labels" | "headingLevel"> {
|
|
8
|
+
/** bar: a thin full-width strip at the bottom. box: a 360px panel in the bottom-start corner. */
|
|
9
|
+
variant?: ConsentVariant;
|
|
10
|
+
/** The notice. Rich text may contain links. Default: a neutral template — review with counsel. */
|
|
11
|
+
text?: React.ReactNode | RichDoc;
|
|
12
|
+
/** Cookie policy. */
|
|
13
|
+
policyLink?: {
|
|
14
|
+
href: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
};
|
|
17
|
+
/** Categories offered. `necessary` is always on. Default all four. */
|
|
18
|
+
categories?: ConsentCategory[];
|
|
19
|
+
/** Bump when the text or categories change — visitors are asked again. Default 1. */
|
|
20
|
+
version?: number;
|
|
21
|
+
/** Default `"bottom"` (bar) / `"bottom-start"` (box). */
|
|
22
|
+
position?: "bottom" | "bottom-start";
|
|
23
|
+
/** `opt-in` (GDPR, KVKK — default): nothing non-essential before a choice. `notice` where the law allows. */
|
|
24
|
+
regionMode?: "opt-in" | "notice";
|
|
25
|
+
/** Render inside its parent instead of fixed to the viewport (docs, builder canvas). */
|
|
26
|
+
contained?: boolean;
|
|
27
|
+
/** Show even when a choice is stored (previews). */
|
|
28
|
+
forceShow?: boolean;
|
|
29
|
+
/** Open the preferences dialog at once (previews). */
|
|
30
|
+
defaultPreferencesOpen?: boolean;
|
|
31
|
+
labels?: Site2BlockLabels;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Cookie consent for GDPR / ePrivacy and Turkey's KVKK, with Google Consent Mode v2. Not a modal:
|
|
35
|
+
* a labelled region with "Reject all" and "Accept all" at equal weight, preferences per category,
|
|
36
|
+
* a first-party `vb_consent` cookie (6 months) and `getConsent` / `onConsent` helpers. Server
|
|
37
|
+
* wrapper around a ~3 KB island. Pair it with `consentDefaultsScript()` in `<head>`.
|
|
38
|
+
*
|
|
39
|
+
* ```tsx
|
|
40
|
+
* <head><script dangerouslySetInnerHTML={{ __html: consentDefaultsScript() }} /></head>
|
|
41
|
+
* …
|
|
42
|
+
* <ConsentBanner policyLink={{ href: "/cookies" }} version={2} />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function ConsentBanner({ variant, text, policyLink, categories, version, position, regionMode, contained, forceShow, defaultPreferencesOpen, className, labels, locale, components, }: ConsentBannerProps): React.JSX.Element;
|
|
46
|
+
/**
|
|
47
|
+
* The Consent Mode v2 defaults as a `<script>` for `<head>` (server component). Renders before any
|
|
48
|
+
* Google tag so ads and analytics wait for the visitor's choice.
|
|
49
|
+
*/
|
|
50
|
+
export declare function ConsentDefaults(props: Parameters<typeof consentDefaultsScript>[0] & {
|
|
51
|
+
nonce?: string;
|
|
52
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { RichText } from "../rich-text.js";
|
|
3
|
+
import { labelTemplates, site2Text } from "./shared/labels-2.js";
|
|
4
|
+
import { consentLabelKeys } from "./shared/island-keys.js";
|
|
5
|
+
import { ConsentBannerIsland } from "./shared/consent-island.js";
|
|
6
|
+
import { CONSENT_CATEGORIES, consentDefaultsScript } from "./shared/consent.js";
|
|
7
|
+
const isRichDoc = (v) => !!v && typeof v === "object" && v.type === "doc";
|
|
8
|
+
/**
|
|
9
|
+
* Cookie consent for GDPR / ePrivacy and Turkey's KVKK, with Google Consent Mode v2. Not a modal:
|
|
10
|
+
* a labelled region with "Reject all" and "Accept all" at equal weight, preferences per category,
|
|
11
|
+
* a first-party `vb_consent` cookie (6 months) and `getConsent` / `onConsent` helpers. Server
|
|
12
|
+
* wrapper around a ~3 KB island. Pair it with `consentDefaultsScript()` in `<head>`.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <head><script dangerouslySetInnerHTML={{ __html: consentDefaultsScript() }} /></head>
|
|
16
|
+
* …
|
|
17
|
+
* <ConsentBanner policyLink={{ href: "/cookies" }} version={2} />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function ConsentBanner({ variant = "bar", text, policyLink, categories = [...CONSENT_CATEGORIES], version = 1, position, regionMode = "opt-in", contained, forceShow, defaultPreferencesOpen, className, labels, locale = "en-US", components, }) {
|
|
21
|
+
const t = site2Text(labels, locale);
|
|
22
|
+
const cats = ["necessary", ...categories.filter((c) => c !== "necessary")];
|
|
23
|
+
const body = text === undefined ? t("cookieText") : isRichDoc(text) ? _jsx(RichText, { doc: text, size: "sm", components: components, labels: labels, locale: locale, className: "[&>p]:m-0" }) : text;
|
|
24
|
+
return (_jsx(ConsentBannerIsland, { variant: variant, text: body, policyLink: policyLink ? { href: policyLink.href, label: policyLink.label ?? t("cookiePolicy") } : undefined, categories: cats, version: version, position: position ?? (variant === "box" ? "bottom-start" : "bottom"), regionMode: regionMode, labels: labelTemplates(labels, consentLabelKeys), contained: contained, forceShow: forceShow, defaultPreferencesOpen: defaultPreferencesOpen, className: className }));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The Consent Mode v2 defaults as a `<script>` for `<head>` (server component). Renders before any
|
|
28
|
+
* Google tag so ads and analytics wait for the visitor's choice.
|
|
29
|
+
*/
|
|
30
|
+
export function ConsentDefaults(props) {
|
|
31
|
+
const { nonce, ...opts } = props;
|
|
32
|
+
return _jsx("script", { nonce: nonce, dangerouslySetInnerHTML: { __html: consentDefaultsScript(opts) } });
|
|
33
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { BlockBaseProps } from "../types.js";
|
|
3
|
+
import type { OpeningHours } from "../schema/types.js";
|
|
4
|
+
import { type Site2BlockLabels } from "./shared/labels-2.js";
|
|
5
|
+
export type ContactDockVariant = "fab" | "bar" | "both";
|
|
6
|
+
export type DockAction = "call" | "whatsapp" | "directions" | "booking" | "email";
|
|
7
|
+
export type MessagingProvider = "whatsapp" | "telegram" | "messenger";
|
|
8
|
+
export interface ContactDockProps extends Omit<BlockBaseProps, "variant" | "labels" | "headingLevel"> {
|
|
9
|
+
/** fab: a round message button in the bottom-end corner. bar: a mobile bottom bar of 2–4 actions. both: fab on desktop, bar on mobile. */
|
|
10
|
+
variant?: ContactDockVariant;
|
|
11
|
+
/** Messaging network of the fab. Default `"whatsapp"`. */
|
|
12
|
+
provider?: MessagingProvider;
|
|
13
|
+
/** E.164 WhatsApp number. */
|
|
14
|
+
whatsapp?: string;
|
|
15
|
+
/** Telegram username (without @). */
|
|
16
|
+
telegram?: string;
|
|
17
|
+
/** Facebook page username for Messenger (`m.me/<page>`). */
|
|
18
|
+
messenger?: string;
|
|
19
|
+
/** Prefilled WhatsApp text ("Hi, I’d like to book a table."). */
|
|
20
|
+
message?: string;
|
|
21
|
+
/** Fab label on desktop. Default "Message us". */
|
|
22
|
+
label?: string;
|
|
23
|
+
/** E.164 phone for "Call". */
|
|
24
|
+
phone?: string;
|
|
25
|
+
directionsHref?: string;
|
|
26
|
+
bookingHref?: string;
|
|
27
|
+
email?: string;
|
|
28
|
+
/** Bar actions, in order (max 4). Default: call · whatsapp · directions (those configured). */
|
|
29
|
+
actions?: DockAction[];
|
|
30
|
+
/** Logical side. Default `"end"`. */
|
|
31
|
+
position?: "end" | "start";
|
|
32
|
+
/** Opening hours for off-hours behaviour. */
|
|
33
|
+
hours?: OpeningHours;
|
|
34
|
+
/** show (default): nothing changes. label: "We’re closed — we’ll reply in the morning". hide: no dock while closed. */
|
|
35
|
+
offHours?: "show" | "label" | "hide";
|
|
36
|
+
/** Fixed "now" (ISO) for previews. */
|
|
37
|
+
now?: string;
|
|
38
|
+
/** Render inside the parent instead of fixed to the viewport (docs, builder canvas). */
|
|
39
|
+
contained?: boolean;
|
|
40
|
+
labels?: Site2BlockLabels;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Floating messaging button and mobile action bar ("Call · Directions · WhatsApp") — the main
|
|
44
|
+
* conversion channel for local businesses in Turkey and many other markets. Plain links with
|
|
45
|
+
* `data-track` for the app's analytics, last in DOM order, ≥ 44px targets, safe-area aware.
|
|
46
|
+
* Server component; off-hours behaviour is a ~0.4 KB island.
|
|
47
|
+
*
|
|
48
|
+
* ```tsx
|
|
49
|
+
* <ContactDock variant="both" whatsapp="+902160000000" message="Hi, I’d like to book a table." phone="+902160000000" directionsHref="https://maps.app.goo.gl/…" />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function ContactDock(props: ContactDockProps): React.JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CalendarCheck, Mail, Navigation, Phone } from "lucide-react";
|
|
3
|
+
import { cn2 as cn } from "./shared/kit-2.js";
|
|
4
|
+
import { site2Text } from "./shared/labels-2.js";
|
|
5
|
+
import { telHref } from "./shared/kit-2.js";
|
|
6
|
+
import { BrandIcon, BRAND_NAMES, waLink } from "./shared/brand-icons.js";
|
|
7
|
+
import { DockHours } from "./shared/dock-hours.js";
|
|
8
|
+
import { DockAvoid } from "./shared/dock-avoid.js";
|
|
9
|
+
function actionSpec(a, p, t) {
|
|
10
|
+
const iconClass = "size-5";
|
|
11
|
+
switch (a) {
|
|
12
|
+
case "call":
|
|
13
|
+
return p.phone ? { href: telHref(p.phone), label: t("call"), aria: t("callNumber", { phone: p.phone }), icon: _jsx(Phone, { "aria-hidden": true, strokeWidth: 1.5, className: iconClass }) } : null;
|
|
14
|
+
case "whatsapp":
|
|
15
|
+
return p.whatsapp
|
|
16
|
+
? { href: waLink(p.whatsapp, p.message), label: "WhatsApp", aria: `${t("messageUsOn", { network: "WhatsApp" })}, ${t("opensInNewTab").replace(/[()]/g, "")}`, icon: _jsx(BrandIcon, { name: "whatsapp", className: iconClass }), external: true }
|
|
17
|
+
: null;
|
|
18
|
+
case "directions":
|
|
19
|
+
return p.directionsHref ? { href: p.directionsHref, label: t("directionsShort"), aria: t("directions"), icon: _jsx(Navigation, { "aria-hidden": true, strokeWidth: 1.5, className: iconClass }), external: true } : null;
|
|
20
|
+
case "booking":
|
|
21
|
+
return p.bookingHref ? { href: p.bookingHref, label: t("booking"), aria: t("booking"), icon: _jsx(CalendarCheck, { "aria-hidden": true, strokeWidth: 1.5, className: iconClass }) } : null;
|
|
22
|
+
case "email":
|
|
23
|
+
return p.email ? { href: `mailto:${p.email}`, label: t("emailShort"), aria: `${t("email")}: ${p.email}`, icon: _jsx(Mail, { "aria-hidden": true, strokeWidth: 1.5, className: iconClass }) } : null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function messagingHref(p) {
|
|
27
|
+
const provider = p.provider ?? "whatsapp";
|
|
28
|
+
if (provider === "telegram")
|
|
29
|
+
return p.telegram ? `https://t.me/${p.telegram.replace(/^@/, "")}` : undefined;
|
|
30
|
+
if (provider === "messenger")
|
|
31
|
+
return p.messenger ? `https://m.me/${p.messenger}` : undefined;
|
|
32
|
+
return p.whatsapp ? waLink(p.whatsapp, p.message) : undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Floating messaging button and mobile action bar ("Call · Directions · WhatsApp") — the main
|
|
36
|
+
* conversion channel for local businesses in Turkey and many other markets. Plain links with
|
|
37
|
+
* `data-track` for the app's analytics, last in DOM order, ≥ 44px targets, safe-area aware.
|
|
38
|
+
* Server component; off-hours behaviour is a ~0.4 KB island.
|
|
39
|
+
*
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <ContactDock variant="both" whatsapp="+902160000000" message="Hi, I’d like to book a table." phone="+902160000000" directionsHref="https://maps.app.goo.gl/…" />
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function ContactDock(props) {
|
|
45
|
+
const { variant = "both", provider = "whatsapp", label, position = "end", hours, offHours = "show", now, contained, className, labels, locale = "en-US", id, editMode } = props;
|
|
46
|
+
const t = site2Text(labels, locale);
|
|
47
|
+
const network = BRAND_NAMES[provider];
|
|
48
|
+
const href = messagingHref(props);
|
|
49
|
+
const defaultActions = ["call", "whatsapp", "directions", "booking", "email"];
|
|
50
|
+
const actions = (props.actions ?? defaultActions).map((a) => [a, actionSpec(a, props, t)]).filter((x) => !!x[1]).slice(0, 4);
|
|
51
|
+
const showFab = variant !== "bar" && href;
|
|
52
|
+
const showBar = variant !== "fab" && actions.length >= 2;
|
|
53
|
+
const hoursIsland = hours && offHours !== "show" ? _jsx(DockHours, { hours: hours, mode: offHours, text: t("offHours"), now: now, className: "vb-dock-offhours" }) : null;
|
|
54
|
+
return (_jsxs("div", { "data-contact-dock": "", "data-variant": variant, "data-position": position, "data-contained": contained ? "" : undefined, "data-block-id": editMode ? id : undefined, className: cn("vb-dock", className), children: [showFab ? (_jsxs("div", { className: cn("vb-dock-fab", variant === "both" && "vb-dock-desktop", position === "start" && "flex-row-reverse"), children: [hoursIsland ? _jsx("span", { className: "vb-dock-note surface-popover max-w-[16rem] rounded-ui px-3 py-2 text-xs text-fg empty:hidden [&:has(>span:empty)]:hidden", children: hoursIsland }) : null, _jsx("span", { "aria-hidden": true, className: "vb-dock-label surface-popover rounded-full px-3.5 py-2 text-sm font-medium text-fg", children: label ?? t("messageUs") }), _jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", "data-track": provider, "aria-label": `${t("messageUsOn", { network })}, ${t("opensInNewTab").replace(/[()]/g, "")}`, className: "vb-dock-button inline-flex size-[52px] shrink-0 items-center justify-center rounded-full bg-fg text-scene transition-opacity hover:opacity-90 focus-ring", children: _jsx(BrandIcon, { name: provider, className: "size-6" }) })] })) : null, showBar ? (_jsxs("nav", { "aria-label": t("contactActions"), className: cn("vb-dock-bar surface-bar border-t border-line", variant === "both" && "vb-dock-mobile"), children: [hoursIsland && !showFab ? _jsx("p", { className: "px-4 pt-2 text-center text-xs text-fg-muted empty:hidden", children: hoursIsland }) : null, _jsx("ul", { className: "grid", style: { gridTemplateColumns: `repeat(${actions.length}, minmax(0, 1fr))` }, children: actions.map(([a, s]) => (_jsx("li", { children: _jsxs("a", { href: s.href, target: s.external ? "_blank" : undefined, rel: s.external ? "noopener noreferrer" : undefined, "data-track": a, "aria-label": s.aria, className: "flex h-14 flex-col items-center justify-center gap-1 text-[11px] font-medium text-fg transition-colors hover:bg-hover focus-ring", children: [s.icon, _jsx("span", { "aria-hidden": true, children: s.label })] }) }, a))) })] })) : null, !contained && (showFab || showBar) ? _jsx(DockAvoid, {}) : null] }));
|
|
55
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { BlockBaseProps } from "../types.js";
|
|
3
|
+
import type { AddressValue, OpeningHours } from "../schema/types.js";
|
|
4
|
+
import type { RichDoc } from "../schema/rich-doc.js";
|
|
5
|
+
import { type Site2BlockLabels } from "./shared/labels-2.js";
|
|
6
|
+
import { type ContactFieldConfig, type SiteFormAction, type SiteFormState } from "./shared/site-form.js";
|
|
7
|
+
export type ContactFormVariant = "split" | "stacked" | "minimal";
|
|
8
|
+
export interface ContactInfo {
|
|
9
|
+
address?: AddressValue | string;
|
|
10
|
+
/** E.164 ("+902160000000"); shown large and used as the fallback on server errors. */
|
|
11
|
+
phone?: string;
|
|
12
|
+
email?: string;
|
|
13
|
+
/** Opening hours (summarised "Mon–Fri 09:00–18:00") or a free text line. */
|
|
14
|
+
hours?: OpeningHours | string;
|
|
15
|
+
}
|
|
16
|
+
export interface ContactFormProps extends Omit<BlockBaseProps, "variant" | "labels"> {
|
|
17
|
+
/**
|
|
18
|
+
* split: contact details as a typographic list beside the form. stacked: title + form in one
|
|
19
|
+
* 42rem column. minimal: name, contact, message and the button in one row — under a CTA.
|
|
20
|
+
*/
|
|
21
|
+
variant?: ContactFormVariant;
|
|
22
|
+
eyebrow?: React.ReactNode;
|
|
23
|
+
title?: React.ReactNode;
|
|
24
|
+
lead?: React.ReactNode;
|
|
25
|
+
/** 2–8 fields. Default: name, email, message. */
|
|
26
|
+
fields?: ContactFieldConfig[];
|
|
27
|
+
/** The app's server action (`useActionState` signature), or a URL for a plain POST. */
|
|
28
|
+
action?: SiteFormAction | string;
|
|
29
|
+
submitLabel?: string;
|
|
30
|
+
/** Replaces the form after success; focus moves to it. */
|
|
31
|
+
successMessage?: React.ReactNode | RichDoc;
|
|
32
|
+
/** Privacy notice (KVKK requires a linked notice). */
|
|
33
|
+
privacyLink?: {
|
|
34
|
+
href: string;
|
|
35
|
+
label?: string;
|
|
36
|
+
};
|
|
37
|
+
/** A required, never pre-checked "I have read the notice" checkbox. */
|
|
38
|
+
privacyCheckbox?: boolean;
|
|
39
|
+
/** A separate, optional marketing consent checkbox. */
|
|
40
|
+
marketingConsent?: boolean;
|
|
41
|
+
/** Contact details column (`split`). Default true when `info` is given. */
|
|
42
|
+
showInfo?: boolean;
|
|
43
|
+
info?: ContactInfo;
|
|
44
|
+
/** Render a given state (docs, tests, a server-rendered result). */
|
|
45
|
+
initialState?: SiteFormState;
|
|
46
|
+
labels?: Site2BlockLabels;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Contact and quote requests feeding whatever lead store the app uses. Server component around a
|
|
50
|
+
* ~2 KB `useActionState` island: native constraints without JS, the same validation in the
|
|
51
|
+
* browser and in the app's action (`validateContactForm`), honeypot + time trap, an error
|
|
52
|
+
* summary linking to fields, KVKK/GDPR-correct consent boxes.
|
|
53
|
+
*
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <ContactForm variant="split" title="Tell us about the *project*" action={sendLead}
|
|
56
|
+
* fields={[{ name: "name", required: true }, { name: "email", required: true }, { name: "budget", options: ["< $5k", "$5–15k"] }, { name: "message", required: true }]}
|
|
57
|
+
* privacyLink={{ href: "/privacy" }} privacyCheckbox info={{ phone: "+902160000000", email: "hello@vamos.ist" }} />
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function ContactForm({ variant, eyebrow, title, lead, fields, action, submitLabel, successMessage, privacyLink, privacyCheckbox, marketingConsent, showInfo, info, initialState, id, anchor, theme, headingLevel, className, labels, locale, components, editMode, }: ContactFormProps): React.JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn2 as cn } from "./shared/kit-2.js";
|
|
3
|
+
import { Section, Container } from "../section.js";
|
|
4
|
+
import { SectionHeader } from "../section-header.js";
|
|
5
|
+
import { RichText } from "../rich-text.js";
|
|
6
|
+
import { labelTemplates, site2Text } from "./shared/labels-2.js";
|
|
7
|
+
import { addressLines, fieldAttr, prettyPhone, telHref, useBlockIds2 } from "./shared/kit-2.js";
|
|
8
|
+
import { contactFieldLabel } from "./shared/site-form.js";
|
|
9
|
+
import { ContactFormIsland } from "./shared/contact-form-island.js";
|
|
10
|
+
import { contactIslandLabelKeys } from "./shared/island-keys.js";
|
|
11
|
+
import { summarizeHours } from "./shared/opening-hours.js";
|
|
12
|
+
const DEFAULT_FIELDS = [
|
|
13
|
+
{ name: "name", required: true },
|
|
14
|
+
{ name: "email", required: true },
|
|
15
|
+
{ name: "message", required: true },
|
|
16
|
+
];
|
|
17
|
+
const isRichDoc = (v) => !!v && typeof v === "object" && v.type === "doc";
|
|
18
|
+
/**
|
|
19
|
+
* Contact and quote requests feeding whatever lead store the app uses. Server component around a
|
|
20
|
+
* ~2 KB `useActionState` island: native constraints without JS, the same validation in the
|
|
21
|
+
* browser and in the app's action (`validateContactForm`), honeypot + time trap, an error
|
|
22
|
+
* summary linking to fields, KVKK/GDPR-correct consent boxes.
|
|
23
|
+
*
|
|
24
|
+
* ```tsx
|
|
25
|
+
* <ContactForm variant="split" title="Tell us about the *project*" action={sendLead}
|
|
26
|
+
* fields={[{ name: "name", required: true }, { name: "email", required: true }, { name: "budget", options: ["< $5k", "$5–15k"] }, { name: "message", required: true }]}
|
|
27
|
+
* privacyLink={{ href: "/privacy" }} privacyCheckbox info={{ phone: "+902160000000", email: "hello@vamos.ist" }} />
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function ContactForm({ variant = "split", eyebrow, title, lead, fields = DEFAULT_FIELDS, action, submitLabel, successMessage, privacyLink, privacyCheckbox, marketingConsent, showInfo, info, initialState, id, anchor, theme, headingLevel = 2, className, labels, locale = "en-US", components, editMode, }) {
|
|
31
|
+
const t = site2Text(labels, locale);
|
|
32
|
+
const { base, headingId } = useBlockIds2(id, "contact");
|
|
33
|
+
const resolved = fields.slice(0, 8).map((f) => ({ ...f, label: contactFieldLabel(f, labels) }));
|
|
34
|
+
const minimal = variant === "minimal";
|
|
35
|
+
const islandFields = minimal ? resolved.filter((f) => f.name === "name" || f.name === "email" || f.name === "phone" || f.name === "message").slice(0, 3) : resolved;
|
|
36
|
+
const split = variant === "split" && (showInfo ?? !!info) && info;
|
|
37
|
+
const form = (_jsx(ContactFormIsland, { action: action, fields: islandFields, labels: labelTemplates(labels, contactIslandLabelKeys), locale: locale, layout: variant, submitLabel: submitLabel, successMessage: isRichDoc(successMessage) ? _jsx(RichText, { doc: successMessage, components: components, labels: labels, locale: locale }) : successMessage, privacy: privacyLink ? { href: privacyLink.href, label: privacyLink.label, checkbox: privacyCheckbox } : undefined, marketingConsent: marketingConsent, fallbackPhone: info?.phone ? { href: telHref(info.phone), label: prettyPhone(info.phone) } : undefined, initialState: initialState, idBase: base }));
|
|
38
|
+
const header = title || eyebrow || lead ? _jsx(SectionHeader, { eyebrow: eyebrow, title: title, lead: lead, headingId: headingId, headingLevel: headingLevel, size: minimal ? "m" : "m", editMode: editMode, labels: labels, locale: locale }) : null;
|
|
39
|
+
return (_jsx(Section, { theme: theme, anchor: anchor, headingId: title ? headingId : undefined, blockId: id, blockType: "contact-form", editMode: editMode, className: cn("vb-contact", className), "data-variant": variant, children: split ? (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-14 @4xl:grid-cols-12", children: [_jsxs("div", { className: "flex flex-col gap-10 @4xl:col-span-5", children: [header, _jsx(InfoList, { info: info, t: t, locale: locale, editMode: editMode })] }), _jsx("div", { className: "@4xl:col-span-6 @4xl:col-start-7 @4xl:pt-2", children: form })] })) : (_jsxs(Container, { size: minimal ? "content" : "prose", className: cn("flex flex-col", minimal ? "gap-8" : "gap-10"), children: [header, form] })) }));
|
|
40
|
+
}
|
|
41
|
+
function InfoList({ info, t, locale, editMode }) {
|
|
42
|
+
const hours = typeof info.hours === "object" ? summarizeHours(info.hours, locale) : undefined;
|
|
43
|
+
const linkClass = "text-fg underline decoration-line underline-offset-[0.25em] transition-colors hover:decoration-current focus-ring rounded-[2px]";
|
|
44
|
+
return (_jsxs("dl", { className: "flex flex-col border-t border-line", children: [info.phone ? (_jsxs("div", { className: "flex flex-col gap-2 border-b border-line py-5", children: [_jsx("dt", { className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", children: t("phone") }), _jsx("dd", { ...fieldAttr(editMode, "info.phone"), children: _jsx("a", { href: telHref(info.phone), className: "font-display text-display-m tabular text-fg transition-colors hover:text-accent-ink focus-ring rounded-[2px]", "data-track": "call", children: prettyPhone(info.phone) }) })] })) : null, info.email ? (_jsxs("div", { className: "flex flex-col gap-2 border-b border-line py-5", children: [_jsx("dt", { className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", children: t("email") }), _jsx("dd", { children: _jsx("a", { href: `mailto:${info.email}`, className: cn(linkClass, "text-lead"), "data-track": "email", children: info.email }) })] })) : null, info.address ? (_jsxs("div", { className: "flex flex-col gap-2 border-b border-line py-5", children: [_jsx("dt", { className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", children: t("address") }), _jsx("dd", { className: "not-italic text-fg", children: _jsx("address", { className: "not-italic", children: (typeof info.address === "string" ? info.address.split("\n") : addressLines(info.address, { locale })).map((l, i) => (_jsx("span", { className: "block", children: l }, i))) }) })] })) : null, info.hours ? (_jsxs("div", { className: "flex flex-col gap-2 border-b border-line py-5", children: [_jsx("dt", { className: "font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", children: t("hours") }), _jsx("dd", { className: "text-fg", children: hours ? (_jsx("ul", { className: "flex flex-col gap-1", children: hours.map((h, i) => (_jsxs("li", { className: "flex justify-between gap-6 tabular", children: [_jsx("span", { children: h.days }), _jsx("span", { className: h.closed ? "text-fg-subtle" : undefined, children: h.closed ? t("closedDay") : h.text })] }, i))) })) : info.hours })] })) : null] }));
|
|
45
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type BookingField = "date" | "time" | "guests" | "service";
|
|
3
|
+
export type BookingWeekday = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
|
|
4
|
+
export interface CtaBookingStrings {
|
|
5
|
+
date: string;
|
|
6
|
+
time: string;
|
|
7
|
+
guests: string;
|
|
8
|
+
service: string;
|
|
9
|
+
guestsCount: string;
|
|
10
|
+
submit: string;
|
|
11
|
+
opensWhatsApp: string;
|
|
12
|
+
closedOn: string;
|
|
13
|
+
message: string;
|
|
14
|
+
messageService: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CtaBookingProps {
|
|
17
|
+
provider: "whatsapp" | "url";
|
|
18
|
+
/** whatsapp: digits only (`902160000000`). url: the booking page that receives the fields as query params. */
|
|
19
|
+
target: string;
|
|
20
|
+
fields: BookingField[];
|
|
21
|
+
services?: string[];
|
|
22
|
+
/** Selectable times ("18:00"…). Default every 30 min from 12:00 to 22:00. */
|
|
23
|
+
times?: string[];
|
|
24
|
+
/** Largest party size. Default 8. */
|
|
25
|
+
maxGuests?: number;
|
|
26
|
+
/** Weekdays the business is closed (date picks on these are refused). */
|
|
27
|
+
closedDays?: BookingWeekday[];
|
|
28
|
+
/** IANA zone of the business (for "today"). */
|
|
29
|
+
timeZone?: string;
|
|
30
|
+
locale: string;
|
|
31
|
+
strings: CtaBookingStrings;
|
|
32
|
+
/** No-JS fallback text sent to WhatsApp. */
|
|
33
|
+
fallbackMessage: string;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
/** Today as `YYYY-MM-DD` in the business's time zone (never toISOString). */
|
|
37
|
+
export declare function todayIn(timeZone?: string, now?: Date): string;
|
|
38
|
+
/**
|
|
39
|
+
* Booking bar island of the CTA `booking` variant (~2 KB). Native date/select fields; on submit
|
|
40
|
+
* it builds a prefilled WhatsApp message (Intl-formatted date and time) or sends the fields to a
|
|
41
|
+
* booking URL. Without JS the form still posts to the same target.
|
|
42
|
+
*/
|
|
43
|
+
export declare function CtaBooking({ provider, target, fields, services, times, maxGuests, closedDays, timeZone, locale, strings, fallbackMessage, className }: CtaBookingProps): React.JSX.Element;
|