@contentgrowth/content-widget 1.1.0 → 1.1.2

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.
@@ -1,240 +0,0 @@
1
- /**
2
- * Content Growth Widget
3
- * Main widget class that combines list and viewer
4
- */
5
- import { ContentGrowthAPI } from './utils/api-client.js';
6
- import { ContentList } from './components/content-list.js';
7
- import { ContentViewer } from './components/content-viewer.js';
8
-
9
- export class ContentGrowthWidget {
10
- constructor(container, config) {
11
- console.log('[ContentGrowthWidget] Constructor called with config:', config);
12
-
13
- this.container = typeof container === 'string'
14
- ? document.querySelector(container)
15
- : container;
16
-
17
- if (!this.container) {
18
- throw new Error('Container not found');
19
- }
20
-
21
- this.config = {
22
- apiKey: config.apiKey || config['api-key'],
23
- baseUrl: config.baseUrl || 'https://api.content-growth.com',
24
- tags: this.parseTags(config.tags),
25
- theme: config.theme || 'light',
26
- layoutMode: config.layoutMode || config['layout-mode'] || 'cards', // 'cards' or 'rows'
27
- displayMode: config.displayMode || config['display-mode'] || 'comfortable',
28
- viewerMode: config.viewerMode || config['viewer-mode'] || 'inline', // 'inline' | 'modal' | 'external'
29
- externalUrlPattern: config.externalUrlPattern || config['external-url-pattern'] || '/article/{id}',
30
- externalTarget: config.externalTarget || config['external-target'] || 'article-{id}', // Tab name with {id}
31
- pageSize: config.pageSize || config['page-size'] || 12,
32
- mode: config.mode || 'list', // 'list' or 'article-only'
33
- articleId: config.articleId || config['article-id'] // Article ID for article-only mode
34
- };
35
-
36
- console.log('[ContentGrowthWidget] Final config:', this.config);
37
-
38
- if (!this.config.apiKey) {
39
- throw new Error('API key is required');
40
- }
41
-
42
- console.log('[ContentGrowthWidget] Creating API client with baseUrl:', this.config.baseUrl);
43
- this.api = new ContentGrowthAPI({
44
- apiKey: this.config.apiKey,
45
- baseUrl: this.config.baseUrl
46
- });
47
-
48
- this.currentView = 'list'; // 'list' or 'viewer'
49
- this.contentList = null;
50
- this.contentViewer = null;
51
-
52
- this.init();
53
- }
54
-
55
- /**
56
- * Initialize the widget
57
- */
58
- init() {
59
- console.log('[ContentGrowthWidget] Initializing widget...');
60
- // Apply theme
61
- this.container.classList.add('cg-widget');
62
- this.container.setAttribute('data-theme', this.config.theme);
63
-
64
- // Check if article-only mode
65
- if (this.config.mode === 'article-only' && this.config.articleId) {
66
- console.log('[ContentGrowthWidget] Article-only mode, loading article:', this.config.articleId);
67
- this.showPostInline(this.config.articleId);
68
- } else {
69
- // Create views
70
- this.showList();
71
- }
72
- console.log('[ContentGrowthWidget] Widget initialized');
73
- }
74
-
75
- /**
76
- * Show the list view
77
- */
78
- showList() {
79
- console.log('[ContentGrowthWidget] Showing list view...');
80
- this.currentView = 'list';
81
- this.container.innerHTML = '';
82
-
83
- const listContainer = document.createElement('div');
84
- listContainer.className = 'cg-list-view';
85
- this.container.appendChild(listContainer);
86
-
87
- console.log('[ContentGrowthWidget] Creating ContentList with options:', {
88
- layoutMode: this.config.layoutMode,
89
- displayMode: this.config.displayMode,
90
- pageSize: this.config.pageSize,
91
- tags: this.config.tags
92
- });
93
-
94
- this.contentList = new ContentList(listContainer, this.api, {
95
- layoutMode: this.config.layoutMode,
96
- displayMode: this.config.displayMode,
97
- pageSize: this.config.pageSize,
98
- tags: this.config.tags,
99
- viewerMode: this.config.viewerMode,
100
- externalUrlPattern: this.config.externalUrlPattern,
101
- externalTarget: this.config.externalTarget,
102
- onArticleClick: (article) => this.showPost(article.uuid)
103
- });
104
-
105
- this.contentList.init();
106
- }
107
-
108
- /**
109
- * Show the content viewer
110
- */
111
- showPost(uuid) {
112
- this.currentView = 'viewer';
113
-
114
- if (this.config.viewerMode === 'modal') {
115
- this.showPostModal(uuid);
116
- } else {
117
- this.showPostInline(uuid);
118
- }
119
- }
120
-
121
- /**
122
- * Show content inline (replaces list)
123
- */
124
- showPostInline(uuid) {
125
- this.container.innerHTML = '';
126
-
127
- const viewerContainer = document.createElement('div');
128
- viewerContainer.className = 'cg-viewer-view';
129
- this.container.appendChild(viewerContainer);
130
-
131
- // In article-only mode, don't show back button (no list to go back to)
132
- const showBackButton = this.config.mode !== 'article-only';
133
-
134
- this.contentViewer = new ContentViewer(viewerContainer, this.api, {
135
- displayMode: 'inline',
136
- showBackButton: showBackButton,
137
- onBack: showBackButton ? () => this.showList() : null
138
- });
139
-
140
- this.contentViewer.loadArticle(uuid);
141
- }
142
-
143
- /**
144
- * Show content in modal
145
- */
146
- showPostModal(uuid) {
147
- // Create modal
148
- const modal = document.createElement('div');
149
- modal.className = 'cg-modal';
150
- // Apply theme to modal
151
- if (this.config.theme) {
152
- modal.setAttribute('data-theme', this.config.theme);
153
- }
154
- modal.innerHTML = `
155
- <div class="cg-modal-overlay"></div>
156
- <div class="cg-modal-content">
157
- <button class="cg-modal-close" aria-label="Close">
158
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
159
- <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
160
- </svg>
161
- </button>
162
- <div class="cg-modal-body"></div>
163
- </div>
164
- `;
165
-
166
- document.body.appendChild(modal);
167
-
168
- // Prevent body scroll
169
- document.body.style.overflow = 'hidden';
170
-
171
- // Load content
172
- const modalBody = modal.querySelector('.cg-modal-body');
173
- this.contentViewer = new ContentViewer(modalBody, this.api, {
174
- displayMode: 'modal',
175
- onBack: () => this.closeModal(modal)
176
- });
177
-
178
- this.contentViewer.loadArticle(uuid);
179
-
180
- // Close handlers
181
- const closeBtn = modal.querySelector('.cg-modal-close');
182
- const overlay = modal.querySelector('.cg-modal-overlay');
183
-
184
- const closeModal = () => this.closeModal(modal);
185
- closeBtn.addEventListener('click', closeModal);
186
- overlay.addEventListener('click', closeModal);
187
-
188
- // ESC key
189
- const handleEsc = (e) => {
190
- if (e.key === 'Escape') {
191
- closeModal();
192
- document.removeEventListener('keydown', handleEsc);
193
- }
194
- };
195
- document.addEventListener('keydown', handleEsc);
196
-
197
- // Fade in
198
- requestAnimationFrame(() => {
199
- modal.classList.add('cg-modal--active');
200
- });
201
- }
202
-
203
- /**
204
- * Close modal
205
- */
206
- closeModal(modal) {
207
- modal.classList.remove('cg-modal--active');
208
-
209
- setTimeout(() => {
210
- modal.remove();
211
- document.body.style.overflow = '';
212
- }, 300); // Match CSS transition duration
213
- }
214
-
215
- /**
216
- * Parse tags from string or array
217
- */
218
- parseTags(tags) {
219
- if (!tags) return [];
220
- if (Array.isArray(tags)) return tags;
221
- return tags.split(',').map(t => t.trim()).filter(Boolean);
222
- }
223
-
224
- /**
225
- * Update configuration
226
- */
227
- updateConfig(newConfig) {
228
- Object.assign(this.config, newConfig);
229
- this.init();
230
- }
231
-
232
- /**
233
- * Destroy the widget
234
- */
235
- destroy() {
236
- this.container.innerHTML = '';
237
- this.container.classList.remove('cg-widget');
238
- this.container.removeAttribute('data-theme');
239
- }
240
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Type declarations for ContentGrowthWidget
3
- */
4
-
5
- export interface WidgetConfig {
6
- apiKey: string;
7
- baseUrl?: string;
8
- layoutMode?: 'cards' | 'rows';
9
- displayMode?: 'compact' | 'comfortable' | 'spacious';
10
- theme?: 'light' | 'dark';
11
- pageSize?: number;
12
- tags?: string[];
13
- category?: string;
14
- viewerMode?: 'inline' | 'modal' | 'external';
15
- mode?: 'list' | 'article-only';
16
- uuid?: string;
17
- slug?: string;
18
- articleId?: string; // Legacy support for uuid
19
- }
20
-
21
- export class ContentGrowthWidget {
22
- constructor(container: HTMLElement, config: WidgetConfig);
23
- destroy(): void;
24
- }