@highjumpdigitalsoftware/blog-kit 0.6.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/INTEGRATION.md +76 -0
- package/LICENSE +74 -0
- package/README.md +102 -0
- package/astro/AdPreview.astro +64 -0
- package/astro/AdPreviewPair.astro +10 -0
- package/astro/AuditFindings.astro +29 -0
- package/astro/AuditScores.astro +60 -0
- package/astro/AuthorCard.astro +32 -0
- package/astro/BeforeAfter.astro +26 -0
- package/astro/BlogBehaviors.astro +15 -0
- package/astro/CTABanner.astro +28 -0
- package/astro/CalloutBox.astro +28 -0
- package/astro/CaseStudyHero.astro +45 -0
- package/astro/ChannelMixBars.astro +33 -0
- package/astro/Checklist.astro +24 -0
- package/astro/ChecklistItem.astro +15 -0
- package/astro/CodeSnippet.astro +20 -0
- package/astro/ComparisonTable.astro +103 -0
- package/astro/Definition.astro +30 -0
- package/astro/DeliveryComparison.astro +40 -0
- package/astro/FAQList.astro +43 -0
- package/astro/FurtherReading.astro +34 -0
- package/astro/ImageFeature.astro +22 -0
- package/astro/Infographic.astro +12 -0
- package/astro/KeyMetric.astro +40 -0
- package/astro/KeywordTable.astro +69 -0
- package/astro/List.astro +46 -0
- package/astro/MetricHighlight.astro +77 -0
- package/astro/NewsletterCTA.astro +40 -0
- package/astro/NumberedCard.astro +6 -0
- package/astro/ProConBlock.astro +38 -0
- package/astro/ProseList.astro +46 -0
- package/astro/QuoteBlock.astro +72 -0
- package/astro/RegionCallout.astro +24 -0
- package/astro/RelatedPosts.astro +47 -0
- package/astro/ResultsStrip.astro +59 -0
- package/astro/ScoreBar.astro +19 -0
- package/astro/SerpPreview.astro +35 -0
- package/astro/ServicePromoCard.astro +21 -0
- package/astro/StatCard.astro +48 -0
- package/astro/StepBlock.astro +5 -0
- package/astro/TableOfContents.astro +12 -0
- package/astro/TimelineBlock.astro +30 -0
- package/astro/TipBox.astro +14 -0
- package/astro/TrafficChart.astro +61 -0
- package/astro/VerdictCard.astro +48 -0
- package/astro/blogkit/Article.astro +63 -0
- package/astro/blogkit/BlogIndex.astro +144 -0
- package/core/behaviors/code.js +78 -0
- package/core/behaviors/comparison.js +52 -0
- package/core/behaviors/delivery-comparison.js +52 -0
- package/core/behaviors/faq.js +61 -0
- package/core/behaviors/index.d.ts +3 -0
- package/core/behaviors/index.js +35 -0
- package/core/behaviors/keyword-table.js +52 -0
- package/core/behaviors/toc.js +130 -0
- package/core/css/base.css +146 -0
- package/core/css/components.css +2632 -0
- package/core/css/index-listing.css +207 -0
- package/core/css/index.css +13 -0
- package/core/css/tokens.css +127 -0
- package/core/icons.ts +20 -0
- package/core/lib.ts +70 -0
- package/core/manifest/components.json +573 -0
- package/core/manifest/frontmatter.json +19 -0
- package/core/manifest/templates.json +77 -0
- package/dist/core/behaviors/code.js +78 -0
- package/dist/core/behaviors/comparison.js +52 -0
- package/dist/core/behaviors/delivery-comparison.js +52 -0
- package/dist/core/behaviors/faq.js +61 -0
- package/dist/core/behaviors/index.d.ts +3 -0
- package/dist/core/behaviors/index.js +35 -0
- package/dist/core/behaviors/keyword-table.js +52 -0
- package/dist/core/behaviors/toc.js +130 -0
- package/dist/core/css/base.css +146 -0
- package/dist/core/css/components.css +2632 -0
- package/dist/core/css/index-listing.css +207 -0
- package/dist/core/css/index.css +13 -0
- package/dist/core/css/tokens.css +127 -0
- package/dist/core/icons.d.ts +2 -0
- package/dist/core/icons.d.ts.map +1 -0
- package/dist/core/icons.js +20 -0
- package/dist/core/icons.js.map +1 -0
- package/dist/core/lib.d.ts +21 -0
- package/dist/core/lib.d.ts.map +1 -0
- package/dist/core/lib.js +57 -0
- package/dist/core/lib.js.map +1 -0
- package/dist/core/manifest/components.json +573 -0
- package/dist/core/manifest/frontmatter.json +19 -0
- package/dist/core/manifest/templates.json +77 -0
- package/dist/package/adapters/hjd-api.d.ts +14 -0
- package/dist/package/adapters/hjd-api.d.ts.map +1 -0
- package/dist/package/adapters/hjd-api.js +57 -0
- package/dist/package/adapters/hjd-api.js.map +1 -0
- package/dist/package/adapters/index.d.ts +13 -0
- package/dist/package/adapters/index.d.ts.map +1 -0
- package/dist/package/adapters/index.js +16 -0
- package/dist/package/adapters/index.js.map +1 -0
- package/dist/package/adapters/local.d.ts +13 -0
- package/dist/package/adapters/local.d.ts.map +1 -0
- package/dist/package/adapters/local.js +72 -0
- package/dist/package/adapters/local.js.map +1 -0
- package/dist/package/adapters/source.d.ts +39 -0
- package/dist/package/adapters/source.d.ts.map +1 -0
- package/dist/package/adapters/source.js +19 -0
- package/dist/package/adapters/source.js.map +1 -0
- package/dist/package/article.d.ts +17 -0
- package/dist/package/article.d.ts.map +1 -0
- package/dist/package/article.js +37 -0
- package/dist/package/article.js.map +1 -0
- package/dist/package/astro/data.d.ts +45 -0
- package/dist/package/astro/data.d.ts.map +1 -0
- package/dist/package/astro/data.js +81 -0
- package/dist/package/astro/data.js.map +1 -0
- package/dist/package/astro/freshness.d.ts +11 -0
- package/dist/package/astro/freshness.d.ts.map +1 -0
- package/dist/package/astro/freshness.js +48 -0
- package/dist/package/astro/freshness.js.map +1 -0
- package/dist/package/astro/index.d.ts +12 -0
- package/dist/package/astro/index.d.ts.map +1 -0
- package/dist/package/astro/index.js +31 -0
- package/dist/package/astro/index.js.map +1 -0
- package/dist/package/blog-index.d.ts +10 -0
- package/dist/package/blog-index.d.ts.map +1 -0
- package/dist/package/blog-index.js +27 -0
- package/dist/package/blog-index.js.map +1 -0
- package/dist/package/cli/exchange.d.ts +27 -0
- package/dist/package/cli/exchange.d.ts.map +1 -0
- package/dist/package/cli/exchange.js +94 -0
- package/dist/package/cli/exchange.js.map +1 -0
- package/dist/package/cli/index.d.ts +3 -0
- package/dist/package/cli/index.d.ts.map +1 -0
- package/dist/package/cli/index.js +301 -0
- package/dist/package/cli/index.js.map +1 -0
- package/dist/package/config/define.d.ts +13 -0
- package/dist/package/config/define.d.ts.map +1 -0
- package/dist/package/config/define.js +14 -0
- package/dist/package/config/define.js.map +1 -0
- package/dist/package/config/resolve.d.ts +11 -0
- package/dist/package/config/resolve.d.ts.map +1 -0
- package/dist/package/config/resolve.js +43 -0
- package/dist/package/config/resolve.js.map +1 -0
- package/dist/package/config/types.d.ts +74 -0
- package/dist/package/config/types.d.ts.map +1 -0
- package/dist/package/config/types.js +13 -0
- package/dist/package/config/types.js.map +1 -0
- package/dist/package/index-core.d.ts +28 -0
- package/dist/package/index-core.d.ts.map +1 -0
- package/dist/package/index-core.js +102 -0
- package/dist/package/index-core.js.map +1 -0
- package/dist/package/index.d.ts +13 -0
- package/dist/package/index.d.ts.map +1 -0
- package/dist/package/index.js +25 -0
- package/dist/package/index.js.map +1 -0
- package/dist/package/mdx/render-astro.d.ts +18 -0
- package/dist/package/mdx/render-astro.d.ts.map +1 -0
- package/dist/package/mdx/render-astro.js +75 -0
- package/dist/package/mdx/render-astro.js.map +1 -0
- package/dist/package/mdx/render.d.ts +13 -0
- package/dist/package/mdx/render.d.ts.map +1 -0
- package/dist/package/mdx/render.js +37 -0
- package/dist/package/mdx/render.js.map +1 -0
- package/dist/react/AdPreview.d.ts +26 -0
- package/dist/react/AdPreview.d.ts.map +1 -0
- package/dist/react/AdPreview.js +8 -0
- package/dist/react/AdPreview.js.map +1 -0
- package/dist/react/AdPreviewPair.d.ts +7 -0
- package/dist/react/AdPreviewPair.d.ts.map +1 -0
- package/dist/react/AdPreviewPair.js +5 -0
- package/dist/react/AdPreviewPair.js.map +1 -0
- package/dist/react/AuditFindings.d.ts +14 -0
- package/dist/react/AuditFindings.d.ts.map +1 -0
- package/dist/react/AuditFindings.js +5 -0
- package/dist/react/AuditFindings.js.map +1 -0
- package/dist/react/AuditScores.d.ts +12 -0
- package/dist/react/AuditScores.d.ts.map +1 -0
- package/dist/react/AuditScores.js +25 -0
- package/dist/react/AuditScores.js.map +1 -0
- package/dist/react/AuthorCard.d.ts +10 -0
- package/dist/react/AuthorCard.d.ts.map +1 -0
- package/dist/react/AuthorCard.js +6 -0
- package/dist/react/AuthorCard.js.map +1 -0
- package/dist/react/BeforeAfter.d.ts +12 -0
- package/dist/react/BeforeAfter.d.ts.map +1 -0
- package/dist/react/BeforeAfter.js +7 -0
- package/dist/react/BeforeAfter.js.map +1 -0
- package/dist/react/BlogBehaviors.d.ts +10 -0
- package/dist/react/BlogBehaviors.d.ts.map +1 -0
- package/dist/react/BlogBehaviors.js +20 -0
- package/dist/react/BlogBehaviors.js.map +1 -0
- package/dist/react/CTABanner.d.ts +8 -0
- package/dist/react/CTABanner.d.ts.map +1 -0
- package/dist/react/CTABanner.js +9 -0
- package/dist/react/CTABanner.js.map +1 -0
- package/dist/react/CalloutBox.d.ts +13 -0
- package/dist/react/CalloutBox.d.ts.map +1 -0
- package/dist/react/CalloutBox.js +9 -0
- package/dist/react/CalloutBox.js.map +1 -0
- package/dist/react/CaseStudyHero.d.ts +20 -0
- package/dist/react/CaseStudyHero.d.ts.map +1 -0
- package/dist/react/CaseStudyHero.js +7 -0
- package/dist/react/CaseStudyHero.js.map +1 -0
- package/dist/react/ChannelMixBars.d.ts +18 -0
- package/dist/react/ChannelMixBars.d.ts.map +1 -0
- package/dist/react/ChannelMixBars.js +6 -0
- package/dist/react/ChannelMixBars.js.map +1 -0
- package/dist/react/Checklist.d.ts +10 -0
- package/dist/react/Checklist.d.ts.map +1 -0
- package/dist/react/Checklist.js +7 -0
- package/dist/react/Checklist.js.map +1 -0
- package/dist/react/ChecklistItem.d.ts +7 -0
- package/dist/react/ChecklistItem.d.ts.map +1 -0
- package/dist/react/ChecklistItem.js +5 -0
- package/dist/react/ChecklistItem.js.map +1 -0
- package/dist/react/CodeSnippet.d.ts +17 -0
- package/dist/react/CodeSnippet.d.ts.map +1 -0
- package/dist/react/CodeSnippet.js +14 -0
- package/dist/react/CodeSnippet.js.map +1 -0
- package/dist/react/ComparisonTable.d.ts +22 -0
- package/dist/react/ComparisonTable.d.ts.map +1 -0
- package/dist/react/ComparisonTable.js +35 -0
- package/dist/react/ComparisonTable.js.map +1 -0
- package/dist/react/Definition.d.ts +9 -0
- package/dist/react/Definition.d.ts.map +1 -0
- package/dist/react/Definition.js +19 -0
- package/dist/react/Definition.js.map +1 -0
- package/dist/react/DeliveryComparison.d.ts +16 -0
- package/dist/react/DeliveryComparison.d.ts.map +1 -0
- package/dist/react/DeliveryComparison.js +7 -0
- package/dist/react/DeliveryComparison.js.map +1 -0
- package/dist/react/FAQList.d.ts +20 -0
- package/dist/react/FAQList.d.ts.map +1 -0
- package/dist/react/FAQList.js +19 -0
- package/dist/react/FAQList.js.map +1 -0
- package/dist/react/FurtherReading.d.ts +21 -0
- package/dist/react/FurtherReading.d.ts.map +1 -0
- package/dist/react/FurtherReading.js +13 -0
- package/dist/react/FurtherReading.js.map +1 -0
- package/dist/react/ImageFeature.d.ts +9 -0
- package/dist/react/ImageFeature.d.ts.map +1 -0
- package/dist/react/ImageFeature.js +6 -0
- package/dist/react/ImageFeature.js.map +1 -0
- package/dist/react/Infographic.d.ts +6 -0
- package/dist/react/Infographic.d.ts.map +1 -0
- package/dist/react/Infographic.js +7 -0
- package/dist/react/Infographic.js.map +1 -0
- package/dist/react/KeyMetric.d.ts +16 -0
- package/dist/react/KeyMetric.d.ts.map +1 -0
- package/dist/react/KeyMetric.js +15 -0
- package/dist/react/KeyMetric.js.map +1 -0
- package/dist/react/KeywordTable.d.ts +18 -0
- package/dist/react/KeywordTable.d.ts.map +1 -0
- package/dist/react/KeywordTable.js +23 -0
- package/dist/react/KeywordTable.js.map +1 -0
- package/dist/react/List.d.ts +11 -0
- package/dist/react/List.d.ts.map +1 -0
- package/dist/react/List.js +21 -0
- package/dist/react/List.js.map +1 -0
- package/dist/react/MetricHighlight.d.ts +15 -0
- package/dist/react/MetricHighlight.d.ts.map +1 -0
- package/dist/react/MetricHighlight.js +26 -0
- package/dist/react/MetricHighlight.js.map +1 -0
- package/dist/react/NewsletterCTA.d.ts +9 -0
- package/dist/react/NewsletterCTA.d.ts.map +1 -0
- package/dist/react/NewsletterCTA.js +5 -0
- package/dist/react/NewsletterCTA.js.map +1 -0
- package/dist/react/NumberedCard.d.ts +9 -0
- package/dist/react/NumberedCard.d.ts.map +1 -0
- package/dist/react/NumberedCard.js +7 -0
- package/dist/react/NumberedCard.js.map +1 -0
- package/dist/react/ProConBlock.d.ts +6 -0
- package/dist/react/ProConBlock.d.ts.map +1 -0
- package/dist/react/ProConBlock.js +7 -0
- package/dist/react/ProConBlock.js.map +1 -0
- package/dist/react/ProseList.d.ts +17 -0
- package/dist/react/ProseList.d.ts.map +1 -0
- package/dist/react/ProseList.js +26 -0
- package/dist/react/ProseList.js.map +1 -0
- package/dist/react/QuoteBlock.d.ts +17 -0
- package/dist/react/QuoteBlock.d.ts.map +1 -0
- package/dist/react/QuoteBlock.js +26 -0
- package/dist/react/QuoteBlock.js.map +1 -0
- package/dist/react/RegionCallout.d.ts +13 -0
- package/dist/react/RegionCallout.d.ts.map +1 -0
- package/dist/react/RegionCallout.js +5 -0
- package/dist/react/RegionCallout.js.map +1 -0
- package/dist/react/RelatedPosts.d.ts +20 -0
- package/dist/react/RelatedPosts.d.ts.map +1 -0
- package/dist/react/RelatedPosts.js +7 -0
- package/dist/react/RelatedPosts.js.map +1 -0
- package/dist/react/ResultsStrip.d.ts +18 -0
- package/dist/react/ResultsStrip.d.ts.map +1 -0
- package/dist/react/ResultsStrip.js +22 -0
- package/dist/react/ResultsStrip.js.map +1 -0
- package/dist/react/ScoreBar.d.ts +8 -0
- package/dist/react/ScoreBar.d.ts.map +1 -0
- package/dist/react/ScoreBar.js +6 -0
- package/dist/react/ScoreBar.js.map +1 -0
- package/dist/react/SerpPreview.d.ts +18 -0
- package/dist/react/SerpPreview.d.ts.map +1 -0
- package/dist/react/SerpPreview.js +13 -0
- package/dist/react/SerpPreview.js.map +1 -0
- package/dist/react/ServicePromoCard.d.ts +14 -0
- package/dist/react/ServicePromoCard.d.ts.map +1 -0
- package/dist/react/ServicePromoCard.js +12 -0
- package/dist/react/ServicePromoCard.js.map +1 -0
- package/dist/react/StatCard.d.ts +13 -0
- package/dist/react/StatCard.d.ts.map +1 -0
- package/dist/react/StatCard.js +20 -0
- package/dist/react/StatCard.js.map +1 -0
- package/dist/react/StepBlock.d.ts +8 -0
- package/dist/react/StepBlock.d.ts.map +1 -0
- package/dist/react/StepBlock.js +5 -0
- package/dist/react/StepBlock.js.map +1 -0
- package/dist/react/TableOfContents.d.ts +14 -0
- package/dist/react/TableOfContents.d.ts.map +1 -0
- package/dist/react/TableOfContents.js +12 -0
- package/dist/react/TableOfContents.js.map +1 -0
- package/dist/react/TimelineBlock.d.ts +14 -0
- package/dist/react/TimelineBlock.d.ts.map +1 -0
- package/dist/react/TimelineBlock.js +8 -0
- package/dist/react/TimelineBlock.js.map +1 -0
- package/dist/react/TipBox.d.ts +6 -0
- package/dist/react/TipBox.d.ts.map +1 -0
- package/dist/react/TipBox.js +5 -0
- package/dist/react/TipBox.js.map +1 -0
- package/dist/react/TrafficChart.d.ts +16 -0
- package/dist/react/TrafficChart.d.ts.map +1 -0
- package/dist/react/TrafficChart.js +14 -0
- package/dist/react/TrafficChart.js.map +1 -0
- package/dist/react/VerdictCard.d.ts +15 -0
- package/dist/react/VerdictCard.d.ts.map +1 -0
- package/dist/react/VerdictCard.js +5 -0
- package/dist/react/VerdictCard.js.map +1 -0
- package/dist/react/components-map.d.ts +133 -0
- package/dist/react/components-map.d.ts.map +1 -0
- package/dist/react/components-map.js +120 -0
- package/dist/react/components-map.js.map +1 -0
- package/dist/react/index.d.ts +5 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +13 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +116 -0
- package/react/AdPreview.tsx +94 -0
- package/react/AdPreviewPair.tsx +16 -0
- package/react/AuditFindings.tsx +43 -0
- package/react/AuditScores.tsx +73 -0
- package/react/AuthorCard.tsx +35 -0
- package/react/BeforeAfter.tsx +27 -0
- package/react/BlogBehaviors.tsx +21 -0
- package/react/CTABanner.tsx +32 -0
- package/react/CalloutBox.tsx +31 -0
- package/react/CaseStudyHero.tsx +71 -0
- package/react/ChannelMixBars.tsx +50 -0
- package/react/Checklist.tsx +31 -0
- package/react/ChecklistItem.tsx +19 -0
- package/react/CodeSnippet.tsx +36 -0
- package/react/ComparisonTable.tsx +114 -0
- package/react/Definition.tsx +36 -0
- package/react/DeliveryComparison.tsx +62 -0
- package/react/FAQList.tsx +61 -0
- package/react/FurtherReading.tsx +46 -0
- package/react/ImageFeature.tsx +26 -0
- package/react/Infographic.tsx +18 -0
- package/react/KeyMetric.tsx +61 -0
- package/react/KeywordTable.tsx +92 -0
- package/react/List.tsx +58 -0
- package/react/MetricHighlight.tsx +86 -0
- package/react/NewsletterCTA.tsx +48 -0
- package/react/NumberedCard.tsx +7 -0
- package/react/ProConBlock.tsx +42 -0
- package/react/ProseList.tsx +72 -0
- package/react/QuoteBlock.tsx +89 -0
- package/react/RegionCallout.tsx +38 -0
- package/react/RelatedPosts.tsx +58 -0
- package/react/ResultsStrip.tsx +77 -0
- package/react/ScoreBar.tsx +27 -0
- package/react/SerpPreview.tsx +59 -0
- package/react/ServicePromoCard.tsx +43 -0
- package/react/StatCard.tsx +62 -0
- package/react/StepBlock.tsx +5 -0
- package/react/TableOfContents.tsx +27 -0
- package/react/TimelineBlock.tsx +35 -0
- package/react/TipBox.tsx +16 -0
- package/react/TrafficChart.tsx +79 -0
- package/react/VerdictCard.tsx +60 -0
- package/react/components-map.ts +122 -0
- package/react/index.ts +13 -0
- package/templates/blogkit/app/api/blogkit/revalidate/route.ts.tmpl +32 -0
- package/templates/blogkit/app/blog/[slug]/page.tsx.tmpl +41 -0
- package/templates/blogkit/app/blog/page.tsx.tmpl +18 -0
- package/templates/blogkit/blogkit.config.ts.tmpl +23 -0
- package/templates/blogkit-astro/BLOGKIT_ASTRO_SETUP.md.tmpl +49 -0
- package/templates/blogkit-astro/src/blogkit.config.ts.tmpl +29 -0
- package/templates/blogkit-astro/src/pages/api/blogkit/revalidate.ts.tmpl +46 -0
- package/templates/blogkit-astro/src/pages/blog/[slug].astro.tmpl +39 -0
- package/templates/blogkit-astro/src/pages/blog/index.astro.tmpl +29 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface ChecklistEntry {
|
|
3
|
+
title: string;
|
|
4
|
+
sub?: string;
|
|
5
|
+
done?: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
items: ChecklistEntry[];
|
|
9
|
+
}
|
|
10
|
+
const { items } = Astro.props;
|
|
11
|
+
---
|
|
12
|
+
{items && items.length > 0 && (
|
|
13
|
+
<ul class="bk-checklist">
|
|
14
|
+
{items.map((it) => (
|
|
15
|
+
<li class={`bk-checklist__item${it.done ? " bk-checklist__item--done" : ""}`}>
|
|
16
|
+
<span class="bk-checklist__box" aria-hidden="true">{it.done ? "✓" : ""}</span>
|
|
17
|
+
<span class="bk-checklist__text">
|
|
18
|
+
<span class="bk-checklist__title">{it.title}</span>
|
|
19
|
+
{it.sub && <span class="bk-checklist__sub">{it.sub}</span>}
|
|
20
|
+
</span>
|
|
21
|
+
</li>
|
|
22
|
+
))}
|
|
23
|
+
</ul>
|
|
24
|
+
)}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
const { checked, label, description } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
<div class={`bk-checklist-item${checked ? " bk-checklist-item--checked" : ""}`}>
|
|
10
|
+
<span class="bk-checklist-item__box" aria-hidden={!checked}>{checked ? "✓" : ""}</span>
|
|
11
|
+
<span class="bk-checklist-item__text">
|
|
12
|
+
<span class="bk-checklist-item__label">{label}</span>
|
|
13
|
+
{description && <span class="bk-checklist-item__desc">{description}</span>}
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { ICONS } from "../core/icons";
|
|
3
|
+
interface Props {
|
|
4
|
+
code: string;
|
|
5
|
+
language?: string;
|
|
6
|
+
filename?: string;
|
|
7
|
+
}
|
|
8
|
+
const { code, language = "text", filename } = Astro.props;
|
|
9
|
+
const label = filename || (language !== "text" ? language : "code");
|
|
10
|
+
---
|
|
11
|
+
<div class="bk-code" data-bk-code>
|
|
12
|
+
<div class="bk-code__bar">
|
|
13
|
+
<span class="bk-code__label">{label}</span>
|
|
14
|
+
<button type="button" class="bk-code__copy" data-bk-code-copy>
|
|
15
|
+
<span class="bk-code__copy-icon" set:html={ICONS.copy} />
|
|
16
|
+
<span class="bk-code__copy-label">Copy</span>
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
19
|
+
<pre class="bk-code__pre"><code class={`bk-code__code language-${language}`}>{code}</code></pre>
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface ComparisonItem {
|
|
3
|
+
feature: string;
|
|
4
|
+
optionA: string;
|
|
5
|
+
optionB: string;
|
|
6
|
+
winner?: "a" | "b" | "tie";
|
|
7
|
+
}
|
|
8
|
+
interface Props {
|
|
9
|
+
title?: string;
|
|
10
|
+
optionALabel: string;
|
|
11
|
+
optionBLabel: string;
|
|
12
|
+
items?: ComparisonItem[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const TICK = "✓";
|
|
16
|
+
const CROSS = "✕";
|
|
17
|
+
|
|
18
|
+
type Cell = { kind: "yes" | "no" | "text"; text: string };
|
|
19
|
+
|
|
20
|
+
/** Normalise a cell value: tick/"yes" and cross/"no" become glyph marks. */
|
|
21
|
+
function resolveCell(text: string): Cell {
|
|
22
|
+
const v = String(text ?? "").trim();
|
|
23
|
+
const lower = v.toLowerCase();
|
|
24
|
+
if (v === TICK || lower === "yes") return { kind: "yes", text: TICK };
|
|
25
|
+
if (v === CROSS || lower === "no") return { kind: "no", text: CROSS };
|
|
26
|
+
return { kind: "text", text: v };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { title, optionALabel, optionBLabel, items = [] } = Astro.props;
|
|
30
|
+
const list = items ?? [];
|
|
31
|
+
---
|
|
32
|
+
{list.length > 0 && (
|
|
33
|
+
<div class="bk-comparison">
|
|
34
|
+
{title && <h3 class="bk-comparison__title">{title}</h3>}
|
|
35
|
+
|
|
36
|
+
<div class="bk-comparison__cards">
|
|
37
|
+
{list.map((item) => {
|
|
38
|
+
const a = resolveCell(item.optionA);
|
|
39
|
+
const b = resolveCell(item.optionB);
|
|
40
|
+
return (
|
|
41
|
+
<div class="bk-comparison__card">
|
|
42
|
+
<div class="bk-comparison__card-feature">{item.feature}</div>
|
|
43
|
+
<div class={`bk-comparison__card-row${item.winner === "a" ? " bk-comparison__card-row--best" : ""}`}>
|
|
44
|
+
<span class="bk-comparison__card-label">{optionALabel}</span>
|
|
45
|
+
{a.kind === "yes"
|
|
46
|
+
? <span class="bk-comparison__mark bk-comparison__mark--yes">{a.text}</span>
|
|
47
|
+
: a.kind === "no"
|
|
48
|
+
? <span class="bk-comparison__mark bk-comparison__mark--no">{a.text}</span>
|
|
49
|
+
: <span class={item.winner === "a" ? "bk-comparison__value--best" : undefined}>{a.text}</span>}
|
|
50
|
+
</div>
|
|
51
|
+
<div class={`bk-comparison__card-row${item.winner === "b" ? " bk-comparison__card-row--best" : ""}`}>
|
|
52
|
+
<span class="bk-comparison__card-label">{optionBLabel}</span>
|
|
53
|
+
{b.kind === "yes"
|
|
54
|
+
? <span class="bk-comparison__mark bk-comparison__mark--yes">{b.text}</span>
|
|
55
|
+
: b.kind === "no"
|
|
56
|
+
? <span class="bk-comparison__mark bk-comparison__mark--no">{b.text}</span>
|
|
57
|
+
: <span class={item.winner === "b" ? "bk-comparison__value--best" : undefined}>{b.text}</span>}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
})}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="bk-comparison__table-wrap" data-bk-comparison>
|
|
65
|
+
<div class="bk-comparison__scroll">
|
|
66
|
+
<table class="bk-comparison__table">
|
|
67
|
+
<thead>
|
|
68
|
+
<tr>
|
|
69
|
+
<th class="bk-comparison__th">Feature</th>
|
|
70
|
+
<th class="bk-comparison__th">{optionALabel}</th>
|
|
71
|
+
<th class="bk-comparison__th">{optionBLabel}</th>
|
|
72
|
+
</tr>
|
|
73
|
+
</thead>
|
|
74
|
+
<tbody>
|
|
75
|
+
{list.map((item) => {
|
|
76
|
+
const a = resolveCell(item.optionA);
|
|
77
|
+
const b = resolveCell(item.optionB);
|
|
78
|
+
return (
|
|
79
|
+
<tr class="bk-comparison__tr">
|
|
80
|
+
<td class="bk-comparison__td bk-comparison__td--feature">{item.feature}</td>
|
|
81
|
+
<td class={`bk-comparison__td${item.winner === "a" ? " bk-comparison__td--best" : ""}`}>
|
|
82
|
+
{a.kind === "yes"
|
|
83
|
+
? <span class="bk-comparison__mark bk-comparison__mark--yes">{a.text}</span>
|
|
84
|
+
: a.kind === "no"
|
|
85
|
+
? <span class="bk-comparison__mark bk-comparison__mark--no">{a.text}</span>
|
|
86
|
+
: <span class={item.winner === "a" ? "bk-comparison__value--best" : undefined}>{a.text}</span>}
|
|
87
|
+
</td>
|
|
88
|
+
<td class={`bk-comparison__td${item.winner === "b" ? " bk-comparison__td--best" : ""}`}>
|
|
89
|
+
{b.kind === "yes"
|
|
90
|
+
? <span class="bk-comparison__mark bk-comparison__mark--yes">{b.text}</span>
|
|
91
|
+
: b.kind === "no"
|
|
92
|
+
? <span class="bk-comparison__mark bk-comparison__mark--no">{b.text}</span>
|
|
93
|
+
: <span class={item.winner === "b" ? "bk-comparison__value--best" : undefined}>{b.text}</span>}
|
|
94
|
+
</td>
|
|
95
|
+
</tr>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
98
|
+
</tbody>
|
|
99
|
+
</table>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
term: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
pronunciation?: string;
|
|
6
|
+
}
|
|
7
|
+
const { term, name, pronunciation } = Astro.props;
|
|
8
|
+
// `term` is meant to be a 2-3 char monogram. If an author passes a full
|
|
9
|
+
// phrase, derive initials so the tile doesn't overflow.
|
|
10
|
+
const rawTerm = String(term ?? "").trim();
|
|
11
|
+
const looksLikePhrase = rawTerm.length > 4 || /\s|-/.test(rawTerm);
|
|
12
|
+
const monogram = looksLikePhrase
|
|
13
|
+
? rawTerm
|
|
14
|
+
.split(/[\s-]+/)
|
|
15
|
+
.map((w) => w[0])
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join("")
|
|
18
|
+
.slice(0, 3)
|
|
19
|
+
.toUpperCase()
|
|
20
|
+
: rawTerm.toUpperCase();
|
|
21
|
+
const resolvedName = name ?? (looksLikePhrase ? rawTerm : undefined);
|
|
22
|
+
---
|
|
23
|
+
<div class="bk-definition">
|
|
24
|
+
<div class="bk-definition__monogram" aria-hidden="true">{monogram}</div>
|
|
25
|
+
<div class="bk-definition__content">
|
|
26
|
+
{resolvedName && <p class="bk-definition__name">{resolvedName}</p>}
|
|
27
|
+
{pronunciation && <p class="bk-definition__pronunciation">{pronunciation}</p>}
|
|
28
|
+
<p class="bk-definition__body"><slot /></p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface DeliveryComparisonRow {
|
|
3
|
+
label: string;
|
|
4
|
+
sub?: string;
|
|
5
|
+
values: string[];
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
columns?: string[];
|
|
9
|
+
rows?: DeliveryComparisonRow[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { columns = [], rows = [] } = Astro.props;
|
|
13
|
+
const cols = columns ?? [];
|
|
14
|
+
const list = rows ?? [];
|
|
15
|
+
---
|
|
16
|
+
{list.length > 0 && (
|
|
17
|
+
<div class="bk-delivery-comparison" data-bk-delivery-comparison>
|
|
18
|
+
<div class="bk-delivery-comparison__scroll">
|
|
19
|
+
<table class="bk-delivery-comparison__table">
|
|
20
|
+
<thead>
|
|
21
|
+
<tr>
|
|
22
|
+
<th class="bk-delivery-comparison__th" />
|
|
23
|
+
{cols.map((c) => <th class="bk-delivery-comparison__th">{c}</th>)}
|
|
24
|
+
</tr>
|
|
25
|
+
</thead>
|
|
26
|
+
<tbody>
|
|
27
|
+
{list.map((r) => (
|
|
28
|
+
<tr class="bk-delivery-comparison__tr">
|
|
29
|
+
<td class="bk-delivery-comparison__td bk-delivery-comparison__td--label">
|
|
30
|
+
<strong class="bk-delivery-comparison__label">{r.label}</strong>
|
|
31
|
+
{r.sub}
|
|
32
|
+
</td>
|
|
33
|
+
{r.values.map((v) => <td class="bk-delivery-comparison__td">{v}</td>)}
|
|
34
|
+
</tr>
|
|
35
|
+
))}
|
|
36
|
+
</tbody>
|
|
37
|
+
</table>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
)}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface FAQItem {
|
|
3
|
+
q: string;
|
|
4
|
+
a: string;
|
|
5
|
+
}
|
|
6
|
+
interface Props {
|
|
7
|
+
items?: FAQItem[];
|
|
8
|
+
heading?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Split an answer body into paragraphs on blank lines. */
|
|
12
|
+
function toParagraphs(a: string): string[] {
|
|
13
|
+
return String(a ?? "")
|
|
14
|
+
.split(/\n{2,}/)
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { items, heading } = Astro.props;
|
|
19
|
+
const list = items ?? [];
|
|
20
|
+
---
|
|
21
|
+
<div class="bk-faq" data-bk-faq>
|
|
22
|
+
{heading && <p class="bk-faq__heading">{heading}</p>}
|
|
23
|
+
<div class="bk-faq__list">
|
|
24
|
+
{list.length > 0
|
|
25
|
+
? list.map((it, i) => (
|
|
26
|
+
<details class="bk-faq__item" open={i === 0}>
|
|
27
|
+
<summary class="bk-faq__summary">
|
|
28
|
+
<span class="bk-faq__question">{it.q}</span>
|
|
29
|
+
<span class="bk-faq__toggle" aria-hidden="true">
|
|
30
|
+
<span class="bk-faq__bar bk-faq__bar--h" />
|
|
31
|
+
<span class="bk-faq__bar bk-faq__bar--v" />
|
|
32
|
+
</span>
|
|
33
|
+
</summary>
|
|
34
|
+
<div class="bk-faq__answer">
|
|
35
|
+
{toParagraphs(it.a).map((p) => (
|
|
36
|
+
<p class="bk-faq__para" set:html={p} />
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
</details>
|
|
40
|
+
))
|
|
41
|
+
: <slot />}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface FurtherReadingSource {
|
|
3
|
+
title: string;
|
|
4
|
+
source: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
sources?: FurtherReadingSource[];
|
|
9
|
+
heading?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { sources, heading } = Astro.props;
|
|
13
|
+
const list = sources ?? [];
|
|
14
|
+
---
|
|
15
|
+
{list.length > 0 && (
|
|
16
|
+
<div class="bk-further-reading">
|
|
17
|
+
<p class="bk-further-reading__title">{heading ?? "Further reading"}</p>
|
|
18
|
+
<ul class="bk-further-reading__list">
|
|
19
|
+
{list.map((s) => (
|
|
20
|
+
<li class="bk-further-reading__item">
|
|
21
|
+
<a
|
|
22
|
+
class="bk-further-reading__link"
|
|
23
|
+
href={s.url}
|
|
24
|
+
target="_blank"
|
|
25
|
+
rel="nofollow noopener noreferrer"
|
|
26
|
+
>
|
|
27
|
+
{s.title}
|
|
28
|
+
</a>
|
|
29
|
+
<span class="bk-further-reading__source">{s.source}</span>
|
|
30
|
+
</li>
|
|
31
|
+
))}
|
|
32
|
+
</ul>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
src: string;
|
|
4
|
+
alt: string;
|
|
5
|
+
caption?: string;
|
|
6
|
+
credit?: string;
|
|
7
|
+
position?: "left" | "right" | "full";
|
|
8
|
+
}
|
|
9
|
+
const { src, alt, caption, credit, position = "full" } = Astro.props;
|
|
10
|
+
const pos = position === "left" || position === "right" ? position : "full";
|
|
11
|
+
---
|
|
12
|
+
<figure class={`bk-image-feature bk-image-feature--${pos}`}>
|
|
13
|
+
<div class="bk-image-feature__frame">
|
|
14
|
+
<img class="bk-image-feature__img" src={src} alt={alt} loading="lazy" decoding="async" />
|
|
15
|
+
</div>
|
|
16
|
+
{(caption || credit) && (
|
|
17
|
+
<figcaption class="bk-image-feature__caption">
|
|
18
|
+
{caption && <span class="bk-image-feature__text">{caption}</span>}
|
|
19
|
+
{credit && <span class="bk-image-feature__credit">{credit}</span>}
|
|
20
|
+
</figcaption>
|
|
21
|
+
)}
|
|
22
|
+
</figure>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { ICONS } from "../core/icons";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
number: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
sub?: string;
|
|
9
|
+
source?: string;
|
|
10
|
+
sourceUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { number, label, title, sub, source, sourceUrl } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
<div class="bk-key-metric">
|
|
16
|
+
<div class="bk-key-metric__num">{number}</div>
|
|
17
|
+
<div class="bk-key-metric__copy">
|
|
18
|
+
{label && <div class="bk-key-metric__label">{label}</div>}
|
|
19
|
+
{title && <p class="bk-key-metric__title" set:html={title} />}
|
|
20
|
+
{sub && <p class="bk-key-metric__sub">{sub}</p>}
|
|
21
|
+
{source &&
|
|
22
|
+
(sourceUrl ? (
|
|
23
|
+
<a
|
|
24
|
+
class="bk-key-metric__source bk-key-metric__source--link"
|
|
25
|
+
href={sourceUrl}
|
|
26
|
+
target="_blank"
|
|
27
|
+
rel="nofollow noopener noreferrer"
|
|
28
|
+
>
|
|
29
|
+
<span class="bk-key-metric__source-kicker">Source</span>
|
|
30
|
+
{source}
|
|
31
|
+
<span class="bk-key-metric__source-icon" aria-hidden="true" set:html={ICONS["external"]} />
|
|
32
|
+
</a>
|
|
33
|
+
) : (
|
|
34
|
+
<div class="bk-key-metric__source">
|
|
35
|
+
<span class="bk-key-metric__source-kicker">Source</span>
|
|
36
|
+
{source}
|
|
37
|
+
</div>
|
|
38
|
+
))}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface KeywordRow {
|
|
3
|
+
keyword: string;
|
|
4
|
+
volume: string;
|
|
5
|
+
difficulty: number;
|
|
6
|
+
was?: number | string;
|
|
7
|
+
now: number | string;
|
|
8
|
+
delta: number | string;
|
|
9
|
+
}
|
|
10
|
+
interface Props {
|
|
11
|
+
rows?: KeywordRow[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Bucket a 0–100 difficulty score into low / med / high. */
|
|
15
|
+
function difficultyBucket(difficulty: number): "low" | "med" | "high" {
|
|
16
|
+
return difficulty < 40 ? "low" : difficulty < 60 ? "med" : "high";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** A negative delta means the rank dropped (down); anything else is up. */
|
|
20
|
+
function deltaDirection(delta: number | string): "up" | "down" {
|
|
21
|
+
return delta && String(delta).startsWith("-") ? "down" : "up";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Show the magnitude when numeric, else the raw value. */
|
|
25
|
+
function deltaDisplay(delta: number | string): number | string {
|
|
26
|
+
return Math.abs(Number(delta)) || delta;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { rows = [] } = Astro.props;
|
|
30
|
+
const list = rows ?? [];
|
|
31
|
+
---
|
|
32
|
+
{list.length > 0 && (
|
|
33
|
+
<div class="bk-keyword-table" data-bk-keyword-table>
|
|
34
|
+
<div class="bk-keyword-table__scroll">
|
|
35
|
+
<table class="bk-keyword-table__table">
|
|
36
|
+
<thead>
|
|
37
|
+
<tr>
|
|
38
|
+
<th class="bk-keyword-table__th">Keyword</th>
|
|
39
|
+
<th class="bk-keyword-table__th bk-keyword-table__th--r">Volume</th>
|
|
40
|
+
<th class="bk-keyword-table__th">Difficulty</th>
|
|
41
|
+
<th class="bk-keyword-table__th bk-keyword-table__th--r">Was</th>
|
|
42
|
+
<th class="bk-keyword-table__th bk-keyword-table__th--r">Now</th>
|
|
43
|
+
<th class="bk-keyword-table__th bk-keyword-table__th--r">Δ</th>
|
|
44
|
+
</tr>
|
|
45
|
+
</thead>
|
|
46
|
+
<tbody>
|
|
47
|
+
{list.map((r) => {
|
|
48
|
+
const diff = difficultyBucket(r.difficulty);
|
|
49
|
+
const direction = deltaDirection(r.delta);
|
|
50
|
+
return (
|
|
51
|
+
<tr class="bk-keyword-table__tr">
|
|
52
|
+
<td class="bk-keyword-table__td bk-keyword-table__td--kw">{r.keyword}</td>
|
|
53
|
+
<td class="bk-keyword-table__td bk-keyword-table__td--r">{r.volume}</td>
|
|
54
|
+
<td class="bk-keyword-table__td">
|
|
55
|
+
<span class={`bk-keyword-table__diff bk-keyword-table__diff--${diff}`}>{r.difficulty}</span>
|
|
56
|
+
</td>
|
|
57
|
+
<td class="bk-keyword-table__td bk-keyword-table__td--r bk-keyword-table__rank">{r.was ?? "—"}</td>
|
|
58
|
+
<td class="bk-keyword-table__td bk-keyword-table__td--r bk-keyword-table__rank">{r.now}</td>
|
|
59
|
+
<td class="bk-keyword-table__td bk-keyword-table__td--r">
|
|
60
|
+
<span class={`bk-keyword-table__delta bk-keyword-table__delta--${direction}`}>{deltaDisplay(r.delta)}</span>
|
|
61
|
+
</td>
|
|
62
|
+
</tr>
|
|
63
|
+
);
|
|
64
|
+
})}
|
|
65
|
+
</tbody>
|
|
66
|
+
</table>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
package/astro/List.astro
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { ICONS } from "../core/icons";
|
|
3
|
+
|
|
4
|
+
type ListVariant = "ordered" | "bullet" | "check";
|
|
5
|
+
interface Props {
|
|
6
|
+
variant?: ListVariant | string;
|
|
7
|
+
items: string[];
|
|
8
|
+
heading?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const VARIANTS: Record<string, ListVariant> = {
|
|
12
|
+
ordered: "ordered",
|
|
13
|
+
numbered: "ordered",
|
|
14
|
+
number: "ordered",
|
|
15
|
+
bullet: "bullet",
|
|
16
|
+
bulleted: "bullet",
|
|
17
|
+
dot: "bullet",
|
|
18
|
+
check: "check",
|
|
19
|
+
checked: "check",
|
|
20
|
+
checklist: "check",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const { variant, items, heading } = Astro.props;
|
|
24
|
+
const v = VARIANTS[(variant ?? "bullet").toLowerCase().trim()] ?? "bullet";
|
|
25
|
+
const Tag = v === "ordered" ? "ol" : "ul";
|
|
26
|
+
const hasItems = Array.isArray(items) && items.length > 0;
|
|
27
|
+
---
|
|
28
|
+
{hasItems && (
|
|
29
|
+
<div class={`bk-list bk-list--${v}`}>
|
|
30
|
+
{heading && <p class="bk-list__heading">{heading}</p>}
|
|
31
|
+
<Tag class="bk-list__items">
|
|
32
|
+
{items.map((item, i) => (
|
|
33
|
+
<li class="bk-list__item">
|
|
34
|
+
{v === "ordered" ? (
|
|
35
|
+
<span class="bk-list__marker" aria-hidden="true">{String(i + 1).padStart(2, "0")}</span>
|
|
36
|
+
) : v === "check" ? (
|
|
37
|
+
<span class="bk-list__marker" aria-hidden="true" set:html={ICONS["check-tick"]} />
|
|
38
|
+
) : (
|
|
39
|
+
<span class="bk-list__marker" aria-hidden="true" />
|
|
40
|
+
)}
|
|
41
|
+
<span class="bk-list__text" set:html={item} />
|
|
42
|
+
</li>
|
|
43
|
+
))}
|
|
44
|
+
</Tag>
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { ICONS } from "../core/icons";
|
|
3
|
+
|
|
4
|
+
interface Metric {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
change?: string;
|
|
8
|
+
source?: string;
|
|
9
|
+
sourceUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
metrics?: Metric[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { metrics = [] } = Astro.props;
|
|
17
|
+
const single = metrics.length === 1 ? metrics[0] : null;
|
|
18
|
+
const cols = metrics.length === 2 ? 2 : metrics.length === 3 ? 3 : 4;
|
|
19
|
+
---
|
|
20
|
+
{metrics.length === 0 ? null : single ? (
|
|
21
|
+
<div class="bk-metric-highlight bk-metric-highlight--hero">
|
|
22
|
+
<div class="bk-metric-highlight__hero-value">{single.value}</div>
|
|
23
|
+
<div class="bk-metric-highlight__hero-body">
|
|
24
|
+
{single.change && <div class="bk-metric-highlight__hero-change">{single.change}</div>}
|
|
25
|
+
<div class="bk-metric-highlight__hero-label">{single.label}</div>
|
|
26
|
+
{single.source &&
|
|
27
|
+
(single.sourceUrl ? (
|
|
28
|
+
<a
|
|
29
|
+
class="bk-metric-highlight__source bk-metric-highlight__source--dark bk-metric-highlight__source--link"
|
|
30
|
+
href={single.sourceUrl}
|
|
31
|
+
target="_blank"
|
|
32
|
+
rel="nofollow noopener noreferrer"
|
|
33
|
+
>
|
|
34
|
+
<span class="bk-metric-highlight__source-kicker">Source</span>
|
|
35
|
+
{single.source}
|
|
36
|
+
<span class="bk-metric-highlight__source-icon" aria-hidden="true" set:html={ICONS["external"]} />
|
|
37
|
+
</a>
|
|
38
|
+
) : (
|
|
39
|
+
<div class="bk-metric-highlight__source bk-metric-highlight__source--dark">
|
|
40
|
+
<span class="bk-metric-highlight__source-kicker">Source</span>
|
|
41
|
+
{single.source}
|
|
42
|
+
</div>
|
|
43
|
+
))}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
) : (
|
|
47
|
+
<div class={`bk-metric-highlight bk-metric-highlight--grid bk-metric-highlight--${cols}`}>
|
|
48
|
+
{metrics.map((metric) => (
|
|
49
|
+
<div class="bk-metric-highlight__card">
|
|
50
|
+
<div class="bk-metric-highlight__value">{metric.value}</div>
|
|
51
|
+
<div class="bk-metric-highlight__label">{metric.label}</div>
|
|
52
|
+
{metric.change && <div class="bk-metric-highlight__change">{metric.change}</div>}
|
|
53
|
+
{metric.source && (
|
|
54
|
+
<div class="bk-metric-highlight__source-wrap">
|
|
55
|
+
{metric.sourceUrl ? (
|
|
56
|
+
<a
|
|
57
|
+
class="bk-metric-highlight__source bk-metric-highlight__source--link"
|
|
58
|
+
href={metric.sourceUrl}
|
|
59
|
+
target="_blank"
|
|
60
|
+
rel="nofollow noopener noreferrer"
|
|
61
|
+
>
|
|
62
|
+
<span class="bk-metric-highlight__source-kicker">Source</span>
|
|
63
|
+
{metric.source}
|
|
64
|
+
<span class="bk-metric-highlight__source-icon" aria-hidden="true" set:html={ICONS["external"]} />
|
|
65
|
+
</a>
|
|
66
|
+
) : (
|
|
67
|
+
<div class="bk-metric-highlight__source">
|
|
68
|
+
<span class="bk-metric-highlight__source-kicker">Source</span>
|
|
69
|
+
{metric.source}
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
))}
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
heading?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
action?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
buttonText?: string;
|
|
8
|
+
}
|
|
9
|
+
const {
|
|
10
|
+
heading = "One email, once a week.",
|
|
11
|
+
description = "Field-tested ideas for turning chat traffic into revenue. No filler.",
|
|
12
|
+
action = "/api/newsletter",
|
|
13
|
+
placeholder = "you@studio.com",
|
|
14
|
+
buttonText = "Subscribe",
|
|
15
|
+
} = Astro.props;
|
|
16
|
+
---
|
|
17
|
+
<div class="bk-newsletter">
|
|
18
|
+
<span class="bk-newsletter__glow" aria-hidden="true"></span>
|
|
19
|
+
<div class="bk-newsletter__copy">
|
|
20
|
+
<h3 class="bk-newsletter__heading">{heading}</h3>
|
|
21
|
+
<p class="bk-newsletter__desc">{description}</p>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="bk-newsletter__action">
|
|
24
|
+
<form class="bk-newsletter__form" action={action} method="post">
|
|
25
|
+
<label class="bk-newsletter__honeypot" aria-hidden="true">
|
|
26
|
+
Leave this field empty
|
|
27
|
+
<input type="text" name="website" tabindex="-1" autocomplete="off" />
|
|
28
|
+
</label>
|
|
29
|
+
<input
|
|
30
|
+
class="bk-newsletter__input"
|
|
31
|
+
type="email"
|
|
32
|
+
name="email"
|
|
33
|
+
required
|
|
34
|
+
placeholder={placeholder}
|
|
35
|
+
autocomplete="email"
|
|
36
|
+
/>
|
|
37
|
+
<button class="bk-newsletter__button" type="submit">{buttonText}</button>
|
|
38
|
+
</form>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props { number?: number | string; title?: string; description?: string; }
|
|
3
|
+
const { number, title, description } = Astro.props;
|
|
4
|
+
const n = String(number ?? "").padStart(2, "0");
|
|
5
|
+
---
|
|
6
|
+
<div class="bk-numbered-card"><span class="bk-numbered-card__badge">{n}</span>{title ? <h4 class="bk-numbered-card__title">{title}</h4> : null}<p class="bk-numbered-card__body">{description}<slot /></p></div>
|