@feedlog-ai/webcomponents 0.0.1

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 (82) hide show
  1. package/dist/cjs/feedlog-badge_3.cjs.entry.js +119 -0
  2. package/dist/cjs/feedlog-card.cjs.entry.js +17 -0
  3. package/dist/cjs/feedlog-github-issues-client.cjs.entry.js +520 -0
  4. package/dist/cjs/feedlog-github-issues.cjs.entry.js +81 -0
  5. package/dist/cjs/feedlog-toolkit.cjs.js +24 -0
  6. package/dist/cjs/index-5lluu_3h.js +3144 -0
  7. package/dist/cjs/index.cjs.js +2 -0
  8. package/dist/cjs/loader.cjs.js +12 -0
  9. package/dist/collection/collection-manifest.json +17 -0
  10. package/dist/collection/components/feedlog-badge/feedlog-badge.css +86 -0
  11. package/dist/collection/components/feedlog-badge/feedlog-badge.js +53 -0
  12. package/dist/collection/components/feedlog-badge/feedlog-badge.stories.js +38 -0
  13. package/dist/collection/components/feedlog-button/feedlog-button.css +155 -0
  14. package/dist/collection/components/feedlog-button/feedlog-button.js +154 -0
  15. package/dist/collection/components/feedlog-button/feedlog-button.stories.js +82 -0
  16. package/dist/collection/components/feedlog-card/feedlog-card.css +47 -0
  17. package/dist/collection/components/feedlog-card/feedlog-card.js +23 -0
  18. package/dist/collection/components/feedlog-card/feedlog-card.stories.js +22 -0
  19. package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.css +69 -0
  20. package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.js +308 -0
  21. package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.stories.js +211 -0
  22. package/dist/collection/components/feedlog-github-issues-client/feedlog-github-issues-client.js +395 -0
  23. package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.css +218 -0
  24. package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.js +139 -0
  25. package/dist/collection/components/index.js +6 -0
  26. package/dist/collection/index.js +1 -0
  27. package/dist/components/feedlog-badge.d.ts +11 -0
  28. package/dist/components/feedlog-badge.js +1 -0
  29. package/dist/components/feedlog-button.d.ts +11 -0
  30. package/dist/components/feedlog-button.js +1 -0
  31. package/dist/components/feedlog-card.d.ts +11 -0
  32. package/dist/components/feedlog-card.js +1 -0
  33. package/dist/components/feedlog-github-issues-client.d.ts +11 -0
  34. package/dist/components/feedlog-github-issues-client.js +1 -0
  35. package/dist/components/feedlog-github-issues.d.ts +11 -0
  36. package/dist/components/feedlog-github-issues.js +1 -0
  37. package/dist/components/feedlog-issues-list.d.ts +11 -0
  38. package/dist/components/feedlog-issues-list.js +1 -0
  39. package/dist/components/index.d.ts +35 -0
  40. package/dist/components/index.js +1 -0
  41. package/dist/components/p-CHtSMTyP.js +1 -0
  42. package/dist/components/p-CPOiBAxu.js +1 -0
  43. package/dist/components/p-DMcNh5Ys.js +1 -0
  44. package/dist/components/p-DMdb-G26.js +1 -0
  45. package/dist/esm/feedlog-badge_3.entry.js +115 -0
  46. package/dist/esm/feedlog-card.entry.js +15 -0
  47. package/dist/esm/feedlog-github-issues-client.entry.js +518 -0
  48. package/dist/esm/feedlog-github-issues.entry.js +79 -0
  49. package/dist/esm/feedlog-toolkit.js +20 -0
  50. package/dist/esm/index-CkB6Yzeb.js +3135 -0
  51. package/dist/esm/index.js +1 -0
  52. package/dist/esm/loader.js +10 -0
  53. package/dist/feedlog-toolkit/feedlog-toolkit.css +1 -0
  54. package/dist/feedlog-toolkit/feedlog-toolkit.esm.js +1 -0
  55. package/dist/feedlog-toolkit/index.esm.js +0 -0
  56. package/dist/feedlog-toolkit/p-2f7954f7.entry.js +1 -0
  57. package/dist/feedlog-toolkit/p-399e0281.entry.js +1 -0
  58. package/dist/feedlog-toolkit/p-CkB6Yzeb.js +2 -0
  59. package/dist/feedlog-toolkit/p-b3d26272.entry.js +1 -0
  60. package/dist/feedlog-toolkit/p-cdb2b098.entry.js +1 -0
  61. package/dist/index.cjs.js +1 -0
  62. package/dist/index.js +1 -0
  63. package/dist/types/components/feedlog-badge/feedlog-badge.d.ts +12 -0
  64. package/dist/types/components/feedlog-badge/feedlog-badge.stories.d.ts +9 -0
  65. package/dist/types/components/feedlog-button/feedlog-button.d.ts +30 -0
  66. package/dist/types/components/feedlog-button/feedlog-button.stories.d.ts +13 -0
  67. package/dist/types/components/feedlog-card/feedlog-card.d.ts +8 -0
  68. package/dist/types/components/feedlog-card/feedlog-card.stories.d.ts +9 -0
  69. package/dist/types/components/feedlog-github-issues/feedlog-github-issues.d.ts +67 -0
  70. package/dist/types/components/feedlog-github-issues/feedlog-github-issues.stories.d.ts +11 -0
  71. package/dist/types/components/feedlog-github-issues-client/feedlog-github-issues-client.d.ts +77 -0
  72. package/dist/types/components/feedlog-issues-list/feedlog-issues-list.d.ts +31 -0
  73. package/dist/types/components/index.d.ts +6 -0
  74. package/dist/types/components.d.ts +532 -0
  75. package/dist/types/index.d.ts +1 -0
  76. package/dist/types/stencil-public-runtime.d.ts +1810 -0
  77. package/loader/cdn.js +1 -0
  78. package/loader/index.cjs.js +1 -0
  79. package/loader/index.d.ts +24 -0
  80. package/loader/index.es2017.js +1 -0
  81. package/loader/index.js +2 -0
  82. package/package.json +48 -0
@@ -0,0 +1,15 @@
1
+ import { r as registerInstance, h } from './index-CkB6Yzeb.js';
2
+
3
+ const feedlogCardCss = () => `:host{display:block;font-family:ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;--feedlog-card:#ffffff;--feedlog-card-foreground:oklch(0.145 0 0);--feedlog-border:rgba(0, 0, 0, 0.1);--feedlog-radius:0.625rem;--feedlog-card-shadow:0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);--feedlog-card-hover-shadow:0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)}:host(.dark){--feedlog-card:oklch(0.145 0 0);--feedlog-card-foreground:oklch(0.985 0 0);--feedlog-border:oklch(0.269 0 0);--feedlog-card-shadow:0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.3);--feedlog-card-hover-shadow:0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -4px rgba(0, 0, 0, 0.3)}.feedlog-card{background-color:var(--feedlog-card);color:var(--feedlog-card-foreground);border:1px solid var(--feedlog-border);border-radius:var(--feedlog-radius);box-shadow:var(--feedlog-card-shadow);transition:box-shadow 0.15s ease;position:relative}.feedlog-card:hover{box-shadow:var(--feedlog-card-hover-shadow)}::slotted([slot="header"]){display:block}::slotted([slot="content"]){display:block}::slotted([slot="footer"]){display:block}`;
4
+
5
+ const FeedlogCard = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ }
9
+ render() {
10
+ return (h("div", { key: '293a80e66adedfc1af29daf72390a4f464321b96', class: "feedlog-card" }, h("slot", { key: 'b7e5a827f89035e791d9c756db0f66198e6c5a38', name: "header" }), h("slot", { key: 'da89fee0a01068c8438564848f218faa9c5d849e', name: "content" }), h("slot", { key: '30b05e80e4189c0f73810a48f64e072dfac83267', name: "footer" })));
11
+ }
12
+ };
13
+ FeedlogCard.style = feedlogCardCss();
14
+
15
+ export { FeedlogCard as feedlog_card };
@@ -0,0 +1,518 @@
1
+ import { r as registerInstance, c as createEvent, h } from './index-CkB6Yzeb.js';
2
+
3
+ /**
4
+ * HTML and XSS sanitization utilities
5
+ */
6
+ /**
7
+ * Basic HTML entity escaping to prevent XSS
8
+ * This is a lightweight alternative to DOMPurify
9
+ */
10
+ /**
11
+ * Sanitize HTML by removing dangerous tags and attributes
12
+ * Removes script tags, event handlers, and other potentially malicious content
13
+ */
14
+ function sanitizeHtml(html) {
15
+ if (typeof html !== 'string') {
16
+ return '';
17
+ }
18
+ // Remove script tags and content
19
+ let sanitized = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
20
+ // Remove on* event handlers
21
+ sanitized = sanitized.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, '');
22
+ sanitized = sanitized.replace(/\s*on\w+\s*=\s*[^\s>]*/gi, '');
23
+ // Remove iframe tags
24
+ sanitized = sanitized.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '');
25
+ // Remove style tags
26
+ sanitized = sanitized.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');
27
+ // Remove embed and object tags
28
+ sanitized = sanitized.replace(/<(embed|object)\b[^<]*>/gi, '');
29
+ // Remove javascript: protocol
30
+ sanitized = sanitized.replace(/javascript:/gi, '');
31
+ // Remove data: protocol for potentially dangerous mime types
32
+ sanitized = sanitized.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi, '');
33
+ return sanitized;
34
+ }
35
+
36
+ /**
37
+ * Custom error types for Feedlog SDK
38
+ */
39
+ class FeedlogError extends Error {
40
+ constructor(message, statusCode, originalError) {
41
+ super(message);
42
+ this.statusCode = statusCode;
43
+ this.originalError = originalError;
44
+ this.name = 'FeedlogError';
45
+ Object.setPrototypeOf(this, FeedlogError.prototype);
46
+ }
47
+ }
48
+ class FeedlogValidationError extends FeedlogError {
49
+ constructor(message) {
50
+ super(message);
51
+ this.name = 'FeedlogValidationError';
52
+ Object.setPrototypeOf(this, FeedlogValidationError.prototype);
53
+ }
54
+ }
55
+ class FeedlogNetworkError extends FeedlogError {
56
+ constructor(message, statusCode, originalError) {
57
+ super(message, statusCode, originalError);
58
+ this.name = 'FeedlogNetworkError';
59
+ Object.setPrototypeOf(this, FeedlogNetworkError.prototype);
60
+ }
61
+ }
62
+ class FeedlogTimeoutError extends FeedlogError {
63
+ constructor(message = 'Request timed out') {
64
+ super(message);
65
+ this.name = 'FeedlogTimeoutError';
66
+ Object.setPrototypeOf(this, FeedlogTimeoutError.prototype);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Core SDK for Feedlog Toolkit
72
+ *
73
+ * This package provides the core functionality and utilities
74
+ * used across all Feedlog Toolkit packages.
75
+ */
76
+ /**
77
+ * Main Feedlog SDK class
78
+ * Provides methods to interact with the Feedlog API
79
+ */
80
+ class FeedlogSDK {
81
+ constructor(config = {}) {
82
+ this.config = {
83
+ credentials: 'include',
84
+ ...config,
85
+ };
86
+ this.endpoint = this.config.endpoint || 'https://api.feedlog.app';
87
+ this.timeout = this.config.timeout || 30000;
88
+ // Ensure endpoint doesn't have trailing slash
89
+ this.endpoint = this.endpoint.replace(/\/$/, '');
90
+ }
91
+ /**
92
+ * Fetch issues from the API
93
+ * Supports filtering by repository IDs, type, pagination, and limit
94
+ */
95
+ async fetchIssues(params = {}) {
96
+ try {
97
+ const url = this.buildIssuesUrl(params);
98
+ const response = await this.fetchWithTimeout(url, {
99
+ method: 'GET',
100
+ headers: this.getAuthHeaders(),
101
+ credentials: this.config.credentials || 'include',
102
+ });
103
+ if (!response.ok) {
104
+ throw new FeedlogNetworkError(`Failed to fetch issues: ${response.statusText}`, response.status);
105
+ }
106
+ const data = await response.json();
107
+ return this.validateIssuesResponse(data);
108
+ }
109
+ catch (error) {
110
+ if (error instanceof FeedlogError) {
111
+ throw error;
112
+ }
113
+ if (error instanceof TypeError && error.message.includes('fetch')) {
114
+ throw new FeedlogNetworkError('Network error: Unable to reach API', undefined, error);
115
+ }
116
+ throw new FeedlogError(`Failed to fetch issues: ${error instanceof Error ? error.message : 'Unknown error'}`, undefined, error);
117
+ }
118
+ }
119
+ /**
120
+ * Toggle upvote on an issue
121
+ * Adds upvote if not already upvoted, removes if already upvoted
122
+ */
123
+ async toggleUpvote(issueId) {
124
+ if (!issueId || typeof issueId !== 'string') {
125
+ throw new FeedlogValidationError('Issue ID is required');
126
+ }
127
+ try {
128
+ const url = `${this.endpoint}/api/issues/${encodeURIComponent(issueId)}/upvote`;
129
+ const response = await this.fetchWithTimeout(url, {
130
+ method: 'POST',
131
+ headers: this.getAuthHeaders(),
132
+ credentials: this.config.credentials || 'include',
133
+ });
134
+ if (response.status === 404) {
135
+ throw new FeedlogNetworkError('Issue not found', 404);
136
+ }
137
+ if (response.status === 401) {
138
+ throw new FeedlogNetworkError('Unauthorized', 401);
139
+ }
140
+ if (response.status === 403) {
141
+ throw new FeedlogNetworkError('Forbidden: Domain not allowed for this repository', 403);
142
+ }
143
+ if (!response.ok) {
144
+ throw new FeedlogNetworkError(`Failed to toggle upvote: ${response.statusText}`, response.status);
145
+ }
146
+ const data = await response.json();
147
+ return this.validateUpvoteResponse(data);
148
+ }
149
+ catch (error) {
150
+ if (error instanceof FeedlogError) {
151
+ throw error;
152
+ }
153
+ if (error instanceof TypeError && error.message.includes('fetch')) {
154
+ throw new FeedlogNetworkError('Network error: Unable to reach API', undefined, error);
155
+ }
156
+ throw new FeedlogError(`Failed to toggle upvote: ${error instanceof Error ? error.message : 'Unknown error'}`, undefined, error);
157
+ }
158
+ }
159
+ /**
160
+ * Build the full URL for fetching issues with query parameters
161
+ */
162
+ buildIssuesUrl(params) {
163
+ const url = new URL(`${this.endpoint}/api/issues`);
164
+ // Handle repositoryIds - can be single string or array
165
+ if (params.repositoryIds) {
166
+ const ids = Array.isArray(params.repositoryIds)
167
+ ? params.repositoryIds
168
+ : [params.repositoryIds];
169
+ for (const id of ids) {
170
+ url.searchParams.append('repositoryIds', id);
171
+ }
172
+ }
173
+ if (params.type) {
174
+ url.searchParams.set('type', params.type);
175
+ }
176
+ if (params.cursor) {
177
+ url.searchParams.set('cursor', params.cursor);
178
+ }
179
+ if (params.limit !== undefined) {
180
+ url.searchParams.set('limit', params.limit.toString());
181
+ }
182
+ return url.toString();
183
+ }
184
+ /**
185
+ * Get request headers
186
+ */
187
+ getAuthHeaders() {
188
+ return {
189
+ 'Content-Type': 'application/json',
190
+ };
191
+ }
192
+ /**
193
+ * Fetch with timeout support using AbortController
194
+ */
195
+ async fetchWithTimeout(url, init) {
196
+ const controller = new AbortController();
197
+ const timeout = setTimeout(() => controller.abort(), this.timeout);
198
+ try {
199
+ const response = await fetch(url, {
200
+ ...init,
201
+ signal: controller.signal,
202
+ });
203
+ clearTimeout(timeout);
204
+ return response;
205
+ }
206
+ catch (error) {
207
+ clearTimeout(timeout);
208
+ if (error instanceof Error && error.name === 'AbortError') {
209
+ throw new FeedlogTimeoutError(`Request timed out after ${this.timeout}ms`);
210
+ }
211
+ throw error;
212
+ }
213
+ }
214
+ /**
215
+ * Validate and sanitize issues response
216
+ */
217
+ validateIssuesResponse(data) {
218
+ if (!data || typeof data !== 'object') {
219
+ throw new FeedlogValidationError('Invalid API response: expected object');
220
+ }
221
+ const response = data;
222
+ if (!Array.isArray(response.issues)) {
223
+ throw new FeedlogValidationError('Invalid API response: issues must be an array');
224
+ }
225
+ if (!response.pagination || typeof response.pagination !== 'object') {
226
+ throw new FeedlogValidationError('Invalid API response: pagination is required');
227
+ }
228
+ const issues = response.issues.map(issue => this.validateIssue(issue));
229
+ return {
230
+ issues,
231
+ pagination: {
232
+ cursor: response.pagination.cursor,
233
+ hasMore: Boolean(response.pagination.hasMore),
234
+ },
235
+ };
236
+ }
237
+ /**
238
+ * Validate and sanitize an individual issue
239
+ */
240
+ validateIssue(data) {
241
+ if (!data || typeof data !== 'object') {
242
+ throw new FeedlogValidationError('Invalid issue: expected object');
243
+ }
244
+ const issue = data;
245
+ // Validate required fields
246
+ if (typeof issue.id !== 'string') {
247
+ throw new FeedlogValidationError('Invalid issue: id is required and must be a string');
248
+ }
249
+ if (typeof issue.title !== 'string') {
250
+ throw new FeedlogValidationError('Invalid issue: title is required and must be a string');
251
+ }
252
+ if (!['bug', 'enhancement'].includes(String(issue.type))) {
253
+ throw new FeedlogValidationError('Invalid issue: type must be "bug" or "enhancement"');
254
+ }
255
+ if (!['open', 'closed'].includes(String(issue.status))) {
256
+ throw new FeedlogValidationError('Invalid issue: status must be "open" or "closed"');
257
+ }
258
+ if (!issue.repository || typeof issue.repository !== 'object') {
259
+ throw new FeedlogValidationError('Invalid issue: repository is required');
260
+ }
261
+ const repo = issue.repository;
262
+ if (typeof repo.id !== 'string' ||
263
+ typeof repo.name !== 'string' ||
264
+ typeof repo.owner !== 'string') {
265
+ throw new FeedlogValidationError('Invalid issue: repository must have id, name, and owner');
266
+ }
267
+ // Sanitize string fields to prevent XSS
268
+ const sanitizedTitle = sanitizeHtml(String(issue.title));
269
+ const sanitizedBody = sanitizeHtml(String(issue.body || ''));
270
+ return {
271
+ id: String(issue.id),
272
+ type: issue.type || 'bug',
273
+ status: issue.status || 'open',
274
+ pinnedAt: issue.pinnedAt ? String(issue.pinnedAt) : null,
275
+ revision: Number(issue.revision) || 1,
276
+ title: sanitizedTitle,
277
+ body: sanitizedBody,
278
+ repository: {
279
+ id: String(repo.id),
280
+ name: String(repo.name),
281
+ owner: String(repo.owner),
282
+ },
283
+ updatedAt: String(issue.updatedAt) || new Date().toISOString(),
284
+ createdAt: String(issue.createdAt) || new Date().toISOString(),
285
+ upvoteCount: Number(issue.upvoteCount) || 0,
286
+ hasUpvoted: Boolean(issue.hasUpvoted),
287
+ };
288
+ }
289
+ /**
290
+ * Validate upvote response
291
+ */
292
+ validateUpvoteResponse(data) {
293
+ if (!data || typeof data !== 'object') {
294
+ throw new FeedlogValidationError('Invalid upvote response: expected object');
295
+ }
296
+ const response = data;
297
+ if (typeof response.upvoted !== 'boolean') {
298
+ throw new FeedlogValidationError('Invalid upvote response: upvoted must be a boolean');
299
+ }
300
+ if (typeof response.upvoteCount !== 'number') {
301
+ throw new FeedlogValidationError('Invalid upvote response: upvoteCount must be a number');
302
+ }
303
+ if (typeof response.anonymousUserId !== 'string') {
304
+ throw new FeedlogValidationError('Invalid upvote response: anonymousUserId must be a string');
305
+ }
306
+ return {
307
+ upvoted: response.upvoted,
308
+ upvoteCount: response.upvoteCount,
309
+ anonymousUserId: response.anonymousUserId,
310
+ };
311
+ }
312
+ /**
313
+ * Get the current endpoint
314
+ */
315
+ getEndpoint() {
316
+ return this.endpoint;
317
+ }
318
+ /**
319
+ * Get the current timeout setting
320
+ */
321
+ getTimeout() {
322
+ return this.timeout;
323
+ }
324
+ }
325
+
326
+ const FeedlogGithubIssuesClient = class {
327
+ constructor(hostRef) {
328
+ registerInstance(this, hostRef);
329
+ this.feedlogUpvote = createEvent(this, "feedlogUpvote");
330
+ this.feedlogThemeChange = createEvent(this, "feedlogThemeChange");
331
+ this.feedlogError = createEvent(this, "feedlogError");
332
+ /**
333
+ * Maximum width of the container
334
+ */
335
+ this.maxWidth = '42rem';
336
+ /**
337
+ * Theme variant: 'light' or 'dark'
338
+ */
339
+ this.theme = 'light';
340
+ /**
341
+ * Whether to show the theme toggle button
342
+ */
343
+ this.showThemeToggle = true;
344
+ this.issues = [];
345
+ this.loading = true;
346
+ this.error = null;
347
+ this.cursor = null;
348
+ this.hasMore = false;
349
+ this.isLoadingMore = false;
350
+ this.sdk = null;
351
+ this.handleUpvote = async (event) => {
352
+ if (!this.sdk) {
353
+ return;
354
+ }
355
+ const { issueId, currentUpvoted, currentCount } = event.detail;
356
+ // Optimistic update
357
+ this.issues = this.issues.map(issue => issue.id === issueId
358
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
359
+ try {
360
+ const result = await this.sdk.toggleUpvote(issueId);
361
+ // Update with server response
362
+ this.issues = this.issues.map(issue => issue.id === issueId
363
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: result.upvoted, upvoteCount: result.upvoteCount }) : issue);
364
+ this.feedlogUpvote.emit({
365
+ issueId,
366
+ upvoted: result.upvoted,
367
+ upvoteCount: result.upvoteCount,
368
+ });
369
+ }
370
+ catch (err) {
371
+ // Revert optimistic update on error
372
+ this.issues = this.issues.map(issue => issue.id === issueId
373
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
374
+ const errorMsg = err instanceof Error ? err.message : 'Failed to toggle upvote';
375
+ this.feedlogError.emit({ error: errorMsg });
376
+ }
377
+ };
378
+ this.handleThemeChange = (event) => {
379
+ this.theme = event.detail;
380
+ this.feedlogThemeChange.emit(event.detail);
381
+ };
382
+ }
383
+ componentWillLoad() {
384
+ this.previousRepos = this.repos;
385
+ this.previousType = this.type;
386
+ this.previousLimit = this.limit;
387
+ this.initializeSDK();
388
+ this.fetchIssues();
389
+ }
390
+ componentDidUpdate() {
391
+ // Re-fetch if any props changed
392
+ const reposChanged = JSON.stringify(this.previousRepos) !== JSON.stringify(this.repos);
393
+ const typeChanged = this.previousType !== this.type;
394
+ const limitChanged = this.previousLimit !== this.limit;
395
+ if (reposChanged || typeChanged || limitChanged) {
396
+ // Reset pagination when filters change
397
+ this.cursor = null;
398
+ this.hasMore = false;
399
+ this.issues = [];
400
+ this.fetchIssues();
401
+ this.previousRepos = this.repos;
402
+ this.previousType = this.type;
403
+ this.previousLimit = this.limit;
404
+ }
405
+ }
406
+ initializeSDK() {
407
+ try {
408
+ this.sdk = new FeedlogSDK(Object.assign({}, (this.endpoint && { endpoint: this.endpoint })));
409
+ this.error = null;
410
+ }
411
+ catch (err) {
412
+ const errorMsg = err instanceof Error ? err.message : 'Failed to initialize SDK';
413
+ this.error = errorMsg;
414
+ this.feedlogError.emit({ error: errorMsg });
415
+ }
416
+ }
417
+ parseRepos() {
418
+ if (!this.repos) {
419
+ return [];
420
+ }
421
+ if (typeof this.repos === 'string') {
422
+ try {
423
+ const parsed = JSON.parse(this.repos);
424
+ return Array.isArray(parsed) ? parsed : [this.repos];
425
+ }
426
+ catch (_a) {
427
+ // If not valid JSON, treat as single repo ID
428
+ return [this.repos];
429
+ }
430
+ }
431
+ return Array.isArray(this.repos) ? this.repos : [];
432
+ }
433
+ async fetchIssues() {
434
+ if (!this.sdk) {
435
+ return;
436
+ }
437
+ const repos = this.parseRepos();
438
+ if (repos.length === 0) {
439
+ this.error = 'At least one repository is required';
440
+ this.loading = false;
441
+ this.feedlogError.emit({ error: 'At least one repository is required' });
442
+ return;
443
+ }
444
+ try {
445
+ this.loading = true;
446
+ this.error = null;
447
+ const params = {
448
+ repositoryIds: repos,
449
+ };
450
+ if (this.type) {
451
+ params.type = this.type;
452
+ }
453
+ if (this.limit) {
454
+ params.limit = this.limit;
455
+ }
456
+ if (this.cursor) {
457
+ params.cursor = this.cursor;
458
+ }
459
+ const response = await this.sdk.fetchIssues(params);
460
+ this.issues = response.issues;
461
+ this.cursor = response.pagination.cursor;
462
+ this.hasMore = response.pagination.hasMore;
463
+ }
464
+ catch (err) {
465
+ const errorMsg = err instanceof Error ? err.message : 'Failed to fetch issues';
466
+ this.error = errorMsg;
467
+ this.issues = [];
468
+ this.feedlogError.emit({
469
+ error: errorMsg,
470
+ code: err === null || err === void 0 ? void 0 : err.statusCode,
471
+ });
472
+ }
473
+ finally {
474
+ this.loading = false;
475
+ this.isLoadingMore = false;
476
+ }
477
+ }
478
+ async loadMore() {
479
+ if (!this.sdk || !this.hasMore || this.isLoadingMore || this.loading) {
480
+ return;
481
+ }
482
+ this.isLoadingMore = true;
483
+ try {
484
+ const repos = this.parseRepos();
485
+ const params = {
486
+ repositoryIds: repos,
487
+ };
488
+ if (this.type) {
489
+ params.type = this.type;
490
+ }
491
+ if (this.limit) {
492
+ params.limit = this.limit;
493
+ }
494
+ if (this.cursor) {
495
+ params.cursor = this.cursor;
496
+ }
497
+ const response = await this.sdk.fetchIssues(params);
498
+ this.issues = [...this.issues, ...response.issues];
499
+ this.cursor = response.pagination.cursor;
500
+ this.hasMore = response.pagination.hasMore;
501
+ }
502
+ catch (err) {
503
+ const errorMsg = err instanceof Error ? err.message : 'Failed to load more issues';
504
+ this.feedlogError.emit({
505
+ error: errorMsg,
506
+ code: err === null || err === void 0 ? void 0 : err.statusCode,
507
+ });
508
+ }
509
+ finally {
510
+ this.isLoadingMore = false;
511
+ }
512
+ }
513
+ render() {
514
+ return (h("feedlog-github-issues", { key: '38b9e7ec8a5473acbab39df1d0476fcb357866bf', issues: this.issues, maxWidth: this.maxWidth, theme: this.theme, showThemeToggle: this.showThemeToggle, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogThemeChange: this.handleThemeChange, onFeedlogLoadMore: async () => this.loadMore() }));
515
+ }
516
+ };
517
+
518
+ export { FeedlogGithubIssuesClient as feedlog_github_issues_client };
@@ -0,0 +1,79 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-CkB6Yzeb.js';
2
+
3
+ const feedlogGithubIssuesCss = () => `:host{display:block;font-family:ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;--feedlog-background:#ffffff;--feedlog-foreground:oklch(0.145 0 0);--feedlog-muted-foreground:#717182;--feedlog-destructive:#d4183d;--feedlog-padding:2rem}:host(.dark){--feedlog-background:oklch(0.145 0 0);--feedlog-foreground:oklch(0.985 0 0);--feedlog-muted-foreground:oklch(0.708 0 0);--feedlog-destructive:oklch(0.637 0.237 25.331)}.github-issues-container{min-height:100vh;background-color:var(--feedlog-background);padding:var(--feedlog-padding);margin:0 auto}.issues-header{margin-bottom:1.5rem;display:flex;align-items:flex-start;justify-content:space-between}.header-content{flex:1}.issues-title{color:var(--feedlog-foreground);margin:0 0 0.25rem 0;font-size:1.5rem;font-weight:500;line-height:1.5}.issues-subtitle{color:var(--feedlog-muted-foreground);font-size:0.875rem;margin:0}.loading-state,.error-state{padding:2rem;text-align:center;color:var(--feedlog-muted-foreground)}.error-state{color:var(--feedlog-destructive)}.load-more-container{display:flex;justify-content:center;padding:2rem 0;gap:1rem}`;
4
+
5
+ /**
6
+ * Sun icon SVG component
7
+ */
8
+ const SunIcon = () => (h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "4" }), h("path", { d: "M12 2v2" }), h("path", { d: "M12 20v2" }), h("path", { d: "m4.93 4.93 1.41 1.41" }), h("path", { d: "m17.66 17.66 1.41 1.41" }), h("path", { d: "M2 12h2" }), h("path", { d: "M20 12h2" }), h("path", { d: "m6.34 17.66-1.41 1.41" }), h("path", { d: "m19.07 4.93-1.41 1.41" })));
9
+ /**
10
+ * Moon icon SVG component
11
+ */
12
+ const MoonIcon = () => (h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })));
13
+ const FeedlogGithubIssues = class {
14
+ constructor(hostRef) {
15
+ registerInstance(this, hostRef);
16
+ this.feedlogUpvote = createEvent(this, "feedlogUpvote");
17
+ this.feedlogThemeChange = createEvent(this, "feedlogThemeChange");
18
+ this.feedlogLoadMore = createEvent(this, "feedlogLoadMore");
19
+ /**
20
+ * Array of issues to display
21
+ */
22
+ this.issues = [];
23
+ /**
24
+ * Maximum width of the container
25
+ */
26
+ this.maxWidth = '42rem';
27
+ /**
28
+ * Theme variant: 'light' or 'dark'
29
+ */
30
+ this.theme = 'light';
31
+ /**
32
+ * Loading state - shows loading indicator when true
33
+ */
34
+ this.loading = false;
35
+ /**
36
+ * Error message - shows error state when set
37
+ */
38
+ this.error = null;
39
+ /**
40
+ * Whether to show the theme toggle button
41
+ */
42
+ this.showThemeToggle = true;
43
+ /**
44
+ * Whether there are more issues to load
45
+ */
46
+ this.hasMore = false;
47
+ /**
48
+ * Whether more issues are currently loading
49
+ */
50
+ this.isLoadingMore = false;
51
+ /**
52
+ * Internal state for theme
53
+ */
54
+ this.currentTheme = 'light';
55
+ this.handleUpvote = (event) => {
56
+ this.feedlogUpvote.emit(event.detail);
57
+ };
58
+ this.toggleTheme = () => {
59
+ this.currentTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
60
+ this.theme = this.currentTheme;
61
+ this.feedlogThemeChange.emit(this.currentTheme);
62
+ };
63
+ this.handleLoadMore = () => {
64
+ this.feedlogLoadMore.emit();
65
+ };
66
+ }
67
+ componentWillLoad() {
68
+ this.currentTheme = this.theme;
69
+ }
70
+ render() {
71
+ const containerStyle = {
72
+ maxWidth: this.maxWidth,
73
+ };
74
+ return (h(Host, { key: '8f238ab41f45799062270c84188596d770d6bde0', class: this.currentTheme === 'dark' ? 'dark' : '' }, h("div", { key: 'af0c2155ef3cdc12f228ec804ee906afd7d75477', class: "github-issues-container", style: containerStyle }, h("header", { key: 'ccf9a063df220f7a48e3600cb22df8203960a45b', class: "issues-header" }, h("div", { key: 'c261d6b0c8168a66faef9ec2fb381619f5175070', class: "header-content" }, h("h1", { key: '19203aa63dab0648b0a2865fe812233bfbbc225a', class: "issues-title" }, "GitHub Issues"), h("p", { key: 'e717a4e64cc747c81ad7a9e1cec234c247bfc329', class: "issues-subtitle" }, "Track bugs and enhancements for your project")), this.showThemeToggle && (h("feedlog-button", { key: '21057c7d384c53262e699e0384234077b0b36314', variant: "outline", size: "sm", onFeedlogClick: this.toggleTheme }, this.currentTheme === 'dark' ? h(SunIcon, null) : h(MoonIcon, null)))), this.loading && (h("div", { key: '2059c491247e0a48a81d802d9757d9fa97ac1a72', class: "loading-state" }, h("p", { key: '5654904e73b05bd5a05aa0243506e4bf074e5486' }, "Loading issues..."))), this.error && (h("div", { key: '7d2e09e0055e5d834aa870ed47bd4ebaba64dff1', class: "error-state" }, h("p", { key: 'd4cc2bb872c81234b4e81a4ec4ce21aff368ad74' }, "Error: ", this.error))), !this.loading && !this.error && (h("div", { key: 'e25eb90f7098416837a26a44e5811888530220a4' }, h("feedlog-issues-list", { key: 'a8e7ec5c5861cb31456738107b93f6e7adebbbe9', issues: this.issues, theme: this.currentTheme, onFeedlogUpvote: this.handleUpvote }), this.hasMore && (h("div", { key: '0d935e9247f44bff0700fce487d0bc4ccd104f2a', class: "load-more-container" }, h("feedlog-button", { key: '2858d701f5e3d219c39a6a28a7475c619464bc72', onFeedlogClick: this.handleLoadMore, disabled: this.isLoadingMore, variant: "outline" }, this.isLoadingMore ? 'Loading...' : 'Load More Issues'))))))));
75
+ }
76
+ };
77
+ FeedlogGithubIssues.style = feedlogGithubIssuesCss();
78
+
79
+ export { FeedlogGithubIssues as feedlog_github_issues };
@@ -0,0 +1,20 @@
1
+ import { p as promiseResolve, g as globalScripts, b as bootstrapLazy } from './index-CkB6Yzeb.js';
2
+ export { s as setNonce } from './index-CkB6Yzeb.js';
3
+
4
+ /*
5
+ Stencil Client Patch Browser v4.40.1 | MIT Licensed | https://stenciljs.com
6
+ */
7
+
8
+ var patchBrowser = () => {
9
+ const importMeta = import.meta.url;
10
+ const opts = {};
11
+ if (importMeta !== "") {
12
+ opts.resourcesUrl = new URL(".", importMeta).href;
13
+ }
14
+ return promiseResolve(opts);
15
+ };
16
+
17
+ patchBrowser().then(async (options) => {
18
+ await globalScripts();
19
+ return bootstrapLazy([["feedlog-card",[[257,"feedlog-card"]]],["feedlog-badge_3",[[1,"feedlog-issues-list",{"issues":[16],"theme":[1]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}],[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-github-issues",[[1,"feedlog-github-issues",{"issues":[16],"maxWidth":[1,"max-width"],"theme":[1025],"loading":[4],"error":[1],"showThemeToggle":[4,"show-theme-toggle"],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"currentTheme":[32]}]]],["feedlog-github-issues-client",[[1,"feedlog-github-issues-client",{"repos":[1],"type":[1],"limit":[2],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"showThemeToggle":[4,"show-theme-toggle"],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]}]]]], options);
20
+ });