diff --git a/.changeset/add-on-prettify-callback.md b/.changeset/add-on-prettify-callback.md new file mode 100644 index 00000000000..40640e5571c --- /dev/null +++ b/.changeset/add-on-prettify-callback.md @@ -0,0 +1,6 @@ +--- +"@graphiql/react": minor +"graphiql": minor +--- + +Add support for `onPrettifyQuery` callback to enable customised query formatting diff --git a/.changeset/breezy-chicken-crash.md b/.changeset/breezy-chicken-crash.md new file mode 100644 index 00000000000..1a3bff1737e --- /dev/null +++ b/.changeset/breezy-chicken-crash.md @@ -0,0 +1,12 @@ +--- +'@graphiql/plugin-code-exporter': major +--- + +`style.css` import was changed + +## Migration + +```diff +-import '@graphiql/plugin-code-exporter/dist/style.css'; ++import '@graphiql/plugin-code-exporter/style.css'; +``` diff --git a/.changeset/chatty-spoons-accept.md b/.changeset/chatty-spoons-accept.md new file mode 100644 index 00000000000..64f5e3bab15 --- /dev/null +++ b/.changeset/chatty-spoons-accept.md @@ -0,0 +1,8 @@ +--- +'@graphiql/plugin-code-exporter': minor +'@graphiql/plugin-explorer': minor +'@graphiql/react': minor +'graphiql': minor +--- + +Update GraphiQL CDN example using ESM-based CDN esm.sh diff --git a/.changeset/clean-lamps-bow.md b/.changeset/clean-lamps-bow.md new file mode 100644 index 00000000000..c5df42e4770 --- /dev/null +++ b/.changeset/clean-lamps-bow.md @@ -0,0 +1,8 @@ +--- +'@graphiql/plugin-code-exporter': major +'@graphiql/plugin-explorer': major +'@graphiql/react': minor +'graphiql': major +--- + +drop commonjs build files diff --git a/.changeset/few-steaks-clap.md b/.changeset/few-steaks-clap.md new file mode 100644 index 00000000000..7eff915641d --- /dev/null +++ b/.changeset/few-steaks-clap.md @@ -0,0 +1,5 @@ +--- +'graphiql': major +--- + +show tabs even there is only 1 tab diff --git a/.changeset/flat-lies-heal.md b/.changeset/flat-lies-heal.md new file mode 100644 index 00000000000..dfe39818386 --- /dev/null +++ b/.changeset/flat-lies-heal.md @@ -0,0 +1,7 @@ +--- +'@graphiql/react': minor +'@graphiql/plugin-explorer': minor +'@graphiql/plugin-code-exporter': minor +--- + +generate types with `vite-plugin-dts` diff --git a/.changeset/gentle-bugs-mix.md b/.changeset/gentle-bugs-mix.md new file mode 100644 index 00000000000..9bb1ae56ab2 --- /dev/null +++ b/.changeset/gentle-bugs-mix.md @@ -0,0 +1,19 @@ +--- +'graphiql': major +--- + +remove default export + +## Migration + +### Before + +```jsx +import GraphiQL from 'graphiql' +``` + +### After + +```jsx +import { GraphiQL } from 'graphiql' +``` diff --git a/.changeset/gold-cooks-design.md b/.changeset/gold-cooks-design.md new file mode 100644 index 00000000000..d5d1c00d660 --- /dev/null +++ b/.changeset/gold-cooks-design.md @@ -0,0 +1,10 @@ +--- +'@graphiql/plugin-code-exporter': major +'@graphiql/plugin-explorer': major +'@graphiql/react': minor +'graphiql': major +--- + +- support react 19, drop support react 16 and react 17 +- replace deprecated `ReactDOM.unmountComponentAtNode()` and `ReactDOM.render()` with `root.unmount()` and `createRoot(container).render()` +- update `@radix-ui` and `@headlessui/react` dependencies diff --git a/.changeset/good-vans-refuse.md b/.changeset/good-vans-refuse.md new file mode 100644 index 00000000000..906325035d5 --- /dev/null +++ b/.changeset/good-vans-refuse.md @@ -0,0 +1,12 @@ +--- +'@graphiql/react': minor +--- + +`style.css` import was changed + +## Migration + +```diff +-import '@graphiql/react/dist/style.css'; ++import '@graphiql/react/style.css'; +``` diff --git a/.changeset/green-pugs-worry.md b/.changeset/green-pugs-worry.md new file mode 100644 index 00000000000..4342a6bc271 --- /dev/null +++ b/.changeset/green-pugs-worry.md @@ -0,0 +1,5 @@ +--- +'graphiql': major +--- + +remove `disableTabs` option diff --git a/.changeset/healthy-onions-bake.md b/.changeset/healthy-onions-bake.md new file mode 100644 index 00000000000..37a059e690e --- /dev/null +++ b/.changeset/healthy-onions-bake.md @@ -0,0 +1,5 @@ +--- +'@graphiql/plugin-explorer': patch +--- + +improve explorer styles diff --git a/.changeset/hungry-spiders-cheat.md b/.changeset/hungry-spiders-cheat.md new file mode 100644 index 00000000000..2f22a97f550 --- /dev/null +++ b/.changeset/hungry-spiders-cheat.md @@ -0,0 +1,5 @@ +--- +'graphiql': major +--- + +remove `data-testid="graphiql-container"` diff --git a/.changeset/late-trains-train.md b/.changeset/late-trains-train.md new file mode 100644 index 00000000000..e3e77c1b62a --- /dev/null +++ b/.changeset/late-trains-train.md @@ -0,0 +1,8 @@ +--- +'@graphiql/plugin-code-exporter': minor +'@graphiql/plugin-explorer': minor +'@graphiql/react': minor +'graphiql': minor +--- + +update `vite` and related dependencies diff --git a/.changeset/metal-glasses-bow.md b/.changeset/metal-glasses-bow.md new file mode 100644 index 00000000000..48c99bbf5c7 --- /dev/null +++ b/.changeset/metal-glasses-bow.md @@ -0,0 +1,5 @@ +--- +'graphiql': patch +--- + +update graphql to `16.9.0` and use vite `define` configuration to remove development code from cdn bundle diff --git a/.changeset/nine-meals-happen.md b/.changeset/nine-meals-happen.md new file mode 100644 index 00000000000..34b1551d197 --- /dev/null +++ b/.changeset/nine-meals-happen.md @@ -0,0 +1,6 @@ +--- +'@graphiql/plugin-code-exporter': patch +'@graphiql/plugin-explorer': patch +--- + +fix types incorrect types entry diff --git a/.changeset/old-zebras-knock.md b/.changeset/old-zebras-knock.md new file mode 100644 index 00000000000..a0109290d2e --- /dev/null +++ b/.changeset/old-zebras-knock.md @@ -0,0 +1,5 @@ +--- +'graphiql': minor +--- + +remove `.graphiql-session` class diff --git a/.changeset/olive-mice-hide.md b/.changeset/olive-mice-hide.md new file mode 100644 index 00000000000..2606c7cae1c --- /dev/null +++ b/.changeset/olive-mice-hide.md @@ -0,0 +1,6 @@ +--- +'graphiql': patch +'@graphiql/react': patch +--- + +Respect Markdown format: ignore single newline diff --git a/.changeset/orange-rivers-draw.md b/.changeset/orange-rivers-draw.md new file mode 100644 index 00000000000..f87e0f7e852 --- /dev/null +++ b/.changeset/orange-rivers-draw.md @@ -0,0 +1,9 @@ +--- +'@graphiql/plugin-code-exporter': patch +'@graphiql/plugin-explorer': patch +'@graphiql/react': patch +--- + +use `vite build --watch` instead of `vite` for `dev` script because we don't need development server for them + +do not use `vite-plugin-dts` when generating umd build diff --git a/.changeset/pink-moose-shake.md b/.changeset/pink-moose-shake.md new file mode 100644 index 00000000000..59273f6196b --- /dev/null +++ b/.changeset/pink-moose-shake.md @@ -0,0 +1,5 @@ +--- +'graphiql': patch +--- + +use `position: absolute` for `.graphiql-logo` class diff --git a/.changeset/poor-ghosts-jump.md b/.changeset/poor-ghosts-jump.md new file mode 100644 index 00000000000..79d454d52a5 --- /dev/null +++ b/.changeset/poor-ghosts-jump.md @@ -0,0 +1,13 @@ +--- +'@graphiql/plugin-explorer': major +--- + +`style.css` import was changed + +## Migration + +```diff +-import '@graphiql/plugin-explorer/dist/style.css'; ++import '@graphiql/plugin-explorer/style.css'; +``` + diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 00000000000..19ae22feaef --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,51 @@ +{ + "mode": "exit", + "tag": "alpha", + "initialVersions": { + "cm6-graphql": "0.0.15", + "codemirror-graphql": "2.0.13", + "graphiql": "3.4.0", + "@graphiql/plugin-code-exporter": "3.0.5", + "@graphiql/plugin-explorer": "3.1.1", + "@graphiql/react": "0.23.0", + "@graphiql/toolkit": "0.9.2", + "graphql-language-service": "5.2.2", + "graphql-language-service-cli": "3.4.2", + "graphql-language-service-server": "2.13.2", + "monaco-graphql": "1.5.3", + "vscode-graphql": "0.11.2", + "vscode-graphql-execution": "0.2.6", + "vscode-graphql-syntax": "1.3.6", + "example-graphiql-webpack": "0.0.0", + "example-monaco-graphql-nextjs": "0.0.0", + "example-monaco-graphql-react-vite": "0.0.0", + "example-monaco-graphql-webpack": "0.0.0" + }, + "changesets": [ + "add-on-prettify-callback", + "breezy-chicken-crash", + "few-steaks-clap", + "flat-lies-heal", + "gentle-bugs-mix", + "good-vans-refuse", + "green-pugs-worry", + "healthy-onions-bake", + "hungry-spiders-cheat", + "metal-glasses-bow", + "nine-meals-happen", + "old-zebras-knock", + "olive-mice-hide", + "orange-rivers-draw", + "pink-moose-shake", + "poor-ghosts-jump", + "red-papayas-fly", + "rich-jobs-kick", + "serious-forks-sip", + "spotty-bulldogs-confess", + "strong-ears-bake", + "thick-adults-leave", + "thirty-spoons-call", + "weak-dancers-jog", + "wicked-seas-laugh" + ] +} diff --git a/.changeset/red-papayas-fly.md b/.changeset/red-papayas-fly.md new file mode 100644 index 00000000000..2d02218e3b5 --- /dev/null +++ b/.changeset/red-papayas-fly.md @@ -0,0 +1,6 @@ +--- +'@graphiql/react': patch +'graphiql': patch +--- + +replace `overflow-y: scroll` with `overflow-y: auto` diff --git a/.changeset/rich-jobs-kick.md b/.changeset/rich-jobs-kick.md new file mode 100644 index 00000000000..602fd4c63c3 --- /dev/null +++ b/.changeset/rich-jobs-kick.md @@ -0,0 +1,21 @@ +--- +'graphiql': major +--- + +changed exports + +```diff +-graphiql/graphiql.css ++graphiql/style.css +``` + +changed cdn paths, `dist/index.umd.js` and `dist/style.css` are minified + +```diff +-https://unpkg.com/graphiql/graphiql.js +-https://unpkg.com/graphiql/graphiql.min.js ++https://unpkg.com/graphiql/dist/index.umd.js +-https://unpkg.com/graphiql/graphiql.css +-https://unpkg.com/graphiql/graphiql.min.css ++https://unpkg.com/graphiql/dist/style.css +``` diff --git a/.changeset/serious-forks-sip.md b/.changeset/serious-forks-sip.md new file mode 100644 index 00000000000..e7c0353f66f --- /dev/null +++ b/.changeset/serious-forks-sip.md @@ -0,0 +1,6 @@ +--- +'@graphiql/react': patch +'graphiql': patch +--- + +rollback `position: absolute` style for `.graphiql-logo` because tabs will behind logo diff --git a/.changeset/spotty-bulldogs-confess.md b/.changeset/spotty-bulldogs-confess.md new file mode 100644 index 00000000000..eed64fbd7f1 --- /dev/null +++ b/.changeset/spotty-bulldogs-confess.md @@ -0,0 +1,7 @@ +--- +'@graphiql/react': patch +'graphiql': patch +--- + +- prefer `location` over `window.location` +- prefer `navigator` over `window.navigator` diff --git a/.changeset/strong-ears-bake.md b/.changeset/strong-ears-bake.md new file mode 100644 index 00000000000..45ac76e3ebd --- /dev/null +++ b/.changeset/strong-ears-bake.md @@ -0,0 +1,5 @@ +--- +'graphiql': patch +--- + +use `right: var(--px-16)` instead of `right: 0` for `.graphiql-logo` diff --git a/.changeset/thick-adults-leave.md b/.changeset/thick-adults-leave.md new file mode 100644 index 00000000000..f18738c9905 --- /dev/null +++ b/.changeset/thick-adults-leave.md @@ -0,0 +1,5 @@ +--- +'@graphiql/react': minor +--- + +remove `createComponentGroup` utility in favour `Object.assign` diff --git a/.changeset/thirty-spoons-call.md b/.changeset/thirty-spoons-call.md new file mode 100644 index 00000000000..4853b541b98 --- /dev/null +++ b/.changeset/thirty-spoons-call.md @@ -0,0 +1,8 @@ +--- +"graphiql": major +"@graphiql/react": minor +--- + +- new looks of tabs + +- fix `disableTabs` when `Add tab` button is still shown diff --git a/.changeset/weak-dancers-jog.md b/.changeset/weak-dancers-jog.md new file mode 100644 index 00000000000..8b78fe25302 --- /dev/null +++ b/.changeset/weak-dancers-jog.md @@ -0,0 +1,79 @@ +--- +'graphiql': major +--- + +Remove `toolbar.additionalContent` and `toolbar.additionalComponent` props in favor of `GraphiQL.Toolbar` render props. + +## Migration from `toolbar.additionalContent` + +### Before + +```jsx +My button }} /> +``` + +### After + +```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + +``` + +## Migration from `toolbar.additionalComponent` + +### Before + +```jsx +My button; + }, + }} +/> +``` + +### After + +```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + +``` + +--- + +Additionally, you can sort default toolbar buttons in different order or remove unneeded buttons for you: + +```jsx + + + {({ prettify, copy }) => ( + <> + {copy /* Copy button will be first instead of default last */} + {/* Merge button is removed from toolbar */} + {prettify} + + )} + + +``` diff --git a/.changeset/wicked-seas-laugh.md b/.changeset/wicked-seas-laugh.md new file mode 100644 index 00000000000..3162059dcaf --- /dev/null +++ b/.changeset/wicked-seas-laugh.md @@ -0,0 +1,5 @@ +--- +'graphiql': patch +--- + +replace `Tooltip`s in tabs with html `title="..."` attribute diff --git a/.eslintrc.js b/.eslintrc.js index 103a62f0c34..b83237de399 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -129,6 +129,16 @@ module.exports = { property: 'localStorage', message: 'Use `localStorage` instead', }, + { + object: 'window', + property: 'location', + message: 'Use `location` instead', + }, + { + object: 'window', + property: 'navigator', + message: 'Use `navigator` instead', + }, ], 'no-return-assign': 'error', 'no-return-await': 'error', @@ -366,6 +376,7 @@ module.exports = { excludedFiles: ['**/*.{md,mdx}/*.{ts,tsx}'], // extends: ['plugin:@typescript-eslint/recommended-type-checked'], rules: { + // '@typescript-eslint/no-redundant-type-constituents': 'error', '@typescript-eslint/prefer-optional-chain': 'error', '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/no-floating-promises': 'error', @@ -388,11 +399,10 @@ module.exports = { projectService: { allowDefaultProject: [ 'examples/monaco-graphql-react-vite/vite.config.ts', - 'packages/*/vitest.config.mts', - 'packages/*/vite.config.mts', + 'packages/graphiql/vite.config.mts', + 'packages/{codemirror-graphql,graphiql-toolkit,graphql-language-service-cli,graphql-language-service,monaco-graphql,vscode-graphql-syntax,graphiql}/vitest.config.mts', 'packages/cm6-graphql/__tests__/test.spec.ts', - 'packages/graphiql-react/setup-files.ts', 'packages/graphiql/src/GraphiQL.spec.tsx', 'packages/vscode-graphql-syntax/tests/*.spec.ts', 'packages/graphql-language-service-cli/src/__tests__/*.test.ts', @@ -483,7 +493,7 @@ module.exports = { }, }, { - // Rule prefer await to then without React packages because it's ugly to have `async IIFE` inside `useEffect` + // Rule to prefer await to then without React packages because it's ugly to have `async IIFE` inside `useEffect` files: ['packages/**'], excludedFiles: ['packages/graphiql/**', 'packages/graphiql-react/**'], rules: { @@ -491,7 +501,7 @@ module.exports = { }, }, { - files: ['packages/{graphiql-react,graphiql}/**'], + files: ['packages/{graphiql-react,graphiql}/**/*.{ts,tsx}'], rules: { '@typescript-eslint/no-restricted-imports': [ 'error', @@ -502,6 +512,7 @@ module.exports = { }, ], 'react-hooks/react-compiler': 'error', + '@typescript-eslint/no-deprecated': 'error', }, }, { @@ -529,6 +540,12 @@ module.exports = { 'mdx/code-blocks': true, }, }, + { + files: ['**/*.d.ts'], + rules: { + 'no-var': 'off', + }, + }, { // ❗ALWAYS LAST // Rules for codeblocks inside Markdown/MDX diff --git a/.github/workflows/pr-graphql-compat-check.yml b/.github/workflows/pr-graphql-compat-check.yml index da0c1c2098c..a2849a01370 100644 --- a/.github/workflows/pr-graphql-compat-check.yml +++ b/.github/workflows/pr-graphql-compat-check.yml @@ -4,8 +4,7 @@ on: # only on merge to main. # it's rare that this workflow would # show us an error, but when it does it's important! - branches: - - main + branches: [main] # don't run this regression suite if we don't need to paths-ignore: - '**.md' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3115021a92f..2413edb267b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Release on: push: - branches: [main, graphiql-v4] + branches: [main] permissions: {} jobs: release: diff --git a/docs/migration/graphiql-4.0.0.md b/docs/migration/graphiql-4.0.0.md new file mode 100644 index 00000000000..3ac74c8a76d --- /dev/null +++ b/docs/migration/graphiql-4.0.0.md @@ -0,0 +1,173 @@ +# Upgrading `graphiql` from `3.x` to `4.0.0` + +--- + +## `graphiql` + +- Dropped support for **React 16/17**, added support for **React 19** +- Dropped **CommonJS** build output – now **ESM only** +- Improved UI of tabs + - Changed tabs behavior – tabs are always visible (even if only one) + - Updated tabs tooltip usage – now use HTML `title` attribute +- Removed **default export** +- Removed `disableTabs` option +- Improved Markdown handling – single newlines are ignored +- Added `onPrettifyQuery` callback for custom formatting +- ⚠️ Deprecate **UMD CDN build `index.umd.js`** +- Changed **CDN paths** and **style import** + +> [!WARNING] +> +> ⚠️ **`index.umd.js` is deprecated**. Switch to the [ESM CDN example](../../examples/graphiql-cdn/index.html). + +### UMD CDN path changes + +```diff +-https://unpkg.com/graphiql/graphiql.js +-https://unpkg.com/graphiql/graphiql.min.js ++https://unpkg.com/graphiql/dist/index.umd.js // ⚠️ deprecated + +-https://unpkg.com/graphiql/graphiql.css +-https://unpkg.com/graphiql/graphiql.min.css ++https://unpkg.com/graphiql/dist/style.css +``` + +### Default export removed + +```diff +-import GraphiQL from 'graphiql' ++import { GraphiQL } from 'graphiql' +``` + +### Style import changed + +```diff +-import 'graphiql/graphiql.css' ++import 'graphiql/style.css' +``` + +### Toolbar API migration + +#### `toolbar.additionalContent` → `` + +**Before:** + +```tsx +My button }} /> +``` + +**After:** + +```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + +``` + +--- + +#### `toolbar.additionalComponent` → `` + +**Before:** + +```jsx +My button; + }, + }} +/> +``` + +**After:** + +```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + +``` + +--- + +#### Customizing default toolbar buttons + +You can reorder or remove default toolbar buttons: + +```tsx + + + {({ prettify, copy }) => ( + <> + {copy} {/* Move copy button to the top */} + {prettify} {/* Omit merge button */} + + )} + + +``` + +--- + +## `@graphiql/react` + +- Dropped support for **React 16/17**, added support for **React 19** +- Dropped **CommonJS** build output +- Improved UI of tabs +- Updated dependencies: `@radix-ui` and `@headlessui/react` +- Added `onPrettifyQuery` callback for custom formatting +- Improved Markdown handling (ignores single newlines) +- Style import changed: + ```diff + -import '@graphiql/react/dist/style.css' + +import '@graphiql/react/style.css' + ``` + +--- + +## `@graphiql/plugin-code-exporter` + +- Dropped support for **React 16/17**, added support for **React 19** +- Dropped **CommonJS** build output +- Updated ESM-based CDN example: + [code-exporter ESM CDN example](../../packages/graphiql-plugin-code-exporter/example/index.html) +- ⚠️ UMD build deprecated – migrate to ESM-based CDN +- Style import changed: + ```diff + -import '@graphiql/plugin-code-exporter/dist/style.css' + +import '@graphiql/plugin-code-exporter/style.css' + ``` + +--- + +## `@graphiql/plugin-explorer` + +- Dropped support for **React 16/17**, added support for **React 19** +- Dropped **CommonJS** build output +- Improved styles for the explorer UI +- Updated ESM-based CDN example: + [explorer ESM CDN example](../../examples/graphiql-cdn/index.html) +- ⚠️ UMD build deprecated – migrate to ESM-based CDN +- Style import changed: + ```diff + -import '@graphiql/plugin-explorer/dist/style.css' + +import '@graphiql/plugin-explorer/style.css' + ``` diff --git a/examples/graphiql-cdn/README.md b/examples/graphiql-cdn/README.md index 51573e9581b..62e87a67b35 100644 --- a/examples/graphiql-cdn/README.md +++ b/examples/graphiql-cdn/README.md @@ -1,11 +1,23 @@ # GraphiQL CDN Example -This example uses the CDN bundles to show a simple graphiql example, with explorer plugin. +This is a simple example of using **GraphiQL** directly from a CDN, including the [GraphiQL Explorer plugin](../../packages/graphiql-plugin-explorer/README.md). -It uses the latest version published on npm, via unpkg +It loads the latest GraphiQL version from [esm.sh](https://esm.sh), an ESM-based CDN that serves npm packages as ES modules. -### Setup +## Setup -none required, just open the index.html! +No installation or build step is required — just open the `index.html` file in your browser: -`open index.html` in osx `firefox index.html` or `chromium index.html` in linux +- macOS: + + ```sh + open index.html + ``` + +- Linux: + + ```sh + firefox index.html + # or + chromium index.html + ``` diff --git a/examples/graphiql-cdn/index.html b/examples/graphiql-cdn/index.html index 13bad1a3a3d..cb760ed24e8 100644 --- a/examples/graphiql-cdn/index.html +++ b/examples/graphiql-cdn/index.html @@ -8,74 +8,83 @@ - GraphiQL + + + GraphiQL 4 with React 19 and GraphiQL Explorer - - - - - - - - + .loading { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + font-size: 4rem; + } + - + + + + + + +
+
Loading…
+
diff --git a/examples/graphiql-create-react-app/package.json b/examples/graphiql-create-react-app/package.json index e46b92ee19e..6a2438460a2 100644 --- a/examples/graphiql-create-react-app/package.json +++ b/examples/graphiql-create-react-app/package.json @@ -3,10 +3,10 @@ "version": "0.0.0", "private": true, "dependencies": { - "graphiql": "^3.4.0", + "graphiql": "^3.4.1", "graphql": "^16.9.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-scripts": "5.0.1" }, "scripts": { diff --git a/examples/graphiql-create-react-app/src/App.jsx b/examples/graphiql-create-react-app/src/App.jsx index 9175fb03fee..ba2d6b6fb2e 100644 --- a/examples/graphiql-create-react-app/src/App.jsx +++ b/examples/graphiql-create-react-app/src/App.jsx @@ -1,5 +1,5 @@ import { GraphiQL } from 'graphiql'; -import 'graphiql/graphiql.css'; +import 'graphiql/style.css'; const fetcher = async graphQLParams => { const response = await fetch( diff --git a/examples/graphiql-parcel/package.json b/examples/graphiql-parcel/package.json index 9db03b446eb..250c810f221 100644 --- a/examples/graphiql-parcel/package.json +++ b/examples/graphiql-parcel/package.json @@ -24,8 +24,8 @@ "dependencies": { "graphiql": "^2.2.0", "graphql": "^16.9.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": "^19.1.0", + "react-dom": "^19.1.0" }, "devDependencies": { "parcel": "^2.5.0", diff --git a/examples/graphiql-parcel/src/index.html b/examples/graphiql-parcel/src/index.html index 936537cbb0d..6662d55cae1 100644 --- a/examples/graphiql-parcel/src/index.html +++ b/examples/graphiql-parcel/src/index.html @@ -16,7 +16,10 @@ Parcel React Example - + diff --git a/examples/graphiql-webpack/package.json b/examples/graphiql-webpack/package.json index 2d6f13d3bd2..005e22425d0 100644 --- a/examples/graphiql-webpack/package.json +++ b/examples/graphiql-webpack/package.json @@ -16,7 +16,7 @@ "graphiql": "^3.9.0", "graphql": "^16.9.0", "graphql-ws": "^5.5.5", - "react": "^18.2.0", + "react": "^19.1.0", "regenerator-runtime": "^0.13.9" }, "devDependencies": { @@ -29,7 +29,7 @@ "cross-env": "^7.0.2", "css-loader": "^6.7.3", "html-webpack-plugin": "^5.5.0", - "react-dom": "^18.2.0", + "react-dom": "^19.1.0", "style-loader": "^3.3.1", "webpack": "5.94.0", "webpack-cli": "^5.0.1", diff --git a/examples/graphiql-webpack/public/logo.svg b/examples/graphiql-webpack/public/logo.svg index 43e513e06ca..8b265562b12 100644 --- a/examples/graphiql-webpack/public/logo.svg +++ b/examples/graphiql-webpack/public/logo.svg @@ -1,27 +1,15 @@ - + + + - - + - + - diff --git a/examples/graphiql-webpack/src/index.jsx b/examples/graphiql-webpack/src/index.jsx index ea0adb4c667..7b6f678fa04 100644 --- a/examples/graphiql-webpack/src/index.jsx +++ b/examples/graphiql-webpack/src/index.jsx @@ -5,9 +5,9 @@ import { GraphiQL } from 'graphiql'; import { explorerPlugin } from '@graphiql/plugin-explorer'; import { getSnippets } from './snippets'; import { codeExporterPlugin } from '@graphiql/plugin-code-exporter'; -import 'graphiql/graphiql.css'; -import '@graphiql/plugin-explorer/dist/style.css'; -import '@graphiql/plugin-code-exporter/dist/style.css'; +import 'graphiql/style.css'; +import '@graphiql/plugin-explorer/style.css'; +import '@graphiql/plugin-code-exporter/style.css'; import { createGraphiQLFetcher } from '@graphiql/toolkit'; import { useStorageContext } from '@graphiql/react'; diff --git a/examples/monaco-graphql-nextjs/package.json b/examples/monaco-graphql-nextjs/package.json index b13ee42a0bb..382d88f7f87 100644 --- a/examples/monaco-graphql-nextjs/package.json +++ b/examples/monaco-graphql-nextjs/package.json @@ -19,12 +19,12 @@ "monaco-graphql": "^1.6.1", "next": "13.4.7", "prettier": "3.3.2", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": "^19.1.0", + "react-dom": "^19.1.0" }, "devDependencies": { "@types/node": "^16.18.4", - "@types/react": "18.2.14", + "@types/react": "^19.1.2", "next-global-css": "1.3.1", "typescript": "^4.6.3" } diff --git a/examples/monaco-graphql-react-vite/package.json b/examples/monaco-graphql-react-vite/package.json index 0e0ce70cc2b..379a7ac6e9e 100644 --- a/examples/monaco-graphql-react-vite/package.json +++ b/examples/monaco-graphql-react-vite/package.json @@ -10,11 +10,11 @@ "monaco-editor": "^0.39.0", "monaco-graphql": "^1.6.1", "prettier": "3.3.2", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": "^19.1.0", + "react-dom": "^19.1.0" }, "devDependencies": { - "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-react": "^4.4.1", "vite": "^5.4.18", "vite-plugin-monaco-editor": "^1.1.0" }, diff --git a/examples/monaco-graphql-webpack/webpack.config.js b/examples/monaco-graphql-webpack/webpack.config.js index 577f2b1f5c2..019b0e0ac21 100644 --- a/examples/monaco-graphql-webpack/webpack.config.js +++ b/examples/monaco-graphql-webpack/webpack.config.js @@ -47,7 +47,7 @@ const resultConfig = { plugins: [ // in order to prevent async modules for CDN builds // until we can guarantee it will work with the CDN properly - // and so that graphiql.min.js can retain parity + // and so that `index.umd.js` can retain parity new HtmlWebpackPlugin({ template: relPath('src/index.html.ejs'), filename: 'index.html', diff --git a/functions/graphql.ts b/functions/graphql.ts index 935f056e26f..2788d0b9188 100644 --- a/functions/graphql.ts +++ b/functions/graphql.ts @@ -10,8 +10,8 @@ import type { HandlerContext as NetlifyHandlerContext, } from '@netlify/functions'; -import schema from '../packages/graphiql/test/schema'; -import { customExecute } from '../packages/graphiql/test/execute'; +import { schema } from '../packages/graphiql/test/schema.js'; +import { customExecute } from '../packages/graphiql/test/execute.js'; /** * Handler options when using the netlify adapter diff --git a/package.json b/package.json index 42a383fbd0a..3f0dfe41a27 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,8 @@ "gen-agenda": "wgutils agenda gen" }, "dependencies": { + "identity-obj-proxy": "^3.0.0", + "babel-plugin-macros": "^3.1.0", "graphql-http": "^1.22.1", "@babel/cli": "^7.21.0", "@babel/core": "^7.21.0", @@ -104,7 +106,6 @@ "@typescript-eslint/eslint-plugin": "^8.31.0", "@typescript-eslint/parser": "^8.31.0", "babel-jest": "^29.4.3", - "babel-plugin-macros": "^3.1.0", "babel-plugin-transform-import-meta": "^2.2.1", "concurrently": "^7.0.0", "copy": "^0.3.2", @@ -122,7 +123,6 @@ "eslint-plugin-sonarjs": "^3.0.2", "eslint-plugin-unicorn": "^56.0.0", "execa": "^7.1.1", - "identity-obj-proxy": "^3.0.0", "fetch-mock": "6.5.2", "husky": "^4.2.3", "jest": "^27.5.1", @@ -143,6 +143,8 @@ "resolutions": { "@babel/traverse": "^7.23.2", "vscode-languageserver-types": "3.17.3", - "markdown-it": "14.1.0" + "markdown-it": "14.1.0", + "react": "18.3.1", + "react-dom": "18.3.1" } } diff --git a/packages/graphiql-plugin-code-exporter/CHANGELOG.md b/packages/graphiql-plugin-code-exporter/CHANGELOG.md index e4acbf292d9..7ac8389de9b 100644 --- a/packages/graphiql-plugin-code-exporter/CHANGELOG.md +++ b/packages/graphiql-plugin-code-exporter/CHANGELOG.md @@ -1,5 +1,37 @@ # @graphiql/plugin-code-exporter +## 4.0.0-alpha.1 + +### Patch Changes + +- [#3740](https://github.com/graphql/graphiql/pull/3740) [`3c12ce0`](https://github.com/graphql/graphiql/commit/3c12ce01eb3b2ec9a317a2fea2bb92602b748a8b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix types incorrect types entry + +## 4.0.0-alpha.0 + +### Major Changes + +- [#3709](https://github.com/graphql/graphiql/pull/3709) [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - `style.css` import was changed + + ## Migration + + ```diff + -import '@graphiql/plugin-code-exporter/dist/style.css'; + +import '@graphiql/plugin-code-exporter/style.css'; + ``` + +### Minor Changes + +- [#3702](https://github.com/graphql/graphiql/pull/3702) [`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627) Thanks [@dimaMachina](https://github.com/dimaMachina)! - generate types with `vite-plugin-dts` + +### Patch Changes + +- [#3705](https://github.com/graphql/graphiql/pull/3705) [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `vite build --watch` instead of `vite` for `dev` script because we don't need development server for them + + do not use `vite-plugin-dts` when generating umd build + +- Updated dependencies [[`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627), [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb), [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106), [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad), [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673)]: + - @graphiql/react@1.0.0-alpha.0 + ## 3.1.5 ### Patch Changes diff --git a/packages/graphiql-plugin-code-exporter/README.md b/packages/graphiql-plugin-code-exporter/README.md index 40764460285..56c683531e3 100644 --- a/packages/graphiql-plugin-code-exporter/README.md +++ b/packages/graphiql-plugin-code-exporter/README.md @@ -1,19 +1,17 @@ # GraphiQL Code Exporter Plugin This package provides a plugin that integrates the -[GraphiQL Code Exporter](https://github.com/OneGraph/graphiql-code-exporter) -into the GraphiQL UI. +[GraphiQL Code Exporter](https://github.com/OneGraph/graphiql-code-exporter) into the GraphiQL UI. -## Install +## Installation -Use your favorite package manager to install the package: +Install the plugin using your preferred package manager: ```sh npm install @graphiql/plugin-code-exporter ``` -The following packages are peer dependencies, so make sure you have them -installed as well: +Make sure to also install the required peer dependencies: ```sh npm install react react-dom graphql @@ -21,84 +19,63 @@ npm install react react-dom graphql ## Usage -See -[GraphiQL Code Exporter README](https://github.com/OneGraph/graphiql-code-exporter) -for all details on available `props` and how to -[create snippets](https://github.com/OneGraph/graphiql-code-exporter#snippets). +Refer to the +[GraphiQL Code Exporter README](https://github.com/OneGraph/graphiql-code-exporter) for full details on available `props` and how to [create snippets](https://github.com/OneGraph/graphiql-code-exporter#snippets). + +Example integration: ```jsx -import { useState } from 'react'; import { GraphiQL } from 'graphiql'; import { createGraphiQLFetcher } from '@graphiql/toolkit'; import { codeExporterPlugin } from '@graphiql/plugin-code-exporter'; -import 'graphiql/graphiql.css'; -import '@graphiql/plugin-code-exporter/dist/style.css'; +import 'graphiql/style.css'; +import '@graphiql/plugin-code-exporter/style.css'; const fetcher = createGraphiQLFetcher({ - url: 'https://swapi-graphql.netlify.app/.netlify/functions/index', + url: 'https://countries.trevorblades.com', }); +function getQuery(arg, spaceCount = 2) { + const spaces = ' '.repeat(spaceCount); + const { query } = arg.operationDataList[0]; + return spaces + query.replaceAll('\n', '\n' + spaces); +} -/** - * Example code for snippets. See https://github.com/OneGraph/graphiql-code-exporter#snippets for - * details - */ -const removeQueryName = query => - query.replace( - /^[^{(]+([{(])/, - (_match, openingCurlyBracketsOrParenthesis) => - `query ${openingCurlyBracketsOrParenthesis}`, - ); - -const getQuery = (arg, spaceCount) => { - const { operationDataList } = arg; - const { query } = operationDataList[0]; - const anonymousQuery = removeQueryName(query); - return ( - ' '.repeat(spaceCount) + - anonymousQuery.replaceAll('\n', '\n' + ' '.repeat(spaceCount)) - ); -}; - -const exampleSnippetOne = { - name: 'Example One', - language: 'JavaScript', - codeMirrorMode: 'jsx', - options: [], - generate: arg => `export const query = graphql\` -${getQuery(arg, 2)} -\` -`, -}; - -const exampleSnippetTwo = { - name: 'Example Two', - language: 'JavaScript', - codeMirrorMode: 'jsx', - options: [], - generate: arg => `import { graphql } from 'graphql' - -export const query = graphql\` -${getQuery(arg, 2)} -\` -`, -}; - -const snippets = [exampleSnippetOne, exampleSnippetTwo]; - -const exporter = codeExporterPlugin({ - snippets, - codeMirrorTheme: 'graphiql', +const codeExporter = codeExporterPlugin({ + /** + * Example code for snippets. See https://github.com/OneGraph/graphiql-code-exporter#snippets for details. + */ + snippets: [ + { + name: 'Example One', + language: 'JavaScript', + codeMirrorMode: 'jsx', + options: [], + generate: arg => + ['export const query = graphql`', getQuery(arg), '`'].join('\n'), + }, + { + name: 'Example Two', + language: 'JavaScript', + codeMirrorMode: 'jsx', + options: [], + generate: arg => + [ + "import { graphql } from 'graphql'", + '', + 'export const query = graphql`', + getQuery(arg), + '`', + ].join('\n'), + }, + ], }); - -function GraphiQLWithCodeExporter() { - return ( - - ); +function App() { + return ; } ``` ## CDN bundles -You can also use this plugin with `unpkg`, `jsdelivr`, and other CDNs. +You can also use this plugin via an ESM-based CDN like [esm.sh](https://esm.sh). -See the [example HTML file](examples/index.html) for this plugin +See the [CDN example](./example/index.html) for a working demo. diff --git a/packages/graphiql-plugin-code-exporter/example/index.html b/packages/graphiql-plugin-code-exporter/example/index.html new file mode 100644 index 00000000000..d08d372cf1d --- /dev/null +++ b/packages/graphiql-plugin-code-exporter/example/index.html @@ -0,0 +1,126 @@ + + + + + + + GraphiQL 4 with React 19 and GraphiQL Code Exporter + + + + + + + + +
+
Loading…
+
+ + diff --git a/packages/graphiql-plugin-code-exporter/examples/index.html b/packages/graphiql-plugin-code-exporter/examples/index.html deleted file mode 100644 index 9011e9c4022..00000000000 --- a/packages/graphiql-plugin-code-exporter/examples/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - -
Loading...
- - - - - - - - - - diff --git a/packages/graphiql-plugin-code-exporter/package.json b/packages/graphiql-plugin-code-exporter/package.json index 5268859c300..f96c64eb15d 100644 --- a/packages/graphiql-plugin-code-exporter/package.json +++ b/packages/graphiql-plugin-code-exporter/package.json @@ -1,15 +1,14 @@ { "name": "@graphiql/plugin-code-exporter", "version": "3.1.5", + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/graphql/graphiql", "directory": "packages/graphiql-plugin-code-exporter" }, "author": "LekoArts", - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "license": "MIT", "keywords": [ "react", @@ -19,33 +18,40 @@ "explorer" ], "files": [ - "dist", - "src", - "types" + "dist" ], + "exports": { + "./package.json": "./package.json", + "./style.css": "./dist/style.css", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, "scripts": { - "prebuild": "rimraf dist types", - "dev": "vite", - "build": "tsc --emitDeclarationOnly && node resources/copy-types.mjs && vite build && UMD=true vite build", - "preview": "vite preview" + "dev": "vite build --watch", + "build": "vite build && UMD=true vite build", + "prebuild": "yarn types:check", + "postbuild": "cp src/graphiql-code-exporter.d.ts dist/graphiql-code-exporter.d.ts", + "types:check": "tsc --noEmit" }, "dependencies": { "graphiql-code-exporter": "^3.0.3" }, "peerDependencies": { "@graphiql/react": "^0.29.0", - "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2", + "react": "^18 || ^19", + "react-dom": "^18 || ^19" }, "devDependencies": { "@graphiql/react": "^0.29.0", - "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-react": "^4.4.1", "graphql": "^16.9.0", - "postcss-nesting": "^10.1.7", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "typescript": "^4.6.3", - "vite": "^5.4.18" + "vite": "^6.3.3", + "vite-plugin-dts": "^4.0.1" } } diff --git a/packages/graphiql-plugin-code-exporter/postcss.config.js b/packages/graphiql-plugin-code-exporter/postcss.config.js deleted file mode 100644 index 1ab3f9d65bf..00000000000 --- a/packages/graphiql-plugin-code-exporter/postcss.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - plugins: [require('postcss-nesting')], -}; diff --git a/packages/graphiql-plugin-code-exporter/resources/copy-types.mjs b/packages/graphiql-plugin-code-exporter/resources/copy-types.mjs deleted file mode 100644 index 45e621b507b..00000000000 --- a/packages/graphiql-plugin-code-exporter/resources/copy-types.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const base = path.resolve(path.dirname(__filename), '..'); - -fs.copyFileSync( - path.resolve(base, 'src', 'graphiql-code-exporter.d.ts'), - path.resolve(base, 'types', 'graphiql-code-exporter.d.ts'), -); diff --git a/packages/graphiql-plugin-code-exporter/src/index.css b/packages/graphiql-plugin-code-exporter/src/index.css index 716d01d954c..16af4b1b6f9 100644 --- a/packages/graphiql-plugin-code-exporter/src/index.css +++ b/packages/graphiql-plugin-code-exporter/src/index.css @@ -133,7 +133,7 @@ } & .CodeMirror { box-shadow: var(--popover-box-shadow); - border-radius: calc(var(--border-radius-12)); + border-radius: var(--border-radius-12); padding: var(--px-16); } } diff --git a/packages/graphiql-plugin-code-exporter/tsconfig.json b/packages/graphiql-plugin-code-exporter/tsconfig.json index 8ad4d4a311c..2dd9b41294b 100644 --- a/packages/graphiql-plugin-code-exporter/tsconfig.json +++ b/packages/graphiql-plugin-code-exporter/tsconfig.json @@ -14,9 +14,6 @@ "resolveJsonModule": true, "isolatedModules": true, "declaration": true, - "declarationDir": "types", "jsx": "react" - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + } } diff --git a/packages/graphiql-plugin-code-exporter/tsconfig.node.json b/packages/graphiql-plugin-code-exporter/tsconfig.node.json deleted file mode 100644 index 9d31e2aed93..00000000000 --- a/packages/graphiql-plugin-code-exporter/tsconfig.node.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/packages/graphiql-plugin-code-exporter/vite.config.mts b/packages/graphiql-plugin-code-exporter/vite.config.mts index b963a34933f..627e266b78f 100644 --- a/packages/graphiql-plugin-code-exporter/vite.config.mts +++ b/packages/graphiql-plugin-code-exporter/vite.config.mts @@ -1,20 +1,31 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import packageJSON from './package.json'; +import dts from 'vite-plugin-dts'; const IS_UMD = process.env.UMD === 'true'; export default defineConfig({ - plugins: [react({ jsxRuntime: 'classic' })], + plugins: [ + react({ jsxRuntime: 'classic' }), + !IS_UMD && dts({ include: ['src/**'] }), + ], + css: { + transformer: 'lightningcss', + }, build: { - minify: IS_UMD ? 'esbuild' : false, + minify: IS_UMD + ? 'terser' // produce better bundle size than esbuild + : false, // avoid clean cjs/es builds emptyOutDir: !IS_UMD, lib: { entry: 'src/index.tsx', - fileName: 'index', + fileName: (format, filePath) => + `${filePath}.${format === 'umd' ? 'umd.' : ''}js`, name: 'GraphiQLPluginCodeExporter', - formats: IS_UMD ? ['umd'] : ['cjs', 'es'], + formats: IS_UMD ? ['umd'] : ['es'], + cssFileName: 'style', }, rollupOptions: { external: [ @@ -23,7 +34,6 @@ export default defineConfig({ ...(IS_UMD ? [] : Object.keys(packageJSON.dependencies)), ], output: { - chunkFileNames: '[name].[format].js', globals: { '@graphiql/react': 'GraphiQL.React', graphql: 'GraphiQL.GraphQL', @@ -32,9 +42,5 @@ export default defineConfig({ }, }, }, - commonjsOptions: { - esmExternals: true, - requireReturnsDefault: 'auto', - }, }, }); diff --git a/packages/graphiql-plugin-explorer/CHANGELOG.md b/packages/graphiql-plugin-explorer/CHANGELOG.md index 9d64d6f730e..86bd789f48e 100644 --- a/packages/graphiql-plugin-explorer/CHANGELOG.md +++ b/packages/graphiql-plugin-explorer/CHANGELOG.md @@ -1,5 +1,43 @@ # @graphiql/plugin-explorer +## 4.0.0-alpha.2 + +### Patch Changes + +- [#3740](https://github.com/graphql/graphiql/pull/3740) [`3c12ce0`](https://github.com/graphql/graphiql/commit/3c12ce01eb3b2ec9a317a2fea2bb92602b748a8b) Thanks [@dimaMachina](https://github.com/dimaMachina)! - fix types incorrect types entry + +## 4.0.0-alpha.1 + +### Patch Changes + +- [#3738](https://github.com/graphql/graphiql/pull/3738) [`eaa415c`](https://github.com/graphql/graphiql/commit/eaa415cce5c3baecea76068c02953884eec5ba2e) Thanks [@dimaMachina](https://github.com/dimaMachina)! - improve explorer styles + +## 4.0.0-alpha.0 + +### Major Changes + +- [#3709](https://github.com/graphql/graphiql/pull/3709) [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - `style.css` import was changed + + ## Migration + + ```diff + -import '@graphiql/plugin-explorer/dist/style.css'; + +import '@graphiql/plugin-explorer/style.css'; + ``` + +### Minor Changes + +- [#3702](https://github.com/graphql/graphiql/pull/3702) [`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627) Thanks [@dimaMachina](https://github.com/dimaMachina)! - generate types with `vite-plugin-dts` + +### Patch Changes + +- [#3705](https://github.com/graphql/graphiql/pull/3705) [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `vite build --watch` instead of `vite` for `dev` script because we don't need development server for them + + do not use `vite-plugin-dts` when generating umd build + +- Updated dependencies [[`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627), [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb), [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106), [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad), [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673)]: + - @graphiql/react@1.0.0-alpha.0 + ## 3.2.6 ### Patch Changes diff --git a/packages/graphiql-plugin-explorer/README.md b/packages/graphiql-plugin-explorer/README.md index 69bcbad7eb6..ea75f273f10 100644 --- a/packages/graphiql-plugin-explorer/README.md +++ b/packages/graphiql-plugin-explorer/README.md @@ -1,19 +1,17 @@ # GraphiQL Explorer Plugin -This package provides a plugin that integrated the -[`GraphiQL Explorer`](https://github.com/OneGraph/graphiql-explorer) into the -GraphiQL UI. +This package provides a plugin that integrates the +[`GraphiQL Explorer`](https://github.com/OneGraph/graphiql-explorer) into the GraphiQL UI. -## Install +## Installation -Use your favorite package manager to install the package: +Use your preferred package manager to install the plugin: ```sh npm install @graphiql/plugin-explorer ``` -The following packages are peer dependencies, so make sure you have them -installed as well: +Make sure to also install the required peer dependencies: ```sh npm install react react-dom graphql @@ -25,8 +23,8 @@ npm install react react-dom graphql import { GraphiQL } from 'graphiql'; import { createGraphiQLFetcher } from '@graphiql/toolkit'; import { explorerPlugin } from '@graphiql/plugin-explorer'; -import 'graphiql/graphiql.css'; -import '@graphiql/plugin-explorer/dist/style.css'; +import 'graphiql/style.css'; +import '@graphiql/plugin-explorer/style.css'; const fetcher = createGraphiQLFetcher({ url: 'https://swapi-graphql.netlify.app/.netlify/functions/index', @@ -42,6 +40,6 @@ function GraphiQLWithExplorer() { ## CDN bundles -You can also use this plugin with `unpkg`, `jsdelivr`, and other CDNs. +You can also use this plugin via an ESM-based CDN like [esm.sh](https://esm.sh). -See the [example HTML file](examples/index.html) for this plugin +See the [CDN example](./example/index.html) for a working demo. diff --git a/packages/graphiql-plugin-explorer/example/index.html b/packages/graphiql-plugin-explorer/example/index.html new file mode 120000 index 00000000000..3236e5b32d2 --- /dev/null +++ b/packages/graphiql-plugin-explorer/example/index.html @@ -0,0 +1 @@ +../../../examples/graphiql-cdn/index.html \ No newline at end of file diff --git a/packages/graphiql-plugin-explorer/examples/index.html b/packages/graphiql-plugin-explorer/examples/index.html deleted file mode 100644 index 9e93f7aa6d8..00000000000 --- a/packages/graphiql-plugin-explorer/examples/index.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - -
Loading...
- - - - - - - - - - diff --git a/packages/graphiql-plugin-explorer/package.json b/packages/graphiql-plugin-explorer/package.json index bc95006df48..1740f8b9dee 100644 --- a/packages/graphiql-plugin-explorer/package.json +++ b/packages/graphiql-plugin-explorer/package.json @@ -1,14 +1,13 @@ { "name": "@graphiql/plugin-explorer", "version": "3.2.6", + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/graphql/graphiql", "directory": "packages/graphiql-plugin-explorer" }, - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "license": "MIT", "keywords": [ "react", @@ -18,33 +17,41 @@ "explorer" ], "files": [ - "dist", - "src", - "types" + "dist" ], + "exports": { + "./package.json": "./package.json", + "./style.css": "./dist/style.css", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, "scripts": { - "prebuild": "rimraf dist types", - "dev": "vite", - "build": "tsc --emitDeclarationOnly && node resources/copy-types.mjs && vite build && UMD=true vite build", - "preview": "vite preview" + "dev": "vite build --watch", + "build": "vite build && UMD=true vite build", + "postbuild": "cp src/graphiql-explorer.d.ts dist/graphiql-explorer.d.ts", + "prebuild": "yarn types:check", + "types:check": "tsc --noEmit" }, "dependencies": { "graphiql-explorer": "^0.9.0" }, "peerDependencies": { "@graphiql/react": "^0.29.0", - "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2", + "react": "^18 || ^19", + "react-dom": "^18 || ^19" }, "devDependencies": { "@graphiql/react": "^0.29.0", - "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-react": "^4.4.1", "graphql": "^16.9.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "typescript": "^4.6.3", - "vite": "^5.4.18", - "vite-plugin-svgr": "^4.2.0" + "vite": "^6.3.3", + "vite-plugin-svgr": "^4.3.0", + "vite-plugin-dts": "^4.0.1" } } diff --git a/packages/graphiql-plugin-explorer/resources/copy-types.mjs b/packages/graphiql-plugin-explorer/resources/copy-types.mjs deleted file mode 100644 index 8f6175f68c7..00000000000 --- a/packages/graphiql-plugin-explorer/resources/copy-types.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const base = path.resolve(path.dirname(__filename), '..'); - -fs.copyFileSync( - path.resolve(base, 'src', 'graphiql-explorer.d.ts'), - path.resolve(base, 'types', 'graphiql-explorer.d.ts'), -); diff --git a/packages/graphiql-plugin-explorer/src/icons/folder-plus.svg b/packages/graphiql-plugin-explorer/src/icons/folder-plus.svg index d6714651b81..0e5550c87d8 100644 --- a/packages/graphiql-plugin-explorer/src/icons/folder-plus.svg +++ b/packages/graphiql-plugin-explorer/src/icons/folder-plus.svg @@ -13,8 +13,6 @@ /> div { + overflow: auto !important; /* override overflow: scroll */ +} + .graphiql-explorer-root input { background: unset; } @@ -44,16 +48,23 @@ padding: var(--px-4) var(--px-6); } -.graphiql-operation-title-bar .toolbar-button { - line-height: 0; - margin-left: var(--px-8); - color: hsla(var(--color-neutral), var(--alpha-secondary, 0.6)); - font-size: var(--font-size-h3); - vertical-align: middle; +.toolbar-button { + all: unset; + cursor: pointer; + line-height: 0 !important; + margin-left: var(--px-6); + color: hsl(var(--color-primary)); + font-size: var(--font-size-h3) !important; +} + +.graphiql-explorer-slug .toolbar-button, +.graphiql-explorer-graphql-arguments .toolbar-button { + font-size: inherit !important; } .graphiql-explorer-graphql-arguments input { line-height: 0; + min-width: 2rem; } .graphiql-explorer-actions { diff --git a/packages/graphiql-plugin-explorer/tsconfig.json b/packages/graphiql-plugin-explorer/tsconfig.json index 8ad4d4a311c..2dd9b41294b 100644 --- a/packages/graphiql-plugin-explorer/tsconfig.json +++ b/packages/graphiql-plugin-explorer/tsconfig.json @@ -14,9 +14,6 @@ "resolveJsonModule": true, "isolatedModules": true, "declaration": true, - "declarationDir": "types", "jsx": "react" - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + } } diff --git a/packages/graphiql-plugin-explorer/tsconfig.node.json b/packages/graphiql-plugin-explorer/tsconfig.node.json deleted file mode 100644 index 9d31e2aed93..00000000000 --- a/packages/graphiql-plugin-explorer/tsconfig.node.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/packages/graphiql-plugin-explorer/vite.config.mts b/packages/graphiql-plugin-explorer/vite.config.mts index e47ea748b70..aa65e0ba7f0 100644 --- a/packages/graphiql-plugin-explorer/vite.config.mts +++ b/packages/graphiql-plugin-explorer/vite.config.mts @@ -1,6 +1,7 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; +import dts from 'vite-plugin-dts'; import packageJSON from './package.json'; const IS_UMD = process.env.UMD === 'true'; @@ -9,21 +10,28 @@ export default defineConfig({ plugins: [ react({ jsxRuntime: 'classic' }), svgr({ - exportAsDefault: true, svgrOptions: { titleProp: true, }, }), + !IS_UMD && [dts({ include: ['src/**'] })], ], + css: { + transformer: 'lightningcss', + }, build: { - minify: IS_UMD ? 'esbuild' : false, + minify: IS_UMD + ? 'terser' // produce better bundle size than esbuild + : false, // avoid clean cjs/es builds emptyOutDir: !IS_UMD, lib: { entry: 'src/index.tsx', - fileName: 'index', + fileName: (format, filePath) => + `${filePath}.${format === 'umd' ? 'umd.' : ''}js`, name: 'GraphiQLPluginExplorer', - formats: IS_UMD ? ['umd'] : ['cjs', 'es'], + formats: IS_UMD ? ['umd'] : ['es'], + cssFileName: 'style', }, rollupOptions: { external: [ diff --git a/packages/graphiql-react/CHANGELOG.md b/packages/graphiql-react/CHANGELOG.md index f7042df3357..d0b32d05b1f 100644 --- a/packages/graphiql-react/CHANGELOG.md +++ b/packages/graphiql-react/CHANGELOG.md @@ -1,5 +1,61 @@ # @graphiql/react +## 1.0.0-alpha.4 + +### Minor Changes + +- [#3733](https://github.com/graphql/graphiql/pull/3733) [`8dbddb5`](https://github.com/graphql/graphiql/commit/8dbddb50273720d76f895af6b783b04204c68e03) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Add support for `onPrettifyQuery` callback to enable customised query formatting + +## 1.0.0-alpha.3 + +### Patch Changes + +- [#3414](https://github.com/graphql/graphiql/pull/3414) [`f8b719f`](https://github.com/graphql/graphiql/commit/f8b719f215a79038d1b2a54ddfef461fd849a912) Thanks [@leonardehrenfried](https://github.com/leonardehrenfried)! - Respect Markdown format: ignore single newline + +- [#3730](https://github.com/graphql/graphiql/pull/3730) [`360a038`](https://github.com/graphql/graphiql/commit/360a0385d4ef0105beb8e76044a78f5cd43c9448) Thanks [@dimaMachina](https://github.com/dimaMachina)! - rollback `position: absolute` style for `.graphiql-logo` because tabs will behind logo + +## 1.0.0-alpha.2 + +### Patch Changes + +- [#3720](https://github.com/graphql/graphiql/pull/3720) [`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `overflow-y: scroll` with `overflow-y: auto` + +## 1.0.0-alpha.1 + +### Minor Changes + +- [#3717](https://github.com/graphql/graphiql/pull/3717) [`bf0c4e7`](https://github.com/graphql/graphiql/commit/bf0c4e7236f4a68448063aa0c6a4ed439e869a9f) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `createComponentGroup` utility in favour `Object.assign` + +## 1.0.0-alpha.0 + +### Major Changes + +- [#3709](https://github.com/graphql/graphiql/pull/3709) [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb) Thanks [@dimaMachina](https://github.com/dimaMachina)! - `style.css` import was changed + + ## Migration + + ```diff + -import '@graphiql/react/dist/style.css'; + +import '@graphiql/react/style.css'; + ``` + +### Minor Changes + +- [#3702](https://github.com/graphql/graphiql/pull/3702) [`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627) Thanks [@dimaMachina](https://github.com/dimaMachina)! - generate types with `vite-plugin-dts` + +- [#3644](https://github.com/graphql/graphiql/pull/3644) [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - new looks of tabs + + - fix `disableTabs` when `Add tab` button is still shown + +### Patch Changes + +- [#3705](https://github.com/graphql/graphiql/pull/3705) [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `vite build --watch` instead of `vite` for `dev` script because we don't need development server for them + + do not use `vite-plugin-dts` when generating umd build + +- [#3692](https://github.com/graphql/graphiql/pull/3692) [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - prefer `location` over `window.location` + - prefer `navigator` over `window.navigator` + ## 0.29.0 ### Minor Changes diff --git a/packages/graphiql-react/README.md b/packages/graphiql-react/README.md index 54ac1e2615e..77b90db13c2 100644 --- a/packages/graphiql-react/README.md +++ b/packages/graphiql-react/README.md @@ -61,7 +61,7 @@ function MyGraphQLIDE() { ``` The package also ships the necessary CSS that all its UI components need. You -can import them from `@graphiql/react/dist/style.css`. +can import them from `@graphiql/react/style.css`. > **Note**: In order for these styles to apply, the UI components need to be > rendered inside an element that has a class name `graphiql-container`. diff --git a/packages/graphiql-react/package.json b/packages/graphiql-react/package.json index 06b254b0446..ff936f3fd81 100644 --- a/packages/graphiql-react/package.json +++ b/packages/graphiql-react/package.json @@ -1,6 +1,7 @@ { "name": "@graphiql/react", "version": "0.29.0", + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/graphql/graphiql", @@ -11,20 +12,16 @@ "url": "https://github.com/graphql/graphiql/issues?q=issue+label:@graphiql/react" }, "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.mjs", "exports": { "./package.json": "./package.json", + "./style.css": "./dist/style.css", + "./font/*": "./font/*", ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.js", - "types": "./types/index.d.ts" - }, - "./font/roboto.css": "./font/roboto.css", - "./font/fira-code.css": "./font/fira-code.css", - "./dist/style.css": "./dist/style.css" + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } }, - "types": "types/index.d.ts", + "types": "dist/index.d.ts", "keywords": [ "react", "graphql", @@ -33,35 +30,33 @@ ], "files": [ "dist", - "font", - "src", - "types" + "font" ], "scripts": { - "prebuild": "rimraf dist types", - "dev": "concurrently 'tsc --emitDeclarationOnly --watch' 'vite build --watch'", - "build": "tsc --emitDeclarationOnly && vite build", - "test": "vitest" + "dev": "vite build --watch", + "build": "vite build", + "test": "vitest", + "types:check": "tsc --noEmit" }, "peerDependencies": { "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "react": "^18 || ^19", + "react-dom": "^18 || ^19" }, "dependencies": { "react-compiler-runtime": "19.1.0-rc.1", "@graphiql/toolkit": "^0.11.2", - "@headlessui/react": "^1.7.15", - "@radix-ui/react-dialog": "^1.0.4", - "@radix-ui/react-dropdown-menu": "^2.0.5", - "@radix-ui/react-tooltip": "^1.0.6", - "@radix-ui/react-visually-hidden": "^1.0.3", + "@headlessui/react": "^2.2", + "@radix-ui/react-dialog": "^1.1", + "@radix-ui/react-dropdown-menu": "^2.1", + "@radix-ui/react-tooltip": "^1.2", + "@radix-ui/react-visually-hidden": "^1.2", "@types/codemirror": "^5.60.8", "clsx": "^1.2.1", "codemirror": "^5.65.3", "codemirror-graphql": "^2.2.1", "copy-to-clipboard": "^3.2.0", - "framer-motion": "^6.5.1", + "framer-motion": "^12", "get-value": "^3.0.1", "graphql-language-service": "^5.3.1", "markdown-it": "^14.1.0", @@ -69,20 +64,20 @@ }, "devDependencies": { "babel-plugin-react-compiler": "19.1.0-rc.1", - "@types/react-dom": "^18.3.1", + "@types/react-dom": "^19.1.2", "@babel/helper-string-parser": "^7.19.4", "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.1.0", "@types/markdown-it": "^14.1.2", "@types/get-value": "^3.0.5", "@types/set-value": "^4.0.1", - "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-react": "^4.4.1", "graphql": "^16.9.0", - "postcss-nesting": "^10.1.7", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "typescript": "^4.6.3", - "vite": "^5.4.18", - "vite-plugin-svgr": "^4.2.0" + "vite": "^6.3.3", + "vite-plugin-svgr": "^4.3.0", + "vite-plugin-dts": "^4.5.3" } } diff --git a/packages/graphiql-react/postcss.config.js b/packages/graphiql-react/postcss.config.js deleted file mode 100644 index 1ab3f9d65bf..00000000000 --- a/packages/graphiql-react/postcss.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - plugins: [require('postcss-nesting')], -}; diff --git a/packages/graphiql-react/src/editor/common.ts b/packages/graphiql-react/src/editor/common.ts index 40d45515a17..7b5673c4306 100644 --- a/packages/graphiql-react/src/editor/common.ts +++ b/packages/graphiql-react/src/editor/common.ts @@ -27,10 +27,10 @@ export async function importCodeMirror( addons: Promise[], options?: { useCommonAddons?: boolean }, ) { - const CodeMirror = await import('codemirror').then(c => + const CodeMirror = await import('codemirror').then(mod => // Depending on bundler and settings the dynamic import either returns a - // function (e.g. parcel) or an object containing a `default` property - typeof c === 'function' ? c : c.default, + // function (e.g., parcel) or an object containing a `default` property + typeof mod === 'function' ? mod : mod.default, ); await Promise.all( options?.useCommonAddons === false diff --git a/packages/graphiql-react/src/editor/components/image-preview.tsx b/packages/graphiql-react/src/editor/components/image-preview.tsx index 4a2b65dfc16..f21f6aa5ef5 100644 --- a/packages/graphiql-react/src/editor/components/image-preview.tsx +++ b/packages/graphiql-react/src/editor/components/image-preview.tsx @@ -76,11 +76,8 @@ function tokenToURL(token: Token) { const value = token.string.slice(1).slice(0, -1).trim(); try { - const { location } = window; return new URL(value, location.protocol + '//' + location.host); - } catch { - return; - } + } catch {} } function isImageURL(url: URL) { diff --git a/packages/graphiql-react/src/editor/context.tsx b/packages/graphiql-react/src/editor/context.tsx index 81bd501ebea..0fa20ad2f01 100644 --- a/packages/graphiql-react/src/editor/context.tsx +++ b/packages/graphiql-react/src/editor/context.tsx @@ -211,7 +211,7 @@ export type EditorContextProviderProps = { * - Adding a tab * - Switching to a different tab * - Closing a tab - * @param tabState The tabs state after it has been updated. + * @param tabState The tab state after it has been updated. */ onTabChange?(tabState: TabsState): void; /** @@ -336,7 +336,7 @@ export function EditorContextProvider(props: EditorContextProviderProps) { storage?.set(PERSIST_HEADERS_STORAGE_KEY, persist.toString()); }; - const lastShouldPersistHeadersProp = useRef(); + const lastShouldPersistHeadersProp = useRef(undefined); useEffect(() => { const propValue = Boolean(props.shouldPersistHeaders); if (lastShouldPersistHeadersProp?.current !== propValue) { diff --git a/packages/graphiql-react/src/editor/hooks.ts b/packages/graphiql-react/src/editor/hooks.ts index 2292c7db615..52c1f68b27d 100644 --- a/packages/graphiql-react/src/editor/hooks.ts +++ b/packages/graphiql-react/src/editor/hooks.ts @@ -1,4 +1,9 @@ -import { fillLeafs, GetDefaultFieldNamesFn, mergeAst } from '@graphiql/toolkit'; +import { + fillLeafs, + GetDefaultFieldNamesFn, + mergeAst, + MaybePromise, +} from '@graphiql/toolkit'; import type { EditorChange, EditorConfiguration } from 'codemirror'; import type { SchemaReference } from 'codemirror-graphql/utils/SchemaReference'; import copyToClipboard from 'copy-to-clipboard'; @@ -32,9 +37,7 @@ export function useSynchronizeOption( value: EditorConfiguration[K], ) { useEffect(() => { - if (editor) { - editor.setOption(option, value); - } + editor?.setOption(option, value); }, [editor, option, value]); } @@ -214,19 +217,36 @@ export function useMergeQuery({ caller }: UseMergeQueryArgs = {}) { }; } -type UsePrettifyEditorsArgs = { +export type UsePrettifyEditorsArgs = { /** * This is only meant to be used internally in `@graphiql/react`. */ caller?: Function; + /** + * Invoked when the prettify callback is invoked. + * @param query The current value of the query editor. + * @default + * import { parse, print } from 'graphql' + * + * (query) => print(parse(query)) + * @returns The formatted query. + */ + onPrettifyQuery?: (query: string) => MaybePromise; }; -export function usePrettifyEditors({ caller }: UsePrettifyEditorsArgs = {}) { +function DEFAULT_PRETTIFY_QUERY(query: string): string { + return print(parse(query)); +} + +export function usePrettifyEditors({ + caller, + onPrettifyQuery = DEFAULT_PRETTIFY_QUERY, +}: UsePrettifyEditorsArgs = {}) { const { queryEditor, headerEditor, variableEditor } = useEditorContext({ nonNull: true, caller: caller || _usePrettifyEditors, }); - return () => { + return async () => { if (variableEditor) { const variableEditorContent = variableEditor.getValue(); try { @@ -262,10 +282,13 @@ export function usePrettifyEditors({ caller }: UsePrettifyEditorsArgs = {}) { if (queryEditor) { const editorContent = queryEditor.getValue(); - const prettifiedEditorContent = print(parse(editorContent)); - - if (prettifiedEditorContent !== editorContent) { - queryEditor.setValue(prettifiedEditorContent); + try { + const prettifiedEditorContent = await onPrettifyQuery(editorContent); + if (prettifiedEditorContent !== editorContent) { + queryEditor.setValue(prettifiedEditorContent); + } + } catch { + /* Parsing query failed, skip prettification */ } } }; @@ -344,12 +367,10 @@ export function useAutoCompleteLeafs({ } // https://react.dev/learn/you-might-not-need-an-effect - export const useEditorState = (editor: 'query' | 'variable' | 'header') => { - 'use no memo'; // eslint-disable-line react-hooks/react-compiler -- TODO: check why query builder update only 1st field https://github.com/graphql/graphiql/issues/3836 - const context = useEditorContext({ - nonNull: true, - }); + // eslint-disable-next-line react-hooks/react-compiler -- TODO: check why query builder update only 1st field https://github.com/graphql/graphiql/issues/3836 + 'use no memo'; + const context = useEditorContext({ nonNull: true }); const editorInstance = context[`${editor}Editor` as const]; let valueString = ''; diff --git a/packages/graphiql-react/src/editor/query-editor.ts b/packages/graphiql-react/src/editor/query-editor.ts index 455053253f9..1e3d97cc1ff 100644 --- a/packages/graphiql-react/src/editor/query-editor.ts +++ b/packages/graphiql-react/src/editor/query-editor.ts @@ -11,7 +11,7 @@ import { GraphQLDocumentMode, OperationFacts, } from 'graphql-language-service'; -import { MutableRefObject, useEffect, useRef } from 'react'; +import { RefObject, useEffect, useRef } from 'react'; import { useExecutionContext } from '../execution'; import { useExplorerContext } from '../explorer'; @@ -34,6 +34,7 @@ import { useCompletion, useCopyQuery, UseCopyQueryArgs, + UsePrettifyEditorsArgs, useKeyMap, useMergeQuery, usePrettifyEditors, @@ -47,7 +48,8 @@ import { import { normalizeWhitespace } from './whitespace'; export type UseQueryEditorArgs = WriteableEditorProps & - Pick & { + Pick & + Pick & { /** * Invoked when a reference to the GraphQL schema (type or field) is clicked * as part of the editor or one of its tooltips. @@ -120,6 +122,7 @@ export function useQueryEditor( onClickReference, onCopyQuery, onEdit, + onPrettifyQuery, readOnly = false, }: UseQueryEditorArgs = {}, caller?: Function, @@ -147,9 +150,12 @@ export function useQueryEditor( const plugin = usePluginContext(); const copy = useCopyQuery({ caller: caller || _useQueryEditor, onCopyQuery }); const merge = useMergeQuery({ caller: caller || _useQueryEditor }); - const prettify = usePrettifyEditors({ caller: caller || _useQueryEditor }); + const prettify = usePrettifyEditors({ + caller: caller || _useQueryEditor, + onPrettifyQuery, + }); const ref = useRef(null); - const codeMirrorRef = useRef(); + const codeMirrorRef = useRef(undefined); const onClickReferenceRef = useRef< NonNullable @@ -474,7 +480,7 @@ export function useQueryEditor( function useSynchronizeSchema( editor: CodeMirrorEditor | null, schema: GraphQLSchema | null, - codeMirrorRef: MutableRefObject, + codeMirrorRef: RefObject, ) { useEffect(() => { if (!editor) { @@ -493,7 +499,7 @@ function useSynchronizeSchema( function useSynchronizeValidationRules( editor: CodeMirrorEditor | null, validationRules: ValidationRule[] | null, - codeMirrorRef: MutableRefObject, + codeMirrorRef: RefObject, ) { useEffect(() => { if (!editor) { @@ -512,7 +518,7 @@ function useSynchronizeValidationRules( function useSynchronizeExternalFragments( editor: CodeMirrorEditor | null, externalFragments: Map, - codeMirrorRef: MutableRefObject, + codeMirrorRef: RefObject, ) { const externalFragmentList = [...externalFragments.values()]; // eslint-disable-line react-hooks/exhaustive-deps -- false positive, variable is optimized by react-compiler, no need to wrap with useMemo diff --git a/packages/graphiql-react/src/editor/response-editor.tsx b/packages/graphiql-react/src/editor/response-editor.tsx index 967a83d58ed..91338daf0a1 100644 --- a/packages/graphiql-react/src/editor/response-editor.tsx +++ b/packages/graphiql-react/src/editor/response-editor.tsx @@ -1,8 +1,7 @@ import { formatError } from '@graphiql/toolkit'; import type { Position, Token } from 'codemirror'; import { ComponentType, useEffect, useRef, JSX } from 'react'; -// eslint-disable-next-line react/no-deprecated -- We can't refactor to root.unmount() from React 18 because we support React 16/17 too -import { unmountComponentAtNode, render } from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { useSchemaContext } from '../schema'; import { @@ -84,6 +83,7 @@ export function useResponseEditor( useEffect(() => { let isActive = true; + void importCodeMirrorImports().then(CodeMirror => { // Don't continue if the effect has already been cleaned up if (!isActive) { @@ -91,31 +91,25 @@ export function useResponseEditor( } // Handle image tooltips and custom tooltips - const tooltipDiv = document.createElement('div'); + const tooltipContainer = document.createElement('div'); + const tooltipRoot = createRoot(tooltipContainer); CodeMirror.registerHelper( 'info', 'graphql-results', (token: Token, _options: any, _cm: CodeMirrorEditor, pos: Position) => { - const infoElements: JSX.Element[] = []; - - const ResponseTooltipComponent = responseTooltipRef.current; - if (ResponseTooltipComponent) { - infoElements.push( - , - ); - } - - if (ImagePreview.shouldRender(token)) { - infoElements.push( - , - ); - } - if (!infoElements.length) { - unmountComponentAtNode(tooltipDiv); - return null; + const ResponseTooltip = responseTooltipRef.current; + const infoElements: JSX.Element[] = [ + ResponseTooltip && , + ImagePreview.shouldRender(token) && ( + + ), + ].filter((v): v is JSX.Element => Boolean(v)); + + if (infoElements.length) { + tooltipRoot.render(infoElements); + return tooltipContainer; } - render(infoElements, tooltipDiv); - return tooltipDiv; + tooltipRoot.unmount(); }, ); @@ -151,7 +145,7 @@ export function useResponseEditor( if (fetchError) { responseEditor?.setValue(fetchError); } - if (validationErrors.length > 0) { + if (validationErrors.length) { responseEditor?.setValue(formatError(validationErrors)); } }, [responseEditor, fetchError, validationErrors]); diff --git a/packages/graphiql-react/src/editor/variable-editor.ts b/packages/graphiql-react/src/editor/variable-editor.ts index a03a93cbdce..09bc7fb0046 100644 --- a/packages/graphiql-react/src/editor/variable-editor.ts +++ b/packages/graphiql-react/src/editor/variable-editor.ts @@ -17,7 +17,7 @@ import { usePrettifyEditors, useSynchronizeOption, } from './hooks'; -import { CodeMirrorType, WriteableEditorProps } from './types'; +import { WriteableEditorProps } from './types'; export type UseVariableEditorArgs = WriteableEditorProps & { /** @@ -64,8 +64,6 @@ export function useVariableEditor( const merge = useMergeQuery({ caller: caller || _useVariableEditor }); const prettify = usePrettifyEditors({ caller: caller || _useVariableEditor }); const ref = useRef(null); - const codeMirrorRef = useRef(); - useEffect(() => { let isActive = true; @@ -74,9 +72,6 @@ export function useVariableEditor( if (!isActive) { return; } - - codeMirrorRef.current = CodeMirror; - const container = ref.current; if (!container) { return; diff --git a/packages/graphiql-react/src/explorer/components/search.tsx b/packages/graphiql-react/src/explorer/components/search.tsx index 1246599908a..90f1e4f4ec6 100644 --- a/packages/graphiql-react/src/explorer/components/search.tsx +++ b/packages/graphiql-react/src/explorer/components/search.tsx @@ -8,7 +8,12 @@ import { isObjectType, } from 'graphql'; import { FC, useEffect, useRef, useState } from 'react'; -import { Combobox } from '@headlessui/react'; +import { + Combobox, + ComboboxInput, + ComboboxOptions, + ComboboxOption, +} from '@headlessui/react'; import { MagnifyingGlassIcon } from '../../icons'; import { useSchemaContext } from '../../schema'; import debounce from '../../utility/debounce'; @@ -85,7 +90,7 @@ export const Search: FC = () => { }} > - setSearchValue(event.target.value)} placeholder={`${isMacOs ? '⌘' : 'Ctrl'} K`} @@ -95,7 +100,7 @@ export const Search: FC = () => { /> {isFocused && ( - + {results.within.length + results.types.length + results.fields.length === @@ -105,13 +110,13 @@ export const Search: FC = () => { ) : ( results.within.map((result, i) => ( - - + )) )} {results.within.length > 0 && @@ -121,25 +126,25 @@ export const Search: FC = () => { ) : null} {results.types.map((result, i) => ( - - + ))} {results.fields.map((result, i) => ( - . - + ))} - + )} ); diff --git a/packages/graphiql-react/src/icons/implements.svg b/packages/graphiql-react/src/icons/implements.svg index 43b3374052a..afae9fc2721 100644 --- a/packages/graphiql-react/src/icons/implements.svg +++ b/packages/graphiql-react/src/icons/implements.svg @@ -11,8 +11,7 @@ stroke="currentColor" stroke-width="1.2" stroke-dasharray="4.241025 4.241025" - transform="rotate(22.5)" - transform-origin="center" + transform="rotate(22.5 6 6)" /> diff --git a/packages/graphiql-react/src/markdown.ts b/packages/graphiql-react/src/markdown.ts index e8d24628cff..c1fe6a36465 100644 --- a/packages/graphiql-react/src/markdown.ts +++ b/packages/graphiql-react/src/markdown.ts @@ -3,6 +3,8 @@ import MarkdownIt from 'markdown-it'; export const markdown = new MarkdownIt({ - breaks: true, + // we don't want to convert \n to
because in markdown a single newline is not a line break + // https://github.com/graphql/graphiql/issues/3155 + breaks: false, linkify: true, }); diff --git a/packages/graphiql-react/src/style/root.css b/packages/graphiql-react/src/style/root.css index 5f18fa336c6..8c8dbcfa09f 100644 --- a/packages/graphiql-react/src/style/root.css +++ b/packages/graphiql-react/src/style/root.css @@ -68,7 +68,7 @@ /* Layout */ --sidebar-width: 60px; --toolbar-width: 40px; - --session-header-height: 51px; + --session-header-height: 38.5px; } @media (prefers-color-scheme: dark) { diff --git a/packages/graphiql-react/src/toolbar/menu.tsx b/packages/graphiql-react/src/toolbar/menu.tsx index 1874679cbfc..7f8a6a9d154 100644 --- a/packages/graphiql-react/src/toolbar/menu.tsx +++ b/packages/graphiql-react/src/toolbar/menu.tsx @@ -1,7 +1,6 @@ import { ReactNode } from 'react'; import { clsx } from 'clsx'; import { DropdownMenu, Tooltip } from '../ui'; -import { createComponentGroup } from '../utility/component-group'; import './menu.css'; import { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; @@ -38,6 +37,6 @@ const ToolbarMenuRoot = ({ ); }; -export const ToolbarMenu = createComponentGroup(ToolbarMenuRoot, { +export const ToolbarMenu = Object.assign(ToolbarMenuRoot, { Item: DropdownMenu.Item, }); diff --git a/packages/graphiql-react/src/ui/dialog.tsx b/packages/graphiql-react/src/ui/dialog.tsx index 50c54bdb0c4..7ec068fe0cb 100644 --- a/packages/graphiql-react/src/ui/dialog.tsx +++ b/packages/graphiql-react/src/ui/dialog.tsx @@ -1,7 +1,6 @@ import { clsx } from 'clsx'; import { forwardRef, ReactElement, JSX } from 'react'; import { CloseIcon } from '../icons'; -import { createComponentGroup } from '../utility/component-group'; import { UnStyledButton } from './button'; import * as D from '@radix-ui/react-dialog'; import { Root as VisuallyHidden } from '@radix-ui/react-visually-hidden'; @@ -40,7 +39,7 @@ export function DialogRoot({ ); } -export const Dialog = createComponentGroup(DialogRoot, { +export const Dialog = Object.assign(DialogRoot, { Close: DialogClose, Title: D.Title, Trigger: D.Trigger, diff --git a/packages/graphiql-react/src/ui/dropdown.css b/packages/graphiql-react/src/ui/dropdown.css index 5f7b9186ee2..09f4c57524e 100644 --- a/packages/graphiql-react/src/ui/dropdown.css +++ b/packages/graphiql-react/src/ui/dropdown.css @@ -12,7 +12,7 @@ calc(var(--radix-dropdown-menu-content-available-height) - 10px), 400px ); - overflow-y: scroll; + overflow-y: auto; } .graphiql-dropdown-item { diff --git a/packages/graphiql-react/src/ui/dropdown.tsx b/packages/graphiql-react/src/ui/dropdown.tsx index 5009c102da4..4d39e706fbc 100644 --- a/packages/graphiql-react/src/ui/dropdown.tsx +++ b/packages/graphiql-react/src/ui/dropdown.tsx @@ -1,6 +1,5 @@ import { ComponentProps, forwardRef, ReactElement } from 'react'; import { clsx } from 'clsx'; -import { createComponentGroup } from '../utility/component-group'; import { Trigger, Portal, @@ -53,7 +52,7 @@ const Item = ({ className, children, ...props }: DropdownMenuItemProps) => ( ); -export const DropdownMenu = createComponentGroup(Root, { +export const DropdownMenu = Object.assign(Root, { Button, Item, Content, diff --git a/packages/graphiql-react/src/ui/tabs.css b/packages/graphiql-react/src/ui/tabs.css index d3ddb46e7e8..66cd5b73361 100644 --- a/packages/graphiql-react/src/ui/tabs.css +++ b/packages/graphiql-react/src/ui/tabs.css @@ -1,46 +1,84 @@ .graphiql-tabs { + --bg: hsl(var(--color-base)); + display: flex; align-items: center; - overflow-x: auto; - padding: var(--px-12); + gap: var(--px-8); + /* reset browser defaults */ + padding: 0; + margin: 0; + list-style: none; +} - & > :not(:first-child) { - margin-left: var(--px-12); - } +/* trick to shrink multiple tabs, instead of overflow container */ +.graphiql-tabs, +.graphiql-tab { + min-width: 0; } .graphiql-tab { - align-items: stretch; - border-radius: var(--border-radius-8); - color: hsla(var(--color-neutral), var(--alpha-secondary)); + border-radius: var(--border-radius-8) var(--border-radius-8) 0 0; + background: hsla(var(--color-neutral), var(--alpha-background-light)); + position: relative; display: flex; + max-width: 140px; - & > button.graphiql-tab-close { - visibility: hidden; - } - &.graphiql-tab-active > button.graphiql-tab-close, - &:hover > button.graphiql-tab-close, - &:focus-within > button.graphiql-tab-close { - visibility: unset; + /* disable shrinking while changing the operation name */ + &:not(:focus-within) { + transform: none !important; } + &:hover, + &:focus-within, &.graphiql-tab-active { - background-color: hsla(var(--color-neutral), var(--alpha-background-heavy)); - color: hsla(var(--color-neutral), 1); + background: var(--bg); + color: hsl(var(--color-neutral)); + + .graphiql-tab-close { + display: block; + } } -} -button.graphiql-tab-button { - padding: var(--px-4) 0 var(--px-4) var(--px-8); -} + .graphiql-tab-button { + border-radius: var(--border-radius-8) var(--border-radius-8) 0 0; + overflow: hidden; + text-overflow: ellipsis; + padding: var(--px-4) 28px var(--px-4) var(--px-8); -button.graphiql-tab-close { - align-items: center; - display: flex; - padding: var(--px-4) var(--px-8); + &:hover { + background: none; + } + } + + .graphiql-tab-close { + position: absolute; + right: min(var(--px-4), 5%); + top: 50%; + transform: translateY(-50%); + display: none; + background: var(--bg); + box-shadow: -10px 0 10px 0 var(--bg); + padding: var(--px-6); + line-height: 0; + + & > svg { + height: var(--px-8); + width: var(--px-8); + } + + &:hover { + background: var(--bg); + color: hsl(var(--color-neutral)); + overflow: hidden; /* bg in `:before` will not overflow from radius area */ - & > svg { - height: var(--px-8); - width: var(--px-8); + /* trick to add 2nd bg with opacity */ + &:before { + content: ''; + position: absolute; + inset: 0; + z-index: -1; + background: hsla(var(--color-neutral), 0.3); + } + } } } diff --git a/packages/graphiql-react/src/ui/tabs.tsx b/packages/graphiql-react/src/ui/tabs.tsx index a0a2c7dd920..331c0f5fa61 100644 --- a/packages/graphiql-react/src/ui/tabs.tsx +++ b/packages/graphiql-react/src/ui/tabs.tsx @@ -2,9 +2,7 @@ import { forwardRef, ReactNode, JSX } from 'react'; import { clsx } from 'clsx'; import { Reorder } from 'framer-motion'; import { CloseIcon } from '../icons'; -import { createComponentGroup } from '../utility/component-group'; import { UnStyledButton } from './button'; -import { Tooltip } from './tooltip'; import './tabs.css'; @@ -21,7 +19,7 @@ const TabRoot = forwardRef( {...props} ref={ref} value={value} - aria-selected={isActive ? 'true' : undefined} + aria-selected={isActive} role="tab" className={clsx( 'graphiql-tab', @@ -38,36 +36,34 @@ TabRoot.displayName = 'Tab'; const TabButton = forwardRef< HTMLButtonElement, JSX.IntrinsicElements['button'] ->((props, ref) => ( +>(({ children, className, ...props }, ref) => ( - {props.children} + {children} )); TabButton.displayName = 'Tab.Button'; const TabClose = forwardRef( (props, ref) => ( - - - - - + + + ), ); TabClose.displayName = 'Tab.Close'; -export const Tab = createComponentGroup(TabRoot, { +export const Tab = Object.assign(TabRoot, { Button: TabButton, Close: TabClose, }); diff --git a/packages/graphiql-react/src/ui/tooltip.tsx b/packages/graphiql-react/src/ui/tooltip.tsx index af141a9364c..125d7c10db6 100644 --- a/packages/graphiql-react/src/ui/tooltip.tsx +++ b/packages/graphiql-react/src/ui/tooltip.tsx @@ -1,15 +1,14 @@ -import { ReactElement, ReactNode } from 'react'; +import { FC, ReactNode } from 'react'; import * as T from '@radix-ui/react-tooltip'; -import { createComponentGroup } from '../utility/component-group'; import './tooltip.css'; -export function TooltipRoot({ +export const TooltipRoot: FC = ({ children, align = 'start', side = 'bottom', sideOffset = 5, label, -}: T.TooltipContentProps & { label: ReactNode }): ReactElement { +}) => { return ( {children} @@ -25,8 +24,8 @@ export function TooltipRoot({ ); -} +}; -export const Tooltip = createComponentGroup(TooltipRoot, { +export const Tooltip = Object.assign(TooltipRoot, { Provider: T.Provider, }); diff --git a/packages/graphiql-react/src/utility/component-group.ts b/packages/graphiql-react/src/utility/component-group.ts deleted file mode 100644 index 71e67ac3c32..00000000000 --- a/packages/graphiql-react/src/utility/component-group.ts +++ /dev/null @@ -1,15 +0,0 @@ -'use no memo'; - -import { JSXElementConstructor } from 'react'; - -export const createComponentGroup = < - Root extends JSXElementConstructor, - Children extends { [key: string]: JSXElementConstructor }, ->( - root: Root, - children: Children, -): Root & Children => - Object.entries(children).reduce((r, [key, value]) => { - r[key] = value; - return r; - }, root); diff --git a/packages/graphiql-react/tsconfig.json b/packages/graphiql-react/tsconfig.json index ccf8cb89dee..d1c216fef77 100644 --- a/packages/graphiql-react/tsconfig.json +++ b/packages/graphiql-react/tsconfig.json @@ -5,7 +5,7 @@ "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, "skipLibCheck": true, - "esModuleInterop": false, + "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, @@ -15,9 +15,6 @@ "isolatedModules": true, "jsx": "react-jsx", "declaration": true, - "declarationDir": "types", "types": ["vitest/globals", "@testing-library/jest-dom"] - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + } } diff --git a/packages/graphiql-react/tsconfig.node.json b/packages/graphiql-react/tsconfig.node.json deleted file mode 100644 index e993792cb12..00000000000 --- a/packages/graphiql-react/tsconfig.node.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "esnext", - "moduleResolution": "node" - }, - "include": ["vite.config.ts"] -} diff --git a/packages/graphiql-react/vite.config.mts b/packages/graphiql-react/vite.config.mts index 0b9c34108b2..2094b5108c5 100644 --- a/packages/graphiql-react/vite.config.mts +++ b/packages/graphiql-react/vite.config.mts @@ -2,12 +2,12 @@ import { defineConfig, PluginOption } from 'vite'; import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; -import postCssNestingPlugin from 'postcss-nesting'; import type { PluginOptions as ReactCompilerConfig } from 'babel-plugin-react-compiler'; -import packageJSON from './package.json'; +import packageJSON from './package.json' assert { type: 'json' }; +import dts from 'vite-plugin-dts'; export const reactCompilerConfig: Partial = { - target: '17', + target: '18', sources(filename) { if (filename.includes('__tests__')) { return false; @@ -53,26 +53,34 @@ export const plugins: PluginOption[] = [ titleProp: true, }, }), + dts({ + include: ['src/**'], + outDir: ['dist'], + exclude: ['**/*.spec.{ts,tsx}', '**/__tests__/'], + }), ]; export default defineConfig({ plugins, css: { - postcss: { - plugins: [postCssNestingPlugin()], - }, + transformer: 'lightningcss', }, build: { minify: false, sourcemap: true, lib: { entry: 'src/index.ts', - fileName: 'index', - formats: ['cjs', 'es'], + fileName(_format, entryName) { + const filePath = entryName.replace(/\.svg$/, ''); + return `${filePath}.js`; + }, + formats: ['es'], + cssFileName: 'style', }, rollupOptions: { external: [ 'react/jsx-runtime', + 'react-dom/client', // Exclude peer dependencies and dependencies from bundle ...Object.keys(packageJSON.peerDependencies), ...Object.keys(packageJSON.dependencies), @@ -80,7 +88,7 @@ export default defineConfig({ /codemirror[/-]/, ], output: { - chunkFileNames: '[name].[format].js', + preserveModules: true, }, }, }, diff --git a/packages/graphiql/CHANGELOG.md b/packages/graphiql/CHANGELOG.md index 02fc07ad16c..978db1997f6 100644 --- a/packages/graphiql/CHANGELOG.md +++ b/packages/graphiql/CHANGELOG.md @@ -1,5 +1,192 @@ # Change Log +## 4.0.0-alpha.5 + +### Minor Changes + +- [#3733](https://github.com/graphql/graphiql/pull/3733) [`8dbddb5`](https://github.com/graphql/graphiql/commit/8dbddb50273720d76f895af6b783b04204c68e03) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Add support for `onPrettifyQuery` callback to enable customised query formatting + +### Patch Changes + +- Updated dependencies [[`8dbddb5`](https://github.com/graphql/graphiql/commit/8dbddb50273720d76f895af6b783b04204c68e03)]: + - @graphiql/react@1.0.0-alpha.4 + +## 4.0.0-alpha.4 + +### Minor Changes + +- [#3728](https://github.com/graphql/graphiql/pull/3728) [`a1a5208`](https://github.com/graphql/graphiql/commit/a1a5208aeebe4ff622e83cd355f8b4e9b7fa011c) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `.graphiql-session` class + +### Patch Changes + +- [#3414](https://github.com/graphql/graphiql/pull/3414) [`f8b719f`](https://github.com/graphql/graphiql/commit/f8b719f215a79038d1b2a54ddfef461fd849a912) Thanks [@leonardehrenfried](https://github.com/leonardehrenfried)! - Respect Markdown format: ignore single newline + +- [#3730](https://github.com/graphql/graphiql/pull/3730) [`360a038`](https://github.com/graphql/graphiql/commit/360a0385d4ef0105beb8e76044a78f5cd43c9448) Thanks [@dimaMachina](https://github.com/dimaMachina)! - rollback `position: absolute` style for `.graphiql-logo` because tabs will behind logo + +- [#3726](https://github.com/graphql/graphiql/pull/3726) [`196e9a0`](https://github.com/graphql/graphiql/commit/196e9a081ffc0df16a5537c8ec0fb622fc3ba0b0) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `right: var(--px-16)` instead of `right: 0` for `.graphiql-logo` + +- Updated dependencies [[`f8b719f`](https://github.com/graphql/graphiql/commit/f8b719f215a79038d1b2a54ddfef461fd849a912), [`360a038`](https://github.com/graphql/graphiql/commit/360a0385d4ef0105beb8e76044a78f5cd43c9448)]: + - @graphiql/react@1.0.0-alpha.3 + +## 4.0.0-alpha.3 + +### Patch Changes + +- [#3720](https://github.com/graphql/graphiql/pull/3720) [`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `overflow-y: scroll` with `overflow-y: auto` + +- [#3720](https://github.com/graphql/graphiql/pull/3720) [`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242) Thanks [@dimaMachina](https://github.com/dimaMachina)! - replace `Tooltip`s in tabs with html `title="..."` attribute + +- Updated dependencies [[`79f3abf`](https://github.com/graphql/graphiql/commit/79f3abf9b697c448442e32eb5a21b7ff720bc242)]: + - @graphiql/react@1.0.0-alpha.2 + +## 4.0.0-alpha.2 + +### Patch Changes + +- [#3716](https://github.com/graphql/graphiql/pull/3716) [`cc2808f`](https://github.com/graphql/graphiql/commit/cc2808f9b0d9ac0f98603299ec67e2a659cbfcd7) Thanks [@dimaMachina](https://github.com/dimaMachina)! - use `position: absolute` for `.graphiql-logo` class + +- Updated dependencies [[`bf0c4e7`](https://github.com/graphql/graphiql/commit/bf0c4e7236f4a68448063aa0c6a4ed439e869a9f)]: + - @graphiql/react@1.0.0-alpha.1 + +## 4.0.0-alpha.1 + +### Major Changes + +- [#3713](https://github.com/graphql/graphiql/pull/3713) [`27bbc51`](https://github.com/graphql/graphiql/commit/27bbc51a69504ffa9c6efbb17f112668f38fe52d) Thanks [@dimaMachina](https://github.com/dimaMachina)! - show tabs even there is only 1 tab + +- [#3707](https://github.com/graphql/graphiql/pull/3707) [`3c901c1`](https://github.com/graphql/graphiql/commit/3c901c104123750f45bcd64ade5b0ab9706d3146) Thanks [@dimaMachina](https://github.com/dimaMachina)! - Remove `toolbar.additionalContent` and `toolbar.additionalComponent` props in favor of `GraphiQL.Toolbar` render props. + + ## Migration from `toolbar.additionalContent` + + #### Before + + ```jsx + My button }} /> + ``` + + #### After + + ```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + + ``` + + ### Migration from `toolbar.additionalComponent` + + #### Before + + ```jsx + My button; + }, + }} + /> + ``` + + #### After + + ```jsx + + + {({ merge, prettify, copy }) => ( + <> + {prettify} + {merge} + {copy} + + + )} + + + ``` + + *** + + Additionally, you can sort default toolbar buttons in different order or remove unneeded buttons for you: + + ```jsx + + + {({ prettify, copy }) => ( + <> + {copy /* Copy button will be first instead of default last */} + {/* Merge button is removed from toolbar */} + {prettify} + + )} + + + ``` + +## 4.0.0-alpha.0 + +### Major Changes + +- [#3706](https://github.com/graphql/graphiql/pull/3706) [`343dd59`](https://github.com/graphql/graphiql/commit/343dd599ee10b0670cd7ab4dfaa65344f0d48c84) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove default export + + ## Migration + + ### Before + + ```jsx + import GraphiQL from 'graphiql'; + ``` + + ### After + + ```jsx + import { GraphiQL } from 'graphiql'; + ``` + +- [#3687](https://github.com/graphql/graphiql/pull/3687) [`09e7004`](https://github.com/graphql/graphiql/commit/09e700403beb6c7290d165df33a2455ac2196971) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `disableTabs` option + +- [#3688](https://github.com/graphql/graphiql/pull/3688) [`0fdd9b9`](https://github.com/graphql/graphiql/commit/0fdd9b9f32513d96281f577a5d9bd2fefb5f05d4) Thanks [@dimaMachina](https://github.com/dimaMachina)! - remove `data-testid="graphiql-container"` + +- [#3679](https://github.com/graphql/graphiql/pull/3679) [`5d90e0e`](https://github.com/graphql/graphiql/commit/5d90e0eed58214c5926e6e0edb196971b15b1121) Thanks [@dimaMachina](https://github.com/dimaMachina)! - migrate from `webpack` to `vite` + + changed exports + + ```diff + -graphiql/graphiql.css + +graphiql/style.css + ``` + + changed cdn paths, `dist/index.umd.js` and `dist/style.css` are minified + + ```diff + -https://unpkg.com/graphiql/graphiql.js + -https://unpkg.com/graphiql/graphiql.min.js + +https://unpkg.com/graphiql/dist/index.umd.js + -https://unpkg.com/graphiql/graphiql.css + -https://unpkg.com/graphiql/graphiql.min.css + +https://unpkg.com/graphiql/dist/style.css + ``` + +- [#3644](https://github.com/graphql/graphiql/pull/3644) [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - new looks of tabs + + - fix `disableTabs` when `Add tab` button is still shown + +### Patch Changes + +- [#3683](https://github.com/graphql/graphiql/pull/3683) [`8efb873`](https://github.com/graphql/graphiql/commit/8efb873458489ce3497d917bcafd4ad8dfcbe6c8) Thanks [@dimaMachina](https://github.com/dimaMachina)! - update graphql to `16.9.0` and use vite `define` configuration to remove development code from cdn bundle + +- [#3692](https://github.com/graphql/graphiql/pull/3692) [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad) Thanks [@dimaMachina](https://github.com/dimaMachina)! - - prefer `location` over `window.location` + - prefer `navigator` over `window.navigator` +- Updated dependencies [[`00415d2`](https://github.com/graphql/graphiql/commit/00415d2940c4d76a4a9e683e9fa0504ba97dd627), [`9baf1f0`](https://github.com/graphql/graphiql/commit/9baf1f0fc9f32404fbb8bf57b3d1c2c2c8778ddb), [`8ff87d7`](https://github.com/graphql/graphiql/commit/8ff87d7b6b3d5d12b539612a39ca3abf7e631106), [`82bc961`](https://github.com/graphql/graphiql/commit/82bc961a33c4e9da29dffb4a603035a4909f49ad), [`3c1a345`](https://github.com/graphql/graphiql/commit/3c1a345acd9bf07b45bc230009cb57c51c425673)]: + - @graphiql/react@1.0.0-alpha.0 + ## 3.9.0 ### Minor Changes diff --git a/packages/graphiql/README.md b/packages/graphiql/README.md index 817cf6a3171..d851dfee0c9 100644 --- a/packages/graphiql/README.md +++ b/packages/graphiql/README.md @@ -45,8 +45,7 @@ _/ˈɡrafək(ə)l/_ A graphical interactive in-browser GraphQL IDE. ## Examples -- [`Unpkg (CDN)`](../../examples/graphiql-cdn) - A single HTML file using CDN - assets and a script tag +- [`CDN (ESM-based)`](../../examples/graphiql-cdn) - A single HTML file using [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) from http URLs and a ` -``` +Use the modern, ESM-based CDN approach. +See the [ESM-based example](../../examples/graphiql-cdn) for setup details. + +#### UMD (deprecated) -(see: Usage UMD Bundle below for more required script tags) +> [!WARNING] +> +> The UMD CDN build is **deprecated** and will be removed in a future major release of GraphiQL. +> Please migrate to the [ESM-based example](../../examples/graphiql-cdn). ## Usage @@ -96,7 +98,7 @@ may return a `Promise` for queries or mutations, but also an `Observable` or an An easy way to get create such a function is the [`createGraphiQLFetcher`](../graphiql-toolkit/src/create-fetcher/createFetcher.ts) method exported from the `@graphiql/toolkit` package. If you want to implement -your own fetcher function you can use the `Fetcher` type from +your own fetcher function, you can use the `Fetcher` type from `@graphiql/toolkit` to make sure the signature matches what GraphiQL expects. The following is everything you need to render GraphiQL in your React @@ -105,9 +107,8 @@ application: ```jsx import { createGraphiQLFetcher } from '@graphiql/toolkit'; import { GraphiQL } from 'graphiql'; -import React from 'react'; import { createRoot } from 'react-dom/client'; -import 'graphiql/graphiql.css'; +import 'graphiql/style.css'; const fetcher = createGraphiQLFetcher({ url: 'https://my.backend/graphql' }); @@ -115,12 +116,6 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -### Using as UMD bundle over CDN (Unpkg, JSDelivr, etc) - -There exist pre-bundled static assets that allow you to easily render GraphiQL -just by putting together a single HTML file. Check out the `index.html` file in -the [example project](../../examples/graphiql-cdn) in this repository. - ## Customize GraphiQL supports customization in UI and behavior by accepting React props and diff --git a/packages/graphiql/cypress/e2e/errors.cy.ts b/packages/graphiql/cypress/e2e/errors.cy.ts index a6613665f19..b46511b3a8d 100644 --- a/packages/graphiql/cypress/e2e/errors.cy.ts +++ b/packages/graphiql/cypress/e2e/errors.cy.ts @@ -39,7 +39,7 @@ describe('Errors', () => { cy.visit('/'); /** * We can't use `cy.assertQueryResult` here because the stack contains line - * and column numbers of the `graphiql.min.js` bundle which are not stable. + * and column numbers of the `index.umd.js` bundle which are not stable. */ cy.get('section.result-window').should(element => { expect(element.get(0).innerText).to.contain( diff --git a/packages/graphiql/cypress/e2e/incremental-delivery.cy.ts b/packages/graphiql/cypress/e2e/incremental-delivery.cy.ts index d10273434b2..00e46ff0312 100644 --- a/packages/graphiql/cypress/e2e/incremental-delivery.cy.ts +++ b/packages/graphiql/cypress/e2e/incremental-delivery.cy.ts @@ -106,7 +106,7 @@ describeOrSkip('IncrementalDelivery support via fetcher', () => { This tests that; 1. user ({name}) => { name } 2. user ({age}) => { name, age } - 3. user.friends.0 ({name}) => { name, age, friends: [{name}] } <- can sometimes happen before 4, due the the promise race + 3. user.friends.0 ({name}) => { name, age, friends: [{name}] } <- can sometimes happen before 4, due to the promise race 4. user.friends.0 ({age}) => { name, age, friends: [{name, age}] } This shows us that we can deep merge defers, deep merge streams, and also deep merge defers inside streams diff --git a/packages/graphiql/cypress/e2e/prettify.cy.ts b/packages/graphiql/cypress/e2e/prettify.cy.ts index 6e2224f28dc..ba8e3e16ada 100644 --- a/packages/graphiql/cypress/e2e/prettify.cy.ts +++ b/packages/graphiql/cypress/e2e/prettify.cy.ts @@ -1,4 +1,5 @@ import { version } from 'graphql'; + let describeOrSkip = describe.skip; // hard to account for the extra \n between 15/16 so these only run for 16 for now @@ -25,6 +26,26 @@ const brokenQuery = 'longDescriptionType {id}}'; const brokenVariables = '"a": 1}'; describeOrSkip('GraphiQL Prettify', () => { + describe('onPrettifyQuery', () => { + const rawQuery = '{ test\n\nid }'; + const resultQuery = '{ test id }'; + + it('should work while click on prettify button', () => { + cy.visit(`/?query=${rawQuery}&onPrettifyQuery=true`); + cy.clickPrettify(); + cy.assertHasValues({ query: resultQuery }); + }); + + it('should work while click on key map short cut', () => { + cy.visit(`/?query=${rawQuery}&onPrettifyQuery=true`); + cy.get('.graphiql-query-editor textarea').type('{shift}{ctrl}P', { + force: true, + }); + cy.get('.graphiql-query-editor textarea').type('{esc}'); + cy.assertHasValues({ query: resultQuery }); + }); + }); + it('Regular prettification', () => { cy.visitWithOp({ query: uglyQuery, variablesString: uglyVariables }); diff --git a/packages/graphiql/cypress/e2e/tabs.cy.ts b/packages/graphiql/cypress/e2e/tabs.cy.ts index 43df5a2db4c..c3dac4a5705 100644 --- a/packages/graphiql/cypress/e2e/tabs.cy.ts +++ b/packages/graphiql/cypress/e2e/tabs.cy.ts @@ -2,8 +2,8 @@ describe('Tabs', () => { it('Should store editor contents when switching between tabs', () => { cy.visit('/?defaultQuery=&query='); - // Assert that no tab visible when there's only one session - cy.get('#graphiql-session-tab-0').should('not.exist'); + // Assert that tab visible when there's only one session + cy.get('.graphiql-tab-button').eq(0).should('exist'); // Enter a query without operation name cy.get('.graphiql-query-editor textarea').type('{id', { force: true }); @@ -18,7 +18,7 @@ describe('Tabs', () => { cy.get('.graphiql-query-editor textarea').type('query Foo {image', { force: true, }); - cy.get('#graphiql-session-tab-1').should('have.text', 'Foo'); + cy.get('.graphiql-tab-button').eq(1).should('have.text', 'Foo'); // Enter variables cy.get('.graphiql-editor-tool textarea') @@ -35,11 +35,11 @@ describe('Tabs', () => { cy.clickExecuteQuery(); // Switch back to the first tab - cy.get('#graphiql-session-tab-0').click(); + cy.get('.graphiql-tab-button').eq(0).click(); // Assert tab titles - cy.get('#graphiql-session-tab-0').should('have.text', ''); - cy.get('#graphiql-session-tab-1').should('have.text', 'Foo'); + cy.get('.graphiql-tab-button').eq(0).should('have.text', ''); + cy.get('.graphiql-tab-button').eq(1).should('have.text', 'Foo'); // Assert editor values cy.assertHasValues({ @@ -50,11 +50,11 @@ describe('Tabs', () => { }); // Switch back to the second tab - cy.get('#graphiql-session-tab-1').click(); + cy.get('.graphiql-tab-button').eq(1).click(); // Assert tab titles - cy.get('#graphiql-session-tab-0').should('have.text', ''); - cy.get('#graphiql-session-tab-1').should('have.text', 'Foo'); + cy.get('.graphiql-tab-button').eq(0).should('have.text', ''); + cy.get('.graphiql-tab-button').eq(1).should('have.text', 'Foo'); // Assert editor values cy.assertHasValues({ @@ -65,10 +65,10 @@ describe('Tabs', () => { }); // Close tab - cy.get('#graphiql-session-tab-1 + .graphiql-tab-close').click(); + cy.get('.graphiql-tab-button + .graphiql-tab-close').eq(1).click(); - // Assert that no tab visible when there's only one session - cy.get('#graphiql-session-tab-0').should('not.exist'); + // Assert that tab close button not visible when there is only 1 tab + cy.get('.graphiql-tab-button + .graphiql-tab-close').should('not.exist'); // Assert editor values cy.assertHasValues({ @@ -99,7 +99,7 @@ describe('Tabs', () => { cy.get('.graphiql-tab-button + .graphiql-tab-close').eq(1).click(); - cy.get('.graphiql-tab-button').should('have.length', 0); + cy.get('.graphiql-tab-button').should('have.length', 1); }); }); }); diff --git a/packages/graphiql/cypress/support/commands.ts b/packages/graphiql/cypress/support/commands.ts index 411033d2fcc..4e34051cab5 100644 --- a/packages/graphiql/cypress/support/commands.ts +++ b/packages/graphiql/cypress/support/commands.ts @@ -1,12 +1,10 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** +/** + * This example commands.ts shows you how to create various custom commands and + * overwrite existing commands. + * + * For more comprehensive examples of custom commands, please read more here: + * https://on.cypress.io/custom-commands + */ /// @@ -26,7 +24,7 @@ declare namespace Cypress { interface Chainable { /** - * Custom command to select DOM element by data-cy attribute. + * Custom command to select a DOM element by `data-cy` attribute. * @example cy.dataCy('greeting') */ dataCy(value: string): Chainable; @@ -56,11 +54,15 @@ Cypress.Commands.add('dataCy', value => { // @ts-expect-error -- fixme Cypress.Commands.add('clickExecuteQuery', () => { + // Check CodeMirror was initialized + cy.get('.graphiql-query-editor .CodeMirror-scroll').should('exist'); return cy.get('.graphiql-execute-button').click(); }); // @ts-expect-error -- fixme Cypress.Commands.add('clickPrettify', () => { + // Check CodeMirror was initialized + cy.get('.graphiql-query-editor .CodeMirror-scroll').should('exist'); return cy.get('[aria-label="Prettify query (Shift-Ctrl-P)"]').click(); }); @@ -139,11 +141,11 @@ function codeWithLineNumbers(code: string): string { .join('\n'); } -function normalize(str: string) { +function normalize(str: string): string { return str.replaceAll('​', ''); } -function normalizeWhitespace(str: string) { +function normalizeWhitespace(str: string): string { return str.replaceAll('\xA0', ' '); } diff --git a/packages/graphiql/index.html b/packages/graphiql/index.html index 04073bb4c0e..67dce46c302 100644 --- a/packages/graphiql/index.html +++ b/packages/graphiql/index.html @@ -24,6 +24,7 @@ } + - +
Loading…
- diff --git a/packages/graphiql/package.json b/packages/graphiql/package.json index 7e5d475b5e7..d9aca9c28ba 100644 --- a/packages/graphiql/package.json +++ b/packages/graphiql/package.json @@ -1,10 +1,11 @@ { "name": "graphiql", "version": "3.9.0", + "sideEffects": false, "description": "An graphical interactive in-browser GraphQL IDE.", "contributors": [ "Hyohyeon Jeong ", - "Lee Byron (http://leebyron.com/)" + "Lee Byron (https://leebyron.com)" ], "repository": { "type": "git", @@ -16,11 +17,10 @@ "url": "https://github.com/graphql/graphiql/issues?q=issue+label:graphiql" }, "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.mjs", "types": "dist/index.d.ts", "files": [ "dist", + "!dist/e2e.*", "graphiql.js", "graphiql.js.map", "graphiql.min.js", @@ -33,16 +33,15 @@ "./style.css": "./dist/style.css", "./graphiql.css": "./dist/style.css", ".": { - "require": "./dist/index.js", - "import": "./dist/index.mjs", - "types": "./dist/index.d.ts" + "types": "./dist/index.d.ts", + "import": "./dist/index.js" } }, "scripts": { "prebuild": "yarn types:check", "types:check": "tsc --noEmit", "build": "vite build && UMD=true vite build", - "cypress-open": "yarn dev 'cypress open'", + "cypress-open": "yarn dev 'cypress open --browser electron'", "dev": "concurrently 'cross-env PORT=8080 node test/e2e-server' vite", "e2e": "yarn e2e-server 'cypress run'", "e2e-server": "start-server-and-test 'cross-env PORT=8080 node test/e2e-server' 'http-get://localhost:8080/graphql?query={test { id }}'", @@ -55,28 +54,26 @@ }, "peerDependencies": { "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "react": "^18 || ^19", + "react-dom": "^18 || ^19" }, "devDependencies": { + "lightningcss": "^1.29.3", "babel-plugin-react-compiler": "19.1.0-rc.1", - "vite-plugin-dts": "^4.3.0", - "vite": "^5.3.6", - "postcss-lightningcss": "^1.0.1", - "@vitejs/plugin-react": "^4.3.1", + "vite-plugin-dts": "^4.5.3", + "vite": "^6.3.3", + "@vitejs/plugin-react": "^4.4.1", "@graphiql/toolkit": "^0.11.2", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.1.0", "cross-env": "^7.0.2", "cypress": "^13.13.2", "express": "^4.20.0", - "graphql": "^16.9.0", - "graphql-http": "^1.22.1", + "graphql": "^16.11.0", + "graphql-helix": "^1.13.0", "graphql-subscriptions": "^2.0.0", - "postcss": "8.4.31", - "postcss-import": "15.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", "start-server-and-test": "^1.10.11", "subscriptions-transport-ws": "0.11.0", "typescript": "^4.6.3", diff --git a/packages/graphiql/postcss.config.js b/packages/graphiql/postcss.config.js deleted file mode 100644 index 31470672ba7..00000000000 --- a/packages/graphiql/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - plugins: { - // https://github.com/postcss/postcss-import/issues/442#issuecomment-822427606 - 'postcss-import': '', - 'postcss-lightningcss': { - browsers: '>= .25%', - }, - }, -}; diff --git a/packages/graphiql/resources/build.sh b/packages/graphiql/resources/build.sh deleted file mode 100644 index e112482842c..00000000000 --- a/packages/graphiql/resources/build.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -if [ ! -d "node_modules/.bin" ]; then - echo "Be sure to run \`yarn install\` before building GraphiQL." - exit 1 -fi - -babel src --ignore __tests__ --out-dir dist/ -ESM=true babel src --ignore __tests__ --out-dir esm/ -echo "Bundling graphiql.js..." -browserify -g browserify-shim -s GraphiQL dist/index.js > graphiql.js -echo "Bundling graphiql.min.js..." -browserify -g browserify-shim -t uglifyify -s GraphiQL graphiql.js | uglifyjs -c > graphiql.min.js -echo "Bundling graphiql.css..." -postcss --no-map --use autoprefixer -d dist/ css/*.css -cat dist/*.css > graphiql.css -echo "Done" diff --git a/packages/graphiql/resources/checkgit.sh b/packages/graphiql/resources/checkgit.sh deleted file mode 100644 index f6798e23d40..00000000000 --- a/packages/graphiql/resources/checkgit.sh +++ /dev/null @@ -1,27 +0,0 @@ -# -# This script determines if current git state is the up to date master. If so -# it exits normally. If not it prompts for an explicit continue. This script -# intends to protect from versioning for NPM without first pushing changes -# and including any changes on master. -# - -# First fetch to ensure git is up to date. Fail-fast if this fails. -git fetch; -if [[ $? -ne 0 ]]; then exit 1; fi; - -# Extract useful information. -GITBRANCH=$(git branch -v 2> /dev/null | sed '/^[^*]/d'); -GITBRANCHNAME=$(echo "$GITBRANCH" | sed 's/* \([A-Za-z0-9_\-]*\).*/\1/'); -GITBRANCHSYNC=$(echo "$GITBRANCH" | sed 's/* [^[]*.\([^]]*\).*/\1/'); - -# Check if master is checked out -if [ "$GITBRANCHNAME" != "master" ]; then - read -p "Git not on master but $GITBRANCHNAME. Continue? (y|N) " yn; - if [ "$yn" != "y" ]; then exit 1; fi; -fi; - -# Check if branch is synced with remote -if [ "$GITBRANCHSYNC" != "" ]; then - read -p "Git not up to date but $GITBRANCHSYNC. Continue? (y|N) " yn; - if [ "$yn" != "y" ]; then exit 1; fi; -fi; diff --git a/packages/graphiql/resources/logo.svg b/packages/graphiql/resources/logo.svg index 43e513e06ca..e50db408fa2 100644 --- a/packages/graphiql/resources/logo.svg +++ b/packages/graphiql/resources/logo.svg @@ -1,27 +1,15 @@ - + + + - - + - + - diff --git a/packages/graphiql/src/GraphiQL.spec.tsx b/packages/graphiql/src/GraphiQL.spec.tsx index eb363ff13a3..5d8f1fd8e38 100644 --- a/packages/graphiql/src/GraphiQL.spec.tsx +++ b/packages/graphiql/src/GraphiQL.spec.tsx @@ -415,13 +415,13 @@ describe('GraphiQL', () => { }); describe('Tabs', () => { - it('show tabs if there are more than one', async () => { + it('show tabs', async () => { const { container } = render(); await waitFor(() => { expect( container.querySelectorAll('.graphiql-tabs .graphiql-tab'), - ).toHaveLength(0); + ).toHaveLength(1); }); act(() => { @@ -497,7 +497,7 @@ describe('GraphiQL', () => { await waitFor(() => { expect( container.querySelectorAll('.graphiql-tabs .graphiql-tab'), - ).toHaveLength(0); + ).toHaveLength(1); expect( container.querySelectorAll('.graphiql-tab .graphiql-tab-close'), ).toHaveLength(0); @@ -604,28 +604,6 @@ describe('GraphiQL', () => { expect(getByText('My Exported Type Logo')).toBeInTheDocument(); }); }); - - it('can be overridden using a named component', async () => { - const WrappedLogo = () => { - return ( -
- My Named Component Logo -
- ); - }; - WrappedLogo.displayName = 'GraphiQLLogo'; - - const { container, getByText } = render( - - - , - ); - - await waitFor(() => { - expect(container.querySelector('.test-wrapper')).toBeInTheDocument(); - expect(getByText('My Named Component Logo')).toBeInTheDocument(); - }); - }); }); describe('GraphiQL.Toolbar', () => { @@ -633,7 +611,7 @@ describe('GraphiQL', () => { const { container } = render( - + {() => } , ); @@ -646,35 +624,6 @@ describe('GraphiQL', () => { ).toHaveLength(1); }); }); - - it('can be overridden using a named component', async () => { - const WrappedToolbar = () => { - return ( -
- - - - , -
- ); - }; - WrappedToolbar.displayName = 'GraphiQLToolbar'; - - const { container } = render( - - - , - ); - - await waitFor(() => { - expect(container.querySelector('.test-wrapper')).toBeInTheDocument(); - expect( - container.querySelectorAll( - '[role="toolbar"] .graphiql-toolbar-button', - ), - ).toHaveLength(1); - }); - }); }); describe('GraphiQL.Footer', () => { @@ -693,33 +642,6 @@ describe('GraphiQL', () => { ).toHaveLength(1); }); }); - - it('can be overridden using a named component', async () => { - const WrappedFooter = () => { - return ( -
- - - - , -
- ); - }; - WrappedFooter.displayName = 'GraphiQLFooter'; - - const { container } = render( - - - , - ); - - await waitFor(() => { - expect(container.querySelector('.test-wrapper')).toBeInTheDocument(); - expect( - container.querySelectorAll('.graphiql-footer button'), - ).toHaveLength(1); - }); - }); }); }); }); diff --git a/packages/graphiql/src/GraphiQL.tsx b/packages/graphiql/src/GraphiQL.tsx index 4927bc94087..8178050c367 100644 --- a/packages/graphiql/src/GraphiQL.tsx +++ b/packages/graphiql/src/GraphiQL.tsx @@ -6,14 +6,20 @@ */ import type { - ComponentType, MouseEventHandler, PropsWithChildren, ReactNode, ReactElement, - JSXElementConstructor, + JSX, +} from 'react'; +import { + Fragment, + useState, + useEffect, + version, + Children, + cloneElement, } from 'react'; -import { Fragment, useState, useEffect, version, Children } from 'react'; import { Button, ButtonGroup, @@ -71,20 +77,6 @@ if (majorVersion < 16) { ); } -export type GraphiQLToolbarConfig = { - /** - * This content will be rendered after the built-in buttons of the toolbar. - * Note that this will not apply if you provide a completely custom toolbar - * (by passing `GraphiQL.Toolbar` as child to the `GraphiQL` component). - */ - additionalContent?: ReactNode; - - /** - * same as above, except a component with access to context - */ - additionalComponent?: JSXElementConstructor; -}; - /** * API docs for this live here: * @@ -135,7 +127,18 @@ export function GraphiQL({ 'The `GraphiQL` component requires a `fetcher` function to be passed as prop.', ); } - + // @ts-expect-error -- Prop is removed + if (props.toolbar?.additionalContent) { + throw new TypeError( + '`toolbar.additionalContent` was removed. Use render props on `GraphiQL.Toolbar` component instead.', + ); + } + // @ts-expect-error -- Prop is removed + if (props.toolbar?.additionalComponent) { + throw new TypeError( + '`toolbar.additionalComponent` was removed. Use render props on `GraphiQL.Toolbar` component instead.', + ); + } return ( @@ -187,7 +189,7 @@ type AddSuffix, Suffix extends string> = { export type GraphiQLInterfaceProps = WriteableEditorProps & AddSuffix, 'Query'> & - Pick & + Pick & AddSuffix, 'Variables'> & AddSuffix, 'Headers'> & Pick & { @@ -207,18 +209,12 @@ export type GraphiQLInterfaceProps = WriteableEditorProps & * @default true */ isHeadersEditorEnabled?: boolean; - /** - * An object that allows configuration of the toolbar next to the query - * editor. - */ - toolbar?: GraphiQLToolbarConfig; /** * Indicates if settings for persisting headers should appear in the * settings modal. */ showPersistHeadersSettings?: boolean; defaultTheme?: Theme; - disableTabs?: boolean; /** * `forcedTheme` allows enforcement of a specific theme for GraphiQL. * This is useful when you want to make sure that GraphiQL is always @@ -254,11 +250,6 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) { props.forcedTheme && THEMES.includes(props.forcedTheme) ? props.forcedTheme : undefined; - - const copy = useCopyQuery({ onCopyQuery: props.onCopyQuery }); - const merge = useMergeQuery(); - const prettify = usePrettifyEditors(); - const { theme, setTheme } = useTheme(props.defaultTheme); useEffect(() => { @@ -332,37 +323,39 @@ export function GraphiQLInterface(props: GraphiQLInterfaceProps) { 'success' | 'error' | null >(null); - const children = Children.toArray(props.children); - - const logo = children.find(child => - isChildComponentType(child, GraphiQL.Logo), - ) || ; - - const toolbar = children.find(child => - isChildComponentType(child, GraphiQL.Toolbar), - ) || ( - <> - - - - - - - {props.toolbar?.additionalContent} - {props.toolbar?.additionalComponent && ( - - )} - - ); - - const footer = children.find(child => - isChildComponentType(child, GraphiQL.Footer), + const { logo, toolbar, footer } = Children.toArray(props.children).reduce<{ + logo?: ReactNode; + toolbar?: ReactNode; + footer?: ReactNode; + }>( + (acc, curr) => { + switch (getChildComponentType(curr)) { + case GraphiQL.Logo: + acc.logo = curr; + break; + case GraphiQL.Toolbar: + // @ts-expect-error -- fix type error + acc.toolbar = cloneElement(curr, { + onCopyQuery: props.onCopyQuery, + onPrettifyQuery: props.onPrettifyQuery, + }); + break; + case GraphiQL.Footer: + acc.footer = curr; + break; + } + return acc; + }, + { + logo: , + toolbar: ( +