feedback-vos 1.0.0 → 1.0.2

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/index.mjs CHANGED
@@ -54,7 +54,7 @@ function ScreenshotButton({
54
54
  "button",
55
55
  {
56
56
  type: "button",
57
- className: "p-1 w-10 h-10 rounded-md border-transparent flex \r\n justify-end items-end text-zinc-400 hover:text-zinc-100 transition-colors",
57
+ className: "p-1 w-10 h-10 rounded-md border-transparent flex \n justify-end items-end text-zinc-400 hover:text-zinc-100 transition-colors",
58
58
  onClick: () => onScreenshotTook(null),
59
59
  style: {
60
60
  backgroundImage: `url(${screenshot})`,
@@ -69,119 +69,384 @@ function ScreenshotButton({
69
69
  "button",
70
70
  {
71
71
  type: "button",
72
- className: "p-2 bg-zinc-800 rounded-md border-transparent hover:bg-zinc-700\r\n transitions-colors focus:outline-none focus:ring-2\r\n focus:ring-offset-2 focus:ring-offset-zinc-900 focus:ring-brand-500",
72
+ className: "p-2 bg-zinc-800 rounded-md border-transparent hover:bg-zinc-700\n transitions-colors focus:outline-none focus:ring-2\n focus:ring-offset-2 focus:ring-offset-zinc-900 focus:ring-brand-500",
73
73
  onClick: handleTakeScreenshot,
74
74
  children: isTakenScreenshot ? /* @__PURE__ */ jsx(Loading, {}) : /* @__PURE__ */ jsx(Camera, { weight: "bold", className: "w-6 h-6" })
75
75
  }
76
76
  );
77
77
  }
78
78
 
79
- // src/lib/integrations/notion.ts
80
- async function sendToNotion(config, data) {
81
- const { apiKey, databaseId } = config;
82
- const { type, comment, screenshot } = data;
83
- const typeMap = {
84
- BUG: "Bug",
85
- IDEA: "Idea",
86
- OTHER: "Other"
87
- };
88
- const properties = {
89
- Type: {
90
- select: {
91
- name: typeMap[type]
79
+ // src/lib/integrations/github.ts
80
+ async function uploadScreenshotToRepo(token, owner, repo, screenshot, screenshotPath) {
81
+ const compressedScreenshot = await compressScreenshot(screenshot, 1920, 0.7);
82
+ const base64Data = compressedScreenshot.split(",")[1];
83
+ const binaryData = Uint8Array.from(atob(base64Data), (c) => c.charCodeAt(0));
84
+ const repoResponse = await fetch(
85
+ `https://api.github.com/repos/${owner}/${repo}`,
86
+ {
87
+ headers: {
88
+ "Authorization": `Bearer ${token}`,
89
+ "Accept": "application/vnd.github.v3+json",
90
+ "User-Agent": "feedback-vos"
92
91
  }
93
- },
94
- Comment: {
95
- rich_text: [
96
- {
97
- text: {
98
- content: comment
99
- }
100
- }
101
- ]
102
92
  }
103
- };
104
- const children = [];
105
- if (screenshot) {
106
- children.push({
107
- object: "block",
108
- type: "paragraph",
109
- paragraph: {
110
- rich_text: [
111
- {
112
- text: {
113
- content: "Screenshot provided (see comment for details)"
114
- }
115
- }
116
- ]
93
+ );
94
+ let defaultBranch = "main";
95
+ if (repoResponse.ok) {
96
+ const repoData = await repoResponse.json();
97
+ defaultBranch = repoData.default_branch || "main";
98
+ }
99
+ const folderPath = screenshotPath || ".feedback-vos";
100
+ const timestamp = Date.now();
101
+ const randomId = Math.random().toString(36).substring(2, 9);
102
+ const filename = `feedback-${timestamp}-${randomId}.jpg`;
103
+ const path = `${folderPath}/${filename}`;
104
+ const base64Content = btoa(String.fromCharCode(...binaryData));
105
+ const folderCheckUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${folderPath}`;
106
+ try {
107
+ const folderCheck = await fetch(folderCheckUrl, {
108
+ headers: {
109
+ "Authorization": `Bearer ${token}`,
110
+ "Accept": "application/vnd.github.v3+json",
111
+ "User-Agent": "feedback-vos"
117
112
  }
118
113
  });
119
- properties.Screenshot = {
120
- rich_text: [
121
- {
122
- text: {
123
- content: screenshot.substring(0, 2e3)
124
- // Truncate if too long
125
- }
114
+ if (folderCheck.status === 404) {
115
+ const readmeContent = btoa("# Feedback Screenshots\n\nThis folder contains screenshots from user feedback.\n");
116
+ try {
117
+ const folderCreateResponse = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${folderPath}/README.md`, {
118
+ method: "PUT",
119
+ headers: {
120
+ "Authorization": `Bearer ${token}`,
121
+ "Accept": "application/vnd.github.v3+json",
122
+ "Content-Type": "application/json",
123
+ "User-Agent": "feedback-vos"
124
+ },
125
+ body: JSON.stringify({
126
+ message: "Create feedback screenshots folder",
127
+ content: readmeContent,
128
+ branch: defaultBranch
129
+ })
130
+ });
131
+ if (!folderCreateResponse.ok) {
132
+ const folderError = await folderCreateResponse.json().catch(() => ({}));
133
+ console.warn("Could not create folder, proceeding with upload anyway:", folderError);
134
+ } else {
135
+ console.log(`Folder ${folderPath} created successfully`);
126
136
  }
127
- ]
128
- };
137
+ } catch (folderCreateError) {
138
+ console.warn("Could not create folder, proceeding with upload:", folderCreateError);
139
+ }
140
+ } else if (folderCheck.status === 200) {
141
+ const folderData = await folderCheck.json().catch(() => null);
142
+ if (folderData && !Array.isArray(folderData)) {
143
+ throw new Error(`Path "${folderPath}" exists as a file, not a folder. Please use a different path or remove the file.`);
144
+ }
145
+ console.log(`Folder ${folderPath} already exists`);
146
+ }
147
+ } catch (folderError) {
148
+ if (folderError instanceof Error && folderError.message.includes("exists as a file")) {
149
+ throw folderError;
150
+ }
151
+ console.warn("Could not verify/create screenshots folder:", folderError);
129
152
  }
130
- const response = await fetch("https://api.notion.com/v1/pages", {
131
- method: "POST",
153
+ const uploadUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
154
+ const response = await fetch(uploadUrl, {
155
+ method: "PUT",
132
156
  headers: {
133
- "Authorization": `Bearer ${apiKey}`,
157
+ "Authorization": `Bearer ${token}`,
158
+ "Accept": "application/vnd.github.v3+json",
134
159
  "Content-Type": "application/json",
135
- "Notion-Version": "2022-06-28"
160
+ "User-Agent": "feedback-vos"
136
161
  },
137
162
  body: JSON.stringify({
138
- parent: {
139
- database_id: databaseId
140
- },
141
- properties,
142
- children
163
+ message: `Add feedback screenshot: ${filename}`,
164
+ content: base64Content,
165
+ branch: defaultBranch
143
166
  })
144
167
  });
145
168
  if (!response.ok) {
146
- const error = await response.text();
147
- throw new Error(`Notion API error: ${error}`);
169
+ const errorData = await response.json().catch(() => ({}));
170
+ const errorMessage = errorData.message || "Unknown error";
171
+ if (response.status === 409) {
172
+ throw new Error(`File already exists. This is unexpected - please try again.`);
173
+ } else if (response.status === 403) {
174
+ throw new Error(`Permission denied. Make sure your token has write access to the repository.`);
175
+ } else if (response.status === 422) {
176
+ throw new Error(`Validation failed: ${errorMessage}. The file might be too large.`);
177
+ }
178
+ throw new Error(`Failed to upload screenshot (${response.status}): ${errorMessage}`);
179
+ }
180
+ await response.json();
181
+ const rawUrl = `https://github.com/${owner}/${repo}/blob/${defaultBranch}/${path}?raw=true`;
182
+ console.log(`Screenshot uploaded successfully to: ${rawUrl}`);
183
+ return rawUrl;
184
+ }
185
+ function compressScreenshot(dataUrl, maxWidth = 1920, quality = 0.7) {
186
+ return new Promise((resolve, reject) => {
187
+ if (typeof window === "undefined" || typeof document === "undefined") {
188
+ reject(new Error("Screenshot compression only works in browser environments"));
189
+ return;
190
+ }
191
+ const img = new Image();
192
+ img.onload = () => {
193
+ const canvas = document.createElement("canvas");
194
+ let width = img.width;
195
+ let height = img.height;
196
+ if (width > maxWidth) {
197
+ height = height * maxWidth / width;
198
+ width = maxWidth;
199
+ }
200
+ canvas.width = width;
201
+ canvas.height = height;
202
+ const ctx = canvas.getContext("2d");
203
+ if (!ctx) {
204
+ reject(new Error("Could not get canvas context"));
205
+ return;
206
+ }
207
+ ctx.drawImage(img, 0, 0, width, height);
208
+ const compressedDataUrl = canvas.toDataURL("image/jpeg", quality);
209
+ resolve(compressedDataUrl);
210
+ };
211
+ img.onerror = () => reject(new Error("Failed to load image"));
212
+ img.src = dataUrl;
213
+ });
214
+ }
215
+ async function verifyRepositoryAccess(token, owner, repo) {
216
+ try {
217
+ const response = await fetch(
218
+ `https://api.github.com/repos/${owner}/${repo}`,
219
+ {
220
+ headers: {
221
+ "Authorization": `Bearer ${token}`,
222
+ "Accept": "application/vnd.github.v3+json",
223
+ "User-Agent": "feedback-vos"
224
+ }
225
+ }
226
+ );
227
+ if (response.status === 404) {
228
+ return { exists: false, hasIssues: false, error: "Repository not found" };
229
+ }
230
+ if (!response.ok) {
231
+ const errorData = await response.json().catch(() => ({}));
232
+ return {
233
+ exists: false,
234
+ hasIssues: false,
235
+ error: errorData.message || `HTTP ${response.status}`
236
+ };
237
+ }
238
+ const repoData = await response.json();
239
+ return {
240
+ exists: true,
241
+ hasIssues: repoData.has_issues !== false
242
+ // Default is true if not specified
243
+ };
244
+ } catch (error) {
245
+ return {
246
+ exists: false,
247
+ hasIssues: false,
248
+ error: error instanceof Error ? error.message : "Unknown error"
249
+ };
148
250
  }
149
251
  }
150
-
151
- // src/lib/integrations/github.ts
152
252
  async function sendToGitHub(config, data) {
153
- const { token, owner, repo } = config;
253
+ const { token, owner, repo, screenshotPath } = config;
154
254
  const { type, comment, screenshot } = data;
255
+ if (!token || !owner || !repo) {
256
+ throw new Error("GitHub configuration is incomplete. Please provide token, owner, and repo.");
257
+ }
258
+ const verification = await verifyRepositoryAccess(token, owner, repo);
259
+ if (!verification.exists) {
260
+ throw new Error(
261
+ `Repository "${owner}/${repo}" not found or not accessible.
262
+ Error: ${verification.error || "Unknown error"}
263
+
264
+ Please verify:
265
+ - Repository exists at https://github.com/${owner}/${repo}
266
+ - Your token has access to this repository
267
+ - Token has "repo" scope (for private) or "public_repo" scope (for public)`
268
+ );
269
+ }
270
+ if (!verification.hasIssues) {
271
+ throw new Error(
272
+ `Issues are disabled for repository "${owner}/${repo}".
273
+
274
+ Please enable Issues in repository Settings \u2192 General \u2192 Features \u2192 Issues`
275
+ );
276
+ }
155
277
  const title = `[${type}] Feedback`;
278
+ const ABSOLUTE_MAX_LENGTH = 65536;
279
+ const BASE_BODY_LENGTH = 50;
280
+ const SCREENSHOT_URL_LENGTH = 150;
281
+ const SAFETY_MARGIN = 1e3;
282
+ const MAX_COMMENT_LENGTH = ABSOLUTE_MAX_LENGTH - BASE_BODY_LENGTH - SCREENSHOT_URL_LENGTH - SAFETY_MARGIN;
283
+ const limitedComment = comment.length > MAX_COMMENT_LENGTH ? comment.substring(0, MAX_COMMENT_LENGTH) + "\n\n... (comment truncated)" : comment;
156
284
  let body = `**Type:** ${type}
157
285
 
158
286
  **Comment:**
159
- ${comment}`;
287
+ ${limitedComment}`;
160
288
  if (screenshot) {
161
- body += `
289
+ try {
290
+ console.log("Uploading screenshot to repository...");
291
+ console.log("Screenshot path:", screenshotPath || ".feedback-vos");
292
+ const screenshotUrl = await uploadScreenshotToRepo(token, owner, repo, screenshot, screenshotPath);
293
+ console.log("Screenshot uploaded successfully, URL:", screenshotUrl);
294
+ body += `
162
295
 
163
296
  **Screenshot:**
164
- ![Screenshot](${screenshot})`;
297
+ ![Screenshot](${screenshotUrl})`;
298
+ console.log("Body length after adding screenshot URL:", body.length);
299
+ } catch (error) {
300
+ console.error("Failed to upload screenshot to repository:", error);
301
+ body += `
302
+
303
+ **Screenshot:** Upload failed - screenshot not included.`;
304
+ console.log("Body length after upload failure:", body.length);
305
+ }
165
306
  }
166
- const response = await fetch(
167
- `https://api.github.com/repos/${owner}/${repo}/issues`,
168
- {
307
+ const SAFE_MAX_LENGTH = 65e3;
308
+ console.log(`Issue body length before final check: ${body.length} characters`);
309
+ if (body.length > SAFE_MAX_LENGTH) {
310
+ console.warn(`Body is too long (${body.length}), truncating...`);
311
+ const excess = body.length - SAFE_MAX_LENGTH;
312
+ const commentStartMarker = "\n\n**Comment:**\n";
313
+ const commentStart = body.indexOf(commentStartMarker);
314
+ const screenshotStart = body.indexOf("\n\n**Screenshot:**");
315
+ if (commentStart > 0) {
316
+ const commentStartPos = commentStart + commentStartMarker.length;
317
+ const commentEndPos = screenshotStart > 0 ? screenshotStart : body.length;
318
+ const currentComment = body.substring(commentStartPos, commentEndPos);
319
+ const newCommentLength = Math.max(100, currentComment.length - excess - 500);
320
+ const truncatedComment = currentComment.substring(0, newCommentLength) + "\n\n... (truncated due to size limit)";
321
+ const beforeComment = body.substring(0, commentStartPos);
322
+ const afterComment = screenshotStart > 0 ? body.substring(screenshotStart) : "";
323
+ body = beforeComment + truncatedComment + afterComment;
324
+ }
325
+ }
326
+ if (body.length >= ABSOLUTE_MAX_LENGTH) {
327
+ console.error(`Body STILL too long after truncation: ${body.length} characters. Force truncating.`);
328
+ const baseText = `**Type:** ${type}
329
+
330
+ **Comment:**
331
+ `;
332
+ const maxCommentLength = ABSOLUTE_MAX_LENGTH - baseText.length - 1e3;
333
+ const safeComment = comment.substring(0, Math.max(100, maxCommentLength)) + "\n\n... (truncated due to size limit)";
334
+ body = baseText + safeComment;
335
+ const screenshotIndex = body.indexOf("\n\n**Screenshot:**");
336
+ if (screenshotIndex > 0) {
337
+ body = body.substring(0, screenshotIndex) + "\n\n**Screenshot:** Not included due to size limit.";
338
+ }
339
+ }
340
+ if (body.length >= ABSOLUTE_MAX_LENGTH) {
341
+ const minimalBase = `**Type:** ${type}
342
+
343
+ **Comment:**
344
+ `;
345
+ const maxSafeComment = ABSOLUTE_MAX_LENGTH - minimalBase.length - 100;
346
+ const minimalComment = comment.substring(0, Math.max(50, maxSafeComment)) + "\n\n... (truncated)";
347
+ body = minimalBase + minimalComment;
348
+ }
349
+ console.log(`Final issue body length: ${body.length} characters (limit: ${ABSOLUTE_MAX_LENGTH})`);
350
+ if (body.length >= ABSOLUTE_MAX_LENGTH) {
351
+ throw new Error(`CRITICAL: Cannot create issue - body is ${body.length} characters, exceeds GitHub limit of ${ABSOLUTE_MAX_LENGTH}.`);
352
+ }
353
+ const url = `https://api.github.com/repos/${owner}/${repo}/issues`;
354
+ try {
355
+ const response = await fetch(url, {
169
356
  method: "POST",
170
357
  headers: {
171
- "Authorization": `token ${token}`,
358
+ "Authorization": `Bearer ${token}`,
172
359
  "Accept": "application/vnd.github.v3+json",
173
- "Content-Type": "application/json"
360
+ "Content-Type": "application/json",
361
+ "User-Agent": "feedback-vos"
174
362
  },
175
363
  body: JSON.stringify({
176
364
  title,
177
365
  body,
366
+ // Note: Labels must exist in the repository. If they don't exist, GitHub will ignore them.
367
+ // You can create these labels in your repository settings if needed.
178
368
  labels: ["feedback", type.toLowerCase()]
179
369
  })
370
+ });
371
+ if (!response.ok) {
372
+ let errorMessage = `GitHub API error (${response.status}): `;
373
+ try {
374
+ const errorData = await response.json();
375
+ errorMessage += errorData.message || JSON.stringify(errorData);
376
+ if (response.status === 404) {
377
+ errorMessage += `
378
+
379
+ Trying to access: ${url}`;
380
+ errorMessage += `
381
+
382
+ Possible causes:
383
+ `;
384
+ errorMessage += `- Repository "${owner}/${repo}" does not exist or is not accessible
385
+ `;
386
+ errorMessage += `- Token does not have access to this repository
387
+ `;
388
+ errorMessage += `- Check that owner and repo names are correct (case-sensitive)
389
+ `;
390
+ errorMessage += `- Verify the repository URL: https://github.com/${owner}/${repo}
391
+ `;
392
+ errorMessage += `- Make sure Issues are enabled in repository settings
393
+ `;
394
+ errorMessage += `
395
+ To debug:
396
+ `;
397
+ errorMessage += `1. Visit https://github.com/${owner}/${repo} to verify it exists
398
+ `;
399
+ errorMessage += `2. Check repository Settings \u2192 General \u2192 Features \u2192 Issues (must be enabled)
400
+ `;
401
+ errorMessage += `3. Verify your token has "repo" scope (for private) or "public_repo" scope (for public)
402
+ `;
403
+ errorMessage += `4. Test token access: curl -H "Authorization: Bearer YOUR_TOKEN" https://api.github.com/repos/${owner}/${repo}`;
404
+ } else if (response.status === 401) {
405
+ errorMessage += `
406
+
407
+ Possible causes:
408
+ `;
409
+ errorMessage += `- Invalid or expired GitHub token
410
+ `;
411
+ errorMessage += `- Token does not have the required "repo" or "public_repo" scope
412
+ `;
413
+ errorMessage += `- Generate a new token at https://github.com/settings/tokens`;
414
+ } else if (response.status === 422) {
415
+ errorMessage += `
416
+
417
+ Possible causes:
418
+ `;
419
+ errorMessage += `- Issue body is too long (maximum is 65536 characters)
420
+ `;
421
+ errorMessage += `- Screenshot is too large - it will be automatically compressed
422
+ `;
423
+ errorMessage += `- Try reducing the comment length or removing the screenshot
424
+ `;
425
+ errorMessage += `- Invalid label names (labels must exist in the repository)`;
426
+ } else if (response.status === 403) {
427
+ errorMessage += `
428
+
429
+ Possible causes:
430
+ `;
431
+ errorMessage += `- Token does not have permission to create issues
432
+ `;
433
+ errorMessage += `- Repository has issues disabled
434
+ `;
435
+ errorMessage += `- Rate limit exceeded (check GitHub API rate limits)
436
+ `;
437
+ errorMessage += `- Check repository Settings \u2192 General \u2192 Features \u2192 Issues`;
438
+ }
439
+ } catch (parseError) {
440
+ const errorText = await response.text();
441
+ errorMessage += errorText || "Unknown error";
442
+ }
443
+ throw new Error(errorMessage);
180
444
  }
181
- );
182
- if (!response.ok) {
183
- const error = await response.text();
184
- throw new Error(`GitHub API error: ${error}`);
445
+ } catch (error) {
446
+ if (error instanceof Error) {
447
+ throw error;
448
+ }
449
+ throw new Error(`Failed to create GitHub issue: ${String(error)}`);
185
450
  }
186
451
  }
187
452
  function FeedbackContentStep({
@@ -189,7 +454,6 @@ function FeedbackContentStep({
189
454
  onFeedbackRestartRequest,
190
455
  onFeedbackSent,
191
456
  integration,
192
- notionConfig,
193
457
  githubConfig
194
458
  }) {
195
459
  const [screenshot, setScreenshot] = useState(null);
@@ -205,9 +469,7 @@ function FeedbackContentStep({
205
469
  comment,
206
470
  screenshot
207
471
  };
208
- if (integration === "notion" && notionConfig) {
209
- await sendToNotion(notionConfig, feedbackData);
210
- } else if (integration === "github" && githubConfig) {
472
+ if (integration === "github") {
211
473
  await sendToGitHub(githubConfig, feedbackData);
212
474
  } else {
213
475
  throw new Error("Invalid integration configuration");
@@ -248,7 +510,7 @@ function FeedbackContentStep({
248
510
  /* @__PURE__ */ jsx(
249
511
  "textarea",
250
512
  {
251
- className: "min-w-[384px] w-full min-h-[112px] text-sm \r\n placeholder-zinc-400 text-zinc-100 border-zinc-600 bg-transparent rounded-md \r\n focus:border-brand-500 focus:ring-brand-500 focus:ring-1 resize-none focus:outline-none\r\n scrollbar-thumb-zinc-700 scrollbar-track-transparent scrollbar-thin",
513
+ className: "min-w-[384px] w-full min-h-[112px] text-sm \n placeholder-zinc-400 text-zinc-100 border-zinc-600 bg-transparent rounded-md \n focus:border-brand-500 focus:ring-brand-500 focus:ring-1 resize-none focus:outline-none\n scrollbar-thumb-zinc-700 scrollbar-track-transparent scrollbar-thin",
252
514
  placeholder: "Tell in detail what is happening",
253
515
  onChange: (e) => setComment(e.target.value)
254
516
  }
@@ -266,7 +528,7 @@ function FeedbackContentStep({
266
528
  {
267
529
  type: "submit",
268
530
  disabled: comment.length === 0 || isSendingFeedback,
269
- className: "p-2 bg-brand-500 rounded-md border-transparent flex-1 justify-center\r\n items-center text-sm hover:bg-brand-300 focus:outline-none focus:ring-2\r\n focus:ring-offset-2 focus:ring-offset-zinc-900 focus:ring-brand-500\r\n transition-colors disabled:opacity-50 disabled:cursor-not-allowed\r\n disabled:hover:bg-brand-500",
531
+ className: "p-2 bg-brand-500 rounded-md border-transparent flex-1 justify-center\n items-center text-sm hover:bg-brand-300 focus:outline-none focus:ring-2\n focus:ring-offset-2 focus:ring-offset-zinc-900 focus:ring-brand-500\n transition-colors disabled:opacity-50 disabled:cursor-not-allowed\n disabled:hover:bg-brand-500",
270
532
  children: isSendingFeedback ? /* @__PURE__ */ jsx(Loading, {}) : "Send feedback"
271
533
  }
272
534
  )
@@ -318,7 +580,7 @@ var feedbackTypes = {
318
580
  }
319
581
  }
320
582
  };
321
- function WidgetForm({ integration, notionConfig, githubConfig }) {
583
+ function WidgetForm({ integration, githubConfig }) {
322
584
  const [feedbackType, setFeedbackType] = useState(null);
323
585
  const [feedbackSent, setFeedbackSent] = useState(false);
324
586
  function handleRestartFeedback() {
@@ -333,7 +595,6 @@ function WidgetForm({ integration, notionConfig, githubConfig }) {
333
595
  onFeedbackRestartRequest: handleRestartFeedback,
334
596
  onFeedbackSent: () => setFeedbackSent(true),
335
597
  integration,
336
- notionConfig,
337
598
  githubConfig
338
599
  }
339
600
  ) }),
@@ -353,7 +614,6 @@ function WidgetForm({ integration, notionConfig, githubConfig }) {
353
614
  }
354
615
  function Widget({
355
616
  integration,
356
- notionConfig,
357
617
  githubConfig,
358
618
  position = "bottom-right"
359
619
  }) {
@@ -368,7 +628,6 @@ function Widget({
368
628
  WidgetForm,
369
629
  {
370
630
  integration,
371
- notionConfig,
372
631
  githubConfig
373
632
  }
374
633
  ) }),