diff --git a/.craft.yml b/.craft.yml
index bc1446711d2c..820c50f199fd 100644
--- a/.craft.yml
+++ b/.craft.yml
@@ -32,7 +32,15 @@ targets:
- name: npm
id: '@sentry-internal/feedback'
includeNames: /^sentry-internal-feedback-\d.*\.tgz$/
- ## 1.8 ReplayCanvas package (browser only)
+ ## 1.8 Feedback Modal package (browser only)
+ - name: npm
+ id: '@sentry-internal/feedback-modal'
+ includeNames: /^sentry-internal-feedback-modal-\d.*\.tgz$/
+ ## 1.9 Feedback Screenshot package (browser only)
+ - name: npm
+ id: '@sentry-internal/feedback-screenshot'
+ includeNames: /^sentry-internal-feedback-screenshot-\d.*\.tgz$/
+ ## 1.10 ReplayCanvas package (browser only)
- name: npm
id: '@sentry-internal/replay-canvas'
includeNames: /^sentry-internal-replay-canvas-\d.*\.tgz$/
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b131d8cb2717..ddaeed70dab9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -105,6 +105,8 @@ jobs:
- 'packages/replay/**'
- 'packages/replay-canvas/**'
- 'packages/feedback/**'
+ - 'packages/feedback-modal/**'
+ - 'packages/feedback-screenshot/**'
- 'packages/wasm/**'
browser_integration:
- *shared
diff --git a/CODEOWNERS b/CODEOWNERS
index 6ae2679deafa..0cbff3b53444 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -2,4 +2,6 @@ packages/replay @getsentry/replay-sdk-web
packages/replay-worker @getsentry/replay-sdk-web
packages/replay-canvas @getsentry/replay-sdk-web
packages/feedback @getsentry/replay-sdk-web
+packages/feedback-modal @getsentry/replay-sdk-web
+packages/feedback-screenshot @getsentry/replay-sdk-web
dev-packages/browser-integration-tests/suites/replay @getsentry/replay-sdk-web
diff --git a/package.json b/package.json
index 00945d179e72..91351e047d3a 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,8 @@
"packages/eslint-config-sdk",
"packages/eslint-plugin-sdk",
"packages/feedback",
+ "packages/feedback-modal",
+ "packages/feedback-screenshot",
"packages/gatsby",
"packages/google-cloud-serverless",
"packages/integration-shims",
diff --git a/packages/browser/package.json b/packages/browser/package.json
index d748c97dff02..927cbd41a045 100644
--- a/packages/browser/package.json
+++ b/packages/browser/package.json
@@ -43,6 +43,8 @@
},
"dependencies": {
"@sentry-internal/browser-utils": "8.0.0-alpha.9",
+ "@sentry-internal/feedback-modal": "8.0.0-alpha.9",
+ "@sentry-internal/feedback-screenshot": "8.0.0-alpha.9",
"@sentry-internal/feedback": "8.0.0-alpha.9",
"@sentry-internal/replay": "8.0.0-alpha.9",
"@sentry-internal/replay-canvas": "8.0.0-alpha.9",
diff --git a/packages/browser/src/index.bundle.feedback.ts b/packages/browser/src/index.bundle.feedback.ts
index de24e36e2a60..193cac1a5f06 100644
--- a/packages/browser/src/index.bundle.feedback.ts
+++ b/packages/browser/src/index.bundle.feedback.ts
@@ -1,5 +1,7 @@
// This is exported so the loader does not fail when switching off Replay/Tracing
import { feedbackIntegration, getFeedback } from '@sentry-internal/feedback';
+import { feedbackModalIntegration } from '@sentry-internal/feedback-modal';
+import { feedbackScreenshotIntegration } from '@sentry-internal/feedback-screenshot';
import {
addTracingExtensionsShim,
browserTracingIntegrationShim,
@@ -12,6 +14,8 @@ export {
addTracingExtensionsShim as addTracingExtensions,
replayIntegrationShim as replayIntegration,
feedbackIntegration,
+ feedbackModalIntegration,
+ feedbackScreenshotIntegration,
getFeedback,
};
// Note: We do not export a shim for `Span` here, as that is quite complex and would blow up the bundle
diff --git a/packages/browser/src/index.bundle.replay.ts b/packages/browser/src/index.bundle.replay.ts
index ec0a50c92905..0c0bb6ca40ef 100644
--- a/packages/browser/src/index.bundle.replay.ts
+++ b/packages/browser/src/index.bundle.replay.ts
@@ -3,6 +3,8 @@ import {
addTracingExtensionsShim,
browserTracingIntegrationShim,
feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
} from '@sentry-internal/integration-shims';
import { replayIntegration } from '@sentry-internal/replay';
@@ -12,5 +14,7 @@ export {
addTracingExtensionsShim as addTracingExtensions,
replayIntegration,
feedbackIntegrationShim as feedbackIntegration,
+ feedbackModalIntegrationShim as feedbackModalIntegration,
+ feedbackScreenshotIntegrationShim as feedbackScreenshotIntegration,
};
// Note: We do not export a shim for `Span` here, as that is quite complex and would blow up the bundle
diff --git a/packages/browser/src/index.bundle.tracing.replay.feedback.ts b/packages/browser/src/index.bundle.tracing.replay.feedback.ts
index 6133fc2870f5..d26ccf1ba230 100644
--- a/packages/browser/src/index.bundle.tracing.replay.feedback.ts
+++ b/packages/browser/src/index.bundle.tracing.replay.feedback.ts
@@ -4,6 +4,8 @@ import {
startBrowserTracingPageLoadSpan,
} from '@sentry-internal/browser-utils';
import { feedbackIntegration, getFeedback } from '@sentry-internal/feedback';
+import { feedbackModalIntegration } from '@sentry-internal/feedback-modal';
+import { feedbackScreenshotIntegration } from '@sentry-internal/feedback-screenshot';
import { replayIntegration } from '@sentry-internal/replay';
import { addTracingExtensions } from '@sentry/core';
@@ -23,6 +25,8 @@ export {
export {
feedbackIntegration,
+ feedbackModalIntegration,
+ feedbackScreenshotIntegration,
replayIntegration,
browserTracingIntegration,
addTracingExtensions,
diff --git a/packages/browser/src/index.bundle.tracing.replay.ts b/packages/browser/src/index.bundle.tracing.replay.ts
index f949ea43541a..628ebeb19651 100644
--- a/packages/browser/src/index.bundle.tracing.replay.ts
+++ b/packages/browser/src/index.bundle.tracing.replay.ts
@@ -3,7 +3,11 @@ import {
startBrowserTracingNavigationSpan,
startBrowserTracingPageLoadSpan,
} from '@sentry-internal/browser-utils';
-import { feedbackIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+} from '@sentry-internal/integration-shims';
import { replayIntegration } from '@sentry-internal/replay';
import { addTracingExtensions } from '@sentry/core';
@@ -24,6 +28,8 @@ export {
export {
replayIntegration,
feedbackIntegrationShim as feedbackIntegration,
+ feedbackModalIntegrationShim as feedbackModalIntegration,
+ feedbackScreenshotIntegrationShim as feedbackScreenshotIntegration,
browserTracingIntegration,
addTracingExtensions,
startBrowserTracingNavigationSpan,
diff --git a/packages/browser/src/index.bundle.tracing.ts b/packages/browser/src/index.bundle.tracing.ts
index 1b4f89f935df..29c463fae586 100644
--- a/packages/browser/src/index.bundle.tracing.ts
+++ b/packages/browser/src/index.bundle.tracing.ts
@@ -4,7 +4,12 @@ import {
startBrowserTracingPageLoadSpan,
} from '@sentry-internal/browser-utils';
// This is exported so the loader does not fail when switching off Replay
-import { feedbackIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+ replayIntegrationShim,
+} from '@sentry-internal/integration-shims';
import { addTracingExtensions } from '@sentry/core';
// We are patching the global object with our hub extension methods
@@ -23,6 +28,8 @@ export {
export {
feedbackIntegrationShim as feedbackIntegration,
+ feedbackModalIntegrationShim as feedbackModalIntegration,
+ feedbackScreenshotIntegrationShim as feedbackScreenshotIntegration,
replayIntegrationShim as replayIntegration,
browserTracingIntegration,
addTracingExtensions,
diff --git a/packages/browser/src/index.bundle.ts b/packages/browser/src/index.bundle.ts
index b27672414b20..10482f8135cf 100644
--- a/packages/browser/src/index.bundle.ts
+++ b/packages/browser/src/index.bundle.ts
@@ -3,6 +3,8 @@ import {
addTracingExtensionsShim,
browserTracingIntegrationShim,
feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
replayIntegrationShim,
} from '@sentry-internal/integration-shims';
@@ -11,6 +13,8 @@ export {
addTracingExtensionsShim as addTracingExtensions,
browserTracingIntegrationShim as browserTracingIntegration,
feedbackIntegrationShim as feedbackIntegration,
+ feedbackModalIntegrationShim as feedbackModalIntegration,
+ feedbackScreenshotIntegrationShim as feedbackScreenshotIntegration,
replayIntegrationShim as replayIntegration,
};
// Note: We do not export a shim for `Span` here, as that is quite complex and would blow up the bundle
diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts
index 54dd27f8b8b5..8d8069d2460c 100644
--- a/packages/browser/src/index.ts
+++ b/packages/browser/src/index.ts
@@ -35,6 +35,8 @@ export {
getFeedback,
sendFeedback,
} from '@sentry-internal/feedback';
+export { feedbackModalIntegration } from '@sentry-internal/feedback-modal';
+export { feedbackScreenshotIntegration } from '@sentry-internal/feedback-screenshot';
export {
defaultRequestInstrumentationOptions,
diff --git a/packages/browser/test/unit/index.bundle.feedback.test.ts b/packages/browser/test/unit/index.bundle.feedback.test.ts
index 5a3451cb3ef0..c403144d4306 100644
--- a/packages/browser/test/unit/index.bundle.feedback.test.ts
+++ b/packages/browser/test/unit/index.bundle.feedback.test.ts
@@ -1,11 +1,13 @@
import { replayIntegrationShim } from '@sentry-internal/integration-shims';
-import { feedbackIntegration } from '@sentry/browser';
+import { feedbackIntegration, feedbackModalIntegration, feedbackScreenshotIntegration } from '@sentry/browser';
-import * as TracingReplayBundle from '../../src/index.bundle.feedback';
+import * as FeedbackBundle from '../../src/index.bundle.feedback';
describe('index.bundle.feedback', () => {
it('has correct exports', () => {
- expect(TracingReplayBundle.replayIntegration).toBe(replayIntegrationShim);
- expect(TracingReplayBundle.feedbackIntegration).toBe(feedbackIntegration);
+ expect(FeedbackBundle.replayIntegration).toBe(replayIntegrationShim);
+ expect(FeedbackBundle.feedbackIntegration).toBe(feedbackIntegration);
+ expect(FeedbackBundle.feedbackModalIntegration).toBe(feedbackModalIntegration);
+ expect(FeedbackBundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegration);
});
});
diff --git a/packages/browser/test/unit/index.bundle.replay.test.ts b/packages/browser/test/unit/index.bundle.replay.test.ts
index 479e6b23393b..4e3d4e344734 100644
--- a/packages/browser/test/unit/index.bundle.replay.test.ts
+++ b/packages/browser/test/unit/index.bundle.replay.test.ts
@@ -1,11 +1,17 @@
-import { feedbackIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+} from '@sentry-internal/integration-shims';
import { replayIntegration } from '@sentry/browser';
-import * as TracingReplayBundle from '../../src/index.bundle.replay';
+import * as ReplayBundle from '../../src/index.bundle.replay';
describe('index.bundle.replay', () => {
it('has correct exports', () => {
- expect(TracingReplayBundle.replayIntegration).toBe(replayIntegration);
- expect(TracingReplayBundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(ReplayBundle.replayIntegration).toBe(replayIntegration);
+ expect(ReplayBundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(ReplayBundle.feedbackModalIntegration).toBe(feedbackModalIntegrationShim);
+ expect(ReplayBundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegrationShim);
});
});
diff --git a/packages/browser/test/unit/index.bundle.test.ts b/packages/browser/test/unit/index.bundle.test.ts
index 9ef9f38d8db5..f02e2528f802 100644
--- a/packages/browser/test/unit/index.bundle.test.ts
+++ b/packages/browser/test/unit/index.bundle.test.ts
@@ -1,10 +1,17 @@
-import { feedbackIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+ replayIntegrationShim,
+} from '@sentry-internal/integration-shims';
-import * as TracingBundle from '../../src/index.bundle';
+import * as Bundle from '../../src/index.bundle';
describe('index.bundle', () => {
it('has correct exports', () => {
- expect(TracingBundle.replayIntegration).toBe(replayIntegrationShim);
- expect(TracingBundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(Bundle.replayIntegration).toBe(replayIntegrationShim);
+ expect(Bundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(Bundle.feedbackModalIntegration).toBe(feedbackModalIntegrationShim);
+ expect(Bundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegrationShim);
});
});
diff --git a/packages/browser/test/unit/index.bundle.tracing.replay.feedback.test.ts b/packages/browser/test/unit/index.bundle.tracing.replay.feedback.test.ts
index a8440d160e2b..873c41bfc769 100644
--- a/packages/browser/test/unit/index.bundle.tracing.replay.feedback.test.ts
+++ b/packages/browser/test/unit/index.bundle.tracing.replay.feedback.test.ts
@@ -1,5 +1,10 @@
import { browserTracingIntegration } from '@sentry-internal/browser-utils';
-import { feedbackIntegration, replayIntegration } from '@sentry/browser';
+import {
+ feedbackIntegration,
+ feedbackModalIntegration,
+ feedbackScreenshotIntegration,
+ replayIntegration,
+} from '@sentry/browser';
import * as TracingReplayFeedbackBundle from '../../src/index.bundle.tracing.replay.feedback';
@@ -8,5 +13,7 @@ describe('index.bundle.tracing.replay.feedback', () => {
expect(TracingReplayFeedbackBundle.replayIntegration).toBe(replayIntegration);
expect(TracingReplayFeedbackBundle.browserTracingIntegration).toBe(browserTracingIntegration);
expect(TracingReplayFeedbackBundle.feedbackIntegration).toBe(feedbackIntegration);
+ expect(TracingReplayFeedbackBundle.feedbackModalIntegration).toBe(feedbackModalIntegration);
+ expect(TracingReplayFeedbackBundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegration);
});
});
diff --git a/packages/browser/test/unit/index.bundle.tracing.replay.test.ts b/packages/browser/test/unit/index.bundle.tracing.replay.test.ts
index 18c286edffc9..3e2a79e081a9 100644
--- a/packages/browser/test/unit/index.bundle.tracing.replay.test.ts
+++ b/packages/browser/test/unit/index.bundle.tracing.replay.test.ts
@@ -1,5 +1,9 @@
import { browserTracingIntegration } from '@sentry-internal/browser-utils';
-import { feedbackIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+} from '@sentry-internal/integration-shims';
import { replayIntegration } from '@sentry/browser';
import * as TracingReplayBundle from '../../src/index.bundle.tracing.replay';
@@ -11,5 +15,7 @@ describe('index.bundle.tracing.replay', () => {
expect(TracingReplayBundle.browserTracingIntegration).toBe(browserTracingIntegration);
expect(TracingReplayBundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(TracingReplayBundle.feedbackModalIntegration).toBe(feedbackModalIntegrationShim);
+ expect(TracingReplayBundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegrationShim);
});
});
diff --git a/packages/browser/test/unit/index.bundle.tracing.test.ts b/packages/browser/test/unit/index.bundle.tracing.test.ts
index 1bb1ca19eec1..10ec0c6f0fd2 100644
--- a/packages/browser/test/unit/index.bundle.tracing.test.ts
+++ b/packages/browser/test/unit/index.bundle.tracing.test.ts
@@ -1,5 +1,10 @@
import { browserTracingIntegration } from '@sentry-internal/browser-utils';
-import { feedbackIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims';
+import {
+ feedbackIntegrationShim,
+ feedbackModalIntegrationShim,
+ feedbackScreenshotIntegrationShim,
+ replayIntegrationShim,
+} from '@sentry-internal/integration-shims';
import * as TracingBundle from '../../src/index.bundle.tracing';
@@ -8,5 +13,7 @@ describe('index.bundle.tracing', () => {
expect(TracingBundle.replayIntegration).toBe(replayIntegrationShim);
expect(TracingBundle.browserTracingIntegration).toBe(browserTracingIntegration);
expect(TracingBundle.feedbackIntegration).toBe(feedbackIntegrationShim);
+ expect(TracingBundle.feedbackModalIntegration).toBe(feedbackModalIntegrationShim);
+ expect(TracingBundle.feedbackScreenshotIntegration).toBe(feedbackScreenshotIntegrationShim);
});
});
diff --git a/packages/feedback-modal/.eslintignore b/packages/feedback-modal/.eslintignore
new file mode 100644
index 000000000000..b38db2f296ff
--- /dev/null
+++ b/packages/feedback-modal/.eslintignore
@@ -0,0 +1,2 @@
+node_modules/
+build/
diff --git a/packages/feedback-modal/.eslintrc.js b/packages/feedback-modal/.eslintrc.js
new file mode 100644
index 000000000000..0b547ffc828c
--- /dev/null
+++ b/packages/feedback-modal/.eslintrc.js
@@ -0,0 +1,16 @@
+// Note: All paths are relative to the directory in which eslint is being run, rather than the directory where this file
+// lives
+
+// ESLint config docs: https://eslint.org/docs/user-guide/configuring/
+
+module.exports = {
+ extends: ['../../.eslintrc.js'],
+ overrides: [
+ {
+ files: ['jest.setup.ts', 'jest.config.ts'],
+ parserOptions: {
+ project: ['tsconfig.test.json'],
+ },
+ },
+ ],
+};
diff --git a/packages/feedback-modal/.gitignore b/packages/feedback-modal/.gitignore
new file mode 100644
index 000000000000..363d3467c6fa
--- /dev/null
+++ b/packages/feedback-modal/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+/*.tgz
+.eslintcache
+build
diff --git a/packages/feedback-modal/LICENSE b/packages/feedback-modal/LICENSE
new file mode 100644
index 000000000000..ea5e82344f87
--- /dev/null
+++ b/packages/feedback-modal/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2024 Sentry (https://sentry.io) and individual contributors. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/feedback-modal/README.md b/packages/feedback-modal/README.md
new file mode 100644
index 000000000000..f4949a12b0d1
--- /dev/null
+++ b/packages/feedback-modal/README.md
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+# Sentry Integration for Feedback
+
+This integration supports our browser feedback SDK allowing us to code-split heavy UI components as needed.
+
+For the primary Feedback Integration see
+[Sentry Feedback SDK](https://github.com/getsentry/sentry-javascript/tree/develop/packages/feedback)
+
+Note: This package is only meant to be used internally.
diff --git a/packages/feedback-modal/jest.config.js b/packages/feedback-modal/jest.config.js
new file mode 100644
index 000000000000..cd02790794a7
--- /dev/null
+++ b/packages/feedback-modal/jest.config.js
@@ -0,0 +1,6 @@
+const baseConfig = require('../../jest/jest.config.js');
+
+module.exports = {
+ ...baseConfig,
+ testEnvironment: 'jsdom',
+};
diff --git a/packages/feedback-modal/package.json b/packages/feedback-modal/package.json
new file mode 100644
index 000000000000..831e6a29c266
--- /dev/null
+++ b/packages/feedback-modal/package.json
@@ -0,0 +1,76 @@
+{
+ "name": "@sentry-internal/feedback-modal",
+ "version": "8.0.0-alpha.9",
+ "description": "Sentry SDK integration for user feedback",
+ "repository": "git://github.com/getsentry/sentry-javascript.git",
+ "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/feedback-modal",
+ "author": "Sentry",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.18"
+ },
+ "files": [
+ "cjs",
+ "esm",
+ "types",
+ "types-ts3.8"
+ ],
+ "main": "build/npm/cjs/index.js",
+ "module": "build/npm/esm/index.js",
+ "types": "build/npm/types/index.d.ts",
+ "exports": {
+ "./package.json": "./package.json",
+ ".": {
+ "import": {
+ "types": "./build/npm/types/index.d.ts",
+ "default": "./build/npm/esm/index.js"
+ },
+ "require": {
+ "types": "./build/npm/types/index.d.ts",
+ "default": "./build/npm/cjs/index.js"
+ }
+ }
+ },
+ "typesVersions": {
+ "<4.9": {
+ "build/npm/types/index.d.ts": [
+ "build/npm/types-ts3.8/index.d.ts"
+ ]
+ }
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@sentry/core": "8.0.0-alpha.9",
+ "@sentry/types": "8.0.0-alpha.9",
+ "@sentry/utils": "8.0.0-alpha.9",
+ "preact": "^10.19.4"
+ },
+ "scripts": {
+ "build": "run-p build:transpile build:types build:bundle",
+ "build:transpile": "rollup -c rollup.npm.config.mjs",
+ "build:bundle": "rollup -c rollup.bundle.config.mjs",
+ "build:dev": "run-p build:transpile build:types",
+ "build:types": "run-s build:types:core build:types:downlevel",
+ "build:types:core": "tsc -p tsconfig.types.json",
+ "build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8 && yarn node ./scripts/shim-preact-export.js",
+ "build:watch": "run-p build:transpile:watch build:bundle:watch build:types:watch",
+ "build:dev:watch": "run-p build:transpile:watch build:types:watch",
+ "build:transpile:watch": "yarn build:transpile --watch",
+ "build:bundle:watch": "yarn build:bundle --watch",
+ "build:types:watch": "tsc -p tsconfig.types.json --watch",
+ "build:tarball": "ts-node ../../scripts/prepack.ts --bundles && npm pack ./build/npm",
+ "circularDepCheck": "madge --circular src/index.ts",
+ "clean": "rimraf build sentry-feedback-modal-*.tgz",
+ "fix": "eslint . --format stylish --fix",
+ "lint": "eslint . --format stylish",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "yalc:publish": "ts-node ../../scripts/prepack.ts --bundles && yalc publish ./build/npm --push --sig"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ },
+ "sideEffects": false
+}
diff --git a/packages/feedback-modal/rollup.bundle.config.mjs b/packages/feedback-modal/rollup.bundle.config.mjs
new file mode 100644
index 000000000000..9fc71b68bc9d
--- /dev/null
+++ b/packages/feedback-modal/rollup.bundle.config.mjs
@@ -0,0 +1,15 @@
+import { makeBaseBundleConfig, makeBundleConfigVariants } from '@sentry-internal/rollup-utils';
+
+export default makeBundleConfigVariants(
+ makeBaseBundleConfig({
+ bundleType: 'addon',
+ entrypoints: ['src/index.ts'],
+ jsVersion: 'es6',
+ licenseTitle: '@sentry-internal/feedback-modal',
+ outputFileBase: () => 'bundles/feedback-modal',
+ sucrase: {
+ jsxPragma: 'h',
+ jsxFragmentPragma: 'Fragment',
+ },
+ }),
+);
diff --git a/packages/feedback-modal/rollup.npm.config.mjs b/packages/feedback-modal/rollup.npm.config.mjs
new file mode 100644
index 000000000000..3dc031c5ff82
--- /dev/null
+++ b/packages/feedback-modal/rollup.npm.config.mjs
@@ -0,0 +1,20 @@
+import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils';
+
+export default makeNPMConfigVariants(
+ makeBaseNPMConfig({
+ hasBundles: true,
+ packageSpecificConfig: {
+ output: {
+ // set exports to 'named' or 'auto' so that rollup doesn't warn
+ exports: 'named',
+ // set preserveModules to false because for feedback we actually want
+ // to bundle everything into one file.
+ preserveModules: false,
+ },
+ },
+ sucrase: {
+ jsxPragma: 'h',
+ jsxFragmentPragma: 'Fragment',
+ },
+ }),
+);
diff --git a/packages/feedback-modal/scripts/shim-preact-export.js b/packages/feedback-modal/scripts/shim-preact-export.js
new file mode 100644
index 000000000000..bd74e4da0a05
--- /dev/null
+++ b/packages/feedback-modal/scripts/shim-preact-export.js
@@ -0,0 +1,75 @@
+// preact does not support more modern TypeScript versions, which breaks our users that depend on older
+// TypeScript versions. To fix this, we shim the types from preact to be any and remove the dependency on preact
+// for types directly. This script is meant to be run after the build/npm/types-ts3.8 directory is created.
+
+// Path: build/npm/types-ts3.8/global.d.ts
+
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * This regex looks for preact imports we can replace and shim out.
+ *
+ * Example:
+ * import { ComponentChildren, VNode } from 'preact';
+ */
+const preactImportRegex = /import\s*{\s*([\w\s,]+)\s*}\s*from\s*'preact'\s*;?/;
+
+function walk(dir) {
+ const files = fs.readdirSync(dir);
+ files.forEach(file => {
+ const filePath = path.join(dir, file);
+ const stat = fs.lstatSync(filePath);
+ if (stat.isDirectory()) {
+ walk(filePath);
+ } else {
+ if (filePath.endsWith('.d.ts')) {
+ const content = fs.readFileSync(filePath, 'utf8');
+ const capture = preactImportRegex.exec(content);
+ if (capture) {
+ const groups = capture[1].split(',').map(s => s.trim());
+
+ // This generates a shim snippet to replace the type imports from preact
+ // It generates a snippet based on the capture groups of preactImportRegex.
+ //
+ // Example:
+ //
+ // import type { ComponentChildren, VNode } from 'preact';
+ // becomes
+ // type ComponentChildren: any;
+ // type VNode: any;
+ const snippet = groups.reduce((acc, curr) => {
+ const searchableValue = curr.includes(' as ') ? curr.split(' as ')[1] : curr;
+
+ // look to see if imported as value, then we have to use declare const
+ if (content.includes(`typeof ${searchableValue}`)) {
+ return `${acc}declare const ${searchableValue}: any;\n`;
+ }
+
+ // look to see if generic type like Foo
+ if (content.includes(`${searchableValue}<`)) {
+ return `${acc}type ${searchableValue} = any;\n`;
+ }
+
+ // otherwise we can just leave as type
+ return `${acc}type ${searchableValue} = any;\n`;
+ }, '');
+
+ // we then can remove the import from preact
+ const newContent = content.replace(preactImportRegex, '// replaced import from preact');
+
+ // and write the new content to the file
+ fs.writeFileSync(filePath, snippet + newContent, 'utf8');
+ }
+ }
+ }
+ });
+}
+
+function run() {
+ // recurse through build/npm/types-ts3.8 directory
+ const dir = path.join('build', 'npm', 'types-ts3.8');
+ walk(dir);
+}
+
+run();
diff --git a/packages/feedback-modal/src/index.ts b/packages/feedback-modal/src/index.ts
new file mode 100644
index 000000000000..eff7430a6050
--- /dev/null
+++ b/packages/feedback-modal/src/index.ts
@@ -0,0 +1 @@
+export { feedbackModalIntegration } from './modal/integration';
diff --git a/packages/feedback-modal/src/modal/integration.test.ts b/packages/feedback-modal/src/modal/integration.test.ts
new file mode 100644
index 000000000000..d9eedd59c0f3
--- /dev/null
+++ b/packages/feedback-modal/src/modal/integration.test.ts
@@ -0,0 +1,8 @@
+import { feedbackModalIntegration } from './integration';
+
+describe('feedbackModalIntegration', () => {
+ it('should have createDialog', () => {
+ const instance = feedbackModalIntegration();
+ expect(instance).toHaveProperty('createDialog');
+ });
+});
diff --git a/packages/feedback-modal/src/modal/integration.ts b/packages/feedback-modal/src/modal/integration.ts
new file mode 100644
index 000000000000..f9e8a9ad64be
--- /dev/null
+++ b/packages/feedback-modal/src/modal/integration.ts
@@ -0,0 +1,15 @@
+import type { Integration, IntegrationFn } from '@sentry/types';
+
+export interface FeedbackModalIntegration extends Integration {
+ createDialog: unknown;
+}
+
+export const feedbackModalIntegration = ((): FeedbackModalIntegration => {
+ return {
+ name: 'FeedbackModal',
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ setupOnce() {},
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ createDialog: () => {}, // TODO(ryan953): port this over from packages/feedback/src/modal
+ };
+}) satisfies IntegrationFn;
diff --git a/packages/feedback-modal/tsconfig.json b/packages/feedback-modal/tsconfig.json
new file mode 100644
index 000000000000..c1fc08578508
--- /dev/null
+++ b/packages/feedback-modal/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "module": "esnext",
+
+ /* Preact Config */
+ "jsx": "react-jsx",
+ "jsxImportSource": "preact",
+ "skipLibCheck": true,
+ "baseUrl": "./",
+ "paths": {
+ "react": ["./node_modules/preact/compat/"],
+ "react-dom": ["./node_modules/preact/compat/"]
+ }
+ },
+ "include": ["src/**/*.ts","src/**/*.tsx"]
+}
diff --git a/packages/feedback-modal/tsconfig.test.json b/packages/feedback-modal/tsconfig.test.json
new file mode 100644
index 000000000000..ad87caa06c48
--- /dev/null
+++ b/packages/feedback-modal/tsconfig.test.json
@@ -0,0 +1,15 @@
+{
+ "extends": "./tsconfig.json",
+
+ "include": ["test/**/*.ts", "jest.config.ts", "jest.setup.ts"],
+
+ "compilerOptions": {
+ "types": ["node", "jest"],
+ "esModuleInterop": true,
+ "allowJs": true,
+ "noImplicitAny": true,
+ "noImplicitThis": false,
+ "strictNullChecks": true,
+ "strictPropertyInitialization": false
+ }
+}
diff --git a/packages/feedback-modal/tsconfig.types.json b/packages/feedback-modal/tsconfig.types.json
new file mode 100644
index 000000000000..374fd9bc9364
--- /dev/null
+++ b/packages/feedback-modal/tsconfig.types.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "build/npm/types"
+ }
+}
diff --git a/packages/feedback-screenshot/.eslintignore b/packages/feedback-screenshot/.eslintignore
new file mode 100644
index 000000000000..b38db2f296ff
--- /dev/null
+++ b/packages/feedback-screenshot/.eslintignore
@@ -0,0 +1,2 @@
+node_modules/
+build/
diff --git a/packages/feedback-screenshot/.eslintrc.js b/packages/feedback-screenshot/.eslintrc.js
new file mode 100644
index 000000000000..0b547ffc828c
--- /dev/null
+++ b/packages/feedback-screenshot/.eslintrc.js
@@ -0,0 +1,16 @@
+// Note: All paths are relative to the directory in which eslint is being run, rather than the directory where this file
+// lives
+
+// ESLint config docs: https://eslint.org/docs/user-guide/configuring/
+
+module.exports = {
+ extends: ['../../.eslintrc.js'],
+ overrides: [
+ {
+ files: ['jest.setup.ts', 'jest.config.ts'],
+ parserOptions: {
+ project: ['tsconfig.test.json'],
+ },
+ },
+ ],
+};
diff --git a/packages/feedback-screenshot/.gitignore b/packages/feedback-screenshot/.gitignore
new file mode 100644
index 000000000000..363d3467c6fa
--- /dev/null
+++ b/packages/feedback-screenshot/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+/*.tgz
+.eslintcache
+build
diff --git a/packages/feedback-screenshot/LICENSE b/packages/feedback-screenshot/LICENSE
new file mode 100644
index 000000000000..ea5e82344f87
--- /dev/null
+++ b/packages/feedback-screenshot/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2024 Sentry (https://sentry.io) and individual contributors. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/feedback-screenshot/README.md b/packages/feedback-screenshot/README.md
new file mode 100644
index 000000000000..f4949a12b0d1
--- /dev/null
+++ b/packages/feedback-screenshot/README.md
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+# Sentry Integration for Feedback
+
+This integration supports our browser feedback SDK allowing us to code-split heavy UI components as needed.
+
+For the primary Feedback Integration see
+[Sentry Feedback SDK](https://github.com/getsentry/sentry-javascript/tree/develop/packages/feedback)
+
+Note: This package is only meant to be used internally.
diff --git a/packages/feedback-screenshot/jest.config.js b/packages/feedback-screenshot/jest.config.js
new file mode 100644
index 000000000000..cd02790794a7
--- /dev/null
+++ b/packages/feedback-screenshot/jest.config.js
@@ -0,0 +1,6 @@
+const baseConfig = require('../../jest/jest.config.js');
+
+module.exports = {
+ ...baseConfig,
+ testEnvironment: 'jsdom',
+};
diff --git a/packages/feedback-screenshot/package.json b/packages/feedback-screenshot/package.json
new file mode 100644
index 000000000000..e29be49cb539
--- /dev/null
+++ b/packages/feedback-screenshot/package.json
@@ -0,0 +1,76 @@
+{
+ "name": "@sentry-internal/feedback-screenshot",
+ "version": "8.0.0-alpha.9",
+ "description": "Sentry SDK integration for user feedback",
+ "repository": "git://github.com/getsentry/sentry-javascript.git",
+ "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/feedback-screenshot",
+ "author": "Sentry",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.18"
+ },
+ "files": [
+ "cjs",
+ "esm",
+ "types",
+ "types-ts3.8"
+ ],
+ "main": "build/npm/cjs/index.js",
+ "module": "build/npm/esm/index.js",
+ "types": "build/npm/types/index.d.ts",
+ "exports": {
+ "./package.json": "./package.json",
+ ".": {
+ "import": {
+ "types": "./build/npm/types/index.d.ts",
+ "default": "./build/npm/esm/index.js"
+ },
+ "require": {
+ "types": "./build/npm/types/index.d.ts",
+ "default": "./build/npm/cjs/index.js"
+ }
+ }
+ },
+ "typesVersions": {
+ "<4.9": {
+ "build/npm/types/index.d.ts": [
+ "build/npm/types-ts3.8/index.d.ts"
+ ]
+ }
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@sentry/core": "8.0.0-alpha.9",
+ "@sentry/types": "8.0.0-alpha.9",
+ "@sentry/utils": "8.0.0-alpha.9",
+ "preact": "^10.19.4"
+ },
+ "scripts": {
+ "build": "run-p build:transpile build:types build:bundle",
+ "build:transpile": "rollup -c rollup.npm.config.mjs",
+ "build:bundle": "rollup -c rollup.bundle.config.mjs",
+ "build:dev": "run-p build:transpile build:types",
+ "build:types": "run-s build:types:core build:types:downlevel",
+ "build:types:core": "tsc -p tsconfig.types.json",
+ "build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8 && yarn node ./scripts/shim-preact-export.js",
+ "build:watch": "run-p build:transpile:watch build:bundle:watch build:types:watch",
+ "build:dev:watch": "run-p build:transpile:watch build:types:watch",
+ "build:transpile:watch": "yarn build:transpile --watch",
+ "build:bundle:watch": "yarn build:bundle --watch",
+ "build:types:watch": "tsc -p tsconfig.types.json --watch",
+ "build:tarball": "ts-node ../../scripts/prepack.ts --bundles && npm pack ./build/npm",
+ "circularDepCheck": "madge --circular src/index.ts",
+ "clean": "rimraf build sentry-feedback-screenshot-*.tgz",
+ "fix": "eslint . --format stylish --fix",
+ "lint": "eslint . --format stylish",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "yalc:publish": "ts-node ../../scripts/prepack.ts --bundles && yalc publish ./build/npm --push --sig"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ },
+ "sideEffects": false
+}
diff --git a/packages/feedback-screenshot/rollup.bundle.config.mjs b/packages/feedback-screenshot/rollup.bundle.config.mjs
new file mode 100644
index 000000000000..5e2422f0bcd0
--- /dev/null
+++ b/packages/feedback-screenshot/rollup.bundle.config.mjs
@@ -0,0 +1,15 @@
+import { makeBaseBundleConfig, makeBundleConfigVariants } from '@sentry-internal/rollup-utils';
+
+export default makeBundleConfigVariants(
+ makeBaseBundleConfig({
+ bundleType: 'addon',
+ entrypoints: ['src/index.ts'],
+ jsVersion: 'es6',
+ licenseTitle: '@sentry-internal/feedback-screenshot',
+ outputFileBase: () => 'bundles/feedback-screenshot',
+ sucrase: {
+ jsxPragma: 'h',
+ jsxFragmentPragma: 'Fragment',
+ },
+ }),
+);
diff --git a/packages/feedback-screenshot/rollup.npm.config.mjs b/packages/feedback-screenshot/rollup.npm.config.mjs
new file mode 100644
index 000000000000..3dc031c5ff82
--- /dev/null
+++ b/packages/feedback-screenshot/rollup.npm.config.mjs
@@ -0,0 +1,20 @@
+import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils';
+
+export default makeNPMConfigVariants(
+ makeBaseNPMConfig({
+ hasBundles: true,
+ packageSpecificConfig: {
+ output: {
+ // set exports to 'named' or 'auto' so that rollup doesn't warn
+ exports: 'named',
+ // set preserveModules to false because for feedback we actually want
+ // to bundle everything into one file.
+ preserveModules: false,
+ },
+ },
+ sucrase: {
+ jsxPragma: 'h',
+ jsxFragmentPragma: 'Fragment',
+ },
+ }),
+);
diff --git a/packages/feedback-screenshot/scripts/shim-preact-export.js b/packages/feedback-screenshot/scripts/shim-preact-export.js
new file mode 100644
index 000000000000..bd74e4da0a05
--- /dev/null
+++ b/packages/feedback-screenshot/scripts/shim-preact-export.js
@@ -0,0 +1,75 @@
+// preact does not support more modern TypeScript versions, which breaks our users that depend on older
+// TypeScript versions. To fix this, we shim the types from preact to be any and remove the dependency on preact
+// for types directly. This script is meant to be run after the build/npm/types-ts3.8 directory is created.
+
+// Path: build/npm/types-ts3.8/global.d.ts
+
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * This regex looks for preact imports we can replace and shim out.
+ *
+ * Example:
+ * import { ComponentChildren, VNode } from 'preact';
+ */
+const preactImportRegex = /import\s*{\s*([\w\s,]+)\s*}\s*from\s*'preact'\s*;?/;
+
+function walk(dir) {
+ const files = fs.readdirSync(dir);
+ files.forEach(file => {
+ const filePath = path.join(dir, file);
+ const stat = fs.lstatSync(filePath);
+ if (stat.isDirectory()) {
+ walk(filePath);
+ } else {
+ if (filePath.endsWith('.d.ts')) {
+ const content = fs.readFileSync(filePath, 'utf8');
+ const capture = preactImportRegex.exec(content);
+ if (capture) {
+ const groups = capture[1].split(',').map(s => s.trim());
+
+ // This generates a shim snippet to replace the type imports from preact
+ // It generates a snippet based on the capture groups of preactImportRegex.
+ //
+ // Example:
+ //
+ // import type { ComponentChildren, VNode } from 'preact';
+ // becomes
+ // type ComponentChildren: any;
+ // type VNode: any;
+ const snippet = groups.reduce((acc, curr) => {
+ const searchableValue = curr.includes(' as ') ? curr.split(' as ')[1] : curr;
+
+ // look to see if imported as value, then we have to use declare const
+ if (content.includes(`typeof ${searchableValue}`)) {
+ return `${acc}declare const ${searchableValue}: any;\n`;
+ }
+
+ // look to see if generic type like Foo
+ if (content.includes(`${searchableValue}<`)) {
+ return `${acc}type ${searchableValue} = any;\n`;
+ }
+
+ // otherwise we can just leave as type
+ return `${acc}type ${searchableValue} = any;\n`;
+ }, '');
+
+ // we then can remove the import from preact
+ const newContent = content.replace(preactImportRegex, '// replaced import from preact');
+
+ // and write the new content to the file
+ fs.writeFileSync(filePath, snippet + newContent, 'utf8');
+ }
+ }
+ }
+ });
+}
+
+function run() {
+ // recurse through build/npm/types-ts3.8 directory
+ const dir = path.join('build', 'npm', 'types-ts3.8');
+ walk(dir);
+}
+
+run();
diff --git a/packages/feedback-screenshot/src/index.ts b/packages/feedback-screenshot/src/index.ts
new file mode 100644
index 000000000000..2582220645d1
--- /dev/null
+++ b/packages/feedback-screenshot/src/index.ts
@@ -0,0 +1 @@
+export { feedbackScreenshotIntegration } from './screenshot/integration';
diff --git a/packages/feedback-screenshot/src/screenshot/integration.test.ts b/packages/feedback-screenshot/src/screenshot/integration.test.ts
new file mode 100644
index 000000000000..43acdd770670
--- /dev/null
+++ b/packages/feedback-screenshot/src/screenshot/integration.test.ts
@@ -0,0 +1,8 @@
+import { feedbackScreenshotIntegration } from './integration';
+
+describe('feedbackScreenshotIntegration', () => {
+ it('should have createInput', () => {
+ const instance = feedbackScreenshotIntegration();
+ expect(instance).toHaveProperty('createInput');
+ });
+});
diff --git a/packages/feedback-screenshot/src/screenshot/integration.ts b/packages/feedback-screenshot/src/screenshot/integration.ts
new file mode 100644
index 000000000000..ada4e7ec8b65
--- /dev/null
+++ b/packages/feedback-screenshot/src/screenshot/integration.ts
@@ -0,0 +1,15 @@
+import type { Integration, IntegrationFn } from '@sentry/types';
+
+export interface FeedbackScreenshotIntegration extends Integration {
+ createInput: unknown;
+}
+
+export const feedbackScreenshotIntegration = (() => {
+ return {
+ name: 'FeedbackScreenshot',
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ setupOnce() {},
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ createInput: () => {}, // TODO(ryan953): port this over from packages/feedback/src/screenshot
+ };
+}) satisfies IntegrationFn;
diff --git a/packages/feedback-screenshot/tsconfig.json b/packages/feedback-screenshot/tsconfig.json
new file mode 100644
index 000000000000..c1fc08578508
--- /dev/null
+++ b/packages/feedback-screenshot/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "module": "esnext",
+
+ /* Preact Config */
+ "jsx": "react-jsx",
+ "jsxImportSource": "preact",
+ "skipLibCheck": true,
+ "baseUrl": "./",
+ "paths": {
+ "react": ["./node_modules/preact/compat/"],
+ "react-dom": ["./node_modules/preact/compat/"]
+ }
+ },
+ "include": ["src/**/*.ts","src/**/*.tsx"]
+}
diff --git a/packages/feedback-screenshot/tsconfig.test.json b/packages/feedback-screenshot/tsconfig.test.json
new file mode 100644
index 000000000000..ad87caa06c48
--- /dev/null
+++ b/packages/feedback-screenshot/tsconfig.test.json
@@ -0,0 +1,15 @@
+{
+ "extends": "./tsconfig.json",
+
+ "include": ["test/**/*.ts", "jest.config.ts", "jest.setup.ts"],
+
+ "compilerOptions": {
+ "types": ["node", "jest"],
+ "esModuleInterop": true,
+ "allowJs": true,
+ "noImplicitAny": true,
+ "noImplicitThis": false,
+ "strictNullChecks": true,
+ "strictPropertyInitialization": false
+ }
+}
diff --git a/packages/feedback-screenshot/tsconfig.types.json b/packages/feedback-screenshot/tsconfig.types.json
new file mode 100644
index 000000000000..374fd9bc9364
--- /dev/null
+++ b/packages/feedback-screenshot/tsconfig.types.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "build/npm/types"
+ }
+}
diff --git a/packages/integration-shims/src/Feedback.ts b/packages/integration-shims/src/Feedback.ts
index e6bf1607927b..b0bb3f564779 100644
--- a/packages/integration-shims/src/Feedback.ts
+++ b/packages/integration-shims/src/Feedback.ts
@@ -13,8 +13,12 @@ const FEEDBACK_INTEGRATION_METHODS = [
] as const;
type FeedbackSpecificMethods = Record<(typeof FEEDBACK_INTEGRATION_METHODS)[number], () => void>;
+type FeedbackModalSpecificMethods = { createDialog: () => void };
+type FeedbackScreenshotSpecificMethods = { createInput: () => void };
interface FeedbackIntegration extends Integration, FeedbackSpecificMethods {}
+interface FeedbackModalIntegration extends Integration, FeedbackModalSpecificMethods {}
+interface FeedbackScreenshotIntegration extends Integration, FeedbackScreenshotSpecificMethods {}
/**
* This is a shim for the Feedback integration.
@@ -35,3 +39,27 @@ export function feedbackIntegrationShim(_options: unknown): FeedbackIntegration
}, {} as FeedbackSpecificMethods) as FeedbackSpecificMethods),
};
}
+
+/**
+ * This is a shim for the FeedbackModal integration.
+ * It is needed in order for the CDN bundles to continue working when users add/remove feedback
+ * from it, without changing their config. This is necessary for the loader mechanism.
+ */
+export function feedbackModalIntegrationShim(): FeedbackModalIntegration {
+ return {
+ name: 'FeedbackModal',
+ createDialog: FAKE_FUNCTION,
+ };
+}
+
+/**
+ * This is a shim for the FeedbackScreenshot integration.
+ * It is needed in order for the CDN bundles to continue working when users add/remove feedback
+ * from it, without changing their config. This is necessary for the loader mechanism.
+ */
+export function feedbackScreenshotIntegrationShim(): FeedbackScreenshotIntegration {
+ return {
+ name: 'FeedbackScreenshot',
+ createInput: FAKE_FUNCTION,
+ };
+}
diff --git a/packages/integration-shims/src/index.ts b/packages/integration-shims/src/index.ts
index 5dfb2caabea1..f3c0937ff9d4 100644
--- a/packages/integration-shims/src/index.ts
+++ b/packages/integration-shims/src/index.ts
@@ -1,4 +1,4 @@
-export { feedbackIntegrationShim } from './Feedback';
+export { feedbackIntegrationShim, feedbackModalIntegrationShim, feedbackScreenshotIntegrationShim } from './Feedback';
export { replayIntegrationShim } from './Replay';
export {
browserTracingIntegrationShim,
diff --git a/packages/nextjs/test/integration/package.json b/packages/nextjs/test/integration/package.json
index f4c547b5b687..0d17d6a049dc 100644
--- a/packages/nextjs/test/integration/package.json
+++ b/packages/nextjs/test/integration/package.json
@@ -34,6 +34,8 @@
"@sentry-internal/replay": "file:../../../replay-internal",
"@sentry-internal/replay-canvas": "file:../../../replay-canvas",
"@sentry-internal/feedback": "file:../../../feedback",
+ "@sentry-internal/feedback-modal": "file:../../../feedback-modal",
+ "@sentry-internal/feedback-screenshot": "file:../../../feedback-screenshot",
"@sentry/types": "file:../../../types",
"@sentry/utils": "file:../../../utils",
"@sentry/vercel-edge": "file:../../../vercel-edge"
diff --git a/packages/remix/test/integration/package.json b/packages/remix/test/integration/package.json
index 63560ec64e8b..f0f2bb631553 100644
--- a/packages/remix/test/integration/package.json
+++ b/packages/remix/test/integration/package.json
@@ -32,6 +32,8 @@
"@sentry-internal/replay": "file:../../../replay-internal",
"@sentry-internal/replay-canvas": "file:../../../replay-canvas",
"@sentry-internal/feedback": "file:../../../feedback",
+ "@sentry-internal/feedback-modal": "file:../../../feedback-modal",
+ "@sentry-internal/feedback-screenshot": "file:../../../feedback-screenshot",
"@sentry/types": "file:../../../types",
"@sentry/utils": "file:../../../utils",
"@vanilla-extract/css": "1.13.0",