@asteroidcms/core-utils 0.1.8 → 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.js CHANGED
@@ -7,6 +7,7 @@ import { ErrorLink } from '@apollo/client/link/error';
7
7
  import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
8
8
  import { createPortal } from 'react-dom';
9
9
  import hljs from 'highlight.js/lib/common';
10
+ import { useRouter, usePathname, useSearchParams } from 'next/navigation';
10
11
 
11
12
  var AsteroidCMSContext = createContext(null);
12
13
  function useAsteroidCMSConfig() {
@@ -1917,93 +1918,88 @@ function buildCollectionJsonLd(props) {
1917
1918
  inLanguage: "en-US"
1918
1919
  };
1919
1920
  }
1921
+ function renderArticleBody(args) {
1922
+ const { post, cmsImage: cmsImage2, relatedPosts, seoNode, jsonLdNode, renderProps: r } = args;
1923
+ const slot = { post, cmsImage: cmsImage2 };
1924
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1925
+ seoNode,
1926
+ jsonLdNode,
1927
+ r.backLink,
1928
+ r.renderPreArticle?.(slot),
1929
+ r.renderHeader?.(slot),
1930
+ r.renderMeta?.(slot),
1931
+ r.renderDescription?.(slot),
1932
+ r.renderFeaturedImage?.(slot),
1933
+ r.renderToc?.(slot),
1934
+ r.renderContent?.(slot),
1935
+ r.renderMidArticle?.(slot),
1936
+ r.renderTags?.(slot),
1937
+ r.renderAuthorDetails?.(slot),
1938
+ r.renderRelatedPosts?.({ post, relatedPosts, cmsImage: cmsImage2 }),
1939
+ r.renderCTA?.(slot),
1940
+ r.renderPostArticle?.(slot)
1941
+ ] });
1942
+ }
1920
1943
  function AsteroidArticlePage(props) {
1921
1944
  const {
1922
1945
  slug,
1923
1946
  useArticle,
1924
1947
  seo,
1925
1948
  articleType,
1926
- backLink,
1949
+ noindex,
1950
+ relatedPosts = [],
1927
1951
  renderRoot,
1928
1952
  renderSkeleton,
1929
1953
  renderError,
1930
- renderHeader,
1931
- renderMeta,
1932
- renderDescription,
1933
- renderFeaturedImage,
1934
- renderToc,
1935
- renderContent,
1936
- renderPreArticle,
1937
- renderMidArticle,
1938
- renderPostArticle,
1939
- renderTags,
1940
- renderAuthorDetails,
1941
- renderRelatedPosts,
1942
- renderCTA,
1943
1954
  renderJsonLd,
1944
- noindex,
1945
- children
1955
+ children,
1956
+ ...bodyRenderProps
1946
1957
  } = props;
1947
1958
  const { data: article, loading, error } = useArticle(slug);
1948
1959
  const cmsConfig = useContext(AsteroidCMSContext);
1960
+ const cmsImage2 = useCmsImage();
1949
1961
  const seoConfig = seo && !seo.cmsUrl && cmsConfig?.cmsUrl ? { ...seo, cmsUrl: cmsConfig.cmsUrl } : seo;
1950
- if (children) {
1951
- return /* @__PURE__ */ jsx(Fragment$1, { children: children({ data: article, loading, error }) });
1952
- }
1962
+ if (children) return /* @__PURE__ */ jsx(Fragment$1, { children: children({ data: article, loading, error }) });
1953
1963
  if (loading) {
1954
1964
  const body2 = renderSkeleton?.() ?? null;
1955
- return renderRoot ? renderRoot({ children: body2 }) : /* @__PURE__ */ jsx(Fragment$1, { children: body2 });
1965
+ return renderRoot ? /* @__PURE__ */ jsx(Fragment$1, { children: renderRoot({ children: body2 }) }) : /* @__PURE__ */ jsx(Fragment$1, { children: body2 });
1956
1966
  }
1957
1967
  if (!article || error) {
1958
1968
  const body2 = renderError?.({ error, reason: error ? "error" : "not-found" }) ?? null;
1959
- return renderRoot ? renderRoot({ children: body2 }) : /* @__PURE__ */ jsx(Fragment$1, { children: body2 });
1969
+ return renderRoot ? /* @__PURE__ */ jsx(Fragment$1, { children: renderRoot({ children: body2 }) }) : /* @__PURE__ */ jsx(Fragment$1, { children: body2 });
1960
1970
  }
1961
- const seoValues = seoConfig && article ? buildArticleSeoValues(article, seoConfig, slug, { noindex }) : null;
1962
- const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
1963
- seoValues ? /* @__PURE__ */ jsx(Seo, { ...seoValuesToClientProps(seoValues) }) : null,
1964
- seoConfig && article ? renderJsonLd?.({ post: article }) ?? /* @__PURE__ */ jsx(
1965
- JsonLd,
1966
- {
1967
- data: buildArticleJsonLd({
1968
- title: article.title,
1969
- description: article.description || seoConfig.defaultDescription || "",
1970
- url: `${(seoConfig.baseUrl || "").replace(/\/$/, "")}${seoConfig.articlePath ?? "/blog"}/${slug}`,
1971
- siteName: seoConfig.siteName,
1972
- siteUrl: (seoConfig.baseUrl || "").replace(/\/$/, ""),
1973
- articleType,
1974
- image: seoValues?.image,
1975
- authorName: article.author?.name,
1976
- publishedTime: article.published_date || void 0,
1977
- tags: article.tags?.split(",").map((t) => t.trim()).filter(Boolean),
1978
- category: article.category?.name
1979
- })
1980
- }
1981
- ) : null,
1982
- backLink,
1983
- renderPreArticle?.({ post: article }),
1984
- renderHeader?.({ post: article }),
1985
- renderMeta?.({ post: article }),
1986
- renderDescription?.({ post: article }),
1987
- renderFeaturedImage?.({ post: article }),
1988
- renderToc?.({ post: article }),
1989
- renderContent?.({ post: article }),
1990
- renderMidArticle?.({ post: article }),
1991
- renderTags?.({ post: article }),
1992
- renderAuthorDetails?.({ post: article }),
1993
- renderRelatedPosts?.({ post: article }),
1994
- renderCTA?.({ post: article }),
1995
- renderPostArticle?.({ post: article })
1996
- ] });
1997
- return renderRoot ? renderRoot({ children: body }) : /* @__PURE__ */ jsx(Fragment$1, { children: body });
1998
- }
1999
- function useDebouncedValue(value, delay) {
2000
- const [debouncedValue, setDebouncedValue] = useState(value);
2001
- useEffect(() => {
2002
- const timer = setTimeout(() => setDebouncedValue(value), delay);
2003
- return () => clearTimeout(timer);
2004
- }, [value, delay]);
2005
- return debouncedValue;
1971
+ const seoValues = seoConfig ? buildArticleSeoValues(article, seoConfig, slug, { noindex }) : null;
1972
+ const seoNode = seoValues ? /* @__PURE__ */ jsx(Seo, { ...seoValuesToClientProps(seoValues) }) : null;
1973
+ const jsonLdNode = seoConfig ? renderJsonLd?.({ post: article }) ?? /* @__PURE__ */ jsx(
1974
+ JsonLd,
1975
+ {
1976
+ data: buildArticleJsonLd({
1977
+ title: article.title,
1978
+ description: article.description || seoConfig.defaultDescription || "",
1979
+ url: `${(seoConfig.baseUrl || "").replace(/\/$/, "")}${seoConfig.articlePath ?? "/blog"}/${slug}`,
1980
+ siteName: seoConfig.siteName,
1981
+ siteUrl: (seoConfig.baseUrl || "").replace(/\/$/, ""),
1982
+ articleType,
1983
+ image: seoValues?.image,
1984
+ authorName: article.author?.name,
1985
+ publishedTime: article.published_date || void 0,
1986
+ tags: article.tags?.split(",").map((t) => t.trim()).filter(Boolean),
1987
+ category: article.category?.name
1988
+ })
1989
+ }
1990
+ ) : null;
1991
+ const body = renderArticleBody({
1992
+ post: article,
1993
+ cmsImage: cmsImage2,
1994
+ relatedPosts,
1995
+ seoNode,
1996
+ jsonLdNode,
1997
+ renderProps: bodyRenderProps
1998
+ });
1999
+ return renderRoot ? /* @__PURE__ */ jsx(Fragment$1, { children: renderRoot({ children: body }) }) : /* @__PURE__ */ jsx(Fragment$1, { children: body });
2006
2000
  }
2001
+
2002
+ // src/components/articles/articles.state.ts
2007
2003
  function defaultGetCategoryName(post) {
2008
2004
  return post.category?.name?.trim() || void 0;
2009
2005
  }
@@ -2021,10 +2017,7 @@ function defaultGroupPostsByCategory(posts) {
2021
2017
  }
2022
2018
  return Array.from(groups.values());
2023
2019
  }
2024
- function applyPostFilters(posts, {
2025
- categorySlug,
2026
- articleSlug
2027
- }) {
2020
+ function applyPostFilters(posts, { categorySlug, articleSlug }) {
2028
2021
  let filtered = posts;
2029
2022
  if (categorySlug) {
2030
2023
  filtered = filtered.filter((post) => post.category?.slug === categorySlug);
@@ -2039,65 +2032,42 @@ function splitFeaturedAndRest(posts) {
2039
2032
  const rest = featured ? posts.filter((post) => post.slug !== featured.slug) : [...posts];
2040
2033
  return { featured, rest };
2041
2034
  }
2042
- function useAsteroidArticlesState({
2043
- usePosts,
2044
- categorySlug,
2045
- articleSlug,
2046
- searchDebounceMs = 800,
2047
- groupPostsByCategory = defaultGroupPostsByCategory
2048
- }) {
2049
- const [searchQuery, setSearchQuery] = useState("");
2050
- const debouncedSearchQuery = useDebouncedValue(searchQuery, searchDebounceMs);
2051
- const { posts: rawPosts, loading, error } = usePosts(debouncedSearchQuery);
2052
- const posts = useMemo(
2053
- () => applyPostFilters(rawPosts, { categorySlug, articleSlug }),
2054
- [rawPosts, categorySlug, articleSlug]
2055
- );
2056
- const { featured, rest } = useMemo(
2057
- () => splitFeaturedAndRest(posts),
2058
- [posts]
2059
- );
2060
- const isSearching = debouncedSearchQuery.trim().length > 0;
2061
- const categoryGroups = useMemo(() => {
2062
- if (isSearching) {
2063
- if (posts.length === 0) return [];
2064
- return [
2065
- {
2066
- categoryName: `Search results for "${debouncedSearchQuery.trim()}"`,
2067
- categorySlug: "search-results",
2068
- posts
2069
- }
2070
- ];
2035
+ function buildArticlesViewState(rawPosts, options) {
2036
+ const {
2037
+ categorySlug,
2038
+ articleSlug,
2039
+ searchQuery = "",
2040
+ groupPostsByCategory = defaultGroupPostsByCategory
2041
+ } = options;
2042
+ const posts = applyPostFilters(rawPosts, { categorySlug, articleSlug });
2043
+ const { featured, rest } = splitFeaturedAndRest(posts);
2044
+ const trimmedQuery = searchQuery.trim();
2045
+ const isSearching = trimmedQuery.length > 0;
2046
+ const categoryGroups = isSearching ? posts.length === 0 ? [] : [
2047
+ {
2048
+ categoryName: `Search results for "${trimmedQuery}"`,
2049
+ categorySlug: "search-results",
2050
+ posts
2071
2051
  }
2072
- return groupPostsByCategory(rest);
2073
- }, [isSearching, posts, debouncedSearchQuery, rest, groupPostsByCategory]);
2074
- const hasError = Boolean(error);
2075
- const isEmpty = !featured && rest.length === 0;
2052
+ ] : groupPostsByCategory(rest);
2076
2053
  return {
2077
2054
  posts,
2078
2055
  featured,
2079
2056
  rest,
2080
2057
  categoryGroups,
2081
- loading,
2082
- error,
2083
- hasError,
2084
- isEmpty,
2058
+ isEmpty: !featured && rest.length === 0,
2085
2059
  isSearching,
2086
- searchQuery,
2087
- debouncedSearchQuery,
2088
- setSearchQuery
2060
+ searchQuery: trimmedQuery
2089
2061
  };
2090
2062
  }
2091
- function AsteroidArticlesListing(props) {
2063
+ function renderArticlesListingBody(args) {
2064
+ const { state, loading, hasError, error, cmsImage: cmsImage2, searchNode, seoNode, jsonLdNode, renderProps } = args;
2092
2065
  const {
2093
2066
  eyebrow,
2094
2067
  title,
2095
2068
  description,
2096
- seo,
2097
- categorySlug,
2098
2069
  renderRoot,
2099
2070
  renderHeader,
2100
- renderSearch,
2101
2071
  renderFeaturedCard,
2102
2072
  renderPostCard,
2103
2073
  renderCategoryHeading,
@@ -2105,73 +2075,27 @@ function AsteroidArticlesListing(props) {
2105
2075
  renderCategoryGroup,
2106
2076
  renderSkeleton,
2107
2077
  renderEmpty,
2108
- renderContent,
2109
- renderJsonLd,
2110
- noindex,
2111
- children
2112
- } = props;
2113
- const state = useAsteroidArticlesState(props);
2114
- const categoryName = categorySlug ? state.posts[0]?.category?.name?.trim() : void 0;
2115
- if (children) {
2116
- return /* @__PURE__ */ jsx(Fragment$1, { children: children(state) });
2117
- }
2118
- const seoNode = seo ? /* @__PURE__ */ jsx(
2119
- Seo,
2120
- {
2121
- ...seoValuesToClientProps(
2122
- buildArticleListingSeoValues(seo, {
2123
- categoryName,
2124
- categorySlug,
2125
- noindex
2126
- })
2127
- )
2128
- }
2129
- ) : null;
2130
- const jsonLdNode = seo ? renderJsonLd?.(state) ?? /* @__PURE__ */ jsx(
2131
- JsonLd,
2132
- {
2133
- data: buildCollectionJsonLd({
2134
- name: categoryName || `${seo.siteName} ${seo.contentLabel ?? "Articles"}`,
2135
- description: seo.defaultDescription || "",
2136
- url: `${(seo.baseUrl || "").replace(/\/$/, "")}${seo.articlePath ?? "/blog"}${categorySlug ? `/category/${categorySlug}` : ""}`,
2137
- siteUrl: (seo.baseUrl || "").replace(/\/$/, "")
2138
- })
2139
- }
2140
- ) : null;
2141
- const handleSearchSubmit = (event) => {
2142
- event.preventDefault();
2143
- };
2144
- const searchNode = renderSearch ? renderSearch({
2145
- value: state.searchQuery,
2146
- onChange: state.setSearchQuery,
2147
- onSubmit: handleSearchSubmit
2148
- }) : null;
2078
+ renderContent
2079
+ } = renderProps;
2149
2080
  const headerNode = renderHeader ? renderHeader({ eyebrow, title, description, search: searchNode }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
2150
2081
  eyebrow,
2151
2082
  title,
2152
2083
  description,
2153
2084
  searchNode
2154
2085
  ] });
2155
- const featuredNode = state.featured && !state.isSearching && renderFeaturedCard ? renderFeaturedCard({ post: state.featured }) : null;
2156
- const noSearchResultsNode = state.isSearching && !state.loading && state.posts.length === 0 ? renderEmpty?.({
2157
- reason: "no-results",
2158
- searchQuery: state.debouncedSearchQuery.trim()
2159
- }) ?? null : null;
2086
+ const featuredNode = state.featured && !state.isSearching && renderFeaturedCard ? renderFeaturedCard({ post: state.featured, cmsImage: cmsImage2 }) : null;
2087
+ const noSearchResultsNode = state.isSearching && !loading && state.posts.length === 0 ? renderEmpty?.({ reason: "no-results", searchQuery: state.searchQuery }) ?? null : null;
2160
2088
  const groupsNode = noSearchResultsNode ? null : state.categoryGroups.map((group) => {
2161
- const postCards = group.posts.map((post, index) => /* @__PURE__ */ jsx(Fragment, { children: renderPostCard({ post, index, group }) }, post.slug ?? index));
2089
+ const postCards = group.posts.map((post, index) => /* @__PURE__ */ jsx(Fragment, { children: renderPostCard({ post, index, group, cmsImage: cmsImage2 }) }, post.slug ?? index));
2162
2090
  const gridNode = renderPostGrid ? renderPostGrid({ posts: group.posts, group, children: postCards }) : /* @__PURE__ */ jsx(Fragment$1, { children: postCards });
2163
2091
  const headingNode = renderCategoryHeading ? renderCategoryHeading({ group }) : group.categoryName;
2164
2092
  const defaultContent = /* @__PURE__ */ jsxs(Fragment$1, { children: [
2165
2093
  headingNode,
2166
2094
  gridNode
2167
2095
  ] });
2168
- return renderCategoryGroup ? renderCategoryGroup({ group, defaultContent }) : defaultContent;
2096
+ return /* @__PURE__ */ jsx(Fragment, { children: renderCategoryGroup ? renderCategoryGroup({ group, defaultContent }) : defaultContent }, group.categorySlug);
2169
2097
  });
2170
- const contentNode = !state.loading && !state.hasError && (state.featured || state.rest.length > 0) ? renderContent ? renderContent({
2171
- featured: featuredNode,
2172
- groups: groupsNode,
2173
- noSearchResults: noSearchResultsNode
2174
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
2098
+ const contentNode = !loading && !hasError && (state.featured || state.rest.length > 0) ? renderContent ? renderContent({ featured: featuredNode, groups: groupsNode, noSearchResults: noSearchResultsNode }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
2175
2099
  featuredNode,
2176
2100
  noSearchResultsNode,
2177
2101
  groupsNode
@@ -2180,17 +2104,128 @@ function AsteroidArticlesListing(props) {
2180
2104
  seoNode,
2181
2105
  jsonLdNode,
2182
2106
  headerNode,
2183
- state.loading ? renderSkeleton?.() : null,
2184
- !state.loading && (state.hasError || state.isEmpty) ? renderEmpty?.({
2185
- reason: state.hasError ? "error" : "no-posts",
2186
- searchQuery: state.debouncedSearchQuery.trim(),
2187
- error: state.error
2107
+ loading ? renderSkeleton?.() : null,
2108
+ !loading && (hasError || state.isEmpty) ? renderEmpty?.({
2109
+ reason: hasError ? "error" : state.isSearching ? "no-results" : "no-posts",
2110
+ searchQuery: state.searchQuery,
2111
+ error
2188
2112
  }) : null,
2189
2113
  contentNode
2190
2114
  ] });
2191
2115
  return renderRoot ? renderRoot({ children: body }) : /* @__PURE__ */ jsx(Fragment$1, { children: body });
2192
2116
  }
2117
+ function useDebouncedValue(value, delay) {
2118
+ const [debounced, setDebounced] = useState(value);
2119
+ useEffect(() => {
2120
+ const timer = setTimeout(() => setDebounced(value), delay);
2121
+ return () => clearTimeout(timer);
2122
+ }, [value, delay]);
2123
+ return debounced;
2124
+ }
2125
+ function useAsteroidArticlesState(props) {
2126
+ const { usePosts, categorySlug, articleSlug, searchDebounceMs = 800, groupPostsByCategory } = props;
2127
+ const [inputValue, setSearchQuery] = useState("");
2128
+ const debouncedSearchQuery = useDebouncedValue(inputValue, searchDebounceMs);
2129
+ const { posts: rawPosts, loading, error } = usePosts(debouncedSearchQuery);
2130
+ const view = useMemo(
2131
+ () => buildArticlesViewState(rawPosts, {
2132
+ categorySlug,
2133
+ articleSlug,
2134
+ searchQuery: debouncedSearchQuery,
2135
+ groupPostsByCategory
2136
+ }),
2137
+ [rawPosts, categorySlug, articleSlug, debouncedSearchQuery, groupPostsByCategory]
2138
+ );
2139
+ return {
2140
+ ...view,
2141
+ loading,
2142
+ error,
2143
+ hasError: Boolean(error),
2144
+ inputValue,
2145
+ setSearchQuery
2146
+ };
2147
+ }
2148
+ function AsteroidArticlesListing(props) {
2149
+ const { seo, categorySlug, noindex, renderSearch, renderJsonLd, children, ...renderProps } = props;
2150
+ const state = useAsteroidArticlesState(props);
2151
+ const cmsImage2 = useCmsImage();
2152
+ if (children) return /* @__PURE__ */ jsx(Fragment$1, { children: children(state) });
2153
+ const categoryName = categorySlug ? state.posts[0]?.category?.name?.trim() : void 0;
2154
+ const seoNode = seo ? /* @__PURE__ */ jsx(
2155
+ Seo,
2156
+ {
2157
+ ...seoValuesToClientProps(
2158
+ buildArticleListingSeoValues(seo, { categoryName, categorySlug, noindex })
2159
+ )
2160
+ }
2161
+ ) : null;
2162
+ const jsonLdNode = seo ? renderJsonLd?.(state) ?? /* @__PURE__ */ jsx(
2163
+ JsonLd,
2164
+ {
2165
+ data: buildCollectionJsonLd({
2166
+ name: categoryName || `${seo.siteName} ${seo.contentLabel ?? "Articles"}`,
2167
+ description: seo.defaultDescription || "",
2168
+ url: `${(seo.baseUrl || "").replace(/\/$/, "")}${seo.articlePath ?? "/blog"}${categorySlug ? `/category/${categorySlug}` : ""}`,
2169
+ siteUrl: (seo.baseUrl || "").replace(/\/$/, "")
2170
+ })
2171
+ }
2172
+ ) : null;
2173
+ const searchNode = renderSearch ? renderSearch({
2174
+ value: state.inputValue,
2175
+ onChange: state.setSearchQuery,
2176
+ onSubmit: (event) => event.preventDefault()
2177
+ }) : null;
2178
+ return /* @__PURE__ */ jsx(Fragment$1, { children: renderArticlesListingBody({
2179
+ state,
2180
+ loading: state.loading,
2181
+ hasError: state.hasError,
2182
+ error: state.error,
2183
+ cmsImage: cmsImage2,
2184
+ searchNode,
2185
+ seoNode,
2186
+ jsonLdNode,
2187
+ renderProps
2188
+ }) });
2189
+ }
2190
+ function ArticleSearchBox({
2191
+ paramKey = "q",
2192
+ placeholder = "Search articles...",
2193
+ debounceMs = 500,
2194
+ className,
2195
+ render
2196
+ }) {
2197
+ const router = useRouter();
2198
+ const pathname = usePathname();
2199
+ const searchParams = useSearchParams();
2200
+ const initial = searchParams.get(paramKey) ?? "";
2201
+ const [value, setValue] = useState(initial);
2202
+ const searchParamsRef = useRef(searchParams);
2203
+ searchParamsRef.current = searchParams;
2204
+ useEffect(() => {
2205
+ const timer = setTimeout(() => {
2206
+ const params = new URLSearchParams(Array.from(searchParamsRef.current.entries()));
2207
+ const trimmed = value.trim();
2208
+ if (trimmed) params.set(paramKey, trimmed);
2209
+ else params.delete(paramKey);
2210
+ const query = params.toString();
2211
+ router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false });
2212
+ }, debounceMs);
2213
+ return () => clearTimeout(timer);
2214
+ }, [value, debounceMs, paramKey, pathname]);
2215
+ const onSubmit = (event) => event.preventDefault();
2216
+ if (render) return /* @__PURE__ */ jsx(Fragment$1, { children: render({ value, onChange: setValue, onSubmit }) });
2217
+ return /* @__PURE__ */ jsx("form", { onSubmit, className, children: /* @__PURE__ */ jsx(
2218
+ "input",
2219
+ {
2220
+ type: "search",
2221
+ value,
2222
+ placeholder,
2223
+ "aria-label": placeholder,
2224
+ onChange: (event) => setValue(event.target.value)
2225
+ }
2226
+ ) });
2227
+ }
2193
2228
 
2194
- export { AsteroidArticlePage, AsteroidArticlesListing, AsteroidCMSProvider, JsonLd, RichTextContent, Seo, defaultGetCategoryName, defaultGroupPostsByCategory, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidArticlesState, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
2229
+ export { ArticleSearchBox, AsteroidArticlePage, AsteroidArticlesListing, AsteroidCMSProvider, JsonLd, RichTextContent, Seo, defaultGetCategoryName, defaultGroupPostsByCategory, extractHeadingsFromElement, extractHeadingsFromHtml, slugify, useAsteroidArticlesState, useAsteroidCMSConfig, useCmsContent, useCmsImage, useCmsMutate };
2195
2230
  //# sourceMappingURL=client.js.map
2196
2231
  //# sourceMappingURL=client.js.map