@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.
- package/dist/cjs/feedlog-badge_3.cjs.entry.js +119 -0
- package/dist/cjs/feedlog-card.cjs.entry.js +17 -0
- package/dist/cjs/feedlog-github-issues-client.cjs.entry.js +520 -0
- package/dist/cjs/feedlog-github-issues.cjs.entry.js +81 -0
- package/dist/cjs/feedlog-toolkit.cjs.js +24 -0
- package/dist/cjs/index-5lluu_3h.js +3144 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/loader.cjs.js +12 -0
- package/dist/collection/collection-manifest.json +17 -0
- package/dist/collection/components/feedlog-badge/feedlog-badge.css +86 -0
- package/dist/collection/components/feedlog-badge/feedlog-badge.js +53 -0
- package/dist/collection/components/feedlog-badge/feedlog-badge.stories.js +38 -0
- package/dist/collection/components/feedlog-button/feedlog-button.css +155 -0
- package/dist/collection/components/feedlog-button/feedlog-button.js +154 -0
- package/dist/collection/components/feedlog-button/feedlog-button.stories.js +82 -0
- package/dist/collection/components/feedlog-card/feedlog-card.css +47 -0
- package/dist/collection/components/feedlog-card/feedlog-card.js +23 -0
- package/dist/collection/components/feedlog-card/feedlog-card.stories.js +22 -0
- package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.css +69 -0
- package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.js +308 -0
- package/dist/collection/components/feedlog-github-issues/feedlog-github-issues.stories.js +211 -0
- package/dist/collection/components/feedlog-github-issues-client/feedlog-github-issues-client.js +395 -0
- package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.css +218 -0
- package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.js +139 -0
- package/dist/collection/components/index.js +6 -0
- package/dist/collection/index.js +1 -0
- package/dist/components/feedlog-badge.d.ts +11 -0
- package/dist/components/feedlog-badge.js +1 -0
- package/dist/components/feedlog-button.d.ts +11 -0
- package/dist/components/feedlog-button.js +1 -0
- package/dist/components/feedlog-card.d.ts +11 -0
- package/dist/components/feedlog-card.js +1 -0
- package/dist/components/feedlog-github-issues-client.d.ts +11 -0
- package/dist/components/feedlog-github-issues-client.js +1 -0
- package/dist/components/feedlog-github-issues.d.ts +11 -0
- package/dist/components/feedlog-github-issues.js +1 -0
- package/dist/components/feedlog-issues-list.d.ts +11 -0
- package/dist/components/feedlog-issues-list.js +1 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/p-CHtSMTyP.js +1 -0
- package/dist/components/p-CPOiBAxu.js +1 -0
- package/dist/components/p-DMcNh5Ys.js +1 -0
- package/dist/components/p-DMdb-G26.js +1 -0
- package/dist/esm/feedlog-badge_3.entry.js +115 -0
- package/dist/esm/feedlog-card.entry.js +15 -0
- package/dist/esm/feedlog-github-issues-client.entry.js +518 -0
- package/dist/esm/feedlog-github-issues.entry.js +79 -0
- package/dist/esm/feedlog-toolkit.js +20 -0
- package/dist/esm/index-CkB6Yzeb.js +3135 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/loader.js +10 -0
- package/dist/feedlog-toolkit/feedlog-toolkit.css +1 -0
- package/dist/feedlog-toolkit/feedlog-toolkit.esm.js +1 -0
- package/dist/feedlog-toolkit/index.esm.js +0 -0
- package/dist/feedlog-toolkit/p-2f7954f7.entry.js +1 -0
- package/dist/feedlog-toolkit/p-399e0281.entry.js +1 -0
- package/dist/feedlog-toolkit/p-CkB6Yzeb.js +2 -0
- package/dist/feedlog-toolkit/p-b3d26272.entry.js +1 -0
- package/dist/feedlog-toolkit/p-cdb2b098.entry.js +1 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/components/feedlog-badge/feedlog-badge.d.ts +12 -0
- package/dist/types/components/feedlog-badge/feedlog-badge.stories.d.ts +9 -0
- package/dist/types/components/feedlog-button/feedlog-button.d.ts +30 -0
- package/dist/types/components/feedlog-button/feedlog-button.stories.d.ts +13 -0
- package/dist/types/components/feedlog-card/feedlog-card.d.ts +8 -0
- package/dist/types/components/feedlog-card/feedlog-card.stories.d.ts +9 -0
- package/dist/types/components/feedlog-github-issues/feedlog-github-issues.d.ts +67 -0
- package/dist/types/components/feedlog-github-issues/feedlog-github-issues.stories.d.ts +11 -0
- package/dist/types/components/feedlog-github-issues-client/feedlog-github-issues-client.d.ts +77 -0
- package/dist/types/components/feedlog-issues-list/feedlog-issues-list.d.ts +31 -0
- package/dist/types/components/index.d.ts +6 -0
- package/dist/types/components.d.ts +532 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/stencil-public-runtime.d.ts +1810 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +48 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-5lluu_3h.js');
|
|
4
|
+
|
|
5
|
+
const feedlogBadgeCss = () => `:host{display:inline-block;--feedlog-badge-font-size:0.75rem;--feedlog-badge-font-weight:500;--feedlog-badge-padding-x:0.5rem;--feedlog-badge-padding-y:0.125rem;--feedlog-badge-border-radius:calc(0.625rem - 2px);--feedlog-blue-500:oklch(0.623 0.214 259.815);--feedlog-blue-600:oklch(0.546 0.245 262.881);--feedlog-blue-700:oklch(0.488 0.243 264.376);--feedlog-destructive:#d4183d;--feedlog-destructive-hover:#b91c1c}:host(.dark){--feedlog-blue-500:oklch(0.623 0.214 259.815);--feedlog-blue-600:oklch(0.546 0.245 262.881);--feedlog-destructive:oklch(0.396 0.141 25.723);--feedlog-destructive-hover:oklch(0.45 0.16 25.723)}.badge{display:inline-flex;align-items:center;justify-content:center;font-size:var(--feedlog-badge-font-size);font-weight:var(--feedlog-badge-font-weight);padding:var(--feedlog-badge-padding-y) var(--feedlog-badge-padding-x);border-radius:var(--feedlog-badge-border-radius);white-space:nowrap;transition:background-color 0.15s ease;font-family:inherit}.badge-default{background-color:var(--feedlog-blue-600);color:#ffffff}.badge-default:hover{background-color:var(--feedlog-blue-700)}:host(.dark) .badge-default{background-color:var(--feedlog-blue-500)}:host(.dark) .badge-default:hover{background-color:var(--feedlog-blue-600)}.badge-enhancement{background-color:var(--feedlog-blue-600);color:#ffffff}.badge-enhancement:hover{background-color:var(--feedlog-blue-700)}:host(.dark) .badge-enhancement{background-color:var(--feedlog-blue-500)}:host(.dark) .badge-enhancement:hover{background-color:var(--feedlog-blue-600)}.badge-destructive{background-color:var(--feedlog-destructive);color:#ffffff}.badge-destructive:hover{background-color:var(--feedlog-destructive-hover)}`;
|
|
6
|
+
|
|
7
|
+
const FeedlogBadge = class {
|
|
8
|
+
constructor(hostRef) {
|
|
9
|
+
index.registerInstance(this, hostRef);
|
|
10
|
+
/**
|
|
11
|
+
* Badge variant style
|
|
12
|
+
*/
|
|
13
|
+
this.variant = 'default';
|
|
14
|
+
}
|
|
15
|
+
render() {
|
|
16
|
+
return (index.h("span", { key: '482a74feb8d254a75383c30c7b39790edd04a05b', class: `badge badge-${this.variant}` }, index.h("slot", { key: '8d2db3fe0c2bc58e17829db4de7d0233189bb101' })));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
FeedlogBadge.style = feedlogBadgeCss();
|
|
20
|
+
|
|
21
|
+
const feedlogButtonCss = () => `:host{display:inline-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-primary:#030213;--feedlog-primary-foreground:oklch(1 0 0);--feedlog-secondary:oklch(0.95 0.0058 264.53);--feedlog-secondary-foreground:#030213;--feedlog-muted:#ececf0;--feedlog-accent:#e9ebef;--feedlog-accent-foreground:#030213;--feedlog-border:rgba(0, 0, 0, 0.1);--feedlog-input:transparent;--feedlog-ring:oklch(0.708 0 0);--feedlog-destructive:#d4183d;--feedlog-radius:0.625rem}:host(.dark){--feedlog-background:oklch(0.145 0 0);--feedlog-foreground:oklch(0.985 0 0);--feedlog-primary:oklch(0.985 0 0);--feedlog-primary-foreground:oklch(0.205 0 0);--feedlog-secondary:oklch(0.269 0 0);--feedlog-secondary-foreground:oklch(0.985 0 0);--feedlog-muted:oklch(0.269 0 0);--feedlog-accent:oklch(0.269 0 0);--feedlog-accent-foreground:oklch(0.985 0 0);--feedlog-border:oklch(0.269 0 0);--feedlog-input:oklch(0.269 0 0);--feedlog-ring:oklch(0.439 0 0);--feedlog-destructive:oklch(0.396 0.141 25.723)}button{display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;white-space:nowrap;font-size:0.875rem;font-weight:500;border-radius:calc(var(--feedlog-radius) - 2px);border:1px solid transparent;cursor:pointer;transition:all 0.15s ease;outline:none;font-family:inherit}button:disabled{opacity:0.5;cursor:not-allowed;pointer-events:none}button:focus-visible{border-color:var(--feedlog-ring);box-shadow:0 0 0 3px color-mix(in oklab, var(--feedlog-ring) 50%, transparent)}.button-default{background-color:var(--feedlog-primary);color:var(--feedlog-primary-foreground);border-color:transparent}.button-default:hover:not(:disabled){background-color:color-mix(in oklab, var(--feedlog-primary) 90%, transparent)}.button-outline{background-color:var(--feedlog-background);color:var(--feedlog-foreground);border-color:var(--feedlog-border)}.button-outline:hover:not(:disabled){background-color:var(--feedlog-accent);color:var(--feedlog-accent-foreground)}:host(.dark) .button-outline{background-color:transparent;border-color:var(--feedlog-input)}:host(.dark) .button-outline:hover:not(:disabled){background-color:color-mix(in oklab, var(--feedlog-accent) 50%, transparent)}.button-ghost{background-color:transparent;color:var(--feedlog-foreground);border-color:transparent}.button-ghost:hover:not(:disabled){background-color:var(--feedlog-accent);color:var(--feedlog-accent-foreground)}.button-destructive{background-color:var(--feedlog-destructive);color:#ffffff;border-color:transparent}.button-destructive:hover:not(:disabled){background-color:color-mix(in oklab, var(--feedlog-destructive) 90%, transparent)}:host(.dark) .button-destructive{background-color:color-mix(in oklab, var(--feedlog-destructive) 60%, transparent)}.button-size-sm{height:2rem;padding:0 0.75rem;font-size:0.75rem}.button-size-sm:has(svg:only-child){width:2rem;padding:0}.button-size-default{height:2.25rem;padding:0.5rem 1rem}.button-size-lg{height:2.5rem;padding:0.625rem 1.5rem;font-size:1rem}button svg{pointer-events:none;flex-shrink:0;width:1rem;height:1rem}`;
|
|
22
|
+
|
|
23
|
+
const FeedlogButton = class {
|
|
24
|
+
constructor(hostRef) {
|
|
25
|
+
index.registerInstance(this, hostRef);
|
|
26
|
+
this.feedlogClick = index.createEvent(this, "feedlogClick");
|
|
27
|
+
/**
|
|
28
|
+
* Button variant style
|
|
29
|
+
*/
|
|
30
|
+
this.variant = 'default';
|
|
31
|
+
/**
|
|
32
|
+
* Button size
|
|
33
|
+
*/
|
|
34
|
+
this.size = 'default';
|
|
35
|
+
/**
|
|
36
|
+
* Disabled state
|
|
37
|
+
*/
|
|
38
|
+
this.disabled = false;
|
|
39
|
+
/**
|
|
40
|
+
* Button type
|
|
41
|
+
*/
|
|
42
|
+
this.type = 'button';
|
|
43
|
+
this.handleClick = (event) => {
|
|
44
|
+
if (!this.disabled) {
|
|
45
|
+
this.feedlogClick.emit(event);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
render() {
|
|
50
|
+
const sizeClass = this.size === 'default' ? 'button-size-default' : `button-size-${this.size}`;
|
|
51
|
+
return (index.h("button", { key: '6cdd8347def51592707b1fb9aab0dc565ca0f76f', type: this.type, class: `button button-${this.variant} ${sizeClass}`, disabled: this.disabled, onClick: this.handleClick }, index.h("slot", { key: '3f3845195fa4b8a551473ecf1d5702321a31763e' })));
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
FeedlogButton.style = feedlogButtonCss();
|
|
55
|
+
|
|
56
|
+
const feedlogIssuesListCss = () => `: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-card:#ffffff;--feedlog-card-foreground:oklch(0.145 0 0);--feedlog-muted:#ececf0;--feedlog-muted-foreground:#717182;--feedlog-border:rgba(0, 0, 0, 0.1);--feedlog-accent-color:#2563eb;--feedlog-destructive:#d4183d;--feedlog-blue-400:oklch(0.707 0.165 254.624);--feedlog-blue-600:oklch(0.546 0.245 262.881);--feedlog-blue-100:oklch(0.932 0.032 255.585);--feedlog-red-100:#fce7f3;--feedlog-red-400:#f472b6;--feedlog-red-600:#db2777;--feedlog-radius:0.625rem;--feedlog-gap:0.5rem}:host(.dark){--feedlog-background:oklch(0.145 0 0);--feedlog-foreground:oklch(0.985 0 0);--feedlog-card:oklch(0.145 0 0);--feedlog-card-foreground:oklch(0.985 0 0);--feedlog-muted:oklch(0.269 0 0);--feedlog-muted-foreground:oklch(0.708 0 0);--feedlog-border:oklch(0.269 0 0);--feedlog-accent-color:#3b82f6;--feedlog-destructive:oklch(0.396 0.141 25.723);--feedlog-blue-400:oklch(0.707 0.165 254.624);--feedlog-blue-600:oklch(0.546 0.245 262.881);--feedlog-blue-900-30:color-mix(in oklab, oklch(0.379 0.146 265.522) 30%, transparent);--feedlog-red-900-30:color-mix(in oklab, oklch(0.396 0.141 25.723) 30%, transparent)}.issues-list{display:flex;flex-direction:column;gap:var(--feedlog-gap)}.empty-state{text-align:center;padding:3rem 1.5rem;color:var(--feedlog-muted-foreground);font-size:0.875rem}.issue-card{background-color:var(--feedlog-card);border:1px solid var(--feedlog-border);border-radius:var(--feedlog-radius);box-shadow:0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);transition:box-shadow 0.15s ease;position:relative}.issue-card:hover{box-shadow:0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)}.issue-content{padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.issue-header{display:flex;align-items:center;gap:0.5rem;justify-content:space-between}.issue-type-badge{width:fit-content}.pinned-indicator{font-size:1rem;opacity:0.7}.issue-main{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}.issue-details{flex:1;min-width:0}.issue-title{color:var(--feedlog-card-foreground);font-size:0.875rem;font-weight:600;margin:0 0 0.375rem 0;line-height:1.4;word-break:break-word}.issue-body{color:var(--feedlog-muted-foreground);font-size:0.75rem;line-height:1.625;margin:0 0 0.75rem 0;word-break:break-word;white-space:pre-wrap}.issue-repository{display:flex;align-items:center;gap:0.5rem;font-size:0.75rem;color:var(--feedlog-muted-foreground);margin-bottom:0.5rem}.repo-name{font-weight:500}.github-number{color:var(--feedlog-blue-600);font-weight:600}:host(.dark) .github-number{color:var(--feedlog-blue-400)}.upvote-button{display:flex;flex-direction:column;align-items:center;gap:0.125rem;padding:0.5rem 0.75rem;border-radius:0.5rem;background-color:var(--feedlog-muted);border:1px solid transparent;cursor:pointer;transition:all 0.15s ease;flex-shrink:0;font-size:0.75rem;font-weight:600}.upvote-button:hover{background-color:var(--feedlog-blue-100);border-color:var(--feedlog-blue-400)}.upvote-button.upvoted{background-color:var(--feedlog-red-100);border-color:var(--feedlog-red-400)}.upvote-button.upvoted:hover{background-color:var(--feedlog-red-100);border-color:var(--feedlog-red-600)}:host(.dark) .upvote-button:hover{background-color:var(--feedlog-blue-900-30);border-color:var(--feedlog-blue-600)}:host(.dark) .upvote-button.upvoted{background-color:var(--feedlog-red-900-30);border-color:var(--feedlog-red-600)}.upvote-icon{width:1rem;height:1rem;stroke-width:2}.upvote-icon.filled{color:var(--feedlog-red-600)}.upvote-icon.outline{color:var(--feedlog-blue-600)}:host(.dark) .upvote-icon.outline{color:var(--feedlog-blue-400)}.upvote-count{font-size:0.75rem;font-weight:600;color:var(--feedlog-card-foreground)}.issue-footer{display:flex;flex-direction:column;gap:0.25rem;font-size:0.75rem}.issue-date{color:var(--feedlog-muted-foreground);cursor:help}`;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Heart icon SVG component (filled)
|
|
60
|
+
*/
|
|
61
|
+
const HeartFilledIcon = () => (index.h("svg", { class: "upvote-icon filled", xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none" }, index.h("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })));
|
|
62
|
+
/**
|
|
63
|
+
* Heart icon SVG component (outline)
|
|
64
|
+
*/
|
|
65
|
+
const HeartOutlineIcon = () => (index.h("svg", { class: "upvote-icon outline", 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" }, index.h("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })));
|
|
66
|
+
const FeedlogIssuesList = class {
|
|
67
|
+
constructor(hostRef) {
|
|
68
|
+
index.registerInstance(this, hostRef);
|
|
69
|
+
this.feedlogUpvote = index.createEvent(this, "feedlogUpvote");
|
|
70
|
+
/**
|
|
71
|
+
* Array of issues to display
|
|
72
|
+
*/
|
|
73
|
+
this.issues = [];
|
|
74
|
+
/**
|
|
75
|
+
* Theme variant: 'light' or 'dark'
|
|
76
|
+
*/
|
|
77
|
+
this.theme = 'light';
|
|
78
|
+
this.handleUpvote = (event, issue) => {
|
|
79
|
+
event.stopPropagation();
|
|
80
|
+
this.feedlogUpvote.emit({
|
|
81
|
+
issueId: issue.id,
|
|
82
|
+
currentUpvoted: issue.hasUpvoted,
|
|
83
|
+
currentCount: issue.upvoteCount,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
render() {
|
|
88
|
+
return (index.h(index.Host, { key: '5cef6f5476239d0f8096664c04690aa4c3383bd0', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: 'd72fffe457f0497dbbbe0c64dab3282f76a49217', class: "issues-list" }, this.issues.length === 0 ? (index.h("div", { class: "empty-state" }, index.h("p", null, "No issues found"))) : (this.issues.map(issue => (index.h("div", { key: issue.id, class: "issue-card" }, index.h("div", { class: "issue-content" }, index.h("div", { class: "issue-header" }, index.h("div", { class: "issue-type-badge" }, issue.type === 'bug' ? (index.h("feedlog-badge", { variant: "destructive" }, "Bug")) : (index.h("feedlog-badge", { variant: "enhancement" }, "Enhancement"))), issue.pinnedAt && (index.h("div", { class: "pinned-indicator", title: "Pinned issue" }, "\uD83D\uDCCC"))), index.h("div", { class: "issue-main" }, index.h("div", { class: "issue-details" }, index.h("h3", { class: "issue-title" }, issue.title), index.h("p", { class: "issue-body" }, issue.body), index.h("div", { class: "issue-repository" }, index.h("span", { class: "repo-name" }, issue.repository.owner, "/", issue.repository.name))), index.h("button", { class: `upvote-button ${issue.hasUpvoted ? 'upvoted' : ''}`, onClick: (e) => this.handleUpvote(e, issue), title: issue.hasUpvoted ? 'Remove upvote' : 'Upvote this issue' }, issue.hasUpvoted ? index.h(HeartFilledIcon, null) : index.h(HeartOutlineIcon, null), index.h("span", { class: "upvote-count" }, issue.upvoteCount))), index.h("div", { class: "issue-footer" }, index.h("span", { class: "issue-date", title: `Updated: ${issue.updatedAt}` }, "Updated ", this.formatDate(issue.updatedAt)), index.h("span", { class: "issue-date", title: `Created: ${issue.createdAt}` }, "Created ", this.formatDate(issue.createdAt)))))))))));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format an ISO date string to a relative time string
|
|
92
|
+
*/
|
|
93
|
+
formatDate(dateString) {
|
|
94
|
+
try {
|
|
95
|
+
const date = new Date(dateString);
|
|
96
|
+
const now = new Date();
|
|
97
|
+
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
|
98
|
+
if (seconds < 60)
|
|
99
|
+
return 'just now';
|
|
100
|
+
if (seconds < 3600)
|
|
101
|
+
return `${Math.floor(seconds / 60)}m ago`;
|
|
102
|
+
if (seconds < 86400)
|
|
103
|
+
return `${Math.floor(seconds / 3600)}h ago`;
|
|
104
|
+
if (seconds < 604800)
|
|
105
|
+
return `${Math.floor(seconds / 86400)}d ago`;
|
|
106
|
+
if (seconds < 2592000)
|
|
107
|
+
return `${Math.floor(seconds / 604800)}w ago`;
|
|
108
|
+
return date.toLocaleDateString();
|
|
109
|
+
}
|
|
110
|
+
catch (_a) {
|
|
111
|
+
return 'unknown date';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
FeedlogIssuesList.style = feedlogIssuesListCss();
|
|
116
|
+
|
|
117
|
+
exports.feedlog_badge = FeedlogBadge;
|
|
118
|
+
exports.feedlog_button = FeedlogButton;
|
|
119
|
+
exports.feedlog_issues_list = FeedlogIssuesList;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-5lluu_3h.js');
|
|
4
|
+
|
|
5
|
+
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}`;
|
|
6
|
+
|
|
7
|
+
const FeedlogCard = class {
|
|
8
|
+
constructor(hostRef) {
|
|
9
|
+
index.registerInstance(this, hostRef);
|
|
10
|
+
}
|
|
11
|
+
render() {
|
|
12
|
+
return (index.h("div", { key: '293a80e66adedfc1af29daf72390a4f464321b96', class: "feedlog-card" }, index.h("slot", { key: 'b7e5a827f89035e791d9c756db0f66198e6c5a38', name: "header" }), index.h("slot", { key: 'da89fee0a01068c8438564848f218faa9c5d849e', name: "content" }), index.h("slot", { key: '30b05e80e4189c0f73810a48f64e072dfac83267', name: "footer" })));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
FeedlogCard.style = feedlogCardCss();
|
|
16
|
+
|
|
17
|
+
exports.feedlog_card = FeedlogCard;
|
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-5lluu_3h.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* HTML and XSS sanitization utilities
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Basic HTML entity escaping to prevent XSS
|
|
10
|
+
* This is a lightweight alternative to DOMPurify
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Sanitize HTML by removing dangerous tags and attributes
|
|
14
|
+
* Removes script tags, event handlers, and other potentially malicious content
|
|
15
|
+
*/
|
|
16
|
+
function sanitizeHtml(html) {
|
|
17
|
+
if (typeof html !== 'string') {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
// Remove script tags and content
|
|
21
|
+
let sanitized = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
|
|
22
|
+
// Remove on* event handlers
|
|
23
|
+
sanitized = sanitized.replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, '');
|
|
24
|
+
sanitized = sanitized.replace(/\s*on\w+\s*=\s*[^\s>]*/gi, '');
|
|
25
|
+
// Remove iframe tags
|
|
26
|
+
sanitized = sanitized.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '');
|
|
27
|
+
// Remove style tags
|
|
28
|
+
sanitized = sanitized.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');
|
|
29
|
+
// Remove embed and object tags
|
|
30
|
+
sanitized = sanitized.replace(/<(embed|object)\b[^<]*>/gi, '');
|
|
31
|
+
// Remove javascript: protocol
|
|
32
|
+
sanitized = sanitized.replace(/javascript:/gi, '');
|
|
33
|
+
// Remove data: protocol for potentially dangerous mime types
|
|
34
|
+
sanitized = sanitized.replace(/data:(?!image\/(?:png|jpg|jpeg|gif|webp);)/gi, '');
|
|
35
|
+
return sanitized;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Custom error types for Feedlog SDK
|
|
40
|
+
*/
|
|
41
|
+
class FeedlogError extends Error {
|
|
42
|
+
constructor(message, statusCode, originalError) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.statusCode = statusCode;
|
|
45
|
+
this.originalError = originalError;
|
|
46
|
+
this.name = 'FeedlogError';
|
|
47
|
+
Object.setPrototypeOf(this, FeedlogError.prototype);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
class FeedlogValidationError extends FeedlogError {
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = 'FeedlogValidationError';
|
|
54
|
+
Object.setPrototypeOf(this, FeedlogValidationError.prototype);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
class FeedlogNetworkError extends FeedlogError {
|
|
58
|
+
constructor(message, statusCode, originalError) {
|
|
59
|
+
super(message, statusCode, originalError);
|
|
60
|
+
this.name = 'FeedlogNetworkError';
|
|
61
|
+
Object.setPrototypeOf(this, FeedlogNetworkError.prototype);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
class FeedlogTimeoutError extends FeedlogError {
|
|
65
|
+
constructor(message = 'Request timed out') {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = 'FeedlogTimeoutError';
|
|
68
|
+
Object.setPrototypeOf(this, FeedlogTimeoutError.prototype);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Core SDK for Feedlog Toolkit
|
|
74
|
+
*
|
|
75
|
+
* This package provides the core functionality and utilities
|
|
76
|
+
* used across all Feedlog Toolkit packages.
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* Main Feedlog SDK class
|
|
80
|
+
* Provides methods to interact with the Feedlog API
|
|
81
|
+
*/
|
|
82
|
+
class FeedlogSDK {
|
|
83
|
+
constructor(config = {}) {
|
|
84
|
+
this.config = {
|
|
85
|
+
credentials: 'include',
|
|
86
|
+
...config,
|
|
87
|
+
};
|
|
88
|
+
this.endpoint = this.config.endpoint || 'https://api.feedlog.app';
|
|
89
|
+
this.timeout = this.config.timeout || 30000;
|
|
90
|
+
// Ensure endpoint doesn't have trailing slash
|
|
91
|
+
this.endpoint = this.endpoint.replace(/\/$/, '');
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fetch issues from the API
|
|
95
|
+
* Supports filtering by repository IDs, type, pagination, and limit
|
|
96
|
+
*/
|
|
97
|
+
async fetchIssues(params = {}) {
|
|
98
|
+
try {
|
|
99
|
+
const url = this.buildIssuesUrl(params);
|
|
100
|
+
const response = await this.fetchWithTimeout(url, {
|
|
101
|
+
method: 'GET',
|
|
102
|
+
headers: this.getAuthHeaders(),
|
|
103
|
+
credentials: this.config.credentials || 'include',
|
|
104
|
+
});
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
throw new FeedlogNetworkError(`Failed to fetch issues: ${response.statusText}`, response.status);
|
|
107
|
+
}
|
|
108
|
+
const data = await response.json();
|
|
109
|
+
return this.validateIssuesResponse(data);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error instanceof FeedlogError) {
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
if (error instanceof TypeError && error.message.includes('fetch')) {
|
|
116
|
+
throw new FeedlogNetworkError('Network error: Unable to reach API', undefined, error);
|
|
117
|
+
}
|
|
118
|
+
throw new FeedlogError(`Failed to fetch issues: ${error instanceof Error ? error.message : 'Unknown error'}`, undefined, error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Toggle upvote on an issue
|
|
123
|
+
* Adds upvote if not already upvoted, removes if already upvoted
|
|
124
|
+
*/
|
|
125
|
+
async toggleUpvote(issueId) {
|
|
126
|
+
if (!issueId || typeof issueId !== 'string') {
|
|
127
|
+
throw new FeedlogValidationError('Issue ID is required');
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const url = `${this.endpoint}/api/issues/${encodeURIComponent(issueId)}/upvote`;
|
|
131
|
+
const response = await this.fetchWithTimeout(url, {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers: this.getAuthHeaders(),
|
|
134
|
+
credentials: this.config.credentials || 'include',
|
|
135
|
+
});
|
|
136
|
+
if (response.status === 404) {
|
|
137
|
+
throw new FeedlogNetworkError('Issue not found', 404);
|
|
138
|
+
}
|
|
139
|
+
if (response.status === 401) {
|
|
140
|
+
throw new FeedlogNetworkError('Unauthorized', 401);
|
|
141
|
+
}
|
|
142
|
+
if (response.status === 403) {
|
|
143
|
+
throw new FeedlogNetworkError('Forbidden: Domain not allowed for this repository', 403);
|
|
144
|
+
}
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
throw new FeedlogNetworkError(`Failed to toggle upvote: ${response.statusText}`, response.status);
|
|
147
|
+
}
|
|
148
|
+
const data = await response.json();
|
|
149
|
+
return this.validateUpvoteResponse(data);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error instanceof FeedlogError) {
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
if (error instanceof TypeError && error.message.includes('fetch')) {
|
|
156
|
+
throw new FeedlogNetworkError('Network error: Unable to reach API', undefined, error);
|
|
157
|
+
}
|
|
158
|
+
throw new FeedlogError(`Failed to toggle upvote: ${error instanceof Error ? error.message : 'Unknown error'}`, undefined, error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Build the full URL for fetching issues with query parameters
|
|
163
|
+
*/
|
|
164
|
+
buildIssuesUrl(params) {
|
|
165
|
+
const url = new URL(`${this.endpoint}/api/issues`);
|
|
166
|
+
// Handle repositoryIds - can be single string or array
|
|
167
|
+
if (params.repositoryIds) {
|
|
168
|
+
const ids = Array.isArray(params.repositoryIds)
|
|
169
|
+
? params.repositoryIds
|
|
170
|
+
: [params.repositoryIds];
|
|
171
|
+
for (const id of ids) {
|
|
172
|
+
url.searchParams.append('repositoryIds', id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (params.type) {
|
|
176
|
+
url.searchParams.set('type', params.type);
|
|
177
|
+
}
|
|
178
|
+
if (params.cursor) {
|
|
179
|
+
url.searchParams.set('cursor', params.cursor);
|
|
180
|
+
}
|
|
181
|
+
if (params.limit !== undefined) {
|
|
182
|
+
url.searchParams.set('limit', params.limit.toString());
|
|
183
|
+
}
|
|
184
|
+
return url.toString();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get request headers
|
|
188
|
+
*/
|
|
189
|
+
getAuthHeaders() {
|
|
190
|
+
return {
|
|
191
|
+
'Content-Type': 'application/json',
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Fetch with timeout support using AbortController
|
|
196
|
+
*/
|
|
197
|
+
async fetchWithTimeout(url, init) {
|
|
198
|
+
const controller = new AbortController();
|
|
199
|
+
const timeout = setTimeout(() => controller.abort(), this.timeout);
|
|
200
|
+
try {
|
|
201
|
+
const response = await fetch(url, {
|
|
202
|
+
...init,
|
|
203
|
+
signal: controller.signal,
|
|
204
|
+
});
|
|
205
|
+
clearTimeout(timeout);
|
|
206
|
+
return response;
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
clearTimeout(timeout);
|
|
210
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
211
|
+
throw new FeedlogTimeoutError(`Request timed out after ${this.timeout}ms`);
|
|
212
|
+
}
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Validate and sanitize issues response
|
|
218
|
+
*/
|
|
219
|
+
validateIssuesResponse(data) {
|
|
220
|
+
if (!data || typeof data !== 'object') {
|
|
221
|
+
throw new FeedlogValidationError('Invalid API response: expected object');
|
|
222
|
+
}
|
|
223
|
+
const response = data;
|
|
224
|
+
if (!Array.isArray(response.issues)) {
|
|
225
|
+
throw new FeedlogValidationError('Invalid API response: issues must be an array');
|
|
226
|
+
}
|
|
227
|
+
if (!response.pagination || typeof response.pagination !== 'object') {
|
|
228
|
+
throw new FeedlogValidationError('Invalid API response: pagination is required');
|
|
229
|
+
}
|
|
230
|
+
const issues = response.issues.map(issue => this.validateIssue(issue));
|
|
231
|
+
return {
|
|
232
|
+
issues,
|
|
233
|
+
pagination: {
|
|
234
|
+
cursor: response.pagination.cursor,
|
|
235
|
+
hasMore: Boolean(response.pagination.hasMore),
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Validate and sanitize an individual issue
|
|
241
|
+
*/
|
|
242
|
+
validateIssue(data) {
|
|
243
|
+
if (!data || typeof data !== 'object') {
|
|
244
|
+
throw new FeedlogValidationError('Invalid issue: expected object');
|
|
245
|
+
}
|
|
246
|
+
const issue = data;
|
|
247
|
+
// Validate required fields
|
|
248
|
+
if (typeof issue.id !== 'string') {
|
|
249
|
+
throw new FeedlogValidationError('Invalid issue: id is required and must be a string');
|
|
250
|
+
}
|
|
251
|
+
if (typeof issue.title !== 'string') {
|
|
252
|
+
throw new FeedlogValidationError('Invalid issue: title is required and must be a string');
|
|
253
|
+
}
|
|
254
|
+
if (!['bug', 'enhancement'].includes(String(issue.type))) {
|
|
255
|
+
throw new FeedlogValidationError('Invalid issue: type must be "bug" or "enhancement"');
|
|
256
|
+
}
|
|
257
|
+
if (!['open', 'closed'].includes(String(issue.status))) {
|
|
258
|
+
throw new FeedlogValidationError('Invalid issue: status must be "open" or "closed"');
|
|
259
|
+
}
|
|
260
|
+
if (!issue.repository || typeof issue.repository !== 'object') {
|
|
261
|
+
throw new FeedlogValidationError('Invalid issue: repository is required');
|
|
262
|
+
}
|
|
263
|
+
const repo = issue.repository;
|
|
264
|
+
if (typeof repo.id !== 'string' ||
|
|
265
|
+
typeof repo.name !== 'string' ||
|
|
266
|
+
typeof repo.owner !== 'string') {
|
|
267
|
+
throw new FeedlogValidationError('Invalid issue: repository must have id, name, and owner');
|
|
268
|
+
}
|
|
269
|
+
// Sanitize string fields to prevent XSS
|
|
270
|
+
const sanitizedTitle = sanitizeHtml(String(issue.title));
|
|
271
|
+
const sanitizedBody = sanitizeHtml(String(issue.body || ''));
|
|
272
|
+
return {
|
|
273
|
+
id: String(issue.id),
|
|
274
|
+
type: issue.type || 'bug',
|
|
275
|
+
status: issue.status || 'open',
|
|
276
|
+
pinnedAt: issue.pinnedAt ? String(issue.pinnedAt) : null,
|
|
277
|
+
revision: Number(issue.revision) || 1,
|
|
278
|
+
title: sanitizedTitle,
|
|
279
|
+
body: sanitizedBody,
|
|
280
|
+
repository: {
|
|
281
|
+
id: String(repo.id),
|
|
282
|
+
name: String(repo.name),
|
|
283
|
+
owner: String(repo.owner),
|
|
284
|
+
},
|
|
285
|
+
updatedAt: String(issue.updatedAt) || new Date().toISOString(),
|
|
286
|
+
createdAt: String(issue.createdAt) || new Date().toISOString(),
|
|
287
|
+
upvoteCount: Number(issue.upvoteCount) || 0,
|
|
288
|
+
hasUpvoted: Boolean(issue.hasUpvoted),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Validate upvote response
|
|
293
|
+
*/
|
|
294
|
+
validateUpvoteResponse(data) {
|
|
295
|
+
if (!data || typeof data !== 'object') {
|
|
296
|
+
throw new FeedlogValidationError('Invalid upvote response: expected object');
|
|
297
|
+
}
|
|
298
|
+
const response = data;
|
|
299
|
+
if (typeof response.upvoted !== 'boolean') {
|
|
300
|
+
throw new FeedlogValidationError('Invalid upvote response: upvoted must be a boolean');
|
|
301
|
+
}
|
|
302
|
+
if (typeof response.upvoteCount !== 'number') {
|
|
303
|
+
throw new FeedlogValidationError('Invalid upvote response: upvoteCount must be a number');
|
|
304
|
+
}
|
|
305
|
+
if (typeof response.anonymousUserId !== 'string') {
|
|
306
|
+
throw new FeedlogValidationError('Invalid upvote response: anonymousUserId must be a string');
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
upvoted: response.upvoted,
|
|
310
|
+
upvoteCount: response.upvoteCount,
|
|
311
|
+
anonymousUserId: response.anonymousUserId,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get the current endpoint
|
|
316
|
+
*/
|
|
317
|
+
getEndpoint() {
|
|
318
|
+
return this.endpoint;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Get the current timeout setting
|
|
322
|
+
*/
|
|
323
|
+
getTimeout() {
|
|
324
|
+
return this.timeout;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const FeedlogGithubIssuesClient = class {
|
|
329
|
+
constructor(hostRef) {
|
|
330
|
+
index.registerInstance(this, hostRef);
|
|
331
|
+
this.feedlogUpvote = index.createEvent(this, "feedlogUpvote");
|
|
332
|
+
this.feedlogThemeChange = index.createEvent(this, "feedlogThemeChange");
|
|
333
|
+
this.feedlogError = index.createEvent(this, "feedlogError");
|
|
334
|
+
/**
|
|
335
|
+
* Maximum width of the container
|
|
336
|
+
*/
|
|
337
|
+
this.maxWidth = '42rem';
|
|
338
|
+
/**
|
|
339
|
+
* Theme variant: 'light' or 'dark'
|
|
340
|
+
*/
|
|
341
|
+
this.theme = 'light';
|
|
342
|
+
/**
|
|
343
|
+
* Whether to show the theme toggle button
|
|
344
|
+
*/
|
|
345
|
+
this.showThemeToggle = true;
|
|
346
|
+
this.issues = [];
|
|
347
|
+
this.loading = true;
|
|
348
|
+
this.error = null;
|
|
349
|
+
this.cursor = null;
|
|
350
|
+
this.hasMore = false;
|
|
351
|
+
this.isLoadingMore = false;
|
|
352
|
+
this.sdk = null;
|
|
353
|
+
this.handleUpvote = async (event) => {
|
|
354
|
+
if (!this.sdk) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const { issueId, currentUpvoted, currentCount } = event.detail;
|
|
358
|
+
// Optimistic update
|
|
359
|
+
this.issues = this.issues.map(issue => issue.id === issueId
|
|
360
|
+
? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
|
|
361
|
+
try {
|
|
362
|
+
const result = await this.sdk.toggleUpvote(issueId);
|
|
363
|
+
// Update with server response
|
|
364
|
+
this.issues = this.issues.map(issue => issue.id === issueId
|
|
365
|
+
? Object.assign(Object.assign({}, issue), { hasUpvoted: result.upvoted, upvoteCount: result.upvoteCount }) : issue);
|
|
366
|
+
this.feedlogUpvote.emit({
|
|
367
|
+
issueId,
|
|
368
|
+
upvoted: result.upvoted,
|
|
369
|
+
upvoteCount: result.upvoteCount,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
catch (err) {
|
|
373
|
+
// Revert optimistic update on error
|
|
374
|
+
this.issues = this.issues.map(issue => issue.id === issueId
|
|
375
|
+
? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
|
|
376
|
+
const errorMsg = err instanceof Error ? err.message : 'Failed to toggle upvote';
|
|
377
|
+
this.feedlogError.emit({ error: errorMsg });
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
this.handleThemeChange = (event) => {
|
|
381
|
+
this.theme = event.detail;
|
|
382
|
+
this.feedlogThemeChange.emit(event.detail);
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
componentWillLoad() {
|
|
386
|
+
this.previousRepos = this.repos;
|
|
387
|
+
this.previousType = this.type;
|
|
388
|
+
this.previousLimit = this.limit;
|
|
389
|
+
this.initializeSDK();
|
|
390
|
+
this.fetchIssues();
|
|
391
|
+
}
|
|
392
|
+
componentDidUpdate() {
|
|
393
|
+
// Re-fetch if any props changed
|
|
394
|
+
const reposChanged = JSON.stringify(this.previousRepos) !== JSON.stringify(this.repos);
|
|
395
|
+
const typeChanged = this.previousType !== this.type;
|
|
396
|
+
const limitChanged = this.previousLimit !== this.limit;
|
|
397
|
+
if (reposChanged || typeChanged || limitChanged) {
|
|
398
|
+
// Reset pagination when filters change
|
|
399
|
+
this.cursor = null;
|
|
400
|
+
this.hasMore = false;
|
|
401
|
+
this.issues = [];
|
|
402
|
+
this.fetchIssues();
|
|
403
|
+
this.previousRepos = this.repos;
|
|
404
|
+
this.previousType = this.type;
|
|
405
|
+
this.previousLimit = this.limit;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
initializeSDK() {
|
|
409
|
+
try {
|
|
410
|
+
this.sdk = new FeedlogSDK(Object.assign({}, (this.endpoint && { endpoint: this.endpoint })));
|
|
411
|
+
this.error = null;
|
|
412
|
+
}
|
|
413
|
+
catch (err) {
|
|
414
|
+
const errorMsg = err instanceof Error ? err.message : 'Failed to initialize SDK';
|
|
415
|
+
this.error = errorMsg;
|
|
416
|
+
this.feedlogError.emit({ error: errorMsg });
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
parseRepos() {
|
|
420
|
+
if (!this.repos) {
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
423
|
+
if (typeof this.repos === 'string') {
|
|
424
|
+
try {
|
|
425
|
+
const parsed = JSON.parse(this.repos);
|
|
426
|
+
return Array.isArray(parsed) ? parsed : [this.repos];
|
|
427
|
+
}
|
|
428
|
+
catch (_a) {
|
|
429
|
+
// If not valid JSON, treat as single repo ID
|
|
430
|
+
return [this.repos];
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return Array.isArray(this.repos) ? this.repos : [];
|
|
434
|
+
}
|
|
435
|
+
async fetchIssues() {
|
|
436
|
+
if (!this.sdk) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const repos = this.parseRepos();
|
|
440
|
+
if (repos.length === 0) {
|
|
441
|
+
this.error = 'At least one repository is required';
|
|
442
|
+
this.loading = false;
|
|
443
|
+
this.feedlogError.emit({ error: 'At least one repository is required' });
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
try {
|
|
447
|
+
this.loading = true;
|
|
448
|
+
this.error = null;
|
|
449
|
+
const params = {
|
|
450
|
+
repositoryIds: repos,
|
|
451
|
+
};
|
|
452
|
+
if (this.type) {
|
|
453
|
+
params.type = this.type;
|
|
454
|
+
}
|
|
455
|
+
if (this.limit) {
|
|
456
|
+
params.limit = this.limit;
|
|
457
|
+
}
|
|
458
|
+
if (this.cursor) {
|
|
459
|
+
params.cursor = this.cursor;
|
|
460
|
+
}
|
|
461
|
+
const response = await this.sdk.fetchIssues(params);
|
|
462
|
+
this.issues = response.issues;
|
|
463
|
+
this.cursor = response.pagination.cursor;
|
|
464
|
+
this.hasMore = response.pagination.hasMore;
|
|
465
|
+
}
|
|
466
|
+
catch (err) {
|
|
467
|
+
const errorMsg = err instanceof Error ? err.message : 'Failed to fetch issues';
|
|
468
|
+
this.error = errorMsg;
|
|
469
|
+
this.issues = [];
|
|
470
|
+
this.feedlogError.emit({
|
|
471
|
+
error: errorMsg,
|
|
472
|
+
code: err === null || err === void 0 ? void 0 : err.statusCode,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
finally {
|
|
476
|
+
this.loading = false;
|
|
477
|
+
this.isLoadingMore = false;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async loadMore() {
|
|
481
|
+
if (!this.sdk || !this.hasMore || this.isLoadingMore || this.loading) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
this.isLoadingMore = true;
|
|
485
|
+
try {
|
|
486
|
+
const repos = this.parseRepos();
|
|
487
|
+
const params = {
|
|
488
|
+
repositoryIds: repos,
|
|
489
|
+
};
|
|
490
|
+
if (this.type) {
|
|
491
|
+
params.type = this.type;
|
|
492
|
+
}
|
|
493
|
+
if (this.limit) {
|
|
494
|
+
params.limit = this.limit;
|
|
495
|
+
}
|
|
496
|
+
if (this.cursor) {
|
|
497
|
+
params.cursor = this.cursor;
|
|
498
|
+
}
|
|
499
|
+
const response = await this.sdk.fetchIssues(params);
|
|
500
|
+
this.issues = [...this.issues, ...response.issues];
|
|
501
|
+
this.cursor = response.pagination.cursor;
|
|
502
|
+
this.hasMore = response.pagination.hasMore;
|
|
503
|
+
}
|
|
504
|
+
catch (err) {
|
|
505
|
+
const errorMsg = err instanceof Error ? err.message : 'Failed to load more issues';
|
|
506
|
+
this.feedlogError.emit({
|
|
507
|
+
error: errorMsg,
|
|
508
|
+
code: err === null || err === void 0 ? void 0 : err.statusCode,
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
finally {
|
|
512
|
+
this.isLoadingMore = false;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
render() {
|
|
516
|
+
return (index.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() }));
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
exports.feedlog_github_issues_client = FeedlogGithubIssuesClient;
|