@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,56 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn2 as cn } from "./kit-2.js";
|
|
3
|
+
const PATHS = {
|
|
4
|
+
whatsapp: (_jsx("path", { d: "M17.47 14.38c-.3-.15-1.76-.87-2.03-.97-.27-.1-.47-.15-.67.15-.2.3-.77.97-.94 1.16-.17.2-.35.22-.64.07-.3-.15-1.26-.46-2.39-1.47-.88-.79-1.48-1.76-1.65-2.06-.17-.3-.02-.46.13-.6.13-.14.3-.35.45-.52.15-.18.2-.3.3-.5.1-.2.05-.37-.03-.52-.07-.15-.67-1.61-.92-2.2-.24-.58-.49-.5-.67-.51h-.57c-.2 0-.52.07-.79.37-.27.3-1.04 1.02-1.04 2.48 0 1.46 1.07 2.88 1.21 3.07.15.2 2.1 3.2 5.08 4.49.71.3 1.26.49 1.7.63.71.22 1.36.19 1.87.12.57-.09 1.76-.72 2-1.42.25-.69.25-1.29.18-1.41-.08-.13-.28-.2-.57-.35m-5.42 7.4h-.01a9.87 9.87 0 0 1-5.03-1.38l-.36-.21-3.74.98 1-3.65-.24-.37a9.86 9.86 0 0 1-1.51-5.26c0-5.45 4.44-9.88 9.89-9.88 2.64 0 5.12 1.03 6.99 2.9a9.82 9.82 0 0 1 2.89 6.99c0 5.45-4.44 9.88-9.88 9.88m8.41-18.3A11.81 11.81 0 0 0 12.05 0C5.5 0 .16 5.34.16 11.89c0 2.1.55 4.14 1.59 5.95L.06 24l6.3-1.65a11.88 11.88 0 0 0 5.68 1.45h.01c6.55 0 11.89-5.34 11.89-11.89a11.82 11.82 0 0 0-3.48-8.41Z" })),
|
|
5
|
+
instagram: (_jsx("path", { fillRule: "evenodd", d: "M7.5 2h9A5.5 5.5 0 0 1 22 7.5v9a5.5 5.5 0 0 1-5.5 5.5h-9A5.5 5.5 0 0 1 2 16.5v-9A5.5 5.5 0 0 1 7.5 2Zm0 2A3.5 3.5 0 0 0 4 7.5v9A3.5 3.5 0 0 0 7.5 20h9a3.5 3.5 0 0 0 3.5-3.5v-9A3.5 3.5 0 0 0 16.5 4h-9ZM12 7a5 5 0 1 1 0 10 5 5 0 0 1 0-10Zm0 2a3 3 0 1 0 0 6 3 3 0 0 0 0-6Zm5.25-3.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Z" })),
|
|
6
|
+
facebook: _jsx("path", { d: "M13.5 22v-8.2h2.75l.42-3.2H13.5V8.56c0-.93.26-1.56 1.59-1.56h1.7V4.14A22.6 22.6 0 0 0 14.31 4C11.86 4 10.2 5.49 10.2 8.24v2.36H7.44v3.2h2.76V22h3.3Z" }),
|
|
7
|
+
linkedin: (_jsx("path", { d: "M5.34 3A2.17 2.17 0 1 1 5.33 7.35 2.17 2.17 0 0 1 5.34 3ZM3.46 8.98h3.75V21H3.46V8.98ZM9.56 8.98h3.6v1.64h.05c.5-.95 1.72-1.95 3.55-1.95 3.8 0 4.5 2.5 4.5 5.75V21h-3.74v-5.84c0-1.4-.03-3.19-1.94-3.19-1.95 0-2.25 1.52-2.25 3.09V21H9.56V8.98Z" })),
|
|
8
|
+
x: _jsx("path", { d: "M17.75 3h3.07l-6.7 7.66L22 21h-6.17l-4.83-6.32L5.47 21H2.4l7.17-8.2L2 3h6.33l4.37 5.78L17.75 3Zm-1.08 16.17h1.7L7.4 4.73H5.58l11.09 14.44Z" }),
|
|
9
|
+
youtube: (_jsx("path", { fillRule: "evenodd", d: "M22.54 7.2a2.76 2.76 0 0 0-1.94-1.96C18.88 4.78 12 4.78 12 4.78s-6.88 0-8.6.46A2.76 2.76 0 0 0 1.46 7.2C1 8.93 1 12.5 1 12.5s0 3.57.46 5.3a2.76 2.76 0 0 0 1.94 1.96c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.76 2.76 0 0 0 1.94-1.96c.46-1.73.46-5.3.46-5.3s0-3.57-.46-5.3ZM9.75 15.77V9.23l5.75 3.27-5.75 3.27Z" })),
|
|
10
|
+
tiktok: _jsx("path", { d: "M16.6 2h-3.3v13.17a2.85 2.85 0 1 1-2.85-2.85c.3 0 .59.05.86.13V9.1a6.19 6.19 0 1 0 5.29 6.12V8.68a7.6 7.6 0 0 0 4.4 1.4V6.77A4.4 4.4 0 0 1 16.6 2.4V2Z" }),
|
|
11
|
+
telegram: (_jsx("path", { d: "M21.94 4.3 18.8 19.13c-.24 1.05-.86 1.31-1.74.82l-4.8-3.54-2.32 2.23c-.26.26-.47.47-.97.47l.35-4.89 8.9-8.04c.39-.35-.08-.54-.6-.19l-11 6.93-4.74-1.48c-1.03-.32-1.05-1.03.21-1.52L20.6 2.82c.86-.32 1.6.19 1.34 1.48Z" })),
|
|
12
|
+
messenger: (_jsx("path", { d: "M12 2C6.36 2 2 6.13 2 11.7c0 2.91 1.2 5.43 3.14 7.17.17.15.27.36.27.58l.06 1.78a.8.8 0 0 0 1.12.71l1.98-.88a.8.8 0 0 1 .54-.04c.91.25 1.87.38 2.89.38 5.64 0 10-4.13 10-9.7S17.64 2 12 2Zm6 7.46-2.94 4.66a1.5 1.5 0 0 1-2.17.4l-2.34-1.75a.6.6 0 0 0-.72 0l-3.16 2.4c-.42.32-.97-.18-.69-.63l2.94-4.66a1.5 1.5 0 0 1 2.17-.4l2.34 1.75a.6.6 0 0 0 .72 0l3.16-2.4c.42-.32.97.18.69.63Z" })),
|
|
13
|
+
"google-maps": (_jsx("path", { fillRule: "evenodd", d: "M12 1.5a7.5 7.5 0 0 0-7.5 7.5c0 5.4 6.27 12.4 6.84 13.03a.9.9 0 0 0 1.32 0C13.23 21.4 19.5 14.4 19.5 9A7.5 7.5 0 0 0 12 1.5Zm0 4.5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z" })),
|
|
14
|
+
"apple-maps": (_jsx("path", { fillRule: "evenodd", d: "M6 2h12a4 4 0 0 1 4 4v12a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4Zm10.9 4.1-9.6 4.1c-.6.26-.5 1.13.13 1.25l3.82.73.73 3.82c.12.64 1 .73 1.25.13l4.1-9.6a.33.33 0 0 0-.43-.43Z" })),
|
|
15
|
+
"yandex-maps": (_jsx("path", { fillRule: "evenodd", d: "M12 1.5a7.5 7.5 0 0 0-7.5 7.5c0 5.4 6.27 12.4 6.84 13.03a.9.9 0 0 0 1.32 0C13.23 21.4 19.5 14.4 19.5 9A7.5 7.5 0 0 0 12 1.5ZM10.4 5h1.9c1.9 0 3 .9 3 2.6 0 1.2-.6 2-1.6 2.4l1.9 3.6h-1.8l-1.7-3.3h-.2v3.3h-1.5V5Zm1.5 1.25v2.5h.4c.9 0 1.4-.4 1.4-1.25 0-.85-.5-1.25-1.4-1.25h-.4Z" })),
|
|
16
|
+
waze: (_jsx("path", { fillRule: "evenodd", d: "M12.5 2.5c5 0 9 3.6 9 8.2 0 2.9-1.6 5.3-4 6.8a2 2 0 1 1-3.9.9h-2.6a2 2 0 0 1-3.94-.35A7.6 7.6 0 0 1 3.5 15c.9-.3 1.5-1.1 1.5-2.3v-2C5 6.1 8.3 2.5 12.5 2.5Zm-2.25 6.25a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm4.5 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm-5 3.6a.6.6 0 0 0-.5.9 3.6 3.6 0 0 0 6.1 0 .6.6 0 0 0-1-.65 2.4 2.4 0 0 1-4.1 0 .6.6 0 0 0-.5-.25Z" })),
|
|
17
|
+
email: _jsx("path", { fillRule: "evenodd", d: "M3.5 4h17A1.5 1.5 0 0 1 22 5.5v13a1.5 1.5 0 0 1-1.5 1.5h-17A1.5 1.5 0 0 1 2 18.5v-13A1.5 1.5 0 0 1 3.5 4Zm.5 2.3V18h16V6.3l-7.4 5.55a1 1 0 0 1-1.2 0L4 6.3ZM5.7 6l6.3 4.72L18.3 6H5.7Z" }),
|
|
18
|
+
phone: (_jsx("path", { d: "M7.2 2.5c.5 0 .95.32 1.1.8l1.2 3.6c.14.43 0 .9-.34 1.19L7.6 9.4a13 13 0 0 0 7 7l1.3-1.56c.29-.35.76-.48 1.19-.34l3.6 1.2c.48.15.8.6.8 1.1v3.2c0 .64-.52 1.17-1.17 1.16C10.9 21.06 2.94 13.1 2.84 3.67 2.83 3.02 3.36 2.5 4 2.5h3.2Z" })),
|
|
19
|
+
};
|
|
20
|
+
/** Human names for networks ("LinkedIn", "Google Maps") — for aria-labels and link text. */
|
|
21
|
+
export const BRAND_NAMES = {
|
|
22
|
+
whatsapp: "WhatsApp",
|
|
23
|
+
instagram: "Instagram",
|
|
24
|
+
facebook: "Facebook",
|
|
25
|
+
linkedin: "LinkedIn",
|
|
26
|
+
x: "X",
|
|
27
|
+
youtube: "YouTube",
|
|
28
|
+
tiktok: "TikTok",
|
|
29
|
+
telegram: "Telegram",
|
|
30
|
+
messenger: "Messenger",
|
|
31
|
+
"google-maps": "Google Maps",
|
|
32
|
+
"apple-maps": "Apple Maps",
|
|
33
|
+
"yandex-maps": "Yandex Maps",
|
|
34
|
+
waze: "Waze",
|
|
35
|
+
email: "Email",
|
|
36
|
+
phone: "Phone",
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A brand mark (WhatsApp, Instagram, LinkedIn, X, YouTube, TikTok, Telegram, maps providers…).
|
|
40
|
+
* Monochrome `currentColor`, 20px by default, never boxed in a coloured tile (D6-3).
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* <a href="https://instagram.com/meyhane" aria-label="Instagram"><BrandIcon name="instagram" /></a>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function BrandIcon({ name, title, className, ...props }) {
|
|
47
|
+
const path = PATHS[name];
|
|
48
|
+
if (!path)
|
|
49
|
+
return null;
|
|
50
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", role: title ? "img" : undefined, "aria-hidden": title ? undefined : true, "aria-label": title, focusable: "false", className: cn("size-5 shrink-0", className), ...props, children: path }));
|
|
51
|
+
}
|
|
52
|
+
/** `https://wa.me/<digits>?text=<encoded>` from an E.164 number. */
|
|
53
|
+
export function waLink(e164, text) {
|
|
54
|
+
const digits = e164.replace(/\D/g, "");
|
|
55
|
+
return `https://wa.me/${digits}${text ? `?text=${encodeURIComponent(text)}` : ""}`;
|
|
56
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ConsentCategory } from "./consent.js";
|
|
3
|
+
export interface ConsentGateProps {
|
|
4
|
+
/** The iframe URL loaded after consent or a click (maps, YouTube, Vimeo, Calendly). */
|
|
5
|
+
src: string;
|
|
6
|
+
/** Iframe `title` (required for screen readers): "Map of Meyhane Rasimpaşa". */
|
|
7
|
+
title: string;
|
|
8
|
+
/** Consent category that loads the embed automatically. Default `"functional"`. */
|
|
9
|
+
category?: ConsentCategory;
|
|
10
|
+
/** Button text: "Load map". */
|
|
11
|
+
loadLabel: string;
|
|
12
|
+
/** One line under the button: "The map loads from Google Maps, which may set cookies." */
|
|
13
|
+
notice?: React.ReactNode;
|
|
14
|
+
/** Offer "Always load maps" — grants `category` for the whole site. */
|
|
15
|
+
rememberLabel?: string;
|
|
16
|
+
/** CSS aspect-ratio of the frame. Default `"4 / 3"`. */
|
|
17
|
+
aspect?: string;
|
|
18
|
+
/** Iframe `allow` (video: "autoplay; encrypted-media; picture-in-picture"). */
|
|
19
|
+
allow?: string;
|
|
20
|
+
/** Load immediately (the user already clicked something that means "show it"). */
|
|
21
|
+
defaultLoaded?: boolean;
|
|
22
|
+
/** Banner version; an older stored answer doesn't count. */
|
|
23
|
+
version?: number;
|
|
24
|
+
/** The static preview (an image). Painted under the button, decorative. */
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
/** Classes for the facade button. */
|
|
28
|
+
buttonClassName?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Facade for third-party embeds: a static preview with one button. The iframe loads only after
|
|
32
|
+
* a click or when the visitor has already granted `category` — never before (privacy law and
|
|
33
|
+
* performance). ~0.5 KB.
|
|
34
|
+
*
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <ConsentGate src="https://www.google.com/maps?q=…&output=embed" title="Map of Meyhane Rasimpaşa" loadLabel="Load map">
|
|
37
|
+
* <BlockImage src="/map-static.png" decorative aspect="4:3" />
|
|
38
|
+
* </ConsentGate>
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function ConsentGate({ src, title, category, loadLabel, notice, rememberLabel, aspect, allow, defaultLoaded, version, children, className, buttonClassName, }: ConsentGateProps): React.JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn2 as cn } from "./kit-2.js";
|
|
5
|
+
import { getConsent, onConsent, readConsent, writeConsent } from "./consent.js";
|
|
6
|
+
/**
|
|
7
|
+
* Facade for third-party embeds: a static preview with one button. The iframe loads only after
|
|
8
|
+
* a click or when the visitor has already granted `category` — never before (privacy law and
|
|
9
|
+
* performance). ~0.5 KB.
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <ConsentGate src="https://www.google.com/maps?q=…&output=embed" title="Map of Meyhane Rasimpaşa" loadLabel="Load map">
|
|
13
|
+
* <BlockImage src="/map-static.png" decorative aspect="4:3" />
|
|
14
|
+
* </ConsentGate>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function ConsentGate({ src, title, category = "functional", loadLabel, notice, rememberLabel, aspect = "4 / 3", allow, defaultLoaded = false, version, children, className, buttonClassName, }) {
|
|
18
|
+
const [loaded, setLoaded] = React.useState(defaultLoaded);
|
|
19
|
+
const [remember, setRemember] = React.useState(false);
|
|
20
|
+
const frameRef = React.useRef(null);
|
|
21
|
+
const focusOnLoad = React.useRef(false);
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (loaded)
|
|
24
|
+
return;
|
|
25
|
+
if (getConsent(category, version)) {
|
|
26
|
+
setLoaded(true);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return onConsent(category, () => setLoaded(true));
|
|
30
|
+
}, [category, version, loaded]);
|
|
31
|
+
React.useEffect(() => {
|
|
32
|
+
if (loaded && focusOnLoad.current)
|
|
33
|
+
frameRef.current?.focus();
|
|
34
|
+
}, [loaded]);
|
|
35
|
+
return (_jsx("div", { "data-consent-gate": "", "data-loaded": loaded ? "" : undefined, className: cn("vb-gate relative overflow-hidden rounded-ui bg-surface-2", className), style: { aspectRatio: aspect }, children: loaded ? (_jsx("iframe", { ref: frameRef, src: src, title: title, allow: allow, loading: "lazy", referrerPolicy: "strict-origin-when-cross-origin", allowFullScreen: true, className: "absolute inset-0 size-full border-0" })) : (_jsxs(_Fragment, { children: [children ? (_jsx("div", { "aria-hidden": true, className: "vb-gate-preview absolute inset-0 [&_.vb-image]:size-full", children: children })) : null, _jsxs("div", { className: "absolute inset-x-0 bottom-0 flex flex-col items-start gap-2 p-4 @2xl:p-5", children: [_jsx("button", { type: "button", onClick: () => {
|
|
36
|
+
if (remember) {
|
|
37
|
+
const prev = readConsent();
|
|
38
|
+
writeConsent({ functional: prev?.c.functional === 1, analytics: prev?.c.analytics === 1, marketing: prev?.c.marketing === 1, [category]: true }, version ?? prev?.v ?? 1);
|
|
39
|
+
}
|
|
40
|
+
focusOnLoad.current = true;
|
|
41
|
+
setLoaded(true);
|
|
42
|
+
}, className: cn("surface-popover inline-flex h-11 items-center gap-2 rounded-ui px-4 text-sm font-medium text-fg transition-colors hover:bg-hover focus-ring", buttonClassName), children: loadLabel }), notice || rememberLabel ? (_jsxs("div", { className: "vb-gate-note flex max-w-[44ch] flex-col gap-1.5 rounded-ui-sm px-2 py-1 text-xs text-fg-muted", children: [notice ? _jsx("p", { children: notice }) : null, rememberLabel ? (_jsxs("label", { className: "inline-flex cursor-pointer items-center gap-2 text-fg", children: [_jsx("input", { type: "checkbox", checked: remember, onChange: (e) => setRemember(e.target.checked), className: "vb-check size-3.5" }), rememberLabel] })) : null] })) : null] })] })) }));
|
|
43
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ConsentCategory, type ConsentRecord } from "./consent.js";
|
|
3
|
+
import type { ConsentLabels } from "./island-keys.js";
|
|
4
|
+
export interface ConsentBannerIslandProps {
|
|
5
|
+
variant: "bar" | "box";
|
|
6
|
+
/** Server-rendered notice text. */
|
|
7
|
+
text: React.ReactNode;
|
|
8
|
+
policyLink?: {
|
|
9
|
+
href: string;
|
|
10
|
+
label: string;
|
|
11
|
+
};
|
|
12
|
+
categories: ConsentCategory[];
|
|
13
|
+
version: number;
|
|
14
|
+
position: "bottom" | "bottom-start";
|
|
15
|
+
regionMode: "opt-in" | "notice";
|
|
16
|
+
labels: ConsentLabels;
|
|
17
|
+
/** Render inside the parent (docs previews) instead of fixed to the viewport. */
|
|
18
|
+
contained?: boolean;
|
|
19
|
+
/** Show even when a choice is stored (previews). */
|
|
20
|
+
forceShow?: boolean;
|
|
21
|
+
/** Start with preferences open (previews). */
|
|
22
|
+
defaultPreferencesOpen?: boolean;
|
|
23
|
+
/** Called with every record — for a server-side proof log. Client prop only. */
|
|
24
|
+
onRecord?: (record: ConsentRecord) => void | Promise<void>;
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The interactive part of the Cookie / consent banner (~3 KB). Not modal: a labelled region that
|
|
29
|
+
* never blocks the page or steals focus. "Reject all" and "Accept all" are equal secondary
|
|
30
|
+
* buttons on the first layer; preferences open in a Dialog with one Switch per category, none
|
|
31
|
+
* pre-checked. Renders nothing until mounted (no non-essential cookies without JS).
|
|
32
|
+
*/
|
|
33
|
+
export declare function ConsentBannerIsland({ variant, text, policyLink, categories, version, position, regionMode, labels, contained, forceShow, defaultPreferencesOpen, onRecord, className, }: ConsentBannerIslandProps): React.JSX.Element;
|
|
34
|
+
/** "Cookie settings" — a button (not a link) that reopens the preferences. For the footer. */
|
|
35
|
+
export declare function ConsentSettingsButton({ children, className }: {
|
|
36
|
+
children: React.ReactNode;
|
|
37
|
+
className?: string;
|
|
38
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn2 as cn } from "./kit-2.js";
|
|
5
|
+
import { Button } from "../../../components/button.js";
|
|
6
|
+
import { Switch } from "../../../components/switch.js";
|
|
7
|
+
import { Dialog, DialogBody, DialogContent, DialogFooter, DialogHeader } from "../../../components/dialog.js";
|
|
8
|
+
import { CONSENT_OPEN_EVENT, readConsent, writeConsent, openConsentPreferences } from "./consent.js";
|
|
9
|
+
const CAT_LABEL = {
|
|
10
|
+
necessary: ["catNecessary", "catNecessaryHint"],
|
|
11
|
+
functional: ["catFunctional", "catFunctionalHint"],
|
|
12
|
+
analytics: ["catAnalytics", "catAnalyticsHint"],
|
|
13
|
+
marketing: ["catMarketing", "catMarketingHint"],
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The interactive part of the Cookie / consent banner (~3 KB). Not modal: a labelled region that
|
|
17
|
+
* never blocks the page or steals focus. "Reject all" and "Accept all" are equal secondary
|
|
18
|
+
* buttons on the first layer; preferences open in a Dialog with one Switch per category, none
|
|
19
|
+
* pre-checked. Renders nothing until mounted (no non-essential cookies without JS).
|
|
20
|
+
*/
|
|
21
|
+
export function ConsentBannerIsland({ variant, text, policyLink, categories, version, position, regionMode, labels, contained, forceShow, defaultPreferencesOpen, onRecord, className, }) {
|
|
22
|
+
const [visible, setVisible] = React.useState(false);
|
|
23
|
+
const [prefsOpen, setPrefsOpen] = React.useState(!!defaultPreferencesOpen);
|
|
24
|
+
const optional = categories.filter((c) => c !== "necessary");
|
|
25
|
+
const [choices, setChoices] = React.useState({});
|
|
26
|
+
const titleId = React.useId();
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
const stored = readConsent(version);
|
|
29
|
+
if (stored)
|
|
30
|
+
setChoices({ functional: !!stored.c.functional, analytics: !!stored.c.analytics, marketing: !!stored.c.marketing });
|
|
31
|
+
setVisible(forceShow || !stored);
|
|
32
|
+
const open = () => {
|
|
33
|
+
const r = readConsent(version);
|
|
34
|
+
if (r)
|
|
35
|
+
setChoices({ functional: !!r.c.functional, analytics: !!r.c.analytics, marketing: !!r.c.marketing });
|
|
36
|
+
setPrefsOpen(true);
|
|
37
|
+
};
|
|
38
|
+
window.addEventListener(CONSENT_OPEN_EVENT, open);
|
|
39
|
+
return () => window.removeEventListener(CONSENT_OPEN_EVENT, open);
|
|
40
|
+
}, [version, forceShow]);
|
|
41
|
+
const save = (c) => {
|
|
42
|
+
const record = writeConsent(c, version);
|
|
43
|
+
void onRecord?.(record);
|
|
44
|
+
setChoices(c);
|
|
45
|
+
setPrefsOpen(false);
|
|
46
|
+
if (!forceShow)
|
|
47
|
+
setVisible(false);
|
|
48
|
+
};
|
|
49
|
+
const all = (on) => Object.fromEntries(optional.map((k) => [k, on]));
|
|
50
|
+
const preferences = (_jsx(Dialog, { open: prefsOpen, onOpenChange: setPrefsOpen, children: _jsxs(DialogContent, { size: "md", children: [_jsx(DialogHeader, { title: labels.cookiePreferences, description: labels.cookiePreferencesLead }), _jsxs(DialogBody, { children: [_jsx("ul", { className: "flex flex-col", children: categories.map((cat) => {
|
|
51
|
+
const [name, hint] = CAT_LABEL[cat];
|
|
52
|
+
const locked = cat === "necessary";
|
|
53
|
+
return (_jsx("li", { className: "border-b border-line py-4 last:border-b-0", children: _jsx(Switch, { label: labels[name], description: locked ? `${labels[hint]} ${labels.alwaysOn}.` : labels[hint], labelPosition: "start", checked: locked ? true : !!choices[cat], disabled: locked, onCheckedChange: (v) => setChoices((p) => ({ ...p, [cat]: v })) }) }, cat));
|
|
54
|
+
}) }), policyLink ? (_jsx("p", { className: "mt-4 text-small text-fg-muted", children: _jsx("a", { href: policyLink.href, className: "font-medium text-fg underline decoration-line underline-offset-[0.25em] hover:decoration-current focus-ring rounded-[2px]", children: policyLink.label }) })) : null] }), _jsxs(DialogFooter, { align: "between", children: [_jsx(Button, { variant: "secondary", onClick: () => save(all(false)), children: labels.rejectAll }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "secondary", onClick: () => save(all(true)), children: labels.acceptAll }), _jsx(Button, { variant: "solid", onClick: () => save(choices), children: labels.savePreferences })] })] })] }) }));
|
|
55
|
+
if (!visible)
|
|
56
|
+
return preferences;
|
|
57
|
+
const box = variant === "box";
|
|
58
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { role: "region", "aria-labelledby": titleId, "data-consent-banner": "", "data-variant": variant, "data-position": position, "data-contained": contained ? "" : undefined, className: cn("vb-consent surface-popover text-small text-fg", box ? "vb-consent-box rounded-ui-lg p-5" : "vb-consent-bar", className), children: _jsx("div", { className: "@container", children: _jsxs("div", { className: cn(box ? "flex flex-col gap-4" : "vb-container flex flex-col gap-4 py-4 @3xl:flex-row @3xl:items-center @3xl:justify-between @3xl:gap-10"), children: [_jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [_jsx("p", { id: titleId, className: cn(box ? "text-body font-semibold text-fg" : "sr-only"), children: box ? labels.cookies : labels.cookieConsent }), _jsxs("div", { className: "max-w-[72ch] text-fg-muted text-pretty [&_a]:font-medium [&_a]:text-fg [&_a]:underline [&_a]:underline-offset-[0.25em]", children: [text, policyLink ? (_jsxs(_Fragment, { children: [" ", _jsx("a", { href: policyLink.href, className: "focus-ring rounded-[2px]", children: policyLink.label })] })) : null] })] }), _jsxs("div", { className: cn("flex shrink-0 flex-wrap items-center gap-2", box && "flex-col items-stretch"), children: [regionMode === "opt-in" ? (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "secondary", onClick: () => save(all(false)), className: cn(box && "w-full"), children: labels.rejectAll }), _jsx(Button, { variant: "secondary", onClick: () => save(all(true)), className: cn(box && "w-full"), children: labels.acceptAll })] })) : (_jsx(Button, { variant: "secondary", onClick: () => save(all(true)), className: cn(box && "w-full"), children: labels.acceptAll })), _jsx(Button, { variant: "ghost", onClick: () => setPrefsOpen(true), className: cn("underline decoration-line underline-offset-[0.3em]", box && "w-full"), children: labels.preferences })] })] }) }) }), preferences] }));
|
|
59
|
+
}
|
|
60
|
+
/** "Cookie settings" — a button (not a link) that reopens the preferences. For the footer. */
|
|
61
|
+
export function ConsentSettingsButton({ children, className }) {
|
|
62
|
+
return (_jsx("button", { type: "button", onClick: () => openConsentPreferences(), className: cn("rounded-[2px] underline-offset-[0.25em] hover:underline focus-ring", className), children: children }));
|
|
63
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type ConsentCategory = "necessary" | "functional" | "analytics" | "marketing";
|
|
2
|
+
export type OptionalCategory = Exclude<ConsentCategory, "necessary">;
|
|
3
|
+
export declare const CONSENT_CATEGORIES: readonly ConsentCategory[];
|
|
4
|
+
export declare const CONSENT_COOKIE = "vb_consent";
|
|
5
|
+
/** Fired on `window` after every choice: `detail` is the record. */
|
|
6
|
+
export declare const CONSENT_EVENT = "vb:consent";
|
|
7
|
+
/** Fire on `window` to open the preferences dialog (Footer "Cookie settings"). */
|
|
8
|
+
export declare const CONSENT_OPEN_EVENT = "vb:consent-open";
|
|
9
|
+
export interface ConsentRecord {
|
|
10
|
+
/** Banner version the visitor answered; a newer version asks again. */
|
|
11
|
+
v: number;
|
|
12
|
+
/** Unix seconds of the choice. */
|
|
13
|
+
t: number;
|
|
14
|
+
c: Record<OptionalCategory, 0 | 1>;
|
|
15
|
+
}
|
|
16
|
+
export type ConsentChoices = Partial<Record<OptionalCategory, boolean>>;
|
|
17
|
+
/** Reads the record from a cookie string (`document.cookie` or a request's Cookie header). */
|
|
18
|
+
export declare function parseConsent(cookie: string | undefined | null, name?: string): ConsentRecord | null;
|
|
19
|
+
/** The record as a cookie value. */
|
|
20
|
+
export declare const serializeConsent: (r: ConsentRecord) => string;
|
|
21
|
+
/** The visitor's current record, or null (never answered, or answered an older `version`). */
|
|
22
|
+
export declare function readConsent(version?: number): ConsentRecord | null;
|
|
23
|
+
/** True when `category` may be used now. `necessary` is always true. */
|
|
24
|
+
export declare function getConsent(category: ConsentCategory, version?: number): boolean;
|
|
25
|
+
/** Google Consent Mode v2 signals for a set of choices. */
|
|
26
|
+
export declare function consentModeSignals(c: ConsentChoices | ConsentRecord["c"]): Record<string, "granted" | "denied">;
|
|
27
|
+
/** Saves a choice: cookie, Consent Mode update, `vb:consent` event. Returns the record. */
|
|
28
|
+
export declare function writeConsent(choices: ConsentChoices, version?: number, opts?: {
|
|
29
|
+
days?: number;
|
|
30
|
+
cookieName?: string;
|
|
31
|
+
}): ConsentRecord;
|
|
32
|
+
/** Calls `fn` now (if already granted) and whenever `category` becomes granted. Returns an unsubscribe. */
|
|
33
|
+
export declare function onConsent(category: ConsentCategory, fn: (record: ConsentRecord | null) => void): () => void;
|
|
34
|
+
/** Opens the preferences dialog of the mounted `ConsentBanner`. */
|
|
35
|
+
export declare function openConsentPreferences(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Inline `<head>` snippet: Consent Mode v2 defaults (everything denied except security), then an
|
|
38
|
+
* immediate update from a stored choice, before any Google tag loads.
|
|
39
|
+
*
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <head><script dangerouslySetInnerHTML={{ __html: consentDefaultsScript() }} /></head>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function consentDefaultsScript(opts?: {
|
|
45
|
+
waitForUpdate?: number;
|
|
46
|
+
version?: number;
|
|
47
|
+
regionMode?: "opt-in" | "notice";
|
|
48
|
+
region?: string[];
|
|
49
|
+
}): string;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Consent state — a first-party cookie, a DOM event and Google Consent Mode v2. React-free and
|
|
2
|
+
// server-safe: every DOM access is guarded, `parseConsent` also runs on the server (cookie header).
|
|
3
|
+
//
|
|
4
|
+
// Cookie: vb_consent={"v":3,"t":1762761600,"c":{"functional":1,"analytics":0,"marketing":0}} (6 months)
|
|
5
|
+
export const CONSENT_CATEGORIES = ["necessary", "functional", "analytics", "marketing"];
|
|
6
|
+
export const CONSENT_COOKIE = "vb_consent";
|
|
7
|
+
/** Fired on `window` after every choice: `detail` is the record. */
|
|
8
|
+
export const CONSENT_EVENT = "vb:consent";
|
|
9
|
+
/** Fire on `window` to open the preferences dialog (Footer "Cookie settings"). */
|
|
10
|
+
export const CONSENT_OPEN_EVENT = "vb:consent-open";
|
|
11
|
+
const SIX_MONTHS = 182;
|
|
12
|
+
/** Reads the record from a cookie string (`document.cookie` or a request's Cookie header). */
|
|
13
|
+
export function parseConsent(cookie, name = CONSENT_COOKIE) {
|
|
14
|
+
if (!cookie)
|
|
15
|
+
return null;
|
|
16
|
+
const hit = cookie.split(/;\s*/).find((c) => c.startsWith(`${name}=`));
|
|
17
|
+
if (!hit)
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const raw = JSON.parse(decodeURIComponent(hit.slice(name.length + 1)));
|
|
21
|
+
if (typeof raw.v !== "number" || !raw.c || typeof raw.c !== "object")
|
|
22
|
+
return null;
|
|
23
|
+
const c = raw.c;
|
|
24
|
+
return { v: raw.v, t: Number(raw.t) || 0, c: { functional: c.functional ? 1 : 0, analytics: c.analytics ? 1 : 0, marketing: c.marketing ? 1 : 0 } };
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** The record as a cookie value. */
|
|
31
|
+
export const serializeConsent = (r) => encodeURIComponent(JSON.stringify(r));
|
|
32
|
+
/** The visitor's current record, or null (never answered, or answered an older `version`). */
|
|
33
|
+
export function readConsent(version) {
|
|
34
|
+
if (typeof document === "undefined")
|
|
35
|
+
return null;
|
|
36
|
+
const r = parseConsent(document.cookie);
|
|
37
|
+
if (!r)
|
|
38
|
+
return null;
|
|
39
|
+
if (version !== undefined && r.v < version)
|
|
40
|
+
return null;
|
|
41
|
+
return r;
|
|
42
|
+
}
|
|
43
|
+
/** True when `category` may be used now. `necessary` is always true. */
|
|
44
|
+
export function getConsent(category, version) {
|
|
45
|
+
if (category === "necessary")
|
|
46
|
+
return true;
|
|
47
|
+
return readConsent(version)?.c[category] === 1;
|
|
48
|
+
}
|
|
49
|
+
/** Google Consent Mode v2 signals for a set of choices. */
|
|
50
|
+
export function consentModeSignals(c) {
|
|
51
|
+
const on = (k) => (c[k] ? "granted" : "denied");
|
|
52
|
+
return {
|
|
53
|
+
ad_storage: on("marketing"),
|
|
54
|
+
ad_user_data: on("marketing"),
|
|
55
|
+
ad_personalization: on("marketing"),
|
|
56
|
+
analytics_storage: on("analytics"),
|
|
57
|
+
functionality_storage: on("functional"),
|
|
58
|
+
personalization_storage: on("functional"),
|
|
59
|
+
security_storage: "granted",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Saves a choice: cookie, Consent Mode update, `vb:consent` event. Returns the record. */
|
|
63
|
+
export function writeConsent(choices, version = 1, opts = {}) {
|
|
64
|
+
const record = {
|
|
65
|
+
v: version,
|
|
66
|
+
t: Math.floor(Date.now() / 1000),
|
|
67
|
+
c: { functional: choices.functional ? 1 : 0, analytics: choices.analytics ? 1 : 0, marketing: choices.marketing ? 1 : 0 },
|
|
68
|
+
};
|
|
69
|
+
if (typeof document !== "undefined") {
|
|
70
|
+
const secure = typeof location !== "undefined" && location.protocol === "https:" ? "; secure" : "";
|
|
71
|
+
document.cookie = `${opts.cookieName ?? CONSENT_COOKIE}=${serializeConsent(record)}; max-age=${(opts.days ?? SIX_MONTHS) * 86400}; path=/; samesite=lax${secure}`;
|
|
72
|
+
}
|
|
73
|
+
if (typeof window !== "undefined") {
|
|
74
|
+
const w = window;
|
|
75
|
+
w.gtag?.("consent", "update", consentModeSignals(record.c));
|
|
76
|
+
window.dispatchEvent(new CustomEvent(CONSENT_EVENT, { detail: record }));
|
|
77
|
+
}
|
|
78
|
+
return record;
|
|
79
|
+
}
|
|
80
|
+
/** Calls `fn` now (if already granted) and whenever `category` becomes granted. Returns an unsubscribe. */
|
|
81
|
+
export function onConsent(category, fn) {
|
|
82
|
+
if (typeof window === "undefined")
|
|
83
|
+
return () => { };
|
|
84
|
+
let fired = false;
|
|
85
|
+
const check = (r) => {
|
|
86
|
+
const granted = category === "necessary" || r?.c[category] === 1;
|
|
87
|
+
if (granted && !fired) {
|
|
88
|
+
fired = true;
|
|
89
|
+
fn(r);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
check(readConsent());
|
|
93
|
+
const handler = (e) => check(e.detail ?? readConsent());
|
|
94
|
+
window.addEventListener(CONSENT_EVENT, handler);
|
|
95
|
+
return () => window.removeEventListener(CONSENT_EVENT, handler);
|
|
96
|
+
}
|
|
97
|
+
/** Opens the preferences dialog of the mounted `ConsentBanner`. */
|
|
98
|
+
export function openConsentPreferences() {
|
|
99
|
+
if (typeof window !== "undefined")
|
|
100
|
+
window.dispatchEvent(new Event(CONSENT_OPEN_EVENT));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Inline `<head>` snippet: Consent Mode v2 defaults (everything denied except security), then an
|
|
104
|
+
* immediate update from a stored choice, before any Google tag loads.
|
|
105
|
+
*
|
|
106
|
+
* ```tsx
|
|
107
|
+
* <head><script dangerouslySetInnerHTML={{ __html: consentDefaultsScript() }} /></head>
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export function consentDefaultsScript(opts = {}) {
|
|
111
|
+
const deny = opts.regionMode === "notice" ? "granted" : "denied";
|
|
112
|
+
const defaults = {
|
|
113
|
+
ad_storage: deny,
|
|
114
|
+
ad_user_data: deny,
|
|
115
|
+
ad_personalization: deny,
|
|
116
|
+
analytics_storage: deny,
|
|
117
|
+
functionality_storage: deny,
|
|
118
|
+
personalization_storage: deny,
|
|
119
|
+
security_storage: "granted",
|
|
120
|
+
wait_for_update: opts.waitForUpdate ?? 500,
|
|
121
|
+
...(opts.region ? { region: opts.region } : null),
|
|
122
|
+
};
|
|
123
|
+
const v = opts.version ?? 1;
|
|
124
|
+
return [
|
|
125
|
+
"window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}",
|
|
126
|
+
`gtag('consent','default',${JSON.stringify(defaults)});`,
|
|
127
|
+
"gtag('set','ads_data_redaction',true);",
|
|
128
|
+
`try{var m=document.cookie.match(/(?:^|; )${CONSENT_COOKIE}=([^;]*)/);if(m){var r=JSON.parse(decodeURIComponent(m[1]));if(r&&r.v>=${v}&&r.c){var g=function(k){return r.c[k]?'granted':'denied'};gtag('consent','update',{ad_storage:g('marketing'),ad_user_data:g('marketing'),ad_personalization:g('marketing'),analytics_storage:g('analytics'),functionality_storage:g('functional'),personalization_storage:g('functional')});}}}catch(e){}`,
|
|
129
|
+
].join("");
|
|
130
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ContactFieldConfig, type SiteFormAction, type SiteFormState } from "./site-form.js";
|
|
3
|
+
import type { ContactIslandLabels } from "./island-keys.js";
|
|
4
|
+
export interface ContactFormIslandProps {
|
|
5
|
+
/** The app's server action, or a URL for a plain POST. Without it the form validates in the browser only (previews). */
|
|
6
|
+
action?: SiteFormAction | string;
|
|
7
|
+
/** Field config; `label` already resolved. */
|
|
8
|
+
fields: (ContactFieldConfig & {
|
|
9
|
+
label: string;
|
|
10
|
+
})[];
|
|
11
|
+
labels: ContactIslandLabels;
|
|
12
|
+
locale?: string;
|
|
13
|
+
layout?: "split" | "stacked" | "minimal";
|
|
14
|
+
submitLabel?: string;
|
|
15
|
+
/** Rendered in place of the form after a successful submit. */
|
|
16
|
+
successMessage?: React.ReactNode;
|
|
17
|
+
/** Privacy notice link; with `privacyCheckbox` a required (never pre-checked) checkbox. */
|
|
18
|
+
privacy?: {
|
|
19
|
+
href: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
checkbox?: boolean;
|
|
22
|
+
};
|
|
23
|
+
/** Separate, optional marketing consent checkbox. */
|
|
24
|
+
marketingConsent?: boolean;
|
|
25
|
+
/** Shown with server errors: "call us on …". */
|
|
26
|
+
fallbackPhone?: {
|
|
27
|
+
href: string;
|
|
28
|
+
label: string;
|
|
29
|
+
};
|
|
30
|
+
/** Render a given state (docs, tests, server-rendered results). */
|
|
31
|
+
initialState?: SiteFormState;
|
|
32
|
+
/** Base for field ids. */
|
|
33
|
+
idBase: string;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Client island of the Contact form: `useActionState` + the app's server action, honeypot and time
|
|
38
|
+
* trap, an error summary that links to fields, focus management, and the same states without JS
|
|
39
|
+
* (native constraints + full round trip). ~2 KB.
|
|
40
|
+
*/
|
|
41
|
+
export declare function ContactFormIsland({ action, fields, labels, locale, layout, submitLabel, successMessage, privacy, marketingConsent, fallbackPhone, initialState, idBase, className, }: ContactFormIslandProps): React.JSX.Element;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ArrowRight } from "lucide-react";
|
|
5
|
+
import { cn2 as cn } from "./kit-2.js";
|
|
6
|
+
import { formatMessage } from "../../../lib/message-format.js";
|
|
7
|
+
import { Button } from "../../../components/button.js";
|
|
8
|
+
import { Field, Input, Textarea } from "../../../components/input.js";
|
|
9
|
+
import { NativeSelect } from "../../../components/native-select.js";
|
|
10
|
+
import { HONEYPOT_FIELD, MARKETING_FIELD, PRIVACY_FIELD, TIMESTAMP_FIELD, fieldConstraints, validateContactForm, } from "./site-form.js";
|
|
11
|
+
const IDLE = { status: "idle" };
|
|
12
|
+
/**
|
|
13
|
+
* Client island of the Contact form: `useActionState` + the app's server action, honeypot and time
|
|
14
|
+
* trap, an error summary that links to fields, focus management, and the same states without JS
|
|
15
|
+
* (native constraints + full round trip). ~2 KB.
|
|
16
|
+
*/
|
|
17
|
+
export function ContactFormIsland({ action, fields, labels, locale = "en-US", layout = "stacked", submitLabel, successMessage, privacy, marketingConsent, fallbackPhone, initialState, idBase, className, }) {
|
|
18
|
+
const f = (k, vars) => formatMessage(labels[k], vars, locale);
|
|
19
|
+
const run = React.useCallback(async (prev, data) => {
|
|
20
|
+
// Same rules as the server, so most mistakes never need a round trip. Spam is the server's call.
|
|
21
|
+
const check = validateContactForm(fields, data, { privacyCheckbox: privacy?.checkbox, labels, locale });
|
|
22
|
+
if (!check.ok)
|
|
23
|
+
return { status: "invalid", errors: check.errors, values: check.values, ts: Date.now() };
|
|
24
|
+
if (typeof action === "function") {
|
|
25
|
+
try {
|
|
26
|
+
return await action(prev, data);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return { status: "error", message: e instanceof Error ? e.message : undefined, values: check.values, ts: Date.now() };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { status: "success", ts: Date.now() };
|
|
33
|
+
}, [action, fields, labels, locale, privacy?.checkbox]);
|
|
34
|
+
const [state, formAction, pending] = React.useActionState(run, initialState ?? IDLE);
|
|
35
|
+
const [hydrated, setHydrated] = React.useState(false);
|
|
36
|
+
const [ts, setTs] = React.useState("");
|
|
37
|
+
const summaryRef = React.useRef(null);
|
|
38
|
+
const successRef = React.useRef(null);
|
|
39
|
+
const firstRender = React.useRef(true);
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
setHydrated(true);
|
|
42
|
+
setTs(String(Date.now()));
|
|
43
|
+
}, []);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
// Never move focus on mount (a server-rendered result must not yank the page).
|
|
46
|
+
if (firstRender.current) {
|
|
47
|
+
firstRender.current = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (state.status === "success")
|
|
51
|
+
successRef.current?.focus();
|
|
52
|
+
else if (state.status === "invalid" || state.status === "error")
|
|
53
|
+
summaryRef.current?.focus();
|
|
54
|
+
}, [state]);
|
|
55
|
+
if (state.status === "success") {
|
|
56
|
+
return (_jsxs("div", { ref: successRef, tabIndex: -1, role: "status", "data-form-state": "success", className: cn("vb-form-success flex flex-col gap-3 rounded-ui py-2 outline-none", className), children: [_jsx("span", { "aria-hidden": true, className: "h-px w-10 bg-accent" }), _jsx("div", { className: "text-lead text-fg text-pretty", children: successMessage ?? f("sent") })] }));
|
|
57
|
+
}
|
|
58
|
+
const errors = state.status === "invalid" ? (state.errors ?? {}) : {};
|
|
59
|
+
const errorEntries = Object.entries(errors).filter(([, v]) => v);
|
|
60
|
+
const values = state.values ?? {};
|
|
61
|
+
const fid = (name) => `${idBase}-${name}`;
|
|
62
|
+
const minimal = layout === "minimal";
|
|
63
|
+
const half = (n) => !minimal && (n === "name" || n === "email" || n === "phone" || n === "company" || n === "budget" || n === "date");
|
|
64
|
+
const urlAction = typeof action === "string" ? action : undefined;
|
|
65
|
+
return (_jsxs("form", { action: urlAction ?? formAction, method: urlAction ? "post" : undefined, noValidate: hydrated && !urlAction, "data-form-state": pending ? "submitting" : state.status, "aria-busy": pending || undefined, className: cn("vb-form flex flex-col gap-6", className), children: [errorEntries.length > 0 ? (_jsxs("div", { ref: summaryRef, tabIndex: -1, role: "alert", className: "vb-form-alert flex flex-col gap-2 rounded-ui border-s-2 border-danger bg-surface-2 px-4 py-3 text-small outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("p", { className: "font-medium text-fg", children: f("errorSummary", { count: errorEntries.length }) }), _jsx("ul", { className: "flex flex-col gap-1", children: errorEntries.map(([name, msg]) => (_jsx("li", { children: _jsx("a", { href: `#${fid(name)}`, className: "text-danger underline decoration-current/40 underline-offset-[0.25em] hover:decoration-current focus-ring rounded-[2px]", children: msg }) }, name))) })] })) : null, state.status === "error" ? (_jsxs("div", { ref: summaryRef, tabIndex: -1, role: "alert", className: "vb-form-alert flex flex-col gap-1 rounded-ui border-s-2 border-danger bg-surface-2 px-4 py-3 text-small outline-none", children: [_jsx("p", { className: "font-medium text-fg", children: f("errorServer") }), fallbackPhone ? (_jsx("p", { className: "text-fg-muted", children: f("errorServerCall", { phone: "\u0000" })
|
|
66
|
+
.split("\u0000")
|
|
67
|
+
.flatMap((part, i) => i === 0
|
|
68
|
+
? [part]
|
|
69
|
+
: [
|
|
70
|
+
_jsx("a", { href: fallbackPhone.href, className: "font-medium text-fg underline underline-offset-[0.25em] focus-ring rounded-[2px]", children: fallbackPhone.label }, "p"),
|
|
71
|
+
part,
|
|
72
|
+
]) })) : state.message ? (_jsx("p", { className: "text-fg-muted", children: state.message })) : null] })) : null, _jsxs("div", { className: cn("grid gap-x-5 gap-y-5", minimal ? "@2xl:grid-cols-[1fr_1fr_auto] @2xl:items-end" : "@xl:grid-cols-2"), children: [fields.map((field) => {
|
|
73
|
+
const c = fieldConstraints(field);
|
|
74
|
+
const id = fid(field.name);
|
|
75
|
+
const err = errors[field.name];
|
|
76
|
+
const common = { id, name: field.name, required: field.required, defaultValue: values[field.name] ?? "", placeholder: field.placeholder };
|
|
77
|
+
let control;
|
|
78
|
+
if (field.options?.length) {
|
|
79
|
+
control = _jsx(NativeSelect, { ...common, placeholder: field.placeholder ?? f("choose"), items: field.options.map((o) => ({ value: o, label: o })) });
|
|
80
|
+
}
|
|
81
|
+
else if (field.name === "message") {
|
|
82
|
+
control = _jsx(Textarea, { ...common, rows: minimal ? 2 : 5, maxLength: c.maxLength });
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
control = _jsx(Input, { ...common, type: c.type, autoComplete: c.autoComplete, inputMode: c.inputMode, maxLength: c.maxLength });
|
|
86
|
+
}
|
|
87
|
+
return (_jsx("div", { className: cn("min-w-0", !half(field.name) && !minimal && "@xl:col-span-2", minimal && field.name === "message" && "@2xl:col-span-2"), children: _jsx(Field, { label: field.label, hint: field.hint, error: err, required: field.required, labels: { optional: labels.optional }, children: control }) }, field.name));
|
|
88
|
+
}), minimal ? (_jsx(SubmitButton, { pending: pending, label: submitLabel ?? f("send"), pendingLabel: f("sending"), className: "@2xl:col-start-3 @2xl:row-start-1 @2xl:self-end" })) : null] }), _jsxs("div", { "aria-hidden": "true", className: "vb-hp", children: [_jsxs("label", { children: [labels.honeypot, _jsx("input", { type: "text", name: HONEYPOT_FIELD, tabIndex: -1, autoComplete: "off", defaultValue: "" })] }), _jsx("input", { type: "hidden", name: TIMESTAMP_FIELD, value: ts, readOnly: true })] }), privacy || marketingConsent ? (_jsxs("div", { className: "flex flex-col gap-3 text-small text-fg-muted", children: [privacy ? (privacy.checkbox ? (_jsx(ConsentCheck, { id: fid(PRIVACY_FIELD), name: PRIVACY_FIELD, required: true, error: errors[PRIVACY_FIELD], children: _jsx(PrivacySentence, { template: labels.privacyRead, href: privacy.href, linkLabel: privacy.label ?? labels.privacyLink }) })) : (_jsx("p", { className: "text-pretty", children: _jsx(PrivacySentence, { template: labels.privacyRead, href: privacy.href, linkLabel: privacy.label ?? labels.privacyLink }) }))) : null, marketingConsent ? (_jsx(ConsentCheck, { id: fid(MARKETING_FIELD), name: MARKETING_FIELD, children: labels.marketingConsent })) : null] })) : null, !minimal ? _jsx(SubmitButton, { pending: pending, label: submitLabel ?? f("send"), pendingLabel: f("sending"), className: "self-start" }) : null] }, state.ts ?? 0));
|
|
89
|
+
}
|
|
90
|
+
function SubmitButton({ pending, label, pendingLabel, className }) {
|
|
91
|
+
return (_jsxs(Button, { type: "submit", variant: "primary", size: "lg", loading: pending, loadingText: pendingLabel, className: cn("vb-action-primary", className), children: [label, pending ? null : _jsx(ArrowRight, { "aria-hidden": true, strokeWidth: 1.75, className: "vb-arrow rtl:-scale-x-100" })] }));
|
|
92
|
+
}
|
|
93
|
+
function PrivacySentence({ template, href, linkLabel }) {
|
|
94
|
+
const [before, after] = template.split("{link}");
|
|
95
|
+
return (_jsxs(_Fragment, { children: [before, _jsx("a", { href: href, className: "font-medium text-fg underline decoration-line underline-offset-[0.25em] hover:decoration-current focus-ring rounded-[2px]", children: linkLabel }), after] }));
|
|
96
|
+
}
|
|
97
|
+
function ConsentCheck({ id, name, required, error, children }) {
|
|
98
|
+
const errId = `${id}-error`;
|
|
99
|
+
return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs("label", { htmlFor: id, className: "flex cursor-pointer items-start gap-3 text-pretty", children: [_jsx("input", { id: id, type: "checkbox", name: name, required: required, "aria-invalid": error ? true : undefined, "aria-describedby": error ? errId : undefined, className: "vb-check mt-0.5 size-4 shrink-0" }), _jsx("span", { children: children })] }), error ? (_jsx("p", { id: errId, className: "ps-7 text-small text-danger", children: error })) : null] }));
|
|
100
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ShareLabels } from "./island-keys.js";
|
|
3
|
+
export interface CopyLinkButtonProps {
|
|
4
|
+
/** URL to copy. Default: the current page. */
|
|
5
|
+
url?: string;
|
|
6
|
+
labels: ShareLabels;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
/** "Copy link" for the article share row (~0.3 KB). Announces "Link copied" politely. */
|
|
10
|
+
export declare function CopyLinkButton({ url, labels, className }: CopyLinkButtonProps): React.JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Check, Link2 } from "lucide-react";
|
|
5
|
+
import { cn2 as cn } from "./kit-2.js";
|
|
6
|
+
/** "Copy link" for the article share row (~0.3 KB). Announces "Link copied" politely. */
|
|
7
|
+
export function CopyLinkButton({ url, labels, className }) {
|
|
8
|
+
const [copied, setCopied] = React.useState(false);
|
|
9
|
+
React.useEffect(() => {
|
|
10
|
+
if (!copied)
|
|
11
|
+
return;
|
|
12
|
+
const id = window.setTimeout(() => setCopied(false), 2000);
|
|
13
|
+
return () => window.clearTimeout(id);
|
|
14
|
+
}, [copied]);
|
|
15
|
+
return (_jsxs("button", { type: "button", onClick: async () => {
|
|
16
|
+
const href = url ?? window.location.href;
|
|
17
|
+
try {
|
|
18
|
+
await navigator.clipboard?.writeText(href);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* clipboard blocked: still confirm, the URL is in the address bar */
|
|
22
|
+
}
|
|
23
|
+
setCopied(true);
|
|
24
|
+
}, className: cn("vb-share-btn", className), children: [copied ? _jsx(Check, { "aria-hidden": true, strokeWidth: 1.5, className: "size-4" }) : _jsx(Link2, { "aria-hidden": true, strokeWidth: 1.5, className: "size-4" }), _jsx("span", { children: labels.copyLink }), _jsx("span", { role: "status", className: "sr-only", children: copied ? labels.linkCopied : "" })] }));
|
|
25
|
+
}
|