@feedlog-ai/webcomponents 0.0.10 → 0.0.12
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.cjs.entry.js +21 -0
- package/dist/cjs/{feedlog-badge_3.cjs.entry.js → feedlog-button_2.cjs.entry.js} +2 -19
- package/dist/cjs/feedlog-card.cjs.entry.js +1 -1
- package/dist/cjs/feedlog-github-issues-client.cjs.entry.js +56 -6
- package/dist/cjs/feedlog-github-issues.cjs.entry.js +1 -1
- package/dist/cjs/feedlog-issues-list.cjs.entry.js +66 -0
- package/dist/cjs/feedlog-toolkit.cjs.js +2 -2
- package/dist/cjs/{index-5lluu_3h.js → index-DnsqTPII.js} +0 -37
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +2 -1
- package/dist/collection/components/feedlog-github-issues-client/feedlog-github-issues-client.js +55 -5
- package/dist/collection/components/feedlog-issue/feedlog-issue.js +1 -1
- package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.css +227 -0
- package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.js +139 -0
- package/dist/collection/components/index.js +1 -0
- package/dist/components/feedlog-github-issues-client.js +1 -1
- package/dist/components/feedlog-github-issues.js +1 -1
- package/dist/components/feedlog-issue.js +1 -1
- package/dist/components/feedlog-issues-list.d.ts +11 -0
- package/dist/components/feedlog-issues-list.js +1 -0
- package/dist/components/index.js +1 -1
- package/dist/components/p-BLmN8b4F.js +1 -0
- package/dist/components/{p-5qPAHrMz.js → p-BxyIMDYk.js} +1 -1
- package/dist/esm/feedlog-badge.entry.js +19 -0
- package/dist/esm/{feedlog-badge_3.entry.js → feedlog-button_2.entry.js} +3 -19
- package/dist/esm/feedlog-card.entry.js +1 -1
- package/dist/esm/feedlog-github-issues-client.entry.js +56 -6
- package/dist/esm/feedlog-github-issues.entry.js +1 -1
- package/dist/esm/feedlog-issues-list.entry.js +64 -0
- package/dist/esm/feedlog-toolkit.js +3 -3
- package/dist/esm/{index-CkB6Yzeb.js → index-rs_66Oq4.js} +0 -37
- package/dist/esm/loader.js +3 -3
- package/dist/feedlog-toolkit/feedlog-toolkit.esm.js +1 -1
- package/dist/feedlog-toolkit/p-1ff506c3.entry.js +1 -0
- package/dist/feedlog-toolkit/p-40ff5447.entry.js +1 -0
- package/dist/feedlog-toolkit/{p-cdb2b098.entry.js → p-4e90285c.entry.js} +1 -1
- package/dist/feedlog-toolkit/p-50a467a3.entry.js +1 -0
- package/dist/feedlog-toolkit/{p-95fea2f4.entry.js → p-774e08fd.entry.js} +1 -1
- package/dist/feedlog-toolkit/{p-8c5e3a0b.entry.js → p-f5626239.entry.js} +1 -1
- package/dist/feedlog-toolkit/p-rs_66Oq4.js +2 -0
- package/dist/types/components/feedlog-github-issues-client/feedlog-github-issues-client.d.ts +7 -0
- package/dist/types/components/feedlog-issues-list/feedlog-issues-list.d.ts +31 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/components.d.ts +76 -0
- package/package.json +2 -2
- package/dist/components/p-DaNa3wCt.js +0 -1
- package/dist/feedlog-toolkit/p-CkB6Yzeb.js +0 -2
- package/dist/feedlog-toolkit/p-bbb8c3b6.entry.js +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-DnsqTPII.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
|
+
exports.feedlog_badge = FeedlogBadge;
|
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
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();
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
20
4
|
|
|
21
5
|
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
6
|
|
|
@@ -108,11 +92,10 @@ const FeedlogIssueComponent = class {
|
|
|
108
92
|
const { issue } = this;
|
|
109
93
|
if (!issue)
|
|
110
94
|
return null;
|
|
111
|
-
return (index.h(index.Host, { class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { 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))), issue.type !== 'bug' && (index.h("button", { class: `upvote-button ${issue.hasUpvoted ? 'upvoted' : ''}`, onClick: (e) => this.handleUpvote(e), title: issue.hasUpvoted ? 'Remove upvote' : 'Upvote this issue' }, issue.hasUpvoted ?
|
|
95
|
+
return (index.h(index.Host, { class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { 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))), issue.type !== 'bug' && (index.h("button", { class: `upvote-button ${issue.hasUpvoted ? 'upvoted' : ''}`, onClick: (e) => this.handleUpvote(e), title: issue.hasUpvoted ? 'Remove upvote' : 'Upvote this issue' }, issue.hasUpvoted ? HeartFilledIcon() : HeartOutlineIcon(), 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)))))));
|
|
112
96
|
}
|
|
113
97
|
};
|
|
114
98
|
FeedlogIssueComponent.style = feedlogIssueCss();
|
|
115
99
|
|
|
116
|
-
exports.feedlog_badge = FeedlogBadge;
|
|
117
100
|
exports.feedlog_button = FeedlogButton;
|
|
118
101
|
exports.feedlog_issue = FeedlogIssueComponent;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
4
|
|
|
5
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
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* HTML and XSS sanitization utilities
|
|
@@ -354,16 +354,29 @@ const FeedlogGithubIssuesClient = class {
|
|
|
354
354
|
this.hasMore = false;
|
|
355
355
|
this.isLoadingMore = false;
|
|
356
356
|
this.sdk = null;
|
|
357
|
+
/** Counter to track fetch operations and prevent stale updates */
|
|
358
|
+
this.fetchRequestId = 0;
|
|
359
|
+
/** Flag to prevent state updates after component disconnect */
|
|
360
|
+
this.isDisconnected = false;
|
|
361
|
+
/** Map to track the latest upvote request ID for each issue to handle race conditions */
|
|
362
|
+
this.upvoteRequestIds = new Map();
|
|
357
363
|
this.handleUpvote = async (event) => {
|
|
358
|
-
if (!this.sdk) {
|
|
364
|
+
if (!this.sdk || this.isDisconnected) {
|
|
359
365
|
return;
|
|
360
366
|
}
|
|
361
367
|
const { issueId, currentUpvoted, currentCount } = event.detail;
|
|
368
|
+
// Track request to handle race conditions
|
|
369
|
+
const requestId = (this.upvoteRequestIds.get(issueId) || 0) + 1;
|
|
370
|
+
this.upvoteRequestIds.set(issueId, requestId);
|
|
362
371
|
// Optimistic update
|
|
363
372
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
364
373
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
|
|
365
374
|
try {
|
|
366
375
|
const result = await this.sdk.toggleUpvote(issueId);
|
|
376
|
+
// Ignore if component disconnected or request is stale
|
|
377
|
+
if (this.isDisconnected || this.upvoteRequestIds.get(issueId) !== requestId) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
367
380
|
// Update with server response
|
|
368
381
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
369
382
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: result.upvoted, upvoteCount: result.upvoteCount }) : issue);
|
|
@@ -374,6 +387,10 @@ const FeedlogGithubIssuesClient = class {
|
|
|
374
387
|
});
|
|
375
388
|
}
|
|
376
389
|
catch (err) {
|
|
390
|
+
// Ignore if component disconnected or request is stale
|
|
391
|
+
if (this.isDisconnected || this.upvoteRequestIds.get(issueId) !== requestId) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
377
394
|
// Revert optimistic update on error
|
|
378
395
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
379
396
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
|
|
@@ -388,11 +405,18 @@ const FeedlogGithubIssuesClient = class {
|
|
|
388
405
|
this.initializeSDK();
|
|
389
406
|
this.fetchIssues();
|
|
390
407
|
}
|
|
408
|
+
disconnectedCallback() {
|
|
409
|
+
// Prevent any pending async operations from updating state
|
|
410
|
+
this.isDisconnected = true;
|
|
411
|
+
this.fetchRequestId++;
|
|
412
|
+
}
|
|
391
413
|
componentDidUpdate() {
|
|
392
414
|
// Re-fetch if any props changed
|
|
393
415
|
const typeChanged = this.previousType !== this.type;
|
|
394
416
|
const limitChanged = this.previousLimit !== this.limit;
|
|
395
417
|
if (typeChanged || limitChanged) {
|
|
418
|
+
// Invalidate any in-flight requests
|
|
419
|
+
this.fetchRequestId++;
|
|
396
420
|
// Reset pagination when filters change
|
|
397
421
|
this.cursor = null;
|
|
398
422
|
this.hasMore = false;
|
|
@@ -420,6 +444,8 @@ const FeedlogGithubIssuesClient = class {
|
|
|
420
444
|
if (!this.sdk) {
|
|
421
445
|
return;
|
|
422
446
|
}
|
|
447
|
+
// Capture current request ID to detect stale responses
|
|
448
|
+
const currentRequestId = this.fetchRequestId;
|
|
423
449
|
try {
|
|
424
450
|
this.loading = true;
|
|
425
451
|
this.error = null;
|
|
@@ -434,11 +460,19 @@ const FeedlogGithubIssuesClient = class {
|
|
|
434
460
|
params.cursor = this.cursor;
|
|
435
461
|
}
|
|
436
462
|
const response = await this.sdk.fetchIssues(params);
|
|
463
|
+
// Ignore response if component disconnected or a newer request was made
|
|
464
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
437
467
|
this.issues = response.issues;
|
|
438
468
|
this.cursor = response.pagination.cursor;
|
|
439
469
|
this.hasMore = response.pagination.hasMore;
|
|
440
470
|
}
|
|
441
471
|
catch (err) {
|
|
472
|
+
// Ignore errors from stale requests
|
|
473
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
442
476
|
const errorMsg = err instanceof Error ? err.message : 'Failed to fetch issues';
|
|
443
477
|
this.error = errorMsg;
|
|
444
478
|
this.issues = [];
|
|
@@ -448,14 +482,19 @@ const FeedlogGithubIssuesClient = class {
|
|
|
448
482
|
});
|
|
449
483
|
}
|
|
450
484
|
finally {
|
|
451
|
-
|
|
452
|
-
this.
|
|
485
|
+
// Only update loading state if this is still the current request
|
|
486
|
+
if (!this.isDisconnected && currentRequestId === this.fetchRequestId) {
|
|
487
|
+
this.loading = false;
|
|
488
|
+
this.isLoadingMore = false;
|
|
489
|
+
}
|
|
453
490
|
}
|
|
454
491
|
}
|
|
455
492
|
async loadMore() {
|
|
456
493
|
if (!this.sdk || !this.hasMore || this.isLoadingMore || this.loading) {
|
|
457
494
|
return;
|
|
458
495
|
}
|
|
496
|
+
// Capture current request ID to detect stale responses
|
|
497
|
+
const currentRequestId = this.fetchRequestId;
|
|
459
498
|
this.isLoadingMore = true;
|
|
460
499
|
try {
|
|
461
500
|
const params = {};
|
|
@@ -469,11 +508,19 @@ const FeedlogGithubIssuesClient = class {
|
|
|
469
508
|
params.cursor = this.cursor;
|
|
470
509
|
}
|
|
471
510
|
const response = await this.sdk.fetchIssues(params);
|
|
511
|
+
// Ignore response if component disconnected or a newer request was made
|
|
512
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
472
515
|
this.issues = [...this.issues, ...response.issues];
|
|
473
516
|
this.cursor = response.pagination.cursor;
|
|
474
517
|
this.hasMore = response.pagination.hasMore;
|
|
475
518
|
}
|
|
476
519
|
catch (err) {
|
|
520
|
+
// Ignore errors from stale requests
|
|
521
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
477
524
|
const errorMsg = err instanceof Error ? err.message : 'Failed to load more issues';
|
|
478
525
|
this.feedlogError.emit({
|
|
479
526
|
error: errorMsg,
|
|
@@ -481,11 +528,14 @@ const FeedlogGithubIssuesClient = class {
|
|
|
481
528
|
});
|
|
482
529
|
}
|
|
483
530
|
finally {
|
|
484
|
-
this
|
|
531
|
+
// Only update loading state if this is still the current request
|
|
532
|
+
if (!this.isDisconnected && currentRequestId === this.fetchRequestId) {
|
|
533
|
+
this.isLoadingMore = false;
|
|
534
|
+
}
|
|
485
535
|
}
|
|
486
536
|
}
|
|
487
537
|
render() {
|
|
488
|
-
return (index.h("feedlog-github-issues", { key: '
|
|
538
|
+
return (index.h("feedlog-github-issues", { key: 'bb63dd29e99dfd9418b6cb12a1f45dff086378ab', issues: this.issues, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
489
539
|
}
|
|
490
540
|
};
|
|
491
541
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
4
|
|
|
5
5
|
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-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;--feedlog-padding:2rem}: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)}.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)}.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}.load-more-container{display:flex;justify-content:center;padding:2rem 0;gap:1rem}`;
|
|
6
6
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
|
+
|
|
5
|
+
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{margin:0 0 0.5rem 0;font-size:1rem;font-weight:600;color:var(--feedlog-card-foreground);line-height:1.5;word-wrap:break-word}.issue-body{margin:0 0 0.75rem 0;font-size:0.875rem;color:var(--feedlog-muted-foreground);line-height:1.5;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-wrap:break-word}.issue-repository{display:flex;align-items:center;gap:0.5rem;font-size:0.75rem;color:var(--feedlog-muted-foreground)}.repo-name{font-weight:500}.github-number{background-color:var(--feedlog-muted);padding:0.125rem 0.375rem;border-radius:0.25rem;font-family:ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace}.upvote-button{display:flex;align-items:center;gap:0.375rem;padding:0.5rem 0.75rem;background-color:var(--feedlog-muted);border:1px solid var(--feedlog-border);border-radius:var(--feedlog-radius);color:var(--feedlog-muted-foreground);font-size:0.875rem;font-weight:500;cursor:pointer;transition:all 0.15s ease;white-space:nowrap}.upvote-button:hover{background-color:var(--feedlog-accent-color);color:white}.upvote-button.upvoted{background-color:var(--feedlog-destructive);color:white;border-color:var(--feedlog-destructive)}.upvote-button.upvoted:hover{background-color:var(--feedlog-red-600);border-color:var(--feedlog-red-600)}.upvote-icon{width:1rem;height:1rem;flex-shrink:0}.upvote-icon.filled{color:currentColor}.upvote-icon.outline{stroke:currentColor}.upvote-count{font-variant-numeric:tabular-nums}.issue-footer{display:flex;align-items:center;gap:1rem;font-size:0.75rem;color:var(--feedlog-muted-foreground)}.issue-date{white-space:nowrap}@media (max-width: 640px){.issue-content{padding:1rem;gap:0.75rem}.issue-main{flex-direction:column;align-items:stretch;gap:0.75rem}.upvote-button{align-self:flex-start}.issue-footer{flex-direction:column;align-items:flex-start;gap:0.25rem}}`;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Heart icon SVG component (filled)
|
|
9
|
+
*/
|
|
10
|
+
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" })));
|
|
11
|
+
/**
|
|
12
|
+
* Heart icon SVG component (outline)
|
|
13
|
+
*/
|
|
14
|
+
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" })));
|
|
15
|
+
const FeedlogIssuesList = class {
|
|
16
|
+
constructor(hostRef) {
|
|
17
|
+
index.registerInstance(this, hostRef);
|
|
18
|
+
this.feedlogUpvote = index.createEvent(this, "feedlogUpvote");
|
|
19
|
+
/**
|
|
20
|
+
* Array of issues to display
|
|
21
|
+
*/
|
|
22
|
+
this.issues = [];
|
|
23
|
+
/**
|
|
24
|
+
* Theme variant: 'light' or 'dark'
|
|
25
|
+
*/
|
|
26
|
+
this.theme = 'light';
|
|
27
|
+
this.handleUpvote = (event, issue) => {
|
|
28
|
+
event.stopPropagation();
|
|
29
|
+
this.feedlogUpvote.emit({
|
|
30
|
+
issueId: issue.id,
|
|
31
|
+
currentUpvoted: issue.hasUpvoted,
|
|
32
|
+
currentCount: issue.upvoteCount,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Format an ISO date string to a relative time string
|
|
38
|
+
*/
|
|
39
|
+
formatDate(dateString) {
|
|
40
|
+
try {
|
|
41
|
+
const date = new Date(dateString);
|
|
42
|
+
const now = new Date();
|
|
43
|
+
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
|
44
|
+
if (seconds < 60)
|
|
45
|
+
return 'just now';
|
|
46
|
+
if (seconds < 3600)
|
|
47
|
+
return `${Math.floor(seconds / 60)}m ago`;
|
|
48
|
+
if (seconds < 86400)
|
|
49
|
+
return `${Math.floor(seconds / 3600)}h ago`;
|
|
50
|
+
if (seconds < 604800)
|
|
51
|
+
return `${Math.floor(seconds / 86400)}d ago`;
|
|
52
|
+
if (seconds < 2592000)
|
|
53
|
+
return `${Math.floor(seconds / 604800)}w ago`;
|
|
54
|
+
return date.toLocaleDateString();
|
|
55
|
+
}
|
|
56
|
+
catch (_a) {
|
|
57
|
+
return 'unknown date';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
render() {
|
|
61
|
+
return (index.h(index.Host, { key: 'eece99cd1096c6f0407e196b34e30b4d249bc3fa', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: 'e42daf5d526276290687125b47fb1fc9e11af518', 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 ? HeartFilledIcon() : HeartOutlineIcon(), 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)))))))))));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
FeedlogIssuesList.style = feedlogIssuesListCss();
|
|
65
|
+
|
|
66
|
+
exports.feedlog_issues_list = FeedlogIssuesList;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
4
|
|
|
5
5
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
6
6
|
/*
|
|
@@ -18,7 +18,7 @@ var patchBrowser = () => {
|
|
|
18
18
|
|
|
19
19
|
patchBrowser().then(async (options) => {
|
|
20
20
|
await index.globalScripts();
|
|
21
|
-
return index.bootstrapLazy([["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-
|
|
21
|
+
return index.bootstrapLazy([["feedlog-issues-list.cjs",[[1,"feedlog-issues-list",{"issues":[16],"theme":[1]}]]],["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_2.cjs",[[1,"feedlog-issue",{"issue":[16],"theme":[1]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}]]],["feedlog-github-issues.cjs",[[1,"feedlog-github-issues",{"issues":[16],"maxWidth":[1,"max-width"],"theme":[1025],"heading":[1],"subtitle":[1],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"currentTheme":[32]}]]],["feedlog-github-issues-client.cjs",[[1,"feedlog-github-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]}]]]], options);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
exports.setNonce = index.setNonce;
|
|
@@ -2042,13 +2042,6 @@ var h = (nodeName, vnodeData, ...children) => {
|
|
|
2042
2042
|
}
|
|
2043
2043
|
}
|
|
2044
2044
|
}
|
|
2045
|
-
if (typeof nodeName === "function") {
|
|
2046
|
-
return nodeName(
|
|
2047
|
-
vnodeData === null ? {} : vnodeData,
|
|
2048
|
-
vNodeChildren,
|
|
2049
|
-
vdomFnUtils
|
|
2050
|
-
);
|
|
2051
|
-
}
|
|
2052
2045
|
const vnode = newVNode(nodeName, null);
|
|
2053
2046
|
vnode.$attrs$ = vnodeData;
|
|
2054
2047
|
if (vNodeChildren.length > 0) {
|
|
@@ -2077,36 +2070,6 @@ var newVNode = (tag, text) => {
|
|
|
2077
2070
|
};
|
|
2078
2071
|
var Host = {};
|
|
2079
2072
|
var isHost = (node) => node && node.$tag$ === Host;
|
|
2080
|
-
var vdomFnUtils = {
|
|
2081
|
-
forEach: (children, cb) => children.map(convertToPublic).forEach(cb),
|
|
2082
|
-
map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate)
|
|
2083
|
-
};
|
|
2084
|
-
var convertToPublic = (node) => ({
|
|
2085
|
-
vattrs: node.$attrs$,
|
|
2086
|
-
vchildren: node.$children$,
|
|
2087
|
-
vkey: node.$key$,
|
|
2088
|
-
vname: node.$name$,
|
|
2089
|
-
vtag: node.$tag$,
|
|
2090
|
-
vtext: node.$text$
|
|
2091
|
-
});
|
|
2092
|
-
var convertToPrivate = (node) => {
|
|
2093
|
-
if (typeof node.vtag === "function") {
|
|
2094
|
-
const vnodeData = { ...node.vattrs };
|
|
2095
|
-
if (node.vkey) {
|
|
2096
|
-
vnodeData.key = node.vkey;
|
|
2097
|
-
}
|
|
2098
|
-
if (node.vname) {
|
|
2099
|
-
vnodeData.name = node.vname;
|
|
2100
|
-
}
|
|
2101
|
-
return h(node.vtag, vnodeData, ...node.vchildren || []);
|
|
2102
|
-
}
|
|
2103
|
-
const vnode = newVNode(node.vtag, node.vtext);
|
|
2104
|
-
vnode.$attrs$ = node.vattrs;
|
|
2105
|
-
vnode.$children$ = node.vchildren;
|
|
2106
|
-
vnode.$key$ = node.vkey;
|
|
2107
|
-
vnode.$name$ = node.vname;
|
|
2108
|
-
return vnode;
|
|
2109
|
-
};
|
|
2110
2073
|
var createSupportsRuleRe = (selector) => {
|
|
2111
2074
|
const safeSelector2 = escapeRegExpSpecialCharacters(selector);
|
|
2112
2075
|
return new RegExp(
|
package/dist/cjs/loader.cjs.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-DnsqTPII.js');
|
|
4
4
|
|
|
5
5
|
const defineCustomElements = async (win, options) => {
|
|
6
6
|
if (typeof window === 'undefined') return undefined;
|
|
7
7
|
await index.globalScripts();
|
|
8
|
-
return index.bootstrapLazy([["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-
|
|
8
|
+
return index.bootstrapLazy([["feedlog-issues-list.cjs",[[1,"feedlog-issues-list",{"issues":[16],"theme":[1]}]]],["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_2.cjs",[[1,"feedlog-issue",{"issue":[16],"theme":[1]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}]]],["feedlog-github-issues.cjs",[[1,"feedlog-github-issues",{"issues":[16],"maxWidth":[1,"max-width"],"theme":[1025],"heading":[1],"subtitle":[1],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"currentTheme":[32]}]]],["feedlog-github-issues-client.cjs",[[1,"feedlog-github-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]}]]]], options);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
exports.setNonce = index.setNonce;
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
"components/feedlog-button/feedlog-button.js",
|
|
6
6
|
"components/feedlog-github-issues/feedlog-github-issues.js",
|
|
7
7
|
"components/feedlog-github-issues-client/feedlog-github-issues-client.js",
|
|
8
|
-
"components/feedlog-issue/feedlog-issue.js"
|
|
8
|
+
"components/feedlog-issue/feedlog-issue.js",
|
|
9
|
+
"components/feedlog-issues-list/feedlog-issues-list.js"
|
|
9
10
|
],
|
|
10
11
|
"compiler": {
|
|
11
12
|
"name": "@stencil/core",
|
package/dist/collection/components/feedlog-github-issues-client/feedlog-github-issues-client.js
CHANGED
|
@@ -23,16 +23,29 @@ export class FeedlogGithubIssuesClient {
|
|
|
23
23
|
this.hasMore = false;
|
|
24
24
|
this.isLoadingMore = false;
|
|
25
25
|
this.sdk = null;
|
|
26
|
+
/** Counter to track fetch operations and prevent stale updates */
|
|
27
|
+
this.fetchRequestId = 0;
|
|
28
|
+
/** Flag to prevent state updates after component disconnect */
|
|
29
|
+
this.isDisconnected = false;
|
|
30
|
+
/** Map to track the latest upvote request ID for each issue to handle race conditions */
|
|
31
|
+
this.upvoteRequestIds = new Map();
|
|
26
32
|
this.handleUpvote = async (event) => {
|
|
27
|
-
if (!this.sdk) {
|
|
33
|
+
if (!this.sdk || this.isDisconnected) {
|
|
28
34
|
return;
|
|
29
35
|
}
|
|
30
36
|
const { issueId, currentUpvoted, currentCount } = event.detail;
|
|
37
|
+
// Track request to handle race conditions
|
|
38
|
+
const requestId = (this.upvoteRequestIds.get(issueId) || 0) + 1;
|
|
39
|
+
this.upvoteRequestIds.set(issueId, requestId);
|
|
31
40
|
// Optimistic update
|
|
32
41
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
33
42
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
|
|
34
43
|
try {
|
|
35
44
|
const result = await this.sdk.toggleUpvote(issueId);
|
|
45
|
+
// Ignore if component disconnected or request is stale
|
|
46
|
+
if (this.isDisconnected || this.upvoteRequestIds.get(issueId) !== requestId) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
36
49
|
// Update with server response
|
|
37
50
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
38
51
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: result.upvoted, upvoteCount: result.upvoteCount }) : issue);
|
|
@@ -43,6 +56,10 @@ export class FeedlogGithubIssuesClient {
|
|
|
43
56
|
});
|
|
44
57
|
}
|
|
45
58
|
catch (err) {
|
|
59
|
+
// Ignore if component disconnected or request is stale
|
|
60
|
+
if (this.isDisconnected || this.upvoteRequestIds.get(issueId) !== requestId) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
46
63
|
// Revert optimistic update on error
|
|
47
64
|
this.issues = this.issues.map(issue => issue.id === issueId
|
|
48
65
|
? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
|
|
@@ -57,11 +74,18 @@ export class FeedlogGithubIssuesClient {
|
|
|
57
74
|
this.initializeSDK();
|
|
58
75
|
this.fetchIssues();
|
|
59
76
|
}
|
|
77
|
+
disconnectedCallback() {
|
|
78
|
+
// Prevent any pending async operations from updating state
|
|
79
|
+
this.isDisconnected = true;
|
|
80
|
+
this.fetchRequestId++;
|
|
81
|
+
}
|
|
60
82
|
componentDidUpdate() {
|
|
61
83
|
// Re-fetch if any props changed
|
|
62
84
|
const typeChanged = this.previousType !== this.type;
|
|
63
85
|
const limitChanged = this.previousLimit !== this.limit;
|
|
64
86
|
if (typeChanged || limitChanged) {
|
|
87
|
+
// Invalidate any in-flight requests
|
|
88
|
+
this.fetchRequestId++;
|
|
65
89
|
// Reset pagination when filters change
|
|
66
90
|
this.cursor = null;
|
|
67
91
|
this.hasMore = false;
|
|
@@ -89,6 +113,8 @@ export class FeedlogGithubIssuesClient {
|
|
|
89
113
|
if (!this.sdk) {
|
|
90
114
|
return;
|
|
91
115
|
}
|
|
116
|
+
// Capture current request ID to detect stale responses
|
|
117
|
+
const currentRequestId = this.fetchRequestId;
|
|
92
118
|
try {
|
|
93
119
|
this.loading = true;
|
|
94
120
|
this.error = null;
|
|
@@ -103,11 +129,19 @@ export class FeedlogGithubIssuesClient {
|
|
|
103
129
|
params.cursor = this.cursor;
|
|
104
130
|
}
|
|
105
131
|
const response = await this.sdk.fetchIssues(params);
|
|
132
|
+
// Ignore response if component disconnected or a newer request was made
|
|
133
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
106
136
|
this.issues = response.issues;
|
|
107
137
|
this.cursor = response.pagination.cursor;
|
|
108
138
|
this.hasMore = response.pagination.hasMore;
|
|
109
139
|
}
|
|
110
140
|
catch (err) {
|
|
141
|
+
// Ignore errors from stale requests
|
|
142
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
111
145
|
const errorMsg = err instanceof Error ? err.message : 'Failed to fetch issues';
|
|
112
146
|
this.error = errorMsg;
|
|
113
147
|
this.issues = [];
|
|
@@ -117,14 +151,19 @@ export class FeedlogGithubIssuesClient {
|
|
|
117
151
|
});
|
|
118
152
|
}
|
|
119
153
|
finally {
|
|
120
|
-
|
|
121
|
-
this.
|
|
154
|
+
// Only update loading state if this is still the current request
|
|
155
|
+
if (!this.isDisconnected && currentRequestId === this.fetchRequestId) {
|
|
156
|
+
this.loading = false;
|
|
157
|
+
this.isLoadingMore = false;
|
|
158
|
+
}
|
|
122
159
|
}
|
|
123
160
|
}
|
|
124
161
|
async loadMore() {
|
|
125
162
|
if (!this.sdk || !this.hasMore || this.isLoadingMore || this.loading) {
|
|
126
163
|
return;
|
|
127
164
|
}
|
|
165
|
+
// Capture current request ID to detect stale responses
|
|
166
|
+
const currentRequestId = this.fetchRequestId;
|
|
128
167
|
this.isLoadingMore = true;
|
|
129
168
|
try {
|
|
130
169
|
const params = {};
|
|
@@ -138,11 +177,19 @@ export class FeedlogGithubIssuesClient {
|
|
|
138
177
|
params.cursor = this.cursor;
|
|
139
178
|
}
|
|
140
179
|
const response = await this.sdk.fetchIssues(params);
|
|
180
|
+
// Ignore response if component disconnected or a newer request was made
|
|
181
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
141
184
|
this.issues = [...this.issues, ...response.issues];
|
|
142
185
|
this.cursor = response.pagination.cursor;
|
|
143
186
|
this.hasMore = response.pagination.hasMore;
|
|
144
187
|
}
|
|
145
188
|
catch (err) {
|
|
189
|
+
// Ignore errors from stale requests
|
|
190
|
+
if (this.isDisconnected || currentRequestId !== this.fetchRequestId) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
146
193
|
const errorMsg = err instanceof Error ? err.message : 'Failed to load more issues';
|
|
147
194
|
this.feedlogError.emit({
|
|
148
195
|
error: errorMsg,
|
|
@@ -150,11 +197,14 @@ export class FeedlogGithubIssuesClient {
|
|
|
150
197
|
});
|
|
151
198
|
}
|
|
152
199
|
finally {
|
|
153
|
-
this
|
|
200
|
+
// Only update loading state if this is still the current request
|
|
201
|
+
if (!this.isDisconnected && currentRequestId === this.fetchRequestId) {
|
|
202
|
+
this.isLoadingMore = false;
|
|
203
|
+
}
|
|
154
204
|
}
|
|
155
205
|
}
|
|
156
206
|
render() {
|
|
157
|
-
return (h("feedlog-github-issues", { key: '
|
|
207
|
+
return (h("feedlog-github-issues", { key: 'bb63dd29e99dfd9418b6cb12a1f45dff086378ab', issues: this.issues, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
|
|
158
208
|
}
|
|
159
209
|
static get is() { return "feedlog-github-issues-client"; }
|
|
160
210
|
static get encapsulation() { return "shadow"; }
|
|
@@ -55,7 +55,7 @@ export class FeedlogIssueComponent {
|
|
|
55
55
|
const { issue } = this;
|
|
56
56
|
if (!issue)
|
|
57
57
|
return null;
|
|
58
|
-
return (h(Host, { class: this.theme === 'dark' ? 'dark' : '' }, h("div", { class: "issue-card" }, h("div", { class: "issue-content" }, h("div", { class: "issue-header" }, h("div", { class: "issue-type-badge" }, issue.type === 'bug' ? (h("feedlog-badge", { variant: "destructive" }, "Bug")) : (h("feedlog-badge", { variant: "enhancement" }, "Enhancement"))), issue.pinnedAt && (h("div", { class: "pinned-indicator", title: "Pinned issue" }, "\uD83D\uDCCC"))), h("div", { class: "issue-main" }, h("div", { class: "issue-details" }, h("h3", { class: "issue-title" }, issue.title), h("p", { class: "issue-body" }, issue.body), h("div", { class: "issue-repository" }, h("span", { class: "repo-name" }, issue.repository.owner, "/", issue.repository.name))), issue.type !== 'bug' && (h("button", { class: `upvote-button ${issue.hasUpvoted ? 'upvoted' : ''}`, onClick: (e) => this.handleUpvote(e), title: issue.hasUpvoted ? 'Remove upvote' : 'Upvote this issue' }, issue.hasUpvoted ?
|
|
58
|
+
return (h(Host, { class: this.theme === 'dark' ? 'dark' : '' }, h("div", { class: "issue-card" }, h("div", { class: "issue-content" }, h("div", { class: "issue-header" }, h("div", { class: "issue-type-badge" }, issue.type === 'bug' ? (h("feedlog-badge", { variant: "destructive" }, "Bug")) : (h("feedlog-badge", { variant: "enhancement" }, "Enhancement"))), issue.pinnedAt && (h("div", { class: "pinned-indicator", title: "Pinned issue" }, "\uD83D\uDCCC"))), h("div", { class: "issue-main" }, h("div", { class: "issue-details" }, h("h3", { class: "issue-title" }, issue.title), h("p", { class: "issue-body" }, issue.body), h("div", { class: "issue-repository" }, h("span", { class: "repo-name" }, issue.repository.owner, "/", issue.repository.name))), issue.type !== 'bug' && (h("button", { class: `upvote-button ${issue.hasUpvoted ? 'upvoted' : ''}`, onClick: (e) => this.handleUpvote(e), title: issue.hasUpvoted ? 'Remove upvote' : 'Upvote this issue' }, issue.hasUpvoted ? HeartFilledIcon() : HeartOutlineIcon(), h("span", { class: "upvote-count" }, issue.upvoteCount)))), h("div", { class: "issue-footer" }, h("span", { class: "issue-date", title: `Updated: ${issue.updatedAt}` }, "Updated ", this.formatDate(issue.updatedAt)), h("span", { class: "issue-date", title: `Created: ${issue.createdAt}` }, "Created ", this.formatDate(issue.createdAt)))))));
|
|
59
59
|
}
|
|
60
60
|
static get is() { return "feedlog-issue"; }
|
|
61
61
|
static get encapsulation() { return "shadow"; }
|