@contentgrowth/content-widget 1.1.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +442 -0
  3. package/dist/astro/ContentList.astro +177 -0
  4. package/dist/astro/ContentViewer.astro +252 -0
  5. package/dist/astro/index.d.ts +9 -0
  6. package/dist/astro/index.d.ts.map +1 -0
  7. package/dist/astro/index.js +8 -0
  8. package/dist/core/client.d.ts +67 -0
  9. package/dist/core/client.d.ts.map +1 -0
  10. package/dist/core/client.js +217 -0
  11. package/dist/core/index.d.ts +8 -0
  12. package/dist/core/index.d.ts.map +1 -0
  13. package/dist/core/index.js +7 -0
  14. package/dist/core/utils.d.ts +32 -0
  15. package/dist/core/utils.d.ts.map +1 -0
  16. package/dist/core/utils.js +70 -0
  17. package/dist/index.d.ts +7 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +6 -0
  20. package/dist/react/ContentList.d.ts +12 -0
  21. package/dist/react/ContentList.d.ts.map +1 -0
  22. package/dist/react/ContentList.js +106 -0
  23. package/dist/react/ContentViewer.d.ts +12 -0
  24. package/dist/react/ContentViewer.d.ts.map +1 -0
  25. package/dist/react/ContentViewer.js +97 -0
  26. package/dist/react/hooks.d.ts +63 -0
  27. package/dist/react/hooks.d.ts.map +1 -0
  28. package/dist/react/hooks.js +140 -0
  29. package/dist/react/index.d.ts +9 -0
  30. package/dist/react/index.d.ts.map +1 -0
  31. package/dist/react/index.js +6 -0
  32. package/dist/styles.css +970 -0
  33. package/dist/types/index.d.ts +271 -0
  34. package/dist/types/index.d.ts.map +1 -0
  35. package/dist/types/index.js +16 -0
  36. package/dist/vue/ContentList.vue +166 -0
  37. package/dist/vue/ContentViewer.vue +137 -0
  38. package/dist/vue/composables.d.ts +64 -0
  39. package/dist/vue/composables.d.ts.map +1 -0
  40. package/dist/vue/composables.js +165 -0
  41. package/dist/vue/index.d.ts +10 -0
  42. package/dist/vue/index.d.ts.map +1 -0
  43. package/dist/vue/index.js +8 -0
  44. package/dist/widget/content-card.js +190 -0
  45. package/dist/widget/content-list.js +289 -0
  46. package/dist/widget/content-viewer.js +230 -0
  47. package/dist/widget/index.js +40 -0
  48. package/dist/widget/utils/api-client.js +154 -0
  49. package/dist/widget/utils/helpers.js +71 -0
  50. package/dist/widget/widget-js/content-card.js +190 -0
  51. package/dist/widget/widget-js/content-list.js +289 -0
  52. package/dist/widget/widget-js/content-viewer.js +230 -0
  53. package/dist/widget/widget-js/index.js +40 -0
  54. package/dist/widget/widget-js/utils/api-client.js +154 -0
  55. package/dist/widget/widget-js/utils/helpers.js +71 -0
  56. package/dist/widget/widget-js/widget.d.ts +24 -0
  57. package/dist/widget/widget-js/widget.js +240 -0
  58. package/dist/widget/widget.d.ts +24 -0
  59. package/dist/widget/widget.js +240 -0
  60. package/package.json +99 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Content Growth Content Widget
3
+ * @packageDocumentation
4
+ */
5
+ export * from './core/index.js';
6
+ export type * from './types/index.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,iBAAiB,CAAC;AAGhC,mBAAmB,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Content Growth Content Widget
3
+ * @packageDocumentation
4
+ */
5
+ // Export everything from core
6
+ export * from './core/index.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * React ContentList Component
3
+ * Displays a list of articles with pagination
4
+ */
5
+ import React from 'react';
6
+ import type { ContentListProps } from '../types/index.js';
7
+ export interface ReactContentListProps extends Omit<ContentListProps, 'class'> {
8
+ className?: string;
9
+ }
10
+ export declare const ContentList: React.FC<ReactContentListProps>;
11
+ export default ContentList;
12
+ //# sourceMappingURL=ContentList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentList.d.ts","sourceRoot":"","sources":["../../src/react/ContentList.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,gBAAgB,EAAW,MAAM,mBAAmB,CAAC;AAEnE,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAgLvD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * React ContentList Component
3
+ * Displays a list of articles with pagination
4
+ */
5
+ import React, { useEffect, useState } from 'react';
6
+ import { ContentGrowthClient } from '../core/client.js';
7
+ import { formatDate, calculateReadingTime } from '../core/utils.js';
8
+ export const ContentList = ({ apiKey, baseUrl, layout = 'cards', displayMode = 'comfortable', theme = 'light', pageSize = 12, tags = [], category, showPagination = true, linkPattern = '/articles/{uuid}', showTags = false, showAiSummary = true, summaryMaxLength, linkTarget, className = '' }) => {
9
+ const [articles, setArticles] = useState([]);
10
+ const [currentPage, setCurrentPage] = useState(1);
11
+ const [totalPages, setTotalPages] = useState(1);
12
+ const [loading, setLoading] = useState(true);
13
+ useEffect(() => {
14
+ const fetchArticles = async () => {
15
+ setLoading(true);
16
+ try {
17
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
18
+ // Process tags
19
+ let processedTags;
20
+ const tagsProp = tags;
21
+ if (tagsProp) {
22
+ if (Array.isArray(tagsProp)) {
23
+ processedTags = tagsProp;
24
+ }
25
+ else if (typeof tagsProp === 'string') {
26
+ processedTags = tagsProp.split(',').map((t) => t.trim()).filter(Boolean);
27
+ }
28
+ }
29
+ const result = await client.listArticles({
30
+ page: currentPage,
31
+ limit: pageSize,
32
+ tags: processedTags,
33
+ category
34
+ });
35
+ setArticles(result.articles);
36
+ setTotalPages(result.pagination.totalPages);
37
+ }
38
+ catch (error) {
39
+ console.error('Error fetching articles:', error);
40
+ }
41
+ finally {
42
+ setLoading(false);
43
+ }
44
+ };
45
+ fetchArticles();
46
+ }, [apiKey, baseUrl, currentPage, pageSize, tags, category]);
47
+ // Truncate summary text
48
+ const truncateSummary = (text, maxLength) => {
49
+ if (!text)
50
+ return '';
51
+ if (!maxLength || text.length <= maxLength)
52
+ return text;
53
+ return text.substring(0, maxLength).trim() + '...';
54
+ };
55
+ // Build article URL from pattern
56
+ const buildArticleUrl = (article) => {
57
+ return linkPattern
58
+ .replace('{uuid}', article.uuid)
59
+ .replace('{slug}', article.slug)
60
+ .replace('{category}', article.category || '');
61
+ };
62
+ // Build link target from pattern
63
+ const buildLinkTarget = (article) => {
64
+ if (!linkTarget)
65
+ return undefined;
66
+ return linkTarget
67
+ .replace('{uuid}', article.uuid)
68
+ .replace('{id}', article.uuid);
69
+ };
70
+ if (loading) {
71
+ return (React.createElement("div", { className: `cg-content-list cg-layout-${layout} cg-display-${displayMode} cg-theme-${theme} ${className}` },
72
+ React.createElement("div", { className: "cg-empty-state" },
73
+ React.createElement("p", null, "Loading..."))));
74
+ }
75
+ return (React.createElement("div", { className: `cg-content-list cg-layout-${layout} cg-display-${displayMode} cg-theme-${theme} ${className}`, "data-cg-widget": "list" }, articles.length === 0 ? (React.createElement("div", { className: "cg-empty-state" },
76
+ React.createElement("p", null, "No articles found."))) : (React.createElement(React.Fragment, null,
77
+ React.createElement("div", { className: `cg-articles-grid ${layout === 'cards' ? 'cg-grid' : 'cg-list'}` }, articles.map((article) => {
78
+ const articleUrl = buildArticleUrl(article);
79
+ const articleTarget = buildLinkTarget(article);
80
+ const readingTime = calculateReadingTime(article.wordCount);
81
+ const publishedDate = formatDate(article.publishedAt);
82
+ return (React.createElement("article", { key: article.uuid, className: "cg-article-card" },
83
+ React.createElement("a", { href: articleUrl, target: articleTarget, className: "cg-card-link" },
84
+ React.createElement("div", { className: "cg-card-content" },
85
+ article.category && (React.createElement("div", { className: "cg-card-category" },
86
+ React.createElement("span", { className: "cg-category-badge" }, article.category))),
87
+ React.createElement("h2", { className: "cg-card-title" }, article.title),
88
+ showAiSummary && article.summary && (React.createElement("p", { className: "cg-card-summary" }, truncateSummary(article.summary, summaryMaxLength))),
89
+ React.createElement("div", { className: "cg-card-meta" },
90
+ React.createElement("span", { className: "cg-meta-author" }, article.authorName),
91
+ React.createElement("span", { className: "cg-meta-separator" }, "\u2022"),
92
+ React.createElement("time", { className: "cg-meta-date", dateTime: new Date(article.publishedAt * 1000).toISOString() }, publishedDate),
93
+ React.createElement("span", { className: "cg-meta-separator" }, "\u2022"),
94
+ React.createElement("span", { className: "cg-meta-reading-time" }, readingTime)),
95
+ showTags && article.tags && article.tags.length > 0 && (React.createElement("div", { className: "cg-card-tags" }, article.tags.map((tag) => (React.createElement("span", { key: tag, className: "cg-tag" }, tag)))))))));
96
+ })),
97
+ showPagination && totalPages > 1 && (React.createElement("div", { className: "cg-pagination" },
98
+ React.createElement("button", { className: "cg-pagination-btn", onClick: () => setCurrentPage(p => Math.max(1, p - 1)), disabled: currentPage === 1 }, "Previous"),
99
+ React.createElement("span", { className: "cg-pagination-info" },
100
+ "Page ",
101
+ currentPage,
102
+ " of ",
103
+ totalPages),
104
+ React.createElement("button", { className: "cg-pagination-btn", onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), disabled: currentPage === totalPages }, "Next")))))));
105
+ };
106
+ export default ContentList;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * React ContentViewer Component
3
+ * Displays a single article with full content
4
+ */
5
+ import React from 'react';
6
+ import type { ContentViewerProps } from '../types/index.js';
7
+ export interface ReactContentViewerProps extends Omit<ContentViewerProps, 'class'> {
8
+ className?: string;
9
+ }
10
+ export declare const ContentViewer: React.FC<ReactContentViewerProps>;
11
+ export default ContentViewer;
12
+ //# sourceMappingURL=ContentViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentViewer.d.ts","sourceRoot":"","sources":["../../src/react/ContentViewer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,mBAAmB,CAAC;AAEhF,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAsJ3D,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * React ContentViewer Component
3
+ * Displays a single article with full content
4
+ */
5
+ import React, { useEffect, useState } from 'react';
6
+ import { ContentGrowthClient } from '../core/client.js';
7
+ import { formatDate, calculateReadingTime } from '../core/utils.js';
8
+ import { marked } from 'marked';
9
+ export const ContentViewer = ({ apiKey, uuid, slug, baseUrl, theme = 'light', showBackButton = false, backUrl = '/articles', showAiSummary = true, className = '' }) => {
10
+ const [article, setArticle] = useState(null);
11
+ const [loading, setLoading] = useState(true);
12
+ const [error, setError] = useState(null);
13
+ useEffect(() => {
14
+ const fetchArticle = async () => {
15
+ if (!uuid && !slug) {
16
+ setError('Either uuid or slug must be provided');
17
+ setLoading(false);
18
+ return;
19
+ }
20
+ setLoading(true);
21
+ try {
22
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
23
+ const fetchedArticle = slug
24
+ ? await client.getArticleBySlug(slug)
25
+ : await client.getArticle(uuid);
26
+ setArticle(fetchedArticle);
27
+ }
28
+ catch (err) {
29
+ setError(err instanceof Error ? err.message : 'Failed to load article');
30
+ }
31
+ finally {
32
+ setLoading(false);
33
+ }
34
+ };
35
+ fetchArticle();
36
+ }, [apiKey, baseUrl, uuid, slug]);
37
+ // Process markdown content to handle custom image syntax
38
+ const processImageSyntax = (markdown) => {
39
+ // Match: ![alt](url =widthxheight)
40
+ return markdown.replace(/!\[([^\]]*)\]\(([^\s)]+)\s+=(\d+)x(\d+)\)/g, (match, alt, url, width, height) => {
41
+ return `![${alt}](${url}){width="${width}" height="${height}"}`;
42
+ });
43
+ };
44
+ // Configure marked to handle image attributes
45
+ marked.use({
46
+ renderer: {
47
+ image(href, title, text) {
48
+ // Extract width/height from {width="x" height="y"} syntax
49
+ const attrMatch = text.match(/\{width="(\d+)"\s+height="(\d+)"\}/);
50
+ if (attrMatch) {
51
+ const cleanText = text.replace(/\{[^}]+\}/, '').trim();
52
+ return `<img src="${href}" alt="${cleanText}" width="${attrMatch[1]}" height="${attrMatch[2]}" ${title ? `title="${title}"` : ''} />`;
53
+ }
54
+ return `<img src="${href}" alt="${text}" ${title ? `title="${title}"` : ''} />`;
55
+ }
56
+ }
57
+ });
58
+ if (loading) {
59
+ return (React.createElement("div", { className: `cg-content-viewer cg-theme-${theme} ${className}` },
60
+ React.createElement("div", { className: "cg-empty-state" },
61
+ React.createElement("p", null, "Loading..."))));
62
+ }
63
+ if (error || !article) {
64
+ return (React.createElement("div", { className: `cg-content-viewer cg-theme-${theme} ${className}` },
65
+ React.createElement("div", { className: "cg-empty-state" },
66
+ React.createElement("p", null, error || 'Article not found'))));
67
+ }
68
+ const processedContent = processImageSyntax(article.content);
69
+ const contentHtml = marked(processedContent);
70
+ const publishedDate = formatDate(article.publishedAt);
71
+ const readingTime = calculateReadingTime(article.wordCount);
72
+ return (React.createElement("article", { className: `cg-content-viewer cg-theme-${theme} ${className}`, "data-cg-widget": "post" },
73
+ showBackButton && (React.createElement("div", { className: "cg-post-header" },
74
+ React.createElement("a", { href: backUrl, className: "cg-back-btn" },
75
+ React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none" },
76
+ React.createElement("path", { d: "M12 16L6 10L12 4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })),
77
+ "Back to articles"))),
78
+ React.createElement("header", { className: "cg-post-meta" },
79
+ article.category && (React.createElement("div", { className: "cg-post-category" },
80
+ React.createElement("span", { className: "cg-category-badge" }, article.category))),
81
+ React.createElement("h1", { className: "cg-post-title" }, article.title),
82
+ showAiSummary && article.summary && (React.createElement("div", { className: "cg-ai-summary" },
83
+ React.createElement("div", { className: "cg-ai-summary-header" },
84
+ React.createElement("svg", { className: "cg-ai-summary-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
85
+ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13 10V3L4 14h7v7l9-11h-7z" })),
86
+ React.createElement("span", { className: "cg-ai-summary-label" }, "AI Generated Summary")),
87
+ React.createElement("p", { className: "cg-ai-summary-text" }, article.summary))),
88
+ React.createElement("div", { className: "cg-post-info" },
89
+ React.createElement("span", { className: "cg-info-author" }, article.authorName),
90
+ React.createElement("span", { className: "cg-info-separator" }, "\u2022"),
91
+ React.createElement("time", { className: "cg-info-date", dateTime: new Date(article.publishedAt * 1000).toISOString() }, publishedDate),
92
+ React.createElement("span", { className: "cg-info-separator" }, "\u2022"),
93
+ React.createElement("span", { className: "cg-info-reading-time" }, readingTime)),
94
+ article.tags.length > 0 && (React.createElement("div", { className: "cg-post-tags" }, article.tags.map((tag) => (React.createElement("span", { key: tag, className: "cg-tag" }, tag)))))),
95
+ React.createElement("div", { className: "cg-post-content", dangerouslySetInnerHTML: { __html: contentHtml } })));
96
+ };
97
+ export default ContentViewer;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * React Hooks for Content Growth API
3
+ */
4
+ import type { Article, ArticleWithContent, Pagination, Category, Tag, ListArticlesOptions } from '../types/index.js';
5
+ export interface UseArticlesOptions extends ListArticlesOptions {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ }
9
+ export interface UseArticlesResult {
10
+ articles: Article[];
11
+ pagination: Pagination | null;
12
+ loading: boolean;
13
+ error: Error | null;
14
+ refetch: () => Promise<void>;
15
+ }
16
+ /**
17
+ * Hook to fetch articles list
18
+ */
19
+ export declare function useArticles(options: UseArticlesOptions): UseArticlesResult;
20
+ export interface UseArticleOptions {
21
+ apiKey: string;
22
+ uuid: string;
23
+ baseUrl?: string;
24
+ }
25
+ export interface UseArticleResult {
26
+ article: ArticleWithContent | null;
27
+ loading: boolean;
28
+ error: Error | null;
29
+ refetch: () => Promise<void>;
30
+ }
31
+ /**
32
+ * Hook to fetch a single article
33
+ */
34
+ export declare function useArticle(options: UseArticleOptions): UseArticleResult;
35
+ export interface UseCategoriesOptions {
36
+ apiKey: string;
37
+ baseUrl?: string;
38
+ }
39
+ export interface UseCategoriesResult {
40
+ categories: Category[];
41
+ loading: boolean;
42
+ error: Error | null;
43
+ refetch: () => Promise<void>;
44
+ }
45
+ /**
46
+ * Hook to fetch categories
47
+ */
48
+ export declare function useCategories(options: UseCategoriesOptions): UseCategoriesResult;
49
+ export interface UseTagsOptions {
50
+ apiKey: string;
51
+ baseUrl?: string;
52
+ }
53
+ export interface UseTagsResult {
54
+ tags: Tag[];
55
+ loading: boolean;
56
+ error: Error | null;
57
+ refetch: () => Promise<void>;
58
+ }
59
+ /**
60
+ * Hook to fetch tags
61
+ */
62
+ export declare function useTags(options: UseTagsOptions): UseTagsResult;
63
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,OAAO,EACP,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,GAAG,EACH,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAkC1E;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CA+BvE;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA+BhF;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CA+B9D"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * React Hooks for Content Growth API
3
+ */
4
+ import { useState, useEffect, useCallback } from 'react';
5
+ import { ContentGrowthClient } from '../core/client.js';
6
+ /**
7
+ * Hook to fetch articles list
8
+ */
9
+ export function useArticles(options) {
10
+ const { apiKey, baseUrl, ...listOptions } = options;
11
+ const [articles, setArticles] = useState([]);
12
+ const [pagination, setPagination] = useState(null);
13
+ const [loading, setLoading] = useState(true);
14
+ const [error, setError] = useState(null);
15
+ const fetchArticles = useCallback(async () => {
16
+ setLoading(true);
17
+ setError(null);
18
+ try {
19
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
20
+ const result = await client.listArticles(listOptions);
21
+ setArticles(result.articles);
22
+ setPagination(result.pagination);
23
+ }
24
+ catch (err) {
25
+ setError(err);
26
+ }
27
+ finally {
28
+ setLoading(false);
29
+ }
30
+ }, [apiKey, baseUrl, JSON.stringify(listOptions)]);
31
+ useEffect(() => {
32
+ fetchArticles();
33
+ }, [fetchArticles]);
34
+ return {
35
+ articles,
36
+ pagination,
37
+ loading,
38
+ error,
39
+ refetch: fetchArticles
40
+ };
41
+ }
42
+ /**
43
+ * Hook to fetch a single article
44
+ */
45
+ export function useArticle(options) {
46
+ const { apiKey, uuid, baseUrl } = options;
47
+ const [article, setArticle] = useState(null);
48
+ const [loading, setLoading] = useState(true);
49
+ const [error, setError] = useState(null);
50
+ const fetchArticle = useCallback(async () => {
51
+ setLoading(true);
52
+ setError(null);
53
+ try {
54
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
55
+ const result = await client.getArticle(uuid);
56
+ setArticle(result);
57
+ }
58
+ catch (err) {
59
+ setError(err);
60
+ }
61
+ finally {
62
+ setLoading(false);
63
+ }
64
+ }, [apiKey, uuid, baseUrl]);
65
+ useEffect(() => {
66
+ fetchArticle();
67
+ }, [fetchArticle]);
68
+ return {
69
+ article,
70
+ loading,
71
+ error,
72
+ refetch: fetchArticle
73
+ };
74
+ }
75
+ /**
76
+ * Hook to fetch categories
77
+ */
78
+ export function useCategories(options) {
79
+ const { apiKey, baseUrl } = options;
80
+ const [categories, setCategories] = useState([]);
81
+ const [loading, setLoading] = useState(true);
82
+ const [error, setError] = useState(null);
83
+ const fetchCategories = useCallback(async () => {
84
+ setLoading(true);
85
+ setError(null);
86
+ try {
87
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
88
+ const result = await client.getCategories();
89
+ setCategories(result.categories);
90
+ }
91
+ catch (err) {
92
+ setError(err);
93
+ }
94
+ finally {
95
+ setLoading(false);
96
+ }
97
+ }, [apiKey, baseUrl]);
98
+ useEffect(() => {
99
+ fetchCategories();
100
+ }, [fetchCategories]);
101
+ return {
102
+ categories,
103
+ loading,
104
+ error,
105
+ refetch: fetchCategories
106
+ };
107
+ }
108
+ /**
109
+ * Hook to fetch tags
110
+ */
111
+ export function useTags(options) {
112
+ const { apiKey, baseUrl } = options;
113
+ const [tags, setTags] = useState([]);
114
+ const [loading, setLoading] = useState(true);
115
+ const [error, setError] = useState(null);
116
+ const fetchTags = useCallback(async () => {
117
+ setLoading(true);
118
+ setError(null);
119
+ try {
120
+ const client = new ContentGrowthClient({ apiKey, baseUrl });
121
+ const result = await client.getTags();
122
+ setTags(result.tags);
123
+ }
124
+ catch (err) {
125
+ setError(err);
126
+ }
127
+ finally {
128
+ setLoading(false);
129
+ }
130
+ }, [apiKey, baseUrl]);
131
+ useEffect(() => {
132
+ fetchTags();
133
+ }, [fetchTags]);
134
+ return {
135
+ tags,
136
+ loading,
137
+ error,
138
+ refetch: fetchTags
139
+ };
140
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Content Growth Content Widget - React Components
3
+ */
4
+ export { ContentList } from './ContentList.js';
5
+ export { ContentViewer } from './ContentViewer.js';
6
+ export * from './hooks.js';
7
+ export type { ReactContentListProps } from './ContentList.js';
8
+ export type { ReactContentViewerProps } from './ContentViewer.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,YAAY,CAAC;AAE3B,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Content Growth Content Widget - React Components
3
+ */
4
+ export { ContentList } from './ContentList.js';
5
+ export { ContentViewer } from './ContentViewer.js';
6
+ export * from './hooks.js';