@feedlog-ai/webcomponents 0.0.1

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