@asteroidcms/core-utils 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.cts CHANGED
@@ -294,4 +294,312 @@ declare function extractHeadingsFromElement(root: HTMLElement, options?: Extract
294
294
  scrollMarginTop?: number;
295
295
  }): ExtractedHeading[];
296
296
 
297
- export { AsteroidCMSProvider, type AsteroidCMSProviderProps, type ExtractHeadingsOptions, type ExtractedHeading, type HeadingLevel, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
297
+ type SeoClientProps = {
298
+ title: string;
299
+ description: string;
300
+ url: string;
301
+ siteName?: string;
302
+ keywords?: string;
303
+ twitter?: string;
304
+ image?: string;
305
+ noindex?: boolean;
306
+ };
307
+ /** Theme colors used when generating dynamic OG images. */
308
+ interface AsteroidOgImagePalette {
309
+ background: string;
310
+ foreground: string;
311
+ accent: string;
312
+ accentMuted?: string;
313
+ mutedText?: string;
314
+ }
315
+ interface AsteroidOgImageParams {
316
+ title: string;
317
+ subtitle?: string;
318
+ eyebrow?: string;
319
+ type?: "article" | "listing";
320
+ }
321
+ /** Site-level identity used to build the Organization/WebSite JSON-LD graph. */
322
+ interface AsteroidOrganizationConfig {
323
+ logoUrl?: string;
324
+ contactEmail?: string;
325
+ contactPhone?: string;
326
+ address?: {
327
+ street?: string;
328
+ city?: string;
329
+ country?: string;
330
+ };
331
+ /** Generic list of profile URLs (LinkedIn, X, etc.). Maps to schema.org `sameAs`. */
332
+ socials?: string[];
333
+ }
334
+ /** Site-level SEO config passed into the headless Asteroid content components. */
335
+ interface AsteroidSeoConfig {
336
+ siteName: string;
337
+ baseUrl: string;
338
+ twitter?: string;
339
+ defaultDescription?: string;
340
+ defaultKeywords?: string;
341
+ /** Path prefix for the article collection (e.g. `/blog`, `/news`, `/docs`). Default: `/blog` */
342
+ articlePath?: string;
343
+ /**
344
+ * Human label for the article collection, used in default titles/eyebrows
345
+ * (e.g. "Blog", "News", "Documentation"). Default: `"Articles"`.
346
+ */
347
+ contentLabel?: string;
348
+ /**
349
+ * Override how a raw page/article title becomes the final `<title>`.
350
+ * Default: `(title) => `${title} | ${siteName}``.
351
+ */
352
+ titleTemplate?: (title: string) => string;
353
+ ogImage?: {
354
+ palette: AsteroidOgImagePalette;
355
+ /** OG image API route path. Default: `/api/og` */
356
+ apiPath?: string;
357
+ };
358
+ /** Override dynamic OG image URL generation (e.g. custom CDN or renderer). */
359
+ getOgImageUrl?: (params: AsteroidOgImageParams) => string | undefined;
360
+ /** Site identity for the Organization/WebSite JSON-LD graph. */
361
+ organization?: AsteroidOrganizationConfig;
362
+ /** Extra schema.org @graph nodes (e.g. a ProfessionalService node). */
363
+ extraJsonLdNodes?: object[];
364
+ /** CMS base URL for resolving featured-image URLs. Required server-side for featured images. */
365
+ cmsUrl?: string;
366
+ /** URL to a PWA manifest.json. When set, a `<link rel="manifest">` is emitted. */
367
+ manifestUrl?: string;
368
+ /** Site-wide default robots policy. Per-page overrides are available on builder options. */
369
+ noindex?: boolean;
370
+ }
371
+
372
+ /** Render a JSON-LD <script>. Pass a built graph via `data`; renders nothing if absent. */
373
+ declare function JsonLd({ data }: {
374
+ data?: object;
375
+ }): react_jsx_runtime.JSX.Element | null;
376
+ /**
377
+ * Imperatively sets document title, meta description, canonical URL and social
378
+ * tags. Works in plain React apps and Next.js client components. In a Next.js
379
+ * App Router app, prefer server `generateMetadata` from the `/next` entry.
380
+ */
381
+ declare function Seo({ title, description, url, siteName, keywords, twitter, image, noindex, }: SeoClientProps): null;
382
+
383
+ /** schema.org Article subtypes; pick per content kind. */
384
+ type ArticleJsonLdType = "Article" | "BlogPosting" | "NewsArticle" | "TechArticle" | (string & {});
385
+
386
+ /** Resolves a CMS asset id (or passthrough URL) to an absolute media URL. */
387
+ type ArticleImageResolver = (idOrUrl?: string) => string;
388
+ /** Minimal article post shape shared across Asteroid CMS apps. */
389
+ interface AsteroidArticlePost {
390
+ slug: string;
391
+ title: string;
392
+ description?: string;
393
+ featured_image?: string;
394
+ featured?: boolean;
395
+ published_date?: string | null;
396
+ category?: {
397
+ slug: string;
398
+ name: string;
399
+ description?: string;
400
+ };
401
+ }
402
+ interface AsteroidArticleCategoryGroup<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
403
+ categoryName: string;
404
+ categorySlug: string;
405
+ posts: TPost[];
406
+ }
407
+ /** Runtime-agnostic computed state shared by client + server listing. */
408
+ interface ArticlesViewState<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
409
+ posts: TPost[];
410
+ featured: TPost | null;
411
+ rest: TPost[];
412
+ categoryGroups: AsteroidArticleCategoryGroup<TPost>[];
413
+ isEmpty: boolean;
414
+ isSearching: boolean;
415
+ /** The effective (already-debounced, for client) search query. */
416
+ searchQuery: string;
417
+ }
418
+ type AsteroidArticlesEmptyReason = "error" | "no-posts" | "no-results";
419
+ interface AsteroidArticlesSearchParams {
420
+ value: string;
421
+ onChange: (value: string) => void;
422
+ onSubmit: (event: {
423
+ preventDefault: () => void;
424
+ }) => void;
425
+ }
426
+ interface AsteroidArticlesHeaderParams {
427
+ eyebrow: ReactNode;
428
+ title: ReactNode;
429
+ description?: ReactNode;
430
+ search: ReactNode;
431
+ }
432
+ interface AsteroidArticlesFeaturedCardParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
433
+ post: TPost;
434
+ cmsImage: ArticleImageResolver;
435
+ }
436
+ interface AsteroidArticlesPostCardParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
437
+ post: TPost;
438
+ index: number;
439
+ group: AsteroidArticleCategoryGroup<TPost>;
440
+ cmsImage: ArticleImageResolver;
441
+ }
442
+ interface AsteroidArticlesPostGridParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
443
+ posts: TPost[];
444
+ group: AsteroidArticleCategoryGroup<TPost>;
445
+ children: ReactNode;
446
+ }
447
+ interface AsteroidArticlesCategoryHeadingParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
448
+ group: AsteroidArticleCategoryGroup<TPost>;
449
+ }
450
+ interface AsteroidArticlesCategoryGroupParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
451
+ group: AsteroidArticleCategoryGroup<TPost>;
452
+ defaultContent: ReactNode;
453
+ }
454
+ interface AsteroidArticlesEmptyParams {
455
+ reason: AsteroidArticlesEmptyReason;
456
+ searchQuery?: string;
457
+ error?: unknown;
458
+ }
459
+ interface AsteroidArticlesContentParams {
460
+ featured: ReactNode;
461
+ groups: ReactNode;
462
+ noSearchResults: ReactNode;
463
+ }
464
+
465
+ interface AsteroidArticlePagePost {
466
+ slug: string;
467
+ title: string;
468
+ description?: string;
469
+ content?: string;
470
+ featured_image?: string;
471
+ tags?: string;
472
+ published_date?: string | null;
473
+ category?: {
474
+ slug: string;
475
+ name: string;
476
+ };
477
+ author?: {
478
+ name: string;
479
+ bio?: string;
480
+ };
481
+ }
482
+ type Slot<TPost> = (params: {
483
+ post: TPost;
484
+ cmsImage: ArticleImageResolver;
485
+ }) => ReactNode;
486
+ interface ArticleBodyRenderProps<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> {
487
+ backLink?: ReactNode;
488
+ renderHeader?: Slot<TPost>;
489
+ renderMeta?: Slot<TPost>;
490
+ renderDescription?: Slot<TPost>;
491
+ renderFeaturedImage?: Slot<TPost>;
492
+ renderToc?: Slot<TPost>;
493
+ renderContent?: Slot<TPost>;
494
+ renderPreArticle?: Slot<TPost>;
495
+ renderMidArticle?: Slot<TPost>;
496
+ renderPostArticle?: Slot<TPost>;
497
+ renderTags?: Slot<TPost>;
498
+ renderAuthorDetails?: Slot<TPost>;
499
+ renderRelatedPosts?: (params: {
500
+ post: TPost;
501
+ relatedPosts: TPost[];
502
+ cmsImage: ArticleImageResolver;
503
+ }) => ReactNode;
504
+ renderCTA?: Slot<TPost>;
505
+ }
506
+
507
+ type AsteroidArticlePageUseArticleResult<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> = {
508
+ data?: TPost | null;
509
+ loading: boolean;
510
+ error?: unknown;
511
+ };
512
+ type AsteroidArticlePageUseArticle<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> = (slug: string) => AsteroidArticlePageUseArticleResult<TPost>;
513
+ interface AsteroidArticlePageProps<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> extends ArticleBodyRenderProps<TPost> {
514
+ slug: string;
515
+ useArticle: AsteroidArticlePageUseArticle<TPost>;
516
+ seo?: AsteroidSeoConfig;
517
+ articleType?: ArticleJsonLdType;
518
+ noindex?: boolean;
519
+ relatedPosts?: TPost[];
520
+ renderRoot?: (params: {
521
+ children: ReactNode;
522
+ }) => ReactNode;
523
+ renderSkeleton?: () => ReactNode;
524
+ renderError?: (params: {
525
+ error?: unknown;
526
+ reason: "error" | "not-found";
527
+ }) => ReactNode;
528
+ renderJsonLd?: (params: {
529
+ post: TPost;
530
+ }) => ReactNode;
531
+ children?: (state: AsteroidArticlePageUseArticleResult<TPost>) => ReactNode;
532
+ }
533
+ declare function AsteroidArticlePage<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost>(props: AsteroidArticlePageProps<TPost>): react_jsx_runtime.JSX.Element;
534
+
535
+ interface ArticlesListingRenderProps<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
536
+ eyebrow?: ReactNode;
537
+ title?: ReactNode;
538
+ description?: ReactNode;
539
+ renderRoot?: (params: {
540
+ children: ReactNode;
541
+ }) => ReactNode;
542
+ renderHeader?: (params: AsteroidArticlesHeaderParams) => ReactNode;
543
+ renderFeaturedCard?: (params: AsteroidArticlesFeaturedCardParams<TPost>) => ReactNode;
544
+ renderPostCard: (params: AsteroidArticlesPostCardParams<TPost>) => ReactNode;
545
+ renderCategoryHeading?: (params: AsteroidArticlesCategoryHeadingParams<TPost>) => ReactNode;
546
+ renderPostGrid?: (params: AsteroidArticlesPostGridParams<TPost>) => ReactNode;
547
+ renderCategoryGroup?: (params: AsteroidArticlesCategoryGroupParams<TPost>) => ReactNode;
548
+ renderSkeleton?: () => ReactNode;
549
+ renderEmpty?: (params: AsteroidArticlesEmptyParams) => ReactNode;
550
+ renderContent?: (params: AsteroidArticlesContentParams) => ReactNode;
551
+ }
552
+
553
+ interface AsteroidArticlesUsePostsResult<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
554
+ posts: TPost[];
555
+ featured?: TPost | null;
556
+ rest?: TPost[];
557
+ loading: boolean;
558
+ error?: unknown;
559
+ }
560
+ type AsteroidArticlesUsePosts<TPost extends AsteroidArticlePost = AsteroidArticlePost> = (searchQuery: string) => AsteroidArticlesUsePostsResult<TPost>;
561
+ interface AsteroidArticlesState<TPost extends AsteroidArticlePost = AsteroidArticlePost> extends ArticlesViewState<TPost> {
562
+ loading: boolean;
563
+ error: unknown;
564
+ hasError: boolean;
565
+ /** Raw, un-debounced input value. Bind your search box to this. */
566
+ inputValue: string;
567
+ setSearchQuery: (value: string) => void;
568
+ }
569
+ interface AsteroidArticlesProps<TPost extends AsteroidArticlePost = AsteroidArticlePost> extends ArticlesListingRenderProps<TPost> {
570
+ usePosts: AsteroidArticlesUsePosts<TPost>;
571
+ categorySlug?: string;
572
+ articleSlug?: string;
573
+ searchDebounceMs?: number;
574
+ seo?: AsteroidSeoConfig;
575
+ noindex?: boolean;
576
+ renderSearch?: (params: AsteroidArticlesSearchParams) => ReactNode;
577
+ renderJsonLd?: (state: AsteroidArticlesState<TPost>) => ReactNode;
578
+ groupPostsByCategory?: (posts: TPost[]) => AsteroidArticleCategoryGroup<TPost>[];
579
+ children?: (state: AsteroidArticlesState<TPost>) => ReactNode;
580
+ }
581
+ declare function useAsteroidArticlesState<TPost extends AsteroidArticlePost = AsteroidArticlePost>(props: Pick<AsteroidArticlesProps<TPost>, "usePosts" | "categorySlug" | "articleSlug" | "searchDebounceMs" | "groupPostsByCategory">): AsteroidArticlesState<TPost>;
582
+ declare function AsteroidArticlesListing<TPost extends AsteroidArticlePost = AsteroidArticlePost>(props: AsteroidArticlesProps<TPost>): react_jsx_runtime.JSX.Element;
583
+
584
+ declare function defaultGetCategoryName(post: Pick<AsteroidArticlePost, "category">): string | undefined;
585
+ declare function defaultGroupPostsByCategory<TPost extends AsteroidArticlePost = AsteroidArticlePost>(posts: TPost[]): AsteroidArticleCategoryGroup<TPost>[];
586
+
587
+ interface ArticleSearchBoxProps {
588
+ /** URL query param the search writes to. Default: "q". */
589
+ paramKey?: string;
590
+ placeholder?: string;
591
+ /** Debounce before navigating. Default: 500ms. */
592
+ debounceMs?: number;
593
+ className?: string;
594
+ /** Override the default input UI. */
595
+ render?: (params: {
596
+ value: string;
597
+ onChange: (value: string) => void;
598
+ onSubmit: (event: {
599
+ preventDefault: () => void;
600
+ }) => void;
601
+ }) => ReactNode;
602
+ }
603
+ declare function ArticleSearchBox({ paramKey, placeholder, debounceMs, className, render, }: ArticleSearchBoxProps): react_jsx_runtime.JSX.Element;
604
+
605
+ export { type ArticleBodyRenderProps, type ArticleImageResolver, ArticleSearchBox, type ArticleSearchBoxProps, type AsteroidArticleCategoryGroup, AsteroidArticlePage, type AsteroidArticlePagePost, type AsteroidArticlePageProps, type AsteroidArticlePageUseArticle, type AsteroidArticlePageUseArticleResult, type AsteroidArticlePost, type AsteroidArticlesCategoryGroupParams, type AsteroidArticlesCategoryHeadingParams, type AsteroidArticlesContentParams, type AsteroidArticlesEmptyParams, type AsteroidArticlesEmptyReason, type AsteroidArticlesFeaturedCardParams, type AsteroidArticlesHeaderParams, AsteroidArticlesListing, type AsteroidArticlesPostCardParams, type AsteroidArticlesPostGridParams, type AsteroidArticlesProps, type AsteroidArticlesSearchParams, type AsteroidArticlesState, type AsteroidArticlesUsePosts, type AsteroidArticlesUsePostsResult, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ExtractHeadingsOptions, type ExtractedHeading, type HeadingLevel, JsonLd, RichTextContent, Seo, type UseCmsContentOptions, type UseCmsMutateOptions, defaultGetCategoryName, defaultGroupPostsByCategory, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidArticlesState, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
package/dist/client.d.ts CHANGED
@@ -294,4 +294,312 @@ declare function extractHeadingsFromElement(root: HTMLElement, options?: Extract
294
294
  scrollMarginTop?: number;
295
295
  }): ExtractedHeading[];
296
296
 
297
- export { AsteroidCMSProvider, type AsteroidCMSProviderProps, type ExtractHeadingsOptions, type ExtractedHeading, type HeadingLevel, RichTextContent, type UseCmsContentOptions, type UseCmsMutateOptions, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
297
+ type SeoClientProps = {
298
+ title: string;
299
+ description: string;
300
+ url: string;
301
+ siteName?: string;
302
+ keywords?: string;
303
+ twitter?: string;
304
+ image?: string;
305
+ noindex?: boolean;
306
+ };
307
+ /** Theme colors used when generating dynamic OG images. */
308
+ interface AsteroidOgImagePalette {
309
+ background: string;
310
+ foreground: string;
311
+ accent: string;
312
+ accentMuted?: string;
313
+ mutedText?: string;
314
+ }
315
+ interface AsteroidOgImageParams {
316
+ title: string;
317
+ subtitle?: string;
318
+ eyebrow?: string;
319
+ type?: "article" | "listing";
320
+ }
321
+ /** Site-level identity used to build the Organization/WebSite JSON-LD graph. */
322
+ interface AsteroidOrganizationConfig {
323
+ logoUrl?: string;
324
+ contactEmail?: string;
325
+ contactPhone?: string;
326
+ address?: {
327
+ street?: string;
328
+ city?: string;
329
+ country?: string;
330
+ };
331
+ /** Generic list of profile URLs (LinkedIn, X, etc.). Maps to schema.org `sameAs`. */
332
+ socials?: string[];
333
+ }
334
+ /** Site-level SEO config passed into the headless Asteroid content components. */
335
+ interface AsteroidSeoConfig {
336
+ siteName: string;
337
+ baseUrl: string;
338
+ twitter?: string;
339
+ defaultDescription?: string;
340
+ defaultKeywords?: string;
341
+ /** Path prefix for the article collection (e.g. `/blog`, `/news`, `/docs`). Default: `/blog` */
342
+ articlePath?: string;
343
+ /**
344
+ * Human label for the article collection, used in default titles/eyebrows
345
+ * (e.g. "Blog", "News", "Documentation"). Default: `"Articles"`.
346
+ */
347
+ contentLabel?: string;
348
+ /**
349
+ * Override how a raw page/article title becomes the final `<title>`.
350
+ * Default: `(title) => `${title} | ${siteName}``.
351
+ */
352
+ titleTemplate?: (title: string) => string;
353
+ ogImage?: {
354
+ palette: AsteroidOgImagePalette;
355
+ /** OG image API route path. Default: `/api/og` */
356
+ apiPath?: string;
357
+ };
358
+ /** Override dynamic OG image URL generation (e.g. custom CDN or renderer). */
359
+ getOgImageUrl?: (params: AsteroidOgImageParams) => string | undefined;
360
+ /** Site identity for the Organization/WebSite JSON-LD graph. */
361
+ organization?: AsteroidOrganizationConfig;
362
+ /** Extra schema.org @graph nodes (e.g. a ProfessionalService node). */
363
+ extraJsonLdNodes?: object[];
364
+ /** CMS base URL for resolving featured-image URLs. Required server-side for featured images. */
365
+ cmsUrl?: string;
366
+ /** URL to a PWA manifest.json. When set, a `<link rel="manifest">` is emitted. */
367
+ manifestUrl?: string;
368
+ /** Site-wide default robots policy. Per-page overrides are available on builder options. */
369
+ noindex?: boolean;
370
+ }
371
+
372
+ /** Render a JSON-LD <script>. Pass a built graph via `data`; renders nothing if absent. */
373
+ declare function JsonLd({ data }: {
374
+ data?: object;
375
+ }): react_jsx_runtime.JSX.Element | null;
376
+ /**
377
+ * Imperatively sets document title, meta description, canonical URL and social
378
+ * tags. Works in plain React apps and Next.js client components. In a Next.js
379
+ * App Router app, prefer server `generateMetadata` from the `/next` entry.
380
+ */
381
+ declare function Seo({ title, description, url, siteName, keywords, twitter, image, noindex, }: SeoClientProps): null;
382
+
383
+ /** schema.org Article subtypes; pick per content kind. */
384
+ type ArticleJsonLdType = "Article" | "BlogPosting" | "NewsArticle" | "TechArticle" | (string & {});
385
+
386
+ /** Resolves a CMS asset id (or passthrough URL) to an absolute media URL. */
387
+ type ArticleImageResolver = (idOrUrl?: string) => string;
388
+ /** Minimal article post shape shared across Asteroid CMS apps. */
389
+ interface AsteroidArticlePost {
390
+ slug: string;
391
+ title: string;
392
+ description?: string;
393
+ featured_image?: string;
394
+ featured?: boolean;
395
+ published_date?: string | null;
396
+ category?: {
397
+ slug: string;
398
+ name: string;
399
+ description?: string;
400
+ };
401
+ }
402
+ interface AsteroidArticleCategoryGroup<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
403
+ categoryName: string;
404
+ categorySlug: string;
405
+ posts: TPost[];
406
+ }
407
+ /** Runtime-agnostic computed state shared by client + server listing. */
408
+ interface ArticlesViewState<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
409
+ posts: TPost[];
410
+ featured: TPost | null;
411
+ rest: TPost[];
412
+ categoryGroups: AsteroidArticleCategoryGroup<TPost>[];
413
+ isEmpty: boolean;
414
+ isSearching: boolean;
415
+ /** The effective (already-debounced, for client) search query. */
416
+ searchQuery: string;
417
+ }
418
+ type AsteroidArticlesEmptyReason = "error" | "no-posts" | "no-results";
419
+ interface AsteroidArticlesSearchParams {
420
+ value: string;
421
+ onChange: (value: string) => void;
422
+ onSubmit: (event: {
423
+ preventDefault: () => void;
424
+ }) => void;
425
+ }
426
+ interface AsteroidArticlesHeaderParams {
427
+ eyebrow: ReactNode;
428
+ title: ReactNode;
429
+ description?: ReactNode;
430
+ search: ReactNode;
431
+ }
432
+ interface AsteroidArticlesFeaturedCardParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
433
+ post: TPost;
434
+ cmsImage: ArticleImageResolver;
435
+ }
436
+ interface AsteroidArticlesPostCardParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
437
+ post: TPost;
438
+ index: number;
439
+ group: AsteroidArticleCategoryGroup<TPost>;
440
+ cmsImage: ArticleImageResolver;
441
+ }
442
+ interface AsteroidArticlesPostGridParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
443
+ posts: TPost[];
444
+ group: AsteroidArticleCategoryGroup<TPost>;
445
+ children: ReactNode;
446
+ }
447
+ interface AsteroidArticlesCategoryHeadingParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
448
+ group: AsteroidArticleCategoryGroup<TPost>;
449
+ }
450
+ interface AsteroidArticlesCategoryGroupParams<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
451
+ group: AsteroidArticleCategoryGroup<TPost>;
452
+ defaultContent: ReactNode;
453
+ }
454
+ interface AsteroidArticlesEmptyParams {
455
+ reason: AsteroidArticlesEmptyReason;
456
+ searchQuery?: string;
457
+ error?: unknown;
458
+ }
459
+ interface AsteroidArticlesContentParams {
460
+ featured: ReactNode;
461
+ groups: ReactNode;
462
+ noSearchResults: ReactNode;
463
+ }
464
+
465
+ interface AsteroidArticlePagePost {
466
+ slug: string;
467
+ title: string;
468
+ description?: string;
469
+ content?: string;
470
+ featured_image?: string;
471
+ tags?: string;
472
+ published_date?: string | null;
473
+ category?: {
474
+ slug: string;
475
+ name: string;
476
+ };
477
+ author?: {
478
+ name: string;
479
+ bio?: string;
480
+ };
481
+ }
482
+ type Slot<TPost> = (params: {
483
+ post: TPost;
484
+ cmsImage: ArticleImageResolver;
485
+ }) => ReactNode;
486
+ interface ArticleBodyRenderProps<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> {
487
+ backLink?: ReactNode;
488
+ renderHeader?: Slot<TPost>;
489
+ renderMeta?: Slot<TPost>;
490
+ renderDescription?: Slot<TPost>;
491
+ renderFeaturedImage?: Slot<TPost>;
492
+ renderToc?: Slot<TPost>;
493
+ renderContent?: Slot<TPost>;
494
+ renderPreArticle?: Slot<TPost>;
495
+ renderMidArticle?: Slot<TPost>;
496
+ renderPostArticle?: Slot<TPost>;
497
+ renderTags?: Slot<TPost>;
498
+ renderAuthorDetails?: Slot<TPost>;
499
+ renderRelatedPosts?: (params: {
500
+ post: TPost;
501
+ relatedPosts: TPost[];
502
+ cmsImage: ArticleImageResolver;
503
+ }) => ReactNode;
504
+ renderCTA?: Slot<TPost>;
505
+ }
506
+
507
+ type AsteroidArticlePageUseArticleResult<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> = {
508
+ data?: TPost | null;
509
+ loading: boolean;
510
+ error?: unknown;
511
+ };
512
+ type AsteroidArticlePageUseArticle<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> = (slug: string) => AsteroidArticlePageUseArticleResult<TPost>;
513
+ interface AsteroidArticlePageProps<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost> extends ArticleBodyRenderProps<TPost> {
514
+ slug: string;
515
+ useArticle: AsteroidArticlePageUseArticle<TPost>;
516
+ seo?: AsteroidSeoConfig;
517
+ articleType?: ArticleJsonLdType;
518
+ noindex?: boolean;
519
+ relatedPosts?: TPost[];
520
+ renderRoot?: (params: {
521
+ children: ReactNode;
522
+ }) => ReactNode;
523
+ renderSkeleton?: () => ReactNode;
524
+ renderError?: (params: {
525
+ error?: unknown;
526
+ reason: "error" | "not-found";
527
+ }) => ReactNode;
528
+ renderJsonLd?: (params: {
529
+ post: TPost;
530
+ }) => ReactNode;
531
+ children?: (state: AsteroidArticlePageUseArticleResult<TPost>) => ReactNode;
532
+ }
533
+ declare function AsteroidArticlePage<TPost extends AsteroidArticlePagePost = AsteroidArticlePagePost>(props: AsteroidArticlePageProps<TPost>): react_jsx_runtime.JSX.Element;
534
+
535
+ interface ArticlesListingRenderProps<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
536
+ eyebrow?: ReactNode;
537
+ title?: ReactNode;
538
+ description?: ReactNode;
539
+ renderRoot?: (params: {
540
+ children: ReactNode;
541
+ }) => ReactNode;
542
+ renderHeader?: (params: AsteroidArticlesHeaderParams) => ReactNode;
543
+ renderFeaturedCard?: (params: AsteroidArticlesFeaturedCardParams<TPost>) => ReactNode;
544
+ renderPostCard: (params: AsteroidArticlesPostCardParams<TPost>) => ReactNode;
545
+ renderCategoryHeading?: (params: AsteroidArticlesCategoryHeadingParams<TPost>) => ReactNode;
546
+ renderPostGrid?: (params: AsteroidArticlesPostGridParams<TPost>) => ReactNode;
547
+ renderCategoryGroup?: (params: AsteroidArticlesCategoryGroupParams<TPost>) => ReactNode;
548
+ renderSkeleton?: () => ReactNode;
549
+ renderEmpty?: (params: AsteroidArticlesEmptyParams) => ReactNode;
550
+ renderContent?: (params: AsteroidArticlesContentParams) => ReactNode;
551
+ }
552
+
553
+ interface AsteroidArticlesUsePostsResult<TPost extends AsteroidArticlePost = AsteroidArticlePost> {
554
+ posts: TPost[];
555
+ featured?: TPost | null;
556
+ rest?: TPost[];
557
+ loading: boolean;
558
+ error?: unknown;
559
+ }
560
+ type AsteroidArticlesUsePosts<TPost extends AsteroidArticlePost = AsteroidArticlePost> = (searchQuery: string) => AsteroidArticlesUsePostsResult<TPost>;
561
+ interface AsteroidArticlesState<TPost extends AsteroidArticlePost = AsteroidArticlePost> extends ArticlesViewState<TPost> {
562
+ loading: boolean;
563
+ error: unknown;
564
+ hasError: boolean;
565
+ /** Raw, un-debounced input value. Bind your search box to this. */
566
+ inputValue: string;
567
+ setSearchQuery: (value: string) => void;
568
+ }
569
+ interface AsteroidArticlesProps<TPost extends AsteroidArticlePost = AsteroidArticlePost> extends ArticlesListingRenderProps<TPost> {
570
+ usePosts: AsteroidArticlesUsePosts<TPost>;
571
+ categorySlug?: string;
572
+ articleSlug?: string;
573
+ searchDebounceMs?: number;
574
+ seo?: AsteroidSeoConfig;
575
+ noindex?: boolean;
576
+ renderSearch?: (params: AsteroidArticlesSearchParams) => ReactNode;
577
+ renderJsonLd?: (state: AsteroidArticlesState<TPost>) => ReactNode;
578
+ groupPostsByCategory?: (posts: TPost[]) => AsteroidArticleCategoryGroup<TPost>[];
579
+ children?: (state: AsteroidArticlesState<TPost>) => ReactNode;
580
+ }
581
+ declare function useAsteroidArticlesState<TPost extends AsteroidArticlePost = AsteroidArticlePost>(props: Pick<AsteroidArticlesProps<TPost>, "usePosts" | "categorySlug" | "articleSlug" | "searchDebounceMs" | "groupPostsByCategory">): AsteroidArticlesState<TPost>;
582
+ declare function AsteroidArticlesListing<TPost extends AsteroidArticlePost = AsteroidArticlePost>(props: AsteroidArticlesProps<TPost>): react_jsx_runtime.JSX.Element;
583
+
584
+ declare function defaultGetCategoryName(post: Pick<AsteroidArticlePost, "category">): string | undefined;
585
+ declare function defaultGroupPostsByCategory<TPost extends AsteroidArticlePost = AsteroidArticlePost>(posts: TPost[]): AsteroidArticleCategoryGroup<TPost>[];
586
+
587
+ interface ArticleSearchBoxProps {
588
+ /** URL query param the search writes to. Default: "q". */
589
+ paramKey?: string;
590
+ placeholder?: string;
591
+ /** Debounce before navigating. Default: 500ms. */
592
+ debounceMs?: number;
593
+ className?: string;
594
+ /** Override the default input UI. */
595
+ render?: (params: {
596
+ value: string;
597
+ onChange: (value: string) => void;
598
+ onSubmit: (event: {
599
+ preventDefault: () => void;
600
+ }) => void;
601
+ }) => ReactNode;
602
+ }
603
+ declare function ArticleSearchBox({ paramKey, placeholder, debounceMs, className, render, }: ArticleSearchBoxProps): react_jsx_runtime.JSX.Element;
604
+
605
+ export { type ArticleBodyRenderProps, type ArticleImageResolver, ArticleSearchBox, type ArticleSearchBoxProps, type AsteroidArticleCategoryGroup, AsteroidArticlePage, type AsteroidArticlePagePost, type AsteroidArticlePageProps, type AsteroidArticlePageUseArticle, type AsteroidArticlePageUseArticleResult, type AsteroidArticlePost, type AsteroidArticlesCategoryGroupParams, type AsteroidArticlesCategoryHeadingParams, type AsteroidArticlesContentParams, type AsteroidArticlesEmptyParams, type AsteroidArticlesEmptyReason, type AsteroidArticlesFeaturedCardParams, type AsteroidArticlesHeaderParams, AsteroidArticlesListing, type AsteroidArticlesPostCardParams, type AsteroidArticlesPostGridParams, type AsteroidArticlesProps, type AsteroidArticlesSearchParams, type AsteroidArticlesState, type AsteroidArticlesUsePosts, type AsteroidArticlesUsePostsResult, AsteroidCMSProvider, type AsteroidCMSProviderProps, type ExtractHeadingsOptions, type ExtractedHeading, type HeadingLevel, JsonLd, RichTextContent, Seo, type UseCmsContentOptions, type UseCmsMutateOptions, defaultGetCategoryName, defaultGroupPostsByCategory, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidArticlesState, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };