diff --git a/.size-limit.js b/.size-limit.js index 5e94a923e656..cbc2f411b628 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -61,6 +61,27 @@ module.exports = [ gzip: true, limit: '50 KB', }, + { + name: '@sentry/browser (incl. feedback2Integration) - Webpack (gzipped)', + path: 'packages/browser/build/npm/esm/index.js', + import: '{ init, feedback2Integration }', + gzip: true, + limit: '50 KB', + }, + { + name: '@sentry/browser (incl. feedback2ModalIntegration) - Webpack (gzipped)', + path: 'packages/browser/build/npm/esm/index.js', + import: '{ init, feedback2Integration, feedback2ModalIntegration }', + gzip: true, + limit: '50 KB', + }, + { + name: '@sentry/browser (incl. feedback2ScreenshotIntegration) - Webpack (gzipped)', + path: 'packages/browser/build/npm/esm/index.js', + import: '{ init, feedback2Integration, feedback2ModalIntegration, feedback2ScreenshotIntegration }', + gzip: true, + limit: '50 KB', + }, { name: '@sentry/browser (incl. sendFeedback) - Webpack (gzipped)', path: 'packages/browser/build/npm/esm/index.js', diff --git a/package.json b/package.json index ef36567d47e3..414d4d00713b 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "packages/eslint-plugin-sdk", "packages/feedback", "packages/feedback-screenshot", + "packages/feedback2", "packages/gatsby", "packages/hub", "packages/integrations", diff --git a/packages/feedback2/.eslintignore b/packages/feedback2/.eslintignore new file mode 100644 index 000000000000..b38db2f296ff --- /dev/null +++ b/packages/feedback2/.eslintignore @@ -0,0 +1,2 @@ +node_modules/ +build/ diff --git a/packages/feedback2/.eslintrc.js b/packages/feedback2/.eslintrc.js new file mode 100644 index 000000000000..ef2ed992265c --- /dev/null +++ b/packages/feedback2/.eslintrc.js @@ -0,0 +1,25 @@ +// 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: ['src/**/*.ts', 'src/**/*.tsx'], + rules: { + '@sentry-internal/sdk/no-unsupported-es6-methods': 'off', + }, + }, + { + files: ['jest.setup.ts', 'jest.config.ts'], + parserOptions: { + project: ['tsconfig.test.json'], + }, + rules: { + 'no-console': 'off', + }, + }, + ], +}; diff --git a/packages/feedback2/.gitignore b/packages/feedback2/.gitignore new file mode 100644 index 000000000000..363d3467c6fa --- /dev/null +++ b/packages/feedback2/.gitignore @@ -0,0 +1,4 @@ +node_modules +/*.tgz +.eslintcache +build diff --git a/packages/feedback2/LICENSE b/packages/feedback2/LICENSE new file mode 100644 index 000000000000..d11896ba1181 --- /dev/null +++ b/packages/feedback2/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2023 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/feedback2/README.md b/packages/feedback2/README.md new file mode 100644 index 000000000000..fb5b20400a71 --- /dev/null +++ b/packages/feedback2/README.md @@ -0,0 +1,20 @@ +

+ + Sentry + +

+ +# Sentry Integration for Feedback + +This SDK is **considered experimental and in a beta state**. It may experience breaking changes, and may be discontinued at any time. Please reach out on +[GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback/concerns. + +To view Feedback in Sentry, your [Sentry organization must be an early adopter](https://docs.sentry.io/product/accounts/early-adopter-features/). + +## Installation + +Please read the [offical integration documentation](https://docs.sentry.io/platforms/javascript/user-feedback/) for installation instructions. + +## Configuration + +The Feedback integration is highly customizable, please read the [official integration documentation](https://docs.sentry.io/platforms/javascript/user-feedback/configuration/) for the most up-to-date configuration options. diff --git a/packages/feedback2/jest.config.js b/packages/feedback2/jest.config.js new file mode 100644 index 000000000000..cd02790794a7 --- /dev/null +++ b/packages/feedback2/jest.config.js @@ -0,0 +1,6 @@ +const baseConfig = require('../../jest/jest.config.js'); + +module.exports = { + ...baseConfig, + testEnvironment: 'jsdom', +}; diff --git a/packages/feedback2/package.json b/packages/feedback2/package.json new file mode 100644 index 000000000000..416ba4436049 --- /dev/null +++ b/packages/feedback2/package.json @@ -0,0 +1,64 @@ +{ + "name": "@sentry-internal/feedback2", + "version": "7.100.0", + "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", + "author": "Sentry", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "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", + "typesVersions": { + "<4.9": { + "build/npm/types/index.d.ts": [ + "build/npm/types-ts3.8/index.d.ts" + ] + } + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@sentry/core": "7.100.0", + "@sentry/types": "7.100.0", + "@sentry/utils": "7.100.0", + "preact": "^10.19.4", + "preact-compat": "^3.19.0" + }, + "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", + "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-*.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/feedback2/rollup.bundle.config.mjs b/packages/feedback2/rollup.bundle.config.mjs new file mode 100644 index 000000000000..32c9684415bf --- /dev/null +++ b/packages/feedback2/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/feedback2', + outputFileBase: () => 'bundles/feedback2', + sucrase: { + jsxPragma: 'h', + jsxFragmentPragma: 'Fragment', + }, + }), +); diff --git a/packages/feedback2/rollup.npm.config.mjs b/packages/feedback2/rollup.npm.config.mjs new file mode 100644 index 000000000000..80f2406e78db --- /dev/null +++ b/packages/feedback2/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/feedback2/src/constants/index.ts b/packages/feedback2/src/constants/index.ts new file mode 100644 index 000000000000..9804fdedf431 --- /dev/null +++ b/packages/feedback2/src/constants/index.ts @@ -0,0 +1,27 @@ +import { GLOBAL_OBJ } from '@sentry/utils'; + +export { DEFAULT_THEME } from './theme'; + +// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser` +// prevents the browser package from being bundled in the CDN bundle, and avoids a +// circular dependency between the browser and feedback packages +export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; +export const DOCUMENT = WINDOW.document; +export const NAVIGATOR = WINDOW.navigator; + +export const ACTOR_LABEL = 'Report a Bug'; +export const CANCEL_BUTTON_LABEL = 'Cancel'; +export const SUBMIT_BUTTON_LABEL = 'Send Bug Report'; +export const FORM_TITLE = 'Report a Bug'; +export const EMAIL_PLACEHOLDER = 'your.email@example.org'; +export const EMAIL_LABEL = 'Email'; +export const MESSAGE_PLACEHOLDER = "What's the bug? What did you expect?"; +export const MESSAGE_LABEL = 'Description'; +export const NAME_PLACEHOLDER = 'Your Name'; +export const NAME_LABEL = 'Name'; +export const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!'; + +export const FEEDBACK_WIDGET_SOURCE = 'widget'; +export const FEEDBACK_API_SOURCE = 'api'; + +export const SUCCESS_MESSAGE_TIMEOUT = 5000; diff --git a/packages/feedback2/src/constants/theme.ts b/packages/feedback2/src/constants/theme.ts new file mode 100644 index 000000000000..7fff31f48964 --- /dev/null +++ b/packages/feedback2/src/constants/theme.ts @@ -0,0 +1,55 @@ +const LIGHT_BACKGROUND = '#ffffff'; +const INHERIT = 'inherit'; +const SUBMIT_COLOR = 'rgba(108, 95, 199, 1)'; + +export const LIGHT_THEME = { + fontFamily: "system-ui, 'Helvetica Neue', Arial, sans-serif", + fontSize: '14px', + + background: LIGHT_BACKGROUND, + backgroundHover: '#f6f6f7', + foreground: '#2b2233', + border: '1.5px solid rgba(41, 35, 47, 0.13)', + borderRadius: '12px', + boxShadow: '0px 4px 24px 0px rgba(43, 34, 51, 0.12)', + + success: '#268d75', + error: '#df3338', + + submitBackground: 'rgba(88, 74, 192, 1)', + submitBackgroundHover: SUBMIT_COLOR, + submitBorder: SUBMIT_COLOR, + submitOutlineFocus: '#29232f', + submitForeground: LIGHT_BACKGROUND, + submitForegroundHover: LIGHT_BACKGROUND, + + cancelBackground: 'transparent', + cancelBackgroundHover: 'var(--background-hover)', + cancelBorder: 'var(--border)', + cancelOutlineFocus: 'var(--input-outline-focus)', + cancelForeground: 'var(--foreground)', + cancelForegroundHover: 'var(--foreground)', + + inputBackground: INHERIT, + inputForeground: INHERIT, + inputBorder: 'var(--border)', + inputOutlineFocus: SUBMIT_COLOR, + + formBorderRadius: '20px', + formContentBorderRadius: '6px', +}; + +export const DEFAULT_THEME = { + light: LIGHT_THEME, + dark: { + ...LIGHT_THEME, + + background: '#29232f', + backgroundHover: '#352f3b', + foreground: '#ebe6ef', + border: '1.5px solid rgba(235, 230, 239, 0.15)', + + success: '#2da98c', + error: '#f55459', + }, +}; diff --git a/packages/feedback2/src/core/components/Actor.css.ts b/packages/feedback2/src/core/components/Actor.css.ts new file mode 100644 index 000000000000..9ae8df503cc9 --- /dev/null +++ b/packages/feedback2/src/core/components/Actor.css.ts @@ -0,0 +1,63 @@ +import { DOCUMENT } from '../../constants'; + +/** + * Creates