@feedlog-ai/webcomponents 0.0.42 → 0.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +6 -0
  2. package/dist/{esm/purify.es-B8AIqnOZ.js → cjs/browser-MBNPN4qV.js} +49 -3
  3. package/dist/cjs/feedlog-button_3.cjs.entry.js +6 -5
  4. package/dist/cjs/feedlog-issues-client.cjs.entry.js +48 -72
  5. package/dist/cjs/feedlog-issues.cjs.entry.js +1 -1
  6. package/dist/cjs/feedlog-toolkit.cjs.js +1 -1
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/collection/components/feedlog-issue/feedlog-issue.js +5 -4
  9. package/dist/collection/components/feedlog-issues/feedlog-issues.js +4 -4
  10. package/dist/collection/components/feedlog-issues-client/feedlog-issues-client.js +47 -26
  11. package/dist/collection/components/feedlog-issues-list/feedlog-issues-list.js +3 -3
  12. package/dist/collection/utils/markdown.js +2 -1
  13. package/dist/components/feedlog-badge.js +1 -1
  14. package/dist/components/feedlog-button.js +1 -1
  15. package/dist/components/feedlog-card.js +1 -1
  16. package/dist/components/feedlog-issue.js +1 -1
  17. package/dist/components/feedlog-issues-client.js +1 -1
  18. package/dist/components/feedlog-issues-list.js +1 -1
  19. package/dist/components/feedlog-issues.js +1 -1
  20. package/dist/components/{p-DLNSSGDc.js → p-B-jbJSEa.js} +1 -1
  21. package/dist/components/p-BWpmSn38.js +1 -0
  22. package/dist/components/{p-DzATWlAC.js → p-C-bUP9VO.js} +1 -1
  23. package/dist/components/{p-DMdb-G26.js → p-CIASvKvr.js} +1 -1
  24. package/dist/components/p-Du-VNLmx.js +2 -0
  25. package/dist/{cjs/purify.es-CfCgypMZ.js → esm/browser-BFRt9b48.js} +46 -5
  26. package/dist/esm/feedlog-button_3.entry.js +6 -5
  27. package/dist/esm/feedlog-issues-client.entry.js +47 -71
  28. package/dist/esm/feedlog-issues.entry.js +1 -1
  29. package/dist/esm/feedlog-toolkit.js +1 -1
  30. package/dist/esm/loader.js +1 -1
  31. package/dist/feedlog-toolkit/feedlog-toolkit.esm.js +1 -1
  32. package/dist/feedlog-toolkit/p-87583f75.entry.js +1 -0
  33. package/dist/feedlog-toolkit/{p-2901a753.entry.js → p-97d28b9d.entry.js} +1 -1
  34. package/dist/feedlog-toolkit/p-BFRt9b48.js +2 -0
  35. package/dist/feedlog-toolkit/{p-a7dcf9b6.entry.js → p-e8eb4cf5.entry.js} +1 -1
  36. package/dist/types/components/feedlog-issue/feedlog-issue.d.ts +2 -2
  37. package/dist/types/components/feedlog-issues/feedlog-issues.d.ts +2 -2
  38. package/dist/types/components/feedlog-issues-client/feedlog-issues-client.d.ts +4 -4
  39. package/dist/types/components/feedlog-issues-list/feedlog-issues-list.d.ts +2 -2
  40. package/dist/types/components.d.ts +14 -14
  41. package/dist/types/utils/markdown.d.ts +1 -0
  42. package/hydrate/index.js +97 -76
  43. package/hydrate/index.mjs +97 -76
  44. package/package.json +7 -4
  45. package/dist/components/p-RVHxnHRU.js +0 -1
  46. package/dist/components/p-TX_JzdfG.js +0 -3
  47. package/dist/feedlog-toolkit/p-0a9a5af2.entry.js +0 -1
  48. package/dist/feedlog-toolkit/p-B8AIqnOZ.js +0 -2
package/README.md CHANGED
@@ -19,6 +19,12 @@ Stencil-based web components for GitHub issue management. These are framework-ag
19
19
  npm install @feedlog-ai/webcomponents
20
20
  ```
21
21
 
22
+ ## Server-side rendering (SSR) and Node
23
+
24
+ Imports of these components are evaluated in Node for SSR (for example Vite dev, TanStack Start, or other frameworks that run the same ESM graph on the server). The package aligns with that environment: shared code from `@feedlog-ai/core` and markdown rendering ensure browser-only globals such as `self` are defined on `globalThis` before sanitization libraries load, so you should not need an app-level `self` polyfill for normal usage.
25
+
26
+ Custom elements still rely on a DOM in the browser for full behavior; use the [Stencil hydrate bundle](https://stenciljs.com/docs/hydrate-app) (`@feedlog-ai/webcomponents/hydrate`) or your framework’s integration (for example `@feedlog-ai/react` with `feedlogSSR()`) for SSR patterns that hydrate on the client.
27
+
22
28
  ## Components
23
29
 
24
30
  ### FeedlogIssuesClient
@@ -1,3 +1,34 @@
1
+ 'use strict';
2
+
3
+ function getDefaultExportFromCjs (x) {
4
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
5
+ }
6
+
7
+ function getAugmentedNamespace(n) {
8
+ if (n.__esModule) return n;
9
+ var f = n.default;
10
+ if (typeof f == "function") {
11
+ var a = function a () {
12
+ if (this instanceof a) {
13
+ return Reflect.construct(f, arguments, this.constructor);
14
+ }
15
+ return f.apply(this, arguments);
16
+ };
17
+ a.prototype = f.prototype;
18
+ } else a = {};
19
+ Object.defineProperty(a, '__esModule', {value: true});
20
+ Object.keys(n).forEach(function (k) {
21
+ var d = Object.getOwnPropertyDescriptor(n, k);
22
+ Object.defineProperty(a, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () {
25
+ return n[k];
26
+ }
27
+ });
28
+ });
29
+ return a;
30
+ }
31
+
1
32
  /*! @license DOMPurify 3.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.3/LICENSE */
2
33
 
3
34
  const {
@@ -1385,8 +1416,23 @@ function createDOMPurify() {
1385
1416
  var purify = createDOMPurify();
1386
1417
 
1387
1418
  var purify_es = /*#__PURE__*/Object.freeze({
1388
- __proto__: null,
1389
- default: purify
1419
+ __proto__: null,
1420
+ default: purify
1390
1421
  });
1391
1422
 
1392
- export { purify as a, purify_es as p };
1423
+ var require$$0 = /*@__PURE__*/getAugmentedNamespace(purify_es);
1424
+
1425
+ var browser;
1426
+ var hasRequiredBrowser;
1427
+
1428
+ function requireBrowser () {
1429
+ if (hasRequiredBrowser) return browser;
1430
+ hasRequiredBrowser = 1;
1431
+ browser = self.DOMPurify || (self.DOMPurify = require$$0.default || require$$0);
1432
+ return browser;
1433
+ }
1434
+
1435
+ var browserExports = requireBrowser();
1436
+ var DOMPurify = /*@__PURE__*/getDefaultExportFromCjs(browserExports);
1437
+
1438
+ exports.DOMPurify = DOMPurify;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-CXKBwRlh.js');
4
- var purify_es = require('./purify.es-CfCgypMZ.js');
4
+ var browser = require('./browser-MBNPN4qV.js');
5
5
 
6
6
  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}`;
7
7
 
@@ -127,7 +127,7 @@ function parseMarkdown(markdown) {
127
127
  throw new Error('marked.parse returned a Promise; async markdown is not supported');
128
128
  }
129
129
  const html = parsed;
130
- return purify_es.purify.sanitize(html, {
130
+ return browser.DOMPurify.sanitize(html, {
131
131
  ALLOWED_TAGS: [
132
132
  'p',
133
133
  'br',
@@ -177,10 +177,11 @@ const FeedlogIssueComponent = class {
177
177
  };
178
178
  this.handleUpvote = (event) => {
179
179
  event.stopPropagation();
180
+ const nextUpvoted = !this.issue.hasUpvoted;
180
181
  this.feedlogUpvote.emit({
181
182
  issueId: this.issue.id,
182
- currentUpvoted: this.issue.hasUpvoted,
183
- currentCount: this.issue.upvoteCount,
183
+ upvoted: nextUpvoted,
184
+ upvoteCount: Math.max(0, this.issue.upvoteCount + (nextUpvoted ? 1 : -1)),
184
185
  });
185
186
  };
186
187
  }
@@ -365,7 +366,7 @@ const FeedlogIssuesList = class {
365
366
  }
366
367
  render() {
367
368
  const visibleIssues = this.getVisibleIssues();
368
- return (index.h(index.Host, { key: '7721ed64730cd8e6b508fc829767ea79b2531628', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: '6a2d83f46ce2391294cef018ec243dd13d06a063', class: "issues-list" }, visibleIssues.length === 0 ? (index.h("div", { class: "empty-state" }, this.emptyStateTitle && this.emptyStateMessage ? (index.h("div", { class: "empty-state-content" }, this.renderEmptyStateIllustration(), index.h("h2", { class: "empty-state-title" }, this.emptyStateTitle), index.h("p", { class: "empty-state-message" }, this.emptyStateMessage))) : (index.h("p", null, "No issues found")))) : (visibleIssues.map(issue => {
369
+ return (index.h(index.Host, { key: 'b2b009625ec2cec47449afd7602202a9f95b8740', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: 'f108815569c064e45a78272a83f7048708470a3d', class: "issues-list" }, visibleIssues.length === 0 ? (index.h("div", { class: "empty-state" }, this.emptyStateTitle && this.emptyStateMessage ? (index.h("div", { class: "empty-state-content" }, this.renderEmptyStateIllustration(), index.h("h2", { class: "empty-state-title" }, this.emptyStateTitle), index.h("p", { class: "empty-state-message" }, this.emptyStateMessage))) : (index.h("p", null, "No issues found")))) : (visibleIssues.map(issue => {
369
370
  var _a, _b;
370
371
  return (index.h("feedlog-issue", { key: issue.id, issue: issue, issueUrl: (_b = (_a = this.getIssueUrl) === null || _a === void 0 ? void 0 : _a.call(this, issue)) !== null && _b !== void 0 ? _b : undefined, theme: this.theme, onFeedlogUpvote: (e) => this.handleUpvote(e) }));
371
372
  }))), this.renderPagination()));
@@ -1,51 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-CXKBwRlh.js');
4
- var purify_es = require('./purify.es-CfCgypMZ.js');
5
-
6
- function getDefaultExportFromCjs (x) {
7
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
8
- }
9
-
10
- function getAugmentedNamespace(n) {
11
- if (n.__esModule) return n;
12
- var f = n.default;
13
- if (typeof f == "function") {
14
- var a = function a () {
15
- if (this instanceof a) {
16
- return Reflect.construct(f, arguments, this.constructor);
17
- }
18
- return f.apply(this, arguments);
19
- };
20
- a.prototype = f.prototype;
21
- } else a = {};
22
- Object.defineProperty(a, '__esModule', {value: true});
23
- Object.keys(n).forEach(function (k) {
24
- var d = Object.getOwnPropertyDescriptor(n, k);
25
- Object.defineProperty(a, k, d.get ? d : {
26
- enumerable: true,
27
- get: function () {
28
- return n[k];
29
- }
30
- });
31
- });
32
- return a;
33
- }
34
-
35
- var require$$0 = /*@__PURE__*/getAugmentedNamespace(purify_es.purify_es);
36
-
37
- var browser;
38
- var hasRequiredBrowser;
39
-
40
- function requireBrowser () {
41
- if (hasRequiredBrowser) return browser;
42
- hasRequiredBrowser = 1;
43
- browser = self.DOMPurify || (self.DOMPurify = require$$0.default || require$$0);
44
- return browser;
45
- }
46
-
47
- var browserExports = requireBrowser();
48
- var DOMPurify = /*@__PURE__*/getDefaultExportFromCjs(browserExports);
4
+ var browser = require('./browser-MBNPN4qV.js');
49
5
 
50
6
  /**
51
7
  * HTML and XSS sanitization utilities
@@ -58,7 +14,7 @@ function sanitizeHtml(html) {
58
14
  if (typeof html !== 'string') {
59
15
  return '';
60
16
  }
61
- return DOMPurify.sanitize(html, {
17
+ return browser.DOMPurify.sanitize(html, {
62
18
  USE_PROFILES: { html: true },
63
19
  });
64
20
  }
@@ -110,7 +66,7 @@ class FeedlogTimeoutError extends FeedlogError {
110
66
  class FeedlogSDK {
111
67
  constructor(config) {
112
68
  this.config = {
113
- credentials: 'include',
69
+ credentials: 'same-origin',
114
70
  ...config,
115
71
  };
116
72
  this.apiKey = this.config.apiKey;
@@ -407,13 +363,17 @@ const FeedlogIssuesClient = class {
407
363
  if (!this.sdk || this.isDisconnected) {
408
364
  return;
409
365
  }
410
- const { issueId, currentUpvoted, currentCount } = event.detail;
366
+ const { issueId, upvoted, upvoteCount } = event.detail;
367
+ const currentIssue = this.issues.find(issue => issue.id === issueId);
368
+ if (!currentIssue) {
369
+ return;
370
+ }
411
371
  // Track request to handle race conditions
412
372
  const requestId = (this.upvoteRequestIds.get(issueId) || 0) + 1;
413
373
  this.upvoteRequestIds.set(issueId, requestId);
414
374
  // Optimistic update
415
375
  this.issues = this.issues.map(issue => issue.id === issueId
416
- ? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
376
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: upvoted, upvoteCount }) : issue);
417
377
  try {
418
378
  const result = await this.sdk.toggleUpvote(issueId);
419
379
  // Ignore if component disconnected or request is stale
@@ -436,16 +396,13 @@ const FeedlogIssuesClient = class {
436
396
  }
437
397
  // Revert optimistic update on error
438
398
  this.issues = this.issues.map(issue => issue.id === issueId
439
- ? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
399
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: currentIssue.hasUpvoted, upvoteCount: currentIssue.upvoteCount }) : issue);
440
400
  const errorMsg = err instanceof Error ? err.message : 'Failed to toggle upvote';
441
401
  this.feedlogError.emit({ error: errorMsg });
442
402
  }
443
403
  };
444
404
  }
445
405
  componentWillLoad() {
446
- this.previousType = this.type;
447
- this.previousLimit = this.limit;
448
- this.previousSortBy = this.sortBy;
449
406
  this.initializeSDK();
450
407
  // Return the promise so SSR waits for the fetch before serializing HTML.
451
408
  // During client hydration, skip fetch if we already have server-rendered data.
@@ -459,25 +416,27 @@ const FeedlogIssuesClient = class {
459
416
  this.isDisconnected = true;
460
417
  this.fetchRequestId++;
461
418
  }
462
- componentDidUpdate() {
463
- // Re-fetch if any props changed
464
- const typeChanged = this.previousType !== this.type;
465
- const limitChanged = this.previousLimit !== this.limit;
466
- const sortByChanged = this.previousSortBy !== this.sortBy;
467
- if (typeChanged || limitChanged || sortByChanged) {
468
- // Invalidate any in-flight requests
469
- this.fetchRequestId++;
470
- // Reset pagination when filters change
471
- this.cursor = null;
472
- this.hasMore = false;
473
- this.issues = [];
474
- void this.fetchIssues().catch(() => {
475
- /* errors handled inside fetchIssues */
476
- });
477
- this.previousType = this.type;
478
- this.previousLimit = this.limit;
479
- this.previousSortBy = this.sortBy;
419
+ handleQueryParamChange(newValue, oldValue) {
420
+ if (newValue === oldValue) {
421
+ return;
422
+ }
423
+ void this.resetAndRefetchIssues();
424
+ }
425
+ handleSdkConfigChange(newValue, oldValue) {
426
+ if (newValue === oldValue) {
427
+ return;
480
428
  }
429
+ this.initializeSDK();
430
+ void this.resetAndRefetchIssues();
431
+ }
432
+ async resetAndRefetchIssues() {
433
+ // Invalidate any in-flight requests and reset derived state before reloading.
434
+ this.fetchRequestId++;
435
+ this.cursor = null;
436
+ this.hasMore = false;
437
+ this.issues = [];
438
+ this.upvoteRequestIds.clear();
439
+ await this.fetchIssues();
481
440
  }
482
441
  initializeSDK() {
483
442
  try {
@@ -592,9 +551,26 @@ const FeedlogIssuesClient = class {
592
551
  const style = hostBg
593
552
  ? { '--feedlog-background': hostBg }
594
553
  : undefined;
595
- return (index.h("feedlog-issues", { key: '4467ffabd5f18f9af6c8407622fb2554981b54bd', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
554
+ return (index.h("feedlog-issues", { key: 'd98b8366830171a8a09d01cc9e2b19a19850a5fd', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
596
555
  }
597
556
  get el() { return index.getElement(this); }
557
+ static get watchers() { return {
558
+ "type": [{
559
+ "handleQueryParamChange": 0
560
+ }],
561
+ "limit": [{
562
+ "handleQueryParamChange": 0
563
+ }],
564
+ "sortBy": [{
565
+ "handleQueryParamChange": 0
566
+ }],
567
+ "apiKey": [{
568
+ "handleSdkConfigChange": 0
569
+ }],
570
+ "endpoint": [{
571
+ "handleSdkConfigChange": 0
572
+ }]
573
+ }; }
598
574
  };
599
575
 
600
576
  exports.feedlog_issues_client = FeedlogIssuesClient;
@@ -56,7 +56,7 @@ const FeedlogIssues = class {
56
56
  const containerStyle = {
57
57
  maxWidth: this.maxWidth,
58
58
  };
59
- return (index.h(index.Host, { key: '15ca787d3e5b45331a6582ea908b35b94b3a528c', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: '79d655ca18778660f0156fbdec54764491eaac49', class: "issues-container", style: containerStyle }, (this.heading || this.subtitle) && (index.h("header", { key: 'e9e1b05451f55db894a1b6248dde4d9d90a96068', class: "issues-header" }, index.h("div", { key: 'b2921e777986f9c6afc3ba1cbf8023311c868b34', class: "header-content" }, this.heading && index.h("h1", { key: 'e484da412ff1a92b876f3075489e60be273076b3', class: "issues-title" }, this.heading), this.subtitle && index.h("p", { key: '5030cbb2fdf2deab3681c1177a14e2b540d2ea33', class: "issues-subtitle" }, this.subtitle)))), this.loading && (index.h("div", { key: 'f3fb2c02af4637832c518714f670ca2ae2624d49', class: "loading-state", role: "status", "aria-label": "Loading issues" }, index.h("div", { key: '14e60e4174d22dd2474677a7ec6365d053fe40e7', class: "loading-skeletons" }, [1, 2, 3].map(i => (index.h("div", { key: i, class: "skeleton-card" }, index.h("div", { class: "skeleton-content" }, index.h("div", { class: "skeleton-header" }, index.h("div", { class: "skeleton-badge" }), index.h("div", { class: "skeleton-timestamp" })), index.h("div", { class: "skeleton-main" }, index.h("div", { class: "skeleton-title" }), index.h("div", { class: "skeleton-body" }, index.h("div", { class: "skeleton-line" }), index.h("div", { class: "skeleton-line short" })), index.h("div", { class: "skeleton-repo" })), index.h("div", { class: "skeleton-footer" }, index.h("div", { class: "skeleton-upvote" }))))))))), this.error && (index.h("div", { key: '0c301ece57faeee2c6bbf2a4e346a88b6bc535cc', class: "error-state", role: "alert" }, index.h("div", { key: 'bab84dcbca74730ba44162c57baf65454ffb78c0', class: "error-state-content" }, this.renderErrorIcon(), index.h("h2", { key: '247b25d17323d08ec9c527ebec1352600614f3be', class: "error-state-title" }, "Something went wrong"), index.h("p", { key: '45501981e34a2a163e20724881945a0b75ef57d1', class: "error-state-message" }, this.error)))), !this.loading && !this.error && (index.h("div", { key: 'ca5a2697c898b61121c16a9d1f4320ad35a0bf84' }, this.renderIssuesList(), this.hasMore && (index.h("div", { key: '1896d074714f083c3e171d0516d1d71155cbcd6a', class: "load-more-container" }, index.h("feedlog-button", { key: 'b34a2081a91b14e13aa4ace4d67b4d812f4a1d77', onFeedlogClick: this.handleLoadMore, disabled: this.isLoadingMore, variant: "outline" }, this.isLoadingMore ? 'Loading...' : 'Load More Issues'))))))));
59
+ return (index.h(index.Host, { key: 'efed57e0c474b689a24e202f0fb6b67afd310572', class: this.theme === 'dark' ? 'dark' : '' }, index.h("div", { key: 'ddb7185c3ace088f2883b2dcd193beb8af213cf3', class: "issues-container", style: containerStyle }, (this.heading || this.subtitle) && (index.h("header", { key: '59aeafb96ac34de3ed7d0ecbd20f958dbc4d9ce9', class: "issues-header" }, index.h("div", { key: 'cba96e346d2e09c28cf253bca55e5bc822f69762', class: "header-content" }, this.heading && index.h("h1", { key: '7ce0ea76eb114c453a46592f2e5b1ea81b406cc4', class: "issues-title" }, this.heading), this.subtitle && index.h("p", { key: 'a83fbcc2baab2aeb2b72ff3dbfc03cd3c77a0278', class: "issues-subtitle" }, this.subtitle)))), this.loading && (index.h("div", { key: 'cf24d3838ef214697abfc2d8a03182e08e0ed6e7', class: "loading-state", role: "status", "aria-label": "Loading issues" }, index.h("div", { key: 'd2a1547e4cbd7f41518153d7a8ea757beb384088', class: "loading-skeletons" }, [1, 2, 3].map(i => (index.h("div", { key: i, class: "skeleton-card" }, index.h("div", { class: "skeleton-content" }, index.h("div", { class: "skeleton-header" }, index.h("div", { class: "skeleton-badge" }), index.h("div", { class: "skeleton-timestamp" })), index.h("div", { class: "skeleton-main" }, index.h("div", { class: "skeleton-title" }), index.h("div", { class: "skeleton-body" }, index.h("div", { class: "skeleton-line" }), index.h("div", { class: "skeleton-line short" })), index.h("div", { class: "skeleton-repo" })), index.h("div", { class: "skeleton-footer" }, index.h("div", { class: "skeleton-upvote" }))))))))), this.error && (index.h("div", { key: '79c70736a6ba731432ef2ba84c5902e52a2ed864', class: "error-state", role: "alert" }, index.h("div", { key: '31e987295d26e65c09187ae45e7305a46db27b32', class: "error-state-content" }, this.renderErrorIcon(), index.h("h2", { key: 'c030fb77e635ee6e50b9bebe16d8a97f75e2921c', class: "error-state-title" }, "Something went wrong"), index.h("p", { key: '5c725c8d65d304e58c06ce574366f7ab6f18ea59', class: "error-state-message" }, this.error)))), !this.loading && !this.error && (index.h("div", { key: '4217556c83dbd193eeed23ec50c40ec5fedbf420' }, this.renderIssuesList(), this.hasMore && (index.h("div", { key: 'df669ef16de0c2316715b97edd9c9af935e96464', class: "load-more-container" }, index.h("feedlog-button", { key: 'ba1498e81606245a55d0f428e8b3b7b0bf609367', onFeedlogClick: this.handleLoadMore, disabled: this.isLoadingMore, variant: "outline" }, this.isLoadingMore ? 'Loading...' : 'Load More Issues'))))))));
60
60
  }
61
61
  };
62
62
  FeedlogIssues.style = feedlogIssuesCss();
@@ -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-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_3.cjs",[[1,"feedlog-issues-list",{"issues":[16],"limit":[2],"theme":[1],"getIssueUrl":[16],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"currentPage":[32]},null,{"issues":[{"resetPage":0}],"limit":[{"resetPage":0}]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}],[257,"feedlog-issue",{"issue":[16],"issueUrl":[1,"issue-url"],"theme":[1]}]]],["feedlog-issues.cjs",[[1,"feedlog-issues",{"issues":[16],"maxWidth":[1,"max-width"],"limit":[2],"theme":[1025],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"getIssueUrl":[16]}]]],["feedlog-issues-client.cjs",[[1,"feedlog-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"sortBy":[1,"sort-by"],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"getIssueUrl":[16],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]}]]]], options);
21
+ return index.bootstrapLazy([["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_3.cjs",[[1,"feedlog-issues-list",{"issues":[16],"limit":[2],"theme":[1],"getIssueUrl":[16],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"currentPage":[32]},null,{"issues":[{"resetPage":0}],"limit":[{"resetPage":0}]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}],[257,"feedlog-issue",{"issue":[16],"issueUrl":[1,"issue-url"],"theme":[1]}]]],["feedlog-issues.cjs",[[1,"feedlog-issues",{"issues":[16],"maxWidth":[1,"max-width"],"limit":[2],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"getIssueUrl":[16]}]]],["feedlog-issues-client.cjs",[[1,"feedlog-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"sortBy":[1,"sort-by"],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"getIssueUrl":[16],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]},null,{"type":[{"handleQueryParamChange":0}],"limit":[{"handleQueryParamChange":0}],"sortBy":[{"handleQueryParamChange":0}],"apiKey":[{"handleSdkConfigChange":0}],"endpoint":[{"handleSdkConfigChange":0}]}]]]], options);
22
22
  });
23
23
 
24
24
  exports.setNonce = index.setNonce;
@@ -5,7 +5,7 @@ var index = require('./index-CXKBwRlh.js');
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-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_3.cjs",[[1,"feedlog-issues-list",{"issues":[16],"limit":[2],"theme":[1],"getIssueUrl":[16],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"currentPage":[32]},null,{"issues":[{"resetPage":0}],"limit":[{"resetPage":0}]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}],[257,"feedlog-issue",{"issue":[16],"issueUrl":[1,"issue-url"],"theme":[1]}]]],["feedlog-issues.cjs",[[1,"feedlog-issues",{"issues":[16],"maxWidth":[1,"max-width"],"limit":[2],"theme":[1025],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"getIssueUrl":[16]}]]],["feedlog-issues-client.cjs",[[1,"feedlog-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"sortBy":[1,"sort-by"],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"getIssueUrl":[16],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]}]]]], options);
8
+ return index.bootstrapLazy([["feedlog-card.cjs",[[257,"feedlog-card"]]],["feedlog-badge.cjs",[[257,"feedlog-badge",{"variant":[1]}]]],["feedlog-button_3.cjs",[[1,"feedlog-issues-list",{"issues":[16],"limit":[2],"theme":[1],"getIssueUrl":[16],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"currentPage":[32]},null,{"issues":[{"resetPage":0}],"limit":[{"resetPage":0}]}],[257,"feedlog-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1]}],[257,"feedlog-issue",{"issue":[16],"issueUrl":[1,"issue-url"],"theme":[1]}]]],["feedlog-issues.cjs",[[1,"feedlog-issues",{"issues":[16],"maxWidth":[1,"max-width"],"limit":[2],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"loading":[4],"error":[1],"hasMore":[4,"has-more"],"isLoadingMore":[4,"is-loading-more"],"getIssueUrl":[16]}]]],["feedlog-issues-client.cjs",[[1,"feedlog-issues-client",{"apiKey":[1,"api-key"],"type":[1],"limit":[2],"sortBy":[1,"sort-by"],"endpoint":[1],"maxWidth":[1,"max-width"],"theme":[1],"heading":[1],"subtitle":[1],"emptyStateTitle":[1,"empty-state-title"],"emptyStateMessage":[1,"empty-state-message"],"getIssueUrl":[16],"issues":[32],"loading":[32],"error":[32],"cursor":[32],"hasMore":[32],"isLoadingMore":[32]},null,{"type":[{"handleQueryParamChange":0}],"limit":[{"handleQueryParamChange":0}],"sortBy":[{"handleQueryParamChange":0}],"apiKey":[{"handleSdkConfigChange":0}],"endpoint":[{"handleSdkConfigChange":0}]}]]]], options);
9
9
  };
10
10
 
11
11
  exports.setNonce = index.setNonce;
@@ -16,10 +16,11 @@ export class FeedlogIssueComponent {
16
16
  };
17
17
  this.handleUpvote = (event) => {
18
18
  event.stopPropagation();
19
+ const nextUpvoted = !this.issue.hasUpvoted;
19
20
  this.feedlogUpvote.emit({
20
21
  issueId: this.issue.id,
21
- currentUpvoted: this.issue.hasUpvoted,
22
- currentCount: this.issue.upvoteCount,
22
+ upvoted: nextUpvoted,
23
+ upvoteCount: Math.max(0, this.issue.upvoteCount + (nextUpvoted ? 1 : -1)),
23
24
  });
24
25
  };
25
26
  }
@@ -222,8 +223,8 @@ export class FeedlogIssueComponent {
222
223
  "text": "Event emitted when the issue is upvoted"
223
224
  },
224
225
  "complexType": {
225
- "original": "{\n issueId: string;\n currentUpvoted: boolean;\n currentCount: number;\n }",
226
- "resolved": "{ issueId: string; currentUpvoted: boolean; currentCount: number; }",
226
+ "original": "{\n issueId: string;\n upvoted: boolean;\n upvoteCount: number;\n }",
227
+ "resolved": "{ issueId: string; upvoted: boolean; upvoteCount: number; }",
227
228
  "references": {}
228
229
  }
229
230
  }];
@@ -54,7 +54,7 @@ export class FeedlogIssues {
54
54
  const containerStyle = {
55
55
  maxWidth: this.maxWidth,
56
56
  };
57
- return (h(Host, { key: '15ca787d3e5b45331a6582ea908b35b94b3a528c', class: this.theme === 'dark' ? 'dark' : '' }, h("div", { key: '79d655ca18778660f0156fbdec54764491eaac49', class: "issues-container", style: containerStyle }, (this.heading || this.subtitle) && (h("header", { key: 'e9e1b05451f55db894a1b6248dde4d9d90a96068', class: "issues-header" }, h("div", { key: 'b2921e777986f9c6afc3ba1cbf8023311c868b34', class: "header-content" }, this.heading && h("h1", { key: 'e484da412ff1a92b876f3075489e60be273076b3', class: "issues-title" }, this.heading), this.subtitle && h("p", { key: '5030cbb2fdf2deab3681c1177a14e2b540d2ea33', class: "issues-subtitle" }, this.subtitle)))), this.loading && (h("div", { key: 'f3fb2c02af4637832c518714f670ca2ae2624d49', class: "loading-state", role: "status", "aria-label": "Loading issues" }, h("div", { key: '14e60e4174d22dd2474677a7ec6365d053fe40e7', class: "loading-skeletons" }, [1, 2, 3].map(i => (h("div", { key: i, class: "skeleton-card" }, h("div", { class: "skeleton-content" }, h("div", { class: "skeleton-header" }, h("div", { class: "skeleton-badge" }), h("div", { class: "skeleton-timestamp" })), h("div", { class: "skeleton-main" }, h("div", { class: "skeleton-title" }), h("div", { class: "skeleton-body" }, h("div", { class: "skeleton-line" }), h("div", { class: "skeleton-line short" })), h("div", { class: "skeleton-repo" })), h("div", { class: "skeleton-footer" }, h("div", { class: "skeleton-upvote" }))))))))), this.error && (h("div", { key: '0c301ece57faeee2c6bbf2a4e346a88b6bc535cc', class: "error-state", role: "alert" }, h("div", { key: 'bab84dcbca74730ba44162c57baf65454ffb78c0', class: "error-state-content" }, this.renderErrorIcon(), h("h2", { key: '247b25d17323d08ec9c527ebec1352600614f3be', class: "error-state-title" }, "Something went wrong"), h("p", { key: '45501981e34a2a163e20724881945a0b75ef57d1', class: "error-state-message" }, this.error)))), !this.loading && !this.error && (h("div", { key: 'ca5a2697c898b61121c16a9d1f4320ad35a0bf84' }, this.renderIssuesList(), this.hasMore && (h("div", { key: '1896d074714f083c3e171d0516d1d71155cbcd6a', class: "load-more-container" }, h("feedlog-button", { key: 'b34a2081a91b14e13aa4ace4d67b4d812f4a1d77', onFeedlogClick: this.handleLoadMore, disabled: this.isLoadingMore, variant: "outline" }, this.isLoadingMore ? 'Loading...' : 'Load More Issues'))))))));
57
+ return (h(Host, { key: 'efed57e0c474b689a24e202f0fb6b67afd310572', class: this.theme === 'dark' ? 'dark' : '' }, h("div", { key: 'ddb7185c3ace088f2883b2dcd193beb8af213cf3', class: "issues-container", style: containerStyle }, (this.heading || this.subtitle) && (h("header", { key: '59aeafb96ac34de3ed7d0ecbd20f958dbc4d9ce9', class: "issues-header" }, h("div", { key: 'cba96e346d2e09c28cf253bca55e5bc822f69762', class: "header-content" }, this.heading && h("h1", { key: '7ce0ea76eb114c453a46592f2e5b1ea81b406cc4', class: "issues-title" }, this.heading), this.subtitle && h("p", { key: 'a83fbcc2baab2aeb2b72ff3dbfc03cd3c77a0278', class: "issues-subtitle" }, this.subtitle)))), this.loading && (h("div", { key: 'cf24d3838ef214697abfc2d8a03182e08e0ed6e7', class: "loading-state", role: "status", "aria-label": "Loading issues" }, h("div", { key: 'd2a1547e4cbd7f41518153d7a8ea757beb384088', class: "loading-skeletons" }, [1, 2, 3].map(i => (h("div", { key: i, class: "skeleton-card" }, h("div", { class: "skeleton-content" }, h("div", { class: "skeleton-header" }, h("div", { class: "skeleton-badge" }), h("div", { class: "skeleton-timestamp" })), h("div", { class: "skeleton-main" }, h("div", { class: "skeleton-title" }), h("div", { class: "skeleton-body" }, h("div", { class: "skeleton-line" }), h("div", { class: "skeleton-line short" })), h("div", { class: "skeleton-repo" })), h("div", { class: "skeleton-footer" }, h("div", { class: "skeleton-upvote" }))))))))), this.error && (h("div", { key: '79c70736a6ba731432ef2ba84c5902e52a2ed864', class: "error-state", role: "alert" }, h("div", { key: '31e987295d26e65c09187ae45e7305a46db27b32', class: "error-state-content" }, this.renderErrorIcon(), h("h2", { key: 'c030fb77e635ee6e50b9bebe16d8a97f75e2921c', class: "error-state-title" }, "Something went wrong"), h("p", { key: '5c725c8d65d304e58c06ce574366f7ab6f18ea59', class: "error-state-message" }, this.error)))), !this.loading && !this.error && (h("div", { key: '4217556c83dbd193eeed23ec50c40ec5fedbf420' }, this.renderIssuesList(), this.hasMore && (h("div", { key: 'df669ef16de0c2316715b97edd9c9af935e96464', class: "load-more-container" }, h("feedlog-button", { key: 'ba1498e81606245a55d0f428e8b3b7b0bf609367', onFeedlogClick: this.handleLoadMore, disabled: this.isLoadingMore, variant: "outline" }, this.isLoadingMore ? 'Loading...' : 'Load More Issues'))))))));
58
58
  }
59
59
  static get is() { return "feedlog-issues"; }
60
60
  static get encapsulation() { return "shadow"; }
@@ -135,7 +135,7 @@ export class FeedlogIssues {
135
135
  },
136
136
  "theme": {
137
137
  "type": "string",
138
- "mutable": true,
138
+ "mutable": false,
139
139
  "complexType": {
140
140
  "original": "'light' | 'dark'",
141
141
  "resolved": "\"dark\" | \"light\"",
@@ -346,8 +346,8 @@ export class FeedlogIssues {
346
346
  "text": "Event emitted when an issue is upvoted"
347
347
  },
348
348
  "complexType": {
349
- "original": "{\n issueId: string;\n currentUpvoted: boolean;\n currentCount: number;\n }",
350
- "resolved": "{ issueId: string; currentUpvoted: boolean; currentCount: number; }",
349
+ "original": "{\n issueId: string;\n upvoted: boolean;\n upvoteCount: number;\n }",
350
+ "resolved": "{ issueId: string; upvoted: boolean; upvoteCount: number; }",
351
351
  "references": {}
352
352
  }
353
353
  }, {
@@ -33,13 +33,17 @@ export class FeedlogIssuesClient {
33
33
  if (!this.sdk || this.isDisconnected) {
34
34
  return;
35
35
  }
36
- const { issueId, currentUpvoted, currentCount } = event.detail;
36
+ const { issueId, upvoted, upvoteCount } = event.detail;
37
+ const currentIssue = this.issues.find(issue => issue.id === issueId);
38
+ if (!currentIssue) {
39
+ return;
40
+ }
37
41
  // Track request to handle race conditions
38
42
  const requestId = (this.upvoteRequestIds.get(issueId) || 0) + 1;
39
43
  this.upvoteRequestIds.set(issueId, requestId);
40
44
  // Optimistic update
41
45
  this.issues = this.issues.map(issue => issue.id === issueId
42
- ? Object.assign(Object.assign({}, issue), { hasUpvoted: !currentUpvoted, upvoteCount: currentUpvoted ? currentCount - 1 : currentCount + 1 }) : issue);
46
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: upvoted, upvoteCount }) : issue);
43
47
  try {
44
48
  const result = await this.sdk.toggleUpvote(issueId);
45
49
  // Ignore if component disconnected or request is stale
@@ -62,16 +66,13 @@ export class FeedlogIssuesClient {
62
66
  }
63
67
  // Revert optimistic update on error
64
68
  this.issues = this.issues.map(issue => issue.id === issueId
65
- ? Object.assign(Object.assign({}, issue), { hasUpvoted: currentUpvoted, upvoteCount: currentCount }) : issue);
69
+ ? Object.assign(Object.assign({}, issue), { hasUpvoted: currentIssue.hasUpvoted, upvoteCount: currentIssue.upvoteCount }) : issue);
66
70
  const errorMsg = err instanceof Error ? err.message : 'Failed to toggle upvote';
67
71
  this.feedlogError.emit({ error: errorMsg });
68
72
  }
69
73
  };
70
74
  }
71
75
  componentWillLoad() {
72
- this.previousType = this.type;
73
- this.previousLimit = this.limit;
74
- this.previousSortBy = this.sortBy;
75
76
  this.initializeSDK();
76
77
  // Return the promise so SSR waits for the fetch before serializing HTML.
77
78
  // During client hydration, skip fetch if we already have server-rendered data.
@@ -85,25 +86,27 @@ export class FeedlogIssuesClient {
85
86
  this.isDisconnected = true;
86
87
  this.fetchRequestId++;
87
88
  }
88
- componentDidUpdate() {
89
- // Re-fetch if any props changed
90
- const typeChanged = this.previousType !== this.type;
91
- const limitChanged = this.previousLimit !== this.limit;
92
- const sortByChanged = this.previousSortBy !== this.sortBy;
93
- if (typeChanged || limitChanged || sortByChanged) {
94
- // Invalidate any in-flight requests
95
- this.fetchRequestId++;
96
- // Reset pagination when filters change
97
- this.cursor = null;
98
- this.hasMore = false;
99
- this.issues = [];
100
- void this.fetchIssues().catch(() => {
101
- /* errors handled inside fetchIssues */
102
- });
103
- this.previousType = this.type;
104
- this.previousLimit = this.limit;
105
- this.previousSortBy = this.sortBy;
89
+ handleQueryParamChange(newValue, oldValue) {
90
+ if (newValue === oldValue) {
91
+ return;
106
92
  }
93
+ void this.resetAndRefetchIssues();
94
+ }
95
+ handleSdkConfigChange(newValue, oldValue) {
96
+ if (newValue === oldValue) {
97
+ return;
98
+ }
99
+ this.initializeSDK();
100
+ void this.resetAndRefetchIssues();
101
+ }
102
+ async resetAndRefetchIssues() {
103
+ // Invalidate any in-flight requests and reset derived state before reloading.
104
+ this.fetchRequestId++;
105
+ this.cursor = null;
106
+ this.hasMore = false;
107
+ this.issues = [];
108
+ this.upvoteRequestIds.clear();
109
+ await this.fetchIssues();
107
110
  }
108
111
  initializeSDK() {
109
112
  try {
@@ -218,7 +221,7 @@ export class FeedlogIssuesClient {
218
221
  const style = hostBg
219
222
  ? { '--feedlog-background': hostBg }
220
223
  : undefined;
221
- return (h("feedlog-issues", { key: '4467ffabd5f18f9af6c8407622fb2554981b54bd', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
224
+ return (h("feedlog-issues", { key: 'd98b8366830171a8a09d01cc9e2b19a19850a5fd', style: style, issues: this.issues, limit: this.limit, maxWidth: this.maxWidth, theme: this.theme, heading: this.heading, subtitle: this.subtitle, emptyStateTitle: this.emptyStateTitle, emptyStateMessage: this.emptyStateMessage, getIssueUrl: this.getIssueUrl, loading: this.loading, error: this.error, hasMore: this.hasMore, isLoadingMore: this.isLoadingMore, onFeedlogUpvote: this.handleUpvote, onFeedlogLoadMore: async () => this.loadMore() }));
222
225
  }
223
226
  static get is() { return "feedlog-issues-client"; }
224
227
  static get encapsulation() { return "shadow"; }
@@ -236,7 +239,7 @@ export class FeedlogIssuesClient {
236
239
  "optional": false,
237
240
  "docs": {
238
241
  "tags": [],
239
- "text": "API key for Feedlog authentication (required)\nThe API key determines which repositories' issues are fetched"
242
+ "text": "Set via JS property only; not reflected to an HTML attribute (see Stencil `reflect`)."
240
243
  },
241
244
  "getter": false,
242
245
  "setter": false,
@@ -510,4 +513,22 @@ export class FeedlogIssuesClient {
510
513
  }];
511
514
  }
512
515
  static get elementRef() { return "el"; }
516
+ static get watchers() {
517
+ return [{
518
+ "propName": "type",
519
+ "methodName": "handleQueryParamChange"
520
+ }, {
521
+ "propName": "limit",
522
+ "methodName": "handleQueryParamChange"
523
+ }, {
524
+ "propName": "sortBy",
525
+ "methodName": "handleQueryParamChange"
526
+ }, {
527
+ "propName": "apiKey",
528
+ "methodName": "handleSdkConfigChange"
529
+ }, {
530
+ "propName": "endpoint",
531
+ "methodName": "handleSdkConfigChange"
532
+ }];
533
+ }
513
534
  }
@@ -68,7 +68,7 @@ export class FeedlogIssuesList {
68
68
  }
69
69
  render() {
70
70
  const visibleIssues = this.getVisibleIssues();
71
- return (h(Host, { key: '7721ed64730cd8e6b508fc829767ea79b2531628', class: this.theme === 'dark' ? 'dark' : '' }, h("div", { key: '6a2d83f46ce2391294cef018ec243dd13d06a063', class: "issues-list" }, visibleIssues.length === 0 ? (h("div", { class: "empty-state" }, this.emptyStateTitle && this.emptyStateMessage ? (h("div", { class: "empty-state-content" }, this.renderEmptyStateIllustration(), h("h2", { class: "empty-state-title" }, this.emptyStateTitle), h("p", { class: "empty-state-message" }, this.emptyStateMessage))) : (h("p", null, "No issues found")))) : (visibleIssues.map(issue => {
71
+ return (h(Host, { key: 'b2b009625ec2cec47449afd7602202a9f95b8740', class: this.theme === 'dark' ? 'dark' : '' }, h("div", { key: 'f108815569c064e45a78272a83f7048708470a3d', class: "issues-list" }, visibleIssues.length === 0 ? (h("div", { class: "empty-state" }, this.emptyStateTitle && this.emptyStateMessage ? (h("div", { class: "empty-state-content" }, this.renderEmptyStateIllustration(), h("h2", { class: "empty-state-title" }, this.emptyStateTitle), h("p", { class: "empty-state-message" }, this.emptyStateMessage))) : (h("p", null, "No issues found")))) : (visibleIssues.map(issue => {
72
72
  var _a, _b;
73
73
  return (h("feedlog-issue", { key: issue.id, issue: issue, issueUrl: (_b = (_a = this.getIssueUrl) === null || _a === void 0 ? void 0 : _a.call(this, issue)) !== null && _b !== void 0 ? _b : undefined, theme: this.theme, onFeedlogUpvote: (e) => this.handleUpvote(e) }));
74
74
  }))), this.renderPagination()));
@@ -230,8 +230,8 @@ export class FeedlogIssuesList {
230
230
  "text": "Emitted when an issue is upvoted"
231
231
  },
232
232
  "complexType": {
233
- "original": "{\n issueId: string;\n currentUpvoted: boolean;\n currentCount: number;\n }",
234
- "resolved": "{ issueId: string; currentUpvoted: boolean; currentCount: number; }",
233
+ "original": "{\n issueId: string;\n upvoted: boolean;\n upvoteCount: number;\n }",
234
+ "resolved": "{ issueId: string; upvoted: boolean; upvoteCount: number; }",
235
235
  "references": {}
236
236
  }
237
237
  }];
@@ -1,5 +1,6 @@
1
+ import "@feedlog-ai/core/ssr-globals";
1
2
  import { marked } from "marked";
2
- import DOMPurify from "dompurify";
3
+ import DOMPurify from "isomorphic-dompurify";
3
4
  /**
4
5
  * Parse markdown to sanitized HTML for safe rendering.
5
6
  * Uses marked for parsing and DOMPurify for XSS protection.
@@ -1 +1 @@
1
- import{F as o,d as s}from"./p-DzATWlAC.js";const p=o,r=s;export{p as FeedlogBadge,r as defineCustomElement}
1
+ import{F as o,d as s}from"./p-C-bUP9VO.js";const p=o,r=s;export{p as FeedlogBadge,r as defineCustomElement}
@@ -1 +1 @@
1
- import{F as o,d as s}from"./p-DMdb-G26.js";const p=o,r=s;export{p as FeedlogButton,r as defineCustomElement}
1
+ import{F as o,d as r}from"./p-CIASvKvr.js";const s=o,p=r;export{s as FeedlogButton,p as defineCustomElement}
@@ -1 +1 @@
1
- import{t as e,p as o,H as d,h as a}from"./index.js";const r=o(class extends d{constructor(e){super(),!1!==e&&this.__registerHost(),this.__attachShadow()}render(){return a("div",{key:"293a80e66adedfc1af29daf72390a4f464321b96",class:"feedlog-card"},a("slot",{key:"b7e5a827f89035e791d9c756db0f66198e6c5a38",name:"header"}),a("slot",{key:"da89fee0a01068c8438564848f218faa9c5d849e",name:"content"}),a("slot",{key:"30b05e80e4189c0f73810a48f64e072dfac83267",name:"footer"}))}static get style(){return':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}'}},[257,"feedlog-card"]);function l(){"undefined"!=typeof customElements&&["feedlog-card"].forEach((o=>{"feedlog-card"===o&&(customElements.get(e(o))||customElements.define(e(o),r))}))}l();const s=r,f=l;export{s as FeedlogCard,f as defineCustomElement}
1
+ import{p as e,H as o,h as d,t as a}from"./index.js";const r=e(class extends o{constructor(e){super(),!1!==e&&this.__registerHost(),this.__attachShadow()}render(){return d("div",{key:"293a80e66adedfc1af29daf72390a4f464321b96",class:"feedlog-card"},d("slot",{key:"b7e5a827f89035e791d9c756db0f66198e6c5a38",name:"header"}),d("slot",{key:"da89fee0a01068c8438564848f218faa9c5d849e",name:"content"}),d("slot",{key:"30b05e80e4189c0f73810a48f64e072dfac83267",name:"footer"}))}static get style(){return':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}'}},[257,"feedlog-card"]);function l(){"undefined"!=typeof customElements&&["feedlog-card"].forEach((e=>{"feedlog-card"===e&&(customElements.get(a(e))||customElements.define(a(e),r))}))}l();const s=r,f=l;export{s as FeedlogCard,f as defineCustomElement}
@@ -1 +1 @@
1
- import{F as o,d as s}from"./p-TX_JzdfG.js";const p=o,r=s;export{p as FeedlogIssue,r as defineCustomElement}
1
+ import{F as o,d as s}from"./p-Du-VNLmx.js";const m=o,p=s;export{m as FeedlogIssue,p as defineCustomElement}